back up of work during May 2019

Dependencies:   microbit

Committer:
xx316
Date:
Fri May 31 20:53:51 2019 +0000
Revision:
1:c840c2b6f490
This is the program for bit_board, an accessory developed by a group of Imperial EEE students for MicroBit. This is the first commit to backup the work in May 2019.

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