| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728 |
- /*
- Simple DirectMedia Layer
- 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
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "../../SDL_internal.h"
- #ifdef SDL_JOYSTICK_WGI
- #include "SDL_endian.h"
- #include "SDL_events.h"
- #include "../SDL_sysjoystick.h"
- #include "../hidapi/SDL_hidapijoystick_c.h"
- #include "../../core/windows/SDL_windows.h"
- #define COBJMACROS
- #include "windows.gaming.input.h"
- struct joystick_hwdata
- {
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller;
- __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller;
- __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo *battery;
- __x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad;
- UINT64 timestamp;
- };
- typedef struct WindowsGamingInputControllerState {
- SDL_JoystickID instance_id;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller;
- char *name;
- SDL_JoystickGUID guid;
- SDL_JoystickType type;
- int naxes;
- int nhats;
- int nbuttons;
- } WindowsGamingInputControllerState;
- static struct {
- __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *statics;
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics *arcade_stick_statics;
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2 *arcade_stick_statics2;
- __x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics *flight_stick_statics;
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics *gamepad_statics;
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *gamepad_statics2;
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics *racing_wheel_statics;
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2 *racing_wheel_statics2;
- EventRegistrationToken controller_added_token;
- EventRegistrationToken controller_removed_token;
- int controller_count;
- WindowsGamingInputControllerState *controllers;
- } wgi;
- static const IID IID_IRawGameControllerStatics = { 0xEB8D0792, 0xE95A, 0x4B19, { 0xAF, 0xC7, 0x0A, 0x59, 0xF8, 0xBF, 0x75, 0x9E } };
- static const IID IID_IRawGameController = { 0x7CAD6D91, 0xA7E1, 0x4F71, { 0x9A, 0x78, 0x33, 0xE9, 0xC5, 0xDF, 0xEA, 0x62 } };
- static const IID IID_IRawGameController2 = { 0x43C0C035, 0xBB73, 0x4756, { 0xA7, 0x87, 0x3E, 0xD6, 0xBE, 0xA6, 0x17, 0xBD } };
- static const IID IID_IEventHandler_RawGameController = { 0x00621c22, 0x42e8, 0x529f, { 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72 } };
- static const IID IID_IGameController = { 0x1BAF6522, 0x5F64, 0x42C5, { 0x82, 0x67, 0xB9, 0xFE, 0x22, 0x15, 0xBF, 0xBD } };
- static const IID IID_IGameControllerBatteryInfo = { 0xDCECC681, 0x3963, 0x4DA6, { 0x95, 0x5D, 0x55, 0x3F, 0x3B, 0x6F, 0x61, 0x61 } };
- static const IID IID_IArcadeStickStatics = { 0x5C37B8C8, 0x37B1, 0x4AD8, { 0x94, 0x58, 0x20, 0x0F, 0x1A, 0x30, 0x01, 0x8E } };
- static const IID IID_IArcadeStickStatics2 = { 0x52B5D744, 0xBB86, 0x445A, { 0xB5, 0x9C, 0x59, 0x6F, 0x0E, 0x2A, 0x49, 0xDF } };
- static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };
- static const IID IID_IFlightStickStatics = { 0x5514924A, 0xFECC, 0x435E, { 0x83, 0xDC, 0x5C, 0xEC, 0x8A, 0x18, 0xA5, 0x20 } };
- static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };
- static const IID IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
- static const IID IID_IGamepadStatics2 = { 0x42676DC5, 0x0856, 0x47C4, { 0x92, 0x13, 0xB3, 0x95, 0x50, 0x4C, 0x3A, 0x3C } };
- static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };
- static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F, 0x94, 0x69, 0xF1, 0xE6, 0x51, 0x4C, 0x7D } };
- static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
- static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };
- extern SDL_bool SDL_XINPUT_Enabled(void);
- extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
- static SDL_bool
- SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
- {
- PRAWINPUTDEVICELIST raw_devices = NULL;
- UINT i, raw_device_count = 0;
- LONG vidpid = MAKELONG(vendor, product);
- if (!SDL_XINPUT_Enabled()) {
- return SDL_FALSE;
- }
- /* Go through RAWINPUT (WinXP and later) to find HID devices. */
- if ((GetRawInputDeviceList(NULL, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!raw_device_count)) {
- return SDL_FALSE; /* oh well. */
- }
- raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count);
- if (raw_devices == NULL) {
- SDL_OutOfMemory();
- return SDL_FALSE;
- }
- if (GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
- SDL_free(raw_devices);
- raw_devices = NULL;
- return SDL_FALSE; /* oh well. */
- }
- for (i = 0; i < raw_device_count; i++) {
- RID_DEVICE_INFO rdi;
- char devName[128];
- UINT rdiSize = sizeof(rdi);
- UINT nameSize = SDL_arraysize(devName);
- rdi.cbSize = sizeof(rdi);
- if ((raw_devices[i].dwType == RIM_TYPEHID) &&
- (GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
- (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == vidpid) &&
- (GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
- (SDL_strstr(devName, "IG_") != NULL)) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
- }
- static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, REFIID riid, void **ppvObject)
- {
- if (!ppvObject) {
- return E_INVALIDARG;
- }
- *ppvObject = NULL;
- if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) {
- *ppvObject = This;
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_AddRef(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This)
- {
- return 1;
- }
- static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This)
- {
- return 1;
- }
- static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController * *e)
- {
- HRESULT hr;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
- hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
- if (SUCCEEDED(hr)) {
- char *name = NULL;
- SDL_JoystickGUID guid;
- Uint16 vendor = 0;
- Uint16 product = 0;
- Uint16 version = 0;
- SDL_JoystickType type = SDL_JOYSTICK_TYPE_UNKNOWN;
- Uint16 *guid16 = (Uint16 *)guid.data;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
- __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL;
- SDL_bool ignore_joystick = SDL_FALSE;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product);
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
- if (SUCCEEDED(hr)) {
- HSTRING hString;
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString);
- if (SUCCEEDED(hr)) {
- HMODULE hModule = LoadLibraryA("combase.dll");
- if (hModule != NULL) {
- typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length);
- WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
- if (WindowsGetStringRawBufferFunc) {
- PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL);
- if (string) {
- name = WIN_StringToUTF8(string);
- }
- }
- FreeLibrary(hModule);
- }
- }
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
- }
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller);
- if (SUCCEEDED(hr)) {
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL;
- __x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL;
- __x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad = NULL;
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheel *racing_wheel = NULL;
- if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) {
- type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
- __x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad);
- } else if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) {
- type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick);
- } else if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) {
- type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
- __x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick);
- } else if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) {
- type = SDL_JOYSTICK_TYPE_WHEEL;
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel);
- }
- __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
- }
- /* FIXME: Is there any way to tell whether this is a Bluetooth device? */
- *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(vendor);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(product);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(version);
- *guid16++ = 0;
- /* Note that this is a Windows Gaming Input device for special handling elsewhere */
- guid.data[14] = 'w';
- guid.data[15] = (Uint8)type;
- #ifdef SDL_JOYSTICK_HIDAPI
- if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
- ignore_joystick = SDL_TRUE;
- }
- #endif
- if (!ignore_joystick && SDL_DINPUT_JoystickPresent(vendor, product, version)) {
- ignore_joystick = SDL_TRUE;
- }
- if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) {
- ignore_joystick = SDL_TRUE;
- }
- if (!ignore_joystick && SDL_ShouldIgnoreJoystick(name, guid)) {
- ignore_joystick = SDL_TRUE;
- }
- if (ignore_joystick) {
- SDL_free(name);
- } else {
- /* New device, add it */
- WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
- if (controllers) {
- WindowsGamingInputControllerState *state = &controllers[wgi.controller_count];
- SDL_JoystickID joystickID = SDL_GetNextJoystickInstanceID();
- SDL_zerop(state);
- state->instance_id = joystickID;
- state->controller = controller;
- state->name = name;
- state->guid = guid;
- state->type = type;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(controller, &state->nhats);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller);
- ++wgi.controller_count;
- wgi.controllers = controllers;
- SDL_PrivateJoystickAdded(joystickID);
- }
- }
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
- }
- return S_OK;
- }
- static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemoved(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController * *e)
- {
- HRESULT hr;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
- hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
- if (SUCCEEDED(hr)) {
- int i;
- for (i = 0; i < wgi.controller_count ; i++) {
- if (wgi.controllers[i].controller == controller) {
- WindowsGamingInputControllerState *state = &wgi.controllers[i];
- SDL_JoystickID joystickID = state->instance_id;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(state->controller);
- SDL_free(state->name);
- --wgi.controller_count;
- if (i < wgi.controller_count) {
- SDL_memmove(&wgi.controllers[i], &wgi.controllers[i + 1], (wgi.controller_count - i) * sizeof(wgi.controllers[i]));
- }
- SDL_PrivateJoystickRemoved(joystickID);
- break;
- }
- }
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
- }
- return S_OK;
- }
- static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_added_vtbl = {
- IEventHandler_CRawGameControllerVtbl_QueryInterface,
- IEventHandler_CRawGameControllerVtbl_AddRef,
- IEventHandler_CRawGameControllerVtbl_Release,
- IEventHandler_CRawGameControllerVtbl_InvokeAdded
- };
- static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_added = {
- &controller_added_vtbl
- };
- static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_removed_vtbl = {
- IEventHandler_CRawGameControllerVtbl_QueryInterface,
- IEventHandler_CRawGameControllerVtbl_AddRef,
- IEventHandler_CRawGameControllerVtbl_Release,
- IEventHandler_CRawGameControllerVtbl_InvokeRemoved
- };
- static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_removed = {
- &controller_removed_vtbl
- };
- static int
- WGI_JoystickInit(void)
- {
- if (FAILED(WIN_CoInitialize())) {
- return SDL_SetError("CoInitialize() failed");
- }
- HRESULT hr;
- HMODULE hModule = LoadLibraryA("combase.dll");
- if (hModule != NULL) {
- typedef HRESULT (WINAPI *WindowsCreateString_t)(PCNZWCH sourceString, UINT32 length, HSTRING* string);
- typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string);
- typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
- WindowsCreateString_t WindowsCreateStringFunc = (WindowsCreateString_t)GetProcAddress(hModule, "WindowsCreateString");
- WindowsDeleteString_t WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
- RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
- if (WindowsCreateStringFunc && WindowsDeleteStringFunc && RoGetActivationFactoryFunc) {
- LPTSTR pNamespace;
- HSTRING hNamespaceString;
- pNamespace = L"Windows.Gaming.Input.RawGameController";
- hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
- if (SUCCEEDED(hr)) {
- hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, &wgi.statics);
- if (!SUCCEEDED(hr)) {
- SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%x", hr);
- }
- WindowsDeleteStringFunc(hNamespaceString);
- }
- pNamespace = L"Windows.Gaming.Input.ArcadeStick";
- hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
- if (SUCCEEDED(hr)) {
- hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, &wgi.arcade_stick_statics);
- if (SUCCEEDED(hr)) {
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, &wgi.arcade_stick_statics2);
- } else {
- SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%x", hr);
- }
- WindowsDeleteStringFunc(hNamespaceString);
- }
- pNamespace = L"Windows.Gaming.Input.FlightStick";
- hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
- if (SUCCEEDED(hr)) {
- hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, &wgi.flight_stick_statics);
- if (!SUCCEEDED(hr)) {
- SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%x", hr);
- }
- WindowsDeleteStringFunc(hNamespaceString);
- }
- pNamespace = L"Windows.Gaming.Input.Gamepad";
- hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
- if (SUCCEEDED(hr)) {
- hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, &wgi.gamepad_statics);
- if (SUCCEEDED(hr)) {
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, &wgi.gamepad_statics2);
- } else {
- SDL_SetError("Couldn't find IGamepadStatics: 0x%x", hr);
- }
- WindowsDeleteStringFunc(hNamespaceString);
- }
- pNamespace = L"Windows.Gaming.Input.RacingWheel";
- hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
- if (SUCCEEDED(hr)) {
- hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, &wgi.racing_wheel_statics);
- if (SUCCEEDED(hr)) {
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, &wgi.racing_wheel_statics2);
- } else {
- SDL_SetError("Couldn't find IRacingWheelStatics: 0x%x", hr);
- }
- WindowsDeleteStringFunc(hNamespaceString);
- }
- }
- FreeLibrary(hModule);
- }
- if (wgi.statics) {
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.statics, &controller_added, &wgi.controller_added_token);
- if (!SUCCEEDED(hr)) {
- SDL_SetError("add_RawGameControllerAdded() failed: 0x%x\n", hr);
- }
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.statics, &controller_removed, &wgi.controller_removed_token);
- if (!SUCCEEDED(hr)) {
- SDL_SetError("add_RawGameControllerRemoved() failed: 0x%x\n", hr);
- }
- }
- return 0;
- }
- static int
- WGI_JoystickGetCount(void)
- {
- return wgi.controller_count;
- }
- static void
- WGI_JoystickDetect(void)
- {
- }
- static const char *
- WGI_JoystickGetDeviceName(int device_index)
- {
- return wgi.controllers[device_index].name;
- }
- static int
- WGI_JoystickGetDevicePlayerIndex(int device_index)
- {
- return -1;
- }
- static void
- WGI_JoystickSetDevicePlayerIndex(int device_index, int player_index)
- {
- }
- static SDL_JoystickGUID
- WGI_JoystickGetDeviceGUID(int device_index)
- {
- return wgi.controllers[device_index].guid;
- }
- static SDL_JoystickID
- WGI_JoystickGetDeviceInstanceID(int device_index)
- {
- return wgi.controllers[device_index].instance_id;
- }
- static int
- WGI_JoystickOpen(SDL_Joystick * joystick, int device_index)
- {
- WindowsGamingInputControllerState *state = &wgi.controllers[device_index];
- struct joystick_hwdata *hwdata;
- boolean wireless = SDL_FALSE;
- hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
- if (!hwdata) {
- return SDL_OutOfMemory();
- }
- joystick->hwdata = hwdata;
- hwdata->controller = state->controller;
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(hwdata->controller);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameController, (void **)&hwdata->gamecontroller);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameControllerBatteryInfo, (void **)&hwdata->battery);
- if (wgi.gamepad_statics2) {
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->gamecontroller, &hwdata->gamepad);
- }
- if (hwdata->gamecontroller) {
- __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->gamecontroller, &wireless);
- }
- /* Initialize the joystick capabilities */
- joystick->nbuttons = state->nbuttons;
- joystick->naxes = state->naxes;
- joystick->nhats = state->nhats;
- joystick->epowerlevel = wireless ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
- if (wireless && hwdata->battery) {
- HRESULT hr;
- __x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report;
- hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report);
- if (SUCCEEDED(hr) && report) {
- int full_capacity = 0, curr_capacity = 0;
- __FIReference_1_int *full_capacityP, *curr_capacityP;
- hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP);
- if (SUCCEEDED(hr)) {
- __FIReference_1_int_get_Value(full_capacityP, &full_capacity);
- __FIReference_1_int_Release(full_capacityP);
- }
- hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP);
- if (SUCCEEDED(hr)) {
- __FIReference_1_int_get_Value(curr_capacityP, &curr_capacity);
- __FIReference_1_int_Release(curr_capacityP);
- }
- if (full_capacity > 0) {
- float ratio = (float)curr_capacity / full_capacity;
- if (ratio <= 0.05f) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
- } else if (ratio <= 0.20f) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
- } else if (ratio <= 0.70f) {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
- } else {
- joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
- }
- }
- __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report);
- }
- }
- return 0;
- }
- static int
- WGI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
- {
- struct joystick_hwdata *hwdata = joystick->hwdata;
- if (hwdata->gamepad) {
- HRESULT hr;
- struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
- SDL_zero(vibration);
- vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
- vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
- hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, vibration);
- if (SUCCEEDED(hr)) {
- return 0;
- } else {
- return SDL_SetError("Setting vibration failed: 0x%x\n", hr);
- }
- } else {
- return SDL_Unsupported();
- }
- }
- static Uint8
- ConvertHatValue(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition value)
- {
- switch (value) {
- case GameControllerSwitchPosition_Up:
- return SDL_HAT_UP;
- case GameControllerSwitchPosition_UpRight:
- return SDL_HAT_RIGHTUP;
- case GameControllerSwitchPosition_Right:
- return SDL_HAT_RIGHT;
- case GameControllerSwitchPosition_DownRight:
- return SDL_HAT_RIGHTDOWN;
- case GameControllerSwitchPosition_Down:
- return SDL_HAT_DOWN;
- case GameControllerSwitchPosition_DownLeft:
- return SDL_HAT_LEFTDOWN;
- case GameControllerSwitchPosition_Left:
- return SDL_HAT_LEFT;
- case GameControllerSwitchPosition_UpLeft:
- return SDL_HAT_LEFTUP;
- default:
- return SDL_HAT_CENTERED;
- }
- }
- static void
- WGI_JoystickUpdate(SDL_Joystick * joystick)
- {
- struct joystick_hwdata *hwdata = joystick->hwdata;
- HRESULT hr;
- UINT32 nbuttons = joystick->nbuttons;
- boolean *buttons = SDL_stack_alloc(boolean, nbuttons);
- UINT32 nhats = joystick->nhats;
- __x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition *hats = SDL_stack_alloc(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition, nhats);
- UINT32 naxes = joystick->naxes;
- DOUBLE *axes = SDL_stack_alloc(DOUBLE, naxes);
- UINT64 timestamp;
- hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_GetCurrentReading(hwdata->controller, nbuttons, buttons, nhats, hats, naxes, axes, ×tamp);
- if (SUCCEEDED(hr) && timestamp != hwdata->timestamp) {
- UINT32 i;
- for (i = 0; i < nbuttons; ++i) {
- SDL_PrivateJoystickButton(joystick, i, buttons[i]);
- }
- for (i = 0; i < nhats; ++i) {
- SDL_PrivateJoystickHat(joystick, i, ConvertHatValue(hats[i]));
- }
- for (i = 0; i < naxes; ++i) {
- SDL_PrivateJoystickAxis(joystick, i, (int)(axes[i] * 65535) - 32768);
- }
- hwdata->timestamp = timestamp;
- }
- SDL_stack_free(buttons);
- SDL_stack_free(hats);
- SDL_stack_free(axes);
- }
- static void
- WGI_JoystickClose(SDL_Joystick * joystick)
- {
- struct joystick_hwdata *hwdata = joystick->hwdata;
- if (hwdata) {
- if (hwdata->controller) {
- __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(hwdata->controller);
- }
- if (hwdata->gamecontroller) {
- __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->gamecontroller);
- }
- if (hwdata->battery) {
- __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_Release(hwdata->battery);
- }
- if (hwdata->gamepad) {
- __x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(hwdata->gamepad);
- }
- SDL_free(hwdata);
- }
- joystick->hwdata = NULL;
- }
- static void
- WGI_JoystickQuit(void)
- {
- if (wgi.statics) {
- while (wgi.controller_count > 0) {
- IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed, NULL, (__x_ABI_CWindows_CGaming_CInput_CIRawGameController **)wgi.controllers[wgi.controller_count - 1].controller);
- }
- if (wgi.controllers) {
- SDL_free(wgi.controllers);
- }
- if (wgi.arcade_stick_statics) {
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_Release(wgi.arcade_stick_statics);
- }
- if (wgi.arcade_stick_statics2) {
- __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_Release(wgi.arcade_stick_statics2);
- }
- if (wgi.flight_stick_statics) {
- __x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_Release(wgi.flight_stick_statics);
- }
- if (wgi.gamepad_statics) {
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi.gamepad_statics);
- }
- if (wgi.gamepad_statics2) {
- __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_Release(wgi.gamepad_statics2);
- }
- if (wgi.racing_wheel_statics) {
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_Release(wgi.racing_wheel_statics);
- }
- if (wgi.racing_wheel_statics2) {
- __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_Release(wgi.racing_wheel_statics2);
- }
- __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.statics, wgi.controller_added_token);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.statics, wgi.controller_removed_token);
- __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.statics);
- }
- SDL_zero(wgi);
- WIN_CoUninitialize();
- }
- static SDL_bool
- WGI_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
- {
- return SDL_FALSE;
- }
- SDL_JoystickDriver SDL_WGI_JoystickDriver =
- {
- WGI_JoystickInit,
- WGI_JoystickGetCount,
- WGI_JoystickDetect,
- WGI_JoystickGetDeviceName,
- WGI_JoystickGetDevicePlayerIndex,
- WGI_JoystickSetDevicePlayerIndex,
- WGI_JoystickGetDeviceGUID,
- WGI_JoystickGetDeviceInstanceID,
- WGI_JoystickOpen,
- WGI_JoystickRumble,
- WGI_JoystickUpdate,
- WGI_JoystickClose,
- WGI_JoystickQuit,
- WGI_JoystickGetGamepadMapping
- };
- #endif /* SDL_JOYSTICK_WGI */
- /* vi: set ts=4 sw=4 expandtab: */
|