Updated

Fork of BLE_API by Bluetooth Low Energy

Committer:
vcoubard
Date:
Mon Jan 11 08:51:52 2016 +0000
Revision:
1096:c3a43f09f1c5
Parent:
1094:ff274a1b7a14
Child:
1097:4d22814faf46
Synchronized with git rev 39e3e8d1
Author: Andres Amaya Garcia
Modify functions that manipulate adv payload

Modify the functions addData() and updateData() to correctly update the payload
information for a specified AD type if that type was already present in the
payload. For addData() if the AD type is not found, it is added to the payload.
In contrast, in updateData() if the AD type is not found an error is returned.

Documentation was updated accordingly.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 710:b2e1a2660ec2 1 /* mbed Microcontroller Library
rgrover1 710:b2e1a2660ec2 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 710:b2e1a2660ec2 3 *
rgrover1 710:b2e1a2660ec2 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 710:b2e1a2660ec2 5 * you may not use this file except in compliance with the License.
rgrover1 710:b2e1a2660ec2 6 * You may obtain a copy of the License at
rgrover1 710:b2e1a2660ec2 7 *
rgrover1 710:b2e1a2660ec2 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 710:b2e1a2660ec2 9 *
rgrover1 710:b2e1a2660ec2 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 710:b2e1a2660ec2 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 710:b2e1a2660ec2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 710:b2e1a2660ec2 13 * See the License for the specific language governing permissions and
rgrover1 710:b2e1a2660ec2 14 * limitations under the License.
rgrover1 710:b2e1a2660ec2 15 */
rgrover1 710:b2e1a2660ec2 16
rgrover1 710:b2e1a2660ec2 17 #ifndef __GAP_ADVERTISING_DATA_H__
rgrover1 710:b2e1a2660ec2 18 #define __GAP_ADVERTISING_DATA_H__
rgrover1 710:b2e1a2660ec2 19
rgrover1 710:b2e1a2660ec2 20 #include <stdint.h>
rgrover1 710:b2e1a2660ec2 21 #include <string.h>
rgrover1 710:b2e1a2660ec2 22
rgrover1 710:b2e1a2660ec2 23 #include "blecommon.h"
rgrover1 710:b2e1a2660ec2 24
rgrover1 710:b2e1a2660ec2 25 #define GAP_ADVERTISING_DATA_MAX_PAYLOAD (31)
rgrover1 710:b2e1a2660ec2 26
rgrover1 710:b2e1a2660ec2 27 /**************************************************************************/
rgrover1 710:b2e1a2660ec2 28 /*!
rgrover1 710:b2e1a2660ec2 29 \brief
rgrover1 710:b2e1a2660ec2 30 This class provides several helper functions to generate properly
vcoubard 1048:efb29faf12fc 31 formatted GAP Advertising and Scan Response data payloads.
rgrover1 710:b2e1a2660ec2 32
rgrover1 710:b2e1a2660ec2 33 \note
vcoubard 1048:efb29faf12fc 34 See Bluetooth Specification 4.0 (Vol. 3), Part C, Sections 11 and 18
rgrover1 710:b2e1a2660ec2 35 for further information on Advertising and Scan Response data.
rgrover1 710:b2e1a2660ec2 36
rgrover1 710:b2e1a2660ec2 37 \par Advertising and Scan Response Payloads
rgrover1 710:b2e1a2660ec2 38 Advertising data and Scan Response data are organized around a set of
rgrover1 710:b2e1a2660ec2 39 data types called 'AD types' in Bluetooth 4.0 (see the Bluetooth Core
rgrover1 710:b2e1a2660ec2 40 Specification v4.0, Vol. 3, Part C, Sections 11 and 18).
rgrover1 710:b2e1a2660ec2 41
rgrover1 710:b2e1a2660ec2 42 \par
vcoubard 1048:efb29faf12fc 43 Each AD type has its own standardized assigned number, as defined
rgrover1 710:b2e1a2660ec2 44 by the Bluetooth SIG:
rgrover1 710:b2e1a2660ec2 45 https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
rgrover1 710:b2e1a2660ec2 46
rgrover1 710:b2e1a2660ec2 47 \par
vcoubard 1048:efb29faf12fc 48 For convenience, all appropriate AD types are encapsulated
vcoubard 1048:efb29faf12fc 49 in GapAdvertisingData::DataType.
rgrover1 710:b2e1a2660ec2 50
rgrover1 710:b2e1a2660ec2 51 \par
rgrover1 710:b2e1a2660ec2 52 Before the AD Types and their payload (if any) can be inserted into
rgrover1 710:b2e1a2660ec2 53 the Advertising or Scan Response frames, they need to be formatted as
rgrover1 710:b2e1a2660ec2 54 follows:
rgrover1 710:b2e1a2660ec2 55
vcoubard 1048:efb29faf12fc 56 \li \c Record length (1 byte).
vcoubard 1048:efb29faf12fc 57 \li \c AD Type (1 byte).
vcoubard 1048:efb29faf12fc 58 \li \c AD payload (optional; only present if record length > 1).
rgrover1 710:b2e1a2660ec2 59
rgrover1 710:b2e1a2660ec2 60 \par
rgrover1 710:b2e1a2660ec2 61 This class takes care of properly formatting the payload, performs
rgrover1 710:b2e1a2660ec2 62 some basic checks on the payload length, and tries to avoid common
rgrover1 710:b2e1a2660ec2 63 errors like adding an exclusive AD field twice in the Advertising
rgrover1 710:b2e1a2660ec2 64 or Scan Response payload.
rgrover1 710:b2e1a2660ec2 65
rgrover1 710:b2e1a2660ec2 66 \par EXAMPLE
rgrover1 710:b2e1a2660ec2 67
rgrover1 710:b2e1a2660ec2 68 \code
rgrover1 710:b2e1a2660ec2 69
rgrover1 710:b2e1a2660ec2 70 // ToDo
rgrover1 710:b2e1a2660ec2 71
rgrover1 710:b2e1a2660ec2 72 \endcode
rgrover1 710:b2e1a2660ec2 73 */
rgrover1 710:b2e1a2660ec2 74 /**************************************************************************/
rgrover1 710:b2e1a2660ec2 75 class GapAdvertisingData
rgrover1 710:b2e1a2660ec2 76 {
rgrover1 710:b2e1a2660ec2 77 public:
rgrover1 710:b2e1a2660ec2 78 /**********************************************************************/
rgrover1 710:b2e1a2660ec2 79 /*!
rgrover1 710:b2e1a2660ec2 80 \brief
rgrover1 710:b2e1a2660ec2 81 A list of Advertising Data types commonly used by peripherals.
rgrover1 710:b2e1a2660ec2 82 These AD types are used to describe the capabilities of the
vcoubard 1048:efb29faf12fc 83 peripheral, and are inserted inside the advertising or scan
rgrover1 710:b2e1a2660ec2 84 response payloads.
rgrover1 710:b2e1a2660ec2 85
rgrover1 710:b2e1a2660ec2 86 \par Source
rgrover1 710:b2e1a2660ec2 87 \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18
rgrover1 710:b2e1a2660ec2 88 \li \c https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
rgrover1 710:b2e1a2660ec2 89 */
rgrover1 710:b2e1a2660ec2 90 /**********************************************************************/
rgrover1 756:503c4bd89a3d 91 enum DataType_t {
vcoubard 1052:b55e1ad3e1b3 92 FLAGS = 0x01, /**< \ref *Flags */
vcoubard 1052:b55e1ad3e1b3 93 INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, /**< Incomplete list of 16-bit Service IDs */
vcoubard 1052:b55e1ad3e1b3 94 COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, /**< Complete list of 16-bit Service IDs */
vcoubard 1052:b55e1ad3e1b3 95 INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
vcoubard 1052:b55e1ad3e1b3 96 COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
vcoubard 1052:b55e1ad3e1b3 97 INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit Service IDs */
vcoubard 1052:b55e1ad3e1b3 98 COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, /**< Complete list of 128-bit Service IDs */
vcoubard 1052:b55e1ad3e1b3 99 SHORTENED_LOCAL_NAME = 0x08, /**< Shortened Local Name */
vcoubard 1052:b55e1ad3e1b3 100 COMPLETE_LOCAL_NAME = 0x09, /**< Complete Local Name */
vcoubard 1052:b55e1ad3e1b3 101 TX_POWER_LEVEL = 0x0A, /**< TX Power Level (in dBm) */
vcoubard 1052:b55e1ad3e1b3 102 DEVICE_ID = 0x10, /**< Device ID */
vcoubard 1052:b55e1ad3e1b3 103 SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave Connection Interval Range */
vcoubard 1052:b55e1ad3e1b3 104 LIST_128BIT_SOLICITATION_IDS = 0x15, /**< List of 128 bit service UUIDs the device is looking for */
vcoubard 1052:b55e1ad3e1b3 105 SERVICE_DATA = 0x16, /**< Service Data */
vcoubard 1052:b55e1ad3e1b3 106 APPEARANCE = 0x19, /**< \ref Appearance */
vcoubard 1052:b55e1ad3e1b3 107 ADVERTISING_INTERVAL = 0x1A, /**< Advertising Interval */
vcoubard 1052:b55e1ad3e1b3 108 MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer Specific Data */
rgrover1 710:b2e1a2660ec2 109 };
rgrover1 756:503c4bd89a3d 110 typedef enum DataType_t DataType; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 111
rgrover1 710:b2e1a2660ec2 112 /**********************************************************************/
rgrover1 710:b2e1a2660ec2 113 /*!
rgrover1 710:b2e1a2660ec2 114 \brief
vcoubard 1048:efb29faf12fc 115 A list of values for the FLAGS AD Type.
rgrover1 710:b2e1a2660ec2 116
rgrover1 710:b2e1a2660ec2 117 \note
rgrover1 710:b2e1a2660ec2 118 You can use more than one value in the FLAGS AD Type (ex.
rgrover1 710:b2e1a2660ec2 119 LE_GENERAL_DISCOVERABLE and BREDR_NOT_SUPPORTED).
rgrover1 710:b2e1a2660ec2 120
rgrover1 710:b2e1a2660ec2 121 \par Source
rgrover1 710:b2e1a2660ec2 122 \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1
rgrover1 710:b2e1a2660ec2 123 */
rgrover1 710:b2e1a2660ec2 124 /**********************************************************************/
rgrover1 756:503c4bd89a3d 125 enum Flags_t {
vcoubard 1048:efb29faf12fc 126 LE_LIMITED_DISCOVERABLE = 0x01, /**< *Peripheral device is discoverable for a limited period of time. */
vcoubard 1048:efb29faf12fc 127 LE_GENERAL_DISCOVERABLE = 0x02, /**< Peripheral device is discoverable at any moment. */
vcoubard 1048:efb29faf12fc 128 BREDR_NOT_SUPPORTED = 0x04, /**< Peripheral device is LE only. */
vcoubard 1048:efb29faf12fc 129 SIMULTANEOUS_LE_BREDR_C = 0x08, /**< Not relevant - central mode only. */
vcoubard 1048:efb29faf12fc 130 SIMULTANEOUS_LE_BREDR_H = 0x10 /**< Not relevant - central mode only. */
rgrover1 710:b2e1a2660ec2 131 };
rgrover1 756:503c4bd89a3d 132 typedef enum Flags_t Flags; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 133
rgrover1 710:b2e1a2660ec2 134 /**********************************************************************/
rgrover1 710:b2e1a2660ec2 135 /*!
rgrover1 710:b2e1a2660ec2 136 \brief
rgrover1 710:b2e1a2660ec2 137 A list of values for the APPEARANCE AD Type, which describes the
vcoubard 1048:efb29faf12fc 138 physical shape or appearance of the device.
rgrover1 710:b2e1a2660ec2 139
rgrover1 710:b2e1a2660ec2 140 \par Source
rgrover1 710:b2e1a2660ec2 141 \li \c Bluetooth Core Specification Supplement, Part A, Section 1.12
rgrover1 710:b2e1a2660ec2 142 \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2
rgrover1 710:b2e1a2660ec2 143 \li \c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
rgrover1 710:b2e1a2660ec2 144 */
rgrover1 710:b2e1a2660ec2 145 /**********************************************************************/
rgrover1 756:503c4bd89a3d 146 enum Appearance_t {
vcoubard 1048:efb29faf12fc 147 UNKNOWN = 0, /**< Unknown or unspecified appearance type. */
vcoubard 1048:efb29faf12fc 148 GENERIC_PHONE = 64, /**< Generic Phone. */
vcoubard 1048:efb29faf12fc 149 GENERIC_COMPUTER = 128, /**< Generic Computer. */
vcoubard 1048:efb29faf12fc 150 GENERIC_WATCH = 192, /**< Generic Watch. */
vcoubard 1048:efb29faf12fc 151 WATCH_SPORTS_WATCH = 193, /**< Sports Watch. */
vcoubard 1048:efb29faf12fc 152 GENERIC_CLOCK = 256, /**< Generic Clock. */
vcoubard 1048:efb29faf12fc 153 GENERIC_DISPLAY = 320, /**< Generic Display. */
vcoubard 1048:efb29faf12fc 154 GENERIC_REMOTE_CONTROL = 384, /**< Generic Remote Control. */
vcoubard 1048:efb29faf12fc 155 GENERIC_EYE_GLASSES = 448, /**< Generic Eye Glasses. */
vcoubard 1048:efb29faf12fc 156 GENERIC_TAG = 512, /**< Generic Tag. */
vcoubard 1048:efb29faf12fc 157 GENERIC_KEYRING = 576, /**< Generic Keyring. */
vcoubard 1048:efb29faf12fc 158 GENERIC_MEDIA_PLAYER = 640, /**< Generic Media Player. */
vcoubard 1048:efb29faf12fc 159 GENERIC_BARCODE_SCANNER = 704, /**< Generic Barcode Scanner. */
vcoubard 1048:efb29faf12fc 160 GENERIC_THERMOMETER = 768, /**< Generic Thermometer. */
vcoubard 1048:efb29faf12fc 161 THERMOMETER_EAR = 769, /**< Ear Thermometer. */
vcoubard 1048:efb29faf12fc 162 GENERIC_HEART_RATE_SENSOR = 832, /**< Generic Heart Rate Sensor. */
vcoubard 1048:efb29faf12fc 163 HEART_RATE_SENSOR_HEART_RATE_BELT = 833, /**< Belt Heart Rate Sensor. */
vcoubard 1048:efb29faf12fc 164 GENERIC_BLOOD_PRESSURE = 896, /**< Generic Blood Pressure. */
vcoubard 1048:efb29faf12fc 165 BLOOD_PRESSURE_ARM = 897, /**< Arm Blood Pressure. */
vcoubard 1048:efb29faf12fc 166 BLOOD_PRESSURE_WRIST = 898, /**< Wrist Blood Pressure. */
vcoubard 1048:efb29faf12fc 167 HUMAN_INTERFACE_DEVICE_HID = 960, /**< Human Interface Device (HID). */
vcoubard 1048:efb29faf12fc 168 KEYBOARD = 961, /**< Keyboard. */
vcoubard 1048:efb29faf12fc 169 MOUSE = 962, /**< Mouse. */
vcoubard 1048:efb29faf12fc 170 JOYSTICK = 963, /**< Joystick. */
vcoubard 1048:efb29faf12fc 171 GAMEPAD = 964, /**< Gamepad. */
vcoubard 1048:efb29faf12fc 172 DIGITIZER_TABLET = 965, /**< Digitizer Tablet. */
vcoubard 1048:efb29faf12fc 173 CARD_READER = 966, /**< Card Reader. */
vcoubard 1048:efb29faf12fc 174 DIGITAL_PEN = 967, /**< Digital Pen. */
vcoubard 1048:efb29faf12fc 175 BARCODE_SCANNER = 968, /**< Barcode Scanner. */
vcoubard 1048:efb29faf12fc 176 GENERIC_GLUCOSE_METER = 1024, /**< Generic Glucose Meter. */
vcoubard 1048:efb29faf12fc 177 GENERIC_RUNNING_WALKING_SENSOR = 1088, /**< Generic Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 178 RUNNING_WALKING_SENSOR_IN_SHOE = 1089, /**< In Shoe Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 179 RUNNING_WALKING_SENSOR_ON_SHOE = 1090, /**< On Shoe Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 180 RUNNING_WALKING_SENSOR_ON_HIP = 1091, /**< On Hip Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 181 GENERIC_CYCLING = 1152, /**< Generic Cycling. */
vcoubard 1048:efb29faf12fc 182 CYCLING_CYCLING_COMPUTER = 1153, /**< Cycling Computer. */
vcoubard 1048:efb29faf12fc 183 CYCLING_SPEED_SENSOR = 1154, /**< Cycling Speed Sensor. */
vcoubard 1048:efb29faf12fc 184 CYCLING_CADENCE_SENSOR = 1155, /**< Cycling Cadence Sensor. */
vcoubard 1048:efb29faf12fc 185 CYCLING_POWER_SENSOR = 1156, /**< Cycling Power Sensor. */
vcoubard 1048:efb29faf12fc 186 CYCLING_SPEED_AND_CADENCE_SENSOR = 1157, /**< Cycling Speed and Cadence Sensor. */
vcoubard 1048:efb29faf12fc 187 PULSE_OXIMETER_GENERIC = 3136, /**< Generic Pulse Oximeter. */
vcoubard 1048:efb29faf12fc 188 PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip Pulse Oximeter. */
vcoubard 1048:efb29faf12fc 189 PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn Pulse Oximeter. */
vcoubard 1094:ff274a1b7a14 190 GENERIC_WEIGHT_SCALE = 3200, /**< Generic Weight Scale. */
vcoubard 1048:efb29faf12fc 191 OUTDOOR_GENERIC = 5184, /**< Generic Outdoor. */
vcoubard 1048:efb29faf12fc 192 OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device. */
vcoubard 1048:efb29faf12fc 193 OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device. */
vcoubard 1048:efb29faf12fc 194 OUTDOOR_LOCATION_POD = 5187, /**< Outdoor Location Pod. */
vcoubard 1048:efb29faf12fc 195 OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188 /**< Outdoor Location and Navigation Pod. */
rgrover1 710:b2e1a2660ec2 196 };
rgrover1 756:503c4bd89a3d 197 typedef enum Appearance_t Appearance; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 198
rgrover1 710:b2e1a2660ec2 199 GapAdvertisingData(void) : _payload(), _payloadLen(0), _appearance(GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 200 /* empty */
rgrover1 710:b2e1a2660ec2 201 }
rgrover1 710:b2e1a2660ec2 202
rgrover1 710:b2e1a2660ec2 203 /**
vcoubard 1048:efb29faf12fc 204 * Adds advertising data based on the specified AD type (see DataType).
vcoubard 1096:c3a43f09f1c5 205 * If the supplied AD type is already present in the advertising
vcoubard 1096:c3a43f09f1c5 206 * payload, then the value is updated.
rgrover1 763:36c3e2b1f1ae 207 *
rgrover1 765:4cd91998cd48 208 * @param[in] advDataType The Advertising 'DataType' to add.
rgrover1 765:4cd91998cd48 209 * @param[in] payload Pointer to the payload contents.
rgrover1 765:4cd91998cd48 210 * @param[in] len Size of the payload in bytes.
rgrover1 763:36c3e2b1f1ae 211 *
vcoubard 1096:c3a43f09f1c5 212 * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
vcoubard 1096:c3a43f09f1c5 213 * advertising buffer to overflow. BLE_ERROR_NONE is returned
vcoubard 1096:c3a43f09f1c5 214 * on success.
vcoubard 1096:c3a43f09f1c5 215 *
vcoubard 1096:c3a43f09f1c5 216 * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
vcoubard 1096:c3a43f09f1c5 217 * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
vcoubard 1096:c3a43f09f1c5 218 * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
vcoubard 1096:c3a43f09f1c5 219 * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
vcoubard 1096:c3a43f09f1c5 220 * supplied value is appended to the values previously added to the
vcoubard 1096:c3a43f09f1c5 221 * payload.
vcoubard 1096:c3a43f09f1c5 222 */
vcoubard 1096:c3a43f09f1c5 223 ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
vcoubard 1096:c3a43f09f1c5 224 {
vcoubard 1096:c3a43f09f1c5 225 // find field
vcoubard 1096:c3a43f09f1c5 226 uint8_t* field = findField(advDataType);
vcoubard 1096:c3a43f09f1c5 227
vcoubard 1096:c3a43f09f1c5 228 if (field) {
vcoubard 1096:c3a43f09f1c5 229 // Field type already exist, either add to field or replace
vcoubard 1096:c3a43f09f1c5 230 return updateFieldPayload(advDataType, payload, len, field);
vcoubard 1096:c3a43f09f1c5 231 } else {
vcoubard 1096:c3a43f09f1c5 232 // field doesn't exists, insert new
vcoubard 1096:c3a43f09f1c5 233 return appendField(advDataType, payload, len);
vcoubard 1096:c3a43f09f1c5 234 }
vcoubard 1096:c3a43f09f1c5 235 }
vcoubard 1096:c3a43f09f1c5 236
vcoubard 1096:c3a43f09f1c5 237 /**
vcoubard 1096:c3a43f09f1c5 238 * Update a particular ADV field in the advertising payload (based on
vcoubard 1096:c3a43f09f1c5 239 * matching type).
vcoubard 1096:c3a43f09f1c5 240 *
vcoubard 1096:c3a43f09f1c5 241 * @param[in] advDataType The Advertising 'DataType' to add.
vcoubard 1096:c3a43f09f1c5 242 * @param[in] payload Pointer to the payload contents.
vcoubard 1096:c3a43f09f1c5 243 * @param[in] len Size of the payload in bytes.
vcoubard 1096:c3a43f09f1c5 244 *
vcoubard 1096:c3a43f09f1c5 245 * @return BLE_ERROR_UNSPECIFIED if the specified field is not found,
vcoubard 1096:c3a43f09f1c5 246 * BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
vcoubard 1096:c3a43f09f1c5 247 * advertising buffer to overflow. BLE_ERROR_NONE is returned
vcoubard 1096:c3a43f09f1c5 248 * on success.
rgrover1 763:36c3e2b1f1ae 249 */
rgrover1 765:4cd91998cd48 250 ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
rgrover1 765:4cd91998cd48 251 {
vcoubard 1096:c3a43f09f1c5 252 // find field
vcoubard 1096:c3a43f09f1c5 253 uint8_t* field = findField(advDataType);
rgrover1 765:4cd91998cd48 254
vcoubard 1096:c3a43f09f1c5 255 if (field) {
vcoubard 1096:c3a43f09f1c5 256 // Field type already exist, either add to field or replace
vcoubard 1096:c3a43f09f1c5 257 return updateFieldPayload(advDataType, payload, len, field);
vcoubard 1096:c3a43f09f1c5 258 } else {
vcoubard 1096:c3a43f09f1c5 259 // field doesn't exists, return an error
vcoubard 1096:c3a43f09f1c5 260 return BLE_ERROR_UNSPECIFIED;
rgrover1 763:36c3e2b1f1ae 261 }
rgrover1 763:36c3e2b1f1ae 262 }
rgrover1 763:36c3e2b1f1ae 263
rgrover1 763:36c3e2b1f1ae 264 /**
vcoubard 1048:efb29faf12fc 265 * Helper function to add APPEARANCE data to the advertising payload.
rgrover1 710:b2e1a2660ec2 266 *
rgrover1 710:b2e1a2660ec2 267 * @param appearance
vcoubard 1048:efb29faf12fc 268 * The APPEARANCE value to add.
rgrover1 710:b2e1a2660ec2 269 *
rgrover1 710:b2e1a2660ec2 270 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 271 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 272 */
rgrover1 710:b2e1a2660ec2 273 ble_error_t addAppearance(Appearance appearance = GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 274 _appearance = appearance;
rgrover1 710:b2e1a2660ec2 275 return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
rgrover1 710:b2e1a2660ec2 276 }
rgrover1 710:b2e1a2660ec2 277
rgrover1 710:b2e1a2660ec2 278 /**
rgrover1 710:b2e1a2660ec2 279 * Helper function to add FLAGS data to the advertising payload.
rgrover1 710:b2e1a2660ec2 280 * @param flags
rgrover1 710:b2e1a2660ec2 281 * LE_LIMITED_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 282 * The peripheral is discoverable for a limited period of time.
rgrover1 710:b2e1a2660ec2 283 * LE_GENERAL_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 284 * The peripheral is permanently discoverable.
rgrover1 710:b2e1a2660ec2 285 * BREDR_NOT_SUPPORTED
rgrover1 710:b2e1a2660ec2 286 * This peripheral is a Bluetooth Low Energy only device (no EDR support).
rgrover1 710:b2e1a2660ec2 287 *
rgrover1 710:b2e1a2660ec2 288 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 289 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 290 */
rgrover1 710:b2e1a2660ec2 291 ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE) {
rgrover1 710:b2e1a2660ec2 292 return addData(GapAdvertisingData::FLAGS, &flags, 1);
rgrover1 710:b2e1a2660ec2 293 }
rgrover1 710:b2e1a2660ec2 294
rgrover1 710:b2e1a2660ec2 295 /**
vcoubard 1048:efb29faf12fc 296 * Helper function to add TX_POWER_LEVEL data to the advertising payload.
rgrover1 710:b2e1a2660ec2 297 *
rgrover1 710:b2e1a2660ec2 298 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 299 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 300 */
rgrover1 710:b2e1a2660ec2 301 ble_error_t addTxPower(int8_t txPower) {
vcoubard 1048:efb29faf12fc 302 /* To Do: Basic error checking to make sure txPower is in range. */
rgrover1 710:b2e1a2660ec2 303 return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
rgrover1 710:b2e1a2660ec2 304 }
rgrover1 710:b2e1a2660ec2 305
rgrover1 710:b2e1a2660ec2 306 /**
vcoubard 1048:efb29faf12fc 307 * Clears the payload and resets the payload length counter.
rgrover1 710:b2e1a2660ec2 308 */
rgrover1 710:b2e1a2660ec2 309 void clear(void) {
rgrover1 710:b2e1a2660ec2 310 memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
rgrover1 710:b2e1a2660ec2 311 _payloadLen = 0;
rgrover1 710:b2e1a2660ec2 312 }
rgrover1 710:b2e1a2660ec2 313
rgrover1 710:b2e1a2660ec2 314 /**
vcoubard 1048:efb29faf12fc 315 * Returns a pointer to the current payload.
rgrover1 710:b2e1a2660ec2 316 */
rgrover1 710:b2e1a2660ec2 317 const uint8_t *getPayload(void) const {
rgrover1 769:2d236d9afa9e 318 return _payload;
rgrover1 710:b2e1a2660ec2 319 }
rgrover1 710:b2e1a2660ec2 320
rgrover1 710:b2e1a2660ec2 321 /**
vcoubard 1048:efb29faf12fc 322 * Returns the current payload length (0..31 bytes).
rgrover1 710:b2e1a2660ec2 323 */
rgrover1 710:b2e1a2660ec2 324 uint8_t getPayloadLen(void) const {
rgrover1 710:b2e1a2660ec2 325 return _payloadLen;
rgrover1 710:b2e1a2660ec2 326 }
rgrover1 710:b2e1a2660ec2 327
rgrover1 710:b2e1a2660ec2 328 /**
vcoubard 1048:efb29faf12fc 329 * Returns the 16-bit appearance value for this device.
rgrover1 710:b2e1a2660ec2 330 */
rgrover1 710:b2e1a2660ec2 331 uint16_t getAppearance(void) const {
rgrover1 710:b2e1a2660ec2 332 return (uint16_t)_appearance;
rgrover1 710:b2e1a2660ec2 333 }
rgrover1 710:b2e1a2660ec2 334
vcoubard 1052:b55e1ad3e1b3 335 /**
vcoubard 1052:b55e1ad3e1b3 336 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 337 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 338 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 339 */
vcoubard 1052:b55e1ad3e1b3 340 const uint8_t* findField(DataType_t type) const {
vcoubard 1052:b55e1ad3e1b3 341 return findField(type);
vcoubard 1052:b55e1ad3e1b3 342 }
vcoubard 1052:b55e1ad3e1b3 343
rgrover1 710:b2e1a2660ec2 344 private:
vcoubard 1052:b55e1ad3e1b3 345 /**
vcoubard 1052:b55e1ad3e1b3 346 * Append advertising data based on the specified AD type (see DataType)
vcoubard 1052:b55e1ad3e1b3 347 */
vcoubard 1052:b55e1ad3e1b3 348 ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
vcoubard 1052:b55e1ad3e1b3 349 {
vcoubard 1052:b55e1ad3e1b3 350 /* Make sure we don't exceed the 31 byte payload limit */
vcoubard 1052:b55e1ad3e1b3 351 if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1052:b55e1ad3e1b3 352 return BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1052:b55e1ad3e1b3 353 }
vcoubard 1052:b55e1ad3e1b3 354
vcoubard 1052:b55e1ad3e1b3 355 /* Field length. */
vcoubard 1052:b55e1ad3e1b3 356 memset(&_payload[_payloadLen], len + 1, 1);
vcoubard 1052:b55e1ad3e1b3 357 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 358
vcoubard 1052:b55e1ad3e1b3 359 /* Field ID. */
vcoubard 1052:b55e1ad3e1b3 360 memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
vcoubard 1052:b55e1ad3e1b3 361 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 362
vcoubard 1052:b55e1ad3e1b3 363 /* Payload. */
vcoubard 1052:b55e1ad3e1b3 364 memcpy(&_payload[_payloadLen], payload, len);
vcoubard 1052:b55e1ad3e1b3 365 _payloadLen += len;
vcoubard 1052:b55e1ad3e1b3 366
vcoubard 1052:b55e1ad3e1b3 367 return BLE_ERROR_NONE;
vcoubard 1052:b55e1ad3e1b3 368 }
vcoubard 1052:b55e1ad3e1b3 369
vcoubard 1052:b55e1ad3e1b3 370 /**
vcoubard 1052:b55e1ad3e1b3 371 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 372 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 373 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 374 */
vcoubard 1052:b55e1ad3e1b3 375 uint8_t* findField(DataType_t type) {
vcoubard 1052:b55e1ad3e1b3 376 // scan through advertisement data
vcoubard 1052:b55e1ad3e1b3 377 for (uint8_t idx = 0; idx < _payloadLen; ) {
vcoubard 1052:b55e1ad3e1b3 378 uint8_t fieldType = _payload[idx + 1];
vcoubard 1052:b55e1ad3e1b3 379
vcoubard 1052:b55e1ad3e1b3 380 if (fieldType == type) {
vcoubard 1052:b55e1ad3e1b3 381 return &_payload[idx];
vcoubard 1052:b55e1ad3e1b3 382 }
vcoubard 1052:b55e1ad3e1b3 383
vcoubard 1052:b55e1ad3e1b3 384 // advance to next field
vcoubard 1052:b55e1ad3e1b3 385 idx += _payload[idx] + 1;
vcoubard 1052:b55e1ad3e1b3 386 }
vcoubard 1052:b55e1ad3e1b3 387
vcoubard 1052:b55e1ad3e1b3 388 // field not found
vcoubard 1052:b55e1ad3e1b3 389 return NULL;
vcoubard 1052:b55e1ad3e1b3 390 }
vcoubard 1052:b55e1ad3e1b3 391
vcoubard 1096:c3a43f09f1c5 392 /**
vcoubard 1096:c3a43f09f1c5 393 * Given the a pointer to a field in the advertising payload it replaces
vcoubard 1096:c3a43f09f1c5 394 * the existing data in the field with the supplied data.
vcoubard 1096:c3a43f09f1c5 395 * Returns BLE_ERROR_NONE on success.
vcoubard 1096:c3a43f09f1c5 396 */
vcoubard 1096:c3a43f09f1c5 397 ble_error_t updateFieldPayload(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
vcoubard 1096:c3a43f09f1c5 398 {
vcoubard 1096:c3a43f09f1c5 399 ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1096:c3a43f09f1c5 400
vcoubard 1096:c3a43f09f1c5 401 switch(advDataType) {
vcoubard 1096:c3a43f09f1c5 402 // These fields will have the new data appended if there is sufficient space
vcoubard 1096:c3a43f09f1c5 403 case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 404 case COMPLETE_LIST_16BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 405 case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 406 case COMPLETE_LIST_32BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 407 case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 408 case COMPLETE_LIST_128BIT_SERVICE_IDS:
vcoubard 1096:c3a43f09f1c5 409 case LIST_128BIT_SOLICITATION_IDS: {
vcoubard 1096:c3a43f09f1c5 410 // check if data fits
vcoubard 1096:c3a43f09f1c5 411 if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1096:c3a43f09f1c5 412 // make room for new field by moving the remainder of the
vcoubard 1096:c3a43f09f1c5 413 // advertisement payload "to the right" starting after the
vcoubard 1096:c3a43f09f1c5 414 // TYPE field.
vcoubard 1096:c3a43f09f1c5 415 uint8_t* end = &_payload[_payloadLen];
vcoubard 1096:c3a43f09f1c5 416
vcoubard 1096:c3a43f09f1c5 417 while (&field[1] < end) {
vcoubard 1096:c3a43f09f1c5 418 end[len] = *end;
vcoubard 1096:c3a43f09f1c5 419 end--;
vcoubard 1096:c3a43f09f1c5 420 }
vcoubard 1096:c3a43f09f1c5 421
vcoubard 1096:c3a43f09f1c5 422 // insert new data
vcoubard 1096:c3a43f09f1c5 423 for (uint8_t idx = 0; idx < len; idx++) {
vcoubard 1096:c3a43f09f1c5 424 field[2 + idx] = payload[idx];
vcoubard 1096:c3a43f09f1c5 425 }
vcoubard 1096:c3a43f09f1c5 426
vcoubard 1096:c3a43f09f1c5 427 // increment lengths
vcoubard 1096:c3a43f09f1c5 428 field[0] += len;
vcoubard 1096:c3a43f09f1c5 429 _payloadLen += len;
vcoubard 1096:c3a43f09f1c5 430
vcoubard 1096:c3a43f09f1c5 431 result = BLE_ERROR_NONE;
vcoubard 1096:c3a43f09f1c5 432 }
vcoubard 1096:c3a43f09f1c5 433
vcoubard 1096:c3a43f09f1c5 434 break;
vcoubard 1096:c3a43f09f1c5 435 }
vcoubard 1096:c3a43f09f1c5 436 // These fields will be overwritten with the new value
vcoubard 1096:c3a43f09f1c5 437 default: {
vcoubard 1096:c3a43f09f1c5 438 // current field length, with the type subtracted
vcoubard 1096:c3a43f09f1c5 439 uint8_t dataLength = field[0] - 1;
vcoubard 1096:c3a43f09f1c5 440
vcoubard 1096:c3a43f09f1c5 441 // new data has same length, do in-order replacement
vcoubard 1096:c3a43f09f1c5 442 if (len == dataLength) {
vcoubard 1096:c3a43f09f1c5 443 for (uint8_t idx = 0; idx < dataLength; idx++) {
vcoubard 1096:c3a43f09f1c5 444 field[2 + idx] = payload[idx];
vcoubard 1096:c3a43f09f1c5 445 }
vcoubard 1096:c3a43f09f1c5 446 } else {
vcoubard 1096:c3a43f09f1c5 447 // check if data fits
vcoubard 1096:c3a43f09f1c5 448 if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1096:c3a43f09f1c5 449
vcoubard 1096:c3a43f09f1c5 450 // remove old field
vcoubard 1096:c3a43f09f1c5 451 while ((field + dataLength + 2) < &_payload[_payloadLen]) {
vcoubard 1096:c3a43f09f1c5 452 *field = field[dataLength + 2];
vcoubard 1096:c3a43f09f1c5 453 field++;
vcoubard 1096:c3a43f09f1c5 454 }
vcoubard 1096:c3a43f09f1c5 455
vcoubard 1096:c3a43f09f1c5 456 // reduce length
vcoubard 1096:c3a43f09f1c5 457 _payloadLen -= dataLength + 2;
vcoubard 1096:c3a43f09f1c5 458
vcoubard 1096:c3a43f09f1c5 459 // add new field
vcoubard 1096:c3a43f09f1c5 460 result = appendField(advDataType, payload, len);
vcoubard 1096:c3a43f09f1c5 461 }
vcoubard 1096:c3a43f09f1c5 462 }
vcoubard 1096:c3a43f09f1c5 463
vcoubard 1096:c3a43f09f1c5 464 break;
vcoubard 1096:c3a43f09f1c5 465 }
vcoubard 1096:c3a43f09f1c5 466 }
vcoubard 1096:c3a43f09f1c5 467
vcoubard 1096:c3a43f09f1c5 468 return result;
vcoubard 1096:c3a43f09f1c5 469 }
vcoubard 1096:c3a43f09f1c5 470
rgrover1 710:b2e1a2660ec2 471 uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
rgrover1 710:b2e1a2660ec2 472 uint8_t _payloadLen;
rgrover1 710:b2e1a2660ec2 473 uint16_t _appearance;
rgrover1 710:b2e1a2660ec2 474 };
rgrover1 710:b2e1a2660ec2 475
rgrover1 710:b2e1a2660ec2 476 #endif // ifndef __GAP_ADVERTISING_DATA_H__