commit
cb34899762
6 changed files with 222 additions and 89 deletions
16
DOXYGEN_FRONTPAGE.md
Normal file
16
DOXYGEN_FRONTPAGE.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
#BLE API
|
||||
|
||||
The BLE module within mbed OS offers a high level abstraction for using
|
||||
Bluetooth Low Energy on multiple platforms.
|
||||
|
||||
This documentation describes the internal structure of mbed
|
||||
(BLE_API)[https://github.com/armmbed/ble]. It was automatically generated from
|
||||
specially formatted comment blocks in BLE_API's source code using Doxygen.
|
||||
(See http://www.stack.nl/~dimitri/doxygen/ for more information on Doxygen).
|
||||
|
||||
For getting started with BLE on mbed, check our (introduction
|
||||
page)[https://docs.mbed.com/docs/ble-intros/en/latest/].
|
||||
|
||||
For mbed OS examples using BLE, check (this
|
||||
repository)[https://github.com/armmbed/ble-examples]. For mbed-classic
|
||||
examples, refer to (code under mbed.org)[https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/].
|
|
@ -2,7 +2,7 @@
|
|||
This is the Github repo for the `BLE_API` used by developer.mbed.org. Please see the [mbed BLE Homepage](https://developer.mbed.org/teams/Bluetooth-Low-Energy/) for all documentation, code examples and general help.
|
||||
|
||||
# Supported Services
|
||||
Supported GATT services and constantly being added and can be found in the `ble/source/services/` folder.
|
||||
Supported GATT services and constantly being added and can be found in the (`ble/ble/services/`)[https://github.com/ARMmbed/ble/tree/master/ble/services] folder.
|
||||
|
||||
Currently supported services include:
|
||||
* Battery
|
||||
|
|
|
@ -89,22 +89,23 @@ public:
|
|||
*/
|
||||
/**********************************************************************/
|
||||
enum DataType_t {
|
||||
FLAGS = 0x01, /**< \ref *Flags. */
|
||||
INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, /**< Incomplete list of 16-bit service IDs. */
|
||||
COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, /**< Complete list of 16-bit service IDs. */
|
||||
INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, /**< Incomplete list of 32-bit service IDs (not relevant for Bluetooth 4.0). */
|
||||
COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, /**< Complete list of 32-bit service IDs (not relevant for Bluetooth 4.0). */
|
||||
INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit service IDs. */
|
||||
COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, /**< Complete list of 128-bit service IDs. */
|
||||
SHORTENED_LOCAL_NAME = 0x08, /**< Shortened local name. */
|
||||
COMPLETE_LOCAL_NAME = 0x09, /**< Complete local name. */
|
||||
TX_POWER_LEVEL = 0x0A, /**< TX power level (in dBm). */
|
||||
DEVICE_ID = 0x10, /**< Device ID. */
|
||||
SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave connection interval range. */
|
||||
SERVICE_DATA = 0x16, /**< Service data. */
|
||||
APPEARANCE = 0x19, /**< \ref Appearance. */
|
||||
ADVERTISING_INTERVAL = 0x1A, /**< Advertising interval. */
|
||||
MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer specific data. */
|
||||
FLAGS = 0x01, /**< \ref *Flags */
|
||||
INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, /**< Incomplete list of 16-bit Service IDs */
|
||||
COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, /**< Complete list of 16-bit Service IDs */
|
||||
INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
|
||||
COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
|
||||
INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit Service IDs */
|
||||
COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, /**< Complete list of 128-bit Service IDs */
|
||||
SHORTENED_LOCAL_NAME = 0x08, /**< Shortened Local Name */
|
||||
COMPLETE_LOCAL_NAME = 0x09, /**< Complete Local Name */
|
||||
TX_POWER_LEVEL = 0x0A, /**< TX Power Level (in dBm) */
|
||||
DEVICE_ID = 0x10, /**< Device ID */
|
||||
SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave Connection Interval Range */
|
||||
LIST_128BIT_SOLICITATION_IDS = 0x15, /**< List of 128 bit service UUIDs the device is looking for */
|
||||
SERVICE_DATA = 0x16, /**< Service Data */
|
||||
APPEARANCE = 0x19, /**< \ref Appearance */
|
||||
ADVERTISING_INTERVAL = 0x1A, /**< Advertising Interval */
|
||||
MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer Specific Data */
|
||||
};
|
||||
typedef enum DataType_t DataType; /* Deprecated type alias. This may be dropped in a future release. */
|
||||
|
||||
|
@ -210,27 +211,98 @@ public:
|
|||
*/
|
||||
ble_error_t addData(DataType advDataType, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
/* To Do: Check if an AD type already exists and if the existing */
|
||||
/* value is exclusive or not (flags and so on). */
|
||||
ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
|
||||
|
||||
/* Make sure we don't exceed the 31 byte payload limit. */
|
||||
if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
return BLE_ERROR_BUFFER_OVERFLOW;
|
||||
// find field
|
||||
uint8_t* field = findField(advDataType);
|
||||
|
||||
// Field type already exist, either add to field or replace
|
||||
if (field) {
|
||||
switch(advDataType) {
|
||||
// These fields will be overwritten with the new value
|
||||
case FLAGS:
|
||||
case SHORTENED_LOCAL_NAME:
|
||||
case COMPLETE_LOCAL_NAME:
|
||||
case TX_POWER_LEVEL:
|
||||
case DEVICE_ID:
|
||||
case SLAVE_CONNECTION_INTERVAL_RANGE:
|
||||
case SERVICE_DATA:
|
||||
case APPEARANCE:
|
||||
case ADVERTISING_INTERVAL:
|
||||
case MANUFACTURER_SPECIFIC_DATA: {
|
||||
// current field length, with the type subtracted
|
||||
uint8_t dataLength = field[0] - 1;
|
||||
|
||||
// new data has same length, do in-order replacement
|
||||
if (len == dataLength) {
|
||||
for (uint8_t idx = 0; idx < dataLength; idx++) {
|
||||
field[2 + idx] = payload[idx];
|
||||
}
|
||||
} else {
|
||||
// check if data fits
|
||||
if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
|
||||
// remove old field
|
||||
while ((field + dataLength + 2) < &_payload[_payloadLen]) {
|
||||
*field = field[dataLength + 2];
|
||||
field++;
|
||||
}
|
||||
|
||||
// reduce length
|
||||
_payloadLen -= dataLength + 2;
|
||||
|
||||
// add new field
|
||||
result = appendField(advDataType, payload, len);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// These fields will have the new data appended if there is sufficient space
|
||||
case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_16BIT_SERVICE_IDS:
|
||||
case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_32BIT_SERVICE_IDS:
|
||||
case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_128BIT_SERVICE_IDS:
|
||||
case LIST_128BIT_SOLICITATION_IDS: {
|
||||
// check if data fits
|
||||
if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
// make room for new field by moving the remainder of the
|
||||
// advertisement payload "to the right" starting after the
|
||||
// TYPE field.
|
||||
uint8_t* end = &_payload[_payloadLen];
|
||||
|
||||
while (&field[1] < end) {
|
||||
end[len] = *end;
|
||||
end--;
|
||||
}
|
||||
|
||||
// insert new data
|
||||
for (uint8_t idx = 0; idx < len; idx++) {
|
||||
field[2 + idx] = payload[idx];
|
||||
}
|
||||
|
||||
// increment lengths
|
||||
field[0] += len;
|
||||
_payloadLen += len;
|
||||
|
||||
result = BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// Field exists but updating it is not supported. Abort operation.
|
||||
default:
|
||||
result = BLE_ERROR_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// field doesn't exists, insert new
|
||||
result = appendField(advDataType, payload, len);
|
||||
}
|
||||
|
||||
/* Field length. */
|
||||
memset(&_payload[_payloadLen], len + 1, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Field ID. */
|
||||
memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Payload. */
|
||||
memcpy(&_payload[_payloadLen], payload, len);
|
||||
_payloadLen += len;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -345,7 +417,63 @@ public:
|
|||
return (uint16_t)_appearance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search advertisement data for field.
|
||||
* Returns pointer to the first element in the field if found, NULL otherwise.
|
||||
* Where the first element is the length of the field.
|
||||
*/
|
||||
const uint8_t* findField(DataType_t type) const {
|
||||
return findField(type);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Append advertising data based on the specified AD type (see DataType)
|
||||
*/
|
||||
ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
/* Make sure we don't exceed the 31 byte payload limit */
|
||||
if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
return BLE_ERROR_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Field length. */
|
||||
memset(&_payload[_payloadLen], len + 1, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Field ID. */
|
||||
memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Payload. */
|
||||
memcpy(&_payload[_payloadLen], payload, len);
|
||||
_payloadLen += len;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search advertisement data for field.
|
||||
* Returns pointer to the first element in the field if found, NULL otherwise.
|
||||
* Where the first element is the length of the field.
|
||||
*/
|
||||
uint8_t* findField(DataType_t type) {
|
||||
// scan through advertisement data
|
||||
for (uint8_t idx = 0; idx < _payloadLen; ) {
|
||||
uint8_t fieldType = _payload[idx + 1];
|
||||
|
||||
if (fieldType == type) {
|
||||
return &_payload[idx];
|
||||
}
|
||||
|
||||
// advance to next field
|
||||
idx += _payload[idx] + 1;
|
||||
}
|
||||
|
||||
// field not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
|
||||
uint8_t _payloadLen;
|
||||
uint16_t _appearance;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
/**
|
||||
* @class BatteryService
|
||||
* @brief BLE Battery Service. This service displays the battery level from 0%->100% represented as a 8bit number.<br>
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.battery_service.xml <br>
|
||||
* @brief BLE Battery Service. This service displays the battery level from 0% to 100%, represented as an 8bit number.
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.battery_service.xml
|
||||
* Battery Level Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.battery_level.xml
|
||||
*/
|
||||
class BatteryService {
|
||||
|
@ -45,11 +45,11 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Update the battery level with a new value. Valid values range from
|
||||
* 0..100. Anything outside this range will be ignored.
|
||||
* @brief Update the battery level with a new value. [Valid values lie between 0 and 100];
|
||||
* anything outside this range will be ignored.
|
||||
*
|
||||
* @param newLevel
|
||||
* update to battery level.
|
||||
* Update to battery level.
|
||||
*/
|
||||
void updateBatteryLevel(uint8_t newLevel) {
|
||||
batteryLevel = newLevel;
|
||||
|
|
|
@ -37,20 +37,20 @@ extern const uint8_t DFUServicePacketCharacteristicUUID[];
|
|||
class DFUService {
|
||||
public:
|
||||
/**
|
||||
* @brief Signature for the handover callback. The application may provide such a
|
||||
* callback when setting up the DFU service, in which case it will be
|
||||
* @brief Signature for the handover callback. The application may provide this
|
||||
* callback when setting up the DFU service. The callback is then
|
||||
* invoked before handing control over to the bootloader.
|
||||
*/
|
||||
typedef void (*ResetPrepare_t)(void);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Adds Device Firmware Update service to an existing ble object.
|
||||
* @brief Adds Device Firmware Update Service to an existing BLE object.
|
||||
*
|
||||
* @param[ref] _ble
|
||||
* BLE object for the underlying controller.
|
||||
* @param[in] _handoverCallback
|
||||
* Application specific handover callback.
|
||||
* Application-specific handover callback.
|
||||
*/
|
||||
DFUService(BLE &_ble, ResetPrepare_t _handoverCallback = NULL) :
|
||||
ble(_ble),
|
||||
|
@ -59,12 +59,12 @@ public:
|
|||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
|
||||
controlBytes(),
|
||||
packetBytes() {
|
||||
static bool serviceAdded = false; /* We should only ever need to add the DFU service once. */
|
||||
static bool serviceAdded = false; /* We only add the DFU service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set an initial value for control bytes so that the application's DFUService can
|
||||
/* Set an initial value for control bytes, so that the application's DFU service can
|
||||
* be distinguished from the real DFU service provided by the bootloader. */
|
||||
controlBytes[0] = 0xFF;
|
||||
controlBytes[1] = 0xFF;
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief get the handle for the value attribute of the control characteristic.
|
||||
* @brief Get the handle for the value attribute of the control characteristic.
|
||||
*/
|
||||
uint16_t getControlHandle(void) const {
|
||||
return controlPoint.getValueHandle();
|
||||
|
@ -88,7 +88,7 @@ public:
|
|||
|
||||
/**
|
||||
* @brief This callback allows the DFU service to receive the initial trigger to
|
||||
* handover control to the bootloader; but first the application is given a
|
||||
* hand control over to the bootloader. First, the application is given a
|
||||
* chance to clean up.
|
||||
*
|
||||
* @param[in] params
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
*/
|
||||
virtual void onDataWritten(const GattWriteCallbackParams *params) {
|
||||
if (params->handle == controlPoint.getValueHandle()) {
|
||||
/* At present, writing anything will do the trick--this needs to be improved. */
|
||||
/* At present, writing anything will do the trick - this needs to be improved. */
|
||||
if (handoverCallback) {
|
||||
handoverCallback();
|
||||
}
|
||||
|
@ -112,22 +112,22 @@ protected:
|
|||
protected:
|
||||
BLE &ble;
|
||||
|
||||
/**< Writing to the control characteristic triggers the handover to dfu-
|
||||
* bootloader. At present, writing anything will do the trick--this needs
|
||||
/**< Writing to the control characteristic triggers the handover to DFU
|
||||
* bootloader. At present, writing anything will do the trick - this needs
|
||||
* to be improved. */
|
||||
WriteOnlyArrayGattCharacteristic<uint8_t, SIZEOF_CONTROL_BYTES> controlPoint;
|
||||
|
||||
/**< The packet characteristic in this service doesn't do anything meaningful, but
|
||||
* is only a placeholder to mimic the corresponding characteristic in the
|
||||
/**< The packet characteristic in this service doesn't do anything meaningful;
|
||||
* it is only a placeholder to mimic the corresponding characteristic in the
|
||||
* actual DFU service implemented by the bootloader. Without this, some
|
||||
* FOTA clients might get confused as service definitions change after
|
||||
* FOTA clients might get confused, because service definitions change after
|
||||
* handing control over to the bootloader. */
|
||||
GattCharacteristic packet;
|
||||
|
||||
uint8_t controlBytes[SIZEOF_CONTROL_BYTES];
|
||||
uint8_t packetBytes[SIZEOF_PACKET_BYTES];
|
||||
|
||||
static ResetPrepare_t handoverCallback; /**< application specific handover callback. */
|
||||
static ResetPrepare_t handoverCallback; /**< Application-specific handover callback. */
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_DFU_SERVICE_H__*/
|
||||
|
|
|
@ -21,41 +21,30 @@
|
|||
|
||||
/**
|
||||
* @class DeviceInformationService
|
||||
* @brief BLE Device Information Service <br>
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml <br>
|
||||
* @brief BLE Device Information Service
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml
|
||||
* Manufacturer Name String Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.manufacturer_name_string.xml
|
||||
*/
|
||||
class DeviceInformationService {
|
||||
public:
|
||||
/**
|
||||
* @brief Device Information Service Constructor.
|
||||
* @brief Device Information Service Constructor: copies device-specific information
|
||||
* into the BLE stack.
|
||||
*
|
||||
* @param[ref] _ble
|
||||
* BLE object for the underlying controller.
|
||||
* @param[in] manufacturersName
|
||||
* This characteristic represents the name of the
|
||||
* manufacturer of the device. The name is copied into the
|
||||
* BLE stack during this constructor.
|
||||
* The name of the manufacturer of the device.
|
||||
* @param[in] modelNumber
|
||||
* This characteristic represents the model number that is
|
||||
* assigned by the device vendor. The value is copied into
|
||||
* the BLE stack during this constructor.
|
||||
* The model number that is assigned by the device vendor.
|
||||
* @param[in] serialNumber
|
||||
* This characteristic represents the serial number for a
|
||||
* particular instance of the device. The value is copied
|
||||
* into the BLE stack during this constructor.
|
||||
* The serial number for a particular instance of the device.
|
||||
* @param[in] hardwareRevision
|
||||
* This characteristic represents the hardware revision for
|
||||
* the hardware within the device. The value is copied
|
||||
* into the BLE stack during this constructor.
|
||||
* The hardware revision for the hardware within the device.
|
||||
* @param[in] firmwareRevision
|
||||
* This characteristic represents the firmware revision for
|
||||
* the firmware within the device. The value is copied
|
||||
* into the BLE stack during this constructor.
|
||||
* The device's firmware version.
|
||||
* @param[in] softwareRevision
|
||||
* This characteristic represents the software revision for
|
||||
* the software within the device. The value is copied
|
||||
* into the BLE stack during this constructor.
|
||||
* The device's software version.
|
||||
*/
|
||||
DeviceInformationService(BLE &_ble,
|
||||
const char *manufacturersName = NULL,
|
||||
|
@ -67,36 +56,36 @@ public:
|
|||
ble(_ble),
|
||||
manufacturersNameStringCharacteristic(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR,
|
||||
(uint8_t *)manufacturersName,
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* minLength */
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* maxLength */
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* Min length */
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
modelNumberStringCharacteristic(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR,
|
||||
(uint8_t *)modelNumber,
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* minLength */
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* maxLength */
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* Min length */
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
serialNumberStringCharacteristic(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR,
|
||||
(uint8_t *)serialNumber,
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* minLength */
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* maxLength */
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* Min length */
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
hardwareRevisionStringCharacteristic(GattCharacteristic::UUID_HARDWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)hardwareRevision,
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* minLength */
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* maxLength */
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* Min length */
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
firmwareRevisionStringCharacteristic(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)firmwareRevision,
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* minLength */
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* maxLength */
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* Min length */
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
softwareRevisionStringCharacteristic(GattCharacteristic::UUID_SOFTWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)softwareRevision,
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* minLength */
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* maxLength */
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* Min length */
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)
|
||||
{
|
||||
static bool serviceAdded = false; /* We should only ever need to add the information service once. */
|
||||
static bool serviceAdded = false; /* We only add the information service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue