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 #include "mbed.h"
Jean-Philippe Brucker 0:cfd70fa91663 2
Jean-Philippe Brucker 0:cfd70fa91663 3 #include "HIDServiceBase.h"
Jean-Philippe Brucker 0:cfd70fa91663 4
Jean-Philippe Brucker 0:cfd70fa91663 5 enum ButtonState
Jean-Philippe Brucker 0:cfd70fa91663 6 {
Jean-Philippe Brucker 0:cfd70fa91663 7 BUTTON_UP,
Jean-Philippe Brucker 0:cfd70fa91663 8 BUTTON_DOWN
Jean-Philippe Brucker 0:cfd70fa91663 9 };
Jean-Philippe Brucker 0:cfd70fa91663 10
Jean-Philippe Brucker 0:cfd70fa91663 11 enum JoystickButton
Jean-Philippe Brucker 0:cfd70fa91663 12 {
Jean-Philippe Brucker 0:cfd70fa91663 13 JOYSTICK_BUTTON_1 = 0x1,
Jean-Philippe Brucker 0:cfd70fa91663 14 JOYSTICK_BUTTON_2 = 0x2,
Jean-Philippe Brucker 0:cfd70fa91663 15 };
Jean-Philippe Brucker 0:cfd70fa91663 16
Jean-Philippe Brucker 0:cfd70fa91663 17 report_map_t JOYSTICK_REPORT_MAP = {
Jean-Philippe Brucker 0:cfd70fa91663 18 USAGE_PAGE(1), 0x01, // Generic Desktop
Jean-Philippe Brucker 0:cfd70fa91663 19 USAGE(1), 0x04, // Joystick
Jean-Philippe Brucker 0:cfd70fa91663 20 COLLECTION(1), 0x01, // Application
Jean-Philippe Brucker 0:cfd70fa91663 21 COLLECTION(1), 0x00, // Physical
Jean-Philippe Brucker 0:cfd70fa91663 22 USAGE_PAGE(1), 0x09, // Buttons
Jean-Philippe Brucker 0:cfd70fa91663 23 USAGE_MINIMUM(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 24 USAGE_MAXIMUM(1), 0x03,
Jean-Philippe Brucker 0:cfd70fa91663 25 LOGICAL_MINIMUM(1), 0x00,
Jean-Philippe Brucker 0:cfd70fa91663 26 LOGICAL_MAXIMUM(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 27 REPORT_COUNT(1), 0x03, // 2 bits (Buttons)
Jean-Philippe Brucker 0:cfd70fa91663 28 REPORT_SIZE(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 29 INPUT(1), 0x02, // Data, Variable, Absolute
Jean-Philippe Brucker 0:cfd70fa91663 30 REPORT_COUNT(1), 0x01, // 6 bits (Padding)
Jean-Philippe Brucker 0:cfd70fa91663 31 REPORT_SIZE(1), 0x05,
Jean-Philippe Brucker 0:cfd70fa91663 32 INPUT(1), 0x01, // Constant
Jean-Philippe Brucker 0:cfd70fa91663 33 USAGE_PAGE(1), 0x01, // Generic Desktop
Jean-Philippe Brucker 0:cfd70fa91663 34 USAGE(1), 0x30, // X
Jean-Philippe Brucker 0:cfd70fa91663 35 USAGE(1), 0x31, // Y
Jean-Philippe Brucker 0:cfd70fa91663 36 USAGE(1), 0x32, // Z
Jean-Philippe Brucker 0:cfd70fa91663 37 USAGE(1), 0x33, // Rx
Jean-Philippe Brucker 0:cfd70fa91663 38 LOGICAL_MINIMUM(1), 0x81, // -127
Jean-Philippe Brucker 0:cfd70fa91663 39 LOGICAL_MAXIMUM(1), 0x7f, // 127
Jean-Philippe Brucker 0:cfd70fa91663 40 REPORT_SIZE(1), 0x08, // Three bytes
Jean-Philippe Brucker 0:cfd70fa91663 41 REPORT_COUNT(1), 0x04,
Jean-Philippe Brucker 0:cfd70fa91663 42 INPUT(1), 0x02, // Data, Variable, Absolute (unlike mouse)
Jean-Philippe Brucker 0:cfd70fa91663 43 END_COLLECTION(0),
Jean-Philippe Brucker 0:cfd70fa91663 44 END_COLLECTION(0),
Jean-Philippe Brucker 0:cfd70fa91663 45 };
Jean-Philippe Brucker 0:cfd70fa91663 46
Jean-Philippe Brucker 0:cfd70fa91663 47 uint8_t report[] = { 0, 0, 0, 0, 0 };
Jean-Philippe Brucker 0:cfd70fa91663 48
Jean-Philippe Brucker 0:cfd70fa91663 49 class JoystickService: public HIDServiceBase
Jean-Philippe Brucker 0:cfd70fa91663 50 {
Jean-Philippe Brucker 0:cfd70fa91663 51 public:
Jean-Philippe Brucker 0:cfd70fa91663 52 JoystickService(BLE &_ble) :
Jean-Philippe Brucker 0:cfd70fa91663 53 HIDServiceBase(_ble,
Jean-Philippe Brucker 0:cfd70fa91663 54 JOYSTICK_REPORT_MAP, sizeof(JOYSTICK_REPORT_MAP),
Jean-Philippe Brucker 0:cfd70fa91663 55 inputReport = report,
Jean-Philippe Brucker 0:cfd70fa91663 56 outputReport = NULL,
Jean-Philippe Brucker 0:cfd70fa91663 57 featureReport = NULL,
Jean-Philippe Brucker 0:cfd70fa91663 58 inputReportLength = sizeof(inputReport),
Jean-Philippe Brucker 0:cfd70fa91663 59 outputReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 60 featureReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 61 reportTickerDelay = 20),
Jean-Philippe Brucker 0:cfd70fa91663 62 buttonsState (0),
Jean-Philippe Brucker 0:cfd70fa91663 63 failedReports (0)
Jean-Philippe Brucker 0:cfd70fa91663 64 {
Jean-Philippe Brucker 0:cfd70fa91663 65 speed[0] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 66 speed[1] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 67 speed[2] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 68 speed[3] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 69
Jean-Philippe Brucker 0:cfd70fa91663 70 startReportTicker();
Jean-Philippe Brucker 0:cfd70fa91663 71 }
Jean-Philippe Brucker 0:cfd70fa91663 72
Jean-Philippe Brucker 0:cfd70fa91663 73 int setSpeed(int8_t x, int8_t y, int8_t z)
Jean-Philippe Brucker 0:cfd70fa91663 74 {
Jean-Philippe Brucker 0:cfd70fa91663 75 speed[0] = x;
Jean-Philippe Brucker 0:cfd70fa91663 76 speed[1] = y;
Jean-Philippe Brucker 0:cfd70fa91663 77 speed[2] = z;
Jean-Philippe Brucker 0:cfd70fa91663 78
Jean-Philippe Brucker 0:cfd70fa91663 79 return 0;
Jean-Philippe Brucker 0:cfd70fa91663 80 }
Jean-Philippe Brucker 0:cfd70fa91663 81
Jean-Philippe Brucker 0:cfd70fa91663 82 int setButton(JoystickButton button, ButtonState state)
Jean-Philippe Brucker 0:cfd70fa91663 83 {
Jean-Philippe Brucker 0:cfd70fa91663 84 if (state == BUTTON_UP)
Jean-Philippe Brucker 0:cfd70fa91663 85 buttonsState &= ~(button);
Jean-Philippe Brucker 0:cfd70fa91663 86 else
Jean-Philippe Brucker 0:cfd70fa91663 87 buttonsState |= button;
Jean-Philippe Brucker 0:cfd70fa91663 88
Jean-Philippe Brucker 0:cfd70fa91663 89 return 0;
Jean-Philippe Brucker 0:cfd70fa91663 90 }
Jean-Philippe Brucker 0:cfd70fa91663 91
Jean-Philippe Brucker 0:cfd70fa91663 92 virtual void sendCallback(void) {
Jean-Philippe Brucker 0:cfd70fa91663 93 if (!connected)
Jean-Philippe Brucker 0:cfd70fa91663 94 return;
Jean-Philippe Brucker 0:cfd70fa91663 95
Jean-Philippe Brucker 0:cfd70fa91663 96 report[0] = buttonsState & 0x7;
Jean-Philippe Brucker 0:cfd70fa91663 97 report[1] = speed[0];
Jean-Philippe Brucker 0:cfd70fa91663 98 report[2] = speed[1];
Jean-Philippe Brucker 0:cfd70fa91663 99 report[3] = speed[2];
Jean-Philippe Brucker 0:cfd70fa91663 100 report[4] = speed[3];
Jean-Philippe Brucker 0:cfd70fa91663 101
Jean-Philippe Brucker 0:cfd70fa91663 102 if (send(report))
Jean-Philippe Brucker 0:cfd70fa91663 103 failedReports++;
Jean-Philippe Brucker 0:cfd70fa91663 104 }
Jean-Philippe Brucker 0:cfd70fa91663 105
Jean-Philippe Brucker 0:cfd70fa91663 106 protected:
Jean-Philippe Brucker 0:cfd70fa91663 107 uint8_t buttonsState;
Jean-Philippe Brucker 0:cfd70fa91663 108 uint8_t speed[4];
Jean-Philippe Brucker 0:cfd70fa91663 109
Jean-Philippe Brucker 0:cfd70fa91663 110 public:
Jean-Philippe Brucker 0:cfd70fa91663 111 uint32_t failedReports;
Jean-Philippe Brucker 0:cfd70fa91663 112 };