Dependencies:   microbit

Committer:
xx316
Date:
Wed Jun 12 15:21:01 2019 +0000
Revision:
1:032b96b05e51
for demo on Thursday;

Who changed what in which revision?

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