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)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
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()