High level Bluetooth Low Energy API and radio abstraction layer

Dependencies:   nRF51822

Dependents:   LinkNode_LIS3DH

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Thu Jul 02 09:06:11 2015 +0100
Revision:
716:11b41f651697
Parent:
712:b04b5db36865
Child:
717:3129b149a6b2
Synchronized with git rev d80fec88
Author: Rohit Grover
Release 0.4.0
=============

This is a major release which introduces the GATT Client functionality. It
also aligns BLE_API with builds using our new package manager: yotta
(https://github.com/armmbed/yotta).

Many APIs have seen some redesign. We encourage our users to pay attention to
the changes and migrate appropriately over time. We've also taken care to
ensure that existing code continues to work the same way. There's more
documentation in the form of comment headers for APIs to explain proper usage;
in many cases comment headers suggest alternative use of APIs.

Enhancements
~~~~~~~~~~~~

* Introduce GattClient. This includes functionality for service-discovery,
connections, and attribute-reads and writes. You'll find a demo program for
LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
the GATT client functionality hasn't been implemented yet, but the APIs have
been added.

* Most APIs in the abstract base classes like Gap and GattServer return
BLE_ERROR_NOT_IMPLEMENTED. Previously many APIs were pure-virtual, which did
not permit partial ports to compile.

* We've added a new abstract base class for SecurityManager. All security
related APIs have been moved into that.

* BLEDevice has been renamed as BLE. A deprecated alias for BLEDevice is
available to support existing code.

* There has been a major cleanup of APIs under BLE. APIs have now been
categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
There are accessors to get references for Gap, GattServer, GattClient, and
SecurityManager. A former call to ble.setAddress(...) is now expected to be
achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
some point to support controllers where a commit point was needed to
indicate when the application had finished constructing the GATT database.
This API would get called internally before Gap::startAdvertising(). We now
expect the underlying port to do the equivalent of initializeGattDatabase()
implicitly upon Gap::startAdvertising().

* The callback for BLE.onTimeout() now receives a TimeoutSource_t to indicate
the cause of the timeout. This is perhaps the only breaking API change. We
expect it to have very little disruptive effect.

* We've added a version of Gap::disconnect() which takes a connection handle.
The previous API (which did not take a connection handle) has been
deprecated; it will still work for situations where there's only a single
active connection. We hold on to that API to allow existing code to migrate
to the new API.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 712:b04b5db36865 1 /* mbed Microcontroller Library
rgrover1 712:b04b5db36865 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 712:b04b5db36865 3 *
rgrover1 712:b04b5db36865 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 712:b04b5db36865 5 * you may not use this file except in compliance with the License.
rgrover1 712:b04b5db36865 6 * You may obtain a copy of the License at
rgrover1 712:b04b5db36865 7 *
rgrover1 712:b04b5db36865 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 712:b04b5db36865 9 *
rgrover1 712:b04b5db36865 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 712:b04b5db36865 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 712:b04b5db36865 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 712:b04b5db36865 13 * See the License for the specific language governing permissions and
rgrover1 712:b04b5db36865 14 * limitations under the License.
rgrover1 712:b04b5db36865 15 */
rgrover1 712:b04b5db36865 16
rgrover1 712:b04b5db36865 17 #ifndef __BLE_UART_SERVICE_H__
rgrover1 712:b04b5db36865 18 #define __BLE_UART_SERVICE_H__
rgrover1 712:b04b5db36865 19
rgrover1 712:b04b5db36865 20 #include "mbed.h"
rgrover1 712:b04b5db36865 21 #include "Stream.h"
rgrover1 712:b04b5db36865 22
rgrover1 712:b04b5db36865 23 #include "ble/UUID.h"
rgrover1 712:b04b5db36865 24 #include "ble/BLE.h"
rgrover1 712:b04b5db36865 25
rgrover1 712:b04b5db36865 26 extern const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 712:b04b5db36865 27 extern const uint16_t UARTServiceShortUUID;
rgrover1 712:b04b5db36865 28 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
rgrover1 712:b04b5db36865 29 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
rgrover1 712:b04b5db36865 30
rgrover1 712:b04b5db36865 31 extern const uint8_t UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 712:b04b5db36865 32 extern const uint8_t UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID];
rgrover1 712:b04b5db36865 33
rgrover1 712:b04b5db36865 34 extern const uint8_t UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 712:b04b5db36865 35 extern const uint8_t UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 712:b04b5db36865 36
rgrover1 712:b04b5db36865 37 /**
rgrover1 712:b04b5db36865 38 * @class UARTService
rgrover1 712:b04b5db36865 39 * @brief BLE Service to enable UART over BLE
rgrover1 712:b04b5db36865 40 */
rgrover1 712:b04b5db36865 41 class UARTService {
rgrover1 712:b04b5db36865 42 public:
rgrover1 712:b04b5db36865 43 /**< Maximum length of data (in bytes) that can be transmitted by the UART service module to the peer. */
rgrover1 712:b04b5db36865 44 static const unsigned GATT_MTU_SIZE_DEFAULT = 23;
rgrover1 712:b04b5db36865 45 static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (GATT_MTU_SIZE_DEFAULT - 3);
rgrover1 712:b04b5db36865 46
rgrover1 712:b04b5db36865 47 public:
rgrover1 712:b04b5db36865 48
rgrover1 712:b04b5db36865 49 /**
rgrover1 712:b04b5db36865 50 * @param[ref] ble
rgrover1 712:b04b5db36865 51 * BLE object for the underlying controller.
rgrover1 712:b04b5db36865 52 */
rgrover1 712:b04b5db36865 53 UARTService(BLE &_ble) :
rgrover1 712:b04b5db36865 54 ble(_ble),
rgrover1 712:b04b5db36865 55 receiveBuffer(),
rgrover1 712:b04b5db36865 56 sendBuffer(),
rgrover1 712:b04b5db36865 57 sendBufferIndex(0),
rgrover1 712:b04b5db36865 58 numBytesReceived(0),
rgrover1 712:b04b5db36865 59 receiveBufferIndex(0),
rgrover1 712:b04b5db36865 60 txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
rgrover1 712:b04b5db36865 61 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
rgrover1 712:b04b5db36865 62 rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
rgrover1 712:b04b5db36865 63 GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
rgrover1 712:b04b5db36865 64 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
rgrover1 712:b04b5db36865 65
rgrover1 712:b04b5db36865 66 ble.addService(uartService);
rgrover1 712:b04b5db36865 67 ble.onDataWritten(this, &UARTService::onDataWritten);
rgrover1 712:b04b5db36865 68 }
rgrover1 712:b04b5db36865 69
rgrover1 712:b04b5db36865 70 /**
rgrover1 712:b04b5db36865 71 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
rgrover1 712:b04b5db36865 72 */
rgrover1 712:b04b5db36865 73 uint16_t getTXCharacteristicHandle() {
rgrover1 712:b04b5db36865 74 return txCharacteristic.getValueAttribute().getHandle();
rgrover1 712:b04b5db36865 75 }
rgrover1 712:b04b5db36865 76
rgrover1 712:b04b5db36865 77 /**
rgrover1 712:b04b5db36865 78 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
rgrover1 712:b04b5db36865 79 */
rgrover1 712:b04b5db36865 80 uint16_t getRXCharacteristicHandle() {
rgrover1 712:b04b5db36865 81 return rxCharacteristic.getValueAttribute().getHandle();
rgrover1 712:b04b5db36865 82 }
rgrover1 712:b04b5db36865 83
rgrover1 712:b04b5db36865 84 /**
rgrover1 712:b04b5db36865 85 * We attempt to collect bytes before pushing them to the UART RX
rgrover1 712:b04b5db36865 86 * characteristic--writing to the RX characteristic will then generate
rgrover1 712:b04b5db36865 87 * notifications for the client. Updates made in quick succession to a
rgrover1 712:b04b5db36865 88 * notification-generating characteristic will result in data being buffered
rgrover1 712:b04b5db36865 89 * in the bluetooth stack as notifications are sent out. The stack will have
rgrover1 712:b04b5db36865 90 * its limits for this buffering; typically a small number under 10.
rgrover1 712:b04b5db36865 91 * Collecting data into the sendBuffer buffer helps mitigate the rate of
rgrover1 712:b04b5db36865 92 * updates. But we shouldn't buffer a large amount of data before updating
rgrover1 712:b04b5db36865 93 * the characteristic otherwise the client will need to turn around and make
rgrover1 712:b04b5db36865 94 * a long read request; this is because notifications include only the first
rgrover1 712:b04b5db36865 95 * 20 bytes of the updated data.
rgrover1 712:b04b5db36865 96 *
rgrover1 712:b04b5db36865 97 * @param buffer The received update
rgrover1 712:b04b5db36865 98 * @param length Amount of characters to be appended.
rgrover1 712:b04b5db36865 99 * @return Amount of characters appended to the rxCharacteristic.
rgrover1 712:b04b5db36865 100 */
rgrover1 712:b04b5db36865 101 size_t write(const void *_buffer, size_t length) {
rgrover1 712:b04b5db36865 102 size_t origLength = length;
rgrover1 712:b04b5db36865 103 const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
rgrover1 712:b04b5db36865 104
rgrover1 712:b04b5db36865 105 if (ble.getGapState().connected) {
rgrover1 712:b04b5db36865 106 unsigned bufferIndex = 0;
rgrover1 712:b04b5db36865 107 while (length) {
rgrover1 712:b04b5db36865 108 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
rgrover1 712:b04b5db36865 109 unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
rgrover1 712:b04b5db36865 110
rgrover1 712:b04b5db36865 111 /* copy bytes into sendBuffer */
rgrover1 712:b04b5db36865 112 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
rgrover1 712:b04b5db36865 113 length -= bytesToCopy;
rgrover1 712:b04b5db36865 114 sendBufferIndex += bytesToCopy;
rgrover1 712:b04b5db36865 115 bufferIndex += bytesToCopy;
rgrover1 712:b04b5db36865 116
rgrover1 712:b04b5db36865 117 /* have we collected enough? */
rgrover1 712:b04b5db36865 118 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
rgrover1 712:b04b5db36865 119 // (sendBuffer[sendBufferIndex - 1] == '\r') ||
rgrover1 712:b04b5db36865 120 (sendBuffer[sendBufferIndex - 1] == '\n')) {
rgrover1 712:b04b5db36865 121 ble.updateCharacteristicValue(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
rgrover1 712:b04b5db36865 122 sendBufferIndex = 0;
rgrover1 712:b04b5db36865 123 }
rgrover1 712:b04b5db36865 124 }
rgrover1 712:b04b5db36865 125 }
rgrover1 712:b04b5db36865 126
rgrover1 712:b04b5db36865 127 return origLength;
rgrover1 712:b04b5db36865 128 }
rgrover1 712:b04b5db36865 129
rgrover1 712:b04b5db36865 130 /**
rgrover1 712:b04b5db36865 131 * Helper function to write out strings.
rgrover1 712:b04b5db36865 132 * @param str The received string.
rgrover1 712:b04b5db36865 133 * @return Amount of characters appended to the rxCharacteristic.
rgrover1 712:b04b5db36865 134 */
rgrover1 712:b04b5db36865 135 size_t writeString(const char *str) {
rgrover1 712:b04b5db36865 136 return write(str, strlen(str));
rgrover1 712:b04b5db36865 137 }
rgrover1 712:b04b5db36865 138
rgrover1 712:b04b5db36865 139 /**
rgrover1 712:b04b5db36865 140 * Override for Stream::_putc()
rgrover1 712:b04b5db36865 141 * @param c
rgrover1 712:b04b5db36865 142 * This function writes the character c, cast to an unsigned char, to stream.
rgrover1 712:b04b5db36865 143 * @return
rgrover1 712:b04b5db36865 144 * The character written as an unsigned char cast to an int or EOF on error.
rgrover1 712:b04b5db36865 145 */
rgrover1 712:b04b5db36865 146 int _putc(int c) {
rgrover1 712:b04b5db36865 147 return (write(&c, 1) == 1) ? 1 : EOF;
rgrover1 712:b04b5db36865 148 }
rgrover1 712:b04b5db36865 149
rgrover1 712:b04b5db36865 150 /**
rgrover1 712:b04b5db36865 151 * Override for Stream::_getc()
rgrover1 712:b04b5db36865 152 * @return
rgrover1 712:b04b5db36865 153 * The character read.
rgrover1 712:b04b5db36865 154 */
rgrover1 712:b04b5db36865 155 int _getc() {
rgrover1 712:b04b5db36865 156 if (receiveBufferIndex == numBytesReceived) {
rgrover1 712:b04b5db36865 157 return EOF;
rgrover1 712:b04b5db36865 158 }
rgrover1 712:b04b5db36865 159
rgrover1 712:b04b5db36865 160 return receiveBuffer[receiveBufferIndex++];
rgrover1 712:b04b5db36865 161 }
rgrover1 712:b04b5db36865 162
rgrover1 712:b04b5db36865 163 private:
rgrover1 712:b04b5db36865 164 /**
rgrover1 712:b04b5db36865 165 * This callback allows the UART service to receive updates to the
rgrover1 712:b04b5db36865 166 * txCharacteristic. The application should forward the call to this
rgrover1 712:b04b5db36865 167 * function from the global onDataWritten() callback handler; or if that's
rgrover1 712:b04b5db36865 168 * not used, this method can be used as a callback directly.
rgrover1 712:b04b5db36865 169 */
rgrover1 712:b04b5db36865 170 void onDataWritten(const GattWriteCallbackParams *params) {
rgrover1 712:b04b5db36865 171 if (params->handle == getTXCharacteristicHandle()) {
rgrover1 712:b04b5db36865 172 uint16_t bytesRead = params->len;
rgrover1 712:b04b5db36865 173 if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
rgrover1 712:b04b5db36865 174 numBytesReceived = bytesRead;
rgrover1 712:b04b5db36865 175 receiveBufferIndex = 0;
rgrover1 712:b04b5db36865 176 memcpy(receiveBuffer, params->data, numBytesReceived);
rgrover1 712:b04b5db36865 177 }
rgrover1 712:b04b5db36865 178 }
rgrover1 712:b04b5db36865 179 }
rgrover1 712:b04b5db36865 180
rgrover1 712:b04b5db36865 181 private:
rgrover1 712:b04b5db36865 182 BLE &ble;
rgrover1 712:b04b5db36865 183
rgrover1 712:b04b5db36865 184 uint8_t receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
rgrover1 712:b04b5db36865 185 * inbound data before forwarding it to the
rgrover1 712:b04b5db36865 186 * application. */
rgrover1 712:b04b5db36865 187
rgrover1 712:b04b5db36865 188 uint8_t sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which outbound data is
rgrover1 712:b04b5db36865 189 * accumulated before being pushed to the
rgrover1 712:b04b5db36865 190 * rxCharacteristic. */
rgrover1 712:b04b5db36865 191 uint8_t sendBufferIndex;
rgrover1 712:b04b5db36865 192 uint8_t numBytesReceived;
rgrover1 712:b04b5db36865 193 uint8_t receiveBufferIndex;
rgrover1 712:b04b5db36865 194
rgrover1 712:b04b5db36865 195 GattCharacteristic txCharacteristic; /**< From the point of view of the external client, this is the characteristic
rgrover1 712:b04b5db36865 196 * they'd write into in order to communicate with this application. */
rgrover1 712:b04b5db36865 197 GattCharacteristic rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
rgrover1 712:b04b5db36865 198 * they'd read from in order to receive the bytes transmitted by this
rgrover1 712:b04b5db36865 199 * application. */
rgrover1 712:b04b5db36865 200 };
rgrover1 712:b04b5db36865 201
rgrover1 712:b04b5db36865 202 #endif /* #ifndef __BLE_UART_SERVICE_H__*/