21 #include "../../SDL_internal.h" 23 #include "../SDL_sysjoystick.h" 25 #if SDL_JOYSTICK_XINPUT 32 #include "../hidapi/SDL_hidapijoystick_c.h" 38 static char *s_arrXInputDevicePath[XUSER_MAX_COUNT];
42 SDL_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) {
74 GetXInputName(
const Uint8 userid, BYTE SubType)
78 if (SDL_XInputUseOldJoystickMapping()) {
79 SDL_snprintf(name,
sizeof(name),
"X360 Controller #%u", 1 + userid);
82 case XINPUT_DEVSUBTYPE_GAMEPAD:
83 SDL_snprintf(name,
sizeof(name),
"XInput Controller #%u", 1 + userid);
85 case XINPUT_DEVSUBTYPE_WHEEL:
86 SDL_snprintf(name,
sizeof(name),
"XInput Wheel #%u", 1 + userid);
88 case XINPUT_DEVSUBTYPE_ARCADE_STICK:
89 SDL_snprintf(name,
sizeof(name),
"XInput ArcadeStick #%u", 1 + userid);
91 case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
92 SDL_snprintf(name,
sizeof(name),
"XInput FlightStick #%u", 1 + userid);
94 case XINPUT_DEVSUBTYPE_DANCE_PAD:
95 SDL_snprintf(name,
sizeof(name),
"XInput DancePad #%u", 1 + userid);
97 case XINPUT_DEVSUBTYPE_GUITAR:
98 case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
99 case XINPUT_DEVSUBTYPE_GUITAR_BASS:
100 SDL_snprintf(name,
sizeof(name),
"XInput Guitar #%u", 1 + userid);
102 case XINPUT_DEVSUBTYPE_DRUM_KIT:
103 SDL_snprintf(name,
sizeof(name),
"XInput DrumKit #%u", 1 + userid);
105 case XINPUT_DEVSUBTYPE_ARCADE_PAD:
106 SDL_snprintf(name,
sizeof(name),
"XInput ArcadePad #%u", 1 + userid);
109 SDL_snprintf(name,
sizeof(name),
"XInput Device #%u", 1 + userid);
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);
132 if (devices ==
NULL) {
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 274 DelXInputDevice(
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;
341 UpdateXInputJoystickBatteryInformation(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:
370 UpdateXInputJoystickState_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);
397 UpdateXInputJoystickState(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();
JoyStick_DeviceData * SYS_Joystick
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
#define SDL_HARDWARE_BUS_USB
struct JoyStick_DeviceData * pNext
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint const GLchar * name
#define SDL_GetHintBoolean
#define SDL_HINT_XINPUT_ENABLED
A variable that lets you disable the detection and use of Xinput gamepad devices. ...
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
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)
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
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)
#define SDL_assert(condition)
#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)
#define SDL_arraysize(array)
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version)
#define SDL_Unsupported()