Bill Schilit / BLE_API

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UARTService.h Source File

UARTService.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef __BLE_UART_SERVICE_H__
00018 #define __BLE_UART_SERVICE_H__
00019 
00020 #include "mbed.h"
00021 #include "Stream.h"
00022 
00023 #include "UUID.h"
00024 #include "BLEDevice.h"
00025 
00026 extern const uint8_t  UARTServiceBaseUUID[LENGTH_OF_LONG_UUID];
00027 extern const uint16_t UARTServiceShortUUID;
00028 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
00029 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
00030 
00031 extern const uint8_t  UARTServiceUUID[LENGTH_OF_LONG_UUID];
00032 extern const uint8_t  UARTServiceUUID_reversed[LENGTH_OF_LONG_UUID];
00033 
00034 extern const uint8_t  UARTServiceTXCharacteristicUUID[LENGTH_OF_LONG_UUID];
00035 extern const uint8_t  UARTServiceRXCharacteristicUUID[LENGTH_OF_LONG_UUID];
00036 
00037 /**
00038 * @class UARTService
00039 * @brief BLE Service to enable UART over BLE
00040 */
00041 class UARTService {
00042 public:
00043     /**< Maximum length of data (in bytes) that can be transmitted by the UART service module to the peer. */
00044     static const unsigned GATT_MTU_SIZE_DEFAULT         = 23;
00045     static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (GATT_MTU_SIZE_DEFAULT - 3);
00046 
00047 public:
00048 
00049     /**
00050     * @param[ref] ble
00051     *                 BLEDevice object for the underlying controller.
00052     */
00053     UARTService (BLEDevice &_ble) :
00054         ble(_ble),
00055         receiveBuffer(),
00056         sendBuffer(),
00057         sendBufferIndex(0),
00058         numBytesReceived(0),
00059         receiveBufferIndex(0),
00060         txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
00061                          GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
00062         rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
00063         GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
00064         GattService         uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00065 
00066         ble.addService(uartService);
00067         ble.onDataWritten(this, &UARTService::onDataWritten);
00068     }
00069 
00070     /**
00071      * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
00072      */
00073     uint16_t getTXCharacteristicHandle() {
00074         return txCharacteristic.getValueAttribute().getHandle();
00075     }
00076 
00077     /**
00078      * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
00079      */
00080     uint16_t getRXCharacteristicHandle() {
00081         return rxCharacteristic.getValueAttribute().getHandle();
00082     }
00083 
00084     /**
00085      * We attempt to collect bytes before pushing them to the UART RX
00086      * characteristic--writing to the RX characteristic will then generate
00087      * notifications for the client. Updates made in quick succession to a
00088      * notification-generating characteristic will result in data being buffered
00089      * in the bluetooth stack as notifications are sent out. The stack will have
00090      * its limits for this buffering; typically a small number under 10.
00091      * Collecting data into the sendBuffer buffer helps mitigate the rate of
00092      * updates. But we shouldn't buffer a large amount of data before updating
00093      * the characteristic otherwise the client will need to turn around and make
00094      * a long read request; this is because notifications include only the first
00095      * 20 bytes of the updated data.
00096      *
00097      * @param  buffer The received update
00098      * @param  length Amount of characters to be appended.
00099      * @return        Amount of characters appended to the rxCharacteristic.
00100      */
00101     ssize_t write(const void *_buffer, size_t length) {
00102         size_t         origLength = length;
00103         const uint8_t *buffer     = static_cast<const uint8_t *>(_buffer);
00104 
00105         if (ble.getGapState().connected) {
00106             unsigned bufferIndex = 0;
00107             while (length) {
00108                 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
00109                 unsigned bytesToCopy                = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
00110 
00111                 /* copy bytes into sendBuffer */
00112                 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
00113                 length          -= bytesToCopy;
00114                 sendBufferIndex += bytesToCopy;
00115                 bufferIndex     += bytesToCopy;
00116 
00117                 /* have we collected enough? */
00118                 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
00119                     // (sendBuffer[sendBufferIndex - 1] == '\r')          ||
00120                     (sendBuffer[sendBufferIndex - 1] == '\n')) {
00121                     ble.updateCharacteristicValue (getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
00122                     sendBufferIndex = 0;
00123                 }
00124             }
00125         }
00126 
00127         return origLength;
00128     }
00129 
00130     /**
00131      * Override for Stream::_putc()
00132      * @param  c
00133      *         This function writes the character c, cast to an unsigned char, to stream.
00134      * @return
00135      *     The character written as an unsigned char cast to an int or EOF on error.
00136      */
00137     int _putc(int c) {
00138         return (write(&c, 1) == 1) ? 1 : EOF;
00139     }
00140 
00141     /**
00142      * Override for Stream::_getc()
00143      * @return
00144      *     The character read.
00145      */
00146     int _getc() {
00147         if (receiveBufferIndex == numBytesReceived) {
00148             return EOF;
00149         }
00150 
00151         return receiveBuffer[receiveBufferIndex++];
00152     }
00153 
00154 private:
00155     /**
00156      * This callback allows the UART service to receive updates to the
00157      * txCharacteristic. The application should forward the call to this
00158      * function from the global onDataWritten() callback handler; or if that's
00159      * not used, this method can be used as a callback directly.
00160      */
00161     void onDataWritten(const GattCharacteristicWriteCBParams *params) {
00162         if (params->charHandle == getTXCharacteristicHandle()) {
00163             uint16_t bytesRead = params->len;
00164             if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
00165                 numBytesReceived   = bytesRead;
00166                 receiveBufferIndex = 0;
00167                 memcpy(receiveBuffer, params->data, numBytesReceived);
00168             }
00169         }
00170     }
00171 
00172 private:
00173     BLEDevice          &ble;
00174 
00175     uint8_t             receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
00176                                                                        *   inbound data before forwarding it to the
00177                                                                        *   application. */
00178 
00179     uint8_t             sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN];    /**< The local buffer into which outbound data is
00180                                                                        *   accumulated before being pushed to the
00181                                                                        *   rxCharacteristic. */
00182     uint8_t             sendBufferIndex;
00183     uint8_t             numBytesReceived;
00184     uint8_t             receiveBufferIndex;
00185 
00186     GattCharacteristic  txCharacteristic; /**< From the point of view of the external client, this is the characteristic
00187                                            *   they'd write into in order to communicate with this application. */
00188     GattCharacteristic  rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
00189                                            *   they'd read from in order to receive the bytes transmitted by this
00190                                            *   application. */
00191 };
00192 
00193 #endif /* #ifndef __BLE_UART_SERVICE_H__*/