jgh

Dependents:   Migration

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Wed Dec 02 12:57:28 2015 +0000
Revision:
1008:c27e0c6f1f38
Parent:
1006:76ae9bbf173f
Child:
1017:ccb8c0646e55
Synchronized with git rev 13bf70b6
Author: Rohit Grover
Release 2.1.5
=============

A minor release to separate the concept of minlen and len in
GattCharacteristic. Also contains some improvements to documentation.

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