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.88k stars 110 forks source link

evdev configuration has more buttons than jsdev #359

Closed markpaters closed 2 years ago

markpaters commented 2 years ago

Version of xpadneo

0.9.1

Controller Model

Connection mode

Installed Software

Severity / Impact

Describe the Bug

It's not clear to me whether this is really a bug in xpadneo, or a wrong expectation, so this is a question as much as anything. We have a robotics application that uses a third-party library (jinput) that looks at both js and event for controllers. If determines that the same controller is showing up on both interface by (amongst other things) comparing the set of axes and buttons. With xpadneo v0.9.1, evtest returns a KEY_RECORD button that does not appear on the jstest output, causing the library to think that there are two controllers present. This does not happen on the queue/for-0.10 branch, and I can also work-around the problem by commenting out the usage map entry for KEY_RECORD in 0.9.1.

So, is it a bug that the jsdev and evdev have a different number of buttons, or is this a bad assumption by the library?

Steps to Reproduce

Nominal install of v0.9.1. Run evtest and jstest.

Expected Behavior

evtest and jstest report the same set of axes and buttons

Screenshots / GIFs / Videos

# evtest /dev/input/event18
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x45e product 0x2e0 version 0x903
Input device name: "Xbox Wireless Controller"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 167 (KEY_RECORD)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event code 307 (BTN_NORTH)
    Event code 308 (BTN_WEST)
    Event code 310 (BTN_TL)
    Event code 311 (BTN_TR)
    Event code 314 (BTN_SELECT)
    Event code 315 (BTN_START)
    Event code 317 (BTN_THUMBL)
    Event code 318 (BTN_THUMBR)
    Event code 373 (KEY_MODE)

# jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Xbox Wireless Controller) has 9 axes (X, Y, Z, Rx, Ry, Rz, Hat0X, Hat0Y, (null))
and 11 buttons (BtnA, BtnB, BtnX, BtnY, BtnTL, BtnTR, BtnSelect, BtnStart, BtnThumbL, BtnThumbR, (null)).

System Information

# uname -a
Linux wotan 5.13.0-41-generic #46~20.04.1-Ubuntu SMP Wed Apr 20 13:16:21 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
# xxd -c20 -g1 /sys/module/hid_xpadneo/drivers/hid:xpadneo/0005:045E:*/report_descriptor | tee >(cksum)
00000000: 05 01 09 05 a1 01 85 01 09 01 a1 00 09 30 09 31 15 00 27 ff  .............0.1..'.
00000014: ff 00 00 95 02 75 10 81 02 c0 09 01 a1 00 09 33 09 34 15 00  .....u.........3.4..
00000028: 27 ff ff 00 00 95 02 75 10 81 02 c0 05 01 09 32 15 00 26 ff  '......u.......2..&.
0000003c: 03 95 01 75 0a 81 02 15 00 25 00 75 06 95 01 81 03 05 01 09  ...u.....%.u........
00000050: 35 15 00 26 ff 03 95 01 75 0a 81 02 15 00 25 00 75 06 95 01  5..&....u.....%.u...
00000064: 81 03 05 01 09 39 15 01 25 08 35 00 46 3b 01 66 14 00 75 04  .....9..%.5.F;.f..u.
00000078: 95 01 81 42 75 04 95 01 15 00 25 00 35 00 45 00 65 00 81 03  ...Bu.....%.5.E.e...
0000008c: 05 09 19 01 29 0c 15 00 25 01 75 01 95 0c 81 02 15 00 25 00  ....)...%.u.......%.
000000a0: 75 01 95 04 81 03 05 0c 0a 24 02 15 00 25 01 95 01 75 01 81  u........$...%...u..
000000b4: 02 15 00 25 00 75 07 95 01 81 03 05 0c 09 01 85 02 a1 01 05  ...%.u..............
000000c8: 0c 0a 23 02 15 00 25 01 95 01 75 01 81 02 15 00 25 00 75 07  ..#...%...u.....%.u.
000000dc: 95 01 81 03 c0 05 0f 09 21 85 03 a1 02 09 97 15 00 25 01 75  ........!........%.u
000000f0: 04 95 01 91 02 15 00 25 00 75 04 95 01 91 03 09 70 15 00 25  .......%.u......p..%
00000104: 64 75 08 95 04 91 02 09 50 66 01 10 55 0e 15 00 26 ff 00 75  du......Pf..U...&..u
00000118: 08 95 01 91 02 09 a7 15 00 26 ff 00 75 08 95 01 91 02 65 00  .........&..u.....e.
0000012c: 55 00 09 7c 15 00 26 ff 00 75 08 95 01 91 02 c0 85 04 05 06  U..|..&..u..........
00000140: 09 20 15 00 26 ff 00 75 08 95 01 81 02 c0                    . ..&..u......
1703191670 1558

