ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Thu Sep 15 09:31:05 2016 +0900
Revision:
86:e0fab77e669d
Parent:
83:2e940d154f8b
support consumer keys

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cho45 42:2c3be8694896 1
cho45 5:65d4e94735b6 2 /* mbed Microcontroller Library
cho45 5:65d4e94735b6 3 * Copyright (c) 2015 ARM Limited
cho45 5:65d4e94735b6 4 *
cho45 5:65d4e94735b6 5 * Licensed under the Apache License, Version 2.0 (the "License");
cho45 5:65d4e94735b6 6 * you may not use this file except in compliance with the License.
cho45 5:65d4e94735b6 7 * You may obtain a copy of the License at
cho45 5:65d4e94735b6 8 *
cho45 5:65d4e94735b6 9 * http://www.apache.org/licenses/LICENSE-2.0
cho45 5:65d4e94735b6 10 *
cho45 5:65d4e94735b6 11 * Unless required by applicable law or agreed to in writing, software
cho45 5:65d4e94735b6 12 * distributed under the License is distributed on an "AS IS" BASIS,
cho45 5:65d4e94735b6 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
cho45 5:65d4e94735b6 14 * See the License for the specific language governing permissions and
cho45 5:65d4e94735b6 15 * limitations under the License.
cho45 5:65d4e94735b6 16 */
cho45 5:65d4e94735b6 17
cho45 5:65d4e94735b6 18 #include "HIDServiceBase.h"
cho45 5:65d4e94735b6 19 #include "keyboard.h"
cho45 7:b9270a37345b 20 #include "CircularBuffer.h"
cho45 5:65d4e94735b6 21
cho45 5:65d4e94735b6 22 /**
cho45 5:65d4e94735b6 23 * Report descriptor for a standard 101 keys keyboard, following the HID specification example:
cho45 5:65d4e94735b6 24 * - 8 bytes input report (1 byte for modifiers and 6 for keys)
cho45 5:65d4e94735b6 25 * - 1 byte output report (LEDs)
cho45 5:65d4e94735b6 26 */
cho45 59:2d6c0bff2151 27 const report_map_t KEYBOARD_REPORT_MAP = {
cho45 5:65d4e94735b6 28 USAGE_PAGE(1), 0x01, // Generic Desktop Ctrls
cho45 5:65d4e94735b6 29 USAGE(1), 0x06, // Keyboard
cho45 5:65d4e94735b6 30 COLLECTION(1), 0x01, // Application
cho45 86:e0fab77e669d 31 REPORT_ID(1), 0x01,
cho45 75:351d7ffe81d1 32 USAGE_PAGE(1), 0x07, // Kbrd/Keypad
cho45 75:351d7ffe81d1 33 USAGE_MINIMUM(1), 0xE0,
cho45 75:351d7ffe81d1 34 USAGE_MAXIMUM(1), 0xE7,
cho45 75:351d7ffe81d1 35 LOGICAL_MINIMUM(1), 0x00,
cho45 75:351d7ffe81d1 36 LOGICAL_MAXIMUM(1), 0x01,
cho45 75:351d7ffe81d1 37 REPORT_SIZE(1), 0x01, // 1 byte (Modifier)
cho45 75:351d7ffe81d1 38 REPORT_COUNT(1), 0x08,
cho45 75:351d7ffe81d1 39 INPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position
cho45 75:351d7ffe81d1 40
cho45 75:351d7ffe81d1 41 REPORT_COUNT(1), 0x01, // 1 byte (Reserved)
cho45 75:351d7ffe81d1 42 REPORT_SIZE(1), 0x08,
cho45 75:351d7ffe81d1 43 INPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position
cho45 75:351d7ffe81d1 44
cho45 75:351d7ffe81d1 45 REPORT_COUNT(1), 0x05, // 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana)
cho45 75:351d7ffe81d1 46 REPORT_SIZE(1), 0x01,
cho45 75:351d7ffe81d1 47 USAGE_PAGE(1), 0x08, // LEDs
cho45 75:351d7ffe81d1 48 USAGE_MINIMUM(1), 0x01, // Num Lock
cho45 75:351d7ffe81d1 49 USAGE_MAXIMUM(1), 0x05, // Kana
cho45 75:351d7ffe81d1 50 OUTPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
cho45 75:351d7ffe81d1 51
cho45 75:351d7ffe81d1 52 REPORT_COUNT(1), 0x01, // 3 bits (Padding)
cho45 75:351d7ffe81d1 53 REPORT_SIZE(1), 0x03,
cho45 75:351d7ffe81d1 54 OUTPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
cho45 75:351d7ffe81d1 55
cho45 75:351d7ffe81d1 56 REPORT_COUNT(1), 0x06, // 6 bytes (Keys)
cho45 75:351d7ffe81d1 57 REPORT_SIZE(1), 0x08,
cho45 75:351d7ffe81d1 58 LOGICAL_MINIMUM(1), 0x00,
cho45 75:351d7ffe81d1 59 LOGICAL_MAXIMUM(1), 0x65, // 101 keys
cho45 75:351d7ffe81d1 60 USAGE_PAGE(1), 0x07, // Kbrd/Keypad
cho45 75:351d7ffe81d1 61 USAGE_MINIMUM(1), 0x00,
cho45 75:351d7ffe81d1 62 USAGE_MAXIMUM(1), 0x65,
cho45 75:351d7ffe81d1 63 INPUT(1), 0x00, // Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position
cho45 75:351d7ffe81d1 64
cho45 86:e0fab77e669d 65 USAGE_PAGE(1), 0x0C, // Consumer
cho45 86:e0fab77e669d 66 USAGE(1), 0x00,
cho45 86:e0fab77e669d 67 COLLECTION(1), 0x02, // Logical
cho45 86:e0fab77e669d 68 REPORT_ID(1), 0x01,
cho45 86:e0fab77e669d 69 USAGE_MINIMUM(1), 0x00,
cho45 86:e0fab77e669d 70 USAGE_MAXIMUM(1), 0xFF,
cho45 86:e0fab77e669d 71 REPORT_COUNT(1), 0x01, // 1 byte
cho45 86:e0fab77e669d 72 REPORT_SIZE(1), 0x08,
cho45 86:e0fab77e669d 73 FEATURE(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
cho45 86:e0fab77e669d 74 END_COLLECTION(0),
cho45 5:65d4e94735b6 75 END_COLLECTION(0),
cho45 86:e0fab77e669d 76
cho45 86:e0fab77e669d 77 USAGE_PAGE(1), 0x0C,
cho45 86:e0fab77e669d 78 USAGE(1), 0x01,
cho45 86:e0fab77e669d 79 COLLECTION(1), 0x01,
cho45 86:e0fab77e669d 80 REPORT_ID(1), 0x03,
cho45 86:e0fab77e669d 81 REPORT_SIZE(1), 0x10,
cho45 86:e0fab77e669d 82 REPORT_COUNT(1), 0x01,
cho45 86:e0fab77e669d 83 LOGICAL_MINIMUM(1), 1,
cho45 86:e0fab77e669d 84 LOGICAL_MAXIMUM(2), 0xFF, 0x03,
cho45 86:e0fab77e669d 85 USAGE_MINIMUM(1), 1,
cho45 86:e0fab77e669d 86 USAGE_MAXIMUM(2), 0xFF, 0x03,
cho45 86:e0fab77e669d 87 INPUT(1), 0x60,
cho45 86:e0fab77e669d 88 END_COLLECTION(0),
cho45 86:e0fab77e669d 89 };
cho45 86:e0fab77e669d 90
cho45 86:e0fab77e669d 91 static const report_reference_t consumerInputReportReferenceData = { 3, INPUT_REPORT };
cho45 86:e0fab77e669d 92 static const GattAttribute consumerInputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&consumerInputReportReferenceData, 2, 2, false);
cho45 86:e0fab77e669d 93 static const GattAttribute * consumerInputReportDescriptors[] = {
cho45 86:e0fab77e669d 94 &consumerInputReportReferenceDescriptor,
cho45 5:65d4e94735b6 95 };
cho45 5:65d4e94735b6 96
cho45 75:351d7ffe81d1 97 class KeyboardService : public HIDServiceBase {
cho45 60:b899414e1d34 98
cho45 75:351d7ffe81d1 99 union InputReportData {
cho45 75:351d7ffe81d1 100 uint8_t raw[8];
cho45 75:351d7ffe81d1 101 struct {
cho45 75:351d7ffe81d1 102 uint8_t modifier;
cho45 75:351d7ffe81d1 103 uint8_t padding;
cho45 75:351d7ffe81d1 104 uint8_t keycode[6];
cho45 75:351d7ffe81d1 105 } data;
cho45 75:351d7ffe81d1 106 };
cho45 60:b899414e1d34 107
cho45 75:351d7ffe81d1 108 union OutputReportData {
cho45 75:351d7ffe81d1 109 uint8_t raw[1];
cho45 75:351d7ffe81d1 110 };
cho45 75:351d7ffe81d1 111
cho45 75:351d7ffe81d1 112 union FeatureReportData {
cho45 75:351d7ffe81d1 113 uint8_t raw[1];
cho45 75:351d7ffe81d1 114 };
cho45 7:b9270a37345b 115
cho45 86:e0fab77e669d 116 union ConsumerInputReportData {
cho45 86:e0fab77e669d 117 uint8_t raw[2];
cho45 86:e0fab77e669d 118 uint16_t key;
cho45 86:e0fab77e669d 119 };
cho45 86:e0fab77e669d 120
cho45 81:fbe7358e38a4 121 /**
cho45 81:fbe7358e38a4 122 * Boot Protocol
cho45 81:fbe7358e38a4 123 * Share input/output report with Report Protocol for memmory saving
cho45 81:fbe7358e38a4 124 */
cho45 79:0095bfb18c57 125 GattCharacteristic bootKeyboardInputReportCharacteristic;
cho45 79:0095bfb18c57 126 GattCharacteristic bootKeyboardOutputReportCharacteristic;
cho45 86:e0fab77e669d 127 GattCharacteristic consumerInputReportCharacteristic;
cho45 79:0095bfb18c57 128
cho45 9:d1daefbf1fbd 129 InputReportData inputReportDataPublished;
cho45 7:b9270a37345b 130 InputReportData inputReportData;
cho45 5:65d4e94735b6 131
cho45 60:b899414e1d34 132 // 5ms ごとのスイッチ判定・20ms ごとの送信
cho45 60:b899414e1d34 133 // 人間の連打限界を16press/secとし keydown/keyup それぞれでレポートを送ることを考えると
cho45 60:b899414e1d34 134 // 32report/sec = 31msec で、限界で連打しても20msごとの送信にまにあう
cho45 60:b899414e1d34 135 // ただし上記は1キーに対してであり、複数キーを全力で押すとキューに溜まることがある
cho45 60:b899414e1d34 136 // 実際にカウントして測ってみたところ、どんなに乱暴に連打しても8ぐらいまでしかいかない
cho45 60:b899414e1d34 137 CircularBuffer<InputReportData, 8, uint8_t> inputReportBuffer;
cho45 7:b9270a37345b 138 InputReportData inputReportDataSending;
cho45 75:351d7ffe81d1 139 OutputReportData outputReportData;
cho45 75:351d7ffe81d1 140 FeatureReportData featureReportData;
cho45 7:b9270a37345b 141 bool isSending;
cho45 7:b9270a37345b 142
cho45 86:e0fab77e669d 143 ConsumerInputReportData consumerInputReportData;
cho45 86:e0fab77e669d 144 bool hasPendingConsumerInputReport;
cho45 86:e0fab77e669d 145
cho45 5:65d4e94735b6 146 static const uint8_t MODIFIER_LEFT_CONTROL = 1<<0;
cho45 5:65d4e94735b6 147 static const uint8_t MODIFIER_LEFT_SHIFT = 1<<1;
cho45 5:65d4e94735b6 148 static const uint8_t MODIFIER_LEFT_ALT = 1<<2;
cho45 5:65d4e94735b6 149 static const uint8_t MODIFIER_LEFT_GUI = 1<<3;
cho45 5:65d4e94735b6 150 static const uint8_t MODIFIER_RIGHT_CONTROL = 1<<4;
cho45 5:65d4e94735b6 151 static const uint8_t MODIFIER_RIGHT_SHIFT = 1<<5;
cho45 5:65d4e94735b6 152 static const uint8_t MODIFIER_RIGHT_ALT = 1<<6;
cho45 5:65d4e94735b6 153 static const uint8_t MODIFIER_RIGHT_GUI = 1<<7;
cho45 5:65d4e94735b6 154 public:
cho45 45:f4be69c936f6 155 bool sendAvailable;
cho45 60:b899414e1d34 156 uint8_t bufferCount;
cho45 45:f4be69c936f6 157
cho45 5:65d4e94735b6 158 KeyboardService(BLE& _ble) :
cho45 5:65d4e94735b6 159 HIDServiceBase(
cho45 5:65d4e94735b6 160 _ble,
cho45 5:65d4e94735b6 161 KEYBOARD_REPORT_MAP,
cho45 5:65d4e94735b6 162 sizeof(KEYBOARD_REPORT_MAP),
cho45 9:d1daefbf1fbd 163 inputReport = inputReportDataPublished.raw,
cho45 5:65d4e94735b6 164 outputReport = outputReportData.raw,
cho45 75:351d7ffe81d1 165 featureReport = featureReportData.raw,
cho45 5:65d4e94735b6 166 inputReportLength = sizeof(inputReportData),
cho45 5:65d4e94735b6 167 outputReportLength = sizeof(outputReportData),
cho45 82:af52d37b1946 168 featureReportLength = sizeof(featureReportData)
cho45 7:b9270a37345b 169 ),
cho45 83:2e940d154f8b 170 bootKeyboardInputReportCharacteristic(
cho45 83:2e940d154f8b 171 GattCharacteristic::UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR,
cho45 79:0095bfb18c57 172 (uint8_t *)inputReport, inputReportLength, inputReportLength,
cho45 79:0095bfb18c57 173 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
cho45 79:0095bfb18c57 174 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
cho45 79:0095bfb18c57 175 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
cho45 79:0095bfb18c57 176 ),
cho45 79:0095bfb18c57 177
cho45 83:2e940d154f8b 178 bootKeyboardOutputReportCharacteristic(
cho45 83:2e940d154f8b 179 GattCharacteristic::UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR,
cho45 79:0095bfb18c57 180 (uint8_t *)outputReport, outputReportLength, outputReportLength,
cho45 79:0095bfb18c57 181 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
cho45 79:0095bfb18c57 182 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
cho45 79:0095bfb18c57 183 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
cho45 79:0095bfb18c57 184 ),
cho45 86:e0fab77e669d 185 consumerInputReportCharacteristic(
cho45 86:e0fab77e669d 186 GattCharacteristic::UUID_REPORT_CHAR,
cho45 86:e0fab77e669d 187 (uint8_t *)&consumerInputReportData, sizeof(consumerInputReportData), sizeof(consumerInputReportData),
cho45 86:e0fab77e669d 188 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
cho45 86:e0fab77e669d 189 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
cho45 86:e0fab77e669d 190 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
cho45 86:e0fab77e669d 191 const_cast<GattAttribute**>(consumerInputReportDescriptors), 1
cho45 86:e0fab77e669d 192 ),
cho45 45:f4be69c936f6 193 isSending(false),
cho45 86:e0fab77e669d 194 hasPendingConsumerInputReport(false),
cho45 60:b899414e1d34 195 sendAvailable(false),
cho45 60:b899414e1d34 196 bufferCount(0)
cho45 5:65d4e94735b6 197 {
cho45 6:f1c3ea8bc850 198 for (int i = 0; i < 8; i++) {
cho45 6:f1c3ea8bc850 199 inputReportData.raw[i] = 0;
cho45 6:f1c3ea8bc850 200 }
cho45 6:f1c3ea8bc850 201 outputReportData.raw[0] = 0;
cho45 7:b9270a37345b 202
cho45 7:b9270a37345b 203 inputReportBuffer.reset();
cho45 5:65d4e94735b6 204 }
cho45 5:65d4e94735b6 205
cho45 79:0095bfb18c57 206 virtual void addExtraCharacteristics(GattCharacteristic** characteristics, uint8_t& charIndex) {
cho45 79:0095bfb18c57 207 DEBUG_PRINTF_BLE("addExtraCharacteristics %d\r\n", charIndex);
cho45 79:0095bfb18c57 208 characteristics[charIndex++] = &bootKeyboardInputReportCharacteristic;
cho45 79:0095bfb18c57 209 characteristics[charIndex++] = &bootKeyboardOutputReportCharacteristic;
cho45 86:e0fab77e669d 210 characteristics[charIndex++] = &consumerInputReportCharacteristic;
cho45 79:0095bfb18c57 211 }
cho45 79:0095bfb18c57 212
cho45 79:0095bfb18c57 213 virtual ble_error_t send(const report_t report) {
cho45 79:0095bfb18c57 214 if (protocolMode == REPORT_PROTOCOL) { // this is default
cho45 79:0095bfb18c57 215 return ble.gattServer().write(
cho45 80:3beb0293b384 216 inputReportCharacteristic.getValueHandle(),
cho45 79:0095bfb18c57 217 report,
cho45 79:0095bfb18c57 218 inputReportLength
cho45 79:0095bfb18c57 219 );
cho45 79:0095bfb18c57 220 } else {
cho45 79:0095bfb18c57 221 return ble.gattServer().write(
cho45 80:3beb0293b384 222 bootKeyboardInputReportCharacteristic.getValueHandle(),
cho45 79:0095bfb18c57 223 report,
cho45 79:0095bfb18c57 224 inputReportLength
cho45 79:0095bfb18c57 225 );
cho45 79:0095bfb18c57 226 }
cho45 79:0095bfb18c57 227 }
cho45 79:0095bfb18c57 228
cho45 48:d6938de02f62 229 void appendReportData(const uint8_t keycode) {
cho45 5:65d4e94735b6 230 uint8_t modifier = toModifierBit(keycode);
cho45 5:65d4e94735b6 231 if (modifier) {
cho45 5:65d4e94735b6 232 inputReportData.data.modifier |= modifier;
cho45 5:65d4e94735b6 233 return;
cho45 5:65d4e94735b6 234 }
cho45 5:65d4e94735b6 235
cho45 5:65d4e94735b6 236
cho45 5:65d4e94735b6 237 for (int i = 0; i < 6; i++) {
cho45 5:65d4e94735b6 238 if (inputReportData.data.keycode[i] == 0) {
cho45 5:65d4e94735b6 239 inputReportData.data.keycode[i] = keycode;
cho45 5:65d4e94735b6 240 return;
cho45 5:65d4e94735b6 241 }
cho45 5:65d4e94735b6 242 }
cho45 5:65d4e94735b6 243
cho45 5:65d4e94735b6 244 // TODO: report data is full
cho45 5:65d4e94735b6 245 }
cho45 5:65d4e94735b6 246
cho45 48:d6938de02f62 247 void deleteReportData(const uint8_t keycode) {
cho45 5:65d4e94735b6 248 uint8_t modifier = toModifierBit(keycode);
cho45 5:65d4e94735b6 249 if (modifier) {
cho45 5:65d4e94735b6 250 inputReportData.data.modifier &= ~modifier;
cho45 5:65d4e94735b6 251 return;
cho45 5:65d4e94735b6 252 }
cho45 5:65d4e94735b6 253
cho45 5:65d4e94735b6 254 for (int i = 0; i < 6; i++) {
cho45 5:65d4e94735b6 255 if (inputReportData.data.keycode[i] == keycode) {
cho45 5:65d4e94735b6 256 inputReportData.data.keycode[i] = 0;
cho45 5:65d4e94735b6 257 return;
cho45 5:65d4e94735b6 258 }
cho45 5:65d4e94735b6 259 }
cho45 5:65d4e94735b6 260 }
cho45 5:65d4e94735b6 261
cho45 86:e0fab77e669d 262 void pressConsumerKey(const uint16_t key) {
cho45 86:e0fab77e669d 263 consumerInputReportData.key = key;
cho45 86:e0fab77e669d 264 hasPendingConsumerInputReport = true;
cho45 86:e0fab77e669d 265 sendAvailable = true;
cho45 86:e0fab77e669d 266 }
cho45 86:e0fab77e669d 267
cho45 86:e0fab77e669d 268 void releaseConsumerKey() {
cho45 86:e0fab77e669d 269 consumerInputReportData.key = 0;
cho45 86:e0fab77e669d 270 hasPendingConsumerInputReport = true;
cho45 86:e0fab77e669d 271 sendAvailable = true;
cho45 86:e0fab77e669d 272 }
cho45 86:e0fab77e669d 273
cho45 9:d1daefbf1fbd 274 void queueCurrentReportData() {
cho45 80:3beb0293b384 275 DEBUG_PRINTF_BLE("Q %d\r\n", bufferCount);
cho45 60:b899414e1d34 276 bufferCount++;
cho45 9:d1daefbf1fbd 277 inputReportBuffer.push(inputReportData);
cho45 82:af52d37b1946 278 sendAvailable = true;
cho45 9:d1daefbf1fbd 279 }
cho45 9:d1daefbf1fbd 280
cho45 48:d6938de02f62 281 uint8_t toModifierBit(const uint8_t keycode) const {
cho45 5:65d4e94735b6 282 switch (keycode) {
cho45 5:65d4e94735b6 283 case KEY_LeftControl: return MODIFIER_LEFT_CONTROL;
cho45 5:65d4e94735b6 284 case KEY_LeftShift: return MODIFIER_LEFT_SHIFT;
cho45 5:65d4e94735b6 285 case KEY_LeftAlt: return MODIFIER_LEFT_ALT;
cho45 5:65d4e94735b6 286 case KEY_LeftGUI: return MODIFIER_LEFT_GUI;
cho45 5:65d4e94735b6 287 case KEY_RightControl: return MODIFIER_RIGHT_CONTROL;
cho45 5:65d4e94735b6 288 case KEY_RightShift: return MODIFIER_RIGHT_SHIFT;
cho45 5:65d4e94735b6 289 case KEY_RightAlt: return MODIFIER_RIGHT_ALT;
cho45 5:65d4e94735b6 290 case KEY_RightGUI: return MODIFIER_RIGHT_GUI;
cho45 5:65d4e94735b6 291 }
cho45 5:65d4e94735b6 292 return 0;
cho45 5:65d4e94735b6 293 }
cho45 5:65d4e94735b6 294
cho45 5:65d4e94735b6 295 bool isKeyPressed() {
cho45 5:65d4e94735b6 296 for (int i = 0; i < 8; i++) {
cho45 5:65d4e94735b6 297 if (inputReportData.raw[i]) {
cho45 5:65d4e94735b6 298 return 1;
cho45 5:65d4e94735b6 299 }
cho45 5:65d4e94735b6 300 }
cho45 5:65d4e94735b6 301 return 0;
cho45 5:65d4e94735b6 302 }
cho45 45:f4be69c936f6 303
cho45 45:f4be69c936f6 304 void processSend() {
cho45 45:f4be69c936f6 305 if (!sendAvailable) {
cho45 45:f4be69c936f6 306 return;
cho45 45:f4be69c936f6 307 }
cho45 45:f4be69c936f6 308 sendAvailable = false;
cho45 86:e0fab77e669d 309
cho45 86:e0fab77e669d 310 if (hasPendingConsumerInputReport) {
cho45 86:e0fab77e669d 311 ble.gattServer().write(
cho45 86:e0fab77e669d 312 consumerInputReportCharacteristic.getValueHandle(),
cho45 86:e0fab77e669d 313 (uint8_t*)&consumerInputReportData,
cho45 86:e0fab77e669d 314 sizeof(consumerInputReportData)
cho45 86:e0fab77e669d 315 );
cho45 86:e0fab77e669d 316 hasPendingConsumerInputReport = false;
cho45 86:e0fab77e669d 317 }
cho45 45:f4be69c936f6 318
cho45 45:f4be69c936f6 319 // isSending の場合現在送信中の report があり、再送中である可能性がある
cho45 45:f4be69c936f6 320 // そうではない場合のみ queue から pop して新しく send する
cho45 9:d1daefbf1fbd 321 if (!isSending) {
cho45 9:d1daefbf1fbd 322 if (!inputReportBuffer.pop(inputReportDataSending)) {
cho45 51:d9297f8a60b7 323 // 送るデータがないなら送信をやめる
cho45 51:d9297f8a60b7 324 return;
cho45 7:b9270a37345b 325 }
cho45 60:b899414e1d34 326 bufferCount--;
cho45 7:b9270a37345b 327 }
cho45 7:b9270a37345b 328
cho45 7:b9270a37345b 329 static uint8_t busyCount = 0;
cho45 7:b9270a37345b 330 isSending = true;
cho45 80:3beb0293b384 331 ble_error_t error = send(inputReportDataSending.raw);
cho45 5:65d4e94735b6 332 if (error == BLE_STACK_BUSY) {
cho45 7:b9270a37345b 333 if (busyCount++ > 10) {
cho45 80:3beb0293b384 334 DEBUG_PRINTF_BLE("BLE_STACK_BUSY\r\n");
cho45 7:b9270a37345b 335 busyCount = 0;
cho45 82:af52d37b1946 336 sendAvailable = false;
cho45 7:b9270a37345b 337 }
cho45 5:65d4e94735b6 338 // retry after
cho45 5:65d4e94735b6 339 return;
cho45 5:65d4e94735b6 340 }
cho45 7:b9270a37345b 341 isSending = false;
cho45 7:b9270a37345b 342 }
cho45 5:65d4e94735b6 343
cho45 7:b9270a37345b 344 virtual void onDataSent(unsigned int count) {
cho45 82:af52d37b1946 345 sendAvailable = true;
cho45 5:65d4e94735b6 346 }
cho45 79:0095bfb18c57 347
cho45 79:0095bfb18c57 348 virtual void onDataWritten(const GattWriteCallbackParams *params) {
cho45 79:0095bfb18c57 349 if (params->handle == inputReportCharacteristic.getValueHandle()) {
cho45 79:0095bfb18c57 350 DEBUG_PRINTF_BLE_INTERRUPT("onDataWritten: inputReport %d bytes\r\n", params->len);
cho45 79:0095bfb18c57 351 } else
cho45 79:0095bfb18c57 352 if (params->handle == outputReportCharacteristic.getValueHandle()) {
cho45 79:0095bfb18c57 353 DEBUG_PRINTF_BLE_INTERRUPT("onDataWritten: outputReport %d bytes\r\n", params->len);
cho45 79:0095bfb18c57 354 } else
cho45 79:0095bfb18c57 355 if (params->handle == featureReportCharacteristic.getValueHandle()) {
cho45 79:0095bfb18c57 356 DEBUG_PRINTF_BLE_INTERRUPT("onDataWritten: featureReport %d bytes\r\n", params->len);
cho45 79:0095bfb18c57 357 } else
cho45 79:0095bfb18c57 358 if (params->handle == protocolModeCharacteristic.getValueHandle()) {
cho45 79:0095bfb18c57 359 DEBUG_PRINTF_BLE_INTERRUPT("onDataWritten: protocolMode %d bytes %d\r\n", params->len, params->data[0]);
cho45 79:0095bfb18c57 360 protocolMode = params->data[0];
cho45 79:0095bfb18c57 361 }
cho45 79:0095bfb18c57 362 }
cho45 5:65d4e94735b6 363 };
cho45 5:65d4e94735b6 364
cho45 5:65d4e94735b6 365