add "LE Device Address" 0x1B to advertising data types
Fork of BLE_API by
Revision 1104:0244fbb0324e, committed 2016-01-11
- Comitter:
- vcoubard
- Date:
- Mon Jan 11 08:51:56 2016 +0000
- Parent:
- 1103:551f40053f40
- Child:
- 1105:178ed0b132c4
- Commit message:
- Synchronized with git rev 02ca65bc
Author: Andres Amaya Garcia
Make update adv payload replace previous data
Accumulate and update advertising payload now differ in their implementations.
Accumulate updates the previous value, if it is UUID then the previously added
values are kept and the new one is simple appended. In contrast, update
replaces the previous value in all cases.
Changed in this revision
--- a/ble/Gap.h Mon Jan 11 08:51:55 2016 +0000 +++ b/ble/Gap.h Mon Jan 11 08:51:56 2016 +0000 @@ -604,6 +604,16 @@ * @param type The type describing the variable length data. * @param data Data bytes. * @param len Length of data. + * + * @return BLE_ERROR_NONE if the advertisement payload was updated based on + * matching AD type; otherwise, an appropriate error. + * + * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. */ ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { @@ -620,8 +630,7 @@ /** * Update a particular ADV field in the advertising payload (based on - * matching type and length). Note: the length of the new data must be the - * same as the old one. + * matching type). * * @param[in] type The ADV type field describing the variable length data. * @param[in] data Data bytes. @@ -630,7 +639,7 @@ * @note: If advertisements are enabled, then the update will take effect immediately. * * @return BLE_ERROR_NONE if the advertisement payload was updated based on - * a <type, len> match; otherwise, an appropriate error. + * matching AD type; otherwise, an appropriate error. */ ble_error_t updateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) { if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
--- a/ble/GapAdvertisingData.h Mon Jan 11 08:51:55 2016 +0000 +++ b/ble/GapAdvertisingData.h Mon Jan 11 08:51:56 2016 +0000 @@ -202,149 +202,63 @@ /** * Adds advertising data based on the specified AD type (see DataType). - * - * @param advDataType The Advertising 'DataType' to add. - * @param payload Pointer to the payload contents. - * @param len Size of the payload in bytes. - * - * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the - * advertising buffer to overflow, else BLE_ERROR_NONE. - */ - ble_error_t addData(DataType advDataType, const uint8_t *payload, uint8_t len) - { - ble_error_t result = 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); - } - - return result; - } - - /** - * Update a particular ADV field in the advertising payload (based on - * matching type and length). Note: the length of the new data must be the - * same as the old one. + * If the supplied AD type is already present in the advertising + * payload, then the value is updated. * * @param[in] advDataType The Advertising 'DataType' to add. * @param[in] payload Pointer to the payload contents. * @param[in] len Size of the payload in bytes. * - * @return BLE_ERROR_UNSPECIFIED if the specified field is not found, else - * BLE_ERROR_NONE. + * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the + * advertising buffer to overflow. BLE_ERROR_NONE is returned + * on success. + * + * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. + */ + ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len) + { + // find field + uint8_t* field = findField(advDataType); + + if (field) { + // Field type already exist, either add to field or replace + return addField(advDataType, payload, len, field); + } else { + // field doesn't exists, insert new + return appendField(advDataType, payload, len); + } + } + + /** + * Update a particular ADV field in the advertising payload (based on + * matching type). + * + * @param[in] advDataType The Advertising 'DataType' to add. + * @param[in] payload Pointer to the payload contents. + * @param[in] len Size of the payload in bytes. + * + * @return BLE_ERROR_UNSPECIFIED if the specified field is not found, + * BLE_ERROR_BUFFER_OVERFLOW if the new value causes the + * advertising buffer to overflow. BLE_ERROR_NONE is returned + * on success. */ ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len) { - if ((payload == NULL) || (len == 0)) { - return BLE_ERROR_INVALID_PARAM; - } - - /* A local struct to describe an ADV field. This definition comes from the Bluetooth Core Spec. (v4.2) Part C, Section 11. */ - struct ADVField_t { - uint8_t len; /* Describes the length (in bytes) of the following type and bytes. */ - uint8_t type; /* Should have the same representation of DataType_t (above). */ - uint8_t bytes[0]; /* A placeholder for variable length data. */ - }; + // find field + uint8_t* field = findField(advDataType); - /* Iterate over the adv fields looking for the first match. */ - uint8_t byteIndex = 0; - while (byteIndex < _payloadLen) { - ADVField_t *currentADV = (ADVField_t *)&_payload[byteIndex]; - if ((currentADV->len == (len + 1)) && /* Incoming len only describes the payload, whereas ADV->len describes [type + payload]. */ - (currentADV->type == advDataType)) { - memcpy(currentADV->bytes, payload, len); - return BLE_ERROR_NONE; - } - - byteIndex += (currentADV->len + 1); /* Advance by len+1; '+1' is needed to span the len field itself. */ + if (field) { + // Field type already exist, either add to field or replace + return updateField(advDataType, payload, len, field); + } else { + // field doesn't exists, return an error + return BLE_ERROR_UNSPECIFIED; } - - return BLE_ERROR_UNSPECIFIED; } /** @@ -475,6 +389,107 @@ return NULL; } + /** + * Given the a pointer to a field in the advertising payload it replaces + * the existing data in the field with the supplied data. + * + * When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS, + * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS, + * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS, + * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the + * supplied value is appended to the values previously added to the + * payload. + * + * Returns BLE_ERROR_NONE on success. + */ + ble_error_t addField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field) + { + ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW; + + switch(advDataType) { + // 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; + } + // These fields will be overwritten with the new value + default: { + result = updateField(advDataType, payload, len, field); + + break; + } + } + + return result; + } + + /** + * Given the a pointer to a field in the advertising payload it replaces + * the existing data in the field with the supplied data. + * Returns BLE_ERROR_NONE on success. + */ + ble_error_t updateField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field) + { + ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW; + 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]; + } + + result = BLE_ERROR_NONE; + } 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); + } + } + + return result; + } + uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD]; uint8_t _payloadLen; uint16_t _appearance;
--- a/ble/blecommon.h Mon Jan 11 08:51:55 2016 +0000 +++ b/ble/blecommon.h Mon Jan 11 08:51:56 2016 +0000 @@ -63,7 +63,6 @@ BLE_ERROR_INITIALIZATION_INCOMPLETE = 9, BLE_ERROR_ALREADY_INITIALIZED = 10, BLE_ERROR_UNSPECIFIED = 11, /**< Unknown error. */ - BLE_ERROR_INTERNAL_STACK_FAILURE = 12, /**< The platform-specific stack failed */ }; /** @brief Default MTU size. */
--- a/module.json Mon Jan 11 08:51:55 2016 +0000 +++ b/module.json Mon Jan 11 08:51:56 2016 +0000 @@ -1,6 +1,6 @@ { "name": "ble", - "version": "2.2.2", + "version": "2.2.0", "description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.", "keywords": [ "Bluetooth",
--- a/source/DiscoveredCharacteristic.cpp Mon Jan 11 08:51:55 2016 +0000 +++ b/source/DiscoveredCharacteristic.cpp Mon Jan 11 08:51:56 2016 +0000 @@ -31,29 +31,29 @@ return gattc->read(connHandle, valueHandle, offset); } -struct OneShotReadCallback { - static void launch(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) { +struct OneShotReadCallback { + static void launch(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) { OneShotReadCallback* oneShot = new OneShotReadCallback(client, connHandle, handle, cb); oneShot->attach(); // delete will be made when this callback is called } private: - OneShotReadCallback(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) : + OneShotReadCallback(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) : _client(client), _connHandle(connHandle), - _handle(handle), - _callback(cb) { } + _handle(handle), + _callback(cb) { } - void attach() { + void attach() { _client->onDataRead(makeFunctionPointer(this, &OneShotReadCallback::call)); } void call(const GattReadCallbackParams* params) { // verifiy that it is the right characteristic on the right connection - if (params->connHandle == _connHandle && params->handle == _handle) { + if (params->connHandle == _connHandle && params->handle == _handle) { _callback(params); _client->onDataRead().detach(makeFunctionPointer(this, &OneShotReadCallback::call)); delete this; @@ -68,7 +68,7 @@ ble_error_t DiscoveredCharacteristic::read(uint16_t offset, const GattClient::ReadCallback_t& onRead) const { ble_error_t error = read(offset); - if (error) { + if (error) { return error; } @@ -105,29 +105,29 @@ return gattc->write(GattClient::GATT_OP_WRITE_CMD, connHandle, valueHandle, length, value); } -struct OneShotWriteCallback { - static void launch(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) { +struct OneShotWriteCallback { + static void launch(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) { OneShotWriteCallback* oneShot = new OneShotWriteCallback(client, connHandle, handle, cb); oneShot->attach(); // delete will be made when this callback is called } private: - OneShotWriteCallback(GattClient* client, Gap::Handle_t connHandle, - GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) : + OneShotWriteCallback(GattClient* client, Gap::Handle_t connHandle, + GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) : _client(client), _connHandle(connHandle), - _handle(handle), - _callback(cb) { } + _handle(handle), + _callback(cb) { } - void attach() { + void attach() { _client->onDataWritten(makeFunctionPointer(this, &OneShotWriteCallback::call)); } void call(const GattWriteCallbackParams* params) { // verifiy that it is the right characteristic on the right connection - if (params->connHandle == _connHandle && params->handle == _handle) { + if (params->connHandle == _connHandle && params->handle == _handle) { _callback(params); _client->onDataWritten().detach(makeFunctionPointer(this, &OneShotWriteCallback::call)); delete this; @@ -142,7 +142,7 @@ ble_error_t DiscoveredCharacteristic::write(uint16_t length, const uint8_t *value, const GattClient::WriteCallback_t& onRead) const { ble_error_t error = write(length, value); - if (error) { + if (error) { return error; } @@ -154,9 +154,5 @@ ble_error_t DiscoveredCharacteristic::discoverDescriptors(DescriptorCallback_t callback, const UUID &matchingUUID) const { - /* Avoid compiler warnings */ - (void) callback; - (void) matchingUUID; - return BLE_ERROR_NOT_IMPLEMENTED; /* TODO: this needs to be filled in. */ } \ No newline at end of file