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.

Revision:
2:3d9adb26bdc5
Parent:
1:7a6c2e2c9371
diff -r 7a6c2e2c9371 -r 3d9adb26bdc5 KeyboardService.h
--- a/KeyboardService.h	Wed Oct 07 11:29:52 2015 +0100
+++ b/KeyboardService.h	Thu Oct 29 16:48:26 2015 +0000
@@ -24,7 +24,7 @@
 /* TODO: make this easier to configure by application (e.g. as a template parameter for
  * KeyboardService) */
 #ifndef KEYBUFFER_SIZE
-#define KEYBUFFER_SIZE 512
+#define KEYBUFFER_SIZE 256
 #endif
 
 /**
@@ -237,8 +237,7 @@
             /*
              * We're not transmitting anything anymore. Might as well avoid overloading the
              * system in case it can magically fix itself. Ticker will start again on next _putc
-             * call. It could also be started on next connection, but we can't register a callback
-             * for that, currently.
+             * call, or on next connection.
              */
             stopReportTicker();
             consecutiveFailures = 0;
@@ -298,18 +297,20 @@
 
     /**
      * Pop a key from the internal FIFO, and attempt to send it over BLE
+     *
+     * keyUp reports should theoretically be sent after every keyDown, but we optimize the
+     * throughput by only sending one when strictly necessary:
+     * - when we need to repeat the same key
+     * - when there is no more key to report
+     *
+     * In case of error, put the key event back in the buffer, and retry on next tick.
      */
     virtual void sendCallback(void) {
         ble_error_t ret;
         uint8_t c;
+        static uint8_t previousKey = 0;
 
-        if (!keyBuffer.isSomethingPending()) {
-            /* Stop until the next call to putc */
-            stopReportTicker();
-            return;
-        }
-
-        if (!keyBuffer.isKeyUpPending()) {
+        if (keyBuffer.isSomethingPending() && !keyBuffer.isKeyUpPending()) {
             bool hasData = keyBuffer.getPending(c);
 
             /*
@@ -318,13 +319,26 @@
              */
             MBED_ASSERT(hasData);
 
-            if (hasData) {
+            if (!hasData)
+                return;
+
+            if (previousKey == c) {
+                /*
+                 * When the same key needs to be sent twice, we need to interleave a keyUp report,
+                 * or else the OS won't be able to differentiate them.
+                 * Push the key back into the buffer, and continue to keyUpCode.
+                 */
+                keyBuffer.setPending(c);
+            } else {
                 ret = keyDownCode(c, keymap[c].modifier);
                 if (ret) {
                     keyBuffer.setPending(c);
                     failedReports++;
-                    return;
+                } else {
+                    previousKey = c;
                 }
+
+                return;
             }
         }
 
@@ -334,6 +348,11 @@
             failedReports++;
         } else {
             keyBuffer.clearKeyUpPending();
+            previousKey = 0;
+
+            /* Idle when there is nothing more to send */
+            if (!keyBuffer.isSomethingPending())
+                stopReportTicker();
         }
     }