back up of work during May 2019

Dependencies:   microbit

Committer:
tht216
Date:
Wed Jun 05 15:21:14 2019 +0000
Branch:
class_implmentation
Revision:
6:f372773ad32f
Parent:
1:c840c2b6f490
TODO:; 1. multi keypresses; 2. integration

Who changed what in which revision?

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