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
--- 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
--- 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