atar-axis / xpadneo

Advanced Linux Driver for Xbox One Wireless Controller (shipped with Xbox One S)
https://atar-axis.github.io/xpadneo/
GNU General Public License v3.0
1.87k stars 110 forks source link

no input in steam after module loaded #418

Closed MNS26 closed 1 year ago

MNS26 commented 1 year ago

Version of xpadneo

Controller Model

Connection mode

Installed Software

Protocol Information

Please help us identify at which layer the problem can be found if you want to report mapping errors or if the controller fails to be detected:

Please describe how it is failing below in the next sections.

Severity / Impact

Describe the Bug

after loading the kernel module steam doesnt register ANY inputs (button or axis) but under input devices in my system settings and opening the game controller it does work

Steps to Reproduce

load kernel module -> connect Xbox controller -> open steam and go to axis calibration -> move joysticks and nothing happens

Expected Behavior

steam registering controller inputs

Screenshots / GIFs / Videos

https://youtu.be/zlWGAtrWVpU

System Information

# uname -a
Linux fedora 6.2.8-200.fc37.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Mar 22 19:11:02 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
# xxd -c20 -g1 /sys/module/hid_xpadneo/drivers/hid:xpadneo/0005:045E:*/report_descriptor | tee >(cksum)
zsh: xxd: command not found...

Controller and Bluetooth Information

xpadneo-btmon.txt xpadneo-dmesg.txt xpadneo-lsusb.txt

Additional Context

for now using the controller wired works as a work-around (wouldnt consider it like that personally tbh)

kakra commented 1 year ago

Thanks for the video, that's a great way to show the problem.

Steam Input uses SDL, please check dmesg after loading the module to find the hidraw device, then check if there are any permissions for your user to access that device (maybe also check with getfacl). Try revoking all permissions from the device and then try your SDL-based tests again.

Using evtest shows that the driver is working properly. So I can only guess there's a problem in SDL.

Please also check if jstest-sdl finds more than one device using the -l or -ls parameter.

Also check if there's a stray SDL controllerdb lying around somewhere which could improperly match on the device and mess up mappings.

MNS26 commented 1 year ago

just reran dmesg after the module was loaded and the controller got detected. xpadneo-dmesg.txt

i dont know how to use getfacl sadly. jstest-sdl show a generic xbox 360 controller because steam always make it (jstest also stoped working when steam was closed)

Also check if there's a stray SDL controllerdb lying around somewhere which could improperly match on the device and mess up mappings.

this system was/is a fresh install from a few weeks ago (finally switched to desktop), i havent touched SDL configs on this system yet

edit: all of the hid devices and js and the groups im part of image

kakra commented 1 year ago

Okay, there are no ACLs defined on the hidraw devices (indicates by the + in ls -l output). But the hidraw device belongs to the plugdev group and your user is probably part of it (run the id command to check).

So what I requested is no longer needed but just for completeness: getfacl /dev/hidraw* would list the ACLs for each hidraw device. There are none defined so it will output just the default Unix mandatory access controls for user, group and other.

This line from dmesg tells you which hidraw device has been assigned (it may change each time the driver detects the device, so check after loading the driver and connecting the controller):

[85856.711206] xpadneo 0005:045E:0B22.001E: input,hidraw10: BLUETOOTH HID v11.30 Gamepad [Xbox Wireless Controller] on ac:50:de:e7:b9:42

