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

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GapAdvertisingData.h Source File

GapAdvertisingData.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef __GAP_ADVERTISING_DATA_H__
00018 #define __GAP_ADVERTISING_DATA_H__
00019 
00020 #include <stdint.h>
00021 #include <string.h>
00022 
00023 #include "blecommon.h"
00024 
00025 #define GAP_ADVERTISING_DATA_MAX_PAYLOAD        (31)
00026 
00027 /**************************************************************************/
00028 /*!
00029     \brief
00030     This class provides several helper functions to generate properly
00031     formatted GAP Advertising and Scan Response data payloads.
00032 
00033     \note
00034     See Bluetooth Specification 4.0 (Vol. 3), Part C, Sections 11 and 18
00035     for further information on Advertising and Scan Response data.
00036 
00037     \par Advertising and Scan Response Payloads
00038     Advertising data and Scan Response data are organized around a set of
00039     data types called 'AD types' in Bluetooth 4.0 (see the Bluetooth Core
00040     Specification v4.0, Vol. 3, Part C, Sections 11 and 18).
00041 
00042     \par
00043     Each AD type has its own standardized assigned number, as defined
00044     by the Bluetooth SIG:
00045     https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
00046 
00047     \par
00048     For convenience, all appropriate AD types are encapsulated
00049     in GapAdvertisingData::DataType.
00050 
00051     \par
00052     Before the AD Types and their payload (if any) can be inserted into
00053     the Advertising or Scan Response frames, they need to be formatted as
00054     follows:
00055 
00056     \li \c Record length (1 byte).
00057     \li \c AD Type (1 byte).
00058     \li \c AD payload (optional; only present if record length > 1).
00059 
00060     \par
00061     This class takes care of properly formatting the payload, performs
00062     some basic checks on the payload length, and tries to avoid common
00063     errors like adding an exclusive AD field twice in the Advertising
00064     or Scan Response payload.
00065 
00066     \par EXAMPLE
00067 
00068     \code
00069 
00070     // ToDo
00071 
00072     \endcode
00073 */
00074 /**************************************************************************/
00075 class GapAdvertisingData
00076 {
00077 public:
00078     /**********************************************************************/
00079     /*!
00080         \brief
00081         A list of Advertising Data types commonly used by peripherals.
00082         These AD types are used to describe the capabilities of the
00083         peripheral, and are inserted inside the advertising or scan
00084         response payloads.
00085 
00086         \par Source
00087         \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18
00088         \li \c https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
00089     */
00090     /**********************************************************************/
00091     enum DataType_t {
00092         FLAGS                              = 0x01, /**< \ref *Flags */
00093         INCOMPLETE_LIST_16BIT_SERVICE_IDS  = 0x02, /**< Incomplete list of 16-bit Service IDs */
00094         COMPLETE_LIST_16BIT_SERVICE_IDS    = 0x03, /**< Complete list of 16-bit Service IDs */
00095         INCOMPLETE_LIST_32BIT_SERVICE_IDS  = 0x04, /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
00096         COMPLETE_LIST_32BIT_SERVICE_IDS    = 0x05, /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
00097         INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit Service IDs */
00098         COMPLETE_LIST_128BIT_SERVICE_IDS   = 0x07, /**< Complete list of 128-bit Service IDs */
00099         SHORTENED_LOCAL_NAME               = 0x08, /**< Shortened Local Name */
00100         COMPLETE_LOCAL_NAME                = 0x09, /**< Complete Local Name */
00101         TX_POWER_LEVEL                     = 0x0A, /**< TX Power Level (in dBm) */
00102         DEVICE_ID                          = 0x10, /**< Device ID */
00103         SLAVE_CONNECTION_INTERVAL_RANGE    = 0x12, /**< Slave Connection Interval Range */
00104         LIST_128BIT_SOLICITATION_IDS       = 0x15, /**< List of 128 bit service UUIDs the device is looking for */
00105         SERVICE_DATA                       = 0x16, /**< Service Data */
00106         APPEARANCE                         = 0x19, /**< \ref Appearance */
00107         ADVERTISING_INTERVAL               = 0x1A, /**< Advertising Interval */
00108         BLE_ADDRESS                        = 0x1B, /**< Bluetooth device address */
00109         MANUFACTURER_SPECIFIC_DATA         = 0xFF  /**< Manufacturer Specific Data */
00110     };
00111     typedef enum DataType_t DataType; /* Deprecated type alias. This may be dropped in a future release. */
00112 
00113     /**********************************************************************/
00114     /*!
00115         \brief
00116         A list of values for the FLAGS AD Type.
00117 
00118         \note
00119         You can use more than one value in the FLAGS AD Type (ex.
00120         LE_GENERAL_DISCOVERABLE and BREDR_NOT_SUPPORTED).
00121 
00122         \par Source
00123         \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1
00124     */
00125     /**********************************************************************/
00126     enum Flags_t {
00127         LE_LIMITED_DISCOVERABLE = 0x01, /**< *Peripheral device is discoverable for a limited period of time. */
00128         LE_GENERAL_DISCOVERABLE = 0x02, /**< Peripheral device is discoverable at any moment. */
00129         BREDR_NOT_SUPPORTED     = 0x04, /**< Peripheral device is LE only. */
00130         SIMULTANEOUS_LE_BREDR_C = 0x08, /**< Not relevant - central mode only. */
00131         SIMULTANEOUS_LE_BREDR_H = 0x10  /**< Not relevant - central mode only. */
00132     };
00133     typedef enum Flags_t Flags; /* Deprecated type alias. This may be dropped in a future release. */
00134 
00135     /**********************************************************************/
00136     /*!
00137         \brief
00138         A list of values for the APPEARANCE AD Type, which describes the
00139         physical shape or appearance of the device.
00140 
00141         \par Source
00142         \li \c Bluetooth Core Specification Supplement, Part A, Section 1.12
00143         \li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2
00144         \li \c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
00145     */
00146     /**********************************************************************/
00147     enum Appearance_t {
00148         UNKNOWN                                        = 0,     /**< Unknown or unspecified appearance type. */
00149         GENERIC_PHONE                                  = 64,    /**< Generic Phone. */
00150         GENERIC_COMPUTER                               = 128,   /**< Generic Computer. */
00151         GENERIC_WATCH                                  = 192,   /**< Generic Watch. */
00152         WATCH_SPORTS_WATCH                             = 193,   /**< Sports Watch. */
00153         GENERIC_CLOCK                                  = 256,   /**< Generic Clock. */
00154         GENERIC_DISPLAY                                = 320,   /**< Generic Display. */
00155         GENERIC_REMOTE_CONTROL                         = 384,   /**< Generic Remote Control. */
00156         GENERIC_EYE_GLASSES                            = 448,   /**< Generic Eye Glasses. */
00157         GENERIC_TAG                                    = 512,   /**< Generic Tag. */
00158         GENERIC_KEYRING                                = 576,   /**< Generic Keyring. */
00159         GENERIC_MEDIA_PLAYER                           = 640,   /**< Generic Media Player. */
00160         GENERIC_BARCODE_SCANNER                        = 704,   /**< Generic Barcode Scanner. */
00161         GENERIC_THERMOMETER                            = 768,   /**< Generic Thermometer. */
00162         THERMOMETER_EAR                                = 769,   /**< Ear Thermometer. */
00163         GENERIC_HEART_RATE_SENSOR                      = 832,   /**< Generic Heart Rate Sensor. */
00164         HEART_RATE_SENSOR_HEART_RATE_BELT              = 833,   /**< Belt Heart Rate Sensor. */
00165         GENERIC_BLOOD_PRESSURE                         = 896,   /**< Generic Blood Pressure. */
00166         BLOOD_PRESSURE_ARM                             = 897,   /**< Arm Blood Pressure. */
00167         BLOOD_PRESSURE_WRIST                           = 898,   /**< Wrist Blood Pressure. */
00168         HUMAN_INTERFACE_DEVICE_HID                     = 960,   /**< Human Interface Device (HID). */
00169         KEYBOARD                                       = 961,   /**< Keyboard. */
00170         MOUSE                                          = 962,   /**< Mouse. */
00171         JOYSTICK                                       = 963,   /**< Joystick. */
00172         GAMEPAD                                        = 964,   /**< Gamepad. */
00173         DIGITIZER_TABLET                               = 965,   /**< Digitizer Tablet. */
00174         CARD_READER                                    = 966,   /**< Card Reader. */
00175         DIGITAL_PEN                                    = 967,   /**< Digital Pen. */
00176         BARCODE_SCANNER                                = 968,   /**< Barcode Scanner. */
00177         GENERIC_GLUCOSE_METER                          = 1024,  /**< Generic Glucose Meter. */
00178         GENERIC_RUNNING_WALKING_SENSOR                 = 1088,  /**< Generic Running/Walking Sensor. */
00179         RUNNING_WALKING_SENSOR_IN_SHOE                 = 1089,  /**< In Shoe Running/Walking Sensor. */
00180         RUNNING_WALKING_SENSOR_ON_SHOE                 = 1090,  /**< On Shoe Running/Walking Sensor. */
00181         RUNNING_WALKING_SENSOR_ON_HIP                  = 1091,  /**< On Hip Running/Walking Sensor. */
00182         GENERIC_CYCLING                                = 1152,  /**< Generic Cycling. */
00183         CYCLING_CYCLING_COMPUTER                       = 1153,  /**< Cycling Computer. */
00184         CYCLING_SPEED_SENSOR                           = 1154,  /**< Cycling Speed Sensor. */
00185         CYCLING_CADENCE_SENSOR                         = 1155,  /**< Cycling Cadence Sensor. */
00186         CYCLING_POWER_SENSOR                           = 1156,  /**< Cycling Power Sensor. */
00187         CYCLING_SPEED_AND_CADENCE_SENSOR               = 1157,  /**< Cycling Speed and Cadence Sensor. */
00188         PULSE_OXIMETER_GENERIC                         = 3136,  /**< Generic Pulse Oximeter. */
00189         PULSE_OXIMETER_FINGERTIP                       = 3137,  /**< Fingertip Pulse Oximeter. */
00190         PULSE_OXIMETER_WRIST_WORN                      = 3138,  /**< Wrist Worn Pulse Oximeter. */
00191         GENERIC_WEIGHT_SCALE                           = 3200,  /**< Generic Weight Scale. */
00192         OUTDOOR_GENERIC                                = 5184,  /**< Generic Outdoor. */
00193         OUTDOOR_LOCATION_DISPLAY_DEVICE                = 5185,  /**< Outdoor Location Display Device. */
00194         OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186,  /**< Outdoor Location and Navigation Display Device. */
00195         OUTDOOR_LOCATION_POD                           = 5187,  /**< Outdoor Location Pod. */
00196         OUTDOOR_LOCATION_AND_NAVIGATION_POD            = 5188   /**< Outdoor Location and Navigation Pod. */
00197     };
00198     typedef enum Appearance_t Appearance; /* Deprecated type alias. This may be dropped in a future release. */
00199 
00200     GapAdvertisingData(void) : _payload(), _payloadLen(0), _appearance(GENERIC_TAG) {
00201         /* empty */
00202     }
00203 
00204     /**
00205      * Adds advertising data based on the specified AD type (see DataType).
00206      * If the supplied AD type is already present in the advertising
00207      * payload, then the value is updated.
00208      *
00209      * @param[in] advDataType  The Advertising 'DataType' to add.
00210      * @param[in] payload      Pointer to the payload contents.
00211      * @param[in] len          Size of the payload in bytes.
00212      *
00213      * @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
00214      *         advertising buffer to overflow. BLE_ERROR_NONE is returned
00215      *         on success.
00216      *
00217      * @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
00218      *       COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
00219      *       COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
00220      *       COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
00221      *       supplied value is appended to the values previously added to the
00222      *       payload.
00223      */
00224     ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
00225     {
00226         // find field
00227         uint8_t* field = findField(advDataType);
00228 
00229         if (field) {
00230             // Field type already exist, either add to field or replace
00231             return addField(advDataType, payload, len, field);
00232         } else {
00233             // field doesn't exists, insert new
00234             return appendField(advDataType, payload, len);
00235         }
00236     }
00237 
00238     /**
00239      * Update a particular ADV field in the advertising payload (based on
00240      * matching type).
00241      *
00242      * @param[in] advDataType  The Advertising 'DataType' to add.
00243      * @param[in] payload      Pointer to the payload contents.
00244      * @param[in] len          Size of the payload in bytes.
00245      *
00246      * @return BLE_ERROR_UNSPECIFIED if the specified field is not found,
00247      *         BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
00248      *         advertising buffer to overflow. BLE_ERROR_NONE is returned
00249      *         on success.
00250      */
00251     ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
00252     {
00253         // find field
00254         uint8_t* field = findField(advDataType);
00255 
00256         if (field) {
00257             // Field type already exist, replace field contents
00258             return updateField(advDataType, payload, len, field);
00259         } else {
00260             // field doesn't exists, return an error
00261             return BLE_ERROR_UNSPECIFIED;
00262         }
00263     }
00264 
00265     /**
00266      * Helper function to add APPEARANCE data to the advertising payload.
00267      *
00268      * @param  appearance
00269      *           The APPEARANCE value to add.
00270      *
00271      * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
00272      * advertising buffer to overflow, else BLE_ERROR_NONE.
00273      */
00274     ble_error_t addAppearance(Appearance appearance = GENERIC_TAG) {
00275         _appearance = appearance;
00276         return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
00277     }
00278 
00279     /**
00280      * Helper function to add FLAGS data to the advertising payload.
00281      * @param  flags
00282      *           LE_LIMITED_DISCOVERABLE
00283      *             The peripheral is discoverable for a limited period of time.
00284      *           LE_GENERAL_DISCOVERABLE
00285      *             The peripheral is permanently discoverable.
00286      *           BREDR_NOT_SUPPORTED
00287      *             This peripheral is a Bluetooth Low Energy only device (no EDR support).
00288      *
00289      * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
00290      * advertising buffer to overflow, else BLE_ERROR_NONE.
00291      */
00292     ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE) {
00293         return addData(GapAdvertisingData::FLAGS, &flags, 1);
00294     }
00295 
00296     /**
00297      * Helper function to add TX_POWER_LEVEL data to the advertising payload.
00298      *
00299      * @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
00300      * advertising buffer to overflow, else BLE_ERROR_NONE.
00301      */
00302     ble_error_t addTxPower(int8_t txPower) {
00303         /* To Do: Basic error checking to make sure txPower is in range. */
00304         return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
00305     }
00306 
00307     /**
00308      * Clears the payload and resets the payload length counter.
00309      */
00310     void        clear(void) {
00311         memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
00312         _payloadLen = 0;
00313     }
00314 
00315     /**
00316      * Returns a pointer to the current payload.
00317      */
00318     const uint8_t *getPayload(void) const {
00319         return _payload;
00320     }
00321 
00322     /**
00323      * Returns the current payload length (0..31 bytes).
00324      */
00325     uint8_t     getPayloadLen(void) const {
00326         return _payloadLen;
00327     }
00328 
00329     /**
00330      * Returns the 16-bit appearance value for this device.
00331      */
00332     uint16_t    getAppearance(void) const {
00333         return (uint16_t)_appearance;
00334     }
00335 
00336     /**
00337      * Search advertisement data for field.
00338      * Returns pointer to the first element in the field if found, NULL otherwise.
00339      * Where the first element is the length of the field.
00340      */
00341     const uint8_t* findField(DataType_t type) const {
00342         return findField(type);
00343     }
00344 
00345 private:
00346     /**
00347      * Append advertising data based on the specified AD type (see DataType)
00348      */
00349     ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
00350     {
00351         /* Make sure we don't exceed the 31 byte payload limit */
00352         if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
00353             return BLE_ERROR_BUFFER_OVERFLOW;
00354         }
00355 
00356         /* Field length. */
00357         memset(&_payload[_payloadLen], len + 1, 1);
00358         _payloadLen++;
00359 
00360         /* Field ID. */
00361         memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
00362         _payloadLen++;
00363 
00364         /* Payload. */
00365         memcpy(&_payload[_payloadLen], payload, len);
00366         _payloadLen += len;
00367 
00368         return BLE_ERROR_NONE;
00369     }
00370 
00371     /**
00372      * Search advertisement data for field.
00373      * Returns pointer to the first element in the field if found, NULL otherwise.
00374      * Where the first element is the length of the field.
00375      */
00376     uint8_t* findField(DataType_t type) {
00377         // scan through advertisement data
00378         for (uint8_t idx = 0; idx < _payloadLen; ) {
00379             uint8_t fieldType = _payload[idx + 1];
00380 
00381             if (fieldType == type) {
00382                 return &_payload[idx];
00383             }
00384 
00385             // advance to next field
00386             idx += _payload[idx] + 1;
00387         }
00388 
00389         // field not found
00390         return NULL;
00391     }
00392 
00393     /**
00394      * Given the a pointer to a field in the advertising payload it replaces
00395      * the existing data in the field with the supplied data.
00396      *
00397      * When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
00398      * COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
00399      * COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
00400      * COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
00401      * supplied value is appended to the values previously added to the
00402      * payload.
00403      *
00404      * Returns BLE_ERROR_NONE on success.
00405      */
00406     ble_error_t addField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
00407     {
00408         ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
00409 
00410         switch(advDataType) {
00411             // These fields will have the new data appended if there is sufficient space
00412             case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
00413             case COMPLETE_LIST_16BIT_SERVICE_IDS:
00414             case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
00415             case COMPLETE_LIST_32BIT_SERVICE_IDS:
00416             case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
00417             case COMPLETE_LIST_128BIT_SERVICE_IDS:
00418             case LIST_128BIT_SOLICITATION_IDS: {
00419                 // check if data fits
00420                 if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
00421                     // make room for new field by moving the remainder of the
00422                     // advertisement payload "to the right" starting after the
00423                     // TYPE field.
00424                     uint8_t* end = &_payload[_payloadLen];
00425 
00426                     while (&field[1] < end) {
00427                         end[len] = *end;
00428                         end--;
00429                     }
00430 
00431                     // insert new data
00432                     for (uint8_t idx = 0; idx < len; idx++) {
00433                         field[2 + idx] = payload[idx];
00434                     }
00435 
00436                     // increment lengths
00437                     field[0] += len;
00438                     _payloadLen += len;
00439 
00440                     result = BLE_ERROR_NONE;
00441                 }
00442 
00443                 break;
00444             }
00445             //  These fields will be overwritten with the new value
00446             default: {
00447                 result = updateField(advDataType, payload, len, field);
00448 
00449                 break;
00450             }
00451         }
00452 
00453         return result;
00454     }
00455 
00456     /**
00457      * Given the a pointer to a field in the advertising payload it replaces
00458      * the existing data in the field with the supplied data.
00459      * Returns BLE_ERROR_NONE on success.
00460      */
00461     ble_error_t updateField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
00462     {
00463         ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
00464         uint8_t dataLength = field[0] - 1;
00465 
00466         // new data has same length, do in-order replacement
00467         if (len == dataLength) {
00468             for (uint8_t idx = 0; idx < dataLength; idx++) {
00469                 field[2 + idx] = payload[idx];
00470             }
00471 
00472             result = BLE_ERROR_NONE;
00473         } else {
00474             // check if data fits
00475             if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
00476 
00477                 // remove old field
00478                 while ((field + dataLength + 2) < &_payload[_payloadLen]) {
00479                     *field = field[dataLength + 2];
00480                     field++;
00481                 }
00482 
00483                 // reduce length
00484                 _payloadLen -= dataLength + 2;
00485 
00486                 // add new field
00487                 result = appendField(advDataType, payload, len);
00488             }
00489         }
00490 
00491         return result;
00492     }
00493 
00494     uint8_t  _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
00495     uint8_t  _payloadLen;
00496     uint16_t _appearance;
00497 };
00498 
00499 #endif // ifndef __GAP_ADVERTISING_DATA_H__