テスト用です。

Dependencies:   mbed

Committer:
jksoft
Date:
Tue Oct 11 11:09:42 2016 +0000
Revision:
0:8468a4403fea
SB??ver;

Who changed what in which revision?

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