Paulo Roman / BLE_API

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Fri Jun 19 15:52:06 2015 +0100
Revision:
526:caa67c3187a0
Parent:
524:6e97ab392e2a
Child:
527:493185cebc03
Synchronized with git rev 9bcd7433
Author: Rohit Grover
Rename BLEDevice as BLE. Retain an alias to BLEDevice for the sake of compatibility with old code.

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
rgrover1 227:5c4cb4553821 20 #include "mbed.h"
Rohit Grover 118:620d28e7a1ba 21 #include "Stream.h"
Rohit Grover 118:620d28e7a1ba 22
Rohit Grover 118:620d28e7a1ba 23 #include "UUID.h"
Rohit Grover 118:620d28e7a1ba 24 #include "BLEDevice.h"
Rohit Grover 118:620d28e7a1ba 25
rgrover1 458:5546ebd25359 26 extern const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 27 extern const uint16_t UARTServiceShortUUID;
Rohit Grover 118:620d28e7a1ba 28 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
Rohit Grover 118:620d28e7a1ba 29 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
Rohit Grover 118:620d28e7a1ba 30
rgrover1 458:5546ebd25359 31 extern const uint8_t UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 458:5546ebd25359 32 extern const uint8_t UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 33
rgrover1 458:5546ebd25359 34 extern const uint8_t UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
rgrover1 458:5546ebd25359 35 extern const uint8_t UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
Rohit Grover 118:620d28e7a1ba 36
mbedAustin 233:4d570d99b8cb 37 /**
mbedAustin 233:4d570d99b8cb 38 * @class UARTService
rgrover1 242:0e9201b67e2f 39 * @brief BLE Service to enable UART over BLE
mbedAustin 233:4d570d99b8cb 40 */
rgrover1 197:5551036f054b 41 class UARTService {
Rohit Grover 118:620d28e7a1ba 42 public:
Rohit Grover 118:620d28e7a1ba 43 /**< Maximum length of data (in bytes) that can be transmitted by the UART service module to the peer. */
rgrover1 197:5551036f054b 44 static const unsigned GATT_MTU_SIZE_DEFAULT = 23;
Rohit Grover 118:620d28e7a1ba 45 static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (GATT_MTU_SIZE_DEFAULT - 3);
Rohit Grover 118:620d28e7a1ba 46
Rohit Grover 118:620d28e7a1ba 47 public:
mbedAustin 233:4d570d99b8cb 48
mbedAustin 233:4d570d99b8cb 49 /**
mbedAustin 233:4d570d99b8cb 50 * @param[ref] ble
mbedAustin 233:4d570d99b8cb 51 * BLEDevice object for the underlying controller.
mbedAustin 233:4d570d99b8cb 52 */
Rohit Grover 118:620d28e7a1ba 53 UARTService(BLEDevice &_ble) :
Rohit Grover 118:620d28e7a1ba 54 ble(_ble),
Rohit Grover 118:620d28e7a1ba 55 receiveBuffer(),
Rohit Grover 118:620d28e7a1ba 56 sendBuffer(),
Rohit Grover 118:620d28e7a1ba 57 sendBufferIndex(0),
Rohit Grover 118:620d28e7a1ba 58 numBytesReceived(0),
Rohit Grover 118:620d28e7a1ba 59 receiveBufferIndex(0),
Rohit Grover 118:620d28e7a1ba 60 txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
Rohit Grover 118:620d28e7a1ba 61 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
Rohit Grover 118:620d28e7a1ba 62 rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
Rohit Grover 118:620d28e7a1ba 63 GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
Rohit Grover 118:620d28e7a1ba 64 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Rohit Grover 118:620d28e7a1ba 65
Rohit Grover 118:620d28e7a1ba 66 ble.addService(uartService);
Rohit Grover 118:620d28e7a1ba 67 ble.onDataWritten(this, &UARTService::onDataWritten);
Rohit Grover 118:620d28e7a1ba 68 }
Rohit Grover 118:620d28e7a1ba 69
Rohit Grover 118:620d28e7a1ba 70 /**
Rohit Grover 118:620d28e7a1ba 71 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
Rohit Grover 118:620d28e7a1ba 72 */
Rohit Grover 118:620d28e7a1ba 73 uint16_t getTXCharacteristicHandle() {
Rohit Grover 118:620d28e7a1ba 74 return txCharacteristic.getValueAttribute().getHandle();
Rohit Grover 118:620d28e7a1ba 75 }
Rohit Grover 118:620d28e7a1ba 76
Rohit Grover 118:620d28e7a1ba 77 /**
Rohit Grover 118:620d28e7a1ba 78 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
Rohit Grover 118:620d28e7a1ba 79 */
Rohit Grover 118:620d28e7a1ba 80 uint16_t getRXCharacteristicHandle() {
Rohit Grover 118:620d28e7a1ba 81 return rxCharacteristic.getValueAttribute().getHandle();
Rohit Grover 118:620d28e7a1ba 82 }
Rohit Grover 118:620d28e7a1ba 83
Rohit Grover 118:620d28e7a1ba 84 /**
Rohit Grover 118:620d28e7a1ba 85 * We attempt to collect bytes before pushing them to the UART RX
Rohit Grover 118:620d28e7a1ba 86 * characteristic--writing to the RX characteristic will then generate
Rohit Grover 118:620d28e7a1ba 87 * notifications for the client. Updates made in quick succession to a
Rohit Grover 118:620d28e7a1ba 88 * notification-generating characteristic will result in data being buffered
Rohit Grover 118:620d28e7a1ba 89 * in the bluetooth stack as notifications are sent out. The stack will have
Rohit Grover 118:620d28e7a1ba 90 * its limits for this buffering; typically a small number under 10.
Rohit Grover 118:620d28e7a1ba 91 * Collecting data into the sendBuffer buffer helps mitigate the rate of
Rohit Grover 118:620d28e7a1ba 92 * updates. But we shouldn't buffer a large amount of data before updating
Rohit Grover 118:620d28e7a1ba 93 * the characteristic otherwise the client will need to turn around and make
Rohit Grover 118:620d28e7a1ba 94 * a long read request; this is because notifications include only the first
Rohit Grover 118:620d28e7a1ba 95 * 20 bytes of the updated data.
Rohit Grover 118:620d28e7a1ba 96 *
Rohit Grover 118:620d28e7a1ba 97 * @param buffer The received update
Rohit Grover 118:620d28e7a1ba 98 * @param length Amount of characters to be appended.
Rohit Grover 118:620d28e7a1ba 99 * @return Amount of characters appended to the rxCharacteristic.
Rohit Grover 118:620d28e7a1ba 100 */
rgrover1 326:f79c1562312f 101 size_t write(const void *_buffer, size_t length) {
rgrover1 242:0e9201b67e2f 102 size_t origLength = length;
rgrover1 242:0e9201b67e2f 103 const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
Rohit Grover 118:620d28e7a1ba 104
Rohit Grover 118:620d28e7a1ba 105 if (ble.getGapState().connected) {
Rohit Grover 118:620d28e7a1ba 106 unsigned bufferIndex = 0;
Rohit Grover 118:620d28e7a1ba 107 while (length) {
Rohit Grover 118:620d28e7a1ba 108 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
rgrover1 242:0e9201b67e2f 109 unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
Rohit Grover 118:620d28e7a1ba 110
Rohit Grover 118:620d28e7a1ba 111 /* copy bytes into sendBuffer */
Rohit Grover 118:620d28e7a1ba 112 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
Rohit Grover 118:620d28e7a1ba 113 length -= bytesToCopy;
Rohit Grover 118:620d28e7a1ba 114 sendBufferIndex += bytesToCopy;
Rohit Grover 118:620d28e7a1ba 115 bufferIndex += bytesToCopy;
Rohit Grover 118:620d28e7a1ba 116
Rohit Grover 118:620d28e7a1ba 117 /* have we collected enough? */
Rohit Grover 118:620d28e7a1ba 118 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
Rohit Grover 118:620d28e7a1ba 119 // (sendBuffer[sendBufferIndex - 1] == '\r') ||
Rohit Grover 118:620d28e7a1ba 120 (sendBuffer[sendBufferIndex - 1] == '\n')) {
Rohit Grover 118:620d28e7a1ba 121 ble.updateCharacteristicValue(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
Rohit Grover 118:620d28e7a1ba 122 sendBufferIndex = 0;
Rohit Grover 118:620d28e7a1ba 123 }
Rohit Grover 118:620d28e7a1ba 124 }
Rohit Grover 118:620d28e7a1ba 125 }
Rohit Grover 118:620d28e7a1ba 126
Rohit Grover 118:620d28e7a1ba 127 return origLength;
Rohit Grover 118:620d28e7a1ba 128 }
Rohit Grover 118:620d28e7a1ba 129
Rohit Grover 118:620d28e7a1ba 130 /**
rgrover1 327:8c645f5694b2 131 * Helper function to write out strings.
rgrover1 327:8c645f5694b2 132 * @param str The received string.
rgrover1 327:8c645f5694b2 133 * @return Amount of characters appended to the rxCharacteristic.
rgrover1 327:8c645f5694b2 134 */
rgrover1 327:8c645f5694b2 135 size_t writeString(const char *str) {
rgrover1 327:8c645f5694b2 136 return write(str, strlen(str));
rgrover1 327:8c645f5694b2 137 }
rgrover1 327:8c645f5694b2 138
rgrover1 327:8c645f5694b2 139 /**
Rohit Grover 118:620d28e7a1ba 140 * Override for Stream::_putc()
Rohit Grover 118:620d28e7a1ba 141 * @param c
Rohit Grover 118:620d28e7a1ba 142 * This function writes the character c, cast to an unsigned char, to stream.
Rohit Grover 118:620d28e7a1ba 143 * @return
Rohit Grover 118:620d28e7a1ba 144 * The character written as an unsigned char cast to an int or EOF on error.
Rohit Grover 118:620d28e7a1ba 145 */
rgrover1 197:5551036f054b 146 int _putc(int c) {
Rohit Grover 118:620d28e7a1ba 147 return (write(&c, 1) == 1) ? 1 : EOF;
Rohit Grover 118:620d28e7a1ba 148 }
Rohit Grover 118:620d28e7a1ba 149
mbedAustin 233:4d570d99b8cb 150 /**
mbedAustin 233:4d570d99b8cb 151 * Override for Stream::_getc()
mbedAustin 233:4d570d99b8cb 152 * @return
mbedAustin 233:4d570d99b8cb 153 * The character read.
mbedAustin 233:4d570d99b8cb 154 */
rgrover1 197:5551036f054b 155 int _getc() {
Rohit Grover 118:620d28e7a1ba 156 if (receiveBufferIndex == numBytesReceived) {
Rohit Grover 118:620d28e7a1ba 157 return EOF;
Rohit Grover 118:620d28e7a1ba 158 }
Rohit Grover 118:620d28e7a1ba 159
Rohit Grover 118:620d28e7a1ba 160 return receiveBuffer[receiveBufferIndex++];
Rohit Grover 118:620d28e7a1ba 161 }
Rohit Grover 118:620d28e7a1ba 162
rgrover1 197:5551036f054b 163 private:
rgrover1 197:5551036f054b 164 /**
rgrover1 197:5551036f054b 165 * This callback allows the UART service to receive updates to the
rgrover1 197:5551036f054b 166 * txCharacteristic. The application should forward the call to this
rgrover1 197:5551036f054b 167 * function from the global onDataWritten() callback handler; or if that's
rgrover1 197:5551036f054b 168 * not used, this method can be used as a callback directly.
rgrover1 197:5551036f054b 169 */
rgrover1 526:caa67c3187a0 170 void onDataWritten(const GattCharacteristicWriteCBParams *params) {
rgrover1 526:caa67c3187a0 171 if (params->charHandle == getTXCharacteristicHandle()) {
rgrover1 197:5551036f054b 172 uint16_t bytesRead = params->len;
rgrover1 197:5551036f054b 173 if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
rgrover1 197:5551036f054b 174 numBytesReceived = bytesRead;
rgrover1 197:5551036f054b 175 receiveBufferIndex = 0;
rgrover1 197:5551036f054b 176 memcpy(receiveBuffer, params->data, numBytesReceived);
rgrover1 197:5551036f054b 177 }
rgrover1 197:5551036f054b 178 }
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
rgrover1 242:0e9201b67e2f 202 #endif /* #ifndef __BLE_UART_SERVICE_H__*/