Javier Velasco / BLE_API

Dependents:   BLE_iBeacon

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