In case someone needs this on the future: Here is the code of my proof of principle using the USB Host Library 2.0.
The only changes from the library example sketch are in the .cpp file. It detects any change in the steering wheel (button press of angle change), and prints the new states to the serial monitor.
The .ino file:
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
#include "hidjoystickrptparser.h"
USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid(&Usb);
JoystickEvents JoyEvents;
JoystickReportParser Joy(&JoyEvents);
void setup() {
Serial.begin(115200);
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
delay(200);
if (!Hid.SetReportParser(0, &Joy))
ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}
void loop() {
Usb.Task();
}
The .cpp file:
#include "hidjoystickrptparser.h"
JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt),
oldHat(0xDE),
oldButtons(0) {
for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
oldPad[i] = 0xD;
}
// Variabels.
int angletje = 0;
int Xval = 0;
int Yval = 0;
int DPADval = 0;
int Z2val = 0;
int Rzval = 0;
// Buttons //
// X-Channel
const int btn_X_base = 0; // base value (no buttons pressed)
const int btn_X_ids[] = {1, 2, 4, 8, 16, 32, 64, 128};
bool btn_X_states[] = {0, 0, 0, 0, 0, 0, 0, 0};
// Y-Channel
const int btn_Y_base = 224; // base value (no buttons pressed)
const int btn_Y_ids[] = {225, 226, 228, 232, 240};
bool btn_Y_states[] = {0, 0, 0, 0, 0};
// D-PAD Channel
const int btn_DPAD_base = 255; // base value
const int btn_DPAD_ids[] = {0, 1, 2, 3, 4, 5, 6, 7};
bool btn_DPAD_states[] = {0, 0, 0, 0, 0, 0, 0, 0};
void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
bool match = true;
// Checking if there are changes in report since the method was last called
for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
if (buf[i] != oldPad[i]) {
match = false;
break;
}
// Calling Game Pad event handler
if (!match && joyEvents) {
joyEvents->OnGamePadChanged((const GamePadEventData*)buf);
for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
}
uint8_t hat = (buf[5] & 0xF);
// Calling Hat Switch event handler
if (hat != oldHat && joyEvents) {
joyEvents->OnHatSwitch(hat);
oldHat = hat;
}
uint16_t buttons = (0x0000 | buf[6]);
buttons <<= 4;
buttons |= (buf[5] >> 4);
uint16_t changes = (buttons ^ oldButtons);
// Calling Button Event Handler for every button changed
if (changes) {
for (uint8_t i = 0; i < 0x0C; i++) {
uint16_t mask = (0x0001 << i);
if (((mask & changes) > 0) && joyEvents) {
if ((buttons & mask) > 0)
joyEvents->OnButtonDn(i + 1);
else
joyEvents->OnButtonUp(i + 1);
}
}
oldButtons = buttons;
}
}
void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
// Save raw values to variables.
Xval = evt->X;
Yval = evt->Y;
DPADval = evt->Z1;
Z2val = evt->Z2;
Rzval = evt->Rz;
// Check steering angle.
angletje = map(evt->Z2, 0, 255, -90, 90);
Serial.println("ANGLE:" + (String)angletje);
}
void JoystickEvents::OnHatSwitch(uint8_t hat) {
Serial.print("Hat Switch: ");
Serial.print(hat);
Serial.println("");
}
void JoystickEvents::OnButtonUp(uint8_t but_id) {
Serial.print("Up: ");
Serial.println(but_id, DEC);
}
void JoystickEvents::OnButtonDn(uint8_t but_id) {
Serial.print("Dn: ");
Serial.println(but_id, DEC);
}
The .h file:
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__
#include <usbhid.h>
struct GamePadEventData {
uint8_t X, Y, Z1, Z2, Rz;
};
class JoystickEvents {
public:
virtual void OnGamePadChanged(const GamePadEventData *evt);
virtual void OnHatSwitch(uint8_t hat);
virtual void OnButtonUp(uint8_t but_id);
virtual void OnButtonDn(uint8_t but_id);
};
#define RPT_GEMEPAD_LEN 5
class JoystickReportParser : public HIDReportParser {
JoystickEvents *joyEvents;
uint8_t oldPad[RPT_GEMEPAD_LEN];
uint8_t oldHat;
uint16_t oldButtons;
public:
JoystickReportParser(JoystickEvents *evt);
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
#endif // __HIDJOYSTICKRPTPARSER_H__