Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/joystick/windows/SDL_windowsjoystick.c
9905 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
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
56
static bool s_bJoystickThread = false;
57
static SDL_Condition *s_condJoystickThread = NULL;
58
static SDL_Mutex *s_mutexJoyStickEnum = NULL;
59
static SDL_Thread *s_joystickThread = NULL;
60
static bool s_bJoystickThreadQuit = false;
61
static Uint64 s_lastDeviceChange = 0;
62
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
63
64
JoyStick_DeviceData *SYS_Joystick; // array to hold joystick ID values
65
66
67
static bool WindowsDeviceChanged(void)
68
{
69
return (s_lastDeviceChange != WIN_GetLastDeviceNotification());
70
}
71
72
static void SetWindowsDeviceChanged(void)
73
{
74
s_lastDeviceChange = 0;
75
}
76
77
void WINDOWS_RAWINPUTEnabledChanged(void)
78
{
79
SetWindowsDeviceChanged();
80
}
81
82
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
83
84
typedef 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
96
static 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
128
static 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
149
static 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
193
static 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)
217
static SDL_DeviceNotificationData s_notification_data;
218
#endif
219
220
// Function/thread to scan the system for joysticks.
221
static 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
274
static 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
294
static 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
321
void 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
329
void WINDOWS_JoystickDetect(void);
330
void WINDOWS_JoystickQuit(void);
331
332
static 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
375
static 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
388
void 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
448
static 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
459
static 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
471
static 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
483
static 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
500
static 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
512
static void WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
513
{
514
}
515
516
// return the stable device guid for this device index
517
static 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
530
static 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
*/
547
static 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
570
static 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
579
static bool WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
580
{
581
return SDL_Unsupported();
582
}
583
584
static bool WINDOWS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
585
{
586
return SDL_Unsupported();
587
}
588
589
static bool WINDOWS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
590
{
591
return SDL_Unsupported();
592
}
593
594
static bool WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
595
{
596
return SDL_Unsupported();
597
}
598
599
static 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
613
static 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
625
void 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
657
static bool WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
658
{
659
return false;
660
}
661
662
SDL_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
694
695