Lancaster University's fork of the mbed BLE API. Lives on github, https://github.com/lancaster-university/BLE_API

Dependents:   microbit-dal microbit-dal microbit-ble-open microbit-dal ... more

Fork of BLE_API by Bluetooth Low Energy

Committer:
LancasterUniversity
Date:
Wed Apr 06 18:40:26 2016 +0100
Revision:
1131:73c11a85c6d6
Parent:
1105:178ed0b132c4
Child:
1137:290d499dd0e8
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
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 1048:efb29faf12fc 190 OUTDOOR_GENERIC = 5184, /**< Generic Outdoor. */
vcoubard 1048:efb29faf12fc 191 OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device. */
vcoubard 1048:efb29faf12fc 192 OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device. */
vcoubard 1048:efb29faf12fc 193 OUTDOOR_LOCATION_POD = 5187, /**< Outdoor Location Pod. */
vcoubard 1048:efb29faf12fc 194 OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188 /**< Outdoor Location and Navigation Pod. */
rgrover1 710:b2e1a2660ec2 195 };
rgrover1 756:503c4bd89a3d 196 typedef enum Appearance_t Appearance; /* Deprecated type alias. This may be dropped in a future release. */
rgrover1 710:b2e1a2660ec2 197
rgrover1 710:b2e1a2660ec2 198 GapAdvertisingData(void) : _payload(), _payloadLen(0), _appearance(GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 199 /* empty */
rgrover1 710:b2e1a2660ec2 200 }
rgrover1 710:b2e1a2660ec2 201
rgrover1 710:b2e1a2660ec2 202 /**
vcoubard 1048:efb29faf12fc 203 * Adds advertising data based on the specified AD type (see DataType).
LancasterUniversity 1131:73c11a85c6d6 204 *
LancasterUniversity 1131:73c11a85c6d6 205 * @param advDataType The Advertising 'DataType' to add.
LancasterUniversity 1131:73c11a85c6d6 206 * @param payload Pointer to the payload contents.
LancasterUniversity 1131:73c11a85c6d6 207 * @param len Size of the payload in bytes.
LancasterUniversity 1131:73c11a85c6d6 208 *
LancasterUniversity 1131:73c11a85c6d6 209 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
LancasterUniversity 1131:73c11a85c6d6 210 * advertising buffer to overflow, else BLE_ERROR_NONE.
LancasterUniversity 1131:73c11a85c6d6 211 */
LancasterUniversity 1131:73c11a85c6d6 212 ble_error_t addData(DataType advDataType, const uint8_t *payload, uint8_t len)
LancasterUniversity 1131:73c11a85c6d6 213 {
LancasterUniversity 1131:73c11a85c6d6 214 ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
LancasterUniversity 1131:73c11a85c6d6 215
LancasterUniversity 1131:73c11a85c6d6 216 // find field
LancasterUniversity 1131:73c11a85c6d6 217 uint8_t* field = findField(advDataType);
LancasterUniversity 1131:73c11a85c6d6 218
LancasterUniversity 1131:73c11a85c6d6 219 // Field type already exist, either add to field or replace
LancasterUniversity 1131:73c11a85c6d6 220 if (field) {
LancasterUniversity 1131:73c11a85c6d6 221 switch(advDataType) {
LancasterUniversity 1131:73c11a85c6d6 222 // These fields will be overwritten with the new value
LancasterUniversity 1131:73c11a85c6d6 223 case FLAGS:
LancasterUniversity 1131:73c11a85c6d6 224 case SHORTENED_LOCAL_NAME:
LancasterUniversity 1131:73c11a85c6d6 225 case COMPLETE_LOCAL_NAME:
LancasterUniversity 1131:73c11a85c6d6 226 case TX_POWER_LEVEL:
LancasterUniversity 1131:73c11a85c6d6 227 case DEVICE_ID:
LancasterUniversity 1131:73c11a85c6d6 228 case SLAVE_CONNECTION_INTERVAL_RANGE:
LancasterUniversity 1131:73c11a85c6d6 229 case SERVICE_DATA:
LancasterUniversity 1131:73c11a85c6d6 230 case APPEARANCE:
LancasterUniversity 1131:73c11a85c6d6 231 case ADVERTISING_INTERVAL:
LancasterUniversity 1131:73c11a85c6d6 232 case MANUFACTURER_SPECIFIC_DATA: {
LancasterUniversity 1131:73c11a85c6d6 233 // current field length, with the type subtracted
LancasterUniversity 1131:73c11a85c6d6 234 uint8_t dataLength = field[0] - 1;
LancasterUniversity 1131:73c11a85c6d6 235
LancasterUniversity 1131:73c11a85c6d6 236 // new data has same length, do in-order replacement
LancasterUniversity 1131:73c11a85c6d6 237 if (len == dataLength) {
LancasterUniversity 1131:73c11a85c6d6 238 for (uint8_t idx = 0; idx < dataLength; idx++) {
LancasterUniversity 1131:73c11a85c6d6 239 field[2 + idx] = payload[idx];
LancasterUniversity 1131:73c11a85c6d6 240 }
LancasterUniversity 1131:73c11a85c6d6 241 } else {
LancasterUniversity 1131:73c11a85c6d6 242 // check if data fits
LancasterUniversity 1131:73c11a85c6d6 243 if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
LancasterUniversity 1131:73c11a85c6d6 244
LancasterUniversity 1131:73c11a85c6d6 245 // remove old field
LancasterUniversity 1131:73c11a85c6d6 246 while ((field + dataLength + 2) < &_payload[_payloadLen]) {
LancasterUniversity 1131:73c11a85c6d6 247 *field = field[dataLength + 2];
LancasterUniversity 1131:73c11a85c6d6 248 field++;
LancasterUniversity 1131:73c11a85c6d6 249 }
LancasterUniversity 1131:73c11a85c6d6 250
LancasterUniversity 1131:73c11a85c6d6 251 // reduce length
LancasterUniversity 1131:73c11a85c6d6 252 _payloadLen -= dataLength + 2;
LancasterUniversity 1131:73c11a85c6d6 253
LancasterUniversity 1131:73c11a85c6d6 254 // add new field
LancasterUniversity 1131:73c11a85c6d6 255 result = appendField(advDataType, payload, len);
LancasterUniversity 1131:73c11a85c6d6 256 }
LancasterUniversity 1131:73c11a85c6d6 257 }
LancasterUniversity 1131:73c11a85c6d6 258
LancasterUniversity 1131:73c11a85c6d6 259 break;
LancasterUniversity 1131:73c11a85c6d6 260 }
LancasterUniversity 1131:73c11a85c6d6 261 // These fields will have the new data appended if there is sufficient space
LancasterUniversity 1131:73c11a85c6d6 262 case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 263 case COMPLETE_LIST_16BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 264 case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 265 case COMPLETE_LIST_32BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 266 case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 267 case COMPLETE_LIST_128BIT_SERVICE_IDS:
LancasterUniversity 1131:73c11a85c6d6 268 case LIST_128BIT_SOLICITATION_IDS: {
LancasterUniversity 1131:73c11a85c6d6 269 // check if data fits
LancasterUniversity 1131:73c11a85c6d6 270 if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
LancasterUniversity 1131:73c11a85c6d6 271 // make room for new field by moving the remainder of the
LancasterUniversity 1131:73c11a85c6d6 272 // advertisement payload "to the right" starting after the
LancasterUniversity 1131:73c11a85c6d6 273 // TYPE field.
LancasterUniversity 1131:73c11a85c6d6 274 uint8_t* end = &_payload[_payloadLen];
LancasterUniversity 1131:73c11a85c6d6 275
LancasterUniversity 1131:73c11a85c6d6 276 while (&field[1] < end) {
LancasterUniversity 1131:73c11a85c6d6 277 end[len] = *end;
LancasterUniversity 1131:73c11a85c6d6 278 end--;
LancasterUniversity 1131:73c11a85c6d6 279 }
LancasterUniversity 1131:73c11a85c6d6 280
LancasterUniversity 1131:73c11a85c6d6 281 // insert new data
LancasterUniversity 1131:73c11a85c6d6 282 for (uint8_t idx = 0; idx < len; idx++) {
LancasterUniversity 1131:73c11a85c6d6 283 field[2 + idx] = payload[idx];
LancasterUniversity 1131:73c11a85c6d6 284 }
LancasterUniversity 1131:73c11a85c6d6 285
LancasterUniversity 1131:73c11a85c6d6 286 // increment lengths
LancasterUniversity 1131:73c11a85c6d6 287 field[0] += len;
LancasterUniversity 1131:73c11a85c6d6 288 _payloadLen += len;
LancasterUniversity 1131:73c11a85c6d6 289
LancasterUniversity 1131:73c11a85c6d6 290 result = BLE_ERROR_NONE;
LancasterUniversity 1131:73c11a85c6d6 291 }
LancasterUniversity 1131:73c11a85c6d6 292
LancasterUniversity 1131:73c11a85c6d6 293 break;
LancasterUniversity 1131:73c11a85c6d6 294 }
LancasterUniversity 1131:73c11a85c6d6 295 // Field exists but updating it is not supported. Abort operation.
LancasterUniversity 1131:73c11a85c6d6 296 default:
LancasterUniversity 1131:73c11a85c6d6 297 result = BLE_ERROR_NOT_IMPLEMENTED;
LancasterUniversity 1131:73c11a85c6d6 298 break;
LancasterUniversity 1131:73c11a85c6d6 299 }
LancasterUniversity 1131:73c11a85c6d6 300 } else {
LancasterUniversity 1131:73c11a85c6d6 301 // field doesn't exists, insert new
LancasterUniversity 1131:73c11a85c6d6 302 result = appendField(advDataType, payload, len);
LancasterUniversity 1131:73c11a85c6d6 303 }
LancasterUniversity 1131:73c11a85c6d6 304
LancasterUniversity 1131:73c11a85c6d6 305 return result;
LancasterUniversity 1131:73c11a85c6d6 306 }
LancasterUniversity 1131:73c11a85c6d6 307
LancasterUniversity 1131:73c11a85c6d6 308 /**
LancasterUniversity 1131:73c11a85c6d6 309 * Update a particular ADV field in the advertising payload (based on
LancasterUniversity 1131:73c11a85c6d6 310 * matching type and length). Note: the length of the new data must be the
LancasterUniversity 1131:73c11a85c6d6 311 * same as the old one.
rgrover1 763:36c3e2b1f1ae 312 *
rgrover1 765:4cd91998cd48 313 * @param[in] advDataType The Advertising 'DataType' to add.
rgrover1 765:4cd91998cd48 314 * @param[in] payload Pointer to the payload contents.
rgrover1 765:4cd91998cd48 315 * @param[in] len Size of the payload in bytes.
rgrover1 763:36c3e2b1f1ae 316 *
LancasterUniversity 1131:73c11a85c6d6 317 * @return BLE_ERROR_UNSPECIFIED if the specified field is not found, else
LancasterUniversity 1131:73c11a85c6d6 318 * BLE_ERROR_NONE.
rgrover1 763:36c3e2b1f1ae 319 */
rgrover1 765:4cd91998cd48 320 ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
rgrover1 765:4cd91998cd48 321 {
LancasterUniversity 1131:73c11a85c6d6 322 if ((payload == NULL) || (len == 0)) {
LancasterUniversity 1131:73c11a85c6d6 323 return BLE_ERROR_INVALID_PARAM;
LancasterUniversity 1131:73c11a85c6d6 324 }
LancasterUniversity 1131:73c11a85c6d6 325
LancasterUniversity 1131:73c11a85c6d6 326 /* A local struct to describe an ADV field. This definition comes from the Bluetooth Core Spec. (v4.2) Part C, Section 11. */
LancasterUniversity 1131:73c11a85c6d6 327 struct ADVField_t {
LancasterUniversity 1131:73c11a85c6d6 328 uint8_t len; /* Describes the length (in bytes) of the following type and bytes. */
LancasterUniversity 1131:73c11a85c6d6 329 uint8_t type; /* Should have the same representation of DataType_t (above). */
LancasterUniversity 1131:73c11a85c6d6 330 uint8_t bytes[0]; /* A placeholder for variable length data. */
LancasterUniversity 1131:73c11a85c6d6 331 };
rgrover1 765:4cd91998cd48 332
LancasterUniversity 1131:73c11a85c6d6 333 /* Iterate over the adv fields looking for the first match. */
LancasterUniversity 1131:73c11a85c6d6 334 uint8_t byteIndex = 0;
LancasterUniversity 1131:73c11a85c6d6 335 while (byteIndex < _payloadLen) {
LancasterUniversity 1131:73c11a85c6d6 336 ADVField_t *currentADV = (ADVField_t *)&_payload[byteIndex];
LancasterUniversity 1131:73c11a85c6d6 337 if ((currentADV->len == (len + 1)) && /* Incoming len only describes the payload, whereas ADV->len describes [type + payload]. */
LancasterUniversity 1131:73c11a85c6d6 338 (currentADV->type == advDataType)) {
LancasterUniversity 1131:73c11a85c6d6 339 memcpy(currentADV->bytes, payload, len);
LancasterUniversity 1131:73c11a85c6d6 340 return BLE_ERROR_NONE;
LancasterUniversity 1131:73c11a85c6d6 341 }
LancasterUniversity 1131:73c11a85c6d6 342
LancasterUniversity 1131:73c11a85c6d6 343 byteIndex += (currentADV->len + 1); /* Advance by len+1; '+1' is needed to span the len field itself. */
rgrover1 763:36c3e2b1f1ae 344 }
LancasterUniversity 1131:73c11a85c6d6 345
LancasterUniversity 1131:73c11a85c6d6 346 return BLE_ERROR_UNSPECIFIED;
rgrover1 763:36c3e2b1f1ae 347 }
rgrover1 763:36c3e2b1f1ae 348
rgrover1 763:36c3e2b1f1ae 349 /**
vcoubard 1048:efb29faf12fc 350 * Helper function to add APPEARANCE data to the advertising payload.
rgrover1 710:b2e1a2660ec2 351 *
rgrover1 710:b2e1a2660ec2 352 * @param appearance
vcoubard 1048:efb29faf12fc 353 * The APPEARANCE value to add.
rgrover1 710:b2e1a2660ec2 354 *
rgrover1 710:b2e1a2660ec2 355 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 356 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 357 */
rgrover1 710:b2e1a2660ec2 358 ble_error_t addAppearance(Appearance appearance = GENERIC_TAG) {
rgrover1 710:b2e1a2660ec2 359 _appearance = appearance;
rgrover1 710:b2e1a2660ec2 360 return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
rgrover1 710:b2e1a2660ec2 361 }
rgrover1 710:b2e1a2660ec2 362
rgrover1 710:b2e1a2660ec2 363 /**
rgrover1 710:b2e1a2660ec2 364 * Helper function to add FLAGS data to the advertising payload.
rgrover1 710:b2e1a2660ec2 365 * @param flags
rgrover1 710:b2e1a2660ec2 366 * LE_LIMITED_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 367 * The peripheral is discoverable for a limited period of time.
rgrover1 710:b2e1a2660ec2 368 * LE_GENERAL_DISCOVERABLE
rgrover1 710:b2e1a2660ec2 369 * The peripheral is permanently discoverable.
rgrover1 710:b2e1a2660ec2 370 * BREDR_NOT_SUPPORTED
rgrover1 710:b2e1a2660ec2 371 * This peripheral is a Bluetooth Low Energy only device (no EDR support).
rgrover1 710:b2e1a2660ec2 372 *
rgrover1 710:b2e1a2660ec2 373 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 374 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 375 */
rgrover1 710:b2e1a2660ec2 376 ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE) {
rgrover1 710:b2e1a2660ec2 377 return addData(GapAdvertisingData::FLAGS, &flags, 1);
rgrover1 710:b2e1a2660ec2 378 }
rgrover1 710:b2e1a2660ec2 379
rgrover1 710:b2e1a2660ec2 380 /**
vcoubard 1048:efb29faf12fc 381 * Helper function to add TX_POWER_LEVEL data to the advertising payload.
rgrover1 710:b2e1a2660ec2 382 *
rgrover1 710:b2e1a2660ec2 383 * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
rgrover1 710:b2e1a2660ec2 384 * advertising buffer to overflow, else BLE_ERROR_NONE.
rgrover1 710:b2e1a2660ec2 385 */
rgrover1 710:b2e1a2660ec2 386 ble_error_t addTxPower(int8_t txPower) {
vcoubard 1048:efb29faf12fc 387 /* To Do: Basic error checking to make sure txPower is in range. */
rgrover1 710:b2e1a2660ec2 388 return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
rgrover1 710:b2e1a2660ec2 389 }
rgrover1 710:b2e1a2660ec2 390
rgrover1 710:b2e1a2660ec2 391 /**
vcoubard 1048:efb29faf12fc 392 * Clears the payload and resets the payload length counter.
rgrover1 710:b2e1a2660ec2 393 */
rgrover1 710:b2e1a2660ec2 394 void clear(void) {
rgrover1 710:b2e1a2660ec2 395 memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
rgrover1 710:b2e1a2660ec2 396 _payloadLen = 0;
rgrover1 710:b2e1a2660ec2 397 }
rgrover1 710:b2e1a2660ec2 398
rgrover1 710:b2e1a2660ec2 399 /**
vcoubard 1048:efb29faf12fc 400 * Returns a pointer to the current payload.
rgrover1 710:b2e1a2660ec2 401 */
rgrover1 710:b2e1a2660ec2 402 const uint8_t *getPayload(void) const {
rgrover1 769:2d236d9afa9e 403 return _payload;
rgrover1 710:b2e1a2660ec2 404 }
rgrover1 710:b2e1a2660ec2 405
rgrover1 710:b2e1a2660ec2 406 /**
vcoubard 1048:efb29faf12fc 407 * Returns the current payload length (0..31 bytes).
rgrover1 710:b2e1a2660ec2 408 */
rgrover1 710:b2e1a2660ec2 409 uint8_t getPayloadLen(void) const {
rgrover1 710:b2e1a2660ec2 410 return _payloadLen;
rgrover1 710:b2e1a2660ec2 411 }
rgrover1 710:b2e1a2660ec2 412
rgrover1 710:b2e1a2660ec2 413 /**
vcoubard 1048:efb29faf12fc 414 * Returns the 16-bit appearance value for this device.
rgrover1 710:b2e1a2660ec2 415 */
rgrover1 710:b2e1a2660ec2 416 uint16_t getAppearance(void) const {
rgrover1 710:b2e1a2660ec2 417 return (uint16_t)_appearance;
rgrover1 710:b2e1a2660ec2 418 }
rgrover1 710:b2e1a2660ec2 419
vcoubard 1052:b55e1ad3e1b3 420 /**
vcoubard 1052:b55e1ad3e1b3 421 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 422 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 423 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 424 */
vcoubard 1052:b55e1ad3e1b3 425 const uint8_t* findField(DataType_t type) const {
vcoubard 1052:b55e1ad3e1b3 426 return findField(type);
vcoubard 1052:b55e1ad3e1b3 427 }
vcoubard 1052:b55e1ad3e1b3 428
rgrover1 710:b2e1a2660ec2 429 private:
vcoubard 1052:b55e1ad3e1b3 430 /**
vcoubard 1052:b55e1ad3e1b3 431 * Append advertising data based on the specified AD type (see DataType)
vcoubard 1052:b55e1ad3e1b3 432 */
vcoubard 1052:b55e1ad3e1b3 433 ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
vcoubard 1052:b55e1ad3e1b3 434 {
vcoubard 1052:b55e1ad3e1b3 435 /* Make sure we don't exceed the 31 byte payload limit */
vcoubard 1052:b55e1ad3e1b3 436 if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
vcoubard 1052:b55e1ad3e1b3 437 return BLE_ERROR_BUFFER_OVERFLOW;
vcoubard 1052:b55e1ad3e1b3 438 }
vcoubard 1052:b55e1ad3e1b3 439
vcoubard 1052:b55e1ad3e1b3 440 /* Field length. */
vcoubard 1052:b55e1ad3e1b3 441 memset(&_payload[_payloadLen], len + 1, 1);
vcoubard 1052:b55e1ad3e1b3 442 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 443
vcoubard 1052:b55e1ad3e1b3 444 /* Field ID. */
vcoubard 1052:b55e1ad3e1b3 445 memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
vcoubard 1052:b55e1ad3e1b3 446 _payloadLen++;
vcoubard 1052:b55e1ad3e1b3 447
vcoubard 1052:b55e1ad3e1b3 448 /* Payload. */
vcoubard 1052:b55e1ad3e1b3 449 memcpy(&_payload[_payloadLen], payload, len);
vcoubard 1052:b55e1ad3e1b3 450 _payloadLen += len;
vcoubard 1052:b55e1ad3e1b3 451
vcoubard 1052:b55e1ad3e1b3 452 return BLE_ERROR_NONE;
vcoubard 1052:b55e1ad3e1b3 453 }
vcoubard 1052:b55e1ad3e1b3 454
vcoubard 1052:b55e1ad3e1b3 455 /**
vcoubard 1052:b55e1ad3e1b3 456 * Search advertisement data for field.
vcoubard 1052:b55e1ad3e1b3 457 * Returns pointer to the first element in the field if found, NULL otherwise.
vcoubard 1052:b55e1ad3e1b3 458 * Where the first element is the length of the field.
vcoubard 1052:b55e1ad3e1b3 459 */
vcoubard 1052:b55e1ad3e1b3 460 uint8_t* findField(DataType_t type) {
vcoubard 1052:b55e1ad3e1b3 461 // scan through advertisement data
vcoubard 1052:b55e1ad3e1b3 462 for (uint8_t idx = 0; idx < _payloadLen; ) {
vcoubard 1052:b55e1ad3e1b3 463 uint8_t fieldType = _payload[idx + 1];
vcoubard 1052:b55e1ad3e1b3 464
vcoubard 1052:b55e1ad3e1b3 465 if (fieldType == type) {
vcoubard 1052:b55e1ad3e1b3 466 return &_payload[idx];
vcoubard 1052:b55e1ad3e1b3 467 }
vcoubard 1052:b55e1ad3e1b3 468
vcoubard 1052:b55e1ad3e1b3 469 // advance to next field
vcoubard 1052:b55e1ad3e1b3 470 idx += _payload[idx] + 1;
vcoubard 1052:b55e1ad3e1b3 471 }
vcoubard 1052:b55e1ad3e1b3 472
vcoubard 1052:b55e1ad3e1b3 473 // field not found
vcoubard 1052:b55e1ad3e1b3 474 return NULL;
vcoubard 1052:b55e1ad3e1b3 475 }
vcoubard 1052:b55e1ad3e1b3 476
rgrover1 710:b2e1a2660ec2 477 uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
rgrover1 710:b2e1a2660ec2 478 uint8_t _payloadLen;
rgrover1 710:b2e1a2660ec2 479 uint16_t _appearance;
rgrover1 710:b2e1a2660ec2 480 };
rgrover1 710:b2e1a2660ec2 481
rgrover1 710:b2e1a2660ec2 482 #endif // ifndef __GAP_ADVERTISING_DATA_H__