High level Bluetooth Low Energy API and radio abstraction layer

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate BLE_ANCS_SDAPI_IRC ... more

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 #ifdef YOTTA_CFG_MBED_OS
00021 #include "mbed-drivers/mbed.h"
00022 #include "mbed-drivers/Stream.h"
00023 #else
00024 #include "mbed.h"
00025 #include "Stream.h"
00026 #endif
00027 
00028 #include "ble/UUID.h"
00029 #include "ble/BLE.h"
00030 
00031 extern const uint8_t  UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
00032 extern const uint16_t UARTServiceShortUUID;
00033 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
00034 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
00035 
00036 extern const uint8_t  UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID];
00037 extern const uint8_t  UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID];
00038 
00039 extern const uint8_t  UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
00040 extern const uint8_t  UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
00041 
00042 /**
00043 * @class UARTService.
00044 * @brief BLE Service to enable UART over BLE.
00045 */
00046 class UARTService {
00047 public:
00048     /**< Maximum length of data (in bytes) that the UART service module can transmit to the peer. */
00049     static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (BLE_GATT_MTU_SIZE_DEFAULT - 3);
00050 
00051 public:
00052 
00053     /**
00054     * @param[ref] ble
00055     *               BLE object for the underlying controller.
00056     */
00057     UARTService (BLE &_ble) :
00058         ble(_ble),
00059         receiveBuffer(),
00060         sendBuffer(),
00061         sendBufferIndex(0),
00062         numBytesReceived(0),
00063         receiveBufferIndex(0),
00064         txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
00065                          GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
00066         rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
00067         GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
00068         GattService         uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00069 
00070         ble.addService(uartService);
00071         ble.onDataWritten(this, &UARTService::onDataWritten);
00072     }
00073 
00074     /**
00075      * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
00076      */
00077     uint16_t getTXCharacteristicHandle() {
00078         return txCharacteristic.getValueAttribute().getHandle();
00079     }
00080 
00081     /**
00082      * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
00083      */
00084     uint16_t getRXCharacteristicHandle() {
00085         return rxCharacteristic.getValueAttribute().getHandle();
00086     }
00087 
00088     /**
00089      * We attempt to collect bytes before pushing them to the UART RX
00090      * characteristic; writing to the RX characteristic then generates
00091      * notifications for the client. Updates made in quick succession to a
00092      * notification-generating characteristic result in data being buffered
00093      * in the Bluetooth stack as notifications are sent out. The stack has
00094      * its limits for this buffering - typically a small number under 10.
00095      * Collecting data into the sendBuffer buffer helps mitigate the rate of
00096      * updates. But we shouldn't buffer a large amount of data before updating
00097      * the characteristic, otherwise the client needs to turn around and make
00098      * a long read request; this is because notifications include only the first
00099      * 20 bytes of the updated data.
00100      *
00101      * @param  buffer The received update.
00102      * @param  length Number of characters to be appended.
00103      * @return        Number of characters appended to the rxCharacteristic.
00104      */
00105     size_t write(const void *_buffer, size_t length) {
00106         size_t         origLength = length;
00107         const uint8_t *buffer     = static_cast<const uint8_t *>(_buffer);
00108 
00109         if (ble.getGapState().connected) {
00110             unsigned bufferIndex = 0;
00111             while (length) {
00112                 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
00113                 unsigned bytesToCopy                = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
00114 
00115                 /* Copy bytes into sendBuffer. */
00116                 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
00117                 length          -= bytesToCopy;
00118                 sendBufferIndex += bytesToCopy;
00119                 bufferIndex     += bytesToCopy;
00120 
00121                 /* Have we collected enough? */
00122                 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
00123                     // (sendBuffer[sendBufferIndex - 1] == '\r')          ||
00124                     (sendBuffer[sendBufferIndex - 1] == '\n')) {
00125                     ble.gattServer().write(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
00126                     sendBufferIndex = 0;
00127                 }
00128             }
00129         }
00130 
00131         return origLength;
00132     }
00133 
00134     /**
00135      * Helper function to write out strings.
00136      * @param  str The received string.
00137      * @return     Number of characters appended to the rxCharacteristic.
00138      */
00139     size_t writeString(const char *str) {
00140         return write(str, strlen(str));
00141     }
00142 
00143     /**
00144      * Override for Stream::_putc().
00145      * @param  c
00146      *         This function writes the character c, cast to an unsigned char, to stream.
00147      * @return
00148      *     The character written as an unsigned char cast to an int or EOF on error.
00149      */
00150     int _putc(int c) {
00151         return (write(&c, 1) == 1) ? 1 : EOF;
00152     }
00153 
00154     /**
00155      * Override for Stream::_getc().
00156      * @return
00157      *     The character read.
00158      */
00159     int _getc() {
00160         if (receiveBufferIndex == numBytesReceived) {
00161             return EOF;
00162         }
00163 
00164         return receiveBuffer[receiveBufferIndex++];
00165     }
00166 
00167 protected:
00168     /**
00169      * This callback allows the UART service to receive updates to the
00170      * txCharacteristic. The application should forward the call to this
00171      * function from the global onDataWritten() callback handler; if that's
00172      * not used, this method can be used as a callback directly.
00173      */
00174     void onDataWritten(const GattWriteCallbackParams *params) {
00175         if (params->handle == getTXCharacteristicHandle()) {
00176             uint16_t bytesRead = params->len;
00177             if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
00178                 numBytesReceived   = bytesRead;
00179                 receiveBufferIndex = 0;
00180                 memcpy(receiveBuffer, params->data, numBytesReceived);
00181             }
00182         }
00183     }
00184 
00185 protected:
00186     BLE                &ble;
00187 
00188     uint8_t             receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
00189                                                                        *   inbound data before forwarding it to the
00190                                                                        *   application. */
00191 
00192     uint8_t             sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN];    /**< The local buffer into which outbound data is
00193                                                                        *   accumulated before being pushed to the
00194                                                                        *   rxCharacteristic. */
00195     uint8_t             sendBufferIndex;
00196     uint8_t             numBytesReceived;
00197     uint8_t             receiveBufferIndex;
00198 
00199     GattCharacteristic  txCharacteristic; /**< From the point of view of the external client, this is the characteristic
00200                                            *   they'd write into in order to communicate with this application. */
00201     GattCharacteristic  rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
00202                                            *   they'd read from in order to receive the bytes transmitted by this
00203                                            *   application. */
00204 };
00205 
00206 #endif /* #ifndef __BLE_UART_SERVICE_H__*/