ObjFW  Check-in [5fdf28dd29]

Overview
Comment:OFGameController: Undo the last commit

It seems that just checking for the Xbox 360 controller VID/PID is not
sufficient, as there are a lot of controllers that are compatible with
it, but have a different VID/PID. However, they all use the xpad driver,
which returns BTN_X and BTN_Y, which in the Linux headers are equal to
BTN_NORTH and BTN_WEST - which is incorrect for an Xbox 360 controller.
It seems the Linux kernel is a huge mess where some drivers return what
is written on the button (such as Xbox 360 via the xpad driver, which
returns BTN_X/BTN_Y) and others where they are located (Sony, Nintendo,
which return BTN_NORTH/BTN_WEST). However, since Linux also maps
BTN_X/BTN_NORTH and BTN_Y/BTN_WEST to the same code, it's impossible to
figure out what the driver meant to do.

As grepping the kernel code for BTN_NORTH has revealed that not a lot of
drivers use it and given that most controllers these days are XInput
controllers (which are handled by the xpad driver), it makes more sense
to assume that a controller is an XInput controller and map the Xbox 360
buttons to their locations. It's much easier to keep a list of
controllers with drivers that actually return BTN_NORTH/BTN_WEST instead
of what's written on the button (so far it seems to be only Nintendo and
Sony) than to keep a list of all XInput controllers.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | gamecontroller
Files: files | file ages | folders
SHA3-256: 5fdf28dd295c10ad048902626ba93b62c4a110535f18e256dfd9a64f91fb82da
User & Date: js on 2024-05-15 19:34:12
Other Links: branch diff | manifest | tags
Context
2024-05-15
20:21
Add insane workarounds for Stadia controller check-in: ae7664ae48 user: js tags: gamecontroller
19:34
OFGameController: Undo the last commit check-in: 5fdf28dd29 user: js tags: gamecontroller
2024-05-14
22:14
OFGameController: Fix Xbox 360 controller mapping check-in: a4fa1b26f2 user: js tags: gamecontroller
Changes

Modified src/hid/platform/Linux/OFGameController.m from [a14fd08793] to [3b09a9b74f].

43
44
45
46
47
48
49

50
51
52
53
54
55
56
 * Controllers with tested correct mapping:
 *
 *   Microsoft X-Box 360 pad [045E:028E]
 *   Joy-Con (L) [057E:2006]
 *   Joy-Con (R) [057E:2007]
 *   N64 Controller [057E:2019]
 *   Sony Interactive Entertainment DualSense Wireless Controller [054C:0CE6]

 */

static const uint16_t vendorIDMicrosoft = 0x045E;
static const uint16_t vendorIDNintendo = 0x057E;
static const uint16_t vendorIDSony = 0x054C;

/* Microsoft controllers */







>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 * Controllers with tested correct mapping:
 *
 *   Microsoft X-Box 360 pad [045E:028E]
 *   Joy-Con (L) [057E:2006]
 *   Joy-Con (R) [057E:2007]
 *   N64 Controller [057E:2019]
 *   Sony Interactive Entertainment DualSense Wireless Controller [054C:0CE6]
 *   8BitDo Pro 2 Wired Controller [2DC8:3106]
 */

static const uint16_t vendorIDMicrosoft = 0x045E;
static const uint16_t vendorIDNintendo = 0x057E;
static const uint16_t vendorIDSony = 0x054C;

/* Microsoft controllers */
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101




102
103
104
105
106
107
108
	BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_THUMBL, BTN_THUMBR,
	BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT
};

static OFGameControllerButton
buttonToName(uint16_t button, uint16_t vendorID, uint16_t productID)
{
	if (vendorID == vendorIDMicrosoft && productID == productIDXbox360) {
		switch (button) {
		case BTN_Y:
			return OFGameControllerNorthButton;
		case BTN_X:
			return OFGameControllerWestButton;
		}
	} else if (vendorID == vendorIDNintendo &&
	    productID == productIDLeftJoycon) {
		switch (button) {
		case BTN_SELECT:
			return OFGameControllerMinusButton;
		case BTN_Z:
			return OFGameControllerCaptureButton;
		case BTN_TR:
			return OFGameControllerSLButton;
		case BTN_TR2:
			return OFGameControllerSRButton;
		}
	} else if (vendorID == vendorIDNintendo &&
	    productID == productIDRightJoycon) {
		switch (button) {




		case BTN_START:
			return OFGameControllerPlusButton;
		case BTN_TL:
			return OFGameControllerSLButton;
		case BTN_TL2:
			return OFGameControllerSRButton;
		}







<
<
<
<
<
<
<
|














>
>
>
>







74
75
76
77
78
79
80







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
	BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_THUMBL, BTN_THUMBR,
	BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT
};

static OFGameControllerButton
buttonToName(uint16_t button, uint16_t vendorID, uint16_t productID)
{







	if (vendorID == vendorIDNintendo &&
	    productID == productIDLeftJoycon) {
		switch (button) {
		case BTN_SELECT:
			return OFGameControllerMinusButton;
		case BTN_Z:
			return OFGameControllerCaptureButton;
		case BTN_TR:
			return OFGameControllerSLButton;
		case BTN_TR2:
			return OFGameControllerSRButton;
		}
	} else if (vendorID == vendorIDNintendo &&
	    productID == productIDRightJoycon) {
		switch (button) {
		case BTN_NORTH:
			return OFGameControllerNorthButton;
		case BTN_WEST:
			return OFGameControllerWestButton;
		case BTN_START:
			return OFGameControllerPlusButton;
		case BTN_TL:
			return OFGameControllerSLButton;
		case BTN_TL2:
			return OFGameControllerSRButton;
		}
120
121
122
123
124
125
126








127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
		case BTN_Y:
			return OFGameControllerCPadLeftButton;
		case BTN_C:
			return OFGameControllerCPadRightButton;
		case BTN_Z:
			return OFGameControllerCaptureButton;
		}








	}

	switch (button) {
	case BTN_NORTH:
		return OFGameControllerNorthButton;
	case BTN_SOUTH:
		return OFGameControllerSouthButton;
	case BTN_WEST:
		return OFGameControllerWestButton;
	case BTN_EAST:
		return OFGameControllerEastButton;
	case BTN_TL2:
		return OFGameControllerLeftTriggerButton;
	case BTN_TR2:
		return OFGameControllerRightTriggerButton;
	case BTN_TL:
		return OFGameControllerLeftShoulderButton;







>
>
>
>
>
>
>
>



|

|

|

|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
		case BTN_Y:
			return OFGameControllerCPadLeftButton;
		case BTN_C:
			return OFGameControllerCPadRightButton;
		case BTN_Z:
			return OFGameControllerCaptureButton;
		}
	} else if (vendorID == vendorIDSony &&
	    productID == productIDDualSense) {
		switch (button) {
		case BTN_NORTH:
			return OFGameControllerNorthButton;
		case BTN_WEST:
			return OFGameControllerWestButton;
		}
	}

	switch (button) {
	case BTN_Y:
		return OFGameControllerNorthButton;
	case BTN_A:
		return OFGameControllerSouthButton;
	case BTN_X:
		return OFGameControllerWestButton;
	case BTN_B:
		return OFGameControllerEastButton;
	case BTN_TL2:
		return OFGameControllerLeftTriggerButton;
	case BTN_TR2:
		return OFGameControllerRightTriggerButton;
	case BTN_TL:
		return OFGameControllerLeftShoulderButton;