Atlas - SDL_windowsjoystick.c
Home / ext / SDL / src / joystick / windows Lines: 1 | Size: 20749 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]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 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#ifdef SDL_HAPTIC_DINPUT 420#ifdef SDL_JOYSTICK_XINPUT 421 if (!pCurList->bXInputDevice) { 422 SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice); 423 } 424#else 425 SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice); 426#endif 427#endif 428 429 SDL_PrivateJoystickRemoved(pCurList->nInstanceID); 430 431 pListNext = pCurList->pNext; 432 SDL_free(pCurList->joystickname); 433 SDL_free(pCurList); 434 pCurList = pListNext; 435 } 436 437 for (pCurList = SYS_Joystick; pCurList; pCurList = pCurList->pNext) { 438 if (pCurList->send_add_event) { 439#ifdef SDL_HAPTIC_DINPUT 440#ifdef SDL_JOYSTICK_XINPUT 441 if (!pCurList->bXInputDevice) { 442 SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice); 443 } 444#else 445 SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice); 446#endif 447#endif 448 449 SDL_PrivateJoystickAdded(pCurList->nInstanceID); 450 451 pCurList->send_add_event = false; 452 } 453 } 454} 455 456static bool WINDOWS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) 457{ 458 if (SDL_DINPUT_JoystickPresent(vendor_id, product_id, version)) { 459 return true; 460 } 461 if (SDL_XINPUT_JoystickPresent(vendor_id, product_id, version)) { 462 return true; 463 } 464 return false; 465} 466 467static const char *WINDOWS_JoystickGetDeviceName(int device_index) 468{ 469 JoyStick_DeviceData *device = SYS_Joystick; 470 int index; 471 472 for (index = device_index; index > 0; index--) { 473 device = device->pNext; 474 } 475 476 return device->joystickname; 477} 478 479static const char *WINDOWS_JoystickGetDevicePath(int device_index) 480{ 481 JoyStick_DeviceData *device = SYS_Joystick; 482 int index; 483 484 for (index = device_index; index > 0; index--) { 485 device = device->pNext; 486 } 487 488 return device->path; 489} 490 491static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) 492{ 493 JoyStick_DeviceData *device = SYS_Joystick; 494 int index; 495 496 for (index = device_index; index > 0; index--) { 497 device = device->pNext; 498 } 499 500#ifdef SDL_JOYSTICK_XINPUT 501 if (device->bXInputDevice) { 502 // The slot for XInput devices can change as controllers are seated 503 return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId); 504 } 505#endif 506 return device->steam_virtual_gamepad_slot; 507} 508 509static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index) 510{ 511#ifdef SDL_JOYSTICK_XINPUT 512 JoyStick_DeviceData *device = SYS_Joystick; 513 int index; 514 515 for (index = device_index; index > 0; index--) { 516 device = device->pNext; 517 } 518 519 return device->bXInputDevice ? (int)device->XInputUserId : -1; 520#else 521 return -1; 522#endif 523} 524 525static void WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index) 526{ 527} 528 529// return the stable device guid for this device index 530static SDL_GUID WINDOWS_JoystickGetDeviceGUID(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->guid; 540} 541 542// Function to perform the mapping between current device instance and this joysticks instance id 543static SDL_JoystickID WINDOWS_JoystickGetDeviceInstanceID(int device_index) 544{ 545 JoyStick_DeviceData *device = SYS_Joystick; 546 int index; 547 548 for (index = device_index; index > 0; index--) { 549 device = device->pNext; 550 } 551 552 return device->nInstanceID; 553} 554 555/* Function to open a joystick for use. 556 The joystick to open is specified by the device index. 557 This should fill the nbuttons and naxes fields of the joystick structure. 558 It returns 0, or -1 if there is an error. 559 */ 560static bool WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index) 561{ 562 JoyStick_DeviceData *device = SYS_Joystick; 563 int index; 564 565 for (index = device_index; index > 0; index--) { 566 device = device->pNext; 567 } 568 569 // allocate memory for system specific hardware data 570 joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata)); 571 if (!joystick->hwdata) { 572 return false; 573 } 574 joystick->hwdata->guid = device->guid; 575 576#ifdef SDL_JOYSTICK_XINPUT 577 if (device->bXInputDevice) { 578 return SDL_XINPUT_JoystickOpen(joystick, device); 579 } 580#endif 581 return SDL_DINPUT_JoystickOpen(joystick, device); 582} 583 584static bool WINDOWS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 585{ 586#ifdef SDL_JOYSTICK_XINPUT 587 if (joystick->hwdata->bXInputDevice) { 588 return SDL_XINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble); 589 } 590#endif 591 return SDL_DINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble); 592} 593 594static bool WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 595{ 596 return SDL_Unsupported(); 597} 598 599static bool WINDOWS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 600{ 601 return SDL_Unsupported(); 602} 603 604static bool WINDOWS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) 605{ 606 return SDL_Unsupported(); 607} 608 609static bool WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) 610{ 611 return SDL_Unsupported(); 612} 613 614static void WINDOWS_JoystickUpdate(SDL_Joystick *joystick) 615{ 616 if (!joystick->hwdata) { 617 return; 618 } 619 620#ifdef SDL_JOYSTICK_XINPUT 621 if (joystick->hwdata->bXInputDevice) { 622 SDL_XINPUT_JoystickUpdate(joystick); 623 return; 624 } 625#endif 626 SDL_DINPUT_JoystickUpdate(joystick); 627} 628 629// Function to close a joystick after use 630static void WINDOWS_JoystickClose(SDL_Joystick *joystick) 631{ 632#ifdef SDL_JOYSTICK_XINPUT 633 if (joystick->hwdata->bXInputDevice) { 634 SDL_XINPUT_JoystickClose(joystick); 635 } else { 636 SDL_DINPUT_JoystickClose(joystick); 637 } 638#else 639 SDL_DINPUT_JoystickClose(joystick); 640#endif 641 642 SDL_free(joystick->hwdata); 643} 644 645// Function to perform any system-specific joystick related cleanup 646void WINDOWS_JoystickQuit(void) 647{ 648 JoyStick_DeviceData *device = SYS_Joystick; 649 650 while (device) { 651 JoyStick_DeviceData *device_next = device->pNext; 652 SDL_free(device->joystickname); 653 SDL_free(device); 654 device = device_next; 655 } 656 SYS_Joystick = NULL; 657 658#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) 659 if (s_bJoystickThread) { 660 SDL_StopJoystickThread(); 661 } else { 662 SDL_CleanupDeviceNotification(&s_notification_data); 663 } 664#endif 665 666#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) 667 if (s_bJoystickThread) { 668 SDL_StopJoystickThread(); 669 } 670#endif 671 672 SDL_DINPUT_JoystickQuit(); 673 SDL_XINPUT_JoystickQuit(); 674 675 WIN_QuitDeviceNotification(); 676} 677 678static bool WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) 679{ 680 return false; 681} 682 683SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = { 684 WINDOWS_JoystickInit, 685 WINDOWS_JoystickGetCount, 686 WINDOWS_JoystickDetect, 687 WINDOWS_JoystickIsDevicePresent, 688 WINDOWS_JoystickGetDeviceName, 689 WINDOWS_JoystickGetDevicePath, 690 WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot, 691 WINDOWS_JoystickGetDevicePlayerIndex, 692 WINDOWS_JoystickSetDevicePlayerIndex, 693 WINDOWS_JoystickGetDeviceGUID, 694 WINDOWS_JoystickGetDeviceInstanceID, 695 WINDOWS_JoystickOpen, 696 WINDOWS_JoystickRumble, 697 WINDOWS_JoystickRumbleTriggers, 698 WINDOWS_JoystickSetLED, 699 WINDOWS_JoystickSendEffect, 700 WINDOWS_JoystickSetSensorsEnabled, 701 WINDOWS_JoystickUpdate, 702 WINDOWS_JoystickClose, 703 WINDOWS_JoystickQuit, 704 WINDOWS_JoystickGetGamepadMapping 705}; 706 707#else 708 709#ifdef SDL_JOYSTICK_RAWINPUT 710// The RAWINPUT driver needs the device notification setup above 711#error SDL_JOYSTICK_RAWINPUT requires SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT 712#endif 713 714#endif // SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT 715[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.