Based on the example USB HID keyboard https://developer.mbed.org/users/jbru/code/BLE_HID_KeyboardStreamDemo/

Dependencies:   BLE_API mbed nRF51822

Fork of HID-kb by Microbug

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MouseService.h Source File

MouseService.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 
00019 #include "HIDServiceBase.h"
00020 
00021 enum ButtonState
00022 {
00023     BUTTON_UP,
00024     BUTTON_DOWN
00025 };
00026 
00027 enum MouseButton
00028 {
00029     MOUSE_BUTTON_LEFT    = 0x1,
00030     MOUSE_BUTTON_RIGHT   = 0x2,
00031     MOUSE_BUTTON_MIDDLE  = 0x4,
00032 };
00033 
00034 /**
00035  * Report descriptor for a standard 3 buttons + wheel mouse with relative X/Y
00036  * moves
00037  */
00038 report_map_t MOUSE_REPORT_MAP = {
00039     USAGE_PAGE(1),      0x01,         // Generic Desktop
00040     USAGE(1),           0x02,         // Mouse
00041     COLLECTION(1),      0x01,         // Application
00042     USAGE(1),           0x01,         //  Pointer
00043     COLLECTION(1),      0x00,         //  Physical
00044     USAGE_PAGE(1),      0x09,         //   Buttons
00045     USAGE_MINIMUM(1),   0x01,
00046     USAGE_MAXIMUM(1),   0x03,
00047     LOGICAL_MINIMUM(1), 0x00,
00048     LOGICAL_MAXIMUM(1), 0x01,
00049     REPORT_COUNT(1),    0x03,         //   3 bits (Buttons)
00050     REPORT_SIZE(1),     0x01,
00051     INPUT(1),           0x02,         //   Data, Variable, Absolute
00052     REPORT_COUNT(1),    0x01,         //   5 bits (Padding)
00053     REPORT_SIZE(1),     0x05,
00054     INPUT(1),           0x01,         //   Constant
00055     USAGE_PAGE(1),      0x01,         //   Generic Desktop
00056     USAGE(1),           0x30,         //   X
00057     USAGE(1),           0x31,         //   Y
00058     USAGE(1),           0x38,         //   Wheel
00059     LOGICAL_MINIMUM(1), 0x81,         //   -127
00060     LOGICAL_MAXIMUM(1), 0x7f,         //   127
00061     REPORT_SIZE(1),     0x08,         //   Three bytes
00062     REPORT_COUNT(1),    0x03,
00063     INPUT(1),           0x06,         //   Data, Variable, Relative
00064     END_COLLECTION(0),
00065     END_COLLECTION(0),
00066 };
00067 
00068 uint8_t report[] = { 0, 0, 0, 0 };
00069 
00070 /**
00071  * @class MouseService
00072  * @brief HID-over-Gatt mouse service.
00073  *
00074  * Send mouse moves and button informations over BLE.
00075  *
00076  * @code
00077  * BLE ble;
00078  * MouseService mouse(ble);
00079  *
00080  * Timeout timeout;
00081  *
00082  * void stop_mouse_move(void)
00083  * {
00084  *      // Set mouse state to immobile
00085  *      mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_UP);
00086  *      mouse.setSpeed(0, 0, 0);
00087  * }
00088  *
00089  * void start_mouse_move(void)
00090  * {
00091  *      // Move left with a left button down. If the focus is on a drawing
00092  *      // software, for instance, this should draw a line.
00093  *      mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_DOWN);
00094  *      mouse.setSpeed(1, 0, 0);
00095  *
00096  *      timeout.attach(stop_mouse_move, 0.2);
00097  * }
00098  * @endcode
00099  */
00100 class MouseService: public HIDServiceBase
00101 {
00102 public:
00103     MouseService(BLE &_ble) :
00104         HIDServiceBase(_ble,
00105                        MOUSE_REPORT_MAP, sizeof(MOUSE_REPORT_MAP),
00106                        inputReport          = report,
00107                        outputReport         = NULL,
00108                        featureReport        = NULL,
00109                        inputReportLength    = sizeof(inputReport),
00110                        outputReportLength   = 0,
00111                        featureReportLength  = 0,
00112                        reportTickerDelay    = 20),
00113         buttonsState (0),
00114         failedReports (0)
00115     {
00116         speed[0] = 0;
00117         speed[1] = 0;
00118         speed[2] = 0;
00119 
00120         startReportTicker();
00121     }
00122 
00123     void onConnection(const Gap::ConnectionCallbackParams_t *params)
00124     {
00125         HIDServiceBase::onConnection(params);
00126         startReportTicker();
00127     }
00128 
00129     void onDisconnection(const Gap::DisconnectionCallbackParams_t *params)
00130     {
00131         stopReportTicker();
00132         HIDServiceBase::onDisconnection(params);
00133     }
00134 
00135     /**
00136      * Set X, Y, Z speed of the mouse. Parameters are sticky and will be
00137      * transmitted on every tick. Users should therefore reset them to 0 when
00138      * the device is immobile.
00139      *
00140      * @param x     Speed on hoizontal axis
00141      * @param y     Speed on vertical axis
00142      * @param wheel Scroll speed
00143      *
00144      * @returns A status code
00145      *
00146      * @note Directions depend on the operating system's configuration. It is
00147      * customary to increase values on the X axis from left to right, and on the
00148      * Y axis from top to bottom.
00149      * Wheel is less standard, although positive values will usually scroll up.
00150      */
00151     int setSpeed(int8_t x, int8_t y, int8_t wheel)
00152     {
00153         speed[0] = x;
00154         speed[1] = y;
00155         speed[2] = wheel;
00156 
00157         startReportTicker();
00158 
00159         return 0;
00160     }
00161 
00162     /**
00163      * Toggle the state of one button
00164      *
00165      * @returns A status code
00166      */
00167     int setButton(MouseButton button, ButtonState state)
00168     {
00169         if (state == BUTTON_UP)
00170             buttonsState &= ~(button);
00171         else
00172             buttonsState |= button;
00173 
00174         startReportTicker();
00175 
00176         return 0;
00177     }
00178 
00179     /**
00180      * Called by the report ticker
00181      */
00182     virtual void sendCallback(void) {
00183         uint8_t buttons = buttonsState & 0x7;
00184 
00185         if (!connected)
00186             return;
00187 
00188         bool can_sleep = (report[0] == 0
00189                        && report[1] == 0
00190                        && report[2] == 0
00191                        && report[3] == 0
00192                        && report[0] == buttons
00193                        && report[1] == speed[0]
00194                        && report[2] == speed[1]
00195                        && report[3] == speed[2]);
00196 
00197         if (can_sleep) {
00198             /* TODO: find out why there always is two more calls to sendCallback after this
00199              * stopReportTicker(). */
00200             stopReportTicker();
00201             return;
00202         }
00203 
00204         report[0] = buttons;
00205         report[1] = speed[0];
00206         report[2] = speed[1];
00207         report[3] = speed[2];
00208 
00209         if (send(report))
00210             failedReports++;
00211     }
00212 
00213 protected:
00214     uint8_t buttonsState;
00215     uint8_t speed[3];
00216 
00217 public:
00218     uint32_t failedReports;
00219 };
00220