Marco Zecchini / Mbed OS Example_RTOS
Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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