first commit

Dependencies:   mbed

Dependents:   ibeacon

Fork of BLE_WallbotBLE_Challenge by JKSoft

Committer:
jksoft
Date:
Wed Nov 12 02:40:34 2014 +0000
Revision:
0:76dfa9657d9d
????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jksoft 0:76dfa9657d9d 1 /* mbed Microcontroller Library
jksoft 0:76dfa9657d9d 2 * Copyright (c) 2006-2013 ARM Limited
jksoft 0:76dfa9657d9d 3 *
jksoft 0:76dfa9657d9d 4 * Licensed under the Apache License, Version 2.0 (the "License");
jksoft 0:76dfa9657d9d 5 * you may not use this file except in compliance with the License.
jksoft 0:76dfa9657d9d 6 * You may obtain a copy of the License at
jksoft 0:76dfa9657d9d 7 *
jksoft 0:76dfa9657d9d 8 * http://www.apache.org/licenses/LICENSE-2.0
jksoft 0:76dfa9657d9d 9 *
jksoft 0:76dfa9657d9d 10 * Unless required by applicable law or agreed to in writing, software
jksoft 0:76dfa9657d9d 11 * distributed under the License is distributed on an "AS IS" BASIS,
jksoft 0:76dfa9657d9d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jksoft 0:76dfa9657d9d 13 * See the License for the specific language governing permissions and
jksoft 0:76dfa9657d9d 14 * limitations under the License.
jksoft 0:76dfa9657d9d 15 */
jksoft 0:76dfa9657d9d 16
jksoft 0:76dfa9657d9d 17 #ifndef __BLE_UART_SERVICE_H__
jksoft 0:76dfa9657d9d 18 #define __BLE_UART_SERVICE_H__
jksoft 0:76dfa9657d9d 19
jksoft 0:76dfa9657d9d 20 #include "Stream.h"
jksoft 0:76dfa9657d9d 21
jksoft 0:76dfa9657d9d 22 #include "UUID.h"
jksoft 0:76dfa9657d9d 23 #include "BLEDevice.h"
jksoft 0:76dfa9657d9d 24
jksoft 0:76dfa9657d9d 25 extern const uint8_t UARTServiceBaseUUID[LENGTH_OF_LONG_UUID];
jksoft 0:76dfa9657d9d 26 extern const uint16_t UARTServiceShortUUID;
jksoft 0:76dfa9657d9d 27 extern const uint16_t UARTServiceTXCharacteristicShortUUID;
jksoft 0:76dfa9657d9d 28 extern const uint16_t UARTServiceRXCharacteristicShortUUID;
jksoft 0:76dfa9657d9d 29
jksoft 0:76dfa9657d9d 30 extern const uint8_t UARTServiceUUID[LENGTH_OF_LONG_UUID];
jksoft 0:76dfa9657d9d 31 extern const uint8_t UARTServiceUUID_reversed[LENGTH_OF_LONG_UUID];
jksoft 0:76dfa9657d9d 32
jksoft 0:76dfa9657d9d 33 extern const uint8_t UARTServiceTXCharacteristicUUID[LENGTH_OF_LONG_UUID];
jksoft 0:76dfa9657d9d 34 extern const uint8_t UARTServiceRXCharacteristicUUID[LENGTH_OF_LONG_UUID];
jksoft 0:76dfa9657d9d 35
jksoft 0:76dfa9657d9d 36 class UARTService : public Stream {
jksoft 0:76dfa9657d9d 37 public:
jksoft 0:76dfa9657d9d 38 /**< Maximum length of data (in bytes) that can be transmitted by the UART service module to the peer. */
jksoft 0:76dfa9657d9d 39 static const unsigned GATT_MTU_SIZE_DEFAULT = 23;
jksoft 0:76dfa9657d9d 40 static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (GATT_MTU_SIZE_DEFAULT - 3);
jksoft 0:76dfa9657d9d 41
jksoft 0:76dfa9657d9d 42 public:
jksoft 0:76dfa9657d9d 43 UARTService(BLEDevice &_ble) :
jksoft 0:76dfa9657d9d 44 Stream("blueart"),
jksoft 0:76dfa9657d9d 45 ble(_ble),
jksoft 0:76dfa9657d9d 46 receiveBuffer(),
jksoft 0:76dfa9657d9d 47 sendBuffer(),
jksoft 0:76dfa9657d9d 48 sendBufferIndex(0),
jksoft 0:76dfa9657d9d 49 numBytesReceived(0),
jksoft 0:76dfa9657d9d 50 receiveBufferIndex(0),
jksoft 0:76dfa9657d9d 51 txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
jksoft 0:76dfa9657d9d 52 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
jksoft 0:76dfa9657d9d 53 rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
jksoft 0:76dfa9657d9d 54 GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
jksoft 0:76dfa9657d9d 55 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
jksoft 0:76dfa9657d9d 56
jksoft 0:76dfa9657d9d 57 ble.addService(uartService);
jksoft 0:76dfa9657d9d 58 ble.onDataWritten(this, &UARTService::onDataWritten);
jksoft 0:76dfa9657d9d 59 }
jksoft 0:76dfa9657d9d 60
jksoft 0:76dfa9657d9d 61 /**
jksoft 0:76dfa9657d9d 62 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
jksoft 0:76dfa9657d9d 63 */
jksoft 0:76dfa9657d9d 64 uint16_t getTXCharacteristicHandle() {
jksoft 0:76dfa9657d9d 65 return txCharacteristic.getValueAttribute().getHandle();
jksoft 0:76dfa9657d9d 66 }
jksoft 0:76dfa9657d9d 67
jksoft 0:76dfa9657d9d 68 /**
jksoft 0:76dfa9657d9d 69 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
jksoft 0:76dfa9657d9d 70 */
jksoft 0:76dfa9657d9d 71 uint16_t getRXCharacteristicHandle() {
jksoft 0:76dfa9657d9d 72 return rxCharacteristic.getValueAttribute().getHandle();
jksoft 0:76dfa9657d9d 73 }
jksoft 0:76dfa9657d9d 74
jksoft 0:76dfa9657d9d 75 /**
jksoft 0:76dfa9657d9d 76 * Following a call to this function, all writes to stdout (such as from
jksoft 0:76dfa9657d9d 77 * printf) get redirected to the outbound characteristic of this service.
jksoft 0:76dfa9657d9d 78 * This might be very useful when wanting to receive debug messages over BLE.
jksoft 0:76dfa9657d9d 79 *
jksoft 0:76dfa9657d9d 80 * @Note: debug messages originating from printf() like calls are buffered
jksoft 0:76dfa9657d9d 81 * before being sent out. A '\n' in the printf() triggers the buffer update
jksoft 0:76dfa9657d9d 82 * to the underlying characteristic.
jksoft 0:76dfa9657d9d 83 *
jksoft 0:76dfa9657d9d 84 * @Note: long messages need to be chopped up into 20-byte updates so that
jksoft 0:76dfa9657d9d 85 * they flow out completely with notifications. The receiver should be
jksoft 0:76dfa9657d9d 86 * prepared to stitch these messages back.
jksoft 0:76dfa9657d9d 87 */
jksoft 0:76dfa9657d9d 88 void retargetStdout() {
jksoft 0:76dfa9657d9d 89 freopen("/blueart", "w", stdout);
jksoft 0:76dfa9657d9d 90 }
jksoft 0:76dfa9657d9d 91
jksoft 0:76dfa9657d9d 92 /**
jksoft 0:76dfa9657d9d 93 * This callback allows the UART service to receive updates to the
jksoft 0:76dfa9657d9d 94 * txCharacteristic. The application should forward the call to this
jksoft 0:76dfa9657d9d 95 * function from the global onDataWritten() callback handler; or if that's
jksoft 0:76dfa9657d9d 96 * not used, this method can be used as a callback directly.
jksoft 0:76dfa9657d9d 97 */
jksoft 0:76dfa9657d9d 98 virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
jksoft 0:76dfa9657d9d 99 if (params->charHandle == getTXCharacteristicHandle()) {
jksoft 0:76dfa9657d9d 100 uint16_t bytesRead = params->len;
jksoft 0:76dfa9657d9d 101 if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
jksoft 0:76dfa9657d9d 102 numBytesReceived = bytesRead;
jksoft 0:76dfa9657d9d 103 receiveBufferIndex = 0;
jksoft 0:76dfa9657d9d 104 memcpy(receiveBuffer, params->data, numBytesReceived);
jksoft 0:76dfa9657d9d 105 }
jksoft 0:76dfa9657d9d 106 }
jksoft 0:76dfa9657d9d 107 }
jksoft 0:76dfa9657d9d 108
jksoft 0:76dfa9657d9d 109 protected:
jksoft 0:76dfa9657d9d 110 /**
jksoft 0:76dfa9657d9d 111 * Override for Stream::write().
jksoft 0:76dfa9657d9d 112 *
jksoft 0:76dfa9657d9d 113 * We attempt to collect bytes before pushing them to the UART RX
jksoft 0:76dfa9657d9d 114 * characteristic--writing to the RX characteristic will then generate
jksoft 0:76dfa9657d9d 115 * notifications for the client. Updates made in quick succession to a
jksoft 0:76dfa9657d9d 116 * notification-generating characteristic will result in data being buffered
jksoft 0:76dfa9657d9d 117 * in the bluetooth stack as notifications are sent out. The stack will have
jksoft 0:76dfa9657d9d 118 * its limits for this buffering; typically a small number under 10.
jksoft 0:76dfa9657d9d 119 * Collecting data into the sendBuffer buffer helps mitigate the rate of
jksoft 0:76dfa9657d9d 120 * updates. But we shouldn't buffer a large amount of data before updating
jksoft 0:76dfa9657d9d 121 * the characteristic otherwise the client will need to turn around and make
jksoft 0:76dfa9657d9d 122 * a long read request; this is because notifications include only the first
jksoft 0:76dfa9657d9d 123 * 20 bytes of the updated data.
jksoft 0:76dfa9657d9d 124 *
jksoft 0:76dfa9657d9d 125 * @param buffer The received update
jksoft 0:76dfa9657d9d 126 * @param length Amount of characters to be appended.
jksoft 0:76dfa9657d9d 127 * @return Amount of characters appended to the rxCharacteristic.
jksoft 0:76dfa9657d9d 128 */
jksoft 0:76dfa9657d9d 129 virtual ssize_t write(const void* _buffer, size_t length) {
jksoft 0:76dfa9657d9d 130 size_t origLength = length;
jksoft 0:76dfa9657d9d 131 const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
jksoft 0:76dfa9657d9d 132
jksoft 0:76dfa9657d9d 133 if (ble.getGapState().connected) {
jksoft 0:76dfa9657d9d 134 unsigned bufferIndex = 0;
jksoft 0:76dfa9657d9d 135 while (length) {
jksoft 0:76dfa9657d9d 136 unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
jksoft 0:76dfa9657d9d 137 unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
jksoft 0:76dfa9657d9d 138
jksoft 0:76dfa9657d9d 139 /* copy bytes into sendBuffer */
jksoft 0:76dfa9657d9d 140 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
jksoft 0:76dfa9657d9d 141 length -= bytesToCopy;
jksoft 0:76dfa9657d9d 142 sendBufferIndex += bytesToCopy;
jksoft 0:76dfa9657d9d 143 bufferIndex += bytesToCopy;
jksoft 0:76dfa9657d9d 144
jksoft 0:76dfa9657d9d 145 /* have we collected enough? */
jksoft 0:76dfa9657d9d 146 if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
jksoft 0:76dfa9657d9d 147 // (sendBuffer[sendBufferIndex - 1] == '\r') ||
jksoft 0:76dfa9657d9d 148 (sendBuffer[sendBufferIndex - 1] == '\n')) {
jksoft 0:76dfa9657d9d 149 ble.updateCharacteristicValue(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
jksoft 0:76dfa9657d9d 150 sendBufferIndex = 0;
jksoft 0:76dfa9657d9d 151 }
jksoft 0:76dfa9657d9d 152 }
jksoft 0:76dfa9657d9d 153 }
jksoft 0:76dfa9657d9d 154
jksoft 0:76dfa9657d9d 155 return origLength;
jksoft 0:76dfa9657d9d 156 }
jksoft 0:76dfa9657d9d 157
jksoft 0:76dfa9657d9d 158 /**
jksoft 0:76dfa9657d9d 159 * Override for Stream::_putc()
jksoft 0:76dfa9657d9d 160 * @param c
jksoft 0:76dfa9657d9d 161 * This function writes the character c, cast to an unsigned char, to stream.
jksoft 0:76dfa9657d9d 162 * @return
jksoft 0:76dfa9657d9d 163 * The character written as an unsigned char cast to an int or EOF on error.
jksoft 0:76dfa9657d9d 164 */
jksoft 0:76dfa9657d9d 165 virtual int _putc(int c) {
jksoft 0:76dfa9657d9d 166 return (write(&c, 1) == 1) ? 1 : EOF;
jksoft 0:76dfa9657d9d 167 }
jksoft 0:76dfa9657d9d 168
jksoft 0:76dfa9657d9d 169 virtual int _getc() {
jksoft 0:76dfa9657d9d 170 if (receiveBufferIndex == numBytesReceived) {
jksoft 0:76dfa9657d9d 171 return EOF;
jksoft 0:76dfa9657d9d 172 }
jksoft 0:76dfa9657d9d 173
jksoft 0:76dfa9657d9d 174 return receiveBuffer[receiveBufferIndex++];
jksoft 0:76dfa9657d9d 175 }
jksoft 0:76dfa9657d9d 176
jksoft 0:76dfa9657d9d 177 virtual int isatty() {
jksoft 0:76dfa9657d9d 178 return 1;
jksoft 0:76dfa9657d9d 179 }
jksoft 0:76dfa9657d9d 180
jksoft 0:76dfa9657d9d 181 private:
jksoft 0:76dfa9657d9d 182 BLEDevice &ble;
jksoft 0:76dfa9657d9d 183
jksoft 0:76dfa9657d9d 184 uint8_t receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
jksoft 0:76dfa9657d9d 185 * inbound data before forwarding it to the
jksoft 0:76dfa9657d9d 186 * application. */
jksoft 0:76dfa9657d9d 187
jksoft 0:76dfa9657d9d 188 uint8_t sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which outbound data is
jksoft 0:76dfa9657d9d 189 * accumulated before being pushed to the
jksoft 0:76dfa9657d9d 190 * rxCharacteristic. */
jksoft 0:76dfa9657d9d 191 uint8_t sendBufferIndex;
jksoft 0:76dfa9657d9d 192 uint8_t numBytesReceived;
jksoft 0:76dfa9657d9d 193 uint8_t receiveBufferIndex;
jksoft 0:76dfa9657d9d 194
jksoft 0:76dfa9657d9d 195 GattCharacteristic txCharacteristic; /**< From the point of view of the external client, this is the characteristic
jksoft 0:76dfa9657d9d 196 * they'd write into in order to communicate with this application. */
jksoft 0:76dfa9657d9d 197 GattCharacteristic rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
jksoft 0:76dfa9657d9d 198 * they'd read from in order to receive the bytes transmitted by this
jksoft 0:76dfa9657d9d 199 * application. */
jksoft 0:76dfa9657d9d 200 };
jksoft 0:76dfa9657d9d 201
jksoft 0:76dfa9657d9d 202 #endif /* #ifndef __BLE_UART_SERVICE_H__*/
jksoft 0:76dfa9657d9d 203