| | |
| | | |
| | | #include "SDL_assert.h" |
| | | #include "SDL_hints.h" |
| | | #include "SDL_timer.h" |
| | | #include "SDL_windowsjoystick_c.h" |
| | | #include "SDL_xinputjoystick_c.h" |
| | | #include "../hidapi/SDL_hidapijoystick_c.h" |
| | | |
| | | /* |
| | | * Internal stuff. |
| | |
| | | static void |
| | | AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) |
| | | { |
| | | Uint16 vendor = 0; |
| | | Uint16 product = 0; |
| | | Uint16 version = 0; |
| | | JoyStick_DeviceData *pPrevJoystick = NULL; |
| | | JoyStick_DeviceData *pNewJoystick = *pContext; |
| | | |
| | |
| | | if (SDL_XInputUseOldJoystickMapping()) { |
| | | SDL_zero(pNewJoystick->guid); |
| | | } else { |
| | | const Uint16 BUS_USB = 0x03; |
| | | Uint16 vendor = 0; |
| | | Uint16 product = 0; |
| | | Uint16 version = 0; |
| | | Uint16 *guid16 = (Uint16 *)pNewJoystick->guid.data; |
| | | |
| | | GuessXInputDevice(userid, &vendor, &product, &version); |
| | | |
| | | *guid16++ = SDL_SwapLE16(BUS_USB); |
| | | *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); |
| | | *guid16++ = 0; |
| | | *guid16++ = SDL_SwapLE16(vendor); |
| | | *guid16++ = 0; |
| | |
| | | pNewJoystick->SubType = SubType; |
| | | pNewJoystick->XInputUserId = userid; |
| | | |
| | | if (SDL_ShouldIgnoreGameController(pNewJoystick->joystickname, pNewJoystick->guid)) { |
| | | if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) { |
| | | SDL_free(pNewJoystick); |
| | | return; |
| | | } |
| | | |
| | | SDL_SYS_AddJoystickDevice(pNewJoystick); |
| | | #ifdef SDL_JOYSTICK_HIDAPI |
| | | if (HIDAPI_IsDevicePresent(vendor, product, version)) { |
| | | /* The HIDAPI driver is taking care of this device */ |
| | | SDL_free(pNewJoystick); |
| | | return; |
| | | } |
| | | #endif |
| | | |
| | | WINDOWS_AddJoystickDevice(pNewJoystick); |
| | | } |
| | | |
| | | static void |
| | | DelXInputDevice(Uint8 userid) |
| | | { |
| | | if (s_arrXInputDevicePath[userid]) { |
| | | SDL_free(s_arrXInputDevicePath[userid]); |
| | | s_arrXInputDevicePath[userid] = NULL; |
| | | } |
| | | } |
| | | |
| | | void |
| | |
| | | XINPUT_CAPABILITIES capabilities; |
| | | if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) { |
| | | AddXInputDevice(userid, capabilities.SubType, pContext); |
| | | } else { |
| | | DelXInputDevice(userid); |
| | | } |
| | | } |
| | | } |
| | |
| | | SDL_assert(XINPUTGETCAPABILITIES); |
| | | SDL_assert(XINPUTSETSTATE); |
| | | SDL_assert(userId < XUSER_MAX_COUNT); |
| | | |
| | | joystick->player_index = userId; |
| | | |
| | | joystick->hwdata->bXInputDevice = SDL_TRUE; |
| | | |
| | |
| | | Uint8 button; |
| | | Uint8 hat = SDL_HAT_CENTERED; |
| | | |
| | | SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX); |
| | | SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY))); |
| | | SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768)); |
| | | SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX); |
| | | SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY))); |
| | | SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768)); |
| | | SDL_PrivateJoystickAxis(joystick, 0, pXInputState->Gamepad.sThumbLX); |
| | | SDL_PrivateJoystickAxis(joystick, 1, ~pXInputState->Gamepad.sThumbLY); |
| | | SDL_PrivateJoystickAxis(joystick, 2, ((int)pXInputState->Gamepad.bLeftTrigger * 257) - 32768); |
| | | SDL_PrivateJoystickAxis(joystick, 3, pXInputState->Gamepad.sThumbRX); |
| | | SDL_PrivateJoystickAxis(joystick, 4, ~pXInputState->Gamepad.sThumbRY); |
| | | SDL_PrivateJoystickAxis(joystick, 5, ((int)pXInputState->Gamepad.bRightTrigger * 257) - 32768); |
| | | |
| | | for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) { |
| | | SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED); |
| | |
| | | UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation); |
| | | } |
| | | |
| | | int |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) |
| | | { |
| | | XINPUT_VIBRATION XVibration; |
| | | |
| | | if (!XINPUTSETSTATE) { |
| | | return SDL_Unsupported(); |
| | | } |
| | | |
| | | XVibration.wLeftMotorSpeed = low_frequency_rumble; |
| | | XVibration.wRightMotorSpeed = high_frequency_rumble; |
| | | if (XINPUTSETSTATE(joystick->hwdata->userid, &XVibration) != ERROR_SUCCESS) { |
| | | return SDL_SetError("XInputSetState() failed"); |
| | | } |
| | | |
| | | if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { |
| | | joystick->hwdata->rumble_expiration = SDL_GetTicks() + duration_ms; |
| | | } else { |
| | | joystick->hwdata->rumble_expiration = 0; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | void |
| | | SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick) |
| | | { |
| | |
| | | |
| | | result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState); |
| | | if (result == ERROR_DEVICE_NOT_CONNECTED) { |
| | | Uint8 userid = joystick->hwdata->userid; |
| | | |
| | | joystick->hwdata->send_remove_event = SDL_TRUE; |
| | | joystick->hwdata->removed = SDL_TRUE; |
| | | if (s_arrXInputDevicePath[userid]) { |
| | | SDL_free(s_arrXInputDevicePath[userid]); |
| | | s_arrXInputDevicePath[userid] = NULL; |
| | | } |
| | | return; |
| | | } |
| | | |
| | |
| | | } |
| | | joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber; |
| | | } |
| | | |
| | | if (joystick->hwdata->rumble_expiration) { |
| | | Uint32 now = SDL_GetTicks(); |
| | | if (SDL_TICKS_PASSED(now, joystick->hwdata->rumble_expiration)) { |
| | | SDL_XINPUT_JoystickRumble(joystick, 0, 0, 0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void |
| | |
| | | if (s_bXInputEnabled) { |
| | | WIN_UnloadXInputDLL(); |
| | | } |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index) |
| | | { |
| | | JoyStick_DeviceData *device = SYS_Joystick; |
| | | int index; |
| | | |
| | | for (index = device_index; index > 0; index--) |
| | | device = device->pNext; |
| | | |
| | | return device->bXInputDevice; |
| | | } |
| | | |
| | | #else /* !SDL_JOYSTICK_XINPUT */ |
| | |
| | | return SDL_Unsupported(); |
| | | } |
| | | |
| | | int |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) |
| | | { |
| | | return SDL_Unsupported(); |
| | | } |
| | | |
| | | void |
| | | SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick) |
| | | { |