dmadison / ArduinoXInput

XInput library for USB capable Arduino boards
http://www.partsnotincluded.com/arduino-xinput-library/
MIT License
361 stars 61 forks source link

Question Regarding the LIBRARY'S FUNCTIONALITY #71

Closed 15wileyr closed 2 years ago

15wileyr commented 2 years ago

Hello I have some past Arduino project experience but using others libraries, never written my own.

I am planning to build a personal arcade cabinet and the options on the market for USB encoders aren't as feature packed as it would be If I made my own.

I have no detailed knowledge about Xinput USB descriptors.

My question about the library is whether I could have the Arduino board function as Xinput using your Library and be able to switch modes in the code to be a keyboard HID. I'm hoping that you would know more about that side of usb drivers and all that black magic.

Basically even if I like .begin or .end the Xinput from your library, are there things in the background that would keep it from also functioning as a keyboard with another keyboard HID library installed to your knowledge?

Thanks for making this library also!

dmadison commented 2 years ago

Hello. The short answer is "no", that's not possible.

This library is written to emulate the Xbox 360 controller, which has no keyboard interface. Attempting to add additional interfaces to the descriptors will result in the driver failing to identity the controller.

USB only enumerates the descriptors on connection, which means to change USB "modes" you need to disconnect and reconnect the device. It's not enough to begin()/end() (if the class(es) support that), you need to either physically plug/unplug the device or enable/disable and potentially re-set up the USB hardware on the microcontroller to force the host to re-read the descriptors.

But the biggest roadblock is the Arduino build system. The USB "cores" modifications that make this library work are not extensible. Code compiled using the XInput core does not support any other USB modes and disables the PluggableUSB interface which could otherwise interfere with the XInput functionality. Conversely, source files for imported libraries are compiled automatically when the associated header is included, and the PluggableUSB object instances are declared within those files. In English, if you include a library such as Keyboard.h, the USB descriptors are automatically appended and cannot be removed by calling end() on the class. Arduino likes to handle USB as a compile-time constraint, which makes it difficult to change while the code is deployed.

Assuming you're building your own cabinet with a Linux machine, my suggestion would be to use the Joystick library, which uses class-compliant USB descriptors. That library will work perfectly alongside the Keyboard library. Then if you'd like to use the same inputs between both, you could use a switch to enable/disable which library your code writes to without changing the USB descriptors.

I hope that helps.

15wileyr commented 2 years ago

Thank you for writing me that excellent reply. That explains my concerns, in my case I plan to use a Windows based machine and hack up an Ultrastick u360 to make for the left stick, my back up plan is to have other Arduino boards that are dedicated to keyboard and hook them up to the buttons as well, then make a USB switch setup to handle connecting and disconnecting the different boards. Thank you for your reply, that saved me a bunch of wasted time 😃