Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch Pro controllers via hid_nintendo and gyroscope (IMU) data #6478

Closed
IcedQuinn opened this issue Nov 2, 2022 · 9 comments · Fixed by #7697
Closed

Switch Pro controllers via hid_nintendo and gyroscope (IMU) data #6478

IcedQuinn opened this issue Nov 2, 2022 · 9 comments · Fixed by #7697
Assignees
Milestone

Comments

@IcedQuinn
Copy link

IcedQuinn commented Nov 2, 2022

Testing in AntiMicroX and sdl2-jstest shows that normal controls appear to work but gyroscope data does not appear to make it to the joystick interface. For some reason the driver that has been upstreamed in Linux sends IMU data to a separate /dev/input/event* interface and not to the standard joystick output. On Windows the same controller (8bit Pro 2 in Switch mode) does receive IMU data as part of controller reports and so the same software recognizes and is able to use it.

sdl2-jstest actually seems to crash the IMU endpoint with the error Error: Unhandled event type: 1543 and attempting to run cat on the raw /dev/input/event* shows it no longer reports anything until disconnected and reconnected.

I tried working with downstream first but they're refusing to touch it claiming its a library dependency issue.

Essentially and for reasons unknown to me the drivers in the latest Linux kernels create two joysticks: one with normal sensor platform data, and another which only receives IMU information via special analogue axes.

@slouken
Copy link
Collaborator

slouken commented Nov 2, 2022

This has been pretty standard practice for the Linux kernel - to create a separate event source for each of the types of events on the controller and leave it up to the application to fuse them. I'm not sure what the recommended way is of detecting which event nodes are connected to each other, but once that's done it should be possible to modify the SDL Linux joystick driver to open multiple event nodes for each logical joystick.

Feel free to submit a patch if this is important to you.

@IcedQuinn
Copy link
Author

I'm not sure what the recommended way is of detecting which event nodes are connected to each other,

There is some device identifier which is supposed the same on both of the /dev/event/input* ports despite them presenting as two devices.

@IcedQuinn
Copy link
Author

IcedQuinn commented Nov 4, 2022

Some reverse engineering.

Looks like both devices are registered with completely identical properties except the motion sensor has "IMU" in the name. https://github.com/torvalds/linux/blob/e08466a7c00733a501d3c5328d29ec974478d717/drivers/hid/hid-nintendo.c#L1723 this appears to be the only discernible difference in userland.

kernel land seems to expect you to

  • scan the event endpoints for anything with a matching device ID type
  • group by endpoints which have unique identifiers
  • separate by if \s+IMU\s* is in the name

i'm not sure how entries in /dev/input/js* get there (not a kernel programmer; only done a driver exactly once.)

@slouken
Copy link
Collaborator

slouken commented Nov 4, 2022

How do we get the unique identifier? That seems like the key information we need here.

@IcedQuinn
Copy link
Author

How do we get the unique identifier? That seems like the key information we need here.

Looks like there is an ioctl that will retrieve it given an open file descriptor. This is part of the evdev headers on Linux so shouldn't need any additional dependencies?

I found the loop that evtest uses to list devices and retrieve the names https://gitlab.freedesktop.org/libevdev/evtest/-/blob/master/evtest.c#L902 and a different ioctl gives the unique ID of the device instead of the name. Per hid-nintendo.c the UNIQ identifier will be the same for both devices belonging to the same controller.

https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/input.h#L142

#define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
#define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
#define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
#define EVIOCGPROP(len)		_IOC(_IOC_READ, 'E', 0x09, len)		/* get device properties */

@slouken
Copy link
Collaborator

slouken commented Nov 5, 2022

Great, this seems to be all the information we need to implement collecting device nodes for a single controller. I don't have time to work on this now, but you're welcome to implement a PR, or it can wait for SDL 3.0.

Thanks!

@slouken slouken added this to the 3.0 milestone Nov 5, 2022
@slouken slouken self-assigned this Nov 5, 2022
@meyraud705
Copy link
Contributor

If I understand the bug report in AntiMicroX correctly, the device with only the IMU data is reported by SDL? In this case a rule should be added to ignore it like it is done for the DualShock and Wii extension controls: https://github.com/libsdl-org/SDL/blob/main/src/joystick/SDL_gamecontroller.c#L1999

@slouken
Copy link
Collaborator

slouken commented Nov 8, 2022

If I understand the bug report in AntiMicroX correctly, the device with only the IMU data is reported by SDL? In this case a rule should be added to ignore it like it is done for the DualShock and Wii extension controls: https://github.com/libsdl-org/SDL/blob/main/src/joystick/SDL_gamecontroller.c#L1999

Good idea. This is done in 6432f45.

@marius851000
Copy link

I’ll like to comment that the same happen with the dualsense. Evtest report that it have the property type 6 (INPUT_PROP_ACCELEROMETER), if that’s usefull.

This seems to be the same issue that is described here: #4457

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants