abc

Fork of BLE_API by Bluetooth Low Energy

Committer:
Rohit Grover
Date:
Mon Sep 22 10:59:09 2014 +0100
Revision:
118:620d28e7a1ba
Child:
134:49321f76753e
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_UART_SERVICE_H__
Rohit Grover 118:620d28e7a1ba 18 #define __BLE_UART_SERVICE_H__
Rohit Grover 118:620d28e7a1ba 19
Rohit Grover 118:620d28e7a1ba 20 #include "Stream.h"
Rohit Grover 118:620d28e7a1ba 21
Rohit Grover 118:620d28e7a1ba 22 #include "UUID.h"
Rohit Grover 118:620d28e7a1ba 23 #include "BLEDevice.h"
Rohit Grover 118:620d28e7a1ba 24
Rohit Grover 118:620d28e7a1ba 25 extern const uint8_t UARTServiceBaseUUID[LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 26 extern const uint16_t UARTServiceShortUUID;
Rohit Grover 118:620d28e7a1ba 27 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
Rohit Grover 118:620d28e7a1ba 28 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
Rohit Grover 118:620d28e7a1ba 29
Rohit Grover 118:620d28e7a1ba 30 extern const uint8_t UARTServiceUUID[LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 31 extern const uint8_t UARTServiceUUID_reversed[LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 32
Rohit Grover 118:620d28e7a1ba 33 extern const uint8_t UARTServiceTXCharacteristicUUID[LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 34 extern const uint8_t UARTServiceRXCharacteristicUUID[LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 35
Rohit Grover 118:620d28e7a1ba 36 class UARTService : public Stream {
Rohit Grover 118:620d28e7a1ba 37 public:
Rohit Grover 118:620d28e7a1ba 38 /**< Maximum length of data (in bytes) that can be transmitted by the UART service module to the peer. */
Rohit Grover 118:620d28e7a1ba 39 static const unsigned GATT_MTU_SIZE_DEFAULT = 23;
Rohit Grover 118:620d28e7a1ba 40 static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (GATT_MTU_SIZE_DEFAULT - 3);
Rohit Grover 118:620d28e7a1ba 41
Rohit Grover 118:620d28e7a1ba 42 public:
Rohit Grover 118:620d28e7a1ba 43 UARTService(BLEDevice &_ble) :
Rohit Grover 118:620d28e7a1ba 44 Stream("blueart"),
Rohit Grover 118:620d28e7a1ba 45 ble(_ble),
Rohit Grover 118:620d28e7a1ba 46 receiveBuffer(),
Rohit Grover 118:620d28e7a1ba 47 sendBuffer(),
Rohit Grover 118:620d28e7a1ba 48 sendBufferIndex(0),
Rohit Grover 118:620d28e7a1ba 49 numBytesReceived(0),
Rohit Grover 118:620d28e7a1ba 50 receiveBufferIndex(0),
Rohit Grover 118:620d28e7a1ba 51 txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
Rohit Grover 118:620d28e7a1ba 52 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
Rohit Grover 118:620d28e7a1ba 53 rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
Rohit Grover 118:620d28e7a1ba 54 GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
Rohit Grover 118:620d28e7a1ba 55 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Rohit Grover 118:620d28e7a1ba 56
Rohit Grover 118:620d28e7a1ba 57 ble.addService(uartService);
Rohit Grover 118:620d28e7a1ba 58 ble.onDataWritten(this, &UARTService::onDataWritten);
Rohit Grover 118:620d28e7a1ba 59 }
Rohit Grover 118:620d28e7a1ba 60
Rohit Grover 118:620d28e7a1ba 61 /**
Rohit Grover 118:620d28e7a1ba 62 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
Rohit Grover 118:620d28e7a1ba 63 */
Rohit Grover 118:620d28e7a1ba 64 uint16_t getTXCharacteristicHandle() {
Rohit Grover 118:620d28e7a1ba 65 return txCharacteristic.getValueAttribute().getHandle();
Rohit Grover 118:620d28e7a1ba 66 }
Rohit Grover 118:620d28e7a1ba 67
Rohit Grover 118:620d28e7a1ba 68 /**
Rohit Grover 118:620d28e7a1ba 69 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
Rohit Grover 118:620d28e7a1ba 70 */
Rohit Grover 118:620d28e7a1ba 71 uint16_t getRXCharacteristicHandle() {
Rohit Grover 118:620d28e7a1ba 72 return rxCharacteristic.getValueAttribute().getHandle();
Rohit Grover 118:620d28e7a1ba 73 }
Rohit Grover 118:620d28e7a1ba 74
Rohit Grover 118:620d28e7a1ba 75 /**
Rohit Grover 118:620d28e7a1ba 76 * Following a call to this function, all writes to stdout (such as from
Rohit Grover 118:620d28e7a1ba 77 * printf) get redirected to the outbound characteristic of this service.
Rohit Grover 118:620d28e7a1ba 78 * This might be very useful when wanting to receive debug messages over BLE.
Rohit Grover 118:620d28e7a1ba 79 *
Rohit Grover 118:620d28e7a1ba 80 * @Note: debug messages originating from printf() like calls are buffered
Rohit Grover 118:620d28e7a1ba 81 * before being sent out. A '\n' in the printf() triggers the buffer update
Rohit Grover 118:620d28e7a1ba 82 * to the underlying characteristic.
Rohit Grover 118:620d28e7a1ba 83 *
Rohit Grover 118:620d28e7a1ba 84 * @Note: long messages need to be chopped up into 20-byte updates so that
Rohit Grover 118:620d28e7a1ba 85 * they flow out completely with notifications. The receiver should be
Rohit Grover 118:620d28e7a1ba 86 * prepared to stitch these messages back.
Rohit Grover 118:620d28e7a1ba 87 */
Rohit Grover 118:620d28e7a1ba 88 void retargetStdout() {
Rohit Grover 118:620d28e7a1ba 89 freopen("/blueart", "w", stdout);
Rohit Grover 118:620d28e7a1ba 90 }
Rohit Grover 118:620d28e7a1ba 91
Rohit Grover 118:620d28e7a1ba 92 /**
Rohit Grover 118:620d28e7a1ba 93 * This callback allows the UART service to receive updates to the
Rohit Grover 118:620d28e7a1ba 94 * txCharacteristic. The application should forward the call to this
Rohit Grover 118:620d28e7a1ba 95 * function from the global onDataWritten() callback handler; or if that's
Rohit Grover 118:620d28e7a1ba 96 * not used, this method can be used as a callback directly.
Rohit Grover 118:620d28e7a1ba 97 */
Rohit Grover 118:620d28e7a1ba 98 virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
Rohit Grover 118:620d28e7a1ba 99 if (params->charHandle == getTXCharacteristicHandle()) {
Rohit Grover 118:620d28e7a1ba 100 uint16_t bytesRead = params->len;
Rohit Grover 118:620d28e7a1ba 101 if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
Rohit Grover 118:620d28e7a1ba 102 numBytesReceived = bytesRead;
Rohit Grover 118:620d28e7a1ba 103 receiveBufferIndex = 0;
Rohit Grover 118:620d28e7a1ba 104 memcpy(receiveBuffer, params->data, numBytesReceived);
Rohit Grover 118:620d28e7a1ba 105 }
Rohit Grover 118:620d28e7a1ba 106 }
Rohit Grover 118:620d28e7a1ba 107 }
Rohit Grover 118:620d28e7a1ba 108
Rohit Grover 118:620d28e7a1ba 109 protected:
Rohit Grover 118:620d28e7a1ba 110 /**
Rohit Grover 118:620d28e7a1ba 111 * Override for Stream::write().
Rohit Grover 118:620d28e7a1ba 112 *
Rohit Grover 118:620d28e7a1ba 113 * We attempt to collect bytes before pushing them to the UART RX
Rohit Grover 118:620d28e7a1ba 114 * characteristic--writing to the RX characteristic will then generate
Rohit Grover 118:620d28e7a1ba 115 * notifications for the client. Updates made in quick succession to a
Rohit Grover 118:620d28e7a1ba 116 * notification-generating characteristic will result in data being buffered
Rohit Grover 118:620d28e7a1ba 117 * in the bluetooth stack as notifications are sent out. The stack will have
Rohit Grover 118:620d28e7a1ba 118 * its limits for this buffering; typically a small number under 10.
Rohit Grover 118:620d28e7a1ba 119 * Collecting data into the sendBuffer buffer helps mitigate the rate of
Rohit Grover 118:620d28e7a1ba 120 * updates. But we shouldn't buffer a large amount of data before updating
Rohit Grover 118:620d28e7a1ba 121 * the characteristic otherwise the client will need to turn around and make
Rohit Grover 118:620d28e7a1ba 122 * a long read request; this is because notifications include only the first
Rohit Grover 118:620d28e7a1ba 123 * 20 bytes of the updated data.
Rohit Grover 118:620d28e7a1ba 124 *
Rohit Grover 118:620d28e7a1ba 125 * @param buffer The received update
Rohit Grover 118:620d28e7a1ba 126 * @param length Amount of characters to be appended.
Rohit Grover 118:620d28e7a1ba 127 * @return Amount of characters appended to the rxCharacteristic.
Rohit Grover 118:620d28e7a1ba 128 */
Rohit Grover 118:620d28e7a1ba 129 virtual ssize_t write(const void* _buffer, size_t length) {
Rohit Grover 118:620d28e7a1ba 130 size_t origLength = length;
Rohit Grover 118:620d28e7a1ba 131 const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
Rohit Grover 118:620d28e7a1ba 132
Rohit Grover 118:620d28e7a1ba 133 if (ble.getGapState().connected) {
Rohit Grover 118:620d28e7a1ba 134 unsigned bufferIndex = 0;
Rohit Grover 118:620d28e7a1ba 135 while (length) {
Rohit Grover 118:620d28e7a1ba 136 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
Rohit Grover 118:620d28e7a1ba 137 unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
Rohit Grover 118:620d28e7a1ba 138
Rohit Grover 118:620d28e7a1ba 139 /* copy bytes into sendBuffer */
Rohit Grover 118:620d28e7a1ba 140 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
Rohit Grover 118:620d28e7a1ba 141 length -= bytesToCopy;
Rohit Grover 118:620d28e7a1ba 142 sendBufferIndex += bytesToCopy;
Rohit Grover 118:620d28e7a1ba 143 bufferIndex += bytesToCopy;
Rohit Grover 118:620d28e7a1ba 144
Rohit Grover 118:620d28e7a1ba 145 /* have we collected enough? */
Rohit Grover 118:620d28e7a1ba 146 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
Rohit Grover 118:620d28e7a1ba 147 // (sendBuffer[sendBufferIndex - 1] == '\r') ||
Rohit Grover 118:620d28e7a1ba 148 (sendBuffer[sendBufferIndex - 1] == '\n')) {
Rohit Grover 118:620d28e7a1ba 149 ble.updateCharacteristicValue(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
Rohit Grover 118:620d28e7a1ba 150 sendBufferIndex = 0;
Rohit Grover 118:620d28e7a1ba 151 }
Rohit Grover 118:620d28e7a1ba 152 }
Rohit Grover 118:620d28e7a1ba 153 }
Rohit Grover 118:620d28e7a1ba 154
Rohit Grover 118:620d28e7a1ba 155 return origLength;
Rohit Grover 118:620d28e7a1ba 156 }
Rohit Grover 118:620d28e7a1ba 157
Rohit Grover 118:620d28e7a1ba 158 /**
Rohit Grover 118:620d28e7a1ba 159 * Override for Stream::_putc()
Rohit Grover 118:620d28e7a1ba 160 * @param c
Rohit Grover 118:620d28e7a1ba 161 * This function writes the character c, cast to an unsigned char, to stream.
Rohit Grover 118:620d28e7a1ba 162 * @return
Rohit Grover 118:620d28e7a1ba 163 * The character written as an unsigned char cast to an int or EOF on error.
Rohit Grover 118:620d28e7a1ba 164 */
Rohit Grover 118:620d28e7a1ba 165 virtual int _putc(int c) {
Rohit Grover 118:620d28e7a1ba 166 return (write(&c, 1) == 1) ? 1 : EOF;
Rohit Grover 118:620d28e7a1ba 167 }
Rohit Grover 118:620d28e7a1ba 168
Rohit Grover 118:620d28e7a1ba 169 virtual int _getc() {
Rohit Grover 118:620d28e7a1ba 170 if (receiveBufferIndex == numBytesReceived) {
Rohit Grover 118:620d28e7a1ba 171 return EOF;
Rohit Grover 118:620d28e7a1ba 172 }
Rohit Grover 118:620d28e7a1ba 173
Rohit Grover 118:620d28e7a1ba 174 return receiveBuffer[receiveBufferIndex++];
Rohit Grover 118:620d28e7a1ba 175 }
Rohit Grover 118:620d28e7a1ba 176
Rohit Grover 118:620d28e7a1ba 177 virtual int isatty() {
Rohit Grover 118:620d28e7a1ba 178 return 1;
Rohit Grover 118:620d28e7a1ba 179 }
Rohit Grover 118:620d28e7a1ba 180
Rohit Grover 118:620d28e7a1ba 181 private:
Rohit Grover 118:620d28e7a1ba 182 BLEDevice &ble;
Rohit Grover 118:620d28e7a1ba 183
Rohit Grover 118:620d28e7a1ba 184 uint8_t receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
Rohit Grover 118:620d28e7a1ba 185 * inbound data before forwarding it to the
Rohit Grover 118:620d28e7a1ba 186 * application. */
Rohit Grover 118:620d28e7a1ba 187
Rohit Grover 118:620d28e7a1ba 188 uint8_t sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which outbound data is
Rohit Grover 118:620d28e7a1ba 189 * accumulated before being pushed to the
Rohit Grover 118:620d28e7a1ba 190 * rxCharacteristic. */
Rohit Grover 118:620d28e7a1ba 191 uint8_t sendBufferIndex;
Rohit Grover 118:620d28e7a1ba 192 uint8_t numBytesReceived;
Rohit Grover 118:620d28e7a1ba 193 uint8_t receiveBufferIndex;
Rohit Grover 118:620d28e7a1ba 194
Rohit Grover 118:620d28e7a1ba 195 GattCharacteristic txCharacteristic; /**< From the point of view of the external client, this is the characteristic
Rohit Grover 118:620d28e7a1ba 196 * they'd write into in order to communicate with this application. */
Rohit Grover 118:620d28e7a1ba 197 GattCharacteristic rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
Rohit Grover 118:620d28e7a1ba 198 * they'd read from in order to receive the bytes transmitted by this
Rohit Grover 118:620d28e7a1ba 199 * application. */
Rohit Grover 118:620d28e7a1ba 200 };
Rohit Grover 118:620d28e7a1ba 201
Rohit Grover 118:620d28e7a1ba 202 #endif /* #ifndef __BLE_UART_SERVICE_H__*/
Rohit Grover 118:620d28e7a1ba 203