SDL  2.0
SDL_windowsjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 SDL_JOYSTICK_DINPUT || 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_error.h"
36 #include "SDL_events.h"
37 #include "SDL_hints.h"
38 #include "SDL_timer.h"
39 #include "SDL_mutex.h"
40 #include "SDL_joystick.h"
41 #include "../SDL_sysjoystick.h"
42 #include "../../thread/SDL_systhread.h"
43 #include "../../core/windows/SDL_windows.h"
44 #if !defined(__WINRT__)
45 #include <dbt.h>
46 #endif
47 
48 #define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
49 #include "SDL_windowsjoystick_c.h"
50 #include "SDL_dinputjoystick_c.h"
51 #include "SDL_xinputjoystick_c.h"
52 #include "SDL_rawinputjoystick_c.h"
53 
54 #include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */
55 #include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */
56 
57 
58 #ifndef DEVICE_NOTIFY_WINDOW_HANDLE
59 #define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
60 #endif
61 
62 /* local variables */
63 static SDL_bool s_bJoystickThread = SDL_FALSE;
64 static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
65 static SDL_cond *s_condJoystickThread = NULL;
66 static SDL_mutex *s_mutexJoyStickEnum = NULL;
67 static SDL_Thread *s_joystickThread = NULL;
68 static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
69 
70 JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
71 
72 #ifdef __WINRT__
73 
74 typedef struct
75 {
76  int unused;
77 } SDL_DeviceNotificationData;
78 
79 static void
80 SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
81 {
82 }
83 
84 static int
85 SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
86 {
87  return 0;
88 }
89 
90 static SDL_bool
91 SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_mutex *mutex)
92 {
93  return SDL_FALSE;
94 }
95 
96 #else /* !__WINRT__ */
97 
98 typedef struct
99 {
100  HRESULT coinitialized;
101  WNDCLASSEX wincl;
102  HWND messageWindow;
103  HDEVNOTIFY hNotify;
104 } SDL_DeviceNotificationData;
105 
106 #define IDT_SDL_DEVICE_CHANGE_TIMER_1 1200
107 #define IDT_SDL_DEVICE_CHANGE_TIMER_2 1201
108 
109 /* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
110 static LRESULT CALLBACK
111 SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
112 {
113  switch (msg) {
114  case WM_DEVICECHANGE:
115  switch (wParam) {
116  case DBT_DEVICEARRIVAL:
117  case DBT_DEVICEREMOVECOMPLETE:
118  if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
119  /* notify 300ms and 2 seconds later to ensure all APIs have updated status */
120  SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_1, 300, NULL);
121  SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_2, 2000, NULL);
122  }
123  break;
124  }
125  return 0;
126  case WM_TIMER:
127  if (wParam == IDT_SDL_DEVICE_CHANGE_TIMER_1 ||
128  wParam == IDT_SDL_DEVICE_CHANGE_TIMER_2) {
129  KillTimer(hwnd, wParam);
130  s_bWindowsDeviceChanged = SDL_TRUE;
131  return 0;
132  }
133  break;
134  }
135 
136 #if SDL_JOYSTICK_RAWINPUT
137  return CallWindowProc(RAWINPUT_WindowProc, hwnd, msg, wParam, lParam);
138 #else
139  return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
140 #endif
141 }
142 
143 static void
144 SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
145 {
146 #if SDL_JOYSTICK_RAWINPUT
148 #endif
149 
150  if (data->hNotify)
151  UnregisterDeviceNotification(data->hNotify);
152 
153  if (data->messageWindow)
154  DestroyWindow(data->messageWindow);
155 
156  UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
157 
158  if (data->coinitialized == S_OK) {
160  }
161 }
162 
163 static int
164 SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
165 {
166  DEV_BROADCAST_DEVICEINTERFACE dbh;
167  GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
168 
169  SDL_zerop(data);
170 
171  data->coinitialized = WIN_CoInitialize();
172 
173  data->wincl.hInstance = GetModuleHandle(NULL);
174  data->wincl.lpszClassName = L"Message";
175  data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
176  data->wincl.cbSize = sizeof (WNDCLASSEX);
177 
178  if (!RegisterClassEx(&data->wincl)) {
179  WIN_SetError("Failed to create register class for joystick autodetect");
180  SDL_CleanupDeviceNotification(data);
181  return -1;
182  }
183 
184  data->messageWindow = (HWND)CreateWindowEx(0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
185  if (!data->messageWindow) {
186  WIN_SetError("Failed to create message window for joystick autodetect");
187  SDL_CleanupDeviceNotification(data);
188  return -1;
189  }
190 
191  SDL_zero(dbh);
192  dbh.dbcc_size = sizeof(dbh);
193  dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
194  dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
195 
196  data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
197  if (!data->hNotify) {
198  WIN_SetError("Failed to create notify device for joystick autodetect");
199  SDL_CleanupDeviceNotification(data);
200  return -1;
201  }
202 
203 #if SDL_JOYSTICK_RAWINPUT
204  RAWINPUT_RegisterNotifications(data->messageWindow);
205 #endif
206  return 0;
207 }
208 
209 static SDL_bool
210 SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_mutex *mutex)
211 {
212  MSG msg;
213  int lastret = 1;
214 
215  if (!data->messageWindow) {
216  return SDL_FALSE; /* device notifications require a window */
217  }
218 
220  while (lastret > 0 && s_bWindowsDeviceChanged == SDL_FALSE) {
221  lastret = GetMessage(&msg, NULL, 0, 0); /* WM_QUIT causes return value of 0 */
222  if (lastret > 0) {
223  TranslateMessage(&msg);
224  DispatchMessage(&msg);
225  }
226  }
228  return (lastret != -1) ? SDL_TRUE : SDL_FALSE;
229 }
230 
231 #endif /* __WINRT__ */
232 
233 static SDL_DeviceNotificationData s_notification_data;
234 
235 /* Function/thread to scan the system for joysticks. */
236 static int
237 SDL_JoystickThread(void *_data)
238 {
239 #if SDL_JOYSTICK_XINPUT
240  SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
241  SDL_zeroa(bOpenedXInputDevices);
242 #endif
243 
244  if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
245  return -1;
246  }
247 
248  SDL_LockMutex(s_mutexJoyStickEnum);
249  while (s_bJoystickThreadQuit == SDL_FALSE) {
250  if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
251 #if SDL_JOYSTICK_XINPUT
252  /* WM_DEVICECHANGE not working, poll for new XINPUT controllers */
253  SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
254  if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
255  /* scan for any change in XInput devices */
256  Uint8 userId;
257  for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
258  XINPUT_CAPABILITIES capabilities;
259  const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
260  const SDL_bool available = (result == ERROR_SUCCESS);
261  if (bOpenedXInputDevices[userId] != available) {
262  s_bWindowsDeviceChanged = SDL_TRUE;
263  bOpenedXInputDevices[userId] = available;
264  }
265  }
266  }
267 #else
268  /* WM_DEVICECHANGE not working, no XINPUT, no point in keeping thread alive */
269  break;
270 #endif /* SDL_JOYSTICK_XINPUT */
271  }
272  }
273  SDL_UnlockMutex(s_mutexJoyStickEnum);
274 
275  SDL_CleanupDeviceNotification(&s_notification_data);
276 
277  return 1;
278 }
279 
280 /* spin up the thread to detect hotplug of devices */
281 static int
282 SDL_StartJoystickThread(void)
283 {
284  s_mutexJoyStickEnum = SDL_CreateMutex();
285  if (!s_mutexJoyStickEnum) {
286  return -1;
287  }
288 
289  s_condJoystickThread = SDL_CreateCond();
290  if (!s_condJoystickThread) {
291  return -1;
292  }
293 
294  s_bJoystickThreadQuit = SDL_FALSE;
295  s_joystickThread = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
296  if (!s_joystickThread) {
297  return -1;
298  }
299  return 0;
300 }
301 
302 static void
303 SDL_StopJoystickThread(void)
304 {
305  if (!s_joystickThread) {
306  return;
307  }
308 
309  SDL_LockMutex(s_mutexJoyStickEnum);
310  s_bJoystickThreadQuit = SDL_TRUE;
311  SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
312  SDL_UnlockMutex(s_mutexJoyStickEnum);
313 #ifndef __WINRT__
314  PostThreadMessage(SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0);
315 #endif
316  SDL_WaitThread(s_joystickThread, NULL); /* wait for it to bugger off */
317 
318  SDL_DestroyCond(s_condJoystickThread);
319  s_condJoystickThread = NULL;
320 
321  SDL_DestroyMutex(s_mutexJoyStickEnum);
322  s_mutexJoyStickEnum = NULL;
323 
324  s_joystickThread = NULL;
325 }
326 
328 {
329  device->send_add_event = SDL_TRUE;
330  device->nInstanceID = SDL_GetNextJoystickInstanceID();
331  device->pNext = SYS_Joystick;
333 }
334 
335 static void WINDOWS_JoystickDetect(void);
336 static void WINDOWS_JoystickQuit(void);
337 
338 /* Function to scan the system for joysticks.
339  * Joystick 0 should be the system default joystick.
340  * It should return 0, or -1 on an unrecoverable fatal error.
341  */
342 static int
343 WINDOWS_JoystickInit(void)
344 {
345  if (SDL_DINPUT_JoystickInit() < 0) {
346  WINDOWS_JoystickQuit();
347  return -1;
348  }
349 
350  if (SDL_XINPUT_JoystickInit() < 0) {
351  WINDOWS_JoystickQuit();
352  return -1;
353  }
354 
355  s_bWindowsDeviceChanged = SDL_TRUE; /* force a scan of the system for joysticks this first time */
356 
357  WINDOWS_JoystickDetect();
358 
360  if (s_bJoystickThread) {
361  if (SDL_StartJoystickThread() < 0) {
362  return -1;
363  }
364  } else {
365  if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
366  return -1;
367  }
368  }
369  return 0;
370 }
371 
372 /* return the number of joysticks that are connected right now */
373 static int
374 WINDOWS_JoystickGetCount(void)
375 {
376  int nJoysticks = 0;
378  while (device) {
379  nJoysticks++;
380  device = device->pNext;
381  }
382 
383  return nJoysticks;
384 }
385 
386 /* detect any new joysticks being inserted into the system */
387 static void
388 WINDOWS_JoystickDetect(void)
389 {
390  int device_index = 0;
391  JoyStick_DeviceData *pCurList = NULL;
392 
393  /* only enum the devices if the joystick thread told us something changed */
394  if (!s_bWindowsDeviceChanged) {
395  return; /* thread hasn't signaled, nothing to do right now. */
396  }
397 
398  if (s_mutexJoyStickEnum) {
399  SDL_LockMutex(s_mutexJoyStickEnum);
400  }
401 
402  s_bWindowsDeviceChanged = SDL_FALSE;
403 
404  pCurList = SYS_Joystick;
405  SYS_Joystick = NULL;
406 
407  /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
408  SDL_DINPUT_JoystickDetect(&pCurList);
409 
410  /* Look for XInput devices. Do this last, so they're first in the final list. */
411  SDL_XINPUT_JoystickDetect(&pCurList);
412 
413  if (s_mutexJoyStickEnum) {
414  SDL_UnlockMutex(s_mutexJoyStickEnum);
415  }
416 
417  while (pCurList) {
418  JoyStick_DeviceData *pListNext = NULL;
419 
420  if (pCurList->bXInputDevice) {
421 #if SDL_HAPTIC_XINPUT
423 #endif
424  } else {
425 #if SDL_HAPTIC_DINPUT
427 #endif
428  }
429 
431 
432  pListNext = pCurList->pNext;
433  SDL_free(pCurList->joystickname);
434  SDL_free(pCurList);
435  pCurList = pListNext;
436  }
437 
438  for (device_index = 0, pCurList = SYS_Joystick; pCurList; ++device_index, pCurList = pCurList->pNext) {
439  if (pCurList->send_add_event) {
440  if (pCurList->bXInputDevice) {
441 #if SDL_HAPTIC_XINPUT
442  SDL_XINPUT_MaybeAddDevice(pCurList->XInputUserId);
443 #endif
444  } else {
445 #if SDL_HAPTIC_DINPUT
446  SDL_DINPUT_MaybeAddDevice(&pCurList->dxdevice);
447 #endif
448  }
449 
450  SDL_PrivateJoystickAdded(pCurList->nInstanceID);
451 
452  pCurList->send_add_event = SDL_FALSE;
453  }
454  }
455 }
456 
457 /* Function to get the device-dependent name of a joystick */
458 static const char *
459 WINDOWS_JoystickGetDeviceName(int device_index)
460 {
462  int index;
463 
464  for (index = device_index; index > 0; index--)
465  device = device->pNext;
466 
467  return device->joystickname;
468 }
469 
470 static int
471 WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
472 {
474  int index;
475 
476  for (index = device_index; index > 0; index--)
477  device = device->pNext;
478 
479  return device->bXInputDevice ? (int)device->XInputUserId : -1;
480 }
481 
482 static void
483 WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
484 {
485 }
486 
487 /* return the stable device guid for this device index */
488 static SDL_JoystickGUID
489 WINDOWS_JoystickGetDeviceGUID(int device_index)
490 {
492  int index;
493 
494  for (index = device_index; index > 0; index--)
495  device = device->pNext;
496 
497  return device->guid;
498 }
499 
500 /* Function to perform the mapping between current device instance and this joysticks instance id */
501 static SDL_JoystickID
502 WINDOWS_JoystickGetDeviceInstanceID(int device_index)
503 {
505  int index;
506 
507  for (index = device_index; index > 0; index--)
508  device = device->pNext;
509 
510  return device->nInstanceID;
511 }
512 
513 /* Function to open a joystick for use.
514  The joystick to open is specified by the device index.
515  This should fill the nbuttons and naxes fields of the joystick structure.
516  It returns 0, or -1 if there is an error.
517  */
518 static int
519 WINDOWS_JoystickOpen(SDL_Joystick * joystick, int device_index)
520 {
522  int index;
523 
524  for (index = device_index; index > 0; index--)
525  device = device->pNext;
526 
527  /* allocate memory for system specific hardware data */
528  joystick->instance_id = device->nInstanceID;
529  joystick->hwdata =
530  (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
531  if (joystick->hwdata == NULL) {
532  return SDL_OutOfMemory();
533  }
534  SDL_zerop(joystick->hwdata);
535  joystick->hwdata->guid = device->guid;
536 
537  if (device->bXInputDevice) {
539  } else {
541  }
542 }
543 
544 static int
545 WINDOWS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
546 {
547  if (joystick->hwdata->bXInputDevice) {
548  return SDL_XINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
549  } else {
550  return SDL_DINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
551  }
552 }
553 
554 static int
555 WINDOWS_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble)
556 {
557  return SDL_Unsupported();
558 }
559 
560 static SDL_bool
561 WINDOWS_JoystickHasLED(SDL_Joystick * joystick)
562 {
563  return SDL_FALSE;
564 }
565 
566 static int
567 WINDOWS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
568 {
569  return SDL_Unsupported();
570 }
571 
572 static int
573 WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
574 {
575  return SDL_Unsupported();
576 }
577 
578 static void
579 WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
580 {
581  if (!joystick->hwdata) {
582  return;
583  }
584 
585  if (joystick->hwdata->bXInputDevice) {
587  } else {
589  }
590 }
591 
592 /* Function to close a joystick after use */
593 static void
594 WINDOWS_JoystickClose(SDL_Joystick * joystick)
595 {
596  if (joystick->hwdata->bXInputDevice) {
598  } else {
600  }
601 
602  SDL_free(joystick->hwdata);
603 }
604 
605 /* Function to perform any system-specific joystick related cleanup */
606 static void
607 WINDOWS_JoystickQuit(void)
608 {
610 
611  while (device) {
612  JoyStick_DeviceData *device_next = device->pNext;
613  SDL_free(device->joystickname);
614  SDL_free(device);
615  device = device_next;
616  }
617  SYS_Joystick = NULL;
618 
619  if (s_bJoystickThread) {
620  SDL_StopJoystickThread();
621  } else {
622  SDL_CleanupDeviceNotification(&s_notification_data);
623  }
624 
627 
628  s_bWindowsDeviceChanged = SDL_FALSE;
629 }
630 
631 static SDL_bool
632 WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
633 {
634  return SDL_FALSE;
635 }
636 
638 {
639  WINDOWS_JoystickInit,
640  WINDOWS_JoystickGetCount,
641  WINDOWS_JoystickDetect,
642  WINDOWS_JoystickGetDeviceName,
643  WINDOWS_JoystickGetDevicePlayerIndex,
644  WINDOWS_JoystickSetDevicePlayerIndex,
645  WINDOWS_JoystickGetDeviceGUID,
646  WINDOWS_JoystickGetDeviceInstanceID,
647  WINDOWS_JoystickOpen,
648  WINDOWS_JoystickRumble,
649  WINDOWS_JoystickRumbleTriggers,
650  WINDOWS_JoystickHasLED,
651  WINDOWS_JoystickSetLED,
652  WINDOWS_JoystickSetSensorsEnabled,
653  WINDOWS_JoystickUpdate,
654  WINDOWS_JoystickClose,
655  WINDOWS_JoystickQuit,
656  WINDOWS_JoystickGetGamepadMapping
657 };
658 
659 #endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
660 
661 /* vi: set ts=4 sw=4 expandtab: */
int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance)
int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance)
void SDL_DINPUT_JoystickQuit(void)
int SDL_DINPUT_JoystickInit(void)
int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
void SDL_DINPUT_JoystickClose(SDL_Joystick *joystick)
int SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick)
#define S_OK
Definition: SDL_directx.h:47
#define SDL_GetThreadID
#define SDL_CondBroadcast
#define SDL_CreateCond
#define SDL_LockMutex
#define SDL_malloc
#define SDL_CreateMutex
#define SDL_free
#define SDL_CondWaitTimeout
#define SDL_WaitThread
#define SDL_DestroyCond
#define SDL_GetHintBoolean
#define SDL_DestroyMutex
#define SDL_UnlockMutex
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
const GLubyte GLuint red
Definition: SDL_glfuncs.h:80
#define SDL_HINT_JOYSTICK_THREAD
A variable controlling whether a separate thread should be used for handling joystick detection and r...
Definition: SDL_hints.h:720
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
SDL_JoystickID SDL_GetNextJoystickInstanceID()
Definition: SDL_joystick.c:262
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLbyte GLbyte blue
GLuint64EXT * result
GLuint index
GLbyte green
void RAWINPUT_UnregisterNotifications()
LRESULT CALLBACK RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_bool RAWINPUT_RegisterNotifications(HWND hWnd)
uint16_t Uint16
Definition: SDL_stdinc.h:197
#define SDL_zero(x)
Definition: SDL_stdinc.h:426
#define SDL_zeroa(x)
Definition: SDL_stdinc.h:428
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
#define SDL_zerop(x)
Definition: SDL_stdinc.h:427
SDL_JoystickDriver SDL_WINDOWS_JoystickDriver
SDL_Thread * SDL_CreateThreadInternal(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:391
HRESULT WIN_CoInitialize(void)
void WIN_CoUninitialize(void)
int WIN_SetError(const char *prefix)
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
JoyStick_DeviceData * SYS_Joystick
int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
void SDL_XINPUT_JoystickQuit(void)
void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick)
SDL_bool SDL_XINPUT_Enabled(void)
void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick)
int SDL_XINPUT_JoystickInit(void)
#define NULL
Definition: begin_code.h:163
static SDL_AudioDeviceID device
Definition: loopwave.c:37
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF PF lsl PF PF PF else PF lsl PF lsl PF lsl PF endif SIZE macro preload_middle scratch_holds_offset if bpp if else PF PF endif endif endif endm macro preload_trailing base if bpp if bpp *pix_per_block PF PF lsl PF PF PF PF PF else PF lsl PF lsl PF PF PF PF PF base if bpp if narrow_case &&bpp<=dst_w_bpp) PF bic, WK0, base, #31 PF pld,[WK0] PF add, WK1, base, X, LSL #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 90f PF pld,[WK1]90:.else PF bic, WK0, base, #31 PF pld,[WK0] PF add, WK1, base, X, lsl #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 92f91:PF add, WK0, WK0, #32 PF cmp, WK0, WK1 PF pld,[WK0] PF bne, 91b92:.endif .endif.endm.macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond X, X, #8 *numbytes/dst_w_bpp .endif process_tail cond, numbytes, firstreg .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst cond, numbytes, firstreg, DST .endif.endm.macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_BRANCH_OVER .ifc cond, mi bpl 100f .endif .ifc cond, cs bcc 100f .endif .ifc cond, ne beq 100f .endif conditional_process1_helper, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx100:.else conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .endif.endm.macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx .if(flags) &(FLAG_DST_READWRITE|FLAG_BRANCH_OVER|FLAG_PROCESS_CORRUPTS_PSR|FLAG_PROCESS_DOES_STORE) test conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_PROCESS_CORRUPTS_PSR test .endif conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx .else test process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0 process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond1 X, X, #8 *numbytes1/dst_w_bpp sub &cond2 X, X, #8 *numbytes2/dst_w_bpp .endif process_tail cond1, numbytes1, firstreg1 process_tail cond2, numbytes2, firstreg2 pixst cond1, numbytes1, firstreg1, DST pixst cond2, numbytes2, firstreg2, DST .endif.endm.macro test_bits_1_0_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-1 .else movs SCRATCH, WK0, lsl #32-1 .endif.endm.macro test_bits_3_2_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-3 .else movs SCRATCH, WK0, lsl #32-3 .endif.endm.macro leading_15bytes process_head, process_tail .set DECREMENT_X, 1 .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 .set DECREMENT_X, 0 sub X, X, WK0, lsr #dst_bpp_shift str X,[sp, #LINE_SAVED_REG_COUNT *4] mov X, WK0 .endif .if dst_w_bpp==8 conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X .elseif dst_w_bpp==16 test_bits_1_0_ptr conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X .endif conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 ldr X,[sp, #LINE_SAVED_REG_COUNT *4] .endif.endm.macro test_bits_3_2_pix movs SCRATCH, X, lsl #dst_bpp_shift+32-3.endm.macro test_bits_1_0_pix .if dst_w_bpp==8 movs SCRATCH, X, lsl #dst_bpp_shift+32-1 .else movs SCRATCH, X, lsr #1 .endif.endm.macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0 .if dst_w_bpp==16 test_bits_1_0_pix conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0 .elseif dst_w_bpp==8 conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0 .endif.endm.macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment110:.set SUBBLOCK, 0 .rept pix_per_block *dst_w_bpp/128 process_head, 16, 0, unaligned_src, unaligned_mask, 1 .if(src_bpp > 0) &&(mask_bpp==0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle src_bpp, SRC, 1 .elseif(src_bpp==0) &&(mask_bpp > 0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle mask_bpp, MASK, 1 .else preload_middle src_bpp, SRC, 0 preload_middle mask_bpp, MASK, 0 .endif .if(dst_r_bpp > 0) &&((SUBBLOCK % 2)==0) &&(((flags) &FLAG_NO_PRELOAD_DST)==0) PF pld,[DST, #32 *prefetch_distance - dst_alignment] .endif process_tail, 16, 0 .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst, 16, 0, DST .endif .set SUBBLOCK, SUBBLOCK+1 .endr subs X, X, #pix_per_block bhs 110b.endm.macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask .if dst_r_bpp > tst bne process_inner_loop DST_PRELOAD_BIAS endif preload_trailing SRC preload_trailing MASK DST endif add medium_case_inner_loop_and_trailing_pixels unaligned_mask endm macro medium_case_inner_loop_and_trailing_pixels unused
DIDEVICEINSTANCE dxdevice
struct JoyStick_DeviceData * pNext
static SDL_Joystick * joystick
Definition: testjoystick.c:37
static SDL_mutex * mutex
Definition: testlock.c:23