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:
Tue Sep 15 20:16:58 2015 +0100
Revision:
0:cfd70fa91663
Child:
1:7a6c2e2c9371
Initial version

Provides all the components for an HID-over-GATT Profile implementation using
BLE API.

Who changed what in which revision?

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