21 #include "../../SDL_internal.h" 23 #ifdef SDL_JOYSTICK_HIDAPI 32 #include "../SDL_sysjoystick.h" 35 #if defined(__WIN32__) 36 #include "../../core/windows/SDL_windows.h" 39 #if defined(__MACOSX__) 40 #include <CoreFoundation/CoreFoundation.h> 41 #include <mach/mach.h> 42 #include <IOKit/IOKitLib.h> 43 #include <IOKit/usb/USBSpec.h> 46 #if defined(__LINUX__) 47 #include "../../core/linux/SDL_udev.h" 48 #ifdef SDL_USE_LIBUDEV 62 typedef struct _SDL_HIDAPI_Device
79 struct _SDL_HIDAPI_Device *
next;
83 #ifdef SDL_JOYSTICK_HIDAPI_PS4 86 #ifdef SDL_JOYSTICK_HIDAPI_STEAM 89 #ifdef SDL_JOYSTICK_HIDAPI_SWITCH 92 #ifdef SDL_JOYSTICK_HIDAPI_XBOX360 95 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE 99 static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
100 static int SDL_HIDAPI_numjoysticks = 0;
102 #if defined(SDL_USE_LIBUDEV) 103 static const SDL_UDEV_Symbols * usyms =
NULL;
112 #if defined(__WIN32__) 114 WNDCLASSEXA m_wndClass;
116 HDEVNOTIFY m_hNotify;
117 double m_flLastWin32MessageCheck;
120 #if defined(__MACOSX__) 121 IONotificationPortRef m_notificationPort;
122 mach_port_t m_notificationMach;
125 #if defined(SDL_USE_LIBUDEV) 126 struct udev *m_pUdev;
127 struct udev_monitor *m_pUdevMonitor;
130 } SDL_HIDAPI_discovery;
134 struct _DEV_BROADCAST_HDR
137 DWORD dbch_devicetype;
141 typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A
144 DWORD dbcc_devicetype;
148 } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
150 typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR;
151 #define DBT_DEVICEARRIVAL 0x8000 152 #define DBT_DEVICEREMOVECOMPLETE 0x8004 153 #define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 154 #define DBT_DEVNODES_CHANGED 0x0007 155 #define DBT_CONFIGCHANGED 0x0018 156 #define DBT_DEVICETYPESPECIFIC 0x8005 157 #define DBT_DEVINSTSTARTED 0x8008 159 #include <initguid.h> 160 DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
162 static LRESULT CALLBACK ControllerWndProc(HWND hwnd, UINT
message, WPARAM wParam, LPARAM lParam)
165 case WM_DEVICECHANGE:
167 case DBT_DEVICEARRIVAL:
168 case DBT_DEVICEREMOVECOMPLETE:
169 if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
170 SDL_HIDAPI_discovery.m_bHaveDevicesChanged =
SDL_TRUE;
177 return DefWindowProc(hwnd, message, wParam, lParam);
182 #if defined(__MACOSX__) 183 static void CallbackIOServiceFunc(
void *
context, io_iterator_t portIterator)
187 while ((entry = IOIteratorNext(portIterator)) != 0) {
188 IOObjectRelease(entry);
195 HIDAPI_InitializeDiscovery()
197 SDL_HIDAPI_discovery.m_bHaveDevicesChanged =
SDL_TRUE;
198 SDL_HIDAPI_discovery.m_bCanGetNotifications =
SDL_FALSE;
199 SDL_HIDAPI_discovery.m_unLastDetect = 0;
201 #if defined(__WIN32__) 204 SDL_memset(&SDL_HIDAPI_discovery.m_wndClass, 0
x0,
sizeof(SDL_HIDAPI_discovery.m_wndClass));
205 SDL_HIDAPI_discovery.m_wndClass.hInstance = GetModuleHandle(
NULL);
206 SDL_HIDAPI_discovery.m_wndClass.lpszClassName =
"SDL_HIDAPI_DEVICE_DETECTION";
207 SDL_HIDAPI_discovery.m_wndClass.lpfnWndProc = ControllerWndProc;
208 SDL_HIDAPI_discovery.m_wndClass.cbSize =
sizeof(WNDCLASSEX);
210 RegisterClassExA(&SDL_HIDAPI_discovery.m_wndClass);
211 SDL_HIDAPI_discovery.m_hwndMsg = CreateWindowExA(0,
"SDL_HIDAPI_DEVICE_DETECTION",
NULL, 0, 0, 0, 0, 0, HWND_MESSAGE,
NULL,
NULL,
NULL);
214 DEV_BROADCAST_DEVICEINTERFACE_A devBroadcast;
215 SDL_memset( &devBroadcast, 0
x0,
sizeof( devBroadcast ) );
217 devBroadcast.dbcc_size =
sizeof( devBroadcast );
218 devBroadcast.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
219 devBroadcast.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
225 SDL_HIDAPI_discovery.m_hNotify = RegisterDeviceNotification( SDL_HIDAPI_discovery.m_hwndMsg, &devBroadcast, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES );
226 SDL_HIDAPI_discovery.m_bCanGetNotifications = ( SDL_HIDAPI_discovery.m_hNotify != 0 );
230 #if defined(__MACOSX__) 231 SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
232 if (SDL_HIDAPI_discovery.m_notificationPort) {
234 CFMutableDictionaryRef matchingDict = IOServiceMatching(
"IOUSBDevice");
237 io_iterator_t portIterator = 0;
239 if (IOServiceAddMatchingNotification(SDL_HIDAPI_discovery.m_notificationPort, kIOMatchedNotification, matchingDict, CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator) == 0) {
241 while ((entry = IOIteratorNext(portIterator)) != 0) {
242 IOObjectRelease(entry);
245 IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
246 SDL_HIDAPI_discovery.m_notificationPort = nil;
250 CFMutableDictionaryRef matchingDict = IOServiceMatching(
"IOBluetoothDevice");
253 io_iterator_t portIterator = 0;
255 if (IOServiceAddMatchingNotification(SDL_HIDAPI_discovery.m_notificationPort, kIOMatchedNotification, matchingDict, CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator) == 0) {
257 while ((entry = IOIteratorNext(portIterator)) != 0) {
258 IOObjectRelease(entry);
261 IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
262 SDL_HIDAPI_discovery.m_notificationPort = nil;
267 SDL_HIDAPI_discovery.m_notificationMach = MACH_PORT_NULL;
268 if (SDL_HIDAPI_discovery.m_notificationPort) {
269 SDL_HIDAPI_discovery.m_notificationMach = IONotificationPortGetMachPort(SDL_HIDAPI_discovery.m_notificationPort);
272 SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_notificationMach != MACH_PORT_NULL);
276 #if defined(SDL_USE_LIBUDEV) 277 SDL_HIDAPI_discovery.m_pUdev =
NULL;
278 SDL_HIDAPI_discovery.m_pUdevMonitor =
NULL;
279 SDL_HIDAPI_discovery.m_nUdevFd = -1;
281 usyms = SDL_UDEV_GetUdevSyms();
283 SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
285 if (SDL_HIDAPI_discovery.m_pUdev) {
286 SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev,
"udev");
287 if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
288 usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
289 SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
290 SDL_HIDAPI_discovery.m_bCanGetNotifications =
SDL_TRUE;
298 HIDAPI_UpdateDiscovery()
300 if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) {
301 const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000;
303 if (!SDL_HIDAPI_discovery.m_unLastDetect ||
SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) {
304 SDL_HIDAPI_discovery.m_bHaveDevicesChanged =
SDL_TRUE;
305 SDL_HIDAPI_discovery.m_unLastDetect = now;
310 #if defined(__WIN32__) 313 if (
SDL_ThreadID() == SDL_HIDAPI_discovery.m_nThreadID) {
315 while (PeekMessage(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0, PM_NOREMOVE)) {
316 if (GetMessageA(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0) != 0) {
317 TranslateMessage(&msg);
318 DispatchMessage(&msg);
325 #if defined(__MACOSX__) 326 if (SDL_HIDAPI_discovery.m_notificationPort) {
327 struct { mach_msg_header_t hdr;
char payload[ 4096 ]; } msg;
328 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) {
329 IODispatchCalloutFromMessage(
NULL, &msg.hdr, SDL_HIDAPI_discovery.m_notificationPort);
334 #if defined(SDL_USE_LIBUDEV) 335 if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
342 struct pollfd PollUdev;
343 struct udev_device *pUdevDevice;
345 PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
346 PollUdev.events = POLLIN;
347 if (poll(&PollUdev, 1, 0) != 1) {
351 SDL_HIDAPI_discovery.m_bHaveDevicesChanged =
SDL_TRUE;
353 pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
355 usyms->udev_device_unref(pUdevDevice);
363 HIDAPI_ShutdownDiscovery()
365 #if defined(__WIN32__) 366 if (SDL_HIDAPI_discovery.m_hNotify)
367 UnregisterDeviceNotification(SDL_HIDAPI_discovery.m_hNotify);
369 if (SDL_HIDAPI_discovery.m_hwndMsg) {
370 DestroyWindow(SDL_HIDAPI_discovery.m_hwndMsg);
373 UnregisterClassA(SDL_HIDAPI_discovery.m_wndClass.lpszClassName, SDL_HIDAPI_discovery.m_wndClass.hInstance);
376 #if defined(__MACOSX__) 377 if (SDL_HIDAPI_discovery.m_notificationPort) {
378 IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
382 #if defined(SDL_USE_LIBUDEV) 384 if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
385 usyms->udev_monitor_unref(SDL_HIDAPI_discovery.m_pUdevMonitor);
387 if (SDL_HIDAPI_discovery.m_pUdev) {
388 usyms->udev_unref(SDL_HIDAPI_discovery.m_pUdev);
390 SDL_UDEV_ReleaseUdevSyms();
405 {
MAKE_VIDPID(0x0079, 0x18d4),
"GPD Win 2 X-Box Controller" },
406 {
MAKE_VIDPID(0x044f, 0xb326),
"Thrustmaster Gamepad GP XID" },
407 {
MAKE_VIDPID(0x045e, 0x028e),
"Microsoft X-Box 360 pad" },
408 {
MAKE_VIDPID(0x045e, 0x028f),
"Microsoft X-Box 360 pad v2" },
409 {
MAKE_VIDPID(0x045e, 0x0291),
"Xbox 360 Wireless Receiver (XBOX)" },
410 {
MAKE_VIDPID(0x045e, 0x02d1),
"Microsoft X-Box One pad" },
411 {
MAKE_VIDPID(0x045e, 0x02dd),
"Microsoft X-Box One pad (Firmware 2015)" },
412 {
MAKE_VIDPID(0x045e, 0x02e3),
"Microsoft X-Box One Elite pad" },
413 {
MAKE_VIDPID(0x045e, 0x02ea),
"Microsoft X-Box One S pad" },
414 {
MAKE_VIDPID(0x045e, 0x02ff),
"Microsoft X-Box One pad" },
415 {
MAKE_VIDPID(0x045e, 0x0719),
"Xbox 360 Wireless Receiver" },
416 {
MAKE_VIDPID(0x046d, 0xc21d),
"Logitech Gamepad F310" },
417 {
MAKE_VIDPID(0x046d, 0xc21e),
"Logitech Gamepad F510" },
418 {
MAKE_VIDPID(0x046d, 0xc21f),
"Logitech Gamepad F710" },
419 {
MAKE_VIDPID(0x046d, 0xc242),
"Logitech Chillstream Controller" },
420 {
MAKE_VIDPID(0x046d, 0xcaa3),
"Logitech DriveFx Racing Wheel" },
421 {
MAKE_VIDPID(0x056e, 0x2004),
"Elecom JC-U3613M" },
423 {
MAKE_VIDPID(0x0738, 0x4716),
"Mad Catz Wired Xbox 360 Controller" },
424 {
MAKE_VIDPID(0x0738, 0x4718),
"Mad Catz Street Fighter IV FightStick SE" },
425 {
MAKE_VIDPID(0x0738, 0x4726),
"Mad Catz Xbox 360 Controller" },
426 {
MAKE_VIDPID(0x0738, 0x4728),
"Mad Catz Street Fighter IV FightPad" },
427 {
MAKE_VIDPID(0x0738, 0x4736),
"Mad Catz MicroCon Gamepad" },
428 {
MAKE_VIDPID(0x0738, 0x4738),
"Mad Catz Wired Xbox 360 Controller (SFIV)" },
429 {
MAKE_VIDPID(0x0738, 0x4740),
"Mad Catz Beat Pad" },
430 {
MAKE_VIDPID(0x0738, 0x4758),
"Mad Catz Arcade Game Stick" },
431 {
MAKE_VIDPID(0x0738, 0x4a01),
"Mad Catz FightStick TE 2" },
432 {
MAKE_VIDPID(0x0738, 0x9871),
"Mad Catz Portable Drum" },
433 {
MAKE_VIDPID(0x0738, 0xb726),
"Mad Catz Xbox controller - MW2" },
434 {
MAKE_VIDPID(0x0738, 0xb738),
"Mad Catz MVC2TE Stick 2" },
435 {
MAKE_VIDPID(0x0738, 0xbeef),
"Mad Catz JOYTECH NEO SE Advanced GamePad" },
436 {
MAKE_VIDPID(0x0738, 0xcb02),
"Saitek Cyborg Rumble Pad - PC/Xbox 360" },
437 {
MAKE_VIDPID(0x0738, 0xcb03),
"Saitek P3200 Rumble Pad - PC/Xbox 360" },
438 {
MAKE_VIDPID(0x0738, 0xcb29),
"Saitek Aviator Stick AV8R02" },
439 {
MAKE_VIDPID(0x0738, 0xf738),
"Super SFIV FightStick TE S" },
440 {
MAKE_VIDPID(0x07ff, 0xffff),
"Mad Catz GamePad" },
441 {
MAKE_VIDPID(0x0e6f, 0x0105),
"HSM3 Xbox360 dancepad" },
442 {
MAKE_VIDPID(0x0e6f, 0x0113),
"Afterglow AX.1 Gamepad for Xbox 360" },
443 {
MAKE_VIDPID(0x0e6f, 0x011f),
"Rock Candy Gamepad Wired Controller" },
444 {
MAKE_VIDPID(0x0e6f, 0x0131),
"PDP EA Sports Controller" },
445 {
MAKE_VIDPID(0x0e6f, 0x0133),
"Xbox 360 Wired Controller" },
446 {
MAKE_VIDPID(0x0e6f, 0x0139),
"Afterglow Prismatic Wired Controller" },
447 {
MAKE_VIDPID(0x0e6f, 0x013a),
"PDP Xbox One Controller" },
448 {
MAKE_VIDPID(0x0e6f, 0x0146),
"Rock Candy Wired Controller for Xbox One" },
449 {
MAKE_VIDPID(0x0e6f, 0x0147),
"PDP Marvel Xbox One Controller" },
450 {
MAKE_VIDPID(0x0e6f, 0x015c),
"PDP Xbox One Arcade Stick" },
451 {
MAKE_VIDPID(0x0e6f, 0x0161),
"PDP Xbox One Controller" },
452 {
MAKE_VIDPID(0x0e6f, 0x0162),
"PDP Xbox One Controller" },
453 {
MAKE_VIDPID(0x0e6f, 0x0163),
"PDP Xbox One Controller" },
454 {
MAKE_VIDPID(0x0e6f, 0x0164),
"PDP Battlefield One" },
455 {
MAKE_VIDPID(0x0e6f, 0x0165),
"PDP Titanfall 2" },
456 {
MAKE_VIDPID(0x0e6f, 0x0201),
"Pelican PL-3601 'TSZ' Wired Xbox 360 Controller" },
457 {
MAKE_VIDPID(0x0e6f, 0x0213),
"Afterglow Gamepad for Xbox 360" },
458 {
MAKE_VIDPID(0x0e6f, 0x021f),
"Rock Candy Gamepad for Xbox 360" },
459 {
MAKE_VIDPID(0x0e6f, 0x0246),
"Rock Candy Gamepad for Xbox One 2015" },
460 {
MAKE_VIDPID(0x0e6f, 0x02a4),
"PDP Wired Controller for Xbox One - Stealth Series" },
461 {
MAKE_VIDPID(0x0e6f, 0x02ab),
"PDP Controller for Xbox One" },
462 {
MAKE_VIDPID(0x0e6f, 0x0301),
"Logic3 Controller" },
463 {
MAKE_VIDPID(0x0e6f, 0x0346),
"Rock Candy Gamepad for Xbox One 2016" },
464 {
MAKE_VIDPID(0x0e6f, 0x0401),
"Logic3 Controller" },
465 {
MAKE_VIDPID(0x0e6f, 0x0413),
"Afterglow AX.1 Gamepad for Xbox 360" },
466 {
MAKE_VIDPID(0x0e6f, 0x0501),
"PDP Xbox 360 Controller" },
467 {
MAKE_VIDPID(0x0e6f, 0xf900),
"PDP Afterglow AX.1" },
468 {
MAKE_VIDPID(0x0f0d, 0x000a),
"Hori Co. DOA4 FightStick" },
469 {
MAKE_VIDPID(0x0f0d, 0x000c),
"Hori PadEX Turbo" },
470 {
MAKE_VIDPID(0x0f0d, 0x000d),
"Hori Fighting Stick EX2" },
471 {
MAKE_VIDPID(0x0f0d, 0x0016),
"Hori Real Arcade Pro.EX" },
472 {
MAKE_VIDPID(0x0f0d, 0x001b),
"Hori Real Arcade Pro VX" },
473 {
MAKE_VIDPID(0x0f0d, 0x0063),
"Hori Real Arcade Pro Hayabusa (USA) Xbox One" },
475 {
MAKE_VIDPID(0x0f0d, 0x0078),
"Hori Real Arcade Pro V Kai Xbox One" },
477 {
MAKE_VIDPID(0x12ab, 0x0004),
"Honey Bee Xbox360 dancepad" },
478 {
MAKE_VIDPID(0x12ab, 0x0301),
"PDP AFTERGLOW AX.1" },
479 {
MAKE_VIDPID(0x12ab, 0x0303),
"Mortal Kombat Klassic FightStick" },
480 {
MAKE_VIDPID(0x1430, 0x4748),
"RedOctane Guitar Hero X-plorer" },
481 {
MAKE_VIDPID(0x1430, 0xf801),
"RedOctane Controller" },
482 {
MAKE_VIDPID(0x146b, 0x0601),
"BigBen Interactive XBOX 360 Controller" },
483 {
MAKE_VIDPID(0x1532, 0x0037),
"Razer Sabertooth" },
484 {
MAKE_VIDPID(0x1532, 0x0a00),
"Razer Atrox Arcade Stick" },
486 {
MAKE_VIDPID(0x15e4, 0x3f00),
"Power A Mini Pro Elite" },
487 {
MAKE_VIDPID(0x15e4, 0x3f0a),
"Xbox Airflo wired controller" },
488 {
MAKE_VIDPID(0x15e4, 0x3f10),
"Batarang Xbox 360 controller" },
489 {
MAKE_VIDPID(0x162e, 0xbeef),
"Joytech Neo-Se Take2" },
490 {
MAKE_VIDPID(0x1689, 0xfd00),
"Razer Onza Tournament Edition" },
491 {
MAKE_VIDPID(0x1689, 0xfd01),
"Razer Onza Classic Edition" },
492 {
MAKE_VIDPID(0x1689, 0xfe00),
"Razer Sabertooth" },
493 {
MAKE_VIDPID(0x1bad, 0x0002),
"Harmonix Rock Band Guitar" },
494 {
MAKE_VIDPID(0x1bad, 0x0003),
"Harmonix Rock Band Drumkit" },
495 {
MAKE_VIDPID(0x1bad, 0x0130),
"Ion Drum Rocker" },
496 {
MAKE_VIDPID(0x1bad, 0xf016),
"Mad Catz Xbox 360 Controller" },
497 {
MAKE_VIDPID(0x1bad, 0xf018),
"Mad Catz Street Fighter IV SE Fighting Stick" },
498 {
MAKE_VIDPID(0x1bad, 0xf019),
"Mad Catz Brawlstick for Xbox 360" },
499 {
MAKE_VIDPID(0x1bad, 0xf021),
"Mad Cats Ghost Recon FS GamePad" },
500 {
MAKE_VIDPID(0x1bad, 0xf023),
"MLG Pro Circuit Controller (Xbox)" },
501 {
MAKE_VIDPID(0x1bad, 0xf025),
"Mad Catz Call Of Duty" },
502 {
MAKE_VIDPID(0x1bad, 0xf027),
"Mad Catz FPS Pro" },
503 {
MAKE_VIDPID(0x1bad, 0xf028),
"Street Fighter IV FightPad" },
504 {
MAKE_VIDPID(0x1bad, 0xf02e),
"Mad Catz Fightpad" },
505 {
MAKE_VIDPID(0x1bad, 0xf030),
"Mad Catz Xbox 360 MC2 MicroCon Racing Wheel" },
506 {
MAKE_VIDPID(0x1bad, 0xf036),
"Mad Catz MicroCon GamePad Pro" },
507 {
MAKE_VIDPID(0x1bad, 0xf038),
"Street Fighter IV FightStick TE" },
508 {
MAKE_VIDPID(0x1bad, 0xf039),
"Mad Catz MvC2 TE" },
509 {
MAKE_VIDPID(0x1bad, 0xf03a),
"Mad Catz SFxT Fightstick Pro" },
510 {
MAKE_VIDPID(0x1bad, 0xf03d),
"Street Fighter IV Arcade Stick TE - Chun Li" },
511 {
MAKE_VIDPID(0x1bad, 0xf03e),
"Mad Catz MLG FightStick TE" },
512 {
MAKE_VIDPID(0x1bad, 0xf03f),
"Mad Catz FightStick SoulCaliber" },
513 {
MAKE_VIDPID(0x1bad, 0xf042),
"Mad Catz FightStick TES+" },
514 {
MAKE_VIDPID(0x1bad, 0xf080),
"Mad Catz FightStick TE2" },
515 {
MAKE_VIDPID(0x1bad, 0xf501),
"HoriPad EX2 Turbo" },
516 {
MAKE_VIDPID(0x1bad, 0xf502),
"Hori Real Arcade Pro.VX SA" },
517 {
MAKE_VIDPID(0x1bad, 0xf503),
"Hori Fighting Stick VX" },
518 {
MAKE_VIDPID(0x1bad, 0xf504),
"Hori Real Arcade Pro. EX" },
519 {
MAKE_VIDPID(0x1bad, 0xf505),
"Hori Fighting Stick EX2B" },
520 {
MAKE_VIDPID(0x1bad, 0xf506),
"Hori Real Arcade Pro.EX Premium VLX" },
521 {
MAKE_VIDPID(0x1bad, 0xf900),
"Harmonix Xbox 360 Controller" },
522 {
MAKE_VIDPID(0x1bad, 0xf901),
"Gamestop Xbox 360 Controller" },
523 {
MAKE_VIDPID(0x1bad, 0xf903),
"Tron Xbox 360 controller" },
524 {
MAKE_VIDPID(0x1bad, 0xf904),
"PDP Versus Fighting Pad" },
525 {
MAKE_VIDPID(0x1bad, 0xf906),
"MortalKombat FightStick" },
526 {
MAKE_VIDPID(0x1bad, 0xfa01),
"MadCatz GamePad" },
529 {
MAKE_VIDPID(0x24c6, 0x5000),
"Razer Atrox Arcade Stick" },
530 {
MAKE_VIDPID(0x24c6, 0x5300),
"PowerA MINI PROEX Controller" },
531 {
MAKE_VIDPID(0x24c6, 0x5303),
"Xbox Airflo wired controller" },
532 {
MAKE_VIDPID(0x24c6, 0x530a),
"Xbox 360 Pro EX Controller" },
534 {
MAKE_VIDPID(0x24c6, 0x5397),
"FUS1ON Tournament Controller" },
535 {
MAKE_VIDPID(0x24c6, 0x541a),
"PowerA Xbox One Mini Wired Controller" },
536 {
MAKE_VIDPID(0x24c6, 0x542a),
"Xbox ONE spectra" },
537 {
MAKE_VIDPID(0x24c6, 0x543a),
"PowerA Xbox One wired controller" },
538 {
MAKE_VIDPID(0x24c6, 0x5500),
"Hori XBOX 360 EX 2 with Turbo" },
539 {
MAKE_VIDPID(0x24c6, 0x5501),
"Hori Real Arcade Pro VX-SA" },
540 {
MAKE_VIDPID(0x24c6, 0x5502),
"Hori Fighting Stick VX Alt" },
541 {
MAKE_VIDPID(0x24c6, 0x5503),
"Hori Fighting Edge" },
542 {
MAKE_VIDPID(0x24c6, 0x5506),
"Hori SOULCALIBUR V Stick" },
543 {
MAKE_VIDPID(0x24c6, 0x550d),
"Hori GEM Xbox controller" },
544 {
MAKE_VIDPID(0x24c6, 0x550e),
"Hori Real Arcade Pro V Kai 360" },
545 {
MAKE_VIDPID(0x24c6, 0x551a),
"PowerA FUSION Pro Controller" },
546 {
MAKE_VIDPID(0x24c6, 0x561a),
"PowerA FUSION Controller" },
547 {
MAKE_VIDPID(0x24c6, 0x5b00),
"ThrustMaster Ferrari 458 Racing Wheel" },
548 {
MAKE_VIDPID(0x24c6, 0x5b02),
"Thrustmaster, Inc. GPX Controller" },
549 {
MAKE_VIDPID(0x24c6, 0x5b03),
"Thrustmaster Ferrari 458 Racing Wheel" },
550 {
MAKE_VIDPID(0x24c6, 0x5d04),
"Razer Sabertooth" },
551 {
MAKE_VIDPID(0x24c6, 0xfafe),
"Rock Candy Gamepad for Xbox 360" },
557 if (vidpid ==
names[i].vidpid) {
579 HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *
device)
581 const Uint16 USAGE_PAGE_GENERIC_DESKTOP = 0x0001;
582 const Uint16 USAGE_JOYSTICK = 0x0004;
583 const Uint16 USAGE_GAMEPAD = 0x0005;
584 const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
591 if (device->usage_page && device->usage_page != USAGE_PAGE_GENERIC_DESKTOP) {
594 if (device->usage && device->usage != USAGE_JOYSTICK && device->usage != USAGE_GAMEPAD && device->usage != USAGE_MULTIAXISCONTROLLER) {
600 if (driver->
enabled && driver->
IsSupportedDevice(device->vendor_id, device->product_id, device->version, device->interface_number)) {
607 static SDL_HIDAPI_Device *
608 HIDAPI_GetJoystickByIndex(
int device_index)
610 SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
612 if (device->driver) {
613 if (device_index == 0) {
618 device = device->next;
623 static SDL_HIDAPI_Device *
624 HIDAPI_GetJoystickByInfo(
const char *
path,
Uint16 vendor_id,
Uint16 product_id)
626 SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
628 if (device->vendor_id == vendor_id && device->product_id == product_id &&
632 device = device->next;
638 SDL_HIDAPIDriverHintChanged(
void *userdata,
const char *
name,
const char *oldValue,
const char *hint)
641 SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
661 if (device->driver) {
662 if (!device->driver->enabled) {
663 device->driver =
NULL;
665 --SDL_HIDAPI_numjoysticks;
670 device->driver = HIDAPI_GetDeviceDriver(device);
671 if (device->driver) {
674 ++SDL_HIDAPI_numjoysticks;
679 device = device->next;
683 static void HIDAPI_JoystickDetect(
void);
686 HIDAPI_JoystickInit(
void)
700 SDL_HIDAPIDriverHintChanged,
NULL);
701 HIDAPI_InitializeDiscovery();
702 HIDAPI_JoystickDetect();
707 HIDAPI_JoystickGetCount(
void)
709 return SDL_HIDAPI_numjoysticks;
715 SDL_HIDAPI_Device *
device;
716 SDL_HIDAPI_Device *curr, *last =
NULL;
718 for (curr = SDL_HIDAPI_devices, last =
NULL; curr; last = curr, curr = curr->next) {
722 device = (SDL_HIDAPI_Device *)
SDL_calloc(1,
sizeof(*device));
726 device->instance_id = -1;
733 device->usage = info->
usage;
736 const Uint16 vendor = device->vendor_id;
738 const Uint16 version = device->version;
751 device->guid.data[14] =
'h';
752 device->guid.data[15] = 0;
759 if (!manufacturer_string && !product_string) {
760 if (
sizeof(
wchar_t) ==
sizeof(
Uint16)) {
763 }
else if (
sizeof(
wchar_t) ==
sizeof(
Uint32)) {
768 if (manufacturer_string && product_string) {
772 SDL_snprintf(device->name, name_size,
"%s %s", manufacturer_string, product_string);
775 if (manufacturer_string) {
778 if (product_string) {
783 size_t name_size = (6 + 1 + 6 + 1);
792 device->driver = HIDAPI_GetDeviceDriver(device);
794 if (device->driver) {
795 const char *name = device->driver->GetDeviceName(device->vendor_id, device->product_id);
810 SDL_Log(
"Adding HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, interface %d, usage page 0x%.4x, usage 0x%.4x, driver = %s\n", device->name, device->vendor_id, device->product_id, device->version, device->interface_number, device->usage_page, device->usage, device->driver ? device->driver->hint :
"NONE");
817 SDL_HIDAPI_devices =
device;
820 if (device->driver) {
824 ++SDL_HIDAPI_numjoysticks;
832 HIDAPI_DelDevice(SDL_HIDAPI_Device *device,
SDL_bool send_event)
834 SDL_HIDAPI_Device *curr, *last;
835 for (curr = SDL_HIDAPI_devices, last =
NULL; curr; last = curr, curr = curr->next) {
836 if (curr == device) {
838 last->next = curr->next;
840 SDL_HIDAPI_devices = curr->next;
843 if (device->driver && send_event) {
845 --SDL_HIDAPI_numjoysticks;
859 HIDAPI_UpdateDeviceList(
void)
861 SDL_HIDAPI_Device *
device;
865 device = SDL_HIDAPI_devices;
868 device = device->next;
874 for (info = devs; info; info = info->
next) {
879 HIDAPI_AddDevice(info);
886 device = SDL_HIDAPI_devices;
888 SDL_HIDAPI_Device *
next = device->
next;
900 SDL_HIDAPI_Device *
device;
903 if (!HIDAPI_IsDeviceSupported(vendor_id, product_id, version)) {
908 HIDAPI_UpdateDeviceList();
910 device = SDL_HIDAPI_devices;
912 if (device->vendor_id == vendor_id && device->product_id == product_id && device->driver) {
915 device = device->next;
921 HIDAPI_JoystickDetect(
void)
923 HIDAPI_UpdateDiscovery();
924 if (SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
926 HIDAPI_UpdateDeviceList();
927 SDL_HIDAPI_discovery.m_bHaveDevicesChanged =
SDL_FALSE;
932 HIDAPI_JoystickGetDeviceName(
int device_index)
934 return HIDAPI_GetJoystickByIndex(device_index)->name;
938 HIDAPI_JoystickGetDevicePlayerIndex(
int device_index)
944 HIDAPI_JoystickGetDeviceGUID(
int device_index)
946 return HIDAPI_GetJoystickByIndex(device_index)->guid;
950 HIDAPI_JoystickGetDeviceInstanceID(
int device_index)
952 return HIDAPI_GetJoystickByIndex(device_index)->instance_id;
956 HIDAPI_JoystickOpen(SDL_Joystick *
joystick,
int device_index)
958 SDL_HIDAPI_Device *device = HIDAPI_GetJoystickByIndex(device_index);
966 hwdata->driver = device->driver;
970 return SDL_SetError(
"Couldn't open HID device %s", device->path);
974 if (!device->driver->Init(joystick, hwdata->dev, device->vendor_id, device->product_id, &hwdata->context)) {
980 joystick->hwdata = hwdata;
985 HIDAPI_JoystickRumble(SDL_Joystick * joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble,
Uint32 duration_ms)
992 result = driver->
Rumble(joystick, hwdata->dev, hwdata->context, low_frequency_rumble, high_frequency_rumble, duration_ms);
998 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
1005 succeeded = driver->
Update(joystick, hwdata->dev, hwdata->context);
1009 SDL_HIDAPI_Device *
device;
1010 for (device = SDL_HIDAPI_devices;
device; device = device->next) {
1011 if (device->instance_id == joystick->instance_id) {
1012 HIDAPI_DelDevice(device,
SDL_TRUE);
1020 HIDAPI_JoystickClose(SDL_Joystick * joystick)
1024 driver->
Quit(joystick, hwdata->dev, hwdata->context);
1029 joystick->hwdata =
NULL;
1033 HIDAPI_JoystickQuit(
void)
1037 HIDAPI_ShutdownDiscovery();
1039 while (SDL_HIDAPI_devices) {
1040 HIDAPI_DelDevice(SDL_HIDAPI_devices,
SDL_FALSE);
1047 SDL_HIDAPIDriverHintChanged,
NULL);
1048 SDL_HIDAPI_numjoysticks = 0;
1055 HIDAPI_JoystickInit,
1056 HIDAPI_JoystickGetCount,
1057 HIDAPI_JoystickDetect,
1058 HIDAPI_JoystickGetDeviceName,
1059 HIDAPI_JoystickGetDevicePlayerIndex,
1060 HIDAPI_JoystickGetDeviceGUID,
1061 HIDAPI_JoystickGetDeviceInstanceID,
1062 HIDAPI_JoystickOpen,
1063 HIDAPI_JoystickRumble,
1064 HIDAPI_JoystickUpdate,
1065 HIDAPI_JoystickClose,
1066 HIDAPI_JoystickQuit,
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4
#define MAKE_VIDPID(VID, PID)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
GLuint GLsizei const GLchar * message
#define SDL_HARDWARE_BUS_USB
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
static screen_context_t context
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
struct joystick_hwdata * next
SDL_bool(* Update)(SDL_Joystick *joystick, hid_device *dev, void *context)
wchar_t * manufacturer_string
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch
GLuint const GLchar * name
#define SDL_GetHintBoolean
static SDL_AudioDeviceID device
int(* Rumble)(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
struct hid_device_info * next
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
unsigned short product_id
const char * HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_HINT_JOYSTICK_HIDAPI
A variable controlling whether the HIDAPI joystick drivers should be used.
int HID_API_EXPORT HID_API_CALL hid_exit(void)
Finalize the HIDAPI library.
void(* Quit)(SDL_Joystick *joystick, hid_device *dev, void *context)
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne
SDL_JoystickDriver SDL_HIDAPI_JoystickDriver
struct hid_device_ hid_device
GLenum GLenum GLsizei const GLuint GLboolean enabled
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)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
#define SDL_OutOfMemory()
SDL_bool(* IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
unsigned short usage_page
SDL_JoystickID SDL_GetNextJoystickInstanceID()
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam
#define SDL_AddHintCallback
#define SDL_DelHintCallback
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
#define SDL_arraysize(array)
GLsizei const GLchar *const * path
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version)
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
unsigned short release_number
unsigned long SDL_threadID