IOTIO

Fork of Nucleo_BLE_API by ST Americas mbed Team

Committer:
16038618
Date:
Sat Oct 29 14:16:12 2016 +0000
Revision:
2:584d5bedac75
Parent:
1:79e5c08cbcc7
IOTIO

Who changed what in which revision?

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