SDL  2.0
SDL_hidapijoystick.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 #ifdef SDL_JOYSTICK_HIDAPI
24 
25 #include "SDL_assert.h"
26 #include "SDL_atomic.h"
27 #include "SDL_endian.h"
28 #include "SDL_hints.h"
29 #include "SDL_log.h"
30 #include "SDL_thread.h"
31 #include "SDL_timer.h"
32 #include "SDL_joystick.h"
33 #include "../SDL_sysjoystick.h"
34 #include "SDL_hidapijoystick_c.h"
35 #include "SDL_hidapi_rumble.h"
36 #include "../../SDL_hints_c.h"
37 
38 #if defined(__WIN32__)
39 #include "../../core/windows/SDL_windows.h"
40 #endif
41 
42 #if defined(__MACOSX__)
43 #include <CoreFoundation/CoreFoundation.h>
44 #include <mach/mach.h>
45 #include <IOKit/IOKitLib.h>
46 #include <IOKit/hid/IOHIDDevice.h>
47 #include <IOKit/usb/USBSpec.h>
48 #endif
49 
50 #if defined(__LINUX__)
51 #include "../../core/linux/SDL_udev.h"
52 #ifdef SDL_USE_LIBUDEV
53 #include <poll.h>
54 #endif
55 #endif
56 
57 struct joystick_hwdata
58 {
60 };
61 
62 static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
63 #ifdef SDL_JOYSTICK_HIDAPI_PS4
65 #endif
66 #ifdef SDL_JOYSTICK_HIDAPI_STEAM
68 #endif
69 #ifdef SDL_JOYSTICK_HIDAPI_SWITCH
71 #endif
72 #ifdef SDL_JOYSTICK_HIDAPI_XBOX360
75 #endif
76 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
78 #endif
79 #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
81 #endif
82 };
83 static int SDL_HIDAPI_numdrivers = 0;
84 static SDL_SpinLock SDL_HIDAPI_spinlock;
85 static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
86 static int SDL_HIDAPI_numjoysticks = 0;
87 static SDL_bool initialized = SDL_FALSE;
88 static SDL_bool shutting_down = SDL_FALSE;
89 
90 #if defined(SDL_USE_LIBUDEV)
91 static const SDL_UDEV_Symbols * usyms = NULL;
92 #endif
93 
94 static struct
95 {
96  SDL_bool m_bHaveDevicesChanged;
97  SDL_bool m_bCanGetNotifications;
98  Uint32 m_unLastDetect;
99 
100 #if defined(__WIN32__)
101  SDL_threadID m_nThreadID;
102  WNDCLASSEXA m_wndClass;
103  HWND m_hwndMsg;
104  HDEVNOTIFY m_hNotify;
105  double m_flLastWin32MessageCheck;
106 #endif
107 
108 #if defined(__MACOSX__)
109  IONotificationPortRef m_notificationPort;
110  mach_port_t m_notificationMach;
111 #endif
112 
113 #if defined(SDL_USE_LIBUDEV)
114  struct udev *m_pUdev;
115  struct udev_monitor *m_pUdevMonitor;
116  int m_nUdevFd;
117 #endif
118 } SDL_HIDAPI_discovery;
119 
120 
121 #ifdef __WIN32__
122 struct _DEV_BROADCAST_HDR
123 {
124  DWORD dbch_size;
125  DWORD dbch_devicetype;
126  DWORD dbch_reserved;
127 };
128 
129 typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A
130 {
131  DWORD dbcc_size;
132  DWORD dbcc_devicetype;
133  DWORD dbcc_reserved;
134  GUID dbcc_classguid;
135  char dbcc_name[ 1 ];
136 } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
137 
138 typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR;
139 #define DBT_DEVICEARRIVAL 0x8000 /* system detected a new device */
140 #define DBT_DEVICEREMOVECOMPLETE 0x8004 /* device was removed from the system */
141 #define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 /* device interface class */
142 #define DBT_DEVNODES_CHANGED 0x0007
143 #define DBT_CONFIGCHANGED 0x0018
144 #define DBT_DEVICETYPESPECIFIC 0x8005 /* type specific event */
145 #define DBT_DEVINSTSTARTED 0x8008 /* device installed and started */
146 
147 #include <initguid.h>
148 DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
149 
150 static LRESULT CALLBACK ControllerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
151 {
152  switch (message) {
153  case WM_DEVICECHANGE:
154  switch (wParam) {
155  case DBT_DEVICEARRIVAL:
156  case DBT_DEVICEREMOVECOMPLETE:
157  if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
158  SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
159  }
160  break;
161  }
162  return TRUE;
163  }
164 
165  return DefWindowProc(hwnd, message, wParam, lParam);
166 }
167 #endif /* __WIN32__ */
168 
169 
170 #if defined(__MACOSX__)
171 static void CallbackIOServiceFunc(void *context, io_iterator_t portIterator)
172 {
173  /* Must drain the iterator, or we won't receive new notifications */
174  io_object_t entry;
175  while ((entry = IOIteratorNext(portIterator)) != 0) {
176  IOObjectRelease(entry);
178  }
179 }
180 #endif /* __MACOSX__ */
181 
182 static void
183 HIDAPI_InitializeDiscovery()
184 {
185  SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
186  SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_FALSE;
187  SDL_HIDAPI_discovery.m_unLastDetect = 0;
188 
189 #if defined(__WIN32__)
190  SDL_HIDAPI_discovery.m_nThreadID = SDL_ThreadID();
191 
192  SDL_memset(&SDL_HIDAPI_discovery.m_wndClass, 0x0, sizeof(SDL_HIDAPI_discovery.m_wndClass));
193  SDL_HIDAPI_discovery.m_wndClass.hInstance = GetModuleHandle(NULL);
194  SDL_HIDAPI_discovery.m_wndClass.lpszClassName = "SDL_HIDAPI_DEVICE_DETECTION";
195  SDL_HIDAPI_discovery.m_wndClass.lpfnWndProc = ControllerWndProc; /* This function is called by windows */
196  SDL_HIDAPI_discovery.m_wndClass.cbSize = sizeof(WNDCLASSEX);
197 
198  RegisterClassExA(&SDL_HIDAPI_discovery.m_wndClass);
199  SDL_HIDAPI_discovery.m_hwndMsg = CreateWindowExA(0, "SDL_HIDAPI_DEVICE_DETECTION", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
200 
201  {
202  DEV_BROADCAST_DEVICEINTERFACE_A devBroadcast;
203  SDL_memset( &devBroadcast, 0x0, sizeof( devBroadcast ) );
204 
205  devBroadcast.dbcc_size = sizeof( devBroadcast );
206  devBroadcast.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
207  devBroadcast.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
208 
209  /* DEVICE_NOTIFY_ALL_INTERFACE_CLASSES is important, makes GUID_DEVINTERFACE_USB_DEVICE ignored,
210  * but that seems to be necessary to get a notice after each individual usb input device actually
211  * installs, rather than just as the composite device is seen.
212  */
213  SDL_HIDAPI_discovery.m_hNotify = RegisterDeviceNotification( SDL_HIDAPI_discovery.m_hwndMsg, &devBroadcast, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES );
214  SDL_HIDAPI_discovery.m_bCanGetNotifications = ( SDL_HIDAPI_discovery.m_hNotify != 0 );
215  }
216 #endif /* __WIN32__ */
217 
218 #if defined(__MACOSX__)
219  SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
220  if (SDL_HIDAPI_discovery.m_notificationPort) {
221  {
222  io_iterator_t portIterator = 0;
223  io_object_t entry;
224  IOReturn result = IOServiceAddMatchingNotification(
225  SDL_HIDAPI_discovery.m_notificationPort,
226  kIOFirstMatchNotification,
227  IOServiceMatching(kIOHIDDeviceKey),
228  CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
229 
230  if (result == 0) {
231  /* Must drain the existing iterator, or we won't receive new notifications */
232  while ((entry = IOIteratorNext(portIterator)) != 0) {
233  IOObjectRelease(entry);
234  }
235  } else {
236  IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
237  SDL_HIDAPI_discovery.m_notificationPort = nil;
238  }
239  }
240  {
241  io_iterator_t portIterator = 0;
242  io_object_t entry;
243  IOReturn result = IOServiceAddMatchingNotification(
244  SDL_HIDAPI_discovery.m_notificationPort,
245  kIOTerminatedNotification,
246  IOServiceMatching(kIOHIDDeviceKey),
247  CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
248 
249  if (result == 0) {
250  /* Must drain the existing iterator, or we won't receive new notifications */
251  while ((entry = IOIteratorNext(portIterator)) != 0) {
252  IOObjectRelease(entry);
253  }
254  } else {
255  IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
256  SDL_HIDAPI_discovery.m_notificationPort = nil;
257  }
258  }
259  }
260 
261  SDL_HIDAPI_discovery.m_notificationMach = MACH_PORT_NULL;
262  if (SDL_HIDAPI_discovery.m_notificationPort) {
263  SDL_HIDAPI_discovery.m_notificationMach = IONotificationPortGetMachPort(SDL_HIDAPI_discovery.m_notificationPort);
264  }
265 
266  SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_notificationMach != MACH_PORT_NULL);
267 
268 #endif // __MACOSX__
269 
270 #if defined(SDL_USE_LIBUDEV)
271  SDL_HIDAPI_discovery.m_pUdev = NULL;
272  SDL_HIDAPI_discovery.m_pUdevMonitor = NULL;
273  SDL_HIDAPI_discovery.m_nUdevFd = -1;
274 
275  usyms = SDL_UDEV_GetUdevSyms();
276  if (usyms) {
277  SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
278  }
279  if (SDL_HIDAPI_discovery.m_pUdev) {
280  SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev, "udev");
281  if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
282  usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
283  SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
284  SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
285  }
286  }
287 
288 #endif /* SDL_USE_LIBUDEV */
289 }
290 
291 static void
292 HIDAPI_UpdateDiscovery()
293 {
294  if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) {
295  const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
296  Uint32 now = SDL_GetTicks();
297  if (!SDL_HIDAPI_discovery.m_unLastDetect || SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) {
298  SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
299  SDL_HIDAPI_discovery.m_unLastDetect = now;
300  }
301  return;
302  }
303 
304 #if defined(__WIN32__)
305 #if 0 /* just let the usual SDL_PumpEvents loop dispatch these, fixing bug 4286. --ryan. */
306  /* We'll only get messages on the same thread that created the window */
307  if (SDL_ThreadID() == SDL_HIDAPI_discovery.m_nThreadID) {
308  MSG msg;
309  while (PeekMessage(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0, PM_NOREMOVE)) {
310  if (GetMessageA(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0) != 0) {
311  TranslateMessage(&msg);
312  DispatchMessage(&msg);
313  }
314  }
315  }
316 #endif
317 #endif /* __WIN32__ */
318 
319 #if defined(__MACOSX__)
320  if (SDL_HIDAPI_discovery.m_notificationPort) {
321  struct { mach_msg_header_t hdr; char payload[ 4096 ]; } msg;
322  while (mach_msg(&msg.hdr, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof(msg), SDL_HIDAPI_discovery.m_notificationMach, 0, MACH_PORT_NULL) == KERN_SUCCESS) {
323  IODispatchCalloutFromMessage(NULL, &msg.hdr, SDL_HIDAPI_discovery.m_notificationPort);
324  }
325  }
326 #endif
327 
328 #if defined(SDL_USE_LIBUDEV)
329  if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
330  /* Drain all notification events.
331  * We don't expect a lot of device notifications so just
332  * do a new discovery on any kind or number of notifications.
333  * This could be made more restrictive if necessary.
334  */
335  for (;;) {
336  struct pollfd PollUdev;
337  struct udev_device *pUdevDevice;
338 
339  PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
340  PollUdev.events = POLLIN;
341  if (poll(&PollUdev, 1, 0) != 1) {
342  break;
343  }
344 
345  SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
346 
347  pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
348  if (pUdevDevice) {
349  usyms->udev_device_unref(pUdevDevice);
350  }
351  }
352  }
353 #endif
354 }
355 
356 static void
357 HIDAPI_ShutdownDiscovery()
358 {
359 #if defined(__WIN32__)
360  if (SDL_HIDAPI_discovery.m_hNotify)
361  UnregisterDeviceNotification(SDL_HIDAPI_discovery.m_hNotify);
362 
363  if (SDL_HIDAPI_discovery.m_hwndMsg) {
364  DestroyWindow(SDL_HIDAPI_discovery.m_hwndMsg);
365  }
366 
367  UnregisterClassA(SDL_HIDAPI_discovery.m_wndClass.lpszClassName, SDL_HIDAPI_discovery.m_wndClass.hInstance);
368 #endif
369 
370 #if defined(__MACOSX__)
371  if (SDL_HIDAPI_discovery.m_notificationPort) {
372  IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
373  }
374 #endif
375 
376 #if defined(SDL_USE_LIBUDEV)
377  if (usyms) {
378  if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
379  usyms->udev_monitor_unref(SDL_HIDAPI_discovery.m_pUdevMonitor);
380  }
381  if (SDL_HIDAPI_discovery.m_pUdev) {
382  usyms->udev_unref(SDL_HIDAPI_discovery.m_pUdev);
383  }
384  SDL_UDEV_ReleaseUdevSyms();
385  usyms = NULL;
386  }
387 #endif
388 }
389 
390 static void HIDAPI_JoystickDetect(void);
391 static void HIDAPI_JoystickClose(SDL_Joystick * joystick);
392 
393 static SDL_bool
394 HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
395 {
396  int i;
397  SDL_GameControllerType type = SDL_GetJoystickGameControllerType(name, vendor_id, product_id, -1, 0, 0, 0);
398 
399  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
400  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
401  if (driver->enabled && driver->IsSupportedDevice(name, type, vendor_id, product_id, version, -1, 0, 0, 0)) {
402  return SDL_TRUE;
403  }
404  }
405  return SDL_FALSE;
406 }
407 
409 HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
410 {
411  const Uint16 USAGE_PAGE_GENERIC_DESKTOP = 0x0001;
412  const Uint16 USAGE_JOYSTICK = 0x0004;
413  const Uint16 USAGE_GAMEPAD = 0x0005;
414  const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
415  int i;
417 
418  if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
419  return NULL;
420  }
421 
422  if (device->usage_page && device->usage_page != USAGE_PAGE_GENERIC_DESKTOP) {
423  return NULL;
424  }
425  if (device->usage && device->usage != USAGE_JOYSTICK && device->usage != USAGE_GAMEPAD && device->usage != USAGE_MULTIAXISCONTROLLER) {
426  return NULL;
427  }
428 
429  type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
430  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
431  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
432  if (driver->enabled && driver->IsSupportedDevice(device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
433  return driver;
434  }
435  }
436  return NULL;
437 }
438 
439 static SDL_HIDAPI_Device *
440 HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
441 {
442  SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
443  while (device) {
444  if (device->driver) {
445  if (device_index < device->num_joysticks) {
446  if (pJoystickID) {
447  *pJoystickID = device->joysticks[device_index];
448  }
449  return device;
450  }
451  device_index -= device->num_joysticks;
452  }
453  device = device->next;
454  }
455  return NULL;
456 }
457 
458 static SDL_HIDAPI_Device *
459 HIDAPI_GetJoystickByInfo(const char *path, Uint16 vendor_id, Uint16 product_id)
460 {
461  SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
462  while (device) {
463  if (device->vendor_id == vendor_id && device->product_id == product_id &&
464  SDL_strcmp(device->path, path) == 0) {
465  break;
466  }
467  device = device->next;
468  }
469  return device;
470 }
471 
472 static void
473 HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
474 {
475  if (device->driver) {
476  /* Already setup */
477  return;
478  }
479 
480  device->driver = HIDAPI_GetDeviceDriver(device);
481  if (device->driver) {
482  const char *name = device->driver->GetDeviceName(device->vendor_id, device->product_id);
483  if (name) {
484  SDL_free(device->name);
485  device->name = SDL_strdup(name);
486  }
487  }
488 
489  /* Initialize the device, which may cause a connected event */
490  if (device->driver && !device->driver->InitDevice(device)) {
491  device->driver = NULL;
492  }
493 }
494 
495 static void
496 HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
497 {
498  if (!device->driver) {
499  /* Already cleaned up */
500  return;
501  }
502 
503  /* Disconnect any joysticks */
504  while (device->num_joysticks) {
505  HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
506  }
507 
508  device->driver->FreeDevice(device);
509  device->driver = NULL;
510 }
511 
512 static void SDLCALL
513 SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
514 {
515  int i;
518 
520  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
521  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
522  driver->enabled = SDL_GetHintBoolean(driver->hint, enabled);
523  }
524  } else {
525  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
526  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
527  if (SDL_strcmp(name, driver->hint) == 0) {
528  driver->enabled = enabled;
529  }
530  }
531  }
532 
533  SDL_HIDAPI_numdrivers = 0;
534  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
535  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
536  if (driver->enabled) {
537  ++SDL_HIDAPI_numdrivers;
538  }
539  }
540 
541  /* Update device list if driver availability changes */
543 
544  for (device = SDL_HIDAPI_devices; device; device = device->next) {
545  if (device->driver && !device->driver->enabled) {
546  HIDAPI_CleanupDeviceDriver(device);
547  }
548  HIDAPI_SetupDeviceDriver(device);
549  }
550 
552 }
553 
554 static int
555 HIDAPI_JoystickInit(void)
556 {
557  int i;
558 
559  if (initialized) {
560  return 0;
561  }
562 
563 #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)
564  /* The hidapi framwork is weak-linked on Apple platforms */
565  int HID_API_EXPORT HID_API_CALL hid_init(void) __attribute__((weak_import));
566 
567  if (hid_init == NULL) {
568  SDL_SetError("Couldn't initialize hidapi, framework not available");
569  return -1;
570  }
571 #endif /* __MACOSX__ || __IPHONEOS__ || __TVOS__ */
572 
573  if (hid_init() < 0) {
574  SDL_SetError("Couldn't initialize hidapi");
575  return -1;
576  }
577 
578  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
579  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
580  SDL_AddHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
581  }
583  SDL_HIDAPIDriverHintChanged, NULL);
584  HIDAPI_InitializeDiscovery();
585  HIDAPI_JoystickDetect();
587 
588  initialized = SDL_TRUE;
589 
590  return 0;
591 }
592 
593 SDL_bool
595 {
596  SDL_JoystickID joystickID;
597  SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
598  if (!joysticks) {
599  return SDL_FALSE;
600  }
601 
602  joystickID = SDL_GetNextJoystickInstanceID();
603  device->joysticks = joysticks;
604  device->joysticks[device->num_joysticks++] = joystickID;
605  ++SDL_HIDAPI_numjoysticks;
606 
607  SDL_PrivateJoystickAdded(joystickID);
608 
609  if (pJoystickID) {
610  *pJoystickID = joystickID;
611  }
612  return SDL_TRUE;
613 }
614 
615 void
617 {
618  int i;
619 
620  for (i = 0; i < device->num_joysticks; ++i) {
621  if (device->joysticks[i] == joystickID) {
622  SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
623  if (joystick) {
624  HIDAPI_JoystickClose(joystick);
625  }
626 
627  SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], device->num_joysticks - i - 1);
628  --device->num_joysticks;
629  --SDL_HIDAPI_numjoysticks;
630  if (device->num_joysticks == 0) {
631  SDL_free(device->joysticks);
632  device->joysticks = NULL;
633  }
634 
635  if (!shutting_down) {
636  SDL_PrivateJoystickRemoved(joystickID);
637  }
638  return;
639  }
640  }
641 }
642 
643 static int
644 HIDAPI_JoystickGetCount(void)
645 {
646  return SDL_HIDAPI_numjoysticks;
647 }
648 
649 static void
650 HIDAPI_AddDevice(struct hid_device_info *info)
651 {
653  SDL_HIDAPI_Device *curr, *last = NULL;
654 
655  for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
656  continue;
657  }
658 
659  device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
660  if (!device) {
661  return;
662  }
663  device->path = SDL_strdup(info->path);
664  if (!device->path) {
665  SDL_free(device);
666  return;
667  }
668  device->seen = SDL_TRUE;
669  device->vendor_id = info->vendor_id;
670  device->product_id = info->product_id;
671  device->version = info->release_number;
672  device->interface_number = info->interface_number;
673  device->interface_class = info->interface_class;
674  device->interface_subclass = info->interface_subclass;
675  device->interface_protocol = info->interface_protocol;
676  device->usage_page = info->usage_page;
677  device->usage = info->usage;
678  {
679  /* FIXME: Is there any way to tell whether this is a Bluetooth device? */
680  const Uint16 vendor = device->vendor_id;
681  const Uint16 product = device->product_id;
682  const Uint16 version = device->version;
683  Uint16 *guid16 = (Uint16 *)device->guid.data;
684 
685  *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
686  *guid16++ = 0;
687  *guid16++ = SDL_SwapLE16(vendor);
688  *guid16++ = 0;
689  *guid16++ = SDL_SwapLE16(product);
690  *guid16++ = 0;
691  *guid16++ = SDL_SwapLE16(version);
692  *guid16++ = 0;
693 
694  /* Note that this is a HIDAPI device for special handling elsewhere */
695  device->guid.data[14] = 'h';
696  device->guid.data[15] = 0;
697  }
698  device->dev_lock = SDL_CreateMutex();
699 
700  /* Need the device name before getting the driver to know whether to ignore this device */
701  if (!device->name) {
702  const char *name = SDL_GetCustomJoystickName(device->vendor_id, device->product_id);
703  if (name) {
704  device->name = SDL_strdup(name);
705  }
706  }
707  if (!device->name && info->manufacturer_string && info->product_string) {
708  const char *manufacturer_remapped;
709  char *manufacturer_string = SDL_iconv_string("UTF-8", "WCHAR_T", (char*)info->manufacturer_string, (SDL_wcslen(info->manufacturer_string)+1)*sizeof(wchar_t));
710  char *product_string = SDL_iconv_string("UTF-8", "WCHAR_T", (char*)info->product_string, (SDL_wcslen(info->product_string)+1)*sizeof(wchar_t));
711  if (!manufacturer_string && !product_string) {
712  if (sizeof(wchar_t) == sizeof(Uint16)) {
713  manufacturer_string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char*)info->manufacturer_string, (SDL_wcslen(info->manufacturer_string)+1)*sizeof(wchar_t));
714  product_string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char*)info->product_string, (SDL_wcslen(info->product_string)+1)*sizeof(wchar_t));
715  } else if (sizeof(wchar_t) == sizeof(Uint32)) {
716  manufacturer_string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char*)info->manufacturer_string, (SDL_wcslen(info->manufacturer_string)+1)*sizeof(wchar_t));
717  product_string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char*)info->product_string, (SDL_wcslen(info->product_string)+1)*sizeof(wchar_t));
718  }
719  }
720 
721  manufacturer_remapped = SDL_GetCustomJoystickManufacturer(manufacturer_string);
722  if (manufacturer_remapped != manufacturer_string) {
723  SDL_free(manufacturer_string);
724  manufacturer_string = SDL_strdup(manufacturer_remapped);
725  }
726 
727  if (manufacturer_string && product_string) {
728  size_t name_size = (SDL_strlen(manufacturer_string) + 1 + SDL_strlen(product_string) + 1);
729  device->name = (char *)SDL_malloc(name_size);
730  if (device->name) {
731  if (SDL_strncasecmp(manufacturer_string, product_string, SDL_strlen(manufacturer_string)) == 0) {
732  SDL_strlcpy(device->name, product_string, name_size);
733  } else {
734  SDL_snprintf(device->name, name_size, "%s %s", manufacturer_string, product_string);
735  }
736  }
737  }
738  if (manufacturer_string) {
739  SDL_free(manufacturer_string);
740  }
741  if (product_string) {
742  SDL_free(product_string);
743  }
744  }
745  if (!device->name) {
746  size_t name_size = (6 + 1 + 6 + 1);
747  device->name = (char *)SDL_malloc(name_size);
748  if (!device->name) {
749  SDL_free(device->path);
750  SDL_free(device);
751  return;
752  }
753  SDL_snprintf(device->name, name_size, "0x%.4x/0x%.4x", info->vendor_id, info->product_id);
754  }
755 
756  /* Add it to the list */
757  if (last) {
758  last->next = device;
759  } else {
760  SDL_HIDAPI_devices = device;
761  }
762 
763  HIDAPI_SetupDeviceDriver(device);
764 
765 #ifdef DEBUG_HIDAPI
766  SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
767 #endif
768 }
769 
770 
771 static void
772 HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
773 {
774  SDL_HIDAPI_Device *curr, *last;
775  for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
776  if (curr == device) {
777  if (last) {
778  last->next = curr->next;
779  } else {
780  SDL_HIDAPI_devices = curr->next;
781  }
782 
783  HIDAPI_CleanupDeviceDriver(device);
784 
785  SDL_DestroyMutex(device->dev_lock);
786  SDL_free(device->name);
787  SDL_free(device->path);
788  SDL_free(device);
789  return;
790  }
791  }
792 }
793 
794 static void
795 HIDAPI_UpdateDeviceList(void)
796 {
798  struct hid_device_info *devs, *info;
799 
801 
802  /* Prepare the existing device list */
803  device = SDL_HIDAPI_devices;
804  while (device) {
805  device->seen = SDL_FALSE;
806  device = device->next;
807  }
808 
809  /* Enumerate the devices */
810  if (SDL_HIDAPI_numdrivers > 0) {
811  devs = hid_enumerate(0, 0);
812  if (devs) {
813  for (info = devs; info; info = info->next) {
814  device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
815  if (device) {
816  device->seen = SDL_TRUE;
817  } else {
818  HIDAPI_AddDevice(info);
819  }
820  }
821  hid_free_enumeration(devs);
822  }
823  }
824 
825  /* Remove any devices that weren't seen */
826  device = SDL_HIDAPI_devices;
827  while (device) {
828  SDL_HIDAPI_Device *next = device->next;
829 
830  if (!device->seen) {
831  HIDAPI_DelDevice(device);
832  }
833  device = next;
834  }
835 
837 }
838 
839 SDL_bool
841 {
843  SDL_bool supported = SDL_FALSE;
845 
846  /* Make sure we're initialized, as this could be called from other drivers during startup */
847  if (HIDAPI_JoystickInit() < 0) {
848  return SDL_FALSE;
849  }
850 
851  /* Only update the device list for devices we know might be supported.
852  If we did this for every device, it would hit the USB driver too hard and potentially
853  lock up the system. This won't catch devices that we support but can only detect using
854  USB interface details, like Xbox controllers, but hopefully the device list update is
855  responsive enough to catch those.
856  */
857  supported = HIDAPI_IsDeviceSupported(vendor_id, product_id, version, name);
858 #if defined(SDL_JOYSTICK_HIDAPI_XBOX360) || defined(SDL_JOYSTICK_HIDAPI_XBOXONE)
859  if (!supported &&
860  (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX"))) {
861  supported = SDL_TRUE;
862  }
863 #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 || SDL_JOYSTICK_HIDAPI_XBOXONE */
864  if (supported) {
865  if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
866  HIDAPI_UpdateDeviceList();
867  SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
868  }
869  }
870 
871  /* Note that this isn't a perfect check - there may be multiple devices with 0 VID/PID,
872  or a different name than we have it listed here, etc, but if we support the device
873  and we have something similar in our device list, mark it as present.
874  */
876  device = SDL_HIDAPI_devices;
877  while (device) {
878  if (device->vendor_id == vendor_id && device->product_id == product_id && device->driver) {
879  result = SDL_TRUE;
880  }
881  device = device->next;
882  }
884 
885  /* If we're looking for the wireless XBox 360 controller, also look for the dongle */
886  if (!result && vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x02a1) {
887  return HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, 0x0719, version, name);
888  }
889 
890 #ifdef DEBUG_HIDAPI
891  SDL_Log("HIDAPI_IsDevicePresent() returning %s for 0x%.4x / 0x%.4x\n", result ? "true" : "false", vendor_id, product_id);
892 #endif
893  return result;
894 }
895 
896 static void
897 HIDAPI_JoystickDetect(void)
898 {
899  if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
900  HIDAPI_UpdateDiscovery();
901  if (SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
902  /* FIXME: We probably need to schedule an update in a few seconds as well */
903  HIDAPI_UpdateDeviceList();
904  SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_FALSE;
905  }
906  SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
907  }
908 }
909 
910 void
912 {
914 
915  /* Update the devices, which may change connected joysticks and send events */
916 
917  /* Prepare the existing device list */
918  if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
919  device = SDL_HIDAPI_devices;
920  while (device) {
921  if (device->driver) {
922  if (SDL_TryLockMutex(device->dev_lock) == 0) {
923  device->driver->UpdateDevice(device);
924  SDL_UnlockMutex(device->dev_lock);
925  }
926  }
927  device = device->next;
928  }
929  SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
930  }
931 }
932 
933 static const char *
934 HIDAPI_JoystickGetDeviceName(int device_index)
935 {
937  const char *name = NULL;
938 
939  device = HIDAPI_GetDeviceByIndex(device_index, NULL);
940  if (device) {
941  /* FIXME: The device could be freed after this name is returned... */
942  name = device->name;
943  }
944 
945  return name;
946 }
947 
948 static int
949 HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
950 {
952  SDL_JoystickID instance_id;
953  int player_index = -1;
954 
955  device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
956  if (device) {
957  player_index = device->driver->GetDevicePlayerIndex(device, instance_id);
958  }
959 
960  return player_index;
961 }
962 
963 static void
964 HIDAPI_JoystickSetDevicePlayerIndex(int device_index, int player_index)
965 {
967  SDL_JoystickID instance_id;
968 
969  device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
970  if (device) {
971  device->driver->SetDevicePlayerIndex(device, instance_id, player_index);
972  }
973 }
974 
975 static SDL_JoystickGUID
976 HIDAPI_JoystickGetDeviceGUID(int device_index)
977 {
979  SDL_JoystickGUID guid;
980 
981  device = HIDAPI_GetDeviceByIndex(device_index, NULL);
982  if (device) {
983  SDL_memcpy(&guid, &device->guid, sizeof(guid));
984  } else {
985  SDL_zero(guid);
986  }
987 
988  return guid;
989 }
990 
991 static SDL_JoystickID
992 HIDAPI_JoystickGetDeviceInstanceID(int device_index)
993 {
994  SDL_JoystickID joystickID = -1;
995  HIDAPI_GetDeviceByIndex(device_index, &joystickID);
996  return joystickID;
997 }
998 
999 static int
1000 HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
1001 {
1002  SDL_JoystickID joystickID;
1003  SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index, &joystickID);
1004  struct joystick_hwdata *hwdata;
1005 
1006  hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
1007  if (!hwdata) {
1008  return SDL_OutOfMemory();
1009  }
1010  hwdata->device = device;
1011 
1012  if (!device->driver->OpenJoystick(device, joystick)) {
1013  SDL_free(hwdata);
1014  return -1;
1015  }
1016 
1017  joystick->hwdata = hwdata;
1018  return 0;
1019 }
1020 
1021 static int
1022 HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1023 {
1024  int result;
1025 
1026  if (joystick->hwdata) {
1027  SDL_HIDAPI_Device *device = joystick->hwdata->device;
1028 
1029  result = device->driver->RumbleJoystick(device, joystick, low_frequency_rumble, high_frequency_rumble);
1030  } else {
1031  SDL_SetError("Rumble failed, device disconnected");
1032  result = -1;
1033  }
1034 
1035  return result;
1036 }
1037 
1038 static void
1039 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
1040 {
1041  /* This is handled in SDL_HIDAPI_UpdateDevices() */
1042 }
1043 
1044 static void
1045 HIDAPI_JoystickClose(SDL_Joystick * joystick)
1046 {
1047  if (joystick->hwdata) {
1048  SDL_HIDAPI_Device *device = joystick->hwdata->device;
1049 
1050  /* Wait for pending rumble to complete */
1051  while (SDL_AtomicGet(&device->rumble_pending) > 0) {
1052  SDL_Delay(10);
1053  }
1054 
1055  device->driver->CloseJoystick(device, joystick);
1056 
1057  SDL_free(joystick->hwdata);
1058  joystick->hwdata = NULL;
1059  }
1060 }
1061 
1062 static void
1063 HIDAPI_JoystickQuit(void)
1064 {
1065  int i;
1066 
1067  shutting_down = SDL_TRUE;
1068 
1069  HIDAPI_ShutdownDiscovery();
1070 
1071  while (SDL_HIDAPI_devices) {
1072  HIDAPI_DelDevice(SDL_HIDAPI_devices);
1073  }
1074 
1075  SDL_HIDAPI_QuitRumble();
1076 
1077  for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
1078  SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
1079  SDL_DelHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
1080  }
1082  SDL_HIDAPIDriverHintChanged, NULL);
1083 
1084  hid_exit();
1085 
1086  /* Make sure the drivers cleaned up properly */
1087  SDL_assert(SDL_HIDAPI_numjoysticks == 0);
1088 
1089  shutting_down = SDL_FALSE;
1090  initialized = SDL_FALSE;
1091 }
1092 
1094 {
1095  HIDAPI_JoystickInit,
1096  HIDAPI_JoystickGetCount,
1097  HIDAPI_JoystickDetect,
1098  HIDAPI_JoystickGetDeviceName,
1099  HIDAPI_JoystickGetDevicePlayerIndex,
1100  HIDAPI_JoystickSetDevicePlayerIndex,
1101  HIDAPI_JoystickGetDeviceGUID,
1102  HIDAPI_JoystickGetDeviceInstanceID,
1103  HIDAPI_JoystickOpen,
1104  HIDAPI_JoystickRumble,
1105  HIDAPI_JoystickUpdate,
1106  HIDAPI_JoystickClose,
1107  HIDAPI_JoystickQuit,
1108 };
1109 
1110 #endif /* SDL_JOYSTICK_HIDAPI */
1111 
1112 /* vi: set ts=4 sw=4 expandtab: */
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:418
SDL_ShouldIgnoreJoystick
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
Definition: SDL_joystick.c:1698
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
hid_device_info::interface_subclass
int interface_subclass
Definition: hidapi.h:88
SDL_HIDAPI_DriverPS4
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4
SDL_strlcpy
#define SDL_strlcpy
Definition: SDL_dynapi_overrides.h:394
hid_device_info::interface_number
int interface_number
Definition: hidapi.h:83
SDL_GetCustomJoystickName
const char * SDL_GetCustomJoystickName(Uint16 vendor, Uint16 product)
Definition: SDL_joystick.c:1386
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_UnlockJoysticks
#define SDL_UnlockJoysticks
Definition: SDL_dynapi_overrides.h:639
SDL_atomic.h
NULL
#define NULL
Definition: begin_code.h:167
SDL_timer.h
message
GLuint GLsizei const GLchar * message
Definition: SDL_opengl_glext.h:2486
HIDAPI_JoystickConnected
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
hid_exit
int HID_API_EXPORT HID_API_CALL hid_exit(void)
Finalize the HIDAPI library.
SDL_joystick.h
SDL_JoystickID
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
TRUE
#define TRUE
Definition: edid-parse.c:33
SDL_log.h
USB_VENDOR_MICROSOFT
#define USB_VENDOR_MICROSOFT
Definition: usb_ids.h:28
SDL_hidapi_rumble.h
hid_free_enumeration
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:49
x0
GLuint GLfloat x0
Definition: SDL_opengl_glext.h:8586
hid_init
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_PrivateJoystickAdded
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:921
HIDAPI_IsDevicePresent
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:259
joystick_hwdata::joystick
SDL_Joystick * joystick
Definition: SDL_sysjoystick_c.h:42
SDL_HIDAPI_Device::next
struct _SDL_HIDAPI_Device * next
Definition: SDL_hidapijoystick_c.h:89
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_GetNextJoystickInstanceID
SDL_JoystickID SDL_GetNextJoystickInstanceID()
Definition: SDL_joystick.c:250
SDL_endian.h
SDL_HIDAPI_Device
Definition: SDL_hidapijoystick_c.h:64
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3733
hid_device_info::manufacturer_string
wchar_t * manufacturer_string
Definition: hidapi.h:70
SDL_GetJoystickGameControllerType
SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
Definition: SDL_joystick.c:1409
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:235
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9435
SDL_GetCustomJoystickManufacturer
const char * SDL_GetCustomJoystickManufacturer(const char *manufacturer)
Definition: SDL_joystick.c:1373
SDL_PrivateJoystickRemoved
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:987
SDL_hidapijoystick_c.h
SDL_strncasecmp
#define SDL_strncasecmp
Definition: SDL_dynapi_overrides.h:420
hid_device_info::next
struct hid_device_info * next
Definition: hidapi.h:92
hid_device_info
Definition: hidapi.h:57
SDL_HIDAPI_DriverSwitch
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch
SDL_HIDAPI_DriverXbox360
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
context
static screen_context_t context
Definition: video.c:25
SDL_thread.h
SDL_AtomicUnlock
#define SDL_AtomicUnlock
Definition: SDL_dynapi_overrides.h:65
hid_enumerate
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:31
SDL_JoystickFromInstanceID
#define SDL_JoystickFromInstanceID
Definition: SDL_dynapi_overrides.h:595
hid_device_info::product_id
unsigned short product_id
Definition: hidapi.h:63
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_TryLockMutex
#define SDL_TryLockMutex
Definition: SDL_dynapi_overrides.h:261
SDL_HIDAPI_DeviceDriver::enabled
SDL_bool enabled
Definition: SDL_hidapijoystick_c.h:95
hid_device_info::interface_class
int interface_class
Definition: hidapi.h:87
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
SDL_HIDAPI_DeviceDriver
Definition: SDL_hidapijoystick_c.h:93
SDL_wcslen
#define SDL_wcslen
Definition: SDL_dynapi_overrides.h:390
SDL_assert.h
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_HINT_JOYSTICK_HIDAPI
#define SDL_HINT_JOYSTICK_HIDAPI
A variable controlling whether the HIDAPI joystick drivers should be used.
Definition: SDL_hints.h:580
hid_device_info::release_number
unsigned short release_number
Definition: hidapi.h:68
SDL_memmove
#define SDL_memmove
Definition: SDL_dynapi_overrides.h:388
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_Delay
#define SDL_Delay
Definition: SDL_dynapi_overrides.h:486
hid_device_info::usage
unsigned short usage
Definition: hidapi.h:78
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_HARDWARE_BUS_USB
#define SDL_HARDWARE_BUS_USB
Definition: SDL_sysjoystick.h:82
SDL_HIDAPI_DriverXboxOne
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:89
SDL_JoystickDriver
Definition: SDL_sysjoystick.h:89
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_AtomicTryLock
#define SDL_AtomicTryLock
Definition: SDL_dynapi_overrides.h:63
hid_device_info::interface_protocol
int interface_protocol
Definition: hidapi.h:89
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
HID_API_CALL
#define HID_API_CALL
Definition: hidapi.h:40
SDL_threadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49
HIDAPI_JoystickDisconnected
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
SDL_AddHintCallback
#define SDL_AddHintCallback
Definition: SDL_dynapi_overrides.h:192
hid_device_info::usage_page
unsigned short usage_page
Definition: hidapi.h:75
SDL_HIDAPI_DriverSteam
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam
SDL_iconv_string
#define SDL_iconv_string
Definition: SDL_dynapi_overrides.h:441
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_GameControllerType
SDL_GameControllerType
Definition: SDL_gamecontroller.h:61
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
SDL_hints.h
SDL_HIDAPI_DriverGameCube
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube
SDL_DestroyMutex
#define SDL_DestroyMutex
Definition: SDL_dynapi_overrides.h:263
SDL_HIDAPI_DeviceDriver::IsSupportedDevice
SDL_bool(* IsSupportedDevice)(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
Definition: SDL_hidapijoystick_c.h:96
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:397
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2482
SDL_GetStringBoolean
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
Definition: SDL_hints.c:123
SDL_TICKS_PASSED
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_DelHintCallback
#define SDL_DelHintCallback
Definition: SDL_dynapi_overrides.h:193
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
HIDAPI_UpdateDevices
void HIDAPI_UpdateDevices(void)
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_AtomicGet
#define SDL_AtomicGet
Definition: SDL_dynapi_overrides.h:68
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
hid_device_info::path
char * path
Definition: hidapi.h:59
SDL_strstr
#define SDL_strstr
Definition: SDL_dynapi_overrides.h:403
device
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_JoystickGUID
Definition: SDL_joystick.h:70
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:475
SDL_HIDAPI_DeviceDriver::hint
const char * hint
Definition: SDL_hidapijoystick_c.h:94
SDL_LockJoysticks
#define SDL_LockJoysticks
Definition: SDL_dynapi_overrides.h:638
hid_device_info::vendor_id
unsigned short vendor_id
Definition: hidapi.h:61
hid_device_info::product_string
wchar_t * product_string
Definition: hidapi.h:72
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_HIDAPI_JoystickDriver
SDL_JoystickDriver SDL_HIDAPI_JoystickDriver
joystick_hwdata
Definition: SDL_sysjoystick_c.h:47
HID_API_EXPORT
#define HID_API_EXPORT
Definition: hidapi.h:37
SDL_HIDAPI_DriverXbox360W
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W