DanielOgorchock / linux

Other
49 stars 7 forks source link

Switch Pro Controller: X and Y buttons are swapped #28

Closed SuperSamus closed 2 years ago

SuperSamus commented 2 years ago

On my Switch Pro Controller (never updated the firmware) the mappings are correct with the evdev API, but not with the legacy joystick API. The west button (X on Xbox, Y on Nintendo) is mapped as button 3, and the north button (Y on Xbox, X on Nintendo) is mapped as button 2. This should be the other way around. I never changed settings and I am not using joycond.

The A and B button are mapped correctly: the south button (A on Xbox, B on Nintendo) is mapped as button 0, and the east button (B on Xbox, A on Nintendo) is mapped as button 1.

I am using NixOS unstable, with Linux 5.14.15-zen1 x86_64, and dkms-hid-nintendo 3.2.

SuperSamus commented 2 years ago

I switched to the module from Linux 5.16, and even wiped /etc (NixOS regenerated it). The bug still persists to me.

nicman23 commented 2 years ago

you can change / configure that from userspace. look at arch wiki, specifically on the nintendo switch controller section for a ready made string for your environment (meaning env).

SuperSamus commented 2 years ago

It works (games that were swapping X and Y, like games on Steam if I use firejail, now have the correct mapping). Thanks you! EDIT: For convenience to who's reading:

SDL_GAMECONTROLLERCONFIG=050000007e0500000920000001800000,Nintendo Switch Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,030000007e0500000920000011810000,Nintendo Switch Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:b14,dpdown:b15,dpleft:b16,dpright:b17,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,

But before closing, why isn't this "correct" by default? If the Arch Wiki and the SDL database both remap the controller like this, does it mean that this wrong behavior is "intended"?

nicman23 commented 2 years ago

mostly to follow 360 maps as many people do not look at the buttons

SuperSamus commented 2 years ago

But it doesn't make much sense. If I pretend that I'm holding an Xbox controller (like I do), A and B behave like I expect, while X and Y do not. If instead I'd be looking at the controller and didn't know that Nintendo is different*, X and Y would behave like I expect, while A and B would not.

(*Technically it's Microsoft who swapped the buttons, but this doesn't have anything to do with the discussion)

SeongGino commented 2 years ago

Yeah, not gonna lie; if this has taken me several months just to find this issue and fix these two buttons mixed up on a Pro Controller, I feel like this is either an oversight or bad design in the module, and should be changed.

After all, isn't the idea to make it so that these devices can work out-of-the-box as smoothly as possible? If Linus Sebastian knew about this, he'd be livid.

(Sorry if this is necro-ing, but I felt it appropriate to complain about an issue that technically still persists in-kernel)

SuperSamus commented 2 years ago

Maybe I should reopen this.

nicman23 commented 2 years ago

pull requests for this are welcome because i am not really available atm

nezd5553 commented 2 years ago

I think this is a problem with how controllers work through HID. In input-event-codes.h, A and B follow the Xbox layout, but X and Y are swapped.

...
#define BTN_SOUTH       0x130
#define BTN_A           BTN_SOUTH
#define BTN_EAST        0x131
#define BTN_B           BTN_EAST
#define BTN_C           0x132
#define BTN_NORTH       0x133
#define BTN_X           BTN_NORTH
#define BTN_WEST        0x134
#define BTN_Y           BTN_WEST
...

I tested an Xbox-style controller with evtest and it also showed X as north and Y as west.

SuperSamus commented 2 years ago

I tried to research a bit. So, there are two interfaces: the new evdev interface, and the old joystick interface. I have no idea whether drivers communicate with them separately, or if they are something that works by itself (I'm supposing the former, because if it's the latter, then what I'm saying next will be partially wrong).

On evdev, buttons are identified with codes. Documentation: https://www.kernel.org/doc/html/latest/input/gamepad.html. It seems that on evdev the buttons for the Switch controller are mapped correctly, so it looks like Xbox is in the wrong there.

On joystick, buttons are only identified with a number. I couldn't find documentation on how they should be mapped (this is not clear at all), but it seems that from 0-3 they are mapped in order: south, east, west, north. If I'm right, the problem (that is the reason for the name of the issue) is that in the Pro Controller west is mapped as 3, and north is mapped as 2, instead of the opposite.

Finally, what games use what. The Arch Wiki says that evdev is basically the only thing being used, even SDL is using it. I did a bit of research, and it seems that the wiki is wrong. First, SDL. Basically everything uses SDL (at least for the inputs), otherwise the workaround I described above definitely wouldn't work. And while SDL does use evdev, it's not used for gamepads: for them, it uses good ol' joystick. The evidence:

So, that's basically everything I wanted to say...

...except that after I wrote this wall of text, I found out that SDL has a controller database. So... what is happening? Is it not being used? Is it SDL fault or is it whatever application I tried? (Mostly Wine, of course.)

So... I don't know what to add.

SuperSamus commented 2 years ago

I see that this is being tackled here: https://patchwork.kernel.org/project/linux-input/patch/20220512001500.16739-1-fletcher0max@gmail.com/.

SeongGino commented 2 years ago

Said patch seems to have been stalled for a few days, though.

SuperSamus commented 2 years ago

Fixed with SDL 2.24.0. (By default, SDL sets SDL_GAMECONTROLLER_USE_BUTTON_LABELS=1, which swaps both A/B and X/Y to match the button labels. Set SDL_GAMECONTROLLER_USE_BUTTON_LABELS=0 to match the positional layout. Discussion about this on https://github.com/libsdl-org/SDL/issues/6117)