WIP conversion from HID to PID

Dependents:   USBJoystick_HelloWorld2_wip

Fork of USBJoystick by Wim Huiskamp

Files at this revision

API Documentation at this revision

Comitter:
Cirrus01
Date:
Sat Jul 07 10:46:53 2018 +0000
Parent:
0:e086541742c3
Commit message:
w/o

Changed in this revision

USBJoystick.cpp Show annotated file Show diff for this revision Revisions of this file
USBJoystick.h Show annotated file Show diff for this revision Revisions of this file
diff -r e086541742c3 -r 7f1e68e6da0c USBJoystick.cpp
--- a/USBJoystick.cpp	Thu Jan 05 14:22:02 2017 +0000
+++ b/USBJoystick.cpp	Sat Jul 07 10:46:53 2018 +0000
@@ -2,7 +2,7 @@
  * Copyright (c) 2012, v01:  Initial version, WH,
  *                           Modified USBMouse code ARM Limited.
  *                           (c) 2010-2011 mbed.org, MIT License
- *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button 
+ *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -27,226 +27,679 @@
 #include "stdint.h"
 #include "USBJoystick.h"
 
-bool USBJoystick::update(int16_t t, int16_t r, int16_t x, int16_t y, uint32_t buttons, uint8_t hat) {
+bool USBJoystick::update(int16_t t, int16_t r, int16_t f, int16_t b, int16_t x, int16_t y, uint32_t buttons, uint8_t hat)
+{
 
-   _t = t;
-   _r = r;   
-   _x = x;
-   _y = y;
-   _buttons = buttons;     
-   _hat = hat;
+    _t = t;
+    _r = r;
+    _f = f;
+    _b = b;
+    _x = x;
+    _y = y;
+    _buttons = buttons;
+    _hat = hat;
 
-   return update();
+    return update();
 }
- 
-bool USBJoystick::update() {
-   HID_REPORT report;
+
+bool USBJoystick::update()
+{
+    PID_REPORT report;
 
-   // Fill the report according to the Joystick Descriptor
-   report.data[0] = _t & 0xff;            
-   report.data[1] = _r & 0xff;               
-   report.data[2] = _x & 0xff;            
-   report.data[3] = _y & 0xff;
+    // Fill the report according to the Joystick Descriptor
+    report.data[0] = _t & 0xff;
+    report.data[1] = _r & 0xff;
+    report.data[2] = _f & 0xff;
+    report.data[3] = _b & 0xff;
+    report.data[4] = _x & 0xff;
+    report.data[5] = _y & 0xff;
 
 
-#if (BUTTONS4 == 1)               
+#if (BUTTONS4 == 1)
 //Hat and 4 Buttons
-//   report.data[4] = ((_buttons & 0x0f) << 4) | (_hat & 0x0f) ;                                      
-//   report.length = 5; 
+//   report.data[4] = ((_buttons & 0x0f) << 4) | (_hat & 0x0f) ;
+//   report.length = 5;
 
 
 //Use 4 bit padding for hat4 or hat8
-   report.data[4] = (_hat & 0x0f) ;                                      
+    report.data[6] = (_hat & 0x0f) ;
 
-//Use 4 bit padding for buttons   
-   report.data[5] = (_buttons & 0x0f) ;                                         
-   report.length = 6; 
+//Use 4 bit padding for buttons
+    report.data[7] = (_buttons & 0x0f) ;
+    report.length = 8;
 #endif
 
-#if (BUTTONS8 == 1)               
+#if (BUTTONS8 == 1)
 //Hat and first 4 Buttons
-//   report.data[4] = ((_buttons & 0x0f) << 4) | (_hat & 0x0f) ;                                      
+//   report.data[4] = ((_buttons & 0x0f) << 4) | (_hat & 0x0f) ;
 //
 //Use bit padding for last 4 Buttons
-//   report.data[5] =  (_buttons & 0xf0) >> 4;                                         
-//   report.length = 6; 
+//   report.data[5] =  (_buttons & 0xf0) >> 4;
+//   report.length = 6;
 
 //Use 4 bit padding for hat4 or hat8
-   report.data[4] = (_hat & 0x0f) ;                                      
+    report.data[6] = (_hat & 0x0f) ;
+
+//Use 8 bits for buttons
+    report.data[7] = (_buttons & 0xff) ;
+    report.length = 8;
+#endif
 
-//Use 8 bits for buttons   
-   report.data[5] = (_buttons & 0xff) ;
-   report.length = 6;
+#if (BUTTONS32 == 1)
+//Use 4 bit padding for hat4 or hat8
+    report.data[6] = (_hat & 0x0f) ;
+
+//No bit padding for 32 buttons
+    report.data[7] = (_buttons >>  0) & 0xff;
+    report.data[8] = (_buttons >>  8) & 0xff;
+    report.data[9] = (_buttons >> 16) & 0xff;
+    report.data[10] = (_buttons >> 24) & 0xff;
+    report.length = 11;
 #endif
 
-#if (BUTTONS32 == 1)               
-//Use 4 bit padding for hat4 or hat8
-   report.data[4] = (_hat & 0x0f) ;
+    return send(&report);
+}
 
-//No bit padding for 32 buttons                                         
-   report.data[5] = (_buttons >>  0) & 0xff;
-   report.data[6] = (_buttons >>  8) & 0xff;
-   report.data[7] = (_buttons >> 16) & 0xff;
-   report.data[8] = (_buttons >> 24) & 0xff;
-   report.length = 9;
-#endif
-       
-   return send(&report);
+bool USBJoystick::throttle(int16_t t)
+{
+    _t = t;
+    return update();
 }
 
-bool USBJoystick::throttle(int16_t t) {
-     _t = t;
-   return update();
+bool USBJoystick::rudder(int16_t r)
+{
+    _r = r;
+    return update();
+}
+
+bool USBJoystick::flaps(int16_t f)
+{
+    _f = f;
+    return update();
 }
 
-bool USBJoystick::rudder(int16_t r) {
-   _r = r;
-   return update();
+bool USBJoystick::breaks(int16_t b)
+{
+    _b = b;
+    return update();
 }
 
-bool USBJoystick::move(int16_t x, int16_t y) {
-   _x = x;
-   _y = y;
-   return update();
+bool USBJoystick::move(int16_t x, int16_t y)
+{
+    _x = x;
+    _y = y;
+    return update();
 }
 
-bool USBJoystick::buttons(uint32_t buttons) {
-   _buttons = buttons;
-   return update();
+bool USBJoystick::buttons(uint32_t buttons)
+{
+    _buttons = buttons;
+    return update();
 }
 
-bool USBJoystick::hat(uint8_t hat) {
-   _hat = hat;
-   return update();
+bool USBJoystick::hat(uint8_t hat)
+{
+    _hat = hat;
+    return update();
 }
 
 
-void USBJoystick::_init() {
-   _t = -127;
-   _r = -127;    
-   _x = 0;                       
-   _y = 0;     
-   _buttons = 0x00000000;
-   _hat = 0x00;              
+void USBJoystick::_init()
+{
+    _t = -127;
+    _r = -127;
+    _f = -127;
+    _b = -127;
+    _x = 0;
+    _y = 0;
+    _buttons = 0x00000000;
+    _hat = 0x00;
 }
 
 
-uint8_t * USBJoystick::reportDesc() {    
-         static uint8_t reportDescriptor[] = {
+uint8_t * USBJoystick::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,               //bLength
+        STRING_DESCRIPTOR,  //bDescriptorType 0x03
+        'S',0,              //bString iInterface - PID
+        'i',0,
+        'm',0,
+        'u',0,
+        'l',0,
+        'a',0,
+        't',0,
+        'o',0,
+        'r',0,
+    };
+    return stringIinterfaceDescriptor;
+}
 
-             USAGE_PAGE(1), 0x01,           // Generic Desktop           
-             LOGICAL_MINIMUM(1), 0x00,      // Logical_Minimum (0)             
-             USAGE(1), 0x04,                // Usage (Joystick)
-             COLLECTION(1), 0x01,           // Application
-               USAGE_PAGE(1), 0x02,            // Simulation Controls
-               USAGE(1), 0xBB,                 // Throttle             
-               USAGE(1), 0xBA,                 // Rudder               
-               LOGICAL_MINIMUM(1), 0x81,       // -127
-               LOGICAL_MAXIMUM(1), 0x7f,       // 127
-               REPORT_SIZE(1), 0x08,
-               REPORT_COUNT(1), 0x02,
-               INPUT(1), 0x02,                 // Data, Variable, Absolute               
-               USAGE_PAGE(1), 0x01,            // Generic Desktop
-               USAGE(1), 0x01,                 // Usage (Pointer)
-               COLLECTION(1), 0x00,            // Physical
-                 USAGE(1), 0x30,                 // X
-                 USAGE(1), 0x31,                 // Y
+uint8_t * USBJoystick::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'C',0,                                                      //bString iProduct - PID device
+        'o',0,
+        'n',0,
+        'd',0,
+        'o',0,
+        'r',0,
+        '-',0,
+        'S',0,
+        'i',0,
+        'm',0
+    };
+    return stringIproductDescriptor;
+}
+
+uint8_t * USBJoystick::reportDesc()
+{
+    static uint8_t reportDescriptor[] = {
+
+        USAGE_PAGE(1), 0x01,           // Generic Desktop
+        LOGICAL_MINIMUM(1), 0x00,      // Logical_Minimum (0)
+        USAGE(1), 0x04,                // Usage (Joystick)
+        COLLECTION(1), 0x01,           // Application
+        USAGE_PAGE(1), 0x02,            // Simulation Controls
+        USAGE(1), 0xBB,                 // Throttle
+        USAGE(1), 0xBA,                 // Rudder
+        USAGE(1), 0xC3,                 // Wing Flaps
+        USAGE(1), 0xB6,                 // Dive Breaks
+        LOGICAL_MINIMUM(1), 0x81,       // -127
+        LOGICAL_MAXIMUM(1), 0x7f,       // 127
+        REPORT_SIZE(1), 0x08,
+        REPORT_COUNT(1), 0x02,
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
+        USAGE_PAGE(1), 0x01,            // Generic Desktop
+        USAGE(1), 0x01,                 // Usage (Pointer)
+        COLLECTION(1), 0x00,            // Physical
+        USAGE(1), 0x30,                 // X
+        USAGE(1), 0x31,                 // Y
 //  8 bit values
-                 LOGICAL_MINIMUM(1), 0x81,       // -127
-                 LOGICAL_MAXIMUM(1), 0x7f,       // 127
-                 REPORT_SIZE(1), 0x08,
-                 REPORT_COUNT(1), 0x02,
-                 INPUT(1), 0x02,                 // Data, Variable, Absolute                  
+        LOGICAL_MINIMUM(1), 0x81,       // -127
+        LOGICAL_MAXIMUM(1), 0x7f,       // 127
+        REPORT_SIZE(1), 0x08,
+        REPORT_COUNT(1), 0x02,
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 // 16 bit values
 //                 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                
+//                 INPUT(1), 0x02,                 // Data, Variable, Absolute
 
-               END_COLLECTION(0),               
+        END_COLLECTION(0),
 
 #if (HAT4 == 1)
 // 4 Position Hat Switch
-               USAGE(1), 0x39,                 // Usage (Hat switch)
-               LOGICAL_MINIMUM(1), 0x00,       // 0
-               LOGICAL_MAXIMUM(1), 0x03,       // 3
-               PHYSICAL_MINIMUM(1), 0x00,      // Physical_Minimum (0)
-               PHYSICAL_MAXIMUM(2), 0x0E, 0x01, // Physical_Maximum (270)
-               UNIT(1), 0x14,                  // Unit (Eng Rot:Angular Pos)                            
-               REPORT_SIZE(1), 0x04,
-               REPORT_COUNT(1), 0x01,
-               INPUT(1), 0x02,                 // Data, Variable, Absolute               
+        USAGE(1), 0x39,                 // Usage (Hat switch)
+        LOGICAL_MINIMUM(1), 0x00,       // 0
+        LOGICAL_MAXIMUM(1), 0x03,       // 3
+        PHYSICAL_MINIMUM(1), 0x00,      // Physical_Minimum (0)
+        PHYSICAL_MAXIMUM(2), 0x0E, 0x01, // Physical_Maximum (270)
+        UNIT(1), 0x14,                  // Unit (Eng Rot:Angular Pos)
+        REPORT_SIZE(1), 0x04,
+        REPORT_COUNT(1), 0x01,
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 #endif
 #if (HAT8 == 1)
 // 8 Position Hat Switch
-               USAGE(1), 0x39,                 // Usage (Hat switch)
-               LOGICAL_MINIMUM(1), 0x00,       // 0
-               LOGICAL_MAXIMUM(1), 0x07,       // 7
-               PHYSICAL_MINIMUM(1), 0x00,      // Physical_Minimum (0)
-               PHYSICAL_MAXIMUM(2), 0x3B, 0x01, // Physical_Maximum (315)
-               UNIT(1), 0x14,                  // Unit (Eng Rot:Angular Pos)                            
-               REPORT_SIZE(1), 0x04,
-               REPORT_COUNT(1), 0x01,
-               INPUT(1), 0x02,                 // Data, Variable, Absolute               
+        USAGE(1), 0x39,                 // Usage (Hat switch)
+        LOGICAL_MINIMUM(1), 0x00,       // 0
+        LOGICAL_MAXIMUM(1), 0x07,       // 7
+        PHYSICAL_MINIMUM(1), 0x00,      // Physical_Minimum (0)
+        PHYSICAL_MAXIMUM(2), 0x3B, 0x01, // Physical_Maximum (315)
+        UNIT(1), 0x14,                  // Unit (Eng Rot:Angular Pos)
+        REPORT_SIZE(1), 0x04,
+        REPORT_COUNT(1), 0x01,
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 #endif
 
 // Padding 4 bits
-               REPORT_SIZE(1), 0x01,
-               REPORT_COUNT(1), 0x04,
-               INPUT(1), 0x01,                 // Constant
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x04,
+        INPUT(1), 0x01,                 // Constant
 
 
 #if (BUTTONS4 == 1)
 // 4 Buttons
-               USAGE_PAGE(1), 0x09,            // Buttons
-               USAGE_MINIMUM(1), 0x01,         // 1
-               USAGE_MAXIMUM(1), 0x04,         // 4
-               LOGICAL_MINIMUM(1), 0x00,       // 0
-               LOGICAL_MAXIMUM(1), 0x01,       // 1
-               REPORT_SIZE(1), 0x01,
-               REPORT_COUNT(1), 0x04,
-               UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
-               UNIT(1), 0x00,                  // Unit (None)                                           
-               INPUT(1), 0x02,                 // Data, Variable, Absolute
+        USAGE_PAGE(1), 0x09,            // Buttons
+        USAGE_MINIMUM(1), 0x01,         // 1
+        USAGE_MAXIMUM(1), 0x04,         // 4
+        LOGICAL_MINIMUM(1), 0x00,       // 0
+        LOGICAL_MAXIMUM(1), 0x01,       // 1
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x04,
+        UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
+        UNIT(1), 0x00,                  // Unit (None)
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 
 // Padding 4 bits
-               REPORT_SIZE(1), 0x01,
-               REPORT_COUNT(1), 0x04,
-               INPUT(1), 0x01,                 // Constant
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x04,
+        INPUT(1), 0x01,                 // Constant
 
 #endif
 #if (BUTTONS8 == 1)
 // 8 Buttons
-               USAGE_PAGE(1), 0x09,            // Buttons
-               USAGE_MINIMUM(1), 0x01,         // 1
-               USAGE_MAXIMUM(1), 0x08,         // 8
-               LOGICAL_MINIMUM(1), 0x00,       // 0
-               LOGICAL_MAXIMUM(1), 0x01,       // 1
-               REPORT_SIZE(1), 0x01,
-               REPORT_COUNT(1), 0x08,
-               UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
-               UNIT(1), 0x00,                  // Unit (None)                                           
-               INPUT(1), 0x02,                 // Data, Variable, Absolute
+        USAGE_PAGE(1), 0x09,            // Buttons
+        USAGE_MINIMUM(1), 0x01,         // 1
+        USAGE_MAXIMUM(1), 0x08,         // 8
+        LOGICAL_MINIMUM(1), 0x00,       // 0
+        LOGICAL_MAXIMUM(1), 0x01,       // 1
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x08,
+        UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
+        UNIT(1), 0x00,                  // Unit (None)
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 #endif
 
 #if (BUTTONS32 == 1)
 // 32 Buttons
-               USAGE_PAGE(1), 0x09,            // Buttons
-               USAGE_MINIMUM(1), 0x01,         // 1
-               USAGE_MAXIMUM(1), 0x20,         // 32
-               LOGICAL_MINIMUM(1), 0x00,       // 0
-               LOGICAL_MAXIMUM(1), 0x01,       // 1
-               REPORT_SIZE(1), 0x01,
-               REPORT_COUNT(1), 0x20,
-               UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
-               UNIT(1), 0x00,                  // Unit (None)                                           
-               INPUT(1), 0x02,                 // Data, Variable, Absolute
+        USAGE_PAGE(1), 0x09,            // Buttons
+        USAGE_MINIMUM(1), 0x01,         // 1
+        USAGE_MAXIMUM(1), 0x20,         // 32
+        LOGICAL_MINIMUM(1), 0x00,       // 0
+        LOGICAL_MAXIMUM(1), 0x01,       // 1
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x20,
+        UNIT_EXPONENT(1), 0x00,         // Unit_Exponent (0)
+        UNIT(1), 0x00,                  // Unit (None)
+        INPUT(1), 0x02,                 // Data, Variable, Absolute
 #endif
-
-             END_COLLECTION(0)
-      };
+#if (FFB == 1)
+        PHYSICAL_MINIMUM(1), 0x00,      //   PHYSICAL_MINIMUM (0)
+        INPUT(1), 0x02,                 //   INPUT (Data,Var,Abs)
+        USAGE_PAGE(1), 0x0f,            //   USAGE_PAGE (Physical Interface Device)
+        USAGE(1), 0x21,                 //   USAGE (Set Effect Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        USAGE(1), 0x22,                 //     USAGE (Effect Block Index)
+        LOGICAL_MAXIMUM(1), 0x7f,       //     LOGICAL_MAXIMUM (127)
+        REPORT_SIZE(1), 0x07,           //     REPORT_SIZE (7)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x25,                 //     USAGE (Effect Type)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE(1), 0x26,                 //       USAGE (ET Constant Force)
+        USAGE(1), 0x27,                 //       USAGE (ET Ramp)
+        USAGE(1), 0x30,                 //       USAGE (ET Square)
+        USAGE(1), 0x31,                 //       USAGE (ET Sine)
+        USAGE(1), 0x32,                 //       USAGE (ET Triangle)
+        USAGE(1), 0x33,                 //       USAGE (ET Sawtooth Up)
+        USAGE(1), 0x34,                 //       USAGE (ET Sawtooth Down)
+        USAGE(1), 0x40,                 //       USAGE (ET Spring)
+        USAGE(1), 0x41,                 //       USAGE (ET Damper)
+        USAGE(1), 0x42,                 //       USAGE (ET Inertia)
+        LOGICAL_MINIMUM(1), 0x01,       //       LOGICAL_MINIMUM (1)
+        LOGICAL_MAXIMUM(1), 0x0a,       //       LOGICAL_MAXIMUM (10)
+        REPORT_SIZE(1), 0x08,           //       REPORT_SIZE (8)
+        OUTPUT(1), 0x00,                //       OUTPUT (Data,Ary,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x50,                 //   USAGE (Duration)
+        USAGE(1), 0x54,                 //     USAGE (Trigger Repeat Interval)
+        LOGICAL_MINIMUM(1), 0x00,       //     LOGICAL_MINIMUM (0)
+        LOGICAL_MAXIMUM(2), 0x10, 0x27, //     LOGICAL_MAXIMUM (10000)
+        PHYSICAL_MAXIMUM(2), 0x10, 0x27,//     PHYSICAL_MAXIMUM (10000)
+        REPORT_SIZE(1), 0x10,           //     REPORT_SIZE (16)
+        UNIT(2), 0x03, 0x10,            //     UNIT (Eng Lin:Time)
+        UNIT_EXPONENT(1), 0x0d,         //     UNIT_EXPONENT (-3)
+        REPORT_COUNT(1), 0x02,          //     REPORT_COUNT (2)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        UNIT_EXPONENT(1), 0x0a,         //     UNIT_EXPONENT (-6)
+        USAGE(1), 0x51,                 //     USAGE (Sample Period)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        PHYSICAL_MAXIMUM(1), 0x00,      //     PHYSICAL_MAXIMUM (0)
+        UNIT_EXPONENT(1), 0x00,         //     UNIT_EXPONENT (0)
+        UNIT(1), 0x00,                  //     UNIT (None)
+        USAGE(1), 0x52,                 //     USAGE (Gain)
+        USAGE(1), 0x53,                 //     USAGE (Trigger Button)
+        LOGICAL_MAXIMUM(1), 0x7f,       //     LOGICAL_MAXIMUM (127)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x02,          //     REPORT_COUNT (2)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x55,                 //     USAGE (Axes Enable)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE_PAGE(1), 0x01,            //       USAGE_PAGE (Generic Desktop)
+        USAGE(1), 0x01,                 //       USAGE (Pointer)
+        COLLECTION(1), 0x00,            //       COLLECTION (Physical)
+        USAGE(1), 0x30,                 //         USAGE (X)
+        USAGE(1), 0x31,                 //         USAGE (Y)
+        USAGE(1), 0x32,                 //         USAGE (Z)
+        LOGICAL_MINIMUM(1), 0x01,       //         LOGICAL_MINIMUM (1)
+        REPORT_SIZE(1), 0x01,           //         REPORT_SIZE (1)
+        REPORT_COUNT(1), 0x03,          //         REPORT_COUNT (3)
+        OUTPUT(1), 0x02,                //         OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //       END_COLLECTION
+        END_COLLECTION(0),              //     END_COLLECTION
+        REPORT_COUNT(1), 0x06,          //     REPORT_COUNT (6)
+        OUTPUT(1), 0x03,                //     OUTPUT (Cnst,Var,Abs)
+        USAGE_PAGE(1), 0x0f,            //     USAGE_PAGE (Physical Interface Device)
+        USAGE(1), 0x57,                 //     USAGE (Direction)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE_PAGE(1), 0x01,            //       USAGE_PAGE (Generic Desktop)
+        USAGE(1), 0x01,                 //       USAGE (Pointer)
+        COLLECTION(1), 0x00,            //       COLLECTION (Physical)
+        USAGE(1), 0x30,                 //         USAGE (X)
+        USAGE(1), 0x31,                 //         USAGE (Y)
+        USAGE(1), 0x32,                 //         USAGE (Z)
+        LOGICAL_MINIMUM(1), 0x00,       //         LOGICAL_MINIMUM (0)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //         LOGICAL_MAXIMUM (255)
+        0xPHYSICAL_MAXIMUM(2)6, 0x68, 0x01, //     PHYSICAL_MAXIMUM (360)
+        UNIT(1), 0x14,                  //         UNIT (Eng Rot:Angular Pos)
+        REPORT_SIZE(1), 0x08,           //         REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x03,          //         REPORT_COUNT (3)
+        OUTPUT(1), 0x02,                //         OUTPUT (Data,Var,Abs)
+        UNIT(1), 0x00,                  //         UNIT (None)
+        PHYSICAL_MAXIMUM(1), 0x00,      //         PHYSICAL_MAXIMUM (0)
+        END_COLLECTION(0),              //       END_COLLECTION
+        END_COLLECTION(0),              //     END_COLLECTION
+        USAGE_PAGE(1), 0x0f,            //     USAGE_PAGE (Physical Interface Device)
+        USAGE(1), 0x58,                 //     USAGE (Type Specific Block Offset)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE(3), 0x01, 0x00, 0x0a, 0x00, //     USAGE (Ordinals:Instance 1)
+        USAGE(3), 0x02, 0x00, 0x0a, 0x00, //     USAGE (Ordinals:Instance 2)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //       LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x10,           //       REPORT_SIZE (16)
+        REPORT_COUNT(1), 0x02,          //       REPORT_COUNT (2)
+        OUTPUT(1), 0x02,                //       OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //     END_COLLECTION
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE_PAGE(1), 0x0f,            //   USAGE_PAGE (Physical Interface Device)
+        USAGE(1), 0x5a,                 //   USAGE (Set Envelope Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x02,             //     REPORT_ID (2)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x5b,                 //     USAGE (Attack Level)
+        USAGE(1), 0x5d,                 //     USAGE (Fade Level)
+        LOGICAL_MAXIMUM(1), 0xff        //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x02,          //     REPORT_COUNT (2)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x5c,                 //     USAGE (Attack Time)
+        USAGE(1), 0x5e,                 //     USAGE (Fade Time)
+        LOGICAL_MAXIMUM(2), 0x10, 0x27, //     LOGICAL_MAXIMUM (10000)
+        PHYSICAL_MAXIMUM(1), 0x10, 0x27,//     PHYSICAL_MAXIMUM (10000)
+        UNIT(2), 0x03, 0x10,            //     UNIT (Eng Lin:Time)
+        UNIT_EXPONENT(1), 0x0d,         //     UNIT_EXPONENT (-3)
+        REPORT_SIZE(1), 0x10,           //     REPORT_SIZE (16)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        PHYSICAL_MAXIMUM(1), 0x00,      //     PHYSICAL_MAXIMUM (0)
+        UNIT(1), 0x00,                  //     UNIT (None)
+        UNIT_EXPONENT(1), 0x00,         //     UNIT_EXPONENT (0)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x5f,                 //   USAGE (Set Condition Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x03,             //     REPORT_ID (3)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(1), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x60,                 //     USAGE (CP Offset)
+        USAGE(1), 0x61,                 //     USAGE (Positive Coefficient)
+        USAGE(1), 0x62,                 //     USAGE (Negative Coefficient)
+        USAGE(1), 0x63,                 //     USAGE (Positive Saturation)
+        USAGE(1), 0x64,                 //     USAGE (Negative Saturation)
+        USAGE(1), 0x65,                 //     USAGE (Dead Band)
+        LOGICAL_MAXIMUM(1), 0xff        //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x06,          //     REPORT_COUNT (6)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x6e,                 //   USAGE (Set Periodic Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x04,             //     REPORT_ID (4)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x70,                 //     USAGE (Magnitude)
+        USAGE(1), 0x6f,                 //     USAGE (Offset)
+        USAGE(1), 0x71,                 //     USAGE (Phase)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x03,          //     REPORT_COUNT (3)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x72,                 //     USAGE (Period)
+        LOGICAL_MAXIMUM(2), 0x10, 0x27, //     LOGICAL_MAXIMUM (10000)
+        PHYSICAL_MAXIMUM(2), 0x10, 0x27,//     PHYSICAL_MAXIMUM (10000)
+        UNIT(2), 0x03, 0x10,            //     UNIT (Eng Lin:Time)
+        UNIT_EXPONENT(1), 0x0d,         //     UNIT_EXPONENT (-3)
+        REPORT_SIZE(1), 0x10,           //     REPORT_SIZE (16)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        PHYSICAL_MAXIMUM(1), 0x00,      //     PHYSICAL_MAXIMUM (0)
+        UNIT(1), 0x00,                  //     UNIT (None)
+        UNIT_EXPONENT(1), 0x00,         //     UNIT_EXPONENT (0))
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x73,                 //   USAGE (Set Constant Force Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x05,             //     REPORT_ID (5)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x70,                 //     USAGE (Magnitude)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        COLLECTION(0),                  //   END_COLLECTION
+        USAGE(1), 0x74,                 //   USAGE (Set Ramp Force Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x06,             //     REPORT_ID (6)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x75,                 //     USAGE (Ramp Start)
+        USAGE(1), 0x76,                 //     USAGE (Ramp End)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x02,          //     REPORT_COUNT (2)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x68,                 //   USAGE (Custom Force Data Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x07,             //     REPORT_ID (7)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_SIZE(1), 0x0f,           //     REPORT_SIZE (15)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(3), 0x3b, 0x00, 0x01, 0x00//     USAGE (Generic Desktop:Byte Count)
+        LOGICAL_MAXIMUM(2), 0x00, 0x01, //     LOGICAL_MAXIMUM (256)
+        REPORT_SIZE(1), 0x09,           //     REPORT_SIZE (9)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x69,                 //     USAGE (Custom Force Data)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(2), 0x00, 0x01,    //     REPORT_COUNT (256)
+        OUTPUT(2), 0x02, 0x01,          //     OUTPUT (Data,Var,Abs,Buf)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x66,                 //   USAGE (Download Force Sample)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x08,             //     REPORT_ID (8)
+        USAGE_PAGE(1), 0x01,            //     USAGE_PAGE (Generic Desktop)
+        USAGE(1), 0x01,                 //     USAGE (Pointer)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE(1), 0x30,                 //       USAGE (X)
+        USAGE(1), 0x31,                 //       USAGE (Y)
+        USAGE(1), 0x32,                 //       USAGE (Z)
+        LOGICAL_MINIMUM(1), 0x81,       //       LOGICAL_MINIMUM (-127)
+        LOGICAL_MAXIMUM(1), 0x7f,       //       LOGICAL_MAXIMUM (127)
+        REPORT_SIZE(1), 0x08,           //       REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x03,          //       REPORT_COUNT (3)
+        OUTPUT(1), 0x02,                //       OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //     END_COLLECTION
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE_PAGE(1), 0x0f,            //   USAGE_PAGE (Physical Interface Device)
+        USAGE(1), 0x6b,                 //   USAGE (Set Custom Force Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x09,             //     REPORT_ID (9)
+        USAGE(1), 0x23,                 //     USAGE (Parameter Block Offset)
+        USAGE(1), 0x6c,                 //     USAGE (Custom Force Data Offset)
+        USAGE(1), 0x6d,                 //     USAGE (Sample Count)
+        LOGICAL_MINIMUM(1), 0x00,       //     LOGICAL_MINIMUM (0)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_COUNT(1), 0x03,          //     REPORT_COUNT (3)
+        REPORT_SIZE(1), 0x10,           //     REPORT_SIZE (16)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x77,                 //   USAGE (Effect Operation Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x0a,             //     REPORT_ID (10)
+        USAGE(1), 0x22,                 //     USAGE (Effect Block Index)
+        LOGICAL_MAXIMUM(1), 0x7f,       //     LOGICAL_MAXIMUM (127)
+        REPORT_SIZE(1), 0x07,           //     REPORT_SIZE (7)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        USAGE(1), 0x78,                 //     USAGE (Effect Operation)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE(1), 0x79,                 //       USAGE (Op Effect Start)
+        USAGE(1), 0x7a,                 //       USAGE (Op Effect Start Solo)
+        USAGE(1), 0x7b,                 //       USAGE (Op Effect Stop)
+        LOGICAL_MINIMUM(1), 0x01,       //       LOGICAL_MINIMUM (1)
+        LOGICAL_MAXIMUM(1), 0x03,       //       LOGICAL_MAXIMUM (3)
+        REPORT_SIZE(1), 0x08,           //       REPORT_SIZE (8)
+        OUTPUT(1), 0x00,                //       OUTPUT (Data,Ary,Abs)
+        END_COLLECTION(0),              //     END_COLLECTION
+        USAGE(1), 0x7c,                 //     USAGE (Loop Count)
+        LOGICAL_MINIMUM(1), 0x00,       //     LOGICAL_MINIMUM (0)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        OUTPUT(1), 0x02,                //     OUTPUT (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x7f,                 //   USAGE (PID Pool Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x01,             //     REPORT_ID (1)
+        USAGE(1), 0x80,                 //     USAGE (RAM Pool Size)
+        USAGE(1), 0x81,                 //     USAGE (ROM Pool Size)
+        USAGE(1), 0x82,                 //     USAGE (ROM Effect Block Count)
+        LOGICAL_MAXIMUM(2), 0xfd, 0x7f, //     LOGICAL_MAXIMUM (32765)
+        REPORT_COUNT(1), 0x03,          //     REPORT_COUNT (3)
+        REPORT_SIZE(1), 0x10,           //     REPORT_SIZE (16)
+        FEATURE(1), 0x02,               //     FEATURE (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x92,                 //   USAGE (PID State Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x02,             //     REPORT_ID (2)
+        USAGE(1), 0x22,                 //     USAGE (Effect Block Index)
+        LOGICAL_MAXIMUM(1), 0x7f,       //     LOGICAL_MAXIMUM (127)
+        REPORT_SIZE(1), 0x07,           //     REPORT_SIZE (7)
+        INPUT(1), 0x02,                 //     INPUT (Data,Var,Abs)
+        USAGE(1), 0x24,                 //     USAGE (ROM Flag)
+        LOGICAL_MAXIMUM(1), 0x01,       //     LOGICAL_MAXIMUM (1)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        INPUT(1), 0x02,                 //     INPUT (Data,Var,Abs)
+        USAGE(1), 0x94,                 //     USAGE (Effect Playing)
+        USAGE(1), 0xa0,                 //     USAGE (Actuators Enabled)
+        USAGE(1), 0xa4,                 //     USAGE (Safety Switch)
+        USAGE(1), 0xa6,                 //     USAGE (Actuator Power)
+        REPORT_COUNT(1), 0x04,          //     REPORT_COUNT (4)
+        INPUT(1), 0x02,                 //     INPUT (Data,Var,Abs)
+        INPUT(1), 0x03,                 //     INPUT (Cnst,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x95,                 //   USAGE (PID Device Control Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x0b,             //     REPORT_ID (11)
+        USAGE(1), 0x96,                 //     USAGE (PID Device Control)
+        COLLECTION(1), 0x02,            //     COLLECTION (Logical)
+        USAGE(1), 0x97,                 //       USAGE (DC Enable Actuators)
+        USAGE(1), 0x98,                 //       USAGE (DC Disable Actuators)
+        USAGE(1), 0x99,                 //       USAGE (DC Stop All Effects)
+        USAGE(1), 0x9a,                 //       USAGE (DC Device Reset)
+        USAGE(1), 0x9b,                 //       USAGE (DC Device Pause)
+        USAGE(1), 0x9c,                 //       USAGE (DC Device Continue)
+        LOGICAL_MINIMUM(1), 0x01,       //       LOGICAL_MINIMUM (1)
+        LOGICAL_MAXIMUM(1), 0x06,       //       LOGICAL_MAXIMUM (6)
+        REPORT_SIZE(1), 0x01,           //       REPORT_SIZE (1)
+        REPORT_COUNT(1), 0x04,          //       REPORT_COUNT (4)
+        OUTPUT(1), 0x00,                //       OUTPUT (Data,Ary,Abs)
+        END_COLLECTION(0),              //     END_COLLECTION
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x85,                 //   USAGE (PID Pool Move Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x0c,             //     REPORT_ID (12)
+        USAGE(1), 0x86,                 //     USAGE (Move Source)
+        USAGE(1), 0x87,                 //     USAGE (Move Destination)
+        USAGE(1), 0x88,                 //     USAGE (Move Length)
+        LOGICAL_MAXIMUM(2), 0xff, 0x7f, //     LOGICAL_MAXIMUM (32767)
+        REPORT_SIZE(1), 0x01,           //     REPORT_SIZE (1)
+        REPORT_COUNT(1), 0x04,          //     REPORT_COUNT (4)
+        OUTPUT(1), 0x00,                //     OUTPUT (Data,Ary,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+        USAGE(1), 0x7d,                 //   USAGE (Device Gain Report)
+        COLLECTION(1), 0x02,            //   COLLECTION (Logical)
+        REPORT_ID(1), 0x02,             //     REPORT_ID (2)
+        USAGE(1), 0x7e,                 //     USAGE (Device Gain)
+        LOGICAL_MAXIMUM(2), 0xff, 0x00, //     LOGICAL_MAXIMUM (255)
+        REPORT_SIZE(1), 0x08,           //     REPORT_SIZE (8)
+        REPORT_COUNT(1), 0x01,          //     REPORT_COUNT (1)
+        FEATURE(1), 0x02,               //     FEATURE (Data,Var,Abs)
+        END_COLLECTION(0),              //   END_COLLECTION
+#endif
+        END_COLLECTION(0)               // END_COLLECTION
+    };
 
-      reportLength = sizeof(reportDescriptor);
-      return reportDescriptor;
+    reportLength = sizeof(reportDescriptor);
+    return reportDescriptor;
 }
+
+bool USBPID::EPINT_OUT_callback() {
+    uint32_t bytesRead = 0;
+    uint8_t output[65];
+    uint8_t rID;
+    USBDevice::readEP(EPINT_OUT, output, &bytesRead, MAX_PID_REPORT_SIZE);
+
+    // get the report ID
+    rID = output[0]
+    
+    switch(rID)
+        // Set Envelope Report
+        case 1 : 
+    // 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;
+}
\ No newline at end of file
diff -r e086541742c3 -r 7f1e68e6da0c USBJoystick.h
--- a/USBJoystick.h	Thu Jan 05 14:22:02 2017 +0000
+++ b/USBJoystick.h	Sat Jul 07 10:46:53 2018 +0000
@@ -2,7 +2,7 @@
  * Copyright (c) 2012, v01:  Initial version, WH,
  *                           Modified USBMouse code ARM Limited.
  *                           (c) 2010-2011 mbed.org, MIT License
- *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button 
+ *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -26,47 +26,53 @@
 #ifndef USBJOYSTICK_H
 #define USBJOYSTICK_H
 
-#include "USBHID.h"
+#include "USBPID.h"
 
 #define REPORT_ID_JOYSTICK  4
 
 //Configure Joystick
-#define HAT4      0
-#define HAT8      1
 
+//Number of Hat Buttons
+#define HAT4      1
+#define HAT8      0
+
+//Number of Buttons
 #define BUTTONS4  0
 #define BUTTONS8  0
 #define BUTTONS32 1
 
+//Force Feedback
+#define FFB       1
+
 
 /* Common usage */
 enum JOY_BUTTON {
-     JOY_B0 = 1,
-     JOY_B1 = 2,
-     JOY_B2 = 4,
-     JOY_B3 = 8,     
+    JOY_B0 = 1,
+    JOY_B1 = 2,
+    JOY_B2 = 4,
+    JOY_B3 = 8,
 };
 
 #if (HAT4 == 1)
 enum JOY_HAT {
-     JOY_HAT_UP      = 0,
-     JOY_HAT_RIGHT   = 1,
-     JOY_HAT_DOWN    = 2,
-     JOY_HAT_LEFT    = 3,     
-     JOY_HAT_NEUTRAL = 4,          
+    JOY_HAT_UP      = 0,
+    JOY_HAT_RIGHT   = 1,
+    JOY_HAT_DOWN    = 2,
+    JOY_HAT_LEFT    = 3,
+    JOY_HAT_NEUTRAL = 4,
 };
 #endif
 #if (HAT8 == 1)
 enum JOY_HAT {
-     JOY_HAT_UP         = 0,     
-     JOY_HAT_UP_RIGHT   = 1,
-     JOY_HAT_RIGHT      = 2,
-     JOY_HAT_RIGHT_DOWN = 3,
-     JOY_HAT_DOWN       = 4,
-     JOY_HAT_DOWN_LEFT  = 5,     
-     JOY_HAT_LEFT       = 6,     
-     JOY_HAT_LEFT_UP    = 7,          
-     JOY_HAT_NEUTRAL    = 8,          
+    JOY_HAT_UP         = 0,
+    JOY_HAT_UP_RIGHT   = 1,
+    JOY_HAT_RIGHT      = 2,
+    JOY_HAT_RIGHT_DOWN = 3,
+    JOY_HAT_DOWN       = 4,
+    JOY_HAT_DOWN_LEFT  = 5,
+    JOY_HAT_LEFT       = 6,
+    JOY_HAT_LEFT_UP    = 7,
+    JOY_HAT_NEUTRAL    = 8,
 };
 #endif
 
@@ -76,9 +82,17 @@
 #define JX_MIN_ABS    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
 #define JY_MIN_ABS    (-127)     /*!< The maximum value that we can move up on the y-axis */
 #define JT_MIN_ABS    (-127)     /*!< The minimum value for the throttle */
+#define JR_MIN_ABS    (-127)     /*!< The minimum value for the rudder */
+#define JF_MIN_ABS    (-127)     /*!< The minimum value for the flaps */
+#define JB_MIN_ABS    (-127)     /*!< The minimum value for the breaks */
+#define JB_MIN_ABS    (-127)     /*!< The minimum value for the gear */
 #define JX_MAX_ABS    (127)      /*!< The maximum value that we can move to the right on the x-axis */
 #define JY_MAX_ABS    (127)      /*!< The maximum value that we can move down on the y-axis */
 #define JT_MAX_ABS    (127)      /*!< The maximum value for the throttle */
+#define JR_MAX_ABS    (127)      /*!< The maximum value for the rudder */
+#define JF_MAX_ABS    (127)      /*!< The maximum value for the flaps */
+#define JB_MAX_ABS    (127)      /*!< The maximum value for the breaks */
+#define JB_MAX_ABS    (127)      /*!< The maximum value for the gear */
 
 /**
  *
@@ -110,25 +124,25 @@
  * int main(void) {
  *   uint16_t i = 0;
  *   int16_t throttle = 0;
- *   int16_t rudder = 0;    
+ *   int16_t rudder = 0;
  *   int16_t x = 0;
  *   int16_t y = 0;
  *   int32_t radius = 120;
  *   int32_t angle = 0;
- *   uint32_t buttons = 0;    
- *   uint8_t  hat = 0;    
- *   
+ *   uint32_t buttons = 0;
+ *   uint8_t  hat = 0;
+ *
  *   while (1) {
  *       // Basic Joystick
  *       throttle = (i >> 8) & 0xFF; // value -127 .. 128
- *       rudder   = (i >> 8) & 0xFF; // value -127 .. 128        
- *       buttons  = (i >> 8) & 0x0F; // value    0 .. 15, one bit per button     
- *       hat      = (i >> 8) & 0x07; // value    0 .. 7 or 8 for neutral         
- *       i++;        
- *       
+ *       rudder   = (i >> 8) & 0xFF; // value -127 .. 128
+ *       buttons  = (i >> 8) & 0x0F; // value    0 .. 15, one bit per button
+ *       hat      = (i >> 8) & 0x07; // value    0 .. 7 or 8 for neutral
+ *       i++;
+ *
  *       x = cos((double)angle*3.14/180.0)*radius;  // value -127 .. 128
  *       y = sin((double)angle*3.14/180.0)*radius;  // value -127 .. 128
- *       angle += 3;        
+ *       angle += 3;
  *
  *       joystick.update(throttle, rudder, x, y, buttons, hat);
  *
@@ -139,101 +153,148 @@
  */
 
 
-class USBJoystick: public USBHID {
-   public:
+class USBJoystick: public USBPID
+{
+public:
 
-   /**
-     *   Constructor
-     *
-     * @param vendor_id Your vendor_id (default: 0x1234)
-     * @param product_id Your product_id (default: 0x0002)
-     * @param product_release Your product_release (default: 0x0001)
-     */
+    /**
+      *   Constructor
+      *
+      * @param vendor_id Your vendor_id (default: 0x1234)
+      * @param product_id Your product_id (default: 0x0002)
+      * @param product_release Your product_release (default: 0x0001)
+      */
 //     USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0100, uint16_t product_release = 0x0001, int waitForConnect = true):    // 4 buttons, no padding on buttons
 //     USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0500, uint16_t product_release = 0x0001, int waitForConnect = true):    // 8 buttons, no padding on buttons
-     USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0600, uint16_t product_release = 0x0001, int waitForConnect = true):    // 32 buttons, no padding on buttons
-       USBHID(0, 0, vendor_id, product_id, product_release, false) {
-         _init();
-         connect(waitForConnect);
-     };
-         
-     /**
-       * Write state of the joystick
-       *
-       * @param t throttle position
-       * @param r rudder position         
-       * @param x x-axis position
-       * @param y y-axis position
-       * @param buttons buttons state
-       * @param hat hat state 0 (up), 1 (right, 2 (down), 3 (left) or 4 (neutral)
-       * @returns true if there is no error, false otherwise
-       */
-     bool update(int16_t t, int16_t r, int16_t x, int16_t y, uint32_t buttons, uint8_t hat);
+//     USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0600, uint16_t product_release = 0x0001, int waitForConnect = true):    // 32 buttons, no padding on buttons
+    USBJoystick(uint16_t vendor_id = 0x1209, uint16_t product_id = 0x0601, uint16_t product_release = 0x0101, int waitForConnect = true):    // 32 buttons, no padding on buttons, plus Gear, Flaps and Breaks
+        USBPID(0, 0, vendor_id, product_id, product_release, false) {
+        _init();
+        connect(waitForConnect);
+    };
+
+    /**
+      * Write state of the joystick
+      *
+      * @param t throttle position
+      * @param r rudder position
+      * @param f flaps position
+      * @param b breaks position
+      * @param x x-axis position
+      * @param y y-axis position
+      * @param buttons buttons state
+      * @param hat hat state 0 (up), 1 (right, 2 (down), 3 (left) or 4 (neutral)
+      * @param 
+      * @returns true if there is no error, false otherwise
+      */
+    bool update(int16_t t, int16_t r, int16_t f, int16_t b, int16_t x, int16_t y, uint32_t buttons, uint8_t hat);
+
+    /**
+      * Write state of the joystick
+      *
+      * @returns true if there is no error, false otherwise
+      */
+    bool update();
 
-     /**
-       * Write state of the joystick
-       *
-       * @returns true if there is no error, false otherwise
-       */
-     bool update();
+    /**
+      * Move the throttle position
+      *
+      * @param t throttle position
+      * @returns true if there is no error, false otherwise
+      */
+    bool throttle(int16_t t);
+
+    /**
+      * Move the rudder position
+      *
+      * @param r rudder position
+      * @returns true if there is no error, false otherwise
+      */
+    bool rudder(int16_t r);
 
-     /**
-       * Move the throttle position
-       *
-       * @param t throttle position
-       * @returns true if there is no error, false otherwise
-       */
-     bool throttle(int16_t t);
-         
-     /**
-       * Move the rudder position
-       *
-       * @param r rudder position
-       * @returns true if there is no error, false otherwise
-       */        
-     bool rudder(int16_t r);         
+    /**
+    * Move the flaps position
+    *
+    * @param f flaps position
+    * @returns true if there is no error, false otherwise
+    */
+    bool flaps(int16_t r);
+
+    /**
+      * Move the breaks position
+      *
+      * @param b breaks position
+      * @returns true if there is no error, false otherwise
+      */
+    bool breaks(int16_t b);
 
-     /**
-       * Move the cursor to (x, y)
-       *
-       * @param x-axis position
-       * @param y-axis position
-       * @returns true if there is no error, false otherwise
-       */
-     bool move(int16_t x, int16_t y);
-         
-     /**
-       * Press one or several buttons
-       *
-       * @param buttons buttons state
-       * @returns true if there is no error, false otherwise
-       */
-     bool buttons(uint32_t buttons);
-         
-     /**
-       * Press hat
-       *
-       * @param hat hat state
-       * @returns true if there is no error, false otherwise
-       */
-     bool hat(uint8_t hat);
-         
-     /**
-       * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
-       *
-       * @returns pointer to the report descriptor
-       */
-       virtual uint8_t * reportDesc();
+    /**
+      * Move the cursor to (x, y)
+      *
+      * @param x-axis position
+      * @param y-axis position
+      * @returns true if there is no error, false otherwise
+      */
+    bool move(int16_t x, int16_t y);
+
+    /**
+      * Press one or several buttons
+      *
+      * @param buttons buttons state
+      * @returns true if there is no error, false otherwise
+      */
+    bool buttons(uint32_t buttons);
+
+    /**
+      * Press hat
+      *
+      * @param hat hat state
+      * @returns true if there is no error, false otherwise
+      */
+    bool hat(uint8_t hat);
+
+
+    /**
+      * To define the interface descriptor string.
+      *
+      * @returns pointer to the interface descriptor string
+      */
+//      virtual uint8_t * stringIinterfaceDesc();
 
-   private:
-     int8_t _t;     
-     int8_t _r;              
-     int8_t _x;                       
-     int8_t _y;     
-     uint32_t _buttons;
-     uint8_t _hat; 
-         
-     void _init();                 
+    /**
+      * To define the product descriptor string.
+      *
+      * @returns pointer to the product descriptor string
+      */
+//      virtual uint8_t * stringIproductDesc();
+
+    /**
+      * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+      *
+      * @returns pointer to the report descriptor
+      */
+    virtual uint8_t * reportDesc();
+
+    /*
+    * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
+    *
+    * @returns if handle by subclass, return true
+    */
+    virtual bool EPINT_OUT_callback();
+
+private:
+    int8_t _t;
+    int8_t _r;
+    int8_t _f;
+    int8_t _b;
+    int8_t _g;
+    int8_t _x;
+    int8_t _y;
+    uint32_t _buttons;
+    uint8_t _hat;
+
+    void _init();
+
 };
 
 #endif
\ No newline at end of file