BLE_API

Committer:
vcoubard
Date:
Wed Apr 06 19:13:46 2016 +0100
Revision:
1131:692ddf04fc42
Parent:
1105:178ed0b132c4
Child:
1135:22aada733dbd
Synchronized with git rev 13bf70b6
Author: Rohit Grover
Release 2.1.5
=============

A minor release to separate the concept of minlen and len in
GattCharacteristic. Also contains some improvements to documentation.

Who changed what in which revision?

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