summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c')
-rw-r--r--contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c693
1 files changed, 693 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c b/contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c
new file mode 100644
index 0000000..e7fbfcb
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/joystick/windows/SDL_windowsjoystick.c
@@ -0,0 +1,693 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
24
25/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
26 * A. Formiga's WINMM driver.
27 *
28 * Hats and sliders are completely untested; the app I'm writing this for mostly
29 * doesn't use them and I don't own any joysticks with them.
30 *
31 * We don't bother to use event notification here. It doesn't seem to work
32 * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
33 * let it return 0 events. */
34
35#include "../SDL_sysjoystick.h"
36#include "../../thread/SDL_systhread.h"
37#include "../../core/windows/SDL_windows.h"
38#include "../../core/windows/SDL_hid.h"
39#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
40#include <dbt.h>
41#endif
42
43#define INITGUID // Only set here, if set twice will cause mingw32 to break.
44#include "SDL_windowsjoystick_c.h"
45#include "SDL_dinputjoystick_c.h"
46#include "SDL_xinputjoystick_c.h"
47#include "SDL_rawinputjoystick_c.h"
48
49#include "../../haptic/windows/SDL_dinputhaptic_c.h" // For haptic hot plugging
50
51#ifndef DEVICE_NOTIFY_WINDOW_HANDLE
52#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
53#endif
54
55// local variables
56static bool s_bJoystickThread = false;
57static SDL_Condition *s_condJoystickThread = NULL;
58static SDL_Mutex *s_mutexJoyStickEnum = NULL;
59static SDL_Thread *s_joystickThread = NULL;
60static bool s_bJoystickThreadQuit = false;
61static Uint64 s_lastDeviceChange = 0;
62static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
63
64JoyStick_DeviceData *SYS_Joystick; // array to hold joystick ID values
65
66
67static bool WindowsDeviceChanged(void)
68{
69 return (s_lastDeviceChange != WIN_GetLastDeviceNotification());
70}
71
72static void SetWindowsDeviceChanged(void)
73{
74 s_lastDeviceChange = 0;
75}
76
77void WINDOWS_RAWINPUTEnabledChanged(void)
78{
79 SetWindowsDeviceChanged();
80}
81
82#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
83
84typedef struct
85{
86 HRESULT coinitialized;
87 WNDCLASSEX wincl;
88 HWND messageWindow;
89 HDEVNOTIFY hNotify;
90} SDL_DeviceNotificationData;
91
92#define IDT_SDL_DEVICE_CHANGE_TIMER_1 1200
93#define IDT_SDL_DEVICE_CHANGE_TIMER_2 1201
94
95// windowproc for our joystick detect thread message only window, to detect any USB device addition/removal
96static LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
97{
98 switch (msg) {
99 case WM_DEVICECHANGE:
100 switch (wParam) {
101 case DBT_DEVICEARRIVAL:
102 case DBT_DEVICEREMOVECOMPLETE:
103 if (((DEV_BROADCAST_HDR *)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
104 // notify 300ms and 2 seconds later to ensure all APIs have updated status
105 SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_1, 300, NULL);
106 SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_2, 2000, NULL);
107 }
108 break;
109 }
110 return true;
111 case WM_TIMER:
112 if (wParam == IDT_SDL_DEVICE_CHANGE_TIMER_1 ||
113 wParam == IDT_SDL_DEVICE_CHANGE_TIMER_2) {
114 KillTimer(hwnd, wParam);
115 SetWindowsDeviceChanged();
116 return true;
117 }
118 break;
119 }
120
121#ifdef SDL_JOYSTICK_RAWINPUT
122 return CallWindowProc(RAWINPUT_WindowProc, hwnd, msg, wParam, lParam);
123#else
124 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
125#endif
126}
127
128static void SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
129{
130#ifdef SDL_JOYSTICK_RAWINPUT
131 RAWINPUT_UnregisterNotifications();
132#endif
133
134 if (data->hNotify) {
135 UnregisterDeviceNotification(data->hNotify);
136 }
137
138 if (data->messageWindow) {
139 DestroyWindow(data->messageWindow);
140 }
141
142 UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
143
144 if (data->coinitialized == S_OK) {
145 WIN_CoUninitialize();
146 }
147}
148
149static bool SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
150{
151 DEV_BROADCAST_DEVICEINTERFACE dbh;
152
153 SDL_zerop(data);
154
155 data->coinitialized = WIN_CoInitialize();
156
157 data->wincl.hInstance = GetModuleHandle(NULL);
158 data->wincl.lpszClassName = TEXT("Message");
159 data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; // This function is called by windows
160 data->wincl.cbSize = sizeof(WNDCLASSEX);
161
162 if (!RegisterClassEx(&data->wincl)) {
163 WIN_SetError("Failed to create register class for joystick autodetect");
164 SDL_CleanupDeviceNotification(data);
165 return false;
166 }
167
168 data->messageWindow = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
169 if (!data->messageWindow) {
170 WIN_SetError("Failed to create message window for joystick autodetect");
171 SDL_CleanupDeviceNotification(data);
172 return false;
173 }
174
175 SDL_zero(dbh);
176 dbh.dbcc_size = sizeof(dbh);
177 dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
178 dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
179
180 data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
181 if (!data->hNotify) {
182 WIN_SetError("Failed to create notify device for joystick autodetect");
183 SDL_CleanupDeviceNotification(data);
184 return false;
185 }
186
187#ifdef SDL_JOYSTICK_RAWINPUT
188 RAWINPUT_RegisterNotifications(data->messageWindow);
189#endif
190 return true;
191}
192
193static bool SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_Mutex *mutex)
194{
195 MSG msg;
196 int lastret = 1;
197
198 if (!data->messageWindow) {
199 return false; // device notifications require a window
200 }
201
202 SDL_UnlockMutex(mutex);
203 while (lastret > 0 && !WindowsDeviceChanged()) {
204 lastret = GetMessage(&msg, NULL, 0, 0); // WM_QUIT causes return value of 0
205 if (lastret > 0) {
206 TranslateMessage(&msg);
207 DispatchMessage(&msg);
208 }
209 }
210 SDL_LockMutex(mutex);
211 return (lastret != -1);
212}
213
214#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
215
216#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
217static SDL_DeviceNotificationData s_notification_data;
218#endif
219
220// Function/thread to scan the system for joysticks.
221static int SDLCALL SDL_JoystickThread(void *_data)
222{
223#ifdef SDL_JOYSTICK_XINPUT
224 bool bOpenedXInputDevices[XUSER_MAX_COUNT];
225 SDL_zeroa(bOpenedXInputDevices);
226#endif
227
228#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
229 if (!SDL_CreateDeviceNotification(&s_notification_data)) {
230 return 0;
231 }
232#endif
233
234 SDL_LockMutex(s_mutexJoyStickEnum);
235 while (s_bJoystickThreadQuit == false) {
236#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
237 if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == false) {
238#else
239 {
240#endif
241#ifdef SDL_JOYSTICK_XINPUT
242 // WM_DEVICECHANGE not working, poll for new XINPUT controllers
243 SDL_WaitConditionTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
244 if (SDL_XINPUT_Enabled()) {
245 // scan for any change in XInput devices
246 Uint8 userId;
247 for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
248 XINPUT_CAPABILITIES capabilities;
249 const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
250 const bool available = (result == ERROR_SUCCESS);
251 if (bOpenedXInputDevices[userId] != available) {
252 SetWindowsDeviceChanged();
253 bOpenedXInputDevices[userId] = available;
254 }
255 }
256 }
257#else
258 // WM_DEVICECHANGE not working, no XINPUT, no point in keeping thread alive
259 break;
260#endif // SDL_JOYSTICK_XINPUT
261 }
262 }
263
264 SDL_UnlockMutex(s_mutexJoyStickEnum);
265
266#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
267 SDL_CleanupDeviceNotification(&s_notification_data);
268#endif
269
270 return 1;
271}
272
273// spin up the thread to detect hotplug of devices
274static bool SDL_StartJoystickThread(void)
275{
276 s_mutexJoyStickEnum = SDL_CreateMutex();
277 if (!s_mutexJoyStickEnum) {
278 return false;
279 }
280
281 s_condJoystickThread = SDL_CreateCondition();
282 if (!s_condJoystickThread) {
283 return false;
284 }
285
286 s_bJoystickThreadQuit = false;
287 s_joystickThread = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
288 if (!s_joystickThread) {
289 return false;
290 }
291 return true;
292}
293
294static void SDL_StopJoystickThread(void)
295{
296 if (!s_joystickThread) {
297 return;
298 }
299
300 SDL_LockMutex(s_mutexJoyStickEnum);
301 s_bJoystickThreadQuit = true;
302 SDL_BroadcastCondition(s_condJoystickThread); // signal the joystick thread to quit
303 SDL_UnlockMutex(s_mutexJoyStickEnum);
304 PostThreadMessage((DWORD)SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0);
305
306 // Unlock joysticks while the joystick thread finishes processing messages
307 SDL_AssertJoysticksLocked();
308 SDL_UnlockJoysticks();
309 SDL_WaitThread(s_joystickThread, NULL); // wait for it to bugger off
310 SDL_LockJoysticks();
311
312 SDL_DestroyCondition(s_condJoystickThread);
313 s_condJoystickThread = NULL;
314
315 SDL_DestroyMutex(s_mutexJoyStickEnum);
316 s_mutexJoyStickEnum = NULL;
317
318 s_joystickThread = NULL;
319}
320
321void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
322{
323 device->send_add_event = true;
324 device->nInstanceID = SDL_GetNextObjectID();
325 device->pNext = SYS_Joystick;
326 SYS_Joystick = device;
327}
328
329void WINDOWS_JoystickDetect(void);
330void WINDOWS_JoystickQuit(void);
331
332static bool WINDOWS_JoystickInit(void)
333{
334 if (!SDL_XINPUT_JoystickInit()) {
335 WINDOWS_JoystickQuit();
336 return false;
337 }
338
339 if (!SDL_DINPUT_JoystickInit()) {
340 WINDOWS_JoystickQuit();
341 return false;
342 }
343
344 WIN_InitDeviceNotification();
345
346#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
347 s_bJoystickThread = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_THREAD, true);
348 if (s_bJoystickThread) {
349 if (!SDL_StartJoystickThread()) {
350 return false;
351 }
352 } else {
353 if (!SDL_CreateDeviceNotification(&s_notification_data)) {
354 return false;
355 }
356 }
357#endif
358
359#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
360 // On Xbox, force create the joystick thread for device detection (since other methods don't work
361 s_bJoystickThread = true;
362 if (!SDL_StartJoystickThread()) {
363 return false;
364 }
365#endif
366
367 SetWindowsDeviceChanged(); // force a scan of the system for joysticks this first time
368
369 WINDOWS_JoystickDetect();
370
371 return true;
372}
373
374// return the number of joysticks that are connected right now
375static int WINDOWS_JoystickGetCount(void)
376{
377 int nJoysticks = 0;
378 JoyStick_DeviceData *device = SYS_Joystick;
379 while (device) {
380 nJoysticks++;
381 device = device->pNext;
382 }
383
384 return nJoysticks;
385}
386
387// detect any new joysticks being inserted into the system
388void WINDOWS_JoystickDetect(void)
389{
390 JoyStick_DeviceData *pCurList = NULL;
391
392 // only enum the devices if the joystick thread told us something changed
393 if (!WindowsDeviceChanged()) {
394 return; // thread hasn't signaled, nothing to do right now.
395 }
396
397 if (s_mutexJoyStickEnum) {
398 SDL_LockMutex(s_mutexJoyStickEnum);
399 }
400
401 s_lastDeviceChange = WIN_GetLastDeviceNotification();
402
403 pCurList = SYS_Joystick;
404 SYS_Joystick = NULL;
405
406 // Look for DirectInput joysticks, wheels, head trackers, gamepads, etc..
407 SDL_DINPUT_JoystickDetect(&pCurList);
408
409 // Look for XInput devices. Do this last, so they're first in the final list.
410 SDL_XINPUT_JoystickDetect(&pCurList);
411
412 if (s_mutexJoyStickEnum) {
413 SDL_UnlockMutex(s_mutexJoyStickEnum);
414 }
415
416 while (pCurList) {
417 JoyStick_DeviceData *pListNext = NULL;
418
419 if (!pCurList->bXInputDevice) {
420#ifdef SDL_HAPTIC_DINPUT
421 SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice);
422#endif
423 }
424
425 SDL_PrivateJoystickRemoved(pCurList->nInstanceID);
426
427 pListNext = pCurList->pNext;
428 SDL_free(pCurList->joystickname);
429 SDL_free(pCurList);
430 pCurList = pListNext;
431 }
432
433 for (pCurList = SYS_Joystick; pCurList; pCurList = pCurList->pNext) {
434 if (pCurList->send_add_event) {
435 if (!pCurList->bXInputDevice) {
436#ifdef SDL_HAPTIC_DINPUT
437 SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice);
438#endif
439 }
440
441 SDL_PrivateJoystickAdded(pCurList->nInstanceID);
442
443 pCurList->send_add_event = false;
444 }
445 }
446}
447
448static bool WINDOWS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
449{
450 if (SDL_DINPUT_JoystickPresent(vendor_id, product_id, version)) {
451 return true;
452 }
453 if (SDL_XINPUT_JoystickPresent(vendor_id, product_id, version)) {
454 return true;
455 }
456 return false;
457}
458
459static const char *WINDOWS_JoystickGetDeviceName(int device_index)
460{
461 JoyStick_DeviceData *device = SYS_Joystick;
462 int index;
463
464 for (index = device_index; index > 0; index--) {
465 device = device->pNext;
466 }
467
468 return device->joystickname;
469}
470
471static const char *WINDOWS_JoystickGetDevicePath(int device_index)
472{
473 JoyStick_DeviceData *device = SYS_Joystick;
474 int index;
475
476 for (index = device_index; index > 0; index--) {
477 device = device->pNext;
478 }
479
480 return device->path;
481}
482
483static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
484{
485 JoyStick_DeviceData *device = SYS_Joystick;
486 int index;
487
488 for (index = device_index; index > 0; index--) {
489 device = device->pNext;
490 }
491
492 if (device->bXInputDevice) {
493 // The slot for XInput devices can change as controllers are seated
494 return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId);
495 } else {
496 return device->steam_virtual_gamepad_slot;
497 }
498}
499
500static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
501{
502 JoyStick_DeviceData *device = SYS_Joystick;
503 int index;
504
505 for (index = device_index; index > 0; index--) {
506 device = device->pNext;
507 }
508
509 return device->bXInputDevice ? (int)device->XInputUserId : -1;
510}
511
512static void WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
513{
514}
515
516// return the stable device guid for this device index
517static SDL_GUID WINDOWS_JoystickGetDeviceGUID(int device_index)
518{
519 JoyStick_DeviceData *device = SYS_Joystick;
520 int index;
521
522 for (index = device_index; index > 0; index--) {
523 device = device->pNext;
524 }
525
526 return device->guid;
527}
528
529// Function to perform the mapping between current device instance and this joysticks instance id
530static SDL_JoystickID WINDOWS_JoystickGetDeviceInstanceID(int device_index)
531{
532 JoyStick_DeviceData *device = SYS_Joystick;
533 int index;
534
535 for (index = device_index; index > 0; index--) {
536 device = device->pNext;
537 }
538
539 return device->nInstanceID;
540}
541
542/* Function to open a joystick for use.
543 The joystick to open is specified by the device index.
544 This should fill the nbuttons and naxes fields of the joystick structure.
545 It returns 0, or -1 if there is an error.
546 */
547static bool WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index)
548{
549 JoyStick_DeviceData *device = SYS_Joystick;
550 int index;
551
552 for (index = device_index; index > 0; index--) {
553 device = device->pNext;
554 }
555
556 // allocate memory for system specific hardware data
557 joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata));
558 if (!joystick->hwdata) {
559 return false;
560 }
561 joystick->hwdata->guid = device->guid;
562
563 if (device->bXInputDevice) {
564 return SDL_XINPUT_JoystickOpen(joystick, device);
565 } else {
566 return SDL_DINPUT_JoystickOpen(joystick, device);
567 }
568}
569
570static bool WINDOWS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
571{
572 if (joystick->hwdata->bXInputDevice) {
573 return SDL_XINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
574 } else {
575 return SDL_DINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
576 }
577}
578
579static bool WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
580{
581 return SDL_Unsupported();
582}
583
584static bool WINDOWS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
585{
586 return SDL_Unsupported();
587}
588
589static bool WINDOWS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
590{
591 return SDL_Unsupported();
592}
593
594static bool WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
595{
596 return SDL_Unsupported();
597}
598
599static void WINDOWS_JoystickUpdate(SDL_Joystick *joystick)
600{
601 if (!joystick->hwdata) {
602 return;
603 }
604
605 if (joystick->hwdata->bXInputDevice) {
606 SDL_XINPUT_JoystickUpdate(joystick);
607 } else {
608 SDL_DINPUT_JoystickUpdate(joystick);
609 }
610}
611
612// Function to close a joystick after use
613static void WINDOWS_JoystickClose(SDL_Joystick *joystick)
614{
615 if (joystick->hwdata->bXInputDevice) {
616 SDL_XINPUT_JoystickClose(joystick);
617 } else {
618 SDL_DINPUT_JoystickClose(joystick);
619 }
620
621 SDL_free(joystick->hwdata);
622}
623
624// Function to perform any system-specific joystick related cleanup
625void WINDOWS_JoystickQuit(void)
626{
627 JoyStick_DeviceData *device = SYS_Joystick;
628
629 while (device) {
630 JoyStick_DeviceData *device_next = device->pNext;
631 SDL_free(device->joystickname);
632 SDL_free(device);
633 device = device_next;
634 }
635 SYS_Joystick = NULL;
636
637#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
638 if (s_bJoystickThread) {
639 SDL_StopJoystickThread();
640 } else {
641 SDL_CleanupDeviceNotification(&s_notification_data);
642 }
643#endif
644
645#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
646 if (s_bJoystickThread) {
647 SDL_StopJoystickThread();
648 }
649#endif
650
651 SDL_DINPUT_JoystickQuit();
652 SDL_XINPUT_JoystickQuit();
653
654 WIN_QuitDeviceNotification();
655}
656
657static bool WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
658{
659 return false;
660}
661
662SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
663 WINDOWS_JoystickInit,
664 WINDOWS_JoystickGetCount,
665 WINDOWS_JoystickDetect,
666 WINDOWS_JoystickIsDevicePresent,
667 WINDOWS_JoystickGetDeviceName,
668 WINDOWS_JoystickGetDevicePath,
669 WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,
670 WINDOWS_JoystickGetDevicePlayerIndex,
671 WINDOWS_JoystickSetDevicePlayerIndex,
672 WINDOWS_JoystickGetDeviceGUID,
673 WINDOWS_JoystickGetDeviceInstanceID,
674 WINDOWS_JoystickOpen,
675 WINDOWS_JoystickRumble,
676 WINDOWS_JoystickRumbleTriggers,
677 WINDOWS_JoystickSetLED,
678 WINDOWS_JoystickSendEffect,
679 WINDOWS_JoystickSetSensorsEnabled,
680 WINDOWS_JoystickUpdate,
681 WINDOWS_JoystickClose,
682 WINDOWS_JoystickQuit,
683 WINDOWS_JoystickGetGamepadMapping
684};
685
686#else
687
688#ifdef SDL_JOYSTICK_RAWINPUT
689// The RAWINPUT driver needs the device notification setup above
690#error SDL_JOYSTICK_RAWINPUT requires SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
691#endif
692
693#endif // SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT