add "LE Device Address" 0x1B to advertising data types

Fork of BLE_API by Bluetooth Low Energy

Committer:
andrewjfox
Date:
Mon Feb 22 01:00:38 2016 +0000
Revision:
1131:b93434991cfb
Parent:
1105:178ed0b132c4
Add "LE Device Address" 0x1B to advertising data types

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 */
andrewjfox 1131:b93434991cfb 108 BLE_ADDRESS = 0x1B, /**< Bluetooth device address */
vcoubard 1052:b55e1ad3e1b3 109 MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer Specific Data */
rgrover1 710:b2e1a2660ec2 110 };
rgrover1 756:503c4bd89a3d 111 typedef enum DataType_t DataType; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 112
rgrover1 710:b2e1a2660ec2 113 /**********************************************************************/
rgrover1 710:b2e1a2660ec2 114 /*!
rgrover1 710:b2e1a2660ec2 115 \brief
vcoubard 1048:efb29faf12fc 116 A list of values for the FLAGS AD Type.
rgrover1 710:b2e1a2660ec2 117
rgrover1 710:b2e1a2660ec2 118 \note
rgrover1 710:b2e1a2660ec2 119 You can use more than one value in the FLAGS AD Type (ex.
rgrover1 710:b2e1a2660ec2 120 LE_GENERAL_DISCOVERABLE and BREDR_NOT_SUPPORTED).
rgrover1 710:b2e1a2660ec2 121
rgrover1 710:b2e1a2660ec2 122 \par Source
rgrover1 710:b2e1a2660ec2 123 \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1
rgrover1 710:b2e1a2660ec2 124 */
rgrover1 710:b2e1a2660ec2 125 /**********************************************************************/
rgrover1 756:503c4bd89a3d 126 enum Flags_t {
vcoubard 1048:efb29faf12fc 127 LE_LIMITED_DISCOVERABLE = 0x01, /**< *Peripheral device is discoverable for a limited period of time. */
vcoubard 1048:efb29faf12fc 128 LE_GENERAL_DISCOVERABLE = 0x02, /**< Peripheral device is discoverable at any moment. */
vcoubard 1048:efb29faf12fc 129 BREDR_NOT_SUPPORTED = 0x04, /**< Peripheral device is LE only. */
vcoubard 1048:efb29faf12fc 130 SIMULTANEOUS_LE_BREDR_C = 0x08, /**< Not relevant - central mode only. */
vcoubard 1048:efb29faf12fc 131 SIMULTANEOUS_LE_BREDR_H = 0x10 /**< Not relevant - central mode only. */
rgrover1 710:b2e1a2660ec2 132 };
rgrover1 756:503c4bd89a3d 133 typedef enum Flags_t Flags; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 134
rgrover1 710:b2e1a2660ec2 135 /**********************************************************************/
rgrover1 710:b2e1a2660ec2 136 /*!
rgrover1 710:b2e1a2660ec2 137 \brief
rgrover1 710:b2e1a2660ec2 138 A list of values for the APPEARANCE AD Type, which describes the
vcoubard 1048:efb29faf12fc 139 physical shape or appearance of the device.
rgrover1 710:b2e1a2660ec2 140
rgrover1 710:b2e1a2660ec2 141 \par Source
rgrover1 710:b2e1a2660ec2 142 \li \c Bluetooth Core Specification Supplement, Part A, Section 1.12
rgrover1 710:b2e1a2660ec2 143 \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2
rgrover1 710:b2e1a2660ec2 144 \li \c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
rgrover1 710:b2e1a2660ec2 145 */
rgrover1 710:b2e1a2660ec2 146 /**********************************************************************/
rgrover1 756:503c4bd89a3d 147 enum Appearance_t {
vcoubard 1048:efb29faf12fc 148 UNKNOWN = 0, /**< Unknown or unspecified appearance type. */
vcoubard 1048:efb29faf12fc 149 GENERIC_PHONE = 64, /**< Generic Phone. */
vcoubard 1048:efb29faf12fc 150 GENERIC_COMPUTER = 128, /**< Generic Computer. */
vcoubard 1048:efb29faf12fc 151 GENERIC_WATCH = 192, /**< Generic Watch. */
vcoubard 1048:efb29faf12fc 152 WATCH_SPORTS_WATCH = 193, /**< Sports Watch. */
vcoubard 1048:efb29faf12fc 153 GENERIC_CLOCK = 256, /**< Generic Clock. */
vcoubard 1048:efb29faf12fc 154 GENERIC_DISPLAY = 320, /**< Generic Display. */
vcoubard 1048:efb29faf12fc 155 GENERIC_REMOTE_CONTROL = 384, /**< Generic Remote Control. */
vcoubard 1048:efb29faf12fc 156 GENERIC_EYE_GLASSES = 448, /**< Generic Eye Glasses. */
vcoubard 1048:efb29faf12fc 157 GENERIC_TAG = 512, /**< Generic Tag. */
vcoubard 1048:efb29faf12fc 158 GENERIC_KEYRING = 576, /**< Generic Keyring. */
vcoubard 1048:efb29faf12fc 159 GENERIC_MEDIA_PLAYER = 640, /**< Generic Media Player. */
vcoubard 1048:efb29faf12fc 160 GENERIC_BARCODE_SCANNER = 704, /**< Generic Barcode Scanner. */
vcoubard 1048:efb29faf12fc 161 GENERIC_THERMOMETER = 768, /**< Generic Thermometer. */
vcoubard 1048:efb29faf12fc 162 THERMOMETER_EAR = 769, /**< Ear Thermometer. */
vcoubard 1048:efb29faf12fc 163 GENERIC_HEART_RATE_SENSOR = 832, /**< Generic Heart Rate Sensor. */
vcoubard 1048:efb29faf12fc 164 HEART_RATE_SENSOR_HEART_RATE_BELT = 833, /**< Belt Heart Rate Sensor. */
vcoubard 1048:efb29faf12fc 165 GENERIC_BLOOD_PRESSURE = 896, /**< Generic Blood Pressure. */
vcoubard 1048:efb29faf12fc 166 BLOOD_PRESSURE_ARM = 897, /**< Arm Blood Pressure. */
vcoubard 1048:efb29faf12fc 167 BLOOD_PRESSURE_WRIST = 898, /**< Wrist Blood Pressure. */
vcoubard 1048:efb29faf12fc 168 HUMAN_INTERFACE_DEVICE_HID = 960, /**< Human Interface Device (HID). */
vcoubard 1048:efb29faf12fc 169 KEYBOARD = 961, /**< Keyboard. */
vcoubard 1048:efb29faf12fc 170 MOUSE = 962, /**< Mouse. */
vcoubard 1048:efb29faf12fc 171 JOYSTICK = 963, /**< Joystick. */
vcoubard 1048:efb29faf12fc 172 GAMEPAD = 964, /**< Gamepad. */
vcoubard 1048:efb29faf12fc 173 DIGITIZER_TABLET = 965, /**< Digitizer Tablet. */
vcoubard 1048:efb29faf12fc 174 CARD_READER = 966, /**< Card Reader. */
vcoubard 1048:efb29faf12fc 175 DIGITAL_PEN = 967, /**< Digital Pen. */
vcoubard 1048:efb29faf12fc 176 BARCODE_SCANNER = 968, /**< Barcode Scanner. */
vcoubard 1048:efb29faf12fc 177 GENERIC_GLUCOSE_METER = 1024, /**< Generic Glucose Meter. */
vcoubard 1048:efb29faf12fc 178 GENERIC_RUNNING_WALKING_SENSOR = 1088, /**< Generic Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 179 RUNNING_WALKING_SENSOR_IN_SHOE = 1089, /**< In Shoe Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 180 RUNNING_WALKING_SENSOR_ON_SHOE = 1090, /**< On Shoe Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 181 RUNNING_WALKING_SENSOR_ON_HIP = 1091, /**< On Hip Running/Walking Sensor. */
vcoubard 1048:efb29faf12fc 182 GENERIC_CYCLING = 1152, /**< Generic Cycling. */
vcoubard 1048:efb29faf12fc 183 CYCLING_CYCLING_COMPUTER = 1153, /**< Cycling Computer. */
vcoubard 1048:efb29faf12fc 184 CYCLING_SPEED_SENSOR = 1154, /**< Cycling Speed Sensor. */
vcoubard 1048:efb29faf12fc 185 CYCLING_CADENCE_SENSOR = 1155, /**< Cycling Cadence Sensor. */
vcoubard 1048:efb29faf12fc 186 CYCLING_POWER_SENSOR = 1156, /**< Cycling Power Sensor. */
vcoubard 1048:efb29faf12fc 187 CYCLING_SPEED_AND_CADENCE_SENSOR = 1157, /**< Cycling Speed and Cadence Sensor. */
vcoubard 1048:efb29faf12fc 188 PULSE_OXIMETER_GENERIC = 3136, /**< Generic Pulse Oximeter. */
vcoubard 1048:efb29faf12fc 189 PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip Pulse Oximeter. */
vcoubard 1048:efb29faf12fc 190 PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn Pulse Oximeter. */
vcoubard 1094:ff274a1b7a14 191 GENERIC_WEIGHT_SCALE = 3200, /**< Generic Weight Scale. */
vcoubard 1048:efb29faf12fc 192 OUTDOOR_GENERIC = 5184, /**< Generic Outdoor. */
vcoubard 1048:efb29faf12fc 193 OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device. */
vcoubard 1048:efb29faf12fc 194 OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device. */
vcoubard 1048:efb29faf12fc 195 OUTDOOR_LOCATION_POD = 5187, /**< Outdoor Location Pod. */
vcoubard 1048:efb29faf12fc 196 OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188 /**< Outdoor Location and Navigation Pod. */
rgrover1 710:b2e1a2660ec2 197 };
rgrover1 756:503c4bd89a3d 198 typedef enum Appearance_t Appearance; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 199
rgrover1 710:b2e1a2660ec2 200 GapAdvertisingData(void) : _payload(), _payloadLen(0), _appearance(GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 201 /* empty */
rgrover1 710:b2e1a2660ec2 202 }
rgrover1 710:b2e1a2660ec2 203
rgrover1 710:b2e1a2660ec2 204 /**
vcoubard 1048:efb29faf12fc 205 * Adds advertising data based on the specified AD type (see DataType).
vcoubard 1104:0244fbb0324e 206 * If the supplied AD type is already present in the advertising
vcoubard 1104:0244fbb0324e 207 * payload, then the value is updated.
rgrover1 763:36c3e2b1f1ae 208 *
rgrover1 765:4cd91998cd48 209 * @param[in] advDataType The Advertising 'DataType' to add.
rgrover1 765:4cd91998cd48 210 * @param[in] payload Pointer to the payload contents.
rgrover1 765:4cd91998cd48 211 * @param[in] len Size of the payload in bytes.
rgrover1 763:36c3e2b1f1ae 212 *
vcoubard 1104:0244fbb0324e 213 * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
vcoubard 1104:0244fbb0324e 214 * advertising buffer to overflow. BLE_ERROR_NONE is returned
vcoubard 1104:0244fbb0324e 215 * on success.
vcoubard 1104:0244fbb0324e 216 *
vcoubard 1104:0244fbb0324e 217 * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 218 * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 219 * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 220 * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
vcoubard 1104:0244fbb0324e 221 * supplied value is appended to the values previously added to the
vcoubard 1104:0244fbb0324e 222 * payload.
vcoubard 1104:0244fbb0324e 223 */
vcoubard 1104:0244fbb0324e 224 ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
vcoubard 1104:0244fbb0324e 225 {
vcoubard 1104:0244fbb0324e 226 // find field
vcoubard 1104:0244fbb0324e 227 uint8_t* field = findField(advDataType);
vcoubard 1104:0244fbb0324e 228
vcoubard 1104:0244fbb0324e 229 if (field) {
vcoubard 1104:0244fbb0324e 230 // Field type already exist, either add to field or replace
vcoubard 1104:0244fbb0324e 231 return addField(advDataType, payload, len, field);
vcoubard 1104:0244fbb0324e 232 } else {
vcoubard 1104:0244fbb0324e 233 // field doesn't exists, insert new
vcoubard 1104:0244fbb0324e 234 return appendField(advDataType, payload, len);
vcoubard 1104:0244fbb0324e 235 }
vcoubard 1104:0244fbb0324e 236 }
vcoubard 1104:0244fbb0324e 237
vcoubard 1104:0244fbb0324e 238 /**
vcoubard 1104:0244fbb0324e 239 * Update a particular ADV field in the advertising payload (based on
vcoubard 1104:0244fbb0324e 240 * matching type).
vcoubard 1104:0244fbb0324e 241 *
vcoubard 1104:0244fbb0324e 242 * @param[in] advDataType The Advertising 'DataType' to add.
vcoubard 1104:0244fbb0324e 243 * @param[in] payload Pointer to the payload contents.
vcoubard 1104:0244fbb0324e 244 * @param[in] len Size of the payload in bytes.
vcoubard 1104:0244fbb0324e 245 *
vcoubard 1104:0244fbb0324e 246 * @return BLE_ERROR_UNSPECIFIED if the specified field is not found,
vcoubard 1104:0244fbb0324e 247 * BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
vcoubard 1104:0244fbb0324e 248 * advertising buffer to overflow. BLE_ERROR_NONE is returned
vcoubard 1104:0244fbb0324e 249 * on success.
rgrover1 763:36c3e2b1f1ae 250 */
rgrover1 765:4cd91998cd48 251 ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
rgrover1 765:4cd91998cd48 252 {
vcoubard 1104:0244fbb0324e 253 // find field
vcoubard 1104:0244fbb0324e 254 uint8_t* field = findField(advDataType);
rgrover1 765:4cd91998cd48 255
vcoubard 1104:0244fbb0324e 256 if (field) {
vcoubard 1105:178ed0b132c4 257 // Field type already exist, replace field contents
vcoubard 1104:0244fbb0324e 258 return updateField(advDataType, payload, len, field);
vcoubard 1104:0244fbb0324e 259 } else {
vcoubard 1104:0244fbb0324e 260 // field doesn't exists, return an error
vcoubard 1104:0244fbb0324e 261 return BLE_ERROR_UNSPECIFIED;
rgrover1 763:36c3e2b1f1ae 262 }
rgrover1 763:36c3e2b1f1ae 263 }
rgrover1 763:36c3e2b1f1ae 264
rgrover1 763:36c3e2b1f1ae 265 /**
vcoubard 1048:efb29faf12fc 266 * Helper function to add APPEARANCE data to the advertising payload.
rgrover1 710:b2e1a2660ec2 267 *
rgrover1 710:b2e1a2660ec2 268 * @param appearance
vcoubard 1048:efb29faf12fc 269 * The APPEARANCE value to add.
rgrover1 710:b2e1a2660ec2 270 *
rgrover1 710:b2e1a2660ec2 271 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 272 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 273 */
rgrover1 710:b2e1a2660ec2 274 ble_error_t addAppearance(Appearance appearance = GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 275 _appearance = appearance;
rgrover1 710:b2e1a2660ec2 276 return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
rgrover1 710:b2e1a2660ec2 277 }
rgrover1 710:b2e1a2660ec2 278
rgrover1 710:b2e1a2660ec2 279 /**
rgrover1 710:b2e1a2660ec2 280 * Helper function to add FLAGS data to the advertising payload.
rgrover1 710:b2e1a2660ec2 281 * @param flags
rgrover1 710:b2e1a2660ec2 282 * LE_LIMITED_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 283 * The peripheral is discoverable for a limited period of time.
rgrover1 710:b2e1a2660ec2 284 * LE_GENERAL_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 285 * The peripheral is permanently discoverable.
rgrover1 710:b2e1a2660ec2 286 * BREDR_NOT_SUPPORTED
rgrover1 710:b2e1a2660ec2 287 * This peripheral is a Bluetooth Low Energy only device (no EDR support).
rgrover1 710:b2e1a2660ec2 288 *
rgrover1 710:b2e1a2660ec2 289 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 290 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 291 */
rgrover1 710:b2e1a2660ec2 292 ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE) {
rgrover1 710:b2e1a2660ec2 293 return addData(GapAdvertisingData::FLAGS, &flags, 1);
rgrover1 710:b2e1a2660ec2 294 }
rgrover1 710:b2e1a2660ec2 295
rgrover1 710:b2e1a2660ec2 296 /**
vcoubard 1048:efb29faf12fc 297 * Helper function to add TX_POWER_LEVEL data to the advertising payload.
rgrover1 710:b2e1a2660ec2 298 *
rgrover1 710:b2e1a2660ec2 299 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 300 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 301 */
rgrover1 710:b2e1a2660ec2 302 ble_error_t addTxPower(int8_t txPower) {
vcoubard 1048:efb29faf12fc 303 /* To Do: Basic error checking to make sure txPower is in range. */
rgrover1 710:b2e1a2660ec2 304 return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
rgrover1 710:b2e1a2660ec2 305 }
rgrover1 710:b2e1a2660ec2 306
rgrover1 710:b2e1a2660ec2 307 /**
vcoubard 1048:efb29faf12fc 308 * Clears the payload and resets the payload length counter.
rgrover1 710:b2e1a2660ec2 309 */
rgrover1 710:b2e1a2660ec2 310 void clear(void) {
rgrover1 710:b2e1a2660ec2 311 memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
rgrover1 710:b2e1a2660ec2 312 _payloadLen = 0;
rgrover1 710:b2e1a2660ec2 313 }
rgrover1 710:b2e1a2660ec2 314
rgrover1 710:b2e1a2660ec2 315 /**
vcoubard 1048:efb29faf12fc 316 * Returns a pointer to the current payload.
rgrover1 710:b2e1a2660ec2 317 */
rgrover1 710:b2e1a2660ec2 318 const uint8_t *getPayload(void) const {
rgrover1 769:2d236d9afa9e 319 return _payload;
rgrover1 710:b2e1a2660ec2 320 }
rgrover1 710:b2e1a2660ec2 321
rgrover1 710:b2e1a2660ec2 322 /**
vcoubard 1048:efb29faf12fc 323 * Returns the current payload length (0..31 bytes).
rgrover1 710:b2e1a2660ec2 324 */
rgrover1 710:b2e1a2660ec2 325 uint8_t getPayloadLen(void) const {
rgrover1 710:b2e1a2660ec2 326 return _payloadLen;
rgrover1 710:b2e1a2660ec2 327 }
rgrover1 710:b2e1a2660ec2 328
rgrover1 710:b2e1a2660ec2 329 /**
vcoubard 1048:efb29faf12fc 330 * Returns the 16-bit appearance value for this device.
rgrover1 710:b2e1a2660ec2 331 */
rgrover1 710:b2e1a2660ec2 332 uint16_t getAppearance(void) const {
rgrover1 710:b2e1a2660ec2 333 return (uint16_t)_appearance;
rgrover1 710:b2e1a2660ec2 334 }
rgrover1 710:b2e1a2660ec2 335
vcoubard 1052:b55e1ad3e1b3 336 /**
vcoubard 1052:b55e1ad3e1b3 337 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 338 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 339 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 340 */
vcoubard 1052:b55e1ad3e1b3 341 const uint8_t* findField(DataType_t type) const {
vcoubard 1052:b55e1ad3e1b3 342 return findField(type);
vcoubard 1052:b55e1ad3e1b3 343 }
vcoubard 1052:b55e1ad3e1b3 344
rgrover1 710:b2e1a2660ec2 345 private:
vcoubard 1052:b55e1ad3e1b3 346 /**
vcoubard 1052:b55e1ad3e1b3 347 * Append advertising data based on the specified AD type (see DataType)
vcoubard 1052:b55e1ad3e1b3 348 */
vcoubard 1052:b55e1ad3e1b3 349 ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
vcoubard 1052:b55e1ad3e1b3 350 {
vcoubard 1052:b55e1ad3e1b3 351 /* Make sure we don't exceed the 31 byte payload limit */
vcoubard 1052:b55e1ad3e1b3 352 if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1052:b55e1ad3e1b3 353 return BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1052:b55e1ad3e1b3 354 }
vcoubard 1052:b55e1ad3e1b3 355
vcoubard 1052:b55e1ad3e1b3 356 /* Field length. */
vcoubard 1052:b55e1ad3e1b3 357 memset(&_payload[_payloadLen], len + 1, 1);
vcoubard 1052:b55e1ad3e1b3 358 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 359
vcoubard 1052:b55e1ad3e1b3 360 /* Field ID. */
vcoubard 1052:b55e1ad3e1b3 361 memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
vcoubard 1052:b55e1ad3e1b3 362 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 363
vcoubard 1052:b55e1ad3e1b3 364 /* Payload. */
vcoubard 1052:b55e1ad3e1b3 365 memcpy(&_payload[_payloadLen], payload, len);
vcoubard 1052:b55e1ad3e1b3 366 _payloadLen += len;
vcoubard 1052:b55e1ad3e1b3 367
vcoubard 1052:b55e1ad3e1b3 368 return BLE_ERROR_NONE;
vcoubard 1052:b55e1ad3e1b3 369 }
vcoubard 1052:b55e1ad3e1b3 370
vcoubard 1052:b55e1ad3e1b3 371 /**
vcoubard 1052:b55e1ad3e1b3 372 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 373 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 374 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 375 */
vcoubard 1052:b55e1ad3e1b3 376 uint8_t* findField(DataType_t type) {
vcoubard 1052:b55e1ad3e1b3 377 // scan through advertisement data
vcoubard 1052:b55e1ad3e1b3 378 for (uint8_t idx = 0; idx < _payloadLen; ) {
vcoubard 1052:b55e1ad3e1b3 379 uint8_t fieldType = _payload[idx + 1];
vcoubard 1052:b55e1ad3e1b3 380
vcoubard 1052:b55e1ad3e1b3 381 if (fieldType == type) {
vcoubard 1052:b55e1ad3e1b3 382 return &_payload[idx];
vcoubard 1052:b55e1ad3e1b3 383 }
vcoubard 1052:b55e1ad3e1b3 384
vcoubard 1052:b55e1ad3e1b3 385 // advance to next field
vcoubard 1052:b55e1ad3e1b3 386 idx += _payload[idx] + 1;
vcoubard 1052:b55e1ad3e1b3 387 }
vcoubard 1052:b55e1ad3e1b3 388
vcoubard 1052:b55e1ad3e1b3 389 // field not found
vcoubard 1052:b55e1ad3e1b3 390 return NULL;
vcoubard 1052:b55e1ad3e1b3 391 }
vcoubard 1052:b55e1ad3e1b3 392
vcoubard 1104:0244fbb0324e 393 /**
vcoubard 1104:0244fbb0324e 394 * Given the a pointer to a field in the advertising payload it replaces
vcoubard 1104:0244fbb0324e 395 * the existing data in the field with the supplied data.
vcoubard 1104:0244fbb0324e 396 *
vcoubard 1104:0244fbb0324e 397 * When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 398 * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 399 * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
vcoubard 1104:0244fbb0324e 400 * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
vcoubard 1104:0244fbb0324e 401 * supplied value is appended to the values previously added to the
vcoubard 1104:0244fbb0324e 402 * payload.
vcoubard 1104:0244fbb0324e 403 *
vcoubard 1104:0244fbb0324e 404 * Returns BLE_ERROR_NONE on success.
vcoubard 1104:0244fbb0324e 405 */
vcoubard 1104:0244fbb0324e 406 ble_error_t addField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
vcoubard 1104:0244fbb0324e 407 {
vcoubard 1104:0244fbb0324e 408 ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1104:0244fbb0324e 409
vcoubard 1104:0244fbb0324e 410 switch(advDataType) {
vcoubard 1104:0244fbb0324e 411 // These fields will have the new data appended if there is sufficient space
vcoubard 1104:0244fbb0324e 412 case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 413 case COMPLETE_LIST_16BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 414 case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 415 case COMPLETE_LIST_32BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 416 case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 417 case COMPLETE_LIST_128BIT_SERVICE_IDS:
vcoubard 1104:0244fbb0324e 418 case LIST_128BIT_SOLICITATION_IDS: {
vcoubard 1104:0244fbb0324e 419 // check if data fits
vcoubard 1104:0244fbb0324e 420 if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1104:0244fbb0324e 421 // make room for new field by moving the remainder of the
vcoubard 1104:0244fbb0324e 422 // advertisement payload "to the right" starting after the
vcoubard 1104:0244fbb0324e 423 // TYPE field.
vcoubard 1104:0244fbb0324e 424 uint8_t* end = &_payload[_payloadLen];
vcoubard 1104:0244fbb0324e 425
vcoubard 1104:0244fbb0324e 426 while (&field[1] < end) {
vcoubard 1104:0244fbb0324e 427 end[len] = *end;
vcoubard 1104:0244fbb0324e 428 end--;
vcoubard 1104:0244fbb0324e 429 }
vcoubard 1104:0244fbb0324e 430
vcoubard 1104:0244fbb0324e 431 // insert new data
vcoubard 1104:0244fbb0324e 432 for (uint8_t idx = 0; idx < len; idx++) {
vcoubard 1104:0244fbb0324e 433 field[2 + idx] = payload[idx];
vcoubard 1104:0244fbb0324e 434 }
vcoubard 1104:0244fbb0324e 435
vcoubard 1104:0244fbb0324e 436 // increment lengths
vcoubard 1104:0244fbb0324e 437 field[0] += len;
vcoubard 1104:0244fbb0324e 438 _payloadLen += len;
vcoubard 1104:0244fbb0324e 439
vcoubard 1104:0244fbb0324e 440 result = BLE_ERROR_NONE;
vcoubard 1104:0244fbb0324e 441 }
vcoubard 1104:0244fbb0324e 442
vcoubard 1104:0244fbb0324e 443 break;
vcoubard 1104:0244fbb0324e 444 }
vcoubard 1104:0244fbb0324e 445 // These fields will be overwritten with the new value
vcoubard 1104:0244fbb0324e 446 default: {
vcoubard 1104:0244fbb0324e 447 result = updateField(advDataType, payload, len, field);
vcoubard 1104:0244fbb0324e 448
vcoubard 1104:0244fbb0324e 449 break;
vcoubard 1104:0244fbb0324e 450 }
vcoubard 1104:0244fbb0324e 451 }
vcoubard 1104:0244fbb0324e 452
vcoubard 1104:0244fbb0324e 453 return result;
vcoubard 1104:0244fbb0324e 454 }
vcoubard 1104:0244fbb0324e 455
vcoubard 1104:0244fbb0324e 456 /**
vcoubard 1104:0244fbb0324e 457 * Given the a pointer to a field in the advertising payload it replaces
vcoubard 1104:0244fbb0324e 458 * the existing data in the field with the supplied data.
vcoubard 1104:0244fbb0324e 459 * Returns BLE_ERROR_NONE on success.
vcoubard 1104:0244fbb0324e 460 */
vcoubard 1104:0244fbb0324e 461 ble_error_t updateField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
vcoubard 1104:0244fbb0324e 462 {
vcoubard 1104:0244fbb0324e 463 ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1104:0244fbb0324e 464 uint8_t dataLength = field[0] - 1;
vcoubard 1104:0244fbb0324e 465
vcoubard 1104:0244fbb0324e 466 // new data has same length, do in-order replacement
vcoubard 1104:0244fbb0324e 467 if (len == dataLength) {
vcoubard 1104:0244fbb0324e 468 for (uint8_t idx = 0; idx < dataLength; idx++) {
vcoubard 1104:0244fbb0324e 469 field[2 + idx] = payload[idx];
vcoubard 1104:0244fbb0324e 470 }
vcoubard 1104:0244fbb0324e 471
vcoubard 1104:0244fbb0324e 472 result = BLE_ERROR_NONE;
vcoubard 1104:0244fbb0324e 473 } else {
vcoubard 1104:0244fbb0324e 474 // check if data fits
vcoubard 1104:0244fbb0324e 475 if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1104:0244fbb0324e 476
vcoubard 1104:0244fbb0324e 477 // remove old field
vcoubard 1104:0244fbb0324e 478 while ((field + dataLength + 2) < &_payload[_payloadLen]) {
vcoubard 1104:0244fbb0324e 479 *field = field[dataLength + 2];
vcoubard 1104:0244fbb0324e 480 field++;
vcoubard 1104:0244fbb0324e 481 }
vcoubard 1104:0244fbb0324e 482
vcoubard 1104:0244fbb0324e 483 // reduce length
vcoubard 1104:0244fbb0324e 484 _payloadLen -= dataLength + 2;
vcoubard 1104:0244fbb0324e 485
vcoubard 1104:0244fbb0324e 486 // add new field
vcoubard 1104:0244fbb0324e 487 result = appendField(advDataType, payload, len);
vcoubard 1104:0244fbb0324e 488 }
vcoubard 1104:0244fbb0324e 489 }
vcoubard 1104:0244fbb0324e 490
vcoubard 1104:0244fbb0324e 491 return result;
vcoubard 1104:0244fbb0324e 492 }
vcoubard 1104:0244fbb0324e 493
rgrover1 710:b2e1a2660ec2 494 uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
rgrover1 710:b2e1a2660ec2 495 uint8_t _payloadLen;
rgrover1 710:b2e1a2660ec2 496 uint16_t _appearance;
rgrover1 710:b2e1a2660ec2 497 };
rgrover1 710:b2e1a2660ec2 498
rgrover1 710:b2e1a2660ec2 499 #endif // ifndef __GAP_ADVERTISING_DATA_H__