This time, hidraw10 got assigned. Run chmod a-rwx /dev/hidraw10 to revoke any permissions from that device (this won't be permanent and reset on next connection or driver restart). Now restart Steam to make sure any open file handle to that device would be closed. Then try again.

Also, you say that jstest-sdl stops working when Steam was closed. So what you're seeing is not your device but the virtual Steam Input controller. So please let's exclude Steam from testing first, we need to figure out why jstest-sdl does not see the controller. This means SDL does see your controller (and Steam uses SDL, so it does not see your controller, and thus jstest-sdl).

Do you run Steam from a container (e.g. flatpak)? In this case, I would expect that jstest-sdl does not see any input because Steam Input "steals" the device and it would only be visible inside the same container then.

BTW: Also xpadneo makes a generic "Xbox 360 Controller" for broader compatibility while still providing all the buttons via evdev. This is not exclusive to Steam Input. Rather, Steam Input will create a virtual Steam Input controller (which coincidentally matches with the same device ID but presents it on USB while xpadneo presents it on Bluetooth). In the end, no matter if directly via xpadneo or virtually via Steam Input, the controller would look the same to Proton wine games. Even though xpadneo uses the "Xbox 360 Controller" ID, evdev will still see the plug and play name of the device - unless you're running Steam: Then Steam Input will hide the original device and show its virtual controller which will then have it's own plug and play name but has the same device ID (but on bus 3 instead of bus 5).

You can disable the device-stealing behavior in Steam by unticking the Xbox controller support checkbox in Steam Input configuration. Now, xpadneo would be able to natively present the controller to games - except: We have to figure out why SDL does not see the controller. So please, for further tests: Uncheck Xbox controller support in Steam, or keep Steam closed.

MNS26 commented 1 year ago

i will have a go at it tomorrow (today technically) since its 1:30AM here.

MNS26 commented 1 year ago
❯ id
uid=1000(noah) gid=1000(noah) groups=1000(noah),5(tty),10(wheel),18(dialout),1001(plugdev) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
~/Desktop ❯

i have made the plugdev group because i need to have full access to it for a HOTAS with lights that i have

image those are the 2 that get generated (with xpadneo loaded) first one is xpadneo, second one is steam

Do you run Steam from a container (e.g. flatpak)?

no i have steam installed on the host OS (ideally i wanted in in a container)

You can disable the device-stealing behavior in Steam by unticking the Xbox controller support checkbox in Steam Input configuration.

i need it because since i (unintentionally) updated my controller firmware to fix the rumble crash. since then it doesnt show up as a Xbox Elite series controller but as a normal Xbox wireless controller and lost the paddles (i used to have them mapped in games and 1 for obs highlights with kb remapping in steam). i now have them remapped to my D-pad on the 3rd mode via windows and remapped my D-pad 🙁

This time, hidraw10 got assigned. Run chmod a-rwx /dev/hidraw10 to revoke any permissions from that device (this won't be permanent and reset on next connection or driver restart)

this actually made it work in steams calibration menu

❯ sudo chmod a-rwx /dev/hidraw6
~/Desktop ❯
kakra commented 1 year ago

xpadneo should support the paddles but yes, you cannot remap those without Steam Input. But that is a feature I'll develop in v0.10. I still need to reverse engineer how the reprogramming as done by Windows works but then with v0.11 stable release, you should have all the features you need.

hidraw mode from xpadneo is currently not compatible with Steam Input - thus you don't see anything in Steam Input if hidraw is readable (I will be fixing this during v0.10 or v0.11).

I suggest the following: Undo the plugdev group modifications.

Then tag your HOTAS as uaccess device via udev rules:

# /etc/udev/rules.d/60-hotas.rules
ACTION=="add|change", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", MODE="0660", TAG+="uaccess"

Replace xxxx with the hexadecimal vendor ID of your HOTAS, yyyy with the hexadecimal device ID. If your HOTAS is represented via multiple IDs, repeat the line for each ID. You can use the same method to make more input devices accessible in your user session. Alternatively, instead of matching in ATTR, you can match on the driver, e.g. DRIVER=="xpadneo" would match on our driver. If your HOTAS uses a specific driver, you can match on that.

Example: These match on my Thrustmaster HOTAS but only for the hidraw device:

# Thrustmaster TFRP Rudder
KERNEL=="hidraw*", ATTRS{idVendor}=="044f", ATTRS{idProduct}=="b679", MODE="0660", TAG+="uaccess"

# Thrustmaster TWCS Throttle
KERNEL=="hidraw*", ATTRS{idVendor}=="044f", ATTRS{idProduct}=="b687", MODE="0660", TAG+="uaccess"

# Thrustmaster T.16000M Joystick
KERNEL=="hidraw*", ATTRS{idVendor}=="044f", ATTRS{idProduct}=="b10a", MODE="0660", TAG+="uaccess"

The "60" in the name is important, "65" may also work. Background: uaccess preparation starts before order 60, uaccess evaluation happens after order 65. If the rule runs too early, it becomes overridden, if it runs too late, uaccess has been evaluated.

The uaccess tag will attach an ACL to the device nodes generated when your HOTAS is detected - but only for your running login sessions. The plugdev group is (to my best knowledge) deprecated since udev supports tagging. You can verify the ACL with getfacl /dev/path/to/hotas/device after logging in. It should list your user with write access.

The new udev rules apply after reboot (that's the easiest, there are other ways to apply at runtime).

MNS26 commented 1 year ago

Thanks for the tip to change from the plugdev group to tags, i didnt know tags were a thing for udev.

i have commented out the existing ones and replaced them with the TAG equivalent. image

i wont be using the DRIVER=="" option since i manually load the kernel only when i use the HOTAS (thx wine for breaking the mouse axis on it)

I still need to reverse engineer how the reprogramming as done by Windows works but then with v0.11 stable release, you should have all the features you need.

If there is any help needed im happy to help where i can.

kakra commented 1 year ago

thx wine for breaking the mouse axis on it

Latest Proton Experimental supports full hidraw handling, so it might be worth trying that. But you may need to exclude that device from SDL (which has its own hidraw handler):

# the matching is case-sensitive, use upper case hex codes
SDL_GAMECONTROLLER_IGNORE_DEVICES=0x06A3/0x0255,0x06A3/0x0762,0x06A3/0x075C

I'm pretty sure that the hidraw handling comes from wine upstream but is largely a result of Valve's work - so Proton may have the latest patches. Especially, some wheels and HOTAS need special handling. You may need to report that to Valve then. This way, HID is natively handled within wine, and by a native wine-driver for HID, and games see your HOTAS exactly as they do in Windows. But actually, mouse handling may be a problem here because wine expects mouse input to come from the Linux kernel. Maybe that's exactly the problem and should be fixed in wine (ignore the mouse axes from such devices).

OTOH, you could try not making hidraw accessable, so it would be handled via evdev. You may need to check if the SDL ignore is needed in this case.

From my experience: I need to ignore my joystick with SDL because otherwise some games see it as a gamepad, and non-centered axes cause continuous movement. I do NOT use the SDL ignore for, e.g., Elite Dangerous: It handles the HOTAS correctly and also handles it in parallel with my gamepad. But I didn't change this setup after the hidraw reworks in wine.

Essentially, I have a wrapper script to start Proton:

# Usage: /usr/local/bin/rungame %command%

# ... there's some more export stuff before here
[ "${PROTON_USE_JOYSTICK}" == "1" ] || export SDL_GAMECONTROLLER_IGNORE_DEVICES=${SDL_GAMECONTROLLER_IGNORE_DEVICES:+$SDL_GAMECONTROLLER_IGNORE_DEVICES,}0x044F/0xB10A,0x044F/0xB687

# broken onboard RGB controller that tries to be HID gaming input
export SDL_GAMECONTROLLER_IGNORE_DEVICES=${SDL_GAMECONTROLLER_IGNORE_DEVICES:+$SDL_GAMECONTROLLER_IGNORE_DEVICES,}0x26CE/0x01A2

exec "$@"

The Proton patches are designed to ignore duplicate devices that show up in hidraw, SDL and evdev, preferring the first match in that order.

kakra commented 1 year ago

If there is any help needed im happy to help where i can.

If you know about Bluetooth and USB capturing and Wireshark, you may try to figure out how the protocol works. For xpadneo, only HID (as used by Bluetooth) is interesting, tho it is largely identical to GIP (as used via USB, the difference is mostly only the opcode plus GIP has some more commands, e.g. turning the controller off). Here are the starting points:

MNS26 commented 1 year ago

ive done some very detailed usb packet captures for the asus linux guys, so i know the basics of it.(on or off at boot, sleep/suspend, battery, AC and a lot more)

i will be setting up a VM for this since i dont have to use dedicated hardware.

MNS26 commented 1 year ago

Latest Proton Experimental supports full hidraw handling, so it might be worth trying that.

ive already tried it with Proton, Proton-GE, Wine, Wine-GE they all have the same issue. ive looked at it before and one of the mouse axis shows as type 3 (EV_ABS), code 40 (ABS_MISC) and the other as type 3 (EV_ABS), code 41 (?) in evtest. the kernel module just hides those 2 axis since the driver/service i use directly reads it from the hidraw device

personally i still think its a kernel issue (since at one point it was gone for a while) but in the git issue they still think its wine... although it could be both https://github.com/ValveSoftware/Proton/issues/6537

kakra commented 1 year ago

personally i still think its a kernel issue

Usually, it's not the kernel because that just passes the (sometimes broken) HID descriptor over to user-space - so if user-space want's to use hidraw, it is expected to handle the broken descriptor itself.

I still think, if possible, the kernel should fix obviously broken descriptors, and some kernel input drivers actually do that, xpadneo also does it. But all devices running via hid-generic won't do it, and thus it's a user-space issue always if hid-generic is used. In that case, wine has to work around it (without having looked at the issue).

MNS26 commented 1 year ago

well it again stopped working...

when xpadneo IS loaded steam doesnt detect any inputs but now when xpadneo isnt loaded and the default xpad is used it doesnt work at all and journal thows the following message image On the upside. Steam now is able to use the back paddles over usb

MNS26 commented 1 year ago

commented out the line in the udev fixed it for now...

something else i noticed is that steam DOES see the back paddles for a moment before they are gone (over BT)

kakra commented 1 year ago

If you uncomment that line, xpadneo won't be used. hid-generic is used as it looks from your screenshot. That the attribute write fails would mean that xpadneo isn't loaded at all because udev cannot rebind the device to xpadneo.

If you want to use Steam Input, you should not use xpadneo but hid-microsoft instead. xpadneo currently isn't compatible with Steam Input.

kakra commented 1 year ago

Upcoming SDL2 version with updated xpadneo should fix issues in games and Steam Input, closing as potentially fixed. Paddles will be supported, too.