21 #include "../../SDL_internal.h"
23 #include "../SDL_sysjoystick.h"
25 #if SDL_JOYSTICK_XINPUT
33 #include "../hidapi/SDL_hidapijoystick_c.h"
39 static char *s_arrXInputDevicePath[XUSER_MAX_COUNT];
43 SDL_XInputUseOldJoystickMapping()
50 static int s_XInputUseOldJoystickMapping = -1;
51 if (s_XInputUseOldJoystickMapping < 0) {
54 return (s_XInputUseOldJoystickMapping > 0);
60 return s_bXInputEnabled;
68 if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
75 GetXInputName(
const Uint8 userid, BYTE SubType)
79 if (SDL_XInputUseOldJoystickMapping()) {
83 case XINPUT_DEVSUBTYPE_GAMEPAD:
86 case XINPUT_DEVSUBTYPE_WHEEL:
89 case XINPUT_DEVSUBTYPE_ARCADE_STICK:
92 case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
95 case XINPUT_DEVSUBTYPE_DANCE_PAD:
98 case XINPUT_DEVSUBTYPE_GUITAR:
99 case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
100 case XINPUT_DEVSUBTYPE_GUITAR_BASS:
103 case XINPUT_DEVSUBTYPE_DRUM_KIT:
106 case XINPUT_DEVSUBTYPE_ARCADE_PAD:
126 UINT
i,
j, device_count = 0;
128 if ((GetRawInputDeviceList(
NULL, &device_count,
sizeof(RAWINPUTDEVICELIST)) == -1) || (!device_count)) {
132 devices = (PRAWINPUTDEVICELIST)
SDL_malloc(
sizeof(RAWINPUTDEVICELIST) * device_count);
137 if (GetRawInputDeviceList(
devices, &device_count,
sizeof(RAWINPUTDEVICELIST)) == -1) {
143 if (s_arrXInputDevicePath[userid]) {
144 for (
i = 0;
i < device_count;
i++) {
147 UINT rdiSize =
sizeof(rdi);
150 rdi.cbSize =
sizeof(rdi);
151 if (
devices[
i].dwType == RIM_TYPEHID &&
152 GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 &&
153 GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) {
154 if (
SDL_strcmp(devName, s_arrXInputDevicePath[userid]) == 0) {
155 *pVID = (
Uint16)rdi.hid.dwVendorId;
156 *pPID = (
Uint16)rdi.hid.dwProductId;
157 *pVersion = (
Uint16)rdi.hid.dwVersionNumber;
164 for (
i = 0;
i < device_count;
i++) {
167 UINT rdiSize =
sizeof(rdi);
170 rdi.cbSize =
sizeof(rdi);
171 if (
devices[
i].dwType == RIM_TYPEHID &&
172 GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 &&
173 GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) {
174 #ifdef DEBUG_JOYSTICK
175 SDL_Log(
"Raw input device: VID = 0x%x, PID = 0x%x, %s\n", rdi.hid.dwVendorId, rdi.hid.dwProductId, devName);
180 if (!s_arrXInputDevicePath[
j]) {
183 if (
SDL_strcmp(devName, s_arrXInputDevicePath[
j]) == 0) {
197 *pVID = (
Uint16)rdi.hid.dwVendorId;
198 *pPID = (
Uint16)rdi.hid.dwProductId;
199 *pVersion = (
Uint16)rdi.hid.dwVersionNumber;
200 if (s_arrXInputDevicePath[userid]) {
201 SDL_free(s_arrXInputDevicePath[userid]);
203 s_arrXInputDevicePath[userid] =
SDL_strdup(devName);
227 if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
230 if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
233 while (pNewJoystick) {
236 if (pNewJoystick == *pContext) {
237 *pContext = pNewJoystick->
pNext;
238 }
else if (pPrevJoystick) {
247 pPrevJoystick = pNewJoystick;
248 pNewJoystick = pNewJoystick->
pNext;
257 if (!SDL_XInputUseOldJoystickMapping()) {
260 GuessXInputDevice(userid, &vendor, &product, &version);
273 pNewJoystick->
guid.
data[15] = SubType;
275 pNewJoystick->
SubType = SubType;
282 pNewJoystick->
joystickname = GetXInputName(userid, SubType);
294 #ifdef SDL_JOYSTICK_HIDAPI
306 DelXInputDevice(
Uint8 userid)
308 if (s_arrXInputDevicePath[userid]) {
309 SDL_free(s_arrXInputDevicePath[userid]);
310 s_arrXInputDevicePath[userid] =
NULL;
319 if (!s_bXInputEnabled) {
324 for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
326 XINPUT_CAPABILITIES capabilities;
327 if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
328 AddXInputDevice(userid, capabilities.SubType, pContext);
330 DelXInputDevice(userid);
339 XINPUT_CAPABILITIES capabilities;
340 XINPUT_VIBRATION
state;
347 joystick->hwdata->bXInputDevice =
SDL_TRUE;
349 if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
351 joystick->hwdata =
NULL;
352 return SDL_SetError(
"Failed to obtain XInput device capabilities. Device disconnected?");
355 joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &
state) == ERROR_SUCCESS);
356 joystick->hwdata->userid = userId;
359 if (SDL_XInputUseOldJoystickMapping()) {
361 joystick->nbuttons = 15;
364 joystick->nbuttons = 11;
371 UpdateXInputJoystickBatteryInformation(SDL_Joystick * joystick, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
373 if (pBatteryInformation->BatteryType != BATTERY_TYPE_UNKNOWN) {
375 if (pBatteryInformation->BatteryType == BATTERY_TYPE_WIRED) {
378 switch (pBatteryInformation->BatteryLevel) {
379 case BATTERY_LEVEL_EMPTY:
382 case BATTERY_LEVEL_LOW:
385 case BATTERY_LEVEL_MEDIUM:
389 case BATTERY_LEVEL_FULL:
400 UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
402 static WORD s_XInputButtons[] = {
403 XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
404 XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
405 XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
406 XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
409 WORD wButtons = pXInputState->Gamepad.wButtons;
423 UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
427 UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
429 static WORD s_XInputButtons[] = {
430 XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
431 XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
432 XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
435 WORD wButtons = pXInputState->Gamepad.wButtons;
450 if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
453 if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
456 if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
459 if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
464 UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
470 XINPUT_VIBRATION XVibration;
472 if (!XINPUTSETSTATE) {
476 XVibration.wLeftMotorSpeed = low_frequency_rumble;
477 XVibration.wRightMotorSpeed = high_frequency_rumble;
478 if (XINPUTSETSTATE(joystick->hwdata->userid, &XVibration) != ERROR_SUCCESS) {
488 XINPUT_STATE_EX XInputState;
489 XINPUT_BATTERY_INFORMATION_EX XBatteryInformation;
494 result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
495 if (
result == ERROR_DEVICE_NOT_CONNECTED) {
500 if (XINPUTGETBATTERYINFORMATION) {
501 result = XINPUTGETBATTERYINFORMATION(joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation);
505 if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
506 if (SDL_XInputUseOldJoystickMapping()) {
507 UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation);
509 UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation);
511 joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
523 if (s_bXInputEnabled) {
524 WIN_UnloadXInputDLL();