Rtos API example

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      * Flush sendBuffer, i.e., forcefully write its contents to the UART RX
00145      * characteristic even if the buffer is not full.
00146      */
00147     void flush() {
00148         if (ble.getGapState().connected) {
00149             if (sendBufferIndex != 0) {
00150                 ble.gattServer().write(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
00151                 sendBufferIndex = 0;
00152             }
00153         }
00154     }
00155 
00156     /**
00157      * Override for Stream::_putc().
00158      * @param  c
00159      *         This function writes the character c, cast to an unsigned char, to stream.
00160      * @return
00161      *     The character written as an unsigned char cast to an int or EOF on error.
00162      */
00163     int _putc(int c) {
00164         return (write(&c, 1) == 1) ? 1 : EOF;
00165     }
00166 
00167     /**
00168      * Override for Stream::_getc().
00169      * @return
00170      *     The character read.
00171      */
00172     int _getc() {
00173         if (receiveBufferIndex == numBytesReceived) {
00174             return EOF;
00175         }
00176 
00177         return receiveBuffer[receiveBufferIndex++];
00178     }
00179 
00180 protected:
00181     /**
00182      * This callback allows the UART service to receive updates to the
00183      * txCharacteristic. The application should forward the call to this
00184      * function from the global onDataWritten() callback handler; if that's
00185      * not used, this method can be used as a callback directly.
00186      */
00187     void onDataWritten(const GattWriteCallbackParams *params) {
00188         if (params->handle == getTXCharacteristicHandle()) {
00189             uint16_t bytesRead = params->len;
00190             if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
00191                 numBytesReceived   = bytesRead;
00192                 receiveBufferIndex = 0;
00193                 memcpy(receiveBuffer, params->data, numBytesReceived);
00194             }
00195         }
00196     }
00197 
00198 protected:
00199     BLE                &ble;
00200 
00201     uint8_t             receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
00202                                                                        *   inbound data before forwarding it to the
00203                                                                        *   application. */
00204 
00205     uint8_t             sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN];    /**< The local buffer into which outbound data is
00206                                                                        *   accumulated before being pushed to the
00207                                                                        *   rxCharacteristic. */
00208     uint8_t             sendBufferIndex;
00209     uint8_t             numBytesReceived;
00210     uint8_t             receiveBufferIndex;
00211 
00212     GattCharacteristic  txCharacteristic; /**< From the point of view of the external client, this is the characteristic
00213                                            *   they'd write into in order to communicate with this application. */
00214     GattCharacteristic  rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
00215                                            *   they'd read from in order to receive the bytes transmitted by this
00216                                            *   application. */
00217 };
00218 
00219 #endif /* #ifndef __BLE_UART_SERVICE_H__*/