Controller and Bluetooth Information

Additional Context

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

kakra commented 2 years ago

According to your dmesg log, you're not actually using xpadneo:

[  157.148540] hid-generic 0005:045E:02FD.0003: unknown main item tag 0x0
[  157.148785] input: Xbox Wireless Controller as /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:11/0005:045E:02FD.0003/input/input18
[  157.148946] input: Xbox Wireless Controller Consumer Control as /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:11/0005:045E:02FD.0003/input/input19
[  157.149057] hid-generic 0005:045E:02FD.0003: input,hidraw2: BLUETOOTH HID v9.03 Gamepad [Xbox Wireless Controller] on 00:02:72:c9:53:f6
[  157.282468] input: Xbox Wireless Controller as /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:11/0005:045E:02FD.0003/input/input20
[  157.282611] microsoft 0005:045E:02FD.0003: input,hidraw2: BLUETOOTH HID v9.03 Gamepad [Xbox Wireless Controller] on 00:02:72:c9:53:f6

This uses hid-microsoft as the final driver.

The logs seem somewhat inconsistent, the XB1S controller firmware should not have KEY_MODE. Is this the first connect after boot or a later re-connect? There also seems to be a change to how modern kernels handle driver binding and how this interacts with our udev rules. It has been fixed after v0.9.1 but not yet pushed to stable (https://github.com/atar-axis/xpadneo/commit/b6c070831e418b0cfc4e604e4f6687530d66da0a).

How did you install the driver? At a first glance, this looks like xpadneo wasn't even loaded which could mean that the file in etc/modprobe.conf.d is missing. Loading the driver manually before connecting the controller can work around that.

This does not happen on the queue/for-0.10 branch

I'd like to ask you to test https://github.com/atar-axis/xpadneo/pull/325 - it has a backport of the above mentioned commit (plus a lot other fixes). Plain xpadneo master should also work. The queue/for-0.10 branch doesn't actually include any commits relevant for this issue, it's just two commits ahead of master.

Both KEY_* event items should actually be present in a separate device so jsdev wouldn't actually see them. Those are not strictly joystick buttons (where the Guide button is subject to discussion, at least it is in the wrong position by how evdev is involved).

If determines that the same controller is showing up on both interface by (amongst other things) comparing the set of axes and buttons.

I'm not sure if it is a good idea to combine jsdev and evdev. Any evdev joystick device will automatically show up in jsdev (it's actually what jsdev uses as the lower layer). And I'm not sure if there even exist devices that would only be shown in jsdev but not in evdev. As an example, it seems SDL dropped support for /dev/js* in Linux long ago.

You are seeing two different set of buttons in this bug case because jsdev ignores evdev button bits before BTN_JOYSTICK (which makes it ignore KEY_RECORD) but it will probably map all button bits after it even if they fall out of gamepad/joystick ranges (KEY_MODE). If you adjust your code (or rather jinput) to do the same, it should match again. But I'm not sure if the old jsdev interface should be used at all, I'd rather look into supporting only evdev unless you want to support hardware that is only present on jsdev (I don't know of any except maybe classical old gameports from the last millenium).

Maybe jinput does have a setting to just ignore jsdev and use evdev alone? (a quick glance says "no") I know that the Chrome gamepad API uses a very similar approach and compares jsdev and evdev, then uses evdev to map the buttons and axes, but then uses jsdev to read the values, which creates all sorts of funny effects if the order of mappings does not match (jsdev can actually re-order buttons using the jscal application to make things match jsdev games expectations). Simply speaking, it's bad design: Those both APIs have nothing in common except that jsdev creates devices from evdev in the kernel, they should not be used in combination, at least not in the way Chrome does it, I don't know jinput.

markpaters commented 2 years ago

Thanks so much for the detailed explanation! Per your comments above, I have tried #325 (hash 7bb815e) and also the tip of queue/for-0.9 (hash 351c632) and these do not work for me, but using master does! git bisect shows that the key commit is 428c6f9d68a21c13ee5472c327468e44b2585238. I'm happy using master, and for the longer term I'll suggest to the upstream project that uses jinput that they should look around for a different library.

kakra commented 2 years ago

Thanks for testing. Yes, the mentioned commit removes the key events from the main device, thus it also fixes jinput because that no longer sees the additional key bits. The v0.9 branch won't have this commit backported. Maybe we should filter out buttons in v0.9 that jsdev cannot support instead.

Could you try changing v0.9 xpadneo.h to use different event ids? Change (near the top of the file)

#define BTN_SHARE      KEY_RECORD
#define BTN_XBOX       KEY_MODE

to

#define BTN_SHARE      BTN_TRIGGER_HAPPY1
#define BTN_XBOX       BTN_MODE

I'll reopen this so we can make a v0.9-only fix for it.

markpaters commented 2 years ago

That works perfectly! Thanks :)