21#include "../../SDL_internal.h"
23#include "../SDL_sysjoystick.h"
25#if SDL_JOYSTICK_XINPUT
32#include "../hidapi/SDL_hidapijoystick_c.h"
38static char *s_arrXInputDevicePath[XUSER_MAX_COUNT];
42SDL_XInputUseOldJoystickMapping()
49 static int s_XInputUseOldJoystickMapping = -1;
50 if (s_XInputUseOldJoystickMapping < 0) {
53 return (s_XInputUseOldJoystickMapping > 0);
59 return s_bXInputEnabled;
67 if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
74GetXInputName(
const Uint8 userid, BYTE SubType)
78 if (SDL_XInputUseOldJoystickMapping()) {
82 case XINPUT_DEVSUBTYPE_GAMEPAD:
85 case XINPUT_DEVSUBTYPE_WHEEL:
88 case XINPUT_DEVSUBTYPE_ARCADE_STICK:
91 case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
94 case XINPUT_DEVSUBTYPE_DANCE_PAD:
97 case XINPUT_DEVSUBTYPE_GUITAR:
98 case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
99 case XINPUT_DEVSUBTYPE_GUITAR_BASS:
102 case XINPUT_DEVSUBTYPE_DRUM_KIT:
105 case XINPUT_DEVSUBTYPE_ARCADE_PAD:
125 UINT
i,
j, device_count = 0;
127 if ((GetRawInputDeviceList(
NULL, &device_count,
sizeof(RAWINPUTDEVICELIST)) == -1) || (!device_count)) {
131 devices = (PRAWINPUTDEVICELIST)
SDL_malloc(
sizeof(RAWINPUTDEVICELIST) * device_count);
136 if (GetRawInputDeviceList(
devices, &device_count,
sizeof(RAWINPUTDEVICELIST)) == -1) {
141 for (
i = 0;
i < device_count;
i++) {
144 UINT rdiSize =
sizeof(rdi);
147 rdi.cbSize =
sizeof(rdi);
148 if ((
devices[
i].dwType == RIM_TYPEHID) &&
149 (GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
150 (GetRawInputDeviceInfoA(
devices[
i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
157 if (!s_arrXInputDevicePath[
j]) {
160 if (
SDL_strcmp(devName, s_arrXInputDevicePath[
j]) == 0) {
174 *pVID = (
Uint16)rdi.hid.dwVendorId;
175 *pPID = (
Uint16)rdi.hid.dwProductId;
176 *pVersion = (
Uint16)rdi.hid.dwVersionNumber;
177 if (s_arrXInputDevicePath[userid]) {
178 SDL_free(s_arrXInputDevicePath[userid]);
180 s_arrXInputDevicePath[userid] =
SDL_strdup(devName);
197 if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
200 if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
203 while (pNewJoystick) {
206 if (pNewJoystick == *pContext) {
207 *pContext = pNewJoystick->
pNext;
208 }
else if (pPrevJoystick) {
217 pPrevJoystick = pNewJoystick;
218 pNewJoystick = pNewJoystick->
pNext;
227 pNewJoystick->
joystickname = GetXInputName(userid, SubType);
234 if (SDL_XInputUseOldJoystickMapping()) {
239 GuessXInputDevice(userid, &vendor, &product, &version);
252 pNewJoystick->
guid.
data[15] = SubType;
254 pNewJoystick->
SubType = SubType;
262#ifdef SDL_JOYSTICK_HIDAPI
274DelXInputDevice(
Uint8 userid)
276 if (s_arrXInputDevicePath[userid]) {
277 SDL_free(s_arrXInputDevicePath[userid]);
278 s_arrXInputDevicePath[userid] =
NULL;
287 if (!s_bXInputEnabled) {
292 for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
294 XINPUT_CAPABILITIES capabilities;
295 if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
296 AddXInputDevice(userid, capabilities.SubType, pContext);
298 DelXInputDevice(userid);
307 XINPUT_CAPABILITIES capabilities;
308 XINPUT_VIBRATION
state;
315 joystick->player_index = userId;
317 joystick->hwdata->bXInputDevice =
SDL_TRUE;
319 if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
321 joystick->hwdata =
NULL;
322 return SDL_SetError(
"Failed to obtain XInput device capabilities. Device disconnected?");
325 joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &
state) == ERROR_SUCCESS);
326 joystick->hwdata->userid = userId;
329 if (SDL_XInputUseOldJoystickMapping()) {
331 joystick->nbuttons = 15;
334 joystick->nbuttons = 11;
341UpdateXInputJoystickBatteryInformation(SDL_Joystick * joystick, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
343 if (pBatteryInformation->BatteryType != BATTERY_TYPE_UNKNOWN) {
345 if (pBatteryInformation->BatteryType == BATTERY_TYPE_WIRED) {
348 switch (pBatteryInformation->BatteryLevel) {
349 case BATTERY_LEVEL_EMPTY:
352 case BATTERY_LEVEL_LOW:
355 case BATTERY_LEVEL_MEDIUM:
359 case BATTERY_LEVEL_FULL:
370UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
372 static WORD s_XInputButtons[] = {
373 XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
374 XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
375 XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
376 XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
379 WORD wButtons = pXInputState->Gamepad.wButtons;
393 UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
397UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
399 static WORD s_XInputButtons[] = {
400 XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
401 XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
402 XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
405 WORD wButtons = pXInputState->Gamepad.wButtons;
420 if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
423 if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
426 if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
429 if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
434 UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
440 XINPUT_VIBRATION XVibration;
442 if (!XINPUTSETSTATE) {
446 XVibration.wLeftMotorSpeed = low_frequency_rumble;
447 XVibration.wRightMotorSpeed = high_frequency_rumble;
448 if (XINPUTSETSTATE(joystick->hwdata->userid, &XVibration) != ERROR_SUCCESS) {
452 if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
453 joystick->hwdata->rumble_expiration =
SDL_GetTicks() + duration_ms;
455 joystick->hwdata->rumble_expiration = 0;
464 XINPUT_STATE_EX XInputState;
465 XINPUT_BATTERY_INFORMATION_EX XBatteryInformation;
470 result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
471 if (
result == ERROR_DEVICE_NOT_CONNECTED) {
476 if (XINPUTGETBATTERYINFORMATION) {
477 result = XINPUTGETBATTERYINFORMATION(joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation);
481 if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
482 if (SDL_XInputUseOldJoystickMapping()) {
483 UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation);
485 UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation);
487 joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
490 if (joystick->hwdata->rumble_expiration) {
506 if (s_bXInputEnabled) {
507 WIN_UnloadXInputDLL();
#define SDL_assert(condition)
#define SDL_GetHintBoolean
#define SDL_Unsupported()
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version)
#define SDL_HINT_XINPUT_ENABLED
A variable that lets you disable the detection and use of Xinput gamepad devices.
#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING
A variable that causes SDL to use the old axis and button mapping for XInput devices.
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
@ SDL_JOYSTICK_POWER_FULL
@ SDL_JOYSTICK_POWER_MEDIUM
@ SDL_JOYSTICK_POWER_EMPTY
@ SDL_JOYSTICK_POWER_UNKNOWN
@ SDL_JOYSTICK_POWER_WIRED
GLuint const GLchar * name
#define SDL_arraysize(array)
#define SDL_HARDWARE_BUS_USB
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
JoyStick_DeviceData * SYS_Joystick
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
struct JoyStick_DeviceData * pNext