HID-over-GATT implementation with the BLE API. This library allows to create devices such as mouse, keyboard or joystick, over Bluetooth Low Energy.

Dependents:   BLENano_HID BLE_HID_MouseScrollDemo BLE_HID_KeyboardStreamDemo Shervs_TestKeyboard_TinyBLE ... more

The development repository is currently hosted on github. It contains examples and documentation. This is a snapshot of the library. The documentation can be read on github, or on docs.mbed.com.

Committer:
Jean-Philippe Brucker
Date:
Wed Oct 07 11:29:52 2015 +0100
Revision:
1:7a6c2e2c9371
Parent:
0:cfd70fa91663
Child:
3:4f8429a1905b
Publish version 0.1 of the BLE HID lib

This version number is completely arbitrary, and probably won't stick: once the
service is stable, we'll merge it with BLE API.
It is simply used to keep examples in sync with the lib and the github
repository during development.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jean-Philippe Brucker 1:7a6c2e2c9371 1 /* mbed Microcontroller Library
Jean-Philippe Brucker 1:7a6c2e2c9371 2 * Copyright (c) 2015 ARM Limited
Jean-Philippe Brucker 1:7a6c2e2c9371 3 *
Jean-Philippe Brucker 1:7a6c2e2c9371 4 * Licensed under the Apache License, Version 2.0 (the "License");
Jean-Philippe Brucker 1:7a6c2e2c9371 5 * you may not use this file except in compliance with the License.
Jean-Philippe Brucker 1:7a6c2e2c9371 6 * You may obtain a copy of the License at
Jean-Philippe Brucker 1:7a6c2e2c9371 7 *
Jean-Philippe Brucker 1:7a6c2e2c9371 8 * http://www.apache.org/licenses/LICENSE-2.0
Jean-Philippe Brucker 1:7a6c2e2c9371 9 *
Jean-Philippe Brucker 1:7a6c2e2c9371 10 * Unless required by applicable law or agreed to in writing, software
Jean-Philippe Brucker 1:7a6c2e2c9371 11 * distributed under the License is distributed on an "AS IS" BASIS,
Jean-Philippe Brucker 1:7a6c2e2c9371 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Jean-Philippe Brucker 1:7a6c2e2c9371 13 * See the License for the specific language governing permissions and
Jean-Philippe Brucker 1:7a6c2e2c9371 14 * limitations under the License.
Jean-Philippe Brucker 1:7a6c2e2c9371 15 */
Jean-Philippe Brucker 1:7a6c2e2c9371 16
Jean-Philippe Brucker 0:cfd70fa91663 17 #ifndef HID_SERVICE_BASE_H_
Jean-Philippe Brucker 0:cfd70fa91663 18 #define HID_SERVICE_BASE_H_
Jean-Philippe Brucker 0:cfd70fa91663 19
Jean-Philippe Brucker 0:cfd70fa91663 20 #include "mbed.h"
Jean-Philippe Brucker 0:cfd70fa91663 21
Jean-Philippe Brucker 0:cfd70fa91663 22 #include "ble/BLE.h"
Jean-Philippe Brucker 0:cfd70fa91663 23 #include "HID_types.h"
Jean-Philippe Brucker 0:cfd70fa91663 24
Jean-Philippe Brucker 0:cfd70fa91663 25 #define BLE_UUID_DESCRIPTOR_REPORT_REFERENCE 0x2908
Jean-Philippe Brucker 0:cfd70fa91663 26
Jean-Philippe Brucker 0:cfd70fa91663 27 typedef const uint8_t report_map_t[];
Jean-Philippe Brucker 0:cfd70fa91663 28 typedef const uint8_t * report_t;
Jean-Philippe Brucker 0:cfd70fa91663 29
Jean-Philippe Brucker 0:cfd70fa91663 30 typedef struct {
Jean-Philippe Brucker 0:cfd70fa91663 31 uint16_t bcdHID;
Jean-Philippe Brucker 0:cfd70fa91663 32 uint8_t bCountryCode;
Jean-Philippe Brucker 0:cfd70fa91663 33 uint8_t flags;
Jean-Philippe Brucker 0:cfd70fa91663 34 } HID_information_t;
Jean-Philippe Brucker 0:cfd70fa91663 35
Jean-Philippe Brucker 0:cfd70fa91663 36 enum ReportType {
Jean-Philippe Brucker 0:cfd70fa91663 37 INPUT_REPORT = 0x1,
Jean-Philippe Brucker 0:cfd70fa91663 38 OUTPUT_REPORT = 0x2,
Jean-Philippe Brucker 0:cfd70fa91663 39 FEATURE_REPORT = 0x3,
Jean-Philippe Brucker 0:cfd70fa91663 40 };
Jean-Philippe Brucker 0:cfd70fa91663 41
Jean-Philippe Brucker 0:cfd70fa91663 42 enum ProtocolMode {
Jean-Philippe Brucker 0:cfd70fa91663 43 BOOT_PROTOCOL = 0x0,
Jean-Philippe Brucker 0:cfd70fa91663 44 REPORT_PROTOCOL = 0x1,
Jean-Philippe Brucker 0:cfd70fa91663 45 };
Jean-Philippe Brucker 0:cfd70fa91663 46
Jean-Philippe Brucker 0:cfd70fa91663 47 typedef struct {
Jean-Philippe Brucker 0:cfd70fa91663 48 uint8_t ID;
Jean-Philippe Brucker 0:cfd70fa91663 49 uint8_t type;
Jean-Philippe Brucker 0:cfd70fa91663 50 } report_reference_t;
Jean-Philippe Brucker 0:cfd70fa91663 51
Jean-Philippe Brucker 0:cfd70fa91663 52
Jean-Philippe Brucker 0:cfd70fa91663 53 class HIDServiceBase {
Jean-Philippe Brucker 0:cfd70fa91663 54 public:
Jean-Philippe Brucker 0:cfd70fa91663 55 /**
Jean-Philippe Brucker 0:cfd70fa91663 56 * Constructor
Jean-Philippe Brucker 0:cfd70fa91663 57 *
Jean-Philippe Brucker 0:cfd70fa91663 58 * @param _ble
Jean-Philippe Brucker 0:cfd70fa91663 59 * BLE object to add this service to
Jean-Philippe Brucker 0:cfd70fa91663 60 * @param reportMap
Jean-Philippe Brucker 0:cfd70fa91663 61 * Byte array representing the input/output report formats. In USB HID jargon, it
Jean-Philippe Brucker 0:cfd70fa91663 62 * is called "HID report descriptor".
Jean-Philippe Brucker 0:cfd70fa91663 63 * @param reportMapLength
Jean-Philippe Brucker 0:cfd70fa91663 64 * Size of the reportMap array
Jean-Philippe Brucker 0:cfd70fa91663 65 * @param outputReportLength
Jean-Philippe Brucker 0:cfd70fa91663 66 * Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
Jean-Philippe Brucker 0:cfd70fa91663 67 * @param inputReportLength
Jean-Philippe Brucker 0:cfd70fa91663 68 * Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
Jean-Philippe Brucker 0:cfd70fa91663 69 * @param inputReportTickerDelay
Jean-Philippe Brucker 0:cfd70fa91663 70 * Delay between input report notifications, in ms. Acceptable values depend directly on
Jean-Philippe Brucker 0:cfd70fa91663 71 * GAP's connInterval parameter, so it shouldn't be less than 12ms
Jean-Philippe Brucker 0:cfd70fa91663 72 * Preferred GAP connection interval is set after this value, in order to send
Jean-Philippe Brucker 0:cfd70fa91663 73 * notifications as quick as possible: minimum connection interval will be set to
Jean-Philippe Brucker 0:cfd70fa91663 74 * (inputReportTickerDelay / 2)
Jean-Philippe Brucker 0:cfd70fa91663 75 */
Jean-Philippe Brucker 0:cfd70fa91663 76 HIDServiceBase(BLE &_ble,
Jean-Philippe Brucker 0:cfd70fa91663 77 report_map_t reportMap,
Jean-Philippe Brucker 0:cfd70fa91663 78 uint8_t reportMapLength,
Jean-Philippe Brucker 0:cfd70fa91663 79 report_t inputReport,
Jean-Philippe Brucker 0:cfd70fa91663 80 report_t outputReport,
Jean-Philippe Brucker 0:cfd70fa91663 81 report_t featureReport,
Jean-Philippe Brucker 0:cfd70fa91663 82 uint8_t inputReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 83 uint8_t outputReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 84 uint8_t featureReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 85 uint8_t inputReportTickerDelay = 50);
Jean-Philippe Brucker 0:cfd70fa91663 86
Jean-Philippe Brucker 0:cfd70fa91663 87 /**
Jean-Philippe Brucker 0:cfd70fa91663 88 * Send Report
Jean-Philippe Brucker 0:cfd70fa91663 89 *
Jean-Philippe Brucker 0:cfd70fa91663 90 * @param report Report to send. Must be of size @ref inputReportLength
Jean-Philippe Brucker 0:cfd70fa91663 91 * @return The write status
Jean-Philippe Brucker 0:cfd70fa91663 92 *
Jean-Philippe Brucker 0:cfd70fa91663 93 * @note Don't call send() directly for multiple reports! Use reportTicker for that, in order
Jean-Philippe Brucker 0:cfd70fa91663 94 * to avoid overloading the BLE stack, and let it handle events between each report.
Jean-Philippe Brucker 0:cfd70fa91663 95 */
Jean-Philippe Brucker 0:cfd70fa91663 96 virtual ble_error_t send(const report_t report);
Jean-Philippe Brucker 0:cfd70fa91663 97
Jean-Philippe Brucker 0:cfd70fa91663 98 /**
Jean-Philippe Brucker 0:cfd70fa91663 99 * Read Report
Jean-Philippe Brucker 0:cfd70fa91663 100 *
Jean-Philippe Brucker 0:cfd70fa91663 101 * @param report Report to fill. Must be of size @ref outputReportLength
Jean-Philippe Brucker 0:cfd70fa91663 102 * @return The read status
Jean-Philippe Brucker 0:cfd70fa91663 103 */
Jean-Philippe Brucker 0:cfd70fa91663 104 virtual ble_error_t read(report_t report);
Jean-Philippe Brucker 0:cfd70fa91663 105
Jean-Philippe Brucker 1:7a6c2e2c9371 106 virtual void onConnection(const Gap::ConnectionCallbackParams_t *params);
Jean-Philippe Brucker 1:7a6c2e2c9371 107 virtual void onDisconnection(const Gap::DisconnectionCallbackParams_t *params);
Jean-Philippe Brucker 0:cfd70fa91663 108
Jean-Philippe Brucker 0:cfd70fa91663 109 virtual bool isConnected(void)
Jean-Philippe Brucker 0:cfd70fa91663 110 {
Jean-Philippe Brucker 0:cfd70fa91663 111 return connected;
Jean-Philippe Brucker 0:cfd70fa91663 112 }
Jean-Philippe Brucker 0:cfd70fa91663 113
Jean-Philippe Brucker 0:cfd70fa91663 114 protected:
Jean-Philippe Brucker 0:cfd70fa91663 115 /**
Jean-Philippe Brucker 0:cfd70fa91663 116 * Called by BLE API when data has been successfully sent.
Jean-Philippe Brucker 0:cfd70fa91663 117 *
Jean-Philippe Brucker 0:cfd70fa91663 118 * @param count Number of reports sent
Jean-Philippe Brucker 0:cfd70fa91663 119 *
Jean-Philippe Brucker 0:cfd70fa91663 120 * @note Subclasses can override this to avoid starting the report ticker when there is nothing
Jean-Philippe Brucker 0:cfd70fa91663 121 * to send
Jean-Philippe Brucker 0:cfd70fa91663 122 */
Jean-Philippe Brucker 0:cfd70fa91663 123 virtual void onDataSent(unsigned count);
Jean-Philippe Brucker 0:cfd70fa91663 124
Jean-Philippe Brucker 0:cfd70fa91663 125 /**
Jean-Philippe Brucker 0:cfd70fa91663 126 * Start the ticker that sends input reports at regular interval
Jean-Philippe Brucker 0:cfd70fa91663 127 *
Jean-Philippe Brucker 0:cfd70fa91663 128 * @note reportTickerIsActive describes the state of the ticker and can be used by HIDS
Jean-Philippe Brucker 0:cfd70fa91663 129 * implementations.
Jean-Philippe Brucker 0:cfd70fa91663 130 */
Jean-Philippe Brucker 0:cfd70fa91663 131 virtual void startReportTicker(void);
Jean-Philippe Brucker 0:cfd70fa91663 132
Jean-Philippe Brucker 0:cfd70fa91663 133 /**
Jean-Philippe Brucker 0:cfd70fa91663 134 * Stop the input report ticker
Jean-Philippe Brucker 0:cfd70fa91663 135 */
Jean-Philippe Brucker 0:cfd70fa91663 136 virtual void stopReportTicker(void);
Jean-Philippe Brucker 0:cfd70fa91663 137
Jean-Philippe Brucker 0:cfd70fa91663 138 /**
Jean-Philippe Brucker 0:cfd70fa91663 139 * Called by input report ticker at regular interval (reportTickerDelay). This must be
Jean-Philippe Brucker 0:cfd70fa91663 140 * overriden by HIDS implementations to call the @ref send() with a report, if necessary.
Jean-Philippe Brucker 0:cfd70fa91663 141 */
Jean-Philippe Brucker 0:cfd70fa91663 142 virtual void sendCallback(void) = 0;
Jean-Philippe Brucker 0:cfd70fa91663 143
Jean-Philippe Brucker 0:cfd70fa91663 144 /**
Jean-Philippe Brucker 0:cfd70fa91663 145 * Create the Gatt descriptor for a report characteristic
Jean-Philippe Brucker 0:cfd70fa91663 146 */
Jean-Philippe Brucker 0:cfd70fa91663 147 GattAttribute** inputReportDescriptors();
Jean-Philippe Brucker 0:cfd70fa91663 148 GattAttribute** outputReportDescriptors();
Jean-Philippe Brucker 0:cfd70fa91663 149 GattAttribute** featureReportDescriptors();
Jean-Philippe Brucker 0:cfd70fa91663 150
Jean-Philippe Brucker 0:cfd70fa91663 151 /**
Jean-Philippe Brucker 0:cfd70fa91663 152 * Create the HID information structure
Jean-Philippe Brucker 0:cfd70fa91663 153 */
Jean-Philippe Brucker 0:cfd70fa91663 154 HID_information_t* HIDInformation();
Jean-Philippe Brucker 0:cfd70fa91663 155
Jean-Philippe Brucker 0:cfd70fa91663 156 protected:
Jean-Philippe Brucker 0:cfd70fa91663 157 BLE &ble;
Jean-Philippe Brucker 0:cfd70fa91663 158 bool connected;
Jean-Philippe Brucker 0:cfd70fa91663 159
Jean-Philippe Brucker 0:cfd70fa91663 160 int reportMapLength;
Jean-Philippe Brucker 0:cfd70fa91663 161
Jean-Philippe Brucker 0:cfd70fa91663 162 report_t inputReport;
Jean-Philippe Brucker 0:cfd70fa91663 163 report_t outputReport;
Jean-Philippe Brucker 0:cfd70fa91663 164 report_t featureReport;
Jean-Philippe Brucker 0:cfd70fa91663 165
Jean-Philippe Brucker 0:cfd70fa91663 166 uint8_t inputReportLength;
Jean-Philippe Brucker 0:cfd70fa91663 167 uint8_t outputReportLength;
Jean-Philippe Brucker 0:cfd70fa91663 168 uint8_t featureReportLength;
Jean-Philippe Brucker 0:cfd70fa91663 169
Jean-Philippe Brucker 0:cfd70fa91663 170 uint8_t controlPointCommand;
Jean-Philippe Brucker 0:cfd70fa91663 171 uint8_t protocolMode;
Jean-Philippe Brucker 0:cfd70fa91663 172
Jean-Philippe Brucker 0:cfd70fa91663 173 report_reference_t inputReportReferenceData;
Jean-Philippe Brucker 0:cfd70fa91663 174 report_reference_t outputReportReferenceData;
Jean-Philippe Brucker 0:cfd70fa91663 175 report_reference_t featureReportReferenceData;
Jean-Philippe Brucker 0:cfd70fa91663 176
Jean-Philippe Brucker 0:cfd70fa91663 177 GattAttribute inputReportReferenceDescriptor;
Jean-Philippe Brucker 0:cfd70fa91663 178 GattAttribute outputReportReferenceDescriptor;
Jean-Philippe Brucker 0:cfd70fa91663 179 GattAttribute featureReportReferenceDescriptor;
Jean-Philippe Brucker 0:cfd70fa91663 180
Jean-Philippe Brucker 0:cfd70fa91663 181 // Optional gatt characteristics:
Jean-Philippe Brucker 0:cfd70fa91663 182 GattCharacteristic protocolModeCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 183
Jean-Philippe Brucker 0:cfd70fa91663 184 // Report characteristics (each sort of optional)
Jean-Philippe Brucker 0:cfd70fa91663 185 GattCharacteristic inputReportCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 186 GattCharacteristic outputReportCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 187 GattCharacteristic featureReportCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 188
Jean-Philippe Brucker 0:cfd70fa91663 189 // Required gatt characteristics: Report Map, Information, Control Point
Jean-Philippe Brucker 0:cfd70fa91663 190 GattCharacteristic reportMapCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 191 ReadOnlyGattCharacteristic<HID_information_t> HIDInformationCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 192 GattCharacteristic HIDControlPointCharacteristic;
Jean-Philippe Brucker 0:cfd70fa91663 193
Jean-Philippe Brucker 0:cfd70fa91663 194 Ticker reportTicker;
Jean-Philippe Brucker 0:cfd70fa91663 195 uint32_t reportTickerDelay;
Jean-Philippe Brucker 0:cfd70fa91663 196 bool reportTickerIsActive;
Jean-Philippe Brucker 0:cfd70fa91663 197 };
Jean-Philippe Brucker 0:cfd70fa91663 198
Jean-Philippe Brucker 0:cfd70fa91663 199 #endif /* !HID_SERVICE_BASE_H_ */