BLE switch interface with GROVE joystic for micro:bit http://mahoro-ba.net/e2073.html

Dependencies:   microbit

Committer:
masakjm
Date:
Tue Apr 09 19:37:57 2019 +0000
Revision:
21:961da341b755
Parent:
0:28fb3e9ef81a
Added setting function of installation direction.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
masakjm 0:28fb3e9ef81a 1 /* mbed Microcontroller Library
masakjm 0:28fb3e9ef81a 2 * Copyright (c) 2015 ARM Limited
masakjm 0:28fb3e9ef81a 3 *
masakjm 0:28fb3e9ef81a 4 * Licensed under the Apache License, Version 2.0 (the "License");
masakjm 0:28fb3e9ef81a 5 * you may not use this file except in compliance with the License.
masakjm 0:28fb3e9ef81a 6 * You may obtain a copy of the License at
masakjm 0:28fb3e9ef81a 7 *
masakjm 0:28fb3e9ef81a 8 * http://www.apache.org/licenses/LICENSE-2.0
masakjm 0:28fb3e9ef81a 9 *
masakjm 0:28fb3e9ef81a 10 * Unless required by applicable law or agreed to in writing, software
masakjm 0:28fb3e9ef81a 11 * distributed under the License is distributed on an "AS IS" BASIS,
masakjm 0:28fb3e9ef81a 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
masakjm 0:28fb3e9ef81a 13 * See the License for the specific language governing permissions and
masakjm 0:28fb3e9ef81a 14 * limitations under the License.
masakjm 0:28fb3e9ef81a 15 */
masakjm 0:28fb3e9ef81a 16
masakjm 0:28fb3e9ef81a 17 #include "mbed.h"
masakjm 0:28fb3e9ef81a 18 #include "HIDServiceBase.h"
masakjm 0:28fb3e9ef81a 19
masakjm 0:28fb3e9ef81a 20 HIDServiceBase::HIDServiceBase(BLE &_ble,
masakjm 0:28fb3e9ef81a 21 report_map_t reportMap,
masakjm 0:28fb3e9ef81a 22 uint8_t reportMapSize,
masakjm 0:28fb3e9ef81a 23 report_t inputReport,
masakjm 0:28fb3e9ef81a 24 report_t outputReport,
masakjm 0:28fb3e9ef81a 25 report_t featureReport,
masakjm 0:28fb3e9ef81a 26 uint8_t inputReportLength,
masakjm 0:28fb3e9ef81a 27 uint8_t outputReportLength,
masakjm 0:28fb3e9ef81a 28 uint8_t featureReportLength,
masakjm 0:28fb3e9ef81a 29 uint8_t inputReportTickerDelay) :
masakjm 0:28fb3e9ef81a 30 ble(_ble),
masakjm 0:28fb3e9ef81a 31 connected (false),
masakjm 0:28fb3e9ef81a 32 reportMapLength(reportMapSize),
masakjm 0:28fb3e9ef81a 33
masakjm 0:28fb3e9ef81a 34 inputReport(inputReport),
masakjm 0:28fb3e9ef81a 35 outputReport(outputReport),
masakjm 0:28fb3e9ef81a 36 featureReport(featureReport),
masakjm 0:28fb3e9ef81a 37
masakjm 0:28fb3e9ef81a 38 inputReportLength(inputReportLength),
masakjm 0:28fb3e9ef81a 39 outputReportLength(outputReportLength),
masakjm 0:28fb3e9ef81a 40 featureReportLength(featureReportLength),
masakjm 0:28fb3e9ef81a 41
masakjm 0:28fb3e9ef81a 42 protocolMode(REPORT_PROTOCOL),
masakjm 0:28fb3e9ef81a 43
masakjm 0:28fb3e9ef81a 44 inputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE,
masakjm 0:28fb3e9ef81a 45 (uint8_t *)&inputReportReferenceData, 2, 2),
masakjm 0:28fb3e9ef81a 46 outputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE,
masakjm 0:28fb3e9ef81a 47 (uint8_t *)&outputReportReferenceData, 2, 2),
masakjm 0:28fb3e9ef81a 48 featureReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE,
masakjm 0:28fb3e9ef81a 49 (uint8_t *)&featureReportReferenceData, 2, 2),
masakjm 0:28fb3e9ef81a 50
masakjm 0:28fb3e9ef81a 51 protocolModeCharacteristic(GattCharacteristic::UUID_PROTOCOL_MODE_CHAR, &protocolMode, 1, 1,
masakjm 0:28fb3e9ef81a 52 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
masakjm 0:28fb3e9ef81a 53 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
masakjm 0:28fb3e9ef81a 54
masakjm 0:28fb3e9ef81a 55 inputReportCharacteristic(GattCharacteristic::UUID_REPORT_CHAR,
masakjm 0:28fb3e9ef81a 56 (uint8_t *)inputReport, inputReportLength, inputReportLength,
masakjm 0:28fb3e9ef81a 57 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
masakjm 0:28fb3e9ef81a 58 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
masakjm 0:28fb3e9ef81a 59 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
masakjm 0:28fb3e9ef81a 60 inputReportDescriptors(), 1),
masakjm 0:28fb3e9ef81a 61
masakjm 0:28fb3e9ef81a 62 outputReportCharacteristic(GattCharacteristic::UUID_REPORT_CHAR,
masakjm 0:28fb3e9ef81a 63 (uint8_t *)outputReport, outputReportLength, outputReportLength,
masakjm 0:28fb3e9ef81a 64 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
masakjm 0:28fb3e9ef81a 65 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
masakjm 0:28fb3e9ef81a 66 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
masakjm 0:28fb3e9ef81a 67 outputReportDescriptors(), 1),
masakjm 0:28fb3e9ef81a 68
masakjm 0:28fb3e9ef81a 69 featureReportCharacteristic(GattCharacteristic::UUID_REPORT_CHAR,
masakjm 0:28fb3e9ef81a 70 (uint8_t *)featureReport, featureReportLength, featureReportLength,
masakjm 0:28fb3e9ef81a 71 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
masakjm 0:28fb3e9ef81a 72 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
masakjm 0:28fb3e9ef81a 73 featureReportDescriptors(), 1),
masakjm 0:28fb3e9ef81a 74
masakjm 0:28fb3e9ef81a 75 /*
masakjm 0:28fb3e9ef81a 76 * We need to set reportMap content as const, in order to let the compiler put it into flash
masakjm 0:28fb3e9ef81a 77 * instead of RAM. The characteristic is read-only so it won't be written, but
masakjm 0:28fb3e9ef81a 78 * GattCharacteristic constructor takes non-const arguments only. Hence the cast.
masakjm 0:28fb3e9ef81a 79 */
masakjm 0:28fb3e9ef81a 80 reportMapCharacteristic(GattCharacteristic::UUID_REPORT_MAP_CHAR,
masakjm 0:28fb3e9ef81a 81 const_cast<uint8_t*>(reportMap), reportMapLength, reportMapLength,
masakjm 0:28fb3e9ef81a 82 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
masakjm 0:28fb3e9ef81a 83
masakjm 0:28fb3e9ef81a 84 HIDInformationCharacteristic(GattCharacteristic::UUID_HID_INFORMATION_CHAR, HIDInformation()),
masakjm 0:28fb3e9ef81a 85 HIDControlPointCharacteristic(GattCharacteristic::UUID_HID_CONTROL_POINT_CHAR,
masakjm 0:28fb3e9ef81a 86 &controlPointCommand, 1, 1,
masakjm 0:28fb3e9ef81a 87 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
masakjm 0:28fb3e9ef81a 88
masakjm 0:28fb3e9ef81a 89 reportTickerDelay(inputReportTickerDelay),
masakjm 0:28fb3e9ef81a 90 reportTickerIsActive(false)
masakjm 0:28fb3e9ef81a 91 {
masakjm 0:28fb3e9ef81a 92 static GattCharacteristic *characteristics[] = {
masakjm 0:28fb3e9ef81a 93 &HIDInformationCharacteristic,
masakjm 0:28fb3e9ef81a 94 &reportMapCharacteristic,
masakjm 0:28fb3e9ef81a 95 &protocolModeCharacteristic,
masakjm 0:28fb3e9ef81a 96 &HIDControlPointCharacteristic,
masakjm 0:28fb3e9ef81a 97 NULL,
masakjm 0:28fb3e9ef81a 98 NULL,
masakjm 0:28fb3e9ef81a 99 NULL,
masakjm 0:28fb3e9ef81a 100 NULL,
masakjm 0:28fb3e9ef81a 101 NULL
masakjm 0:28fb3e9ef81a 102 };
masakjm 0:28fb3e9ef81a 103
masakjm 0:28fb3e9ef81a 104 unsigned int charIndex = 4;
masakjm 0:28fb3e9ef81a 105 /*
masakjm 0:28fb3e9ef81a 106 * Report characteristics are optional, and depend on the reportMap descriptor
masakjm 0:28fb3e9ef81a 107 * Note: at least one should be present, but we don't check that at the moment.
masakjm 0:28fb3e9ef81a 108 */
masakjm 0:28fb3e9ef81a 109 if (inputReportLength)
masakjm 0:28fb3e9ef81a 110 characteristics[charIndex++] = &inputReportCharacteristic;
masakjm 0:28fb3e9ef81a 111 if (outputReportLength)
masakjm 0:28fb3e9ef81a 112 characteristics[charIndex++] = &outputReportCharacteristic;
masakjm 0:28fb3e9ef81a 113 if (featureReportLength)
masakjm 0:28fb3e9ef81a 114 characteristics[charIndex++] = &featureReportCharacteristic;
masakjm 0:28fb3e9ef81a 115
masakjm 0:28fb3e9ef81a 116 /* TODO: let children add some more characteristics, namely boot keyboard and mouse (They are
masakjm 0:28fb3e9ef81a 117 * mandatory as per HIDS spec.) Ex:
masakjm 0:28fb3e9ef81a 118 *
masakjm 0:28fb3e9ef81a 119 * addExtraCharacteristics(characteristics, int& charIndex);
masakjm 0:28fb3e9ef81a 120 */
masakjm 0:28fb3e9ef81a 121
masakjm 0:28fb3e9ef81a 122 GattService service(GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
masakjm 0:28fb3e9ef81a 123 characteristics, charIndex);
masakjm 0:28fb3e9ef81a 124
masakjm 0:28fb3e9ef81a 125 ble.gattServer().addService(service);
masakjm 0:28fb3e9ef81a 126
masakjm 0:28fb3e9ef81a 127 ble.gap().onConnection(this, &HIDServiceBase::onConnection);
masakjm 0:28fb3e9ef81a 128 ble.gap().onDisconnection(this, &HIDServiceBase::onDisconnection);
masakjm 0:28fb3e9ef81a 129
masakjm 0:28fb3e9ef81a 130 ble.gattServer().onDataSent(this, &HIDServiceBase::onDataSent);
masakjm 0:28fb3e9ef81a 131
masakjm 0:28fb3e9ef81a 132 /*
masakjm 0:28fb3e9ef81a 133 * Change preferred connection params, in order to optimize the notification frequency. Most
masakjm 0:28fb3e9ef81a 134 * OSes seem to respect this, even though they are not required to.
masakjm 0:28fb3e9ef81a 135 *
masakjm 0:28fb3e9ef81a 136 * Some OSes don't handle reconnection well, at the moment, so we set the maximum possible
masakjm 0:28fb3e9ef81a 137 * timeout, 32 seconds
masakjm 0:28fb3e9ef81a 138 */
masakjm 0:28fb3e9ef81a 139 uint16_t minInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(reportTickerDelay / 2);
masakjm 0:28fb3e9ef81a 140 if (minInterval < 6)
masakjm 0:28fb3e9ef81a 141 minInterval = 6;
masakjm 0:28fb3e9ef81a 142 uint16_t maxInterval = minInterval * 2;
masakjm 0:28fb3e9ef81a 143 Gap::ConnectionParams_t params = {minInterval, maxInterval, 0, 3200};
masakjm 0:28fb3e9ef81a 144
masakjm 0:28fb3e9ef81a 145 ble.gap().setPreferredConnectionParams(&params);
masakjm 0:28fb3e9ef81a 146
masakjm 0:28fb3e9ef81a 147 SecurityManager::SecurityMode_t securityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
masakjm 0:28fb3e9ef81a 148 protocolModeCharacteristic.requireSecurity(securityMode);
masakjm 0:28fb3e9ef81a 149 reportMapCharacteristic.requireSecurity(securityMode);
masakjm 0:28fb3e9ef81a 150 inputReportCharacteristic.requireSecurity(securityMode);
masakjm 0:28fb3e9ef81a 151 outputReportCharacteristic.requireSecurity(securityMode);
masakjm 0:28fb3e9ef81a 152 featureReportCharacteristic.requireSecurity(securityMode);
masakjm 0:28fb3e9ef81a 153 }
masakjm 0:28fb3e9ef81a 154
masakjm 0:28fb3e9ef81a 155 void HIDServiceBase::startReportTicker(void) {
masakjm 0:28fb3e9ef81a 156 if (reportTickerIsActive)
masakjm 0:28fb3e9ef81a 157 return;
masakjm 0:28fb3e9ef81a 158 reportTicker.attach_us(this, &HIDServiceBase::sendCallback, reportTickerDelay * 1000);
masakjm 0:28fb3e9ef81a 159 reportTickerIsActive = true;
masakjm 0:28fb3e9ef81a 160 }
masakjm 0:28fb3e9ef81a 161
masakjm 0:28fb3e9ef81a 162 void HIDServiceBase::stopReportTicker(void) {
masakjm 0:28fb3e9ef81a 163 reportTicker.detach();
masakjm 0:28fb3e9ef81a 164 reportTickerIsActive = false;
masakjm 0:28fb3e9ef81a 165 }
masakjm 0:28fb3e9ef81a 166
masakjm 0:28fb3e9ef81a 167 void HIDServiceBase::onDataSent(unsigned count) {
masakjm 0:28fb3e9ef81a 168 startReportTicker();
masakjm 0:28fb3e9ef81a 169 }
masakjm 0:28fb3e9ef81a 170
masakjm 0:28fb3e9ef81a 171 GattAttribute** HIDServiceBase::inputReportDescriptors() {
masakjm 0:28fb3e9ef81a 172 inputReportReferenceData.ID = 0;
masakjm 0:28fb3e9ef81a 173 inputReportReferenceData.type = INPUT_REPORT;
masakjm 0:28fb3e9ef81a 174
masakjm 0:28fb3e9ef81a 175 static GattAttribute * descs[] = {
masakjm 0:28fb3e9ef81a 176 &inputReportReferenceDescriptor,
masakjm 0:28fb3e9ef81a 177 };
masakjm 0:28fb3e9ef81a 178 return descs;
masakjm 0:28fb3e9ef81a 179 }
masakjm 0:28fb3e9ef81a 180
masakjm 0:28fb3e9ef81a 181 GattAttribute** HIDServiceBase::outputReportDescriptors() {
masakjm 0:28fb3e9ef81a 182 outputReportReferenceData.ID = 0;
masakjm 0:28fb3e9ef81a 183 outputReportReferenceData.type = OUTPUT_REPORT;
masakjm 0:28fb3e9ef81a 184
masakjm 0:28fb3e9ef81a 185 static GattAttribute * descs[] = {
masakjm 0:28fb3e9ef81a 186 &outputReportReferenceDescriptor,
masakjm 0:28fb3e9ef81a 187 };
masakjm 0:28fb3e9ef81a 188 return descs;
masakjm 0:28fb3e9ef81a 189 }
masakjm 0:28fb3e9ef81a 190
masakjm 0:28fb3e9ef81a 191 GattAttribute** HIDServiceBase::featureReportDescriptors() {
masakjm 0:28fb3e9ef81a 192 featureReportReferenceData.ID = 0;
masakjm 0:28fb3e9ef81a 193 featureReportReferenceData.type = FEATURE_REPORT;
masakjm 0:28fb3e9ef81a 194
masakjm 0:28fb3e9ef81a 195 static GattAttribute * descs[] = {
masakjm 0:28fb3e9ef81a 196 &featureReportReferenceDescriptor,
masakjm 0:28fb3e9ef81a 197 };
masakjm 0:28fb3e9ef81a 198 return descs;
masakjm 0:28fb3e9ef81a 199 }
masakjm 0:28fb3e9ef81a 200
masakjm 0:28fb3e9ef81a 201
masakjm 0:28fb3e9ef81a 202 HID_information_t* HIDServiceBase::HIDInformation() {
masakjm 0:28fb3e9ef81a 203 static HID_information_t info = {HID_VERSION_1_11, 0x00, 0x03};
masakjm 0:28fb3e9ef81a 204 printf("read hid information\n");
masakjm 0:28fb3e9ef81a 205
masakjm 0:28fb3e9ef81a 206 return &info;
masakjm 0:28fb3e9ef81a 207 }
masakjm 0:28fb3e9ef81a 208
masakjm 0:28fb3e9ef81a 209 ble_error_t HIDServiceBase::send(const report_t report) {
masakjm 0:28fb3e9ef81a 210 return ble.gattServer().write(inputReportCharacteristic.getValueHandle(),
masakjm 0:28fb3e9ef81a 211 report,
masakjm 0:28fb3e9ef81a 212 inputReportLength);
masakjm 0:28fb3e9ef81a 213 }
masakjm 0:28fb3e9ef81a 214
masakjm 0:28fb3e9ef81a 215 ble_error_t HIDServiceBase::read(report_t report) {
masakjm 0:28fb3e9ef81a 216 // TODO. For the time being, we'll just have HID input reports...
masakjm 0:28fb3e9ef81a 217 printf("read not implemented\n");
masakjm 0:28fb3e9ef81a 218 return BLE_ERROR_NOT_IMPLEMENTED;
masakjm 0:28fb3e9ef81a 219 }
masakjm 0:28fb3e9ef81a 220
masakjm 0:28fb3e9ef81a 221 void HIDServiceBase::onConnection(const Gap::ConnectionCallbackParams_t *params)
masakjm 0:28fb3e9ef81a 222 {
masakjm 0:28fb3e9ef81a 223 this->connected = true;
masakjm 0:28fb3e9ef81a 224 }
masakjm 0:28fb3e9ef81a 225
masakjm 0:28fb3e9ef81a 226 void HIDServiceBase::onDisconnection(const Gap::DisconnectionCallbackParams_t *params)
masakjm 0:28fb3e9ef81a 227 {
masakjm 0:28fb3e9ef81a 228 this->connected = false;
masakjm 0:28fb3e9ef81a 229 }
masakjm 0:28fb3e9ef81a 230