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:
1:7a6c2e2c9371
Parent:
0:cfd70fa91663
Child:
2:3d9adb26bdc5
--- a/MouseService.h	Tue Sep 15 20:16:58 2015 +0100
+++ b/MouseService.h	Wed Oct 07 11:29:52 2015 +0100
@@ -1,3 +1,19 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "mbed.h"
 
 #include "HIDServiceBase.h"
@@ -15,6 +31,10 @@
     MOUSE_BUTTON_MIDDLE  = 0x4,
 };
 
+/**
+ * Report descriptor for a standard 3 buttons + wheel mouse with relative X/Y
+ * moves
+ */
 report_map_t MOUSE_REPORT_MAP = {
     USAGE_PAGE(1),      0x01,         // Generic Desktop
     USAGE(1),           0x02,         // Mouse
@@ -47,6 +67,36 @@
 
 uint8_t report[] = { 0, 0, 0, 0 };
 
+/**
+ * @class MouseService
+ * @brief HID-over-Gatt mouse service.
+ *
+ * Send mouse moves and button informations over BLE.
+ *
+ * @code
+ * BLE ble;
+ * MouseService mouse(ble);
+ *
+ * Timeout timeout;
+ *
+ * void stop_mouse_move(void)
+ * {
+ *      // Set mouse state to immobile
+ *      mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_UP);
+ *      mouse.setSpeed(0, 0, 0);
+ * }
+ *
+ * void start_mouse_move(void)
+ * {
+ *      // Move left with a left button down. If the focus is on a drawing
+ *      // software, for instance, this should draw a line.
+ *      mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_DOWN);
+ *      mouse.setSpeed(1, 0, 0);
+ *
+ *      timeout.attach(stop_mouse_move, 0.2);
+ * }
+ * @endcode
+ */
 class MouseService: public HIDServiceBase
 {
 public:
@@ -70,15 +120,50 @@
         startReportTicker();
     }
 
+    void onConnection(const Gap::ConnectionCallbackParams_t *params)
+    {
+        HIDServiceBase::onConnection(params);
+        startReportTicker();
+    }
+
+    void onDisconnection(const Gap::DisconnectionCallbackParams_t *params)
+    {
+        stopReportTicker();
+        HIDServiceBase::onDisconnection(params);
+    }
+
+    /**
+     * Set X, Y, Z speed of the mouse. Parameters are sticky and will be
+     * transmitted on every tick. Users should therefore reset them to 0 when
+     * the device is immobile.
+     *
+     * @param x     Speed on hoizontal axis
+     * @param y     Speed on vertical axis
+     * @param wheel Scroll speed
+     *
+     * @returns A status code
+     *
+     * @note Directions depend on the operating system's configuration. It is
+     * customary to increase values on the X axis from left to right, and on the
+     * Y axis from top to bottom.
+     * Wheel is less standard, although positive values will usually scroll up.
+     */
     int setSpeed(int8_t x, int8_t y, int8_t wheel)
     {
         speed[0] = x;
         speed[1] = y;
         speed[2] = wheel;
 
+        startReportTicker();
+
         return 0;
     }
 
+    /**
+     * Toggle the state of one button
+     *
+     * @returns A status code
+     */
     int setButton(MouseButton button, ButtonState state)
     {
         if (state == BUTTON_UP)
@@ -86,14 +171,37 @@
         else
             buttonsState |= button;
 
+        startReportTicker();
+
         return 0;
     }
 
+    /**
+     * Called by the report ticker
+     */
     virtual void sendCallback(void) {
+        uint8_t buttons = buttonsState & 0x7;
+
         if (!connected)
             return;
 
-        report[0] = buttonsState & 0x7;
+        bool can_sleep = (report[0] == 0
+                       && report[1] == 0
+                       && report[2] == 0
+                       && report[3] == 0
+                       && report[0] == buttons
+                       && report[1] == speed[0]
+                       && report[2] == speed[1]
+                       && report[3] == speed[2]);
+
+        if (can_sleep) {
+            /* TODO: find out why there always is two more calls to sendCallback after this
+             * stopReportTicker(). */
+            stopReportTicker();
+            return;
+        }
+
+        report[0] = buttons;
         report[1] = speed[0];
         report[2] = speed[1];
         report[3] = speed[2];