| | |
| | | /* |
| | | Simple DirectMedia Layer |
| | | Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> |
| | | Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | |
| | | |
| | | #include "SDL_assert.h" |
| | | #include "SDL_hints.h" |
| | | #include "SDL_log.h" |
| | | #include "SDL_timer.h" |
| | | #include "SDL_windowsjoystick_c.h" |
| | | #include "SDL_xinputjoystick_c.h" |
| | |
| | | return; /* oh well. */ |
| | | } |
| | | |
| | | /* First see if we have a cached entry for this index */ |
| | | if (s_arrXInputDevicePath[userid]) { |
| | | for (i = 0; i < device_count; i++) { |
| | | RID_DEVICE_INFO rdi; |
| | | char devName[128]; |
| | |
| | | UINT nameSize = SDL_arraysize(devName); |
| | | |
| | | rdi.cbSize = sizeof(rdi); |
| | | if ((devices[i].dwType == RIM_TYPEHID) && |
| | | (GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) && |
| | | (GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) && |
| | | (SDL_strstr(devName, "IG_") != NULL)) { |
| | | if (devices[i].dwType == RIM_TYPEHID && |
| | | GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 && |
| | | GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) { |
| | | if (SDL_strcmp(devName, s_arrXInputDevicePath[userid]) == 0) { |
| | | *pVID = (Uint16)rdi.hid.dwVendorId; |
| | | *pPID = (Uint16)rdi.hid.dwProductId; |
| | | *pVersion = (Uint16)rdi.hid.dwVersionNumber; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (i = 0; i < device_count; i++) { |
| | | RID_DEVICE_INFO rdi; |
| | | char devName[128]; |
| | | UINT rdiSize = sizeof(rdi); |
| | | UINT nameSize = SDL_arraysize(devName); |
| | | |
| | | rdi.cbSize = sizeof(rdi); |
| | | if (devices[i].dwType == RIM_TYPEHID && |
| | | GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 && |
| | | GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) { |
| | | #ifdef DEBUG_JOYSTICK |
| | | SDL_Log("Raw input device: VID = 0x%x, PID = 0x%x, %s\n", rdi.hid.dwVendorId, rdi.hid.dwProductId, devName); |
| | | #endif |
| | | if (SDL_strstr(devName, "IG_") != NULL) { |
| | | SDL_bool found = SDL_FALSE; |
| | | for (j = 0; j < SDL_arraysize(s_arrXInputDevicePath); ++j) { |
| | | if (j == userid) { |
| | | continue; |
| | | } |
| | | if (!s_arrXInputDevicePath[j]) { |
| | | continue; |
| | | } |
| | |
| | | SDL_free(s_arrXInputDevicePath[userid]); |
| | | } |
| | | s_arrXInputDevicePath[userid] = SDL_strdup(devName); |
| | | break; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | SDL_free(devices); |
| | | #endif /* ifndef __WINRT__ */ |
| | | |
| | | /* The device wasn't in the raw HID device list, it's probably Bluetooth */ |
| | | *pVID = 0x045e; /* Microsoft */ |
| | | *pPID = 0x02fd; /* XBox One S Bluetooth */ |
| | | *pVersion = 0; |
| | | } |
| | | |
| | | static void |
| | |
| | | Uint16 vendor = 0; |
| | | Uint16 product = 0; |
| | | Uint16 version = 0; |
| | | const char *name; |
| | | JoyStick_DeviceData *pPrevJoystick = NULL; |
| | | JoyStick_DeviceData *pNewJoystick = *pContext; |
| | | |
| | |
| | | pNewJoystick = pNewJoystick->pNext; |
| | | } |
| | | |
| | | pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData)); |
| | | pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData)); |
| | | if (!pNewJoystick) { |
| | | return; /* better luck next time? */ |
| | | } |
| | | SDL_zerop(pNewJoystick); |
| | | |
| | | pNewJoystick->joystickname = GetXInputName(userid, SubType); |
| | | if (!pNewJoystick->joystickname) { |
| | | SDL_free(pNewJoystick); |
| | | return; /* better luck next time? */ |
| | | } |
| | | |
| | | pNewJoystick->bXInputDevice = SDL_TRUE; |
| | | if (SDL_XInputUseOldJoystickMapping()) { |
| | | SDL_zero(pNewJoystick->guid); |
| | | } else { |
| | | if (!SDL_XInputUseOldJoystickMapping()) { |
| | | Uint16 *guid16 = (Uint16 *)pNewJoystick->guid.data; |
| | | |
| | | GuessXInputDevice(userid, &vendor, &product, &version); |
| | |
| | | pNewJoystick->SubType = SubType; |
| | | pNewJoystick->XInputUserId = userid; |
| | | |
| | | name = SDL_GetCustomJoystickName(vendor, product); |
| | | if (name) { |
| | | pNewJoystick->joystickname = SDL_strdup(name); |
| | | } else { |
| | | pNewJoystick->joystickname = GetXInputName(userid, SubType); |
| | | } |
| | | if (!pNewJoystick->joystickname) { |
| | | SDL_free(pNewJoystick); |
| | | return; /* better luck next time? */ |
| | | } |
| | | |
| | | if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) { |
| | | SDL_free(pNewJoystick); |
| | | return; |
| | | } |
| | | |
| | | #ifdef SDL_JOYSTICK_HIDAPI |
| | | if (HIDAPI_IsDevicePresent(vendor, product, version)) { |
| | | if (HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)) { |
| | | /* The HIDAPI driver is taking care of this device */ |
| | | SDL_free(pNewJoystick); |
| | | return; |
| | |
| | | SDL_assert(XINPUTGETCAPABILITIES); |
| | | SDL_assert(XINPUTSETSTATE); |
| | | SDL_assert(userId < XUSER_MAX_COUNT); |
| | | |
| | | joystick->player_index = userId; |
| | | |
| | | joystick->hwdata->bXInputDevice = SDL_TRUE; |
| | | |
| | |
| | | } |
| | | |
| | | int |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) |
| | | { |
| | | XINPUT_VIBRATION XVibration; |
| | | |
| | |
| | | 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; |
| | | } |
| | |
| | | UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation); |
| | | } |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | int |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) |
| | | SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) |
| | | { |
| | | return SDL_Unsupported(); |
| | | } |