Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of BLE_API by
services/UARTService.h@327:8c645f5694b2, 2015-03-27 (annotated)
- Committer:
- rgrover1
- Date:
- Fri Mar 27 13:03:37 2015 +0000
- Revision:
- 327:8c645f5694b2
- Parent:
- 326:f79c1562312f
- Child:
- 419:0b9370f628b4
Synchronized with git rev 1d21e85a
Author: Rohit Grover
Release 0.3.1
=============
Enhancements
~~~~~~~~~~~~
* added helper UARTService::writeString() to simplify writing of strings.
Bugfixes
~~~~~~~~
none.
Who changed what in which revision?
User | Revision | Line number | New 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 | 242:0e9201b67e2f | 26 | extern const uint8_t UARTServiceBaseUUID[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 | 242:0e9201b67e2f | 31 | extern const uint8_t UARTServiceUUID[LENGTH_OF_LONG_UUID]; |
rgrover1 | 242:0e9201b67e2f | 32 | extern const uint8_t UARTServiceUUID_reversed[LENGTH_OF_LONG_UUID]; |
Rohit Grover |
118:620d28e7a1ba | 33 | |
rgrover1 | 242:0e9201b67e2f | 34 | extern const uint8_t UARTServiceTXCharacteristicUUID[LENGTH_OF_LONG_UUID]; |
rgrover1 | 242:0e9201b67e2f | 35 | extern const uint8_t UARTServiceRXCharacteristicUUID[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 | 197:5551036f054b | 170 | void onDataWritten(const GattCharacteristicWriteCBParams *params) { |
rgrover1 | 197:5551036f054b | 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__*/ |