ObjFW  Diff

Differences From Artifact [a14fd08793]:

  • File src/hid/platform/Linux/OFGameController.m — part of check-in [a4fa1b26f2] at 2024-05-14 22:14:19 on branch gamecontroller — OFGameController: Fix Xbox 360 controller mapping

    It turns out the quirk for all other controllers to swap north/west was
    wrong, and the Xbox 360 controller is actually the one that has
    north/west swapped.

    The reason for this seems to be that Linux has BTN_NORTH and BTN_X
    mapped to the same code, as well as BTN_WEST to BTN_Y. However, on the
    Xbox 360 controller, Y is north and X is west. It seems that the Xbox
    360 driver decided to return BTN_X and BTN_Y (so that the labels are
    correct) while other drivers return BTN_NORTH and BTN_SOUTH (so that the
    position is correct). (user: js, size: 15062) [annotate] [blame] [check-ins using]

To Artifact [3b09a9b74f]:

  • File src/hid/platform/Linux/OFGameController.m — part of check-in [5fdf28dd29] at 2024-05-15 19:34:12 on branch gamecontroller — 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. (user: js, size: 15216) [annotate] [blame] [check-ins using]


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;