From 258a5dd0ca15ac3113f6784cd98fd0f86b35671b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 26 Aug 2014 21:12:30 +0200 Subject: [PATCH] Gamepad fixes --- Gamepad.h | 18 +-- HID.cpp | 119 +++++++++++++++++- HID.h | 2 + HID_Reports.h | 6 +- Readme.md | 19 ++- examples/AdvancedGamepad/AdvancedGamepad.ino | 28 ++--- .../AdvancedKeyboard/AdvancedKeyboard.ino | 24 +--- examples/Gamepad/Gamepad.ino | 2 + 8 files changed, 163 insertions(+), 55 deletions(-) diff --git a/Gamepad.h b/Gamepad.h index 6d51014..a6f9946 100644 --- a/Gamepad.h +++ b/Gamepad.h @@ -57,12 +57,12 @@ public: case 2: _reportID = HID_REPORTID_Gamepad2Report; break; - //case 3: - // _reportID = HID_REPORTID_Gamepad3Report; - // break; - //case 4: - // _reportID = HID_REPORTID_Gamepad4Report; - // break; + case 3: + _reportID = HID_REPORTID_Gamepad3Report; + break; + case 4: + _reportID = HID_REPORTID_Gamepad4Report; + break; default: _reportID = HID_REPORTID_NotAReport; break; @@ -75,10 +75,10 @@ public: } inline void end(void){ begin(); } - inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report));} + inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report)); } inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } - inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } - inline void releaseAll(void){ _report.buttons = 0;} + inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } + inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } inline void buttons(uint32_t b){ _report.buttons = b; } inline void xAxis(int16_t a){ _report.xAxis = a; } diff --git a/HID.cpp b/HID.cpp index e0e3d53..710581b 100644 --- a/HID.cpp +++ b/HID.cpp @@ -288,7 +288,6 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION #endif - #ifdef HID_GAMEPAD1_ENABLE // Gamepad1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) @@ -406,6 +405,124 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION #endif +#ifdef HID_GAMEPAD3_ENABLE + // Gamepad3 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad3Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 4 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_GAMEPAD4_ENABLE + // Gamepad4 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad4Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 4 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + #ifdef HID_JOYSTICK1_ENABLE // Joystick1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) diff --git a/HID.h b/HID.h index a8a14a4..6838f1c 100644 --- a/HID.h +++ b/HID.h @@ -48,6 +48,8 @@ THE SOFTWARE. #define HID_SYSTEM_ENABLE 24 #define HID_GAMEPAD1_ENABLE 71 //#define HID_GAMEPAD2_ENABLE 71 +//#define HID_GAMEPAD3_ENABLE 71 +//#define HID_GAMEPAD4_ENABLE 71 //#define HID_JOYSTICK1_ENABLE 51 //#define HID_JOYSTICK2_ENABLE 51 diff --git a/HID_Reports.h b/HID_Reports.h index e0b195d..31ca5ad 100644 --- a/HID_Reports.h +++ b/HID_Reports.h @@ -198,8 +198,10 @@ typedef enum{ HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_Gamepad3Report = 0x08, /**< Report ID for the Gamepad3 report within the device. */ + HID_REPORTID_Gamepad4Report = 0x09, /**< Report ID for the Gamepad4 report within the device. */ + HID_REPORTID_Joystick1Report = 0x10, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x11, /**< Report ID for the Joystick2 report within the device. */ HID_REPORTID_LastNotAReport, // determinate whats the maximum number of reports -1 } HID_Report_IDs; diff --git a/Readme.md b/Readme.md index 0abf45e..a529ada 100644 --- a/Readme.md +++ b/Readme.md @@ -9,7 +9,7 @@ No need for extra hardware. You just need one of the Arduinos and an USB cable. **Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! -**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader.** +**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader (like on Uno/Mega).** Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) @@ -57,11 +57,12 @@ Over all the Uno/Mega solution gives you more opportunities except that the Seri Installation Leonardo/Micro/Uno/Mega ==================================== + +#### Leonardo/Micro only Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. **For the whole Project IDE 1.5.7 or higher is recommended!** -#### Leonardo/Micro only **Edit HID.h to de/activate usb functions.** By default Mouse, Keyboard, Media, System, Gamepad1 is activated. @@ -71,12 +72,18 @@ You cannot use more than 255 bytes HID report on the Leonardo/Micro. The number after each definition tells you the size of each report. I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. -#### Uno/Mega only +#### Uno/Mega onl +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. + +**For the whole Project IDE 1.5.7 or higher is recommended!** + To install the new bootloader connect your Arduino to your PC via USB and see [Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). No special programmer needed, just an USB cable. **You can always switch back to the original firmware, nothing to break.** +Edit HID.h to add an extra delay for raspberry pi. This is a workaround to fix this for slower PCs. There is still a problem with Raspberry. + Usage ===== You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. @@ -103,9 +110,11 @@ Updating to a newer Version =========================== HID library: -To upgrade to v1.8 you need to redownload the ide files, replace the original files and install the library like you are used to. +To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the original files and install the library like you are used to. +You library is now located in sketchbook/libraries/HID/ +Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. -Hoodloader: +Hoodloader (Not needed for Leonardo/Micro): Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. diff --git a/examples/AdvancedGamepad/AdvancedGamepad.ino b/examples/AdvancedGamepad/AdvancedGamepad.ino index 10dba0d..bd8eb03 100644 --- a/examples/AdvancedGamepad/AdvancedGamepad.ino +++ b/examples/AdvancedGamepad/AdvancedGamepad.ino @@ -1,15 +1,13 @@ /* -Copyright (c) 2014 NicoHood + Copyright (c) 2014 NicoHood See the readme for credit to other people. Advanced Gamepad example */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -20,24 +18,15 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); } void loop() { @@ -56,7 +45,7 @@ void loop() { // functions before only set the values // this writes the report to the host - HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); // simple debounce delay(300); @@ -64,4 +53,3 @@ void loop() { } } - diff --git a/examples/AdvancedKeyboard/AdvancedKeyboard.ino b/examples/AdvancedKeyboard/AdvancedKeyboard.ino index 708ae91..725f1be 100644 --- a/examples/AdvancedKeyboard/AdvancedKeyboard.ino +++ b/examples/AdvancedKeyboard/AdvancedKeyboard.ino @@ -5,11 +5,9 @@ Copyright (c) 2014 NicoHood Advanced Keyboard example */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -17,22 +15,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. pressRawKeyboard(0, 0); } @@ -59,7 +48,7 @@ void loop() { void pressRawKeyboard(uint8_t modifiers, uint8_t key) { uint8_t keys[8] = { modifiers, 0, key, 0, 0, 0, 0, 0 }; //modifiers, reserved, key[0] - HID.sendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); + HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); } /* @@ -108,4 +97,3 @@ See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys RAW_KEYBOARD_SCROLL_LOCK RAW_KEYBOARD_PAUSE */ - diff --git a/examples/Gamepad/Gamepad.ino b/examples/Gamepad/Gamepad.ino index 191b374..44dd2ce 100644 --- a/examples/Gamepad/Gamepad.ino +++ b/examples/Gamepad/Gamepad.ino @@ -12,6 +12,8 @@ Press a button and demonstrate Gamepad actions // create a new Gamepad instance (1-4) Gamepad Gamepad1(1); //Gamepad Gamepad2(2); +//Gamepad Gamepad3(3); +//Gamepad Gamepad4(4); const int pinLed = 13; const int pinButton = 8;