USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Revision:
12:a9671b78d24e
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBMouseKeyboard.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBMouseKeyboard.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,751 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMouseKeyboard.h"
+
+typedef struct
+{
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x34, KEY_SHIFT},      /* " */
+    {0x20, KEY_SHIFT},      /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x1f, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x31, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x31, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x35, KEY_SHIFT},      /* ~ */
+    {0, 0},             /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x1f, KEY_SHIFT},      /* " */
+    {0x32, 0},          /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x34, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x64, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x64, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x32, KEY_SHIFT},      /* ~ */
+    {0, 0},            /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+#endif
+
+
+uint8_t *USBMouseKeyboard::reportDesc()
+{
+    if ( mouse_type == REL_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+            // Keyboard
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x06,
+            COLLECTION( 1 ),      0x01,
+            REPORT_ID( 1 ),       REPORT_ID_KEYBOARD,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0xE0,
+            USAGE_MAXIMUM( 1 ),       0xE7,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            REPORT_SIZE( 1 ),     0x01,
+            REPORT_COUNT( 1 ),    0x08,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x08,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x05,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x08,
+            USAGE_MINIMUM( 1 ),       0x01,
+            USAGE_MAXIMUM( 1 ),       0x05,
+            OUTPUT( 1 ),          0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x03,
+            OUTPUT( 1 ),          0x01,
+            REPORT_COUNT( 1 ),    0x06,
+            REPORT_SIZE( 1 ),     0x08,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 2 ),     0xff, 0x00,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0x00,
+            USAGE_MAXIMUM( 2 ),       0xff, 0x00,
+            INPUT( 1 ),           0x00,
+            END_COLLECTION( 0 ),
+
+            // Mouse
+            USAGE_PAGE( 1 ),      0x01,         // Generic Desktop
+            USAGE( 1 ),           0x02,         // Mouse
+            COLLECTION( 1 ),      0x01,         // Application
+            USAGE( 1 ),           0x01,         // Pointer
+            COLLECTION( 1 ),      0x00,         // Physical
+            REPORT_ID( 1 ),       REPORT_ID_MOUSE,
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x09,         // Buttons
+            USAGE_MINIMUM( 1 ),       0x1,
+            USAGE_MAXIMUM( 1 ),       0x3,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x05,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x08,
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x30,         // X
+            USAGE( 1 ),           0x31,         // Y
+            USAGE( 1 ),           0x38,         // scroll
+            LOGICAL_MINIMUM( 1 ),     0x81,
+            LOGICAL_MAXIMUM( 1 ),     0x7f,
+            INPUT( 1 ),           0x06,
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 ),
+
+
+            // Media Control
+            USAGE_PAGE( 1 ), 0x0C,
+            USAGE( 1 ), 0x01,
+            COLLECTION( 1 ), 0x01,
+            REPORT_ID( 1 ), REPORT_ID_VOLUME,
+            USAGE_PAGE( 1 ), 0x0C,
+            LOGICAL_MINIMUM( 1 ), 0x00,
+            LOGICAL_MAXIMUM( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x01,
+            REPORT_COUNT( 1 ), 0x07,
+            USAGE( 1 ), 0xB5,           // Next Track
+            USAGE( 1 ), 0xB6,           // Previous Track
+            USAGE( 1 ), 0xB7,           // Stop
+            USAGE( 1 ), 0xCD,           // Play / Pause
+            USAGE( 1 ), 0xE2,           // Mute
+            USAGE( 1 ), 0xE9,           // Volume Up
+            USAGE( 1 ), 0xEA,           // Volume Down
+            INPUT( 1 ), 0x02,           // Input (Data, Variable, Absolute)
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x01,
+            END_COLLECTION( 0 ),
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+    else if ( mouse_type == ABS_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+
+            // Keyboard
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x06,
+            COLLECTION( 1 ),      0x01,
+            REPORT_ID( 1 ),       REPORT_ID_KEYBOARD,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0xE0,
+            USAGE_MAXIMUM( 1 ),       0xE7,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            REPORT_SIZE( 1 ),     0x01,
+            REPORT_COUNT( 1 ),    0x08,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x08,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x05,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x08,
+            USAGE_MINIMUM( 1 ),       0x01,
+            USAGE_MAXIMUM( 1 ),       0x05,
+            OUTPUT( 1 ),          0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x03,
+            OUTPUT( 1 ),          0x01,
+            REPORT_COUNT( 1 ),    0x06,
+            REPORT_SIZE( 1 ),     0x08,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 2 ),     0xff, 0x00,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0x00,
+            USAGE_MAXIMUM( 2 ),       0xff, 0x00,
+            INPUT( 1 ),           0x00,
+            END_COLLECTION( 0 ),
+
+            // Mouse
+            USAGE_PAGE( 1 ), 0x01,             // Generic Desktop
+            USAGE( 1 ), 0x02,                  // Mouse
+            COLLECTION( 1 ), 0x01,             // Application
+            USAGE( 1 ), 0x01,                  // Pointer
+            COLLECTION( 1 ), 0x00,             // Physical
+            REPORT_ID( 1 ),       REPORT_ID_MOUSE,
+
+            USAGE_PAGE( 1 ), 0x01,              // Generic Desktop
+            USAGE( 1 ), 0x30,                   // X
+            USAGE( 1 ), 0x31,                   // Y
+            LOGICAL_MINIMUM( 1 ), 0x00,         // 0
+            LOGICAL_MAXIMUM( 2 ), 0xff, 0x7f,   // 32767
+            REPORT_SIZE( 1 ), 0x10,
+            REPORT_COUNT( 1 ), 0x02,
+            INPUT( 1 ), 0x02,                   // Data, Variable, Absolute
+
+            USAGE_PAGE( 1 ), 0x01,              // Generic Desktop
+            USAGE( 1 ), 0x38,                   // scroll
+            LOGICAL_MINIMUM( 1 ), 0x81,         // -127
+            LOGICAL_MAXIMUM( 1 ), 0x7f,         // 127
+            REPORT_SIZE( 1 ), 0x08,
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x06,                   // Data, Variable, Relative
+
+            USAGE_PAGE( 1 ), 0x09,              // Buttons
+            USAGE_MINIMUM( 1 ), 0x01,
+            USAGE_MAXIMUM( 1 ), 0x03,
+            LOGICAL_MINIMUM( 1 ), 0x00,         // 0
+            LOGICAL_MAXIMUM( 1 ), 0x01,         // 1
+            REPORT_COUNT( 1 ), 0x03,
+            REPORT_SIZE( 1 ), 0x01,
+            INPUT( 1 ), 0x02,                   // Data, Variable, Absolute
+            REPORT_COUNT( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x05,
+            INPUT( 1 ), 0x01,                   // Constant
+
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 ),
+
+            // Media Control
+            USAGE_PAGE( 1 ), 0x0C,
+            USAGE( 1 ), 0x01,
+            COLLECTION( 1 ), 0x01,
+            REPORT_ID( 1 ), REPORT_ID_VOLUME,
+            USAGE_PAGE( 1 ), 0x0C,
+            LOGICAL_MINIMUM( 1 ), 0x00,
+            LOGICAL_MAXIMUM( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x01,
+            REPORT_COUNT( 1 ), 0x07,
+            USAGE( 1 ), 0xB5,           // Next Track
+            USAGE( 1 ), 0xB6,           // Previous Track
+            USAGE( 1 ), 0xB7,           // Stop
+            USAGE( 1 ), 0xCD,           // Play / Pause
+            USAGE( 1 ), 0xE2,           // Mute
+            USAGE( 1 ), 0xE9,           // Volume Up
+            USAGE( 1 ), 0xEA,           // Volume Down
+            INPUT( 1 ), 0x02,           // Input (Data, Variable, Absolute)
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x01,
+            END_COLLECTION( 0 ),
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+
+    return NULL;
+}
+
+bool USBMouseKeyboard::EP1_OUT_callback()
+{
+    uint32_t bytesRead = 0;
+    uint8_t led[65];
+    USBDevice::readEP( EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE );
+    // we take led[1] because led[0] is the report ID
+    lock_status = led[1] & 0x07;
+
+    // We activate the endpoint to be able to recceive data
+    if ( !readStart( EPINT_OUT, MAX_HID_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+uint8_t USBMouseKeyboard::lockStatus()
+{
+    return lock_status;
+}
+
+bool USBMouseKeyboard::update( int16_t x, int16_t y, uint8_t button, int8_t z )
+{
+    switch ( mouse_type )
+    {
+        case REL_MOUSE:
+            while ( x > 127 )
+            {
+                if ( !mouseSend( 127, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x - 127;
+            }
+
+            while ( x < -128 )
+            {
+                if ( !mouseSend( -128, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x + 128;
+            }
+
+            while ( y > 127 )
+            {
+                if ( !mouseSend( 0, 127, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y - 127;
+            }
+
+            while ( y < -128 )
+            {
+                if ( !mouseSend( 0, -128, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y + 128;
+            }
+
+            return mouseSend( x, y, button, z );
+
+        case ABS_MOUSE:
+            HID_REPORT report;
+            report.data[0] = REPORT_ID_MOUSE;
+            report.data[1] = x & 0xff;
+            report.data[2] = ( x >> 8 ) & 0xff;
+            report.data[3] = y & 0xff;
+            report.data[4] = ( y >> 8 ) & 0xff;
+            report.data[5] = -z;
+            report.data[6] = button & 0x07;
+            report.length = 7;
+            return send( &report );
+
+        default:
+            return false;
+    }
+}
+
+bool USBMouseKeyboard::mouseSend( int8_t x, int8_t y, uint8_t buttons, int8_t z )
+{
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_MOUSE;
+    report.data[1] = buttons & 0x07;
+    report.data[2] = x;
+    report.data[3] = y;
+    report.data[4] = -z; // >0 to scroll down, <0 to scroll up
+    report.length = 5;
+    return send( &report );
+}
+
+bool USBMouseKeyboard::move( int16_t x, int16_t y )
+{
+    return update( x, y, button, 0 );
+}
+
+bool USBMouseKeyboard::scroll( int8_t z )
+{
+    return update( 0, 0, button, z );
+}
+
+bool USBMouseKeyboard::doubleClick()
+{
+    if ( !click( MOUSE_LEFT ) )
+    {
+        return false;
+    }
+
+    wait( 0.1 );
+    return click( MOUSE_LEFT );
+}
+
+bool USBMouseKeyboard::click( uint8_t button )
+{
+    if ( !update( 0, 0, button, 0 ) )
+    {
+        return false;
+    }
+
+    wait( 0.01 );
+    return update( 0, 0, 0, 0 );
+}
+
+bool USBMouseKeyboard::press( uint8_t button_ )
+{
+    button = button_ & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+bool USBMouseKeyboard::release( uint8_t button_ )
+{
+    button = ( button & ( ~button_ ) ) & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+int USBMouseKeyboard::_putc( int c )
+{
+    return keyCode( c, keymap[c].modifier );
+}
+
+bool USBMouseKeyboard::keyCode( uint8_t key, uint8_t modifier )
+{
+    // Send a simulated keyboard keypress. Returns true if successful.
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+    report.length = 9;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool USBMouseKeyboard::mediaControl( MEDIA_KEY key )
+{
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = ( 1 << key ) & 0x7f;
+    report.length = 2;
+    send( &report );
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+    report.length = 2;
+    return send( &report );
+}
+