mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

features/FEATURE_BLE/ble/GapAdvertisingData.h

Committer:
be_bryan
Date:
2017-12-11
Revision:
0:b74591d5ab33

File content as of revision 0:b74591d5ab33:

/* 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 &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__ */