mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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