Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
Diff: features/FEATURE_BLE/ble/GapAdvertisingData.h
- Revision:
- 0:b74591d5ab33
diff -r 000000000000 -r b74591d5ab33 features/FEATURE_BLE/ble/GapAdvertisingData.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/features/FEATURE_BLE/ble/GapAdvertisingData.h Mon Dec 11 17:54:04 2017 +0000
@@ -0,0 +1,924 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MBED_GAP_ADVERTISING_DATA_H__
+#define MBED_GAP_ADVERTISING_DATA_H__
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blecommon.h"
+
+/**
+ * @addtogroup ble
+ * @{
+ * @addtogroup gap
+ * @{
+ */
+
+#define GAP_ADVERTISING_DATA_MAX_PAYLOAD (31)
+
+/**
+ * GAP advertising data builder.
+ *
+ * Advertising data are used by broadcaster or peripheral to advertise state
+ * about the device. This class offers the function to add and update states present
+ * in an advertisement payload.
+ *
+ * After construction, the advertising payload contained in the instance of
+ * GapAdvertisingData is empty. Adding new states and named fields can be
+ * achieved by invoking the function addData(), and updating existing state
+ * involves calling the function updateData().
+ *
+ * Fields present in the payload can be retrieved by a call to the function
+ * findField.
+ *
+ * This class includes shorthand for the most common fields:
+ * - FLAGS: addFlags().
+ * - APPEARANCE: addAppearance().
+ * - TX_POWER_LEVEL: addTxPower().
+ *
+ * @code
+ *
+ * Gap ⪆
+ *
+ * static const uint8_t device_name[] = "HRM";
+ *
+ * // construct an empty advertising payload
+ * GapAdvertisingData advertising_data;
+ *
+ * // set the flags of the advertising device
+ * advertising_data.addFlags(
+ * GapAdvertisingData::LE_GENERAL_DISCOVERABLE |
+ * GapAdvertisingData::BREDR_NOT_SUPPORTED
+ * );
+ *
+ * // set the advertised name of the device
+ * advertising_data.addData(
+ * GapAdvertisingData::COMPLETE_LOCAL_NAME,
+ * device_name,
+ * sizeof(device_name)
+ * );
+ *
+ * // update the advertising data of the gap payload
+ * gap.setAdvertisingPayload(advertising_data);
+ *
+ * @endcode
+ *
+ * @note See Bluetooth Specification 4.0 (Vol. 3), Part C, Sections 11 and 18
+ * for further information on advertising and scan response data.
+ *
+ * @par Advertising and Scan Response Payloads
+ * Advertising data and scan response data are organized around a set of
+ * data types called 'AD types' in Bluetooth 4.0 (see the Bluetooth Core
+ * Specification v4.0, Vol. 3, Part C, Sections 11 and 18).
+ *
+ * @par
+ * Each AD type has its own standardized assigned number, as
+ * the Bluetooth SIG defines:
+ * https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile.
+ *
+ * @par
+ * For convenience, all appropriate AD types are encapsulated in
+ * GapAdvertisingData::DataType.
+ *
+ * @par
+ * Before the AD Types and their payload (if any) can be inserted into
+ * the advertising or scan response frames, they need to be formatted as
+ * follows:
+ *
+ * @li @c Record length (1 byte).
+ * @li @c AD Type (1 byte).
+ * @li @c AD payload (optional; only present if record length > 1).
+ *
+ * @par
+ * This class takes care of properly formatting the payload, performs
+ * some basic checks on the payload length and tries to avoid common
+ * errors such as adding an exclusive AD field twice in the advertising
+ * or scan response payload.
+ */
+class GapAdvertisingData
+{
+public:
+ /*!
+ * List of standard Advertising Data types.
+ *
+ * These AD types are used to describe the capabilities of the peripheral
+ * and are inserted inside the advertising or scan response payloads.
+ *
+ * @par Source
+ *
+ * @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18.
+ * @li @c https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile.
+ */
+ enum DataType_t {
+ /**
+ * Flags, refer to GapAdvertisingData::Flags_t.
+ */
+ FLAGS = 0x01,
+
+ /**
+ * Incomplete list of 16-bit Service IDs.
+ */
+ INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02,
+
+ /**
+ * Complete list of 16-bit Service IDs.
+ */
+ COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03,
+
+ /**
+ * Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0).
+ */
+ INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04,
+
+ /**
+ * Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0).
+ */
+ COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05,
+
+ /**
+ * Incomplete list of 128-bit Service IDs.
+ */
+ INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06,
+
+ /**
+ * Complete list of 128-bit Service IDs.
+ */
+ COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07,
+
+ /**
+ * Shortened Local Name.
+ */
+ SHORTENED_LOCAL_NAME = 0x08,
+
+ /**
+ * Complete Local Name.
+ */
+ COMPLETE_LOCAL_NAME = 0x09,
+
+ /**
+ * TX Power Level (in dBm).
+ */
+ TX_POWER_LEVEL = 0x0A,
+
+ /**
+ * Device ID.
+ */
+ DEVICE_ID = 0x10,
+
+ /**
+ * Slave Connection Interval Range.
+ */
+ SLAVE_CONNECTION_INTERVAL_RANGE = 0x12,
+
+ /**
+ * List of 128-bit service UUIDs the device is looking for.
+ */
+ LIST_128BIT_SOLICITATION_IDS = 0x15,
+
+ /**
+ * Service Data.
+ */
+ SERVICE_DATA = 0x16,
+
+ /**
+ * Appearance, refer to GapAdvertisingData::Appearance_t.
+ */
+ APPEARANCE = 0x19,
+
+ /**
+ * Advertising Interval.
+ */
+ ADVERTISING_INTERVAL = 0x1A,
+
+ /**
+ * Manufacturer Specific Data.
+ */
+ MANUFACTURER_SPECIFIC_DATA = 0xFF
+
+ };
+
+ /**
+ * Alias for GapAdvertisingData::DataType_t.
+ *
+ * @deprecated Future releases will drop this type alias.
+ */
+ typedef enum DataType_t DataType;
+
+ /**
+ * Enumeration of allowed flags for DataType_t::FLAGS.
+ *
+ * @note DataType_t::FLAGS may contain several flags that the bitwise
+ * and operator (ex.LE_GENERAL_DISCOVERABLE & BREDR_NOT_SUPPORTED) assembled.
+ *
+ * @par Source
+ *
+ * @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1.
+ */
+ enum Flags_t {
+ /**
+ * Peripheral device is discoverable for a limited period of time.
+ */
+ LE_LIMITED_DISCOVERABLE = 0x01,
+
+ /**
+ * Peripheral device is discoverable at any moment.
+ */
+ LE_GENERAL_DISCOVERABLE = 0x02,
+
+ /**
+ * Peripheral device is LE only and does not support Bluetooth Enhanced
+ * DataRate.
+ */
+ BREDR_NOT_SUPPORTED = 0x04,
+
+ /**
+ * Not relevant - dual mode only.
+ */
+ SIMULTANEOUS_LE_BREDR_C = 0x08,
+
+ /**
+ * Not relevant - dual mode only.
+ */
+ SIMULTANEOUS_LE_BREDR_H = 0x10
+
+ };
+
+ /**
+ * Alias for GapAdvertisingData::Flags_t.
+ *
+ * @deprecated Future releases will drop this type alias.
+ */
+ typedef enum Flags_t Flags;
+
+ /**
+ * Enumeration of values for the DataType_t::APPEARANCE.
+ *
+ * These values describe the physical shape or appearance of the device.
+ *
+ * @par Source
+ *
+ * @li @c Bluetooth Core Specification Supplement, Part A, Section 1.12.
+ * @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2.
+ * @li @c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml.
+ */
+ enum Appearance_t {
+ /**
+ * Unknown or unspecified appearance type.
+ */
+ UNKNOWN = 0,
+
+ /**
+ * Generic Phone.
+ */
+ GENERIC_PHONE = 64,
+
+ /**
+ * Generic Computer.
+ */
+ GENERIC_COMPUTER = 128,
+
+ /**
+ * Generic Watch.
+ */
+ GENERIC_WATCH = 192,
+
+ /**
+ * Sports Watch.
+ */
+ WATCH_SPORTS_WATCH = 193,
+
+ /**
+ * Generic Clock.
+ */
+ GENERIC_CLOCK = 256,
+
+ /**
+ * Generic Display.
+ */
+ GENERIC_DISPLAY = 320,
+
+ /**
+ * Generic Remote Control.
+ */
+ GENERIC_REMOTE_CONTROL = 384,
+
+ /**
+ * Generic Eye Glasses.
+ */
+ GENERIC_EYE_GLASSES = 448,
+
+ /**
+ * Generic Tag.
+ */
+ GENERIC_TAG = 512,
+
+ /**
+ * Generic Keyring.
+ */
+ GENERIC_KEYRING = 576,
+
+ /**
+ * Generic Media Player.
+ */
+ GENERIC_MEDIA_PLAYER = 640,
+
+ /**
+ * Generic Bar Code Scanner.
+ */
+ GENERIC_BARCODE_SCANNER = 704,
+
+ /**
+ * Generic Thermometer.
+ */
+ GENERIC_THERMOMETER = 768,
+
+ /**
+ * Ear Thermometer.
+ */
+ THERMOMETER_EAR = 769,
+
+ /**
+ * Generic Heart Rate Sensor.
+ */
+ GENERIC_HEART_RATE_SENSOR = 832,
+
+ /**
+ * Belt Heart Rate Sensor.
+ */
+ HEART_RATE_SENSOR_HEART_RATE_BELT = 833,
+
+ /**
+ * Generic Blood Pressure.
+ */
+ GENERIC_BLOOD_PRESSURE = 896,
+
+ /**
+ * Arm Blood Pressure.
+ */
+ BLOOD_PRESSURE_ARM = 897,
+
+ /**
+ * Wrist Blood Pressure.
+ */
+ BLOOD_PRESSURE_WRIST = 898,
+
+ /**
+ * Human Interface Device (HID).
+ */
+ HUMAN_INTERFACE_DEVICE_HID = 960,
+
+ /**
+ * Keyboard.
+ */
+ KEYBOARD = 961,
+
+ /**
+ * Mouse.
+ */
+ MOUSE = 962,
+
+ /**
+ * Joystick.
+ */
+ JOYSTICK = 963,
+
+ /**
+ * Gamepad.
+ */
+ GAMEPAD = 964,
+
+ /**
+ * Digitizer Tablet.
+ */
+ DIGITIZER_TABLET = 965,
+
+ /**
+ * Card Reader.
+ */
+ CARD_READER = 966,
+
+ /**
+ * Digital Pen.
+ */
+ DIGITAL_PEN = 967,
+
+ /**
+ * Bar Code Scanner.
+ */
+ BARCODE_SCANNER = 968,
+
+ /**
+ * Generic Glucose Meter.
+ */
+ GENERIC_GLUCOSE_METER = 1024,
+
+ /**
+ * Generic Running/Walking Sensor.
+ */
+ GENERIC_RUNNING_WALKING_SENSOR = 1088,
+
+ /**
+ * In Shoe Running/Walking Sensor.
+ */
+ RUNNING_WALKING_SENSOR_IN_SHOE = 1089,
+
+ /**
+ * On Shoe Running/Walking Sensor.
+ */
+ RUNNING_WALKING_SENSOR_ON_SHOE = 1090,
+
+ /**
+ * On Hip Running/Walking Sensor.
+ */
+ RUNNING_WALKING_SENSOR_ON_HIP = 1091,
+
+ /**
+ * Generic Cycling.
+ */
+ GENERIC_CYCLING = 1152,
+
+ /**
+ * Cycling Computer.
+ */
+ CYCLING_CYCLING_COMPUTER = 1153,
+
+ /**
+ * Cycling Speed Sensor.
+ */
+ CYCLING_SPEED_SENSOR = 1154,
+
+ /**
+ * Cycling Cadence Sensor.
+ */
+ CYCLING_CADENCE_SENSOR = 1155,
+
+ /**
+ * Cycling Power Sensor.
+ */
+ CYCLING_POWER_SENSOR = 1156,
+
+ /**
+ * Cycling Speed and Cadence Sensor.
+ */
+ CYCLING_SPEED_AND_CADENCE_SENSOR = 1157,
+
+ /**
+ * Generic Pulse Oximeter.
+ */
+ PULSE_OXIMETER_GENERIC = 3136,
+
+ /**
+ * Fingertip Pulse Oximeter.
+ */
+ PULSE_OXIMETER_FINGERTIP = 3137,
+
+ /**
+ * Wrist Worn Pulse Oximeter.
+ */
+ PULSE_OXIMETER_WRIST_WORN = 3138,
+
+ /**
+ * Generic Weight Scale.
+ */
+ GENERIC_WEIGHT_SCALE = 3200,
+
+ /**
+ * Generic Outdoor.
+ */
+ OUTDOOR_GENERIC = 5184,
+
+ /**
+ * Outdoor Location Display Device.
+ */
+ OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185,
+
+ /**
+ * Outdoor Location and Navigation Display Device.
+ */
+ OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186,
+
+ /**
+ * Outdoor Location Pod.
+ */
+ OUTDOOR_LOCATION_POD = 5187,
+
+ /**
+ * Outdoor Location and Navigation Pod.
+ */
+ OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188
+
+ };
+
+ /**
+ * Alias for GapAdvertisingData::Appearance_t.
+ *
+ * @deprecated Future releases will drop this type alias.
+ */
+ typedef enum Appearance_t Appearance;
+
+ /**
+ * Construct a GapAdvertising instance with an empty payload.
+ */
+ GapAdvertisingData(void) :
+ _payload(),
+ _payloadLen(0),
+ _appearance(GENERIC_TAG) {
+ }
+
+ /**
+ * Adds a new field into the payload.
+ *
+ * If the supplied advertising data type is already present in the
+ * advertising payload, then the value is updated.
+ *
+ * @param[in] advDataType The type of the field to add.
+ * @param[in] payload Pointer to the value of the field to add.
+ * @param[in] len Size in bytes of the value to add.
+ *
+ * @return BLE_ERROR_NONE on success.
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the advertising
+ * buffer to overflow.
+ *
+ * @note When the specified data 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 present in 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 exists, either add to field or replace */
+ return addField(advDataType, payload, len, field);
+ } else {
+ /* Field doesn't exist, insert new */
+ return appendField(advDataType, payload, len);
+ }
+ }
+
+ /**
+ * Update a specific field in the advertising payload.
+ *
+ * @param[in] advDataType The type of the field to update.
+ * @param[in] payload Pointer to the updated value of the field.
+ * @param[in] len Size of the new value in bytes.
+ *
+ * @return BLE_ERROR_NONE returned on success.
+ * @return BLE_ERROR_UNSPECIFIED if the specified field is not found,
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
+ * advertising buffer to overflow.
+ */
+ ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
+ {
+ /* Find field */
+ uint8_t* field = findField(advDataType);
+
+ if (field) {
+ /* Field type already exists, replace field contents */
+ return updateField(advDataType, payload, len, field);
+ } else {
+ /* field doesn't exist, return an error */
+ return BLE_ERROR_UNSPECIFIED;
+ }
+ }
+
+ /**
+ * Add device appearance in the advertising payload.
+ *
+ * @param[in] appearance The appearance to advertise.
+ *
+ * @return BLE_ERROR_NONE on success.
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
+ * advertising buffer to overflow.
+ *
+ * @note This call is equivalent to calling addData() with
+ * GapAdvertisingData::APPEARANCE as the field type.
+ */
+ ble_error_t addAppearance(Appearance appearance = GENERIC_TAG)
+ {
+ _appearance = appearance;
+ return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
+ }
+
+ /**
+ * Add BLE flags in the advertising payload.
+ *
+ * @param[in] flags Bitfield describing the capability of the device. See
+ * allowed flags in Flags_t.
+ *
+ * @return BLE_ERROR_NONE on success.
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
+ * advertising buffer to overflow.
+ *
+ * @note This call is equivalent to calling addData() with
+ * GapAdvertisingData::FLAGS as the field type.
+ */
+ ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE)
+ {
+ return addData(GapAdvertisingData::FLAGS, &flags, 1);
+ }
+
+ /**
+ * Add the advertising TX in the advertising payload.
+ *
+ * @param[in] txPower Transmission power level in dB.
+ *
+ * @return BLE_ERROR_NONE on success.
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
+ * advertising buffer to overflow.
+ *
+ * @note This call is equivalent to calling addData() with
+ * GapAdvertisingData::TX_POWER_LEVEL as the field type.
+ */
+ ble_error_t addTxPower(int8_t txPower)
+ {
+ /* To Do: Basic error checking to make sure txPower is in range. */
+ return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
+ }
+
+ /**
+ * Clears the advertising data payload.
+ *
+ * @post getPayloadLen() returns 0.
+ */
+ void clear(void)
+ {
+ memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
+ _payloadLen = 0;
+ }
+
+ /**
+ * Get the pointer to the advertising payload bytes.
+ *
+ * @return A pointer to the payload.
+ */
+ const uint8_t *getPayload(void) const
+ {
+ return _payload;
+ }
+
+ /**
+ * Get the payload length.
+ *
+ * @return The payload length in bytes.
+ */
+ uint8_t getPayloadLen(void) const
+ {
+ return _payloadLen;
+ }
+
+ /**
+ * Get the appearance set.
+ *
+ * If no value has been set, this function returns GENERIC_TAG.
+ *
+ * @return The appearance value set for this device.
+ */
+ uint16_t getAppearance(void) const
+ {
+ return (uint16_t)_appearance;
+ }
+
+ /**
+ * Search advertisement data for a specific field.
+ *
+ * @param[in] type The type of the field to find.
+ *
+ * @return A pointer to the first element in the field if found. The first
+ * element being the length of the field followed by the value of the field.
+ * @return NULL if the field is not present in the payload.
+ */
+ const uint8_t* findField(DataType_t type) const
+ {
+ /* 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;
+ }
+
+private:
+ /**
+ * Append advertising data based on the specified type.
+ *
+ * @param[in] advDataType Type of the new data.
+ * @param[in] payload Pointer to the data to be appended to the advertising
+ * payload.
+ * @param[in] len Length of the data pointed to by @p payload.
+ *
+ * @return BLE_ERROR_NONE on success.
+ * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
+ * advertising buffer to overflow.
+ */
+ 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 a specific field.
+ *
+ * @param[in] type The type of the field to find.
+ *
+ * @return A pointer to the first element in the field if found. The first
+ * element being the length of the field followed by the value of the field.
+ * @return NULL if the field is not present in the payload.
+ */
+ uint8_t* findField(DataType_t type)
+ {
+ return const_cast<uint8_t*>(
+ static_cast<const GapAdvertisingData*>(this)->findField(type)
+ );
+ }
+
+ /**
+ * Update in place the value of a field in the advertising payload.
+ *
+ * @param[in] advDataType Type of the new data.
+ * @param[in] payload Pointer to the data to be added to the advertising
+ * payload.
+ * @param[in] len Length of the data pointed to by @p payload.
+ * @param[in] field Pointer to the field of type @p advDataType in the
+ * advertising buffer.
+ *
+ * @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.
+ *
+ * @return 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 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 are overwritten with the new value */
+ default: {
+ result = updateField(advDataType, payload, len, field);
+
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Update in place the value of a field in the advertising payload.
+ *
+ * @param[in] advDataType Type of the new data.
+ * @param[in] payload Pointer to the data to be added to the advertising
+ * payload.
+ * @param[in] len Length of the data pointed to by @p payload.
+ * @param[in] field Pointer to the field of type @p advDataType in the
+ * advertising buffer.
+ *
+ * @return 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;
+ }
+
+ /**
+ * Advertising data buffer.
+ */
+ uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
+
+ /**
+ * Length of the data added to the advertising buffer.
+ */
+ uint8_t _payloadLen;
+
+ /**
+ * Appearance value.
+ */
+ uint16_t _appearance;
+};
+
+/**
+ * @}
+ * @}
+ */
+
+
+#endif /* ifndef MBED_GAP_ADVERTISING_DATA_H__ */