| | |
| | | |
| | | #include "SDL_windowsjoystick_c.h" |
| | | #include "SDL_dinputjoystick_c.h" |
| | | #include "SDL_rawinputjoystick_c.h" |
| | | #include "SDL_xinputjoystick_c.h" |
| | | #include "../hidapi/SDL_hidapijoystick_c.h" |
| | | |
| | |
| | | static int |
| | | SetDIerror(const char *function, HRESULT code) |
| | | { |
| | | /* |
| | | return SDL_SetError("%s() [%s]: %s", function, |
| | | DXGetErrorString9A(code), DXGetErrorDescription9A(code)); |
| | | */ |
| | | return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code); |
| | | } |
| | | |
| | |
| | | static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; |
| | | |
| | | static SDL_bool |
| | | WIN_IsXInputDevice(const GUID* pGuidProductFromDirectInput) |
| | | WIN_IsXInputDevice(const WCHAR *name, const GUID* pGuidProductFromDirectInput) |
| | | { |
| | | IWbemLocator* pIWbemLocator = NULL; |
| | | IEnumWbemClassObject* pEnumDevices = NULL; |
| | |
| | | UINT iDevice = 0; |
| | | VARIANT var; |
| | | HRESULT hr; |
| | | |
| | | if (!SDL_XINPUT_Enabled()) { |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | if (SDL_wcsstr(name, L" XINPUT ") != NULL) { |
| | | /* This is a duplicate interface for a controller that will show up with XInput, |
| | | e.g. Xbox One Elite Series 2 in Bluetooth mode. |
| | | */ |
| | | return SDL_TRUE; |
| | | } |
| | | |
| | | SDL_zeroa(pDevices); |
| | | |
| | |
| | | #endif /* 0 */ |
| | | |
| | | static SDL_bool |
| | | SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput) |
| | | SDL_IsXInputDevice(const WCHAR *name, const GUID* pGuidProductFromDirectInput) |
| | | { |
| | | UINT i; |
| | | |
| | | if (!SDL_XINPUT_Enabled()) { |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | if (SDL_wcsstr(name, L" XINPUT ") != NULL) { |
| | | /* This is a duplicate interface for a controller that will show up with XInput, |
| | | e.g. Xbox One Elite Series 2 in Bluetooth mode. |
| | | */ |
| | | return SDL_TRUE; |
| | | } |
| | | |
| | | if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) { |
| | |
| | | |
| | | for (i = 0; i < SDL_RawDevListCount; i++) { |
| | | RID_DEVICE_INFO rdi; |
| | | char devName[128]; |
| | | char devName[MAX_PATH]; |
| | | UINT rdiSize = sizeof(rdi); |
| | | UINT nameSize = SDL_arraysize(devName); |
| | | |
| | |
| | | coinitialized = SDL_TRUE; |
| | | |
| | | result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER, |
| | | &IID_IDirectInput8, (LPVOID)&dinput); |
| | | &IID_IDirectInput8, (LPVOID *)&dinput); |
| | | |
| | | if (FAILED(result)) { |
| | | return SetDIerror("CoCreateInstance", result); |
| | |
| | | /* Because we used CoCreateInstance, we need to Initialize it, first. */ |
| | | instance = GetModuleHandle(NULL); |
| | | if (instance == NULL) { |
| | | IDirectInput8_Release(dinput); |
| | | dinput = NULL; |
| | | return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError()); |
| | | } |
| | | result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION); |
| | | |
| | | if (FAILED(result)) { |
| | | IDirectInput8_Release(dinput); |
| | | dinput = NULL; |
| | | return SetDIerror("IDirectInput::Initialize", result); |
| | | } |
| | | return 0; |
| | |
| | | Uint16 product = 0; |
| | | Uint16 version = 0; |
| | | WCHAR hidPath[MAX_PATH]; |
| | | const char *name; |
| | | char *name; |
| | | |
| | | if (devtype == DI8DEVTYPE_SUPPLEMENTAL) { |
| | | /* Add any supplemental devices that should be ignored here */ |
| | |
| | | } |
| | | } |
| | | |
| | | if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) { |
| | | if (SDL_IsXInputDevice(pdidInstance->tszProductName, &pdidInstance->guidProduct)) { |
| | | return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */ |
| | | } |
| | | |
| | |
| | | pPrevJoystick->pNext = pNewJoystick->pNext; |
| | | } |
| | | |
| | | // Update with new guid/etc, if it has changed |
| | | pNewJoystick->dxdevice = *pdidInstance; |
| | | /* Update with new guid/etc, if it has changed */ |
| | | SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE)); |
| | | |
| | | pNewJoystick->pNext = SYS_Joystick; |
| | | SYS_Joystick = pNewJoystick; |
| | |
| | | SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE)); |
| | | SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data)); |
| | | |
| | | guid16 = (Uint16 *)pNewJoystick->guid.data; |
| | | if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { |
| | | vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1); |
| | | product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1); |
| | | version = 0; |
| | | } |
| | | |
| | | name = WIN_StringToUTF8(pdidInstance->tszProductName); |
| | | pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name); |
| | | SDL_free(name); |
| | | |
| | | if (!pNewJoystick->joystickname) { |
| | | SDL_free(pNewJoystick); |
| | | return DIENUM_CONTINUE; /* better luck next time? */ |
| | | } |
| | | |
| | | guid16 = (Uint16 *)pNewJoystick->guid.data; |
| | | if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { |
| | | *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); |
| | | *guid16++ = 0; |
| | | *guid16++ = SDL_SwapLE16(vendor); |
| | |
| | | SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4); |
| | | } |
| | | |
| | | name = SDL_GetCustomJoystickName(vendor, product); |
| | | if (name) { |
| | | pNewJoystick->joystickname = SDL_strdup(name); |
| | | } else { |
| | | pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName); |
| | | } |
| | | if (!pNewJoystick->joystickname) { |
| | | SDL_free(pNewJoystick); |
| | | return DIENUM_CONTINUE; /* better luck next time? */ |
| | | } |
| | | |
| | | if (SDL_strstr(pNewJoystick->joystickname, " XINPUT ") != NULL) { |
| | | /* This is a duplicate interface for a controller that will show up with XInput, |
| | | e.g. Xbox One Elite Series 2 in Bluetooth mode. |
| | | */ |
| | | SDL_free(pNewJoystick->joystickname); |
| | | SDL_free(pNewJoystick); |
| | | return DIENUM_CONTINUE; |
| | | } |
| | | |
| | | if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) { |
| | | SDL_free(pNewJoystick->joystickname); |
| | | SDL_free(pNewJoystick); |
| | |
| | | if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) { |
| | | /* The HIDAPI driver is taking care of this device */ |
| | | SDL_free(pNewJoystick->joystickname); |
| | | SDL_free(pNewJoystick); |
| | | return DIENUM_CONTINUE; |
| | | } |
| | | #endif |
| | | |
| | | #ifdef SDL_JOYSTICK_RAWINPUT |
| | | if (RAWINPUT_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) { |
| | | /* The RAWINPUT driver is taking care of this device */ |
| | | SDL_free(pNewJoystick); |
| | | return DIENUM_CONTINUE; |
| | | } |
| | |
| | | SDL_RawDevList = NULL; |
| | | } |
| | | SDL_RawDevListCount = 0; |
| | | } |
| | | |
| | | typedef struct |
| | | { |
| | | Uint16 vendor; |
| | | Uint16 product; |
| | | Uint16 version; |
| | | SDL_bool present; |
| | | } EnumJoystickPresentData; |
| | | |
| | | static BOOL CALLBACK |
| | | EnumJoystickPresentCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) |
| | | { |
| | | EnumJoystickPresentData *data = (EnumJoystickPresentData *)pContext; |
| | | Uint16 vendor = 0; |
| | | Uint16 product = 0; |
| | | Uint16 version = 0; |
| | | |
| | | if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { |
| | | vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1); |
| | | product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1); |
| | | if (data->vendor == vendor && data->product == product && data->version == version) { |
| | | data->present = SDL_TRUE; |
| | | return DIENUM_STOP; |
| | | } |
| | | } |
| | | return DIENUM_CONTINUE; |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version) |
| | | { |
| | | EnumJoystickPresentData data; |
| | | |
| | | if (dinput == NULL) { |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | data.vendor = vendor; |
| | | data.product = product; |
| | | data.version = version; |
| | | data.present = SDL_FALSE; |
| | | IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY); |
| | | |
| | | return data.present; |
| | | } |
| | | |
| | | static BOOL CALLBACK |
| | |
| | | { |
| | | } |
| | | |
| | | SDL_bool |
| | | SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version) |
| | | { |
| | | return SDL_FALSE; |
| | | } |
| | | |
| | | int |
| | | SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice) |
| | | { |