SDL_hidapijoystick.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2021 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #ifdef SDL_JOYSTICK_HIDAPI
  20. #include "SDL_atomic.h"
  21. #include "SDL_endian.h"
  22. #include "SDL_hints.h"
  23. #include "SDL_timer.h"
  24. #include "SDL_joystick.h"
  25. #include "../SDL_sysjoystick.h"
  26. #include "SDL_hidapijoystick_c.h"
  27. #include "SDL_hidapi_rumble.h"
  28. #include "../../SDL_hints_c.h"
  29. #if defined(__WIN32__)
  30. #include "../windows/SDL_rawinputjoystick_c.h"
  31. #endif
  32. struct joystick_hwdata
  33. {
  34. SDL_HIDAPI_Device *device;
  35. };
  36. static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
  37. #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
  38. &SDL_HIDAPI_DriverGameCube,
  39. #endif
  40. #ifdef SDL_JOYSTICK_HIDAPI_LUNA
  41. &SDL_HIDAPI_DriverLuna,
  42. #endif
  43. #ifdef SDL_JOYSTICK_HIDAPI_PS4
  44. &SDL_HIDAPI_DriverPS4,
  45. #endif
  46. #ifdef SDL_JOYSTICK_HIDAPI_PS5
  47. &SDL_HIDAPI_DriverPS5,
  48. #endif
  49. #ifdef SDL_JOYSTICK_HIDAPI_STADIA
  50. &SDL_HIDAPI_DriverStadia,
  51. #endif
  52. #ifdef SDL_JOYSTICK_HIDAPI_STEAM
  53. &SDL_HIDAPI_DriverSteam,
  54. #endif
  55. #ifdef SDL_JOYSTICK_HIDAPI_SWITCH
  56. &SDL_HIDAPI_DriverSwitch,
  57. #endif
  58. #ifdef SDL_JOYSTICK_HIDAPI_XBOX360
  59. &SDL_HIDAPI_DriverXbox360,
  60. &SDL_HIDAPI_DriverXbox360W,
  61. #endif
  62. #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
  63. &SDL_HIDAPI_DriverXboxOne,
  64. #endif
  65. };
  66. static int SDL_HIDAPI_numdrivers = 0;
  67. static SDL_SpinLock SDL_HIDAPI_spinlock;
  68. static Uint32 SDL_HIDAPI_change_count = 0;
  69. static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
  70. static int SDL_HIDAPI_numjoysticks = 0;
  71. static SDL_bool initialized = SDL_FALSE;
  72. static SDL_bool shutting_down = SDL_FALSE;
  73. void
  74. HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
  75. {
  76. int i;
  77. char *buffer;
  78. size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH*2) + 1 + 1;
  79. int start = 0, amount = size;
  80. buffer = (char *)SDL_malloc(length);
  81. SDL_snprintf(buffer, length, prefix, size);
  82. for (i = start; i < start+amount; ++i) {
  83. if ((i % 8) == 0) {
  84. SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
  85. }
  86. SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
  87. }
  88. SDL_strlcat(buffer, "\n", length);
  89. SDL_Log("%s", buffer);
  90. SDL_free(buffer);
  91. }
  92. float
  93. HIDAPI_RemapVal(float val, float val_min, float val_max, float output_min, float output_max)
  94. {
  95. return output_min + (output_max - output_min) * (val - val_min) / (val_max - val_min);
  96. }
  97. static void HIDAPI_JoystickDetect(void);
  98. static void HIDAPI_JoystickClose(SDL_Joystick *joystick);
  99. static SDL_bool
  100. HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
  101. {
  102. int i;
  103. SDL_GameControllerType type = SDL_GetJoystickGameControllerType(name, vendor_id, product_id, -1, 0, 0, 0);
  104. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  105. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  106. if (driver->enabled && driver->IsSupportedDevice(name, type, vendor_id, product_id, version, -1, 0, 0, 0)) {
  107. return SDL_TRUE;
  108. }
  109. }
  110. return SDL_FALSE;
  111. }
  112. static SDL_HIDAPI_DeviceDriver *
  113. HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
  114. {
  115. const Uint16 USAGE_PAGE_GENERIC_DESKTOP = 0x0001;
  116. const Uint16 USAGE_JOYSTICK = 0x0004;
  117. const Uint16 USAGE_GAMEPAD = 0x0005;
  118. const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
  119. int i;
  120. SDL_GameControllerType type;
  121. SDL_JoystickGUID check_guid;
  122. /* Make sure we have a generic GUID here, otherwise if we pass a HIDAPI
  123. guid, this call will create a game controller mapping for the device.
  124. */
  125. check_guid = device->guid;
  126. check_guid.data[14] = 0;
  127. if (SDL_ShouldIgnoreJoystick(device->name, check_guid)) {
  128. return NULL;
  129. }
  130. if (device->vendor_id != USB_VENDOR_VALVE) {
  131. if (device->usage_page && device->usage_page != USAGE_PAGE_GENERIC_DESKTOP) {
  132. return NULL;
  133. }
  134. if (device->usage && device->usage != USAGE_JOYSTICK && device->usage != USAGE_GAMEPAD && device->usage != USAGE_MULTIAXISCONTROLLER) {
  135. return NULL;
  136. }
  137. }
  138. type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
  139. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  140. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  141. 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)) {
  142. return driver;
  143. }
  144. }
  145. return NULL;
  146. }
  147. static SDL_HIDAPI_Device *
  148. HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
  149. {
  150. SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
  151. while (device) {
  152. if (device->driver) {
  153. if (device_index < device->num_joysticks) {
  154. if (pJoystickID) {
  155. *pJoystickID = device->joysticks[device_index];
  156. }
  157. return device;
  158. }
  159. device_index -= device->num_joysticks;
  160. }
  161. device = device->next;
  162. }
  163. return NULL;
  164. }
  165. static SDL_HIDAPI_Device *
  166. HIDAPI_GetJoystickByInfo(const char *path, Uint16 vendor_id, Uint16 product_id)
  167. {
  168. SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
  169. while (device) {
  170. if (device->vendor_id == vendor_id && device->product_id == product_id &&
  171. SDL_strcmp(device->path, path) == 0) {
  172. break;
  173. }
  174. device = device->next;
  175. }
  176. return device;
  177. }
  178. static void
  179. HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
  180. {
  181. if (device->driver) {
  182. /* Already setup */
  183. return;
  184. }
  185. device->driver = HIDAPI_GetDeviceDriver(device);
  186. if (device->driver) {
  187. const char *name = device->driver->GetDeviceName(device->vendor_id, device->product_id);
  188. if (name) {
  189. SDL_free(device->name);
  190. device->name = SDL_strdup(name);
  191. }
  192. }
  193. /* Initialize the device, which may cause a connected event */
  194. if (device->driver && !device->driver->InitDevice(device)) {
  195. device->driver = NULL;
  196. }
  197. }
  198. static void
  199. HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
  200. {
  201. if (!device->driver) {
  202. /* Already cleaned up */
  203. return;
  204. }
  205. /* Disconnect any joysticks */
  206. while (device->num_joysticks) {
  207. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  208. }
  209. device->driver->FreeDevice(device);
  210. device->driver = NULL;
  211. }
  212. static void SDLCALL
  213. SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  214. {
  215. int i;
  216. SDL_HIDAPI_Device *device;
  217. SDL_bool enabled = SDL_GetStringBoolean(hint, SDL_TRUE);
  218. if (SDL_strcmp(name, SDL_HINT_JOYSTICK_HIDAPI) == 0) {
  219. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  220. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  221. driver->enabled = SDL_GetHintBoolean(driver->hint, enabled);
  222. }
  223. } else {
  224. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  225. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  226. if (SDL_strcmp(name, driver->hint) == 0) {
  227. driver->enabled = enabled;
  228. }
  229. }
  230. }
  231. SDL_HIDAPI_numdrivers = 0;
  232. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  233. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  234. if (driver->enabled) {
  235. ++SDL_HIDAPI_numdrivers;
  236. }
  237. }
  238. /* Update device list if driver availability changes */
  239. SDL_LockJoysticks();
  240. for (device = SDL_HIDAPI_devices; device; device = device->next) {
  241. if (device->driver && !device->driver->enabled) {
  242. HIDAPI_CleanupDeviceDriver(device);
  243. }
  244. HIDAPI_SetupDeviceDriver(device);
  245. }
  246. SDL_UnlockJoysticks();
  247. }
  248. static int
  249. HIDAPI_JoystickInit(void)
  250. {
  251. int i;
  252. if (initialized) {
  253. return 0;
  254. }
  255. #if defined(SDL_USE_LIBUDEV)
  256. if (linux_enumeration_method == ENUMERATION_UNSET) {
  257. if (SDL_getenv("SDL_HIDAPI_JOYSTICK_DISABLE_UDEV") != NULL) {
  258. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
  259. "udev disabled by SDL_HIDAPI_JOYSTICK_DISABLE_UDEV");
  260. linux_enumeration_method = ENUMERATION_FALLBACK;
  261. } else if (access("/.flatpak-info", F_OK) == 0
  262. || access("/run/host/container-manager", F_OK) == 0) {
  263. /* Explicitly check `/.flatpak-info` because, for old versions of
  264. * Flatpak, this was the only available way to tell if we were in
  265. * a Flatpak container. */
  266. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
  267. "Container detected, disabling HIDAPI udev integration");
  268. linux_enumeration_method = ENUMERATION_FALLBACK;
  269. } else {
  270. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
  271. "Using udev for HIDAPI joystick device discovery");
  272. linux_enumeration_method = ENUMERATION_LIBUDEV;
  273. }
  274. }
  275. #endif
  276. if (SDL_hid_init() < 0) {
  277. SDL_SetError("Couldn't initialize hidapi");
  278. return -1;
  279. }
  280. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  281. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  282. SDL_AddHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
  283. }
  284. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
  285. SDL_HIDAPIDriverHintChanged, NULL);
  286. HIDAPI_JoystickDetect();
  287. HIDAPI_UpdateDevices();
  288. initialized = SDL_TRUE;
  289. return 0;
  290. }
  291. SDL_bool
  292. HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
  293. {
  294. SDL_JoystickID joystickID;
  295. SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
  296. if (!joysticks) {
  297. return SDL_FALSE;
  298. }
  299. joystickID = SDL_GetNextJoystickInstanceID();
  300. device->joysticks = joysticks;
  301. device->joysticks[device->num_joysticks++] = joystickID;
  302. ++SDL_HIDAPI_numjoysticks;
  303. SDL_PrivateJoystickAdded(joystickID);
  304. if (pJoystickID) {
  305. *pJoystickID = joystickID;
  306. }
  307. return SDL_TRUE;
  308. }
  309. void
  310. HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
  311. {
  312. int i, size;
  313. for (i = 0; i < device->num_joysticks; ++i) {
  314. if (device->joysticks[i] == joystickID) {
  315. SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
  316. if (joystick) {
  317. HIDAPI_JoystickClose(joystick);
  318. }
  319. size = (device->num_joysticks - i - 1) * sizeof(SDL_JoystickID);
  320. SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], size);
  321. --device->num_joysticks;
  322. --SDL_HIDAPI_numjoysticks;
  323. if (device->num_joysticks == 0) {
  324. SDL_free(device->joysticks);
  325. device->joysticks = NULL;
  326. }
  327. if (!shutting_down) {
  328. SDL_PrivateJoystickRemoved(joystickID);
  329. }
  330. return;
  331. }
  332. }
  333. }
  334. static int
  335. HIDAPI_JoystickGetCount(void)
  336. {
  337. return SDL_HIDAPI_numjoysticks;
  338. }
  339. static char *
  340. HIDAPI_ConvertString(const wchar_t *wide_string)
  341. {
  342. char *string = NULL;
  343. if (wide_string) {
  344. string = SDL_iconv_string("UTF-8", "WCHAR_T", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
  345. if (!string) {
  346. if (sizeof(wchar_t) == sizeof(Uint16)) {
  347. string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
  348. } else if (sizeof(wchar_t) == sizeof(Uint32)) {
  349. string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
  350. }
  351. }
  352. }
  353. return string;
  354. }
  355. static void
  356. HIDAPI_AddDevice(struct SDL_hid_device_info *info)
  357. {
  358. SDL_HIDAPI_Device *device;
  359. SDL_HIDAPI_Device *curr, *last = NULL;
  360. for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
  361. continue;
  362. }
  363. device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
  364. if (!device) {
  365. return;
  366. }
  367. device->path = SDL_strdup(info->path);
  368. if (!device->path) {
  369. SDL_free(device);
  370. return;
  371. }
  372. device->seen = SDL_TRUE;
  373. device->vendor_id = info->vendor_id;
  374. device->product_id = info->product_id;
  375. device->version = info->release_number;
  376. device->interface_number = info->interface_number;
  377. device->interface_class = info->interface_class;
  378. device->interface_subclass = info->interface_subclass;
  379. device->interface_protocol = info->interface_protocol;
  380. device->usage_page = info->usage_page;
  381. device->usage = info->usage;
  382. {
  383. /* FIXME: Is there any way to tell whether this is a Bluetooth device? */
  384. const Uint16 vendor = device->vendor_id;
  385. const Uint16 product = device->product_id;
  386. const Uint16 version = device->version;
  387. Uint16 *guid16 = (Uint16 *)device->guid.data;
  388. *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
  389. *guid16++ = 0;
  390. *guid16++ = SDL_SwapLE16(vendor);
  391. *guid16++ = 0;
  392. *guid16++ = SDL_SwapLE16(product);
  393. *guid16++ = 0;
  394. *guid16++ = SDL_SwapLE16(version);
  395. *guid16++ = 0;
  396. /* Note that this is a HIDAPI device for special handling elsewhere */
  397. device->guid.data[14] = 'h';
  398. device->guid.data[15] = 0;
  399. }
  400. device->dev_lock = SDL_CreateMutex();
  401. /* Need the device name before getting the driver to know whether to ignore this device */
  402. {
  403. char *manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string);
  404. char *product_string = HIDAPI_ConvertString(info->product_string);
  405. char *serial_number = HIDAPI_ConvertString(info->serial_number);
  406. device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
  407. if (SDL_strncmp(device->name, "0x", 2) == 0) {
  408. /* Couldn't find a controller name, try to give it one based on device type */
  409. const char *name = NULL;
  410. switch (SDL_GetJoystickGameControllerType(NULL, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
  411. case SDL_CONTROLLER_TYPE_XBOX360:
  412. name = "Xbox 360 Controller";
  413. break;
  414. case SDL_CONTROLLER_TYPE_XBOXONE:
  415. name = "Xbox One Controller";
  416. break;
  417. case SDL_CONTROLLER_TYPE_PS3:
  418. name = "PS3 Controller";
  419. break;
  420. case SDL_CONTROLLER_TYPE_PS4:
  421. name = "PS4 Controller";
  422. break;
  423. case SDL_CONTROLLER_TYPE_PS5:
  424. name = "PS5 Controller";
  425. break;
  426. case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
  427. name = "Nintendo Switch Pro Controller";
  428. break;
  429. default:
  430. break;
  431. }
  432. if (name) {
  433. SDL_free(device->name);
  434. device->name = SDL_strdup(name);
  435. }
  436. }
  437. if (manufacturer_string) {
  438. SDL_free(manufacturer_string);
  439. }
  440. if (product_string) {
  441. SDL_free(product_string);
  442. }
  443. if (serial_number && *serial_number) {
  444. device->serial = serial_number;
  445. } else {
  446. SDL_free(serial_number);
  447. }
  448. if (!device->name) {
  449. SDL_free(device->serial);
  450. SDL_free(device->path);
  451. SDL_free(device);
  452. return;
  453. }
  454. }
  455. /* Add it to the list */
  456. if (last) {
  457. last->next = device;
  458. } else {
  459. SDL_HIDAPI_devices = device;
  460. }
  461. HIDAPI_SetupDeviceDriver(device);
  462. #ifdef DEBUG_HIDAPI
  463. SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, 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->serial ? device->serial : "NONE", 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");
  464. #endif
  465. }
  466. static void
  467. HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
  468. {
  469. SDL_HIDAPI_Device *curr, *last;
  470. #ifdef DEBUG_HIDAPI
  471. SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, 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->serial ? device->serial : "NONE", 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");
  472. #endif
  473. for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
  474. if (curr == device) {
  475. if (last) {
  476. last->next = curr->next;
  477. } else {
  478. SDL_HIDAPI_devices = curr->next;
  479. }
  480. HIDAPI_CleanupDeviceDriver(device);
  481. /* Make sure the rumble thread is done with this device */
  482. while (SDL_AtomicGet(&device->rumble_pending) > 0) {
  483. SDL_Delay(10);
  484. }
  485. SDL_DestroyMutex(device->dev_lock);
  486. SDL_free(device->serial);
  487. SDL_free(device->name);
  488. SDL_free(device->path);
  489. SDL_free(device);
  490. return;
  491. }
  492. }
  493. }
  494. static void
  495. HIDAPI_UpdateDeviceList(void)
  496. {
  497. SDL_HIDAPI_Device *device;
  498. struct SDL_hid_device_info *devs, *info;
  499. SDL_LockJoysticks();
  500. /* Prepare the existing device list */
  501. device = SDL_HIDAPI_devices;
  502. while (device) {
  503. device->seen = SDL_FALSE;
  504. device = device->next;
  505. }
  506. /* Enumerate the devices */
  507. if (SDL_HIDAPI_numdrivers > 0) {
  508. devs = SDL_hid_enumerate(0, 0);
  509. if (devs) {
  510. for (info = devs; info; info = info->next) {
  511. device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
  512. if (device) {
  513. device->seen = SDL_TRUE;
  514. } else {
  515. HIDAPI_AddDevice(info);
  516. }
  517. }
  518. SDL_hid_free_enumeration(devs);
  519. }
  520. }
  521. /* Remove any devices that weren't seen or have been disconnected due to read errors */
  522. device = SDL_HIDAPI_devices;
  523. while (device) {
  524. SDL_HIDAPI_Device *next = device->next;
  525. if (!device->seen ||
  526. (device->driver && device->num_joysticks == 0 && !device->dev)) {
  527. HIDAPI_DelDevice(device);
  528. }
  529. device = next;
  530. }
  531. SDL_UnlockJoysticks();
  532. }
  533. static SDL_bool
  534. HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Device *device)
  535. {
  536. if (vendor_id == device->vendor_id && product_id == device->product_id) {
  537. return SDL_TRUE;
  538. }
  539. if (vendor_id == USB_VENDOR_MICROSOFT) {
  540. /* If we're looking for the wireless XBox 360 controller, also look for the dongle */
  541. if (product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER && device->product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER) {
  542. return SDL_TRUE;
  543. }
  544. /* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
  545. if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER &&
  546. SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
  547. return SDL_TRUE;
  548. }
  549. /* If we're looking for an XInput controller, match it against any other Xbox controller */
  550. if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
  551. SDL_GameControllerType type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
  552. if (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) {
  553. return SDL_TRUE;
  554. }
  555. }
  556. }
  557. return SDL_FALSE;
  558. }
  559. SDL_bool
  560. HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
  561. {
  562. SDL_HIDAPI_Device *device;
  563. SDL_bool result = SDL_FALSE;
  564. /* Make sure we're initialized, as this could be called from other drivers during startup */
  565. if (HIDAPI_JoystickInit() < 0) {
  566. return SDL_FALSE;
  567. }
  568. if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
  569. HIDAPI_UpdateDeviceList();
  570. SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
  571. }
  572. SDL_LockJoysticks();
  573. device = SDL_HIDAPI_devices;
  574. while (device) {
  575. if (device->driver &&
  576. SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
  577. result = SDL_TRUE;
  578. break;
  579. }
  580. device = device->next;
  581. }
  582. SDL_UnlockJoysticks();
  583. #ifdef DEBUG_HIDAPI
  584. SDL_Log("HIDAPI_IsDeviceTypePresent() returning %s for %d\n", result ? "true" : "false", type);
  585. #endif
  586. return result;
  587. }
  588. SDL_bool
  589. HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
  590. {
  591. SDL_HIDAPI_Device *device;
  592. SDL_bool supported = SDL_FALSE;
  593. SDL_bool result = SDL_FALSE;
  594. /* Make sure we're initialized, as this could be called from other drivers during startup */
  595. if (HIDAPI_JoystickInit() < 0) {
  596. return SDL_FALSE;
  597. }
  598. /* Only update the device list for devices we know might be supported.
  599. If we did this for every device, it would hit the USB driver too hard and potentially
  600. lock up the system. This won't catch devices that we support but can only detect using
  601. USB interface details, like Xbox controllers, but hopefully the device list update is
  602. responsive enough to catch those.
  603. */
  604. supported = HIDAPI_IsDeviceSupported(vendor_id, product_id, version, name);
  605. #if defined(SDL_JOYSTICK_HIDAPI_XBOX360) || defined(SDL_JOYSTICK_HIDAPI_XBOXONE)
  606. if (!supported &&
  607. (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX"))) {
  608. supported = SDL_TRUE;
  609. }
  610. #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 || SDL_JOYSTICK_HIDAPI_XBOXONE */
  611. if (supported) {
  612. if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
  613. HIDAPI_UpdateDeviceList();
  614. SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
  615. }
  616. }
  617. /* Note that this isn't a perfect check - there may be multiple devices with 0 VID/PID,
  618. or a different name than we have it listed here, etc, but if we support the device
  619. and we have something similar in our device list, mark it as present.
  620. */
  621. SDL_LockJoysticks();
  622. device = SDL_HIDAPI_devices;
  623. while (device) {
  624. if (device->driver &&
  625. HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) {
  626. result = SDL_TRUE;
  627. break;
  628. }
  629. device = device->next;
  630. }
  631. SDL_UnlockJoysticks();
  632. #ifdef DEBUG_HIDAPI
  633. SDL_Log("HIDAPI_IsDevicePresent() returning %s for 0x%.4x / 0x%.4x\n", result ? "true" : "false", vendor_id, product_id);
  634. #endif
  635. return result;
  636. }
  637. static void
  638. HIDAPI_JoystickDetect(void)
  639. {
  640. if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
  641. Uint32 count = SDL_hid_device_change_count();
  642. if (SDL_HIDAPI_change_count != count) {
  643. HIDAPI_UpdateDeviceList();
  644. SDL_HIDAPI_change_count = count;
  645. }
  646. SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
  647. }
  648. }
  649. void
  650. HIDAPI_UpdateDevices(void)
  651. {
  652. SDL_HIDAPI_Device *device;
  653. /* Update the devices, which may change connected joysticks and send events */
  654. /* Prepare the existing device list */
  655. if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
  656. device = SDL_HIDAPI_devices;
  657. while (device) {
  658. if (device->driver) {
  659. if (SDL_TryLockMutex(device->dev_lock) == 0) {
  660. device->updating = SDL_TRUE;
  661. device->driver->UpdateDevice(device);
  662. device->updating = SDL_FALSE;
  663. SDL_UnlockMutex(device->dev_lock);
  664. }
  665. }
  666. device = device->next;
  667. }
  668. SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
  669. }
  670. }
  671. static const char *
  672. HIDAPI_JoystickGetDeviceName(int device_index)
  673. {
  674. SDL_HIDAPI_Device *device;
  675. const char *name = NULL;
  676. device = HIDAPI_GetDeviceByIndex(device_index, NULL);
  677. if (device) {
  678. /* FIXME: The device could be freed after this name is returned... */
  679. name = device->name;
  680. }
  681. return name;
  682. }
  683. static int
  684. HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
  685. {
  686. SDL_HIDAPI_Device *device;
  687. SDL_JoystickID instance_id;
  688. int player_index = -1;
  689. device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
  690. if (device) {
  691. player_index = device->driver->GetDevicePlayerIndex(device, instance_id);
  692. }
  693. return player_index;
  694. }
  695. static void
  696. HIDAPI_JoystickSetDevicePlayerIndex(int device_index, int player_index)
  697. {
  698. SDL_HIDAPI_Device *device;
  699. SDL_JoystickID instance_id;
  700. device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
  701. if (device) {
  702. device->driver->SetDevicePlayerIndex(device, instance_id, player_index);
  703. }
  704. }
  705. static SDL_JoystickGUID
  706. HIDAPI_JoystickGetDeviceGUID(int device_index)
  707. {
  708. SDL_HIDAPI_Device *device;
  709. SDL_JoystickGUID guid;
  710. device = HIDAPI_GetDeviceByIndex(device_index, NULL);
  711. if (device) {
  712. SDL_memcpy(&guid, &device->guid, sizeof(guid));
  713. } else {
  714. SDL_zero(guid);
  715. }
  716. return guid;
  717. }
  718. static SDL_JoystickID
  719. HIDAPI_JoystickGetDeviceInstanceID(int device_index)
  720. {
  721. SDL_JoystickID joystickID = -1;
  722. HIDAPI_GetDeviceByIndex(device_index, &joystickID);
  723. return joystickID;
  724. }
  725. static int
  726. HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
  727. {
  728. SDL_JoystickID joystickID;
  729. SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index, &joystickID);
  730. struct joystick_hwdata *hwdata;
  731. hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
  732. if (!hwdata) {
  733. return SDL_OutOfMemory();
  734. }
  735. hwdata->device = device;
  736. if (!device->driver->OpenJoystick(device, joystick)) {
  737. SDL_free(hwdata);
  738. return -1;
  739. }
  740. if (!joystick->serial && device->serial) {
  741. joystick->serial = SDL_strdup(device->serial);
  742. }
  743. joystick->hwdata = hwdata;
  744. return 0;
  745. }
  746. static int
  747. HIDAPI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  748. {
  749. int result;
  750. if (joystick->hwdata) {
  751. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  752. result = device->driver->RumbleJoystick(device, joystick, low_frequency_rumble, high_frequency_rumble);
  753. } else {
  754. SDL_SetError("Rumble failed, device disconnected");
  755. result = -1;
  756. }
  757. return result;
  758. }
  759. static int
  760. HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  761. {
  762. int result;
  763. if (joystick->hwdata) {
  764. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  765. result = device->driver->RumbleJoystickTriggers(device, joystick, left_rumble, right_rumble);
  766. } else {
  767. SDL_SetError("Rumble failed, device disconnected");
  768. result = -1;
  769. }
  770. return result;
  771. }
  772. static Uint32
  773. HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick)
  774. {
  775. Uint32 result = 0;
  776. if (joystick->hwdata) {
  777. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  778. result = device->driver->GetJoystickCapabilities(device, joystick);
  779. }
  780. return result;
  781. }
  782. static int
  783. HIDAPI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  784. {
  785. int result;
  786. if (joystick->hwdata) {
  787. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  788. result = device->driver->SetJoystickLED(device, joystick, red, green, blue);
  789. } else {
  790. SDL_SetError("SetLED failed, device disconnected");
  791. result = -1;
  792. }
  793. return result;
  794. }
  795. static int
  796. HIDAPI_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
  797. {
  798. int result;
  799. if (joystick->hwdata) {
  800. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  801. result = device->driver->SendJoystickEffect(device, joystick, data, size);
  802. } else {
  803. SDL_SetError("SendEffect failed, device disconnected");
  804. result = -1;
  805. }
  806. return result;
  807. }
  808. static int
  809. HIDAPI_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
  810. {
  811. int result;
  812. if (joystick->hwdata) {
  813. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  814. result = device->driver->SetJoystickSensorsEnabled(device, joystick, enabled);
  815. } else {
  816. SDL_SetError("SetSensorsEnabled failed, device disconnected");
  817. result = -1;
  818. }
  819. return result;
  820. }
  821. static void
  822. HIDAPI_JoystickUpdate(SDL_Joystick *joystick)
  823. {
  824. /* This is handled in SDL_HIDAPI_UpdateDevices() */
  825. }
  826. static void
  827. HIDAPI_JoystickClose(SDL_Joystick *joystick)
  828. {
  829. if (joystick->hwdata) {
  830. SDL_HIDAPI_Device *device = joystick->hwdata->device;
  831. int i;
  832. /* Wait up to 30 ms for pending rumble to complete */
  833. if (device->updating) {
  834. /* Unlock the device so rumble can complete */
  835. SDL_UnlockMutex(device->dev_lock);
  836. }
  837. for (i = 0; i < 3; ++i) {
  838. if (SDL_AtomicGet(&device->rumble_pending) > 0) {
  839. SDL_Delay(10);
  840. }
  841. }
  842. if (device->updating) {
  843. /* Relock the device */
  844. SDL_LockMutex(device->dev_lock);
  845. }
  846. device->driver->CloseJoystick(device, joystick);
  847. SDL_free(joystick->hwdata);
  848. joystick->hwdata = NULL;
  849. }
  850. }
  851. static void
  852. HIDAPI_JoystickQuit(void)
  853. {
  854. int i;
  855. shutting_down = SDL_TRUE;
  856. SDL_HIDAPI_QuitRumble();
  857. while (SDL_HIDAPI_devices) {
  858. HIDAPI_DelDevice(SDL_HIDAPI_devices);
  859. }
  860. /* Make sure the drivers cleaned up properly */
  861. SDL_assert(SDL_HIDAPI_numjoysticks == 0);
  862. for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
  863. SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
  864. SDL_DelHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
  865. }
  866. SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
  867. SDL_HIDAPIDriverHintChanged, NULL);
  868. SDL_hid_exit();
  869. shutting_down = SDL_FALSE;
  870. initialized = SDL_FALSE;
  871. }
  872. static SDL_bool
  873. HIDAPI_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
  874. {
  875. return SDL_FALSE;
  876. }
  877. SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
  878. {
  879. HIDAPI_JoystickInit,
  880. HIDAPI_JoystickGetCount,
  881. HIDAPI_JoystickDetect,
  882. HIDAPI_JoystickGetDeviceName,
  883. HIDAPI_JoystickGetDevicePlayerIndex,
  884. HIDAPI_JoystickSetDevicePlayerIndex,
  885. HIDAPI_JoystickGetDeviceGUID,
  886. HIDAPI_JoystickGetDeviceInstanceID,
  887. HIDAPI_JoystickOpen,
  888. HIDAPI_JoystickRumble,
  889. HIDAPI_JoystickRumbleTriggers,
  890. HIDAPI_JoystickGetCapabilities,
  891. HIDAPI_JoystickSetLED,
  892. HIDAPI_JoystickSendEffect,
  893. HIDAPI_JoystickSetSensorsEnabled,
  894. HIDAPI_JoystickUpdate,
  895. HIDAPI_JoystickClose,
  896. HIDAPI_JoystickQuit,
  897. HIDAPI_JoystickGetGamepadMapping
  898. };
  899. #endif /* SDL_JOYSTICK_HIDAPI */
  900. /* vi: set ts=4 sw=4 expandtab: */