Minor temporary patch to allow DFU packet callback

Fork of BLE_API by Bluetooth Low Energy

Committer:
Rohit Grover
Date:
Mon Sep 22 10:59:09 2014 +0100
Revision:
118:620d28e7a1ba
Child:
123:fede41ce9407
Release 0.2.0
=============

Highlights:
Introducing standard services to simplify applications.
Add support for over-the-air firmware updates.

Features
~~~~~~~~

- This release introduces 'templates' for common services such as heart-rate,
battery-level, device-info, UART, device-firmware-update etc. These services
take the shape of class declarations within header files aggregated under a
new folder called 'services/'. These service-classes provide a high-level
API hopefully easing the burden of developing BLE applications. The
underlying APIs to work with characteristics and services are still
available to allow greater control if needed. We expect to grow the
supported services to include all SIG defined BLE profiles.

- WriteCallbackParams now includes the characteristic's value-attribute
handle; this changes the signature of onDataWritten().

- BLEDevice::onDataWritten() now allows chaining of callbacks--this means that
it is possible to chain together multiple onDataWritten callbacks
(potentially from different modules of an application) to receive updates to
characteristics. Many services, such as DFU and UART add their own
onDataWritten callbacks behind the scenes to trap interesting events. It is
also possible to chain callbacks to functions within objects.

- Added the following expectation for GattCharacteristic: If valuePtr ==
NULL, initialLength == 0, and properties == READ for the value attribute of
a characteristic, then that particular characteristic may be considered
optional and dropped while instantiating the service with the underlying BLE
stack.

- Introducing the typedef GattAttribute::Handle_t to capture Attribute handles.

Bugfixes
~~~~~~~~

None.

Compatibility
~~~~~~~~~~~~~

The signature of onDataWritten() has seen a change; so application programs
using this new version of the BLE API will need minor modifications. Please
refer to sample programs under BLE team page.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Rohit Grover 118:620d28e7a1ba 1 /* mbed Microcontroller Library
Rohit Grover 118:620d28e7a1ba 2 * Copyright (c) 2006-2013 ARM Limited
Rohit Grover 118:620d28e7a1ba 3 *
Rohit Grover 118:620d28e7a1ba 4 * Licensed under the Apache License, Version 2.0 (the "License");
Rohit Grover 118:620d28e7a1ba 5 * you may not use this file except in compliance with the License.
Rohit Grover 118:620d28e7a1ba 6 * You may obtain a copy of the License at
Rohit Grover 118:620d28e7a1ba 7 *
Rohit Grover 118:620d28e7a1ba 8 * http://www.apache.org/licenses/LICENSE-2.0
Rohit Grover 118:620d28e7a1ba 9 *
Rohit Grover 118:620d28e7a1ba 10 * Unless required by applicable law or agreed to in writing, software
Rohit Grover 118:620d28e7a1ba 11 * distributed under the License is distributed on an "AS IS" BASIS,
Rohit Grover 118:620d28e7a1ba 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Rohit Grover 118:620d28e7a1ba 13 * See the License for the specific language governing permissions and
Rohit Grover 118:620d28e7a1ba 14 * limitations under the License.
Rohit Grover 118:620d28e7a1ba 15 */
Rohit Grover 118:620d28e7a1ba 16
Rohit Grover 118:620d28e7a1ba 17 #ifndef __BLE_HEART_RATE_SERVICE_H__
Rohit Grover 118:620d28e7a1ba 18 #define __BLE_HEART_RATE_SERVICE_H__
Rohit Grover 118:620d28e7a1ba 19
Rohit Grover 118:620d28e7a1ba 20 #include "BLEDevice.h"
Rohit Grover 118:620d28e7a1ba 21
Rohit Grover 118:620d28e7a1ba 22 /* Heart Rate Service */
Rohit Grover 118:620d28e7a1ba 23 /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml */
Rohit Grover 118:620d28e7a1ba 24 /* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
Rohit Grover 118:620d28e7a1ba 25 /* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml */
Rohit Grover 118:620d28e7a1ba 26 class HeartRateService {
Rohit Grover 118:620d28e7a1ba 27 public:
Rohit Grover 118:620d28e7a1ba 28 enum {
Rohit Grover 118:620d28e7a1ba 29 LOCATION_OTHER = 0,
Rohit Grover 118:620d28e7a1ba 30 LOCATION_CHEST,
Rohit Grover 118:620d28e7a1ba 31 LOCATION_WRIST,
Rohit Grover 118:620d28e7a1ba 32 LOCATION_FINGER,
Rohit Grover 118:620d28e7a1ba 33 LOCATION_HAND,
Rohit Grover 118:620d28e7a1ba 34 LOCATION_EAR_LOBE,
Rohit Grover 118:620d28e7a1ba 35 LOCATION_FOOT,
Rohit Grover 118:620d28e7a1ba 36 };
Rohit Grover 118:620d28e7a1ba 37
Rohit Grover 118:620d28e7a1ba 38 public:
Rohit Grover 118:620d28e7a1ba 39 /**
Rohit Grover 118:620d28e7a1ba 40 * Constructor.
Rohit Grover 118:620d28e7a1ba 41 *
Rohit Grover 118:620d28e7a1ba 42 * param[in] _ble
Rohit Grover 118:620d28e7a1ba 43 * Reference to the underlying BLEDevice.
Rohit Grover 118:620d28e7a1ba 44 * param[in] hrmCounter (8-bit)
Rohit Grover 118:620d28e7a1ba 45 * initial value for the hrm counter.
Rohit Grover 118:620d28e7a1ba 46 * param[in] location
Rohit Grover 118:620d28e7a1ba 47 * Sensor's location.
Rohit Grover 118:620d28e7a1ba 48 */
Rohit Grover 118:620d28e7a1ba 49 HeartRateService(BLEDevice &_ble, uint8_t hrmCounter, uint8_t location) :
Rohit Grover 118:620d28e7a1ba 50 ble(_ble),
Rohit Grover 118:620d28e7a1ba 51 valueBytes(hrmCounter),
Rohit Grover 118:620d28e7a1ba 52 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
Rohit Grover 118:620d28e7a1ba 53 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
Rohit Grover 118:620d28e7a1ba 54 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
Rohit Grover 118:620d28e7a1ba 55 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, (uint8_t *)&location, sizeof(location), sizeof(location),
Rohit Grover 118:620d28e7a1ba 56 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
Rohit Grover 118:620d28e7a1ba 57 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, (uint8_t *)&controlPointValue,
Rohit Grover 118:620d28e7a1ba 58 sizeof(controlPointValue), sizeof(controlPointValue), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) {
Rohit Grover 118:620d28e7a1ba 59 setupService();
Rohit Grover 118:620d28e7a1ba 60 }
Rohit Grover 118:620d28e7a1ba 61
Rohit Grover 118:620d28e7a1ba 62 /**
Rohit Grover 118:620d28e7a1ba 63 * Same constructor as above, but with a 16-bit HRM Counter value.
Rohit Grover 118:620d28e7a1ba 64 */
Rohit Grover 118:620d28e7a1ba 65 HeartRateService(BLEDevice &_ble, uint16_t hrmCounter, uint8_t location) :
Rohit Grover 118:620d28e7a1ba 66 ble(_ble),
Rohit Grover 118:620d28e7a1ba 67 valueBytes(hrmCounter),
Rohit Grover 118:620d28e7a1ba 68 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
Rohit Grover 118:620d28e7a1ba 69 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
Rohit Grover 118:620d28e7a1ba 70 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
Rohit Grover 118:620d28e7a1ba 71 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, (uint8_t *)&location, sizeof(location), sizeof(location),
Rohit Grover 118:620d28e7a1ba 72 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
Rohit Grover 118:620d28e7a1ba 73 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, (uint8_t *)&controlPointValue,
Rohit Grover 118:620d28e7a1ba 74 sizeof(controlPointValue), sizeof(controlPointValue), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) {
Rohit Grover 118:620d28e7a1ba 75 setupService();
Rohit Grover 118:620d28e7a1ba 76 }
Rohit Grover 118:620d28e7a1ba 77
Rohit Grover 118:620d28e7a1ba 78 /**
Rohit Grover 118:620d28e7a1ba 79 * Set a new 8-bit value for heart rate.
Rohit Grover 118:620d28e7a1ba 80 */
Rohit Grover 118:620d28e7a1ba 81 void updateHeartRate(uint8_t hrmCounter) {
Rohit Grover 118:620d28e7a1ba 82 valueBytes.updateHeartRate(hrmCounter);
Rohit Grover 118:620d28e7a1ba 83 ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
Rohit Grover 118:620d28e7a1ba 84 }
Rohit Grover 118:620d28e7a1ba 85
Rohit Grover 118:620d28e7a1ba 86 /**
Rohit Grover 118:620d28e7a1ba 87 * Set a new 16-bit value for heart rate.
Rohit Grover 118:620d28e7a1ba 88 */
Rohit Grover 118:620d28e7a1ba 89 void updateHeartRate(uint16_t hrmCounter) {
Rohit Grover 118:620d28e7a1ba 90 valueBytes.updateHeartRate(hrmCounter);
Rohit Grover 118:620d28e7a1ba 91 ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
Rohit Grover 118:620d28e7a1ba 92 }
Rohit Grover 118:620d28e7a1ba 93
Rohit Grover 118:620d28e7a1ba 94 /**
Rohit Grover 118:620d28e7a1ba 95 * This callback allows the UART service to receive updates to the
Rohit Grover 118:620d28e7a1ba 96 * txCharacteristic. The application should forward the call to this
Rohit Grover 118:620d28e7a1ba 97 * function from the global onDataWritten() callback handler; or if that's
Rohit Grover 118:620d28e7a1ba 98 * not used, this method can be used as a callback directly.
Rohit Grover 118:620d28e7a1ba 99 */
Rohit Grover 118:620d28e7a1ba 100 virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
Rohit Grover 118:620d28e7a1ba 101 if (params->charHandle == controlPoint.getValueAttribute().getHandle()) {
Rohit Grover 118:620d28e7a1ba 102 /* Do something here if the new value is 1; else you can override this method by
Rohit Grover 118:620d28e7a1ba 103 * extending this class.
Rohit Grover 118:620d28e7a1ba 104 * @NOTE: if you are extending this class, be sure to also call
Rohit Grover 118:620d28e7a1ba 105 * ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
Rohit Grover 118:620d28e7a1ba 106 * your constructor.
Rohit Grover 118:620d28e7a1ba 107 */
Rohit Grover 118:620d28e7a1ba 108 }
Rohit Grover 118:620d28e7a1ba 109 }
Rohit Grover 118:620d28e7a1ba 110
Rohit Grover 118:620d28e7a1ba 111 private:
Rohit Grover 118:620d28e7a1ba 112 void setupService(void) {
Rohit Grover 118:620d28e7a1ba 113 static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
Rohit Grover 118:620d28e7a1ba 114 if (serviceAdded) {
Rohit Grover 118:620d28e7a1ba 115 return;
Rohit Grover 118:620d28e7a1ba 116 }
Rohit Grover 118:620d28e7a1ba 117
Rohit Grover 118:620d28e7a1ba 118 GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint};
Rohit Grover 118:620d28e7a1ba 119 GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Rohit Grover 118:620d28e7a1ba 120
Rohit Grover 118:620d28e7a1ba 121 ble.addService(hrmService);
Rohit Grover 118:620d28e7a1ba 122 serviceAdded = true;
Rohit Grover 118:620d28e7a1ba 123
Rohit Grover 118:620d28e7a1ba 124 ble.onDataWritten(this, &HeartRateService::onDataWritten);
Rohit Grover 118:620d28e7a1ba 125 }
Rohit Grover 118:620d28e7a1ba 126
Rohit Grover 118:620d28e7a1ba 127 private:
Rohit Grover 118:620d28e7a1ba 128 /* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
Rohit Grover 118:620d28e7a1ba 129 struct HeartRateValueBytes {
Rohit Grover 118:620d28e7a1ba 130 static const unsigned MAX_VALUE_BYTES = 3; /* FLAGS + up to two bytes for heart-rate */
Rohit Grover 118:620d28e7a1ba 131 static const unsigned FLAGS_BYTE_INDEX = 0;
Rohit Grover 118:620d28e7a1ba 132
Rohit Grover 118:620d28e7a1ba 133 static const unsigned VALUE_FORMAT_BITNUM = 0;
Rohit Grover 118:620d28e7a1ba 134 static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
Rohit Grover 118:620d28e7a1ba 135
Rohit Grover 118:620d28e7a1ba 136 HeartRateValueBytes(uint8_t hrmCounter) : valueBytes() {
Rohit Grover 118:620d28e7a1ba 137 updateHeartRate(hrmCounter);
Rohit Grover 118:620d28e7a1ba 138 }
Rohit Grover 118:620d28e7a1ba 139
Rohit Grover 118:620d28e7a1ba 140 HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
Rohit Grover 118:620d28e7a1ba 141 updateHeartRate(hrmCounter);
Rohit Grover 118:620d28e7a1ba 142 }
Rohit Grover 118:620d28e7a1ba 143
Rohit Grover 118:620d28e7a1ba 144 void updateHeartRate(uint8_t hrmCounter) {
Rohit Grover 118:620d28e7a1ba 145 valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
Rohit Grover 118:620d28e7a1ba 146 valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
Rohit Grover 118:620d28e7a1ba 147 }
Rohit Grover 118:620d28e7a1ba 148
Rohit Grover 118:620d28e7a1ba 149 void updateHeartRate(uint16_t hrmCounter) {
Rohit Grover 118:620d28e7a1ba 150 valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
Rohit Grover 118:620d28e7a1ba 151 valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
Rohit Grover 118:620d28e7a1ba 152 valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
Rohit Grover 118:620d28e7a1ba 153 }
Rohit Grover 118:620d28e7a1ba 154
Rohit Grover 118:620d28e7a1ba 155 uint8_t *getPointer(void) {
Rohit Grover 118:620d28e7a1ba 156 return valueBytes;
Rohit Grover 118:620d28e7a1ba 157 }
Rohit Grover 118:620d28e7a1ba 158
Rohit Grover 118:620d28e7a1ba 159 const uint8_t *getPointer(void) const {
Rohit Grover 118:620d28e7a1ba 160 return valueBytes;
Rohit Grover 118:620d28e7a1ba 161 }
Rohit Grover 118:620d28e7a1ba 162
Rohit Grover 118:620d28e7a1ba 163 unsigned getNumValueBytes(void) const {
Rohit Grover 118:620d28e7a1ba 164 return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t));
Rohit Grover 118:620d28e7a1ba 165 }
Rohit Grover 118:620d28e7a1ba 166
Rohit Grover 118:620d28e7a1ba 167 private:
Rohit Grover 118:620d28e7a1ba 168 /* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
Rohit Grover 118:620d28e7a1ba 169 /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
Rohit Grover 118:620d28e7a1ba 170 uint8_t valueBytes[MAX_VALUE_BYTES];
Rohit Grover 118:620d28e7a1ba 171 };
Rohit Grover 118:620d28e7a1ba 172
Rohit Grover 118:620d28e7a1ba 173 private:
Rohit Grover 118:620d28e7a1ba 174 BLEDevice &ble;
Rohit Grover 118:620d28e7a1ba 175 HeartRateValueBytes valueBytes;
Rohit Grover 118:620d28e7a1ba 176 uint8_t controlPointValue;
Rohit Grover 118:620d28e7a1ba 177 GattCharacteristic hrmRate;
Rohit Grover 118:620d28e7a1ba 178 GattCharacteristic hrmLocation;
Rohit Grover 118:620d28e7a1ba 179 GattCharacteristic controlPoint;
Rohit Grover 118:620d28e7a1ba 180 };
Rohit Grover 118:620d28e7a1ba 181
Rohit Grover 118:620d28e7a1ba 182 #endif /* #ifndef __BLE_HEART_RATE_SERVICE_H__*/