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 MouseButton
Jean-Philippe Brucker 0:cfd70fa91663 12 {
Jean-Philippe Brucker 0:cfd70fa91663 13 MOUSE_BUTTON_LEFT = 0x1,
Jean-Philippe Brucker 0:cfd70fa91663 14 MOUSE_BUTTON_RIGHT = 0x2,
Jean-Philippe Brucker 0:cfd70fa91663 15 MOUSE_BUTTON_MIDDLE = 0x4,
Jean-Philippe Brucker 0:cfd70fa91663 16 };
Jean-Philippe Brucker 0:cfd70fa91663 17
Jean-Philippe Brucker 0:cfd70fa91663 18 report_map_t MOUSE_REPORT_MAP = {
Jean-Philippe Brucker 0:cfd70fa91663 19 USAGE_PAGE(1), 0x01, // Generic Desktop
Jean-Philippe Brucker 0:cfd70fa91663 20 USAGE(1), 0x02, // Mouse
Jean-Philippe Brucker 0:cfd70fa91663 21 COLLECTION(1), 0x01, // Application
Jean-Philippe Brucker 0:cfd70fa91663 22 USAGE(1), 0x01, // Pointer
Jean-Philippe Brucker 0:cfd70fa91663 23 COLLECTION(1), 0x00, // Physical
Jean-Philippe Brucker 0:cfd70fa91663 24 USAGE_PAGE(1), 0x09, // Buttons
Jean-Philippe Brucker 0:cfd70fa91663 25 USAGE_MINIMUM(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 26 USAGE_MAXIMUM(1), 0x03,
Jean-Philippe Brucker 0:cfd70fa91663 27 LOGICAL_MINIMUM(1), 0x00,
Jean-Philippe Brucker 0:cfd70fa91663 28 LOGICAL_MAXIMUM(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 29 REPORT_COUNT(1), 0x03, // 3 bits (Buttons)
Jean-Philippe Brucker 0:cfd70fa91663 30 REPORT_SIZE(1), 0x01,
Jean-Philippe Brucker 0:cfd70fa91663 31 INPUT(1), 0x02, // Data, Variable, Absolute
Jean-Philippe Brucker 0:cfd70fa91663 32 REPORT_COUNT(1), 0x01, // 5 bits (Padding)
Jean-Philippe Brucker 0:cfd70fa91663 33 REPORT_SIZE(1), 0x05,
Jean-Philippe Brucker 0:cfd70fa91663 34 INPUT(1), 0x01, // Constant
Jean-Philippe Brucker 0:cfd70fa91663 35 USAGE_PAGE(1), 0x01, // Generic Desktop
Jean-Philippe Brucker 0:cfd70fa91663 36 USAGE(1), 0x30, // X
Jean-Philippe Brucker 0:cfd70fa91663 37 USAGE(1), 0x31, // Y
Jean-Philippe Brucker 0:cfd70fa91663 38 USAGE(1), 0x38, // Wheel
Jean-Philippe Brucker 0:cfd70fa91663 39 LOGICAL_MINIMUM(1), 0x81, // -127
Jean-Philippe Brucker 0:cfd70fa91663 40 LOGICAL_MAXIMUM(1), 0x7f, // 127
Jean-Philippe Brucker 0:cfd70fa91663 41 REPORT_SIZE(1), 0x08, // Three bytes
Jean-Philippe Brucker 0:cfd70fa91663 42 REPORT_COUNT(1), 0x03,
Jean-Philippe Brucker 0:cfd70fa91663 43 INPUT(1), 0x06, // Data, Variable, Relative
Jean-Philippe Brucker 0:cfd70fa91663 44 END_COLLECTION(0),
Jean-Philippe Brucker 0:cfd70fa91663 45 END_COLLECTION(0),
Jean-Philippe Brucker 0:cfd70fa91663 46 };
Jean-Philippe Brucker 0:cfd70fa91663 47
Jean-Philippe Brucker 0:cfd70fa91663 48 uint8_t report[] = { 0, 0, 0, 0 };
Jean-Philippe Brucker 0:cfd70fa91663 49
Jean-Philippe Brucker 0:cfd70fa91663 50 class MouseService: public HIDServiceBase
Jean-Philippe Brucker 0:cfd70fa91663 51 {
Jean-Philippe Brucker 0:cfd70fa91663 52 public:
Jean-Philippe Brucker 0:cfd70fa91663 53 MouseService(BLE &_ble) :
Jean-Philippe Brucker 0:cfd70fa91663 54 HIDServiceBase(_ble,
Jean-Philippe Brucker 0:cfd70fa91663 55 MOUSE_REPORT_MAP, sizeof(MOUSE_REPORT_MAP),
Jean-Philippe Brucker 0:cfd70fa91663 56 inputReport = report,
Jean-Philippe Brucker 0:cfd70fa91663 57 outputReport = NULL,
Jean-Philippe Brucker 0:cfd70fa91663 58 featureReport = NULL,
Jean-Philippe Brucker 0:cfd70fa91663 59 inputReportLength = sizeof(inputReport),
Jean-Philippe Brucker 0:cfd70fa91663 60 outputReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 61 featureReportLength = 0,
Jean-Philippe Brucker 0:cfd70fa91663 62 reportTickerDelay = 20),
Jean-Philippe Brucker 0:cfd70fa91663 63 buttonsState (0),
Jean-Philippe Brucker 0:cfd70fa91663 64 failedReports (0)
Jean-Philippe Brucker 0:cfd70fa91663 65 {
Jean-Philippe Brucker 0:cfd70fa91663 66 speed[0] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 67 speed[1] = 0;
Jean-Philippe Brucker 0:cfd70fa91663 68 speed[2] = 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 wheel)
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] = wheel;
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(MouseButton 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
Jean-Philippe Brucker 0:cfd70fa91663 101 if (send(report))
Jean-Philippe Brucker 0:cfd70fa91663 102 failedReports++;
Jean-Philippe Brucker 0:cfd70fa91663 103 }
Jean-Philippe Brucker 0:cfd70fa91663 104
Jean-Philippe Brucker 0:cfd70fa91663 105 protected:
Jean-Philippe Brucker 0:cfd70fa91663 106 uint8_t buttonsState;
Jean-Philippe Brucker 0:cfd70fa91663 107 uint8_t speed[3];
Jean-Philippe Brucker 0:cfd70fa91663 108
Jean-Philippe Brucker 0:cfd70fa91663 109 public:
Jean-Philippe Brucker 0:cfd70fa91663 110 uint32_t failedReports;
Jean-Philippe Brucker 0:cfd70fa91663 111 };