add "LE Device Address" 0x1B to advertising data types
Fork of BLE_API by
Revision 1099:6c54ccecf1e8, committed 2016-01-11
- Comitter:
- vcoubard
- Date:
- Mon Jan 11 08:51:54 2016 +0000
- Parent:
- 1098:5f6b5ea5d5f2
- Child:
- 1100:c3d484a482d8
- Commit message:
- Synchronized with git rev fec4e5ec
Author: Andres Amaya Garcia
Add documentation missing for updateData()
Changed in this revision
--- a/ble/Gap.h Mon Jan 11 08:51:53 2016 +0000 +++ b/ble/Gap.h Mon Jan 11 08:51:54 2016 +0000 @@ -620,8 +620,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 +629,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:53 2016 +0000 +++ b/ble/GapAdvertisingData.h Mon Jan 11 08:51:54 2016 +0000 @@ -202,149 +202,70 @@ /** * 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 updateField(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. + * + * @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 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 +396,85 @@ 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. + * 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; + + 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: { + // 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; + } + } + + return result; + } + uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD]; uint8_t _payloadLen; uint16_t _appearance;
--- a/source/DiscoveredCharacteristic.cpp Mon Jan 11 08:51:53 2016 +0000 +++ b/source/DiscoveredCharacteristic.cpp Mon Jan 11 08:51:54 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