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
22 /* Original hybrid wrapper for Linux by Valve Software. Their original notes:
23 *
24 * The libusb version doesn't support Bluetooth, but not all Linux
25 * distributions allow access to /dev/hidraw*
26 *
27 * This merges the two, at a small performance cost, until distributions
28 * have granted access to /dev/hidraw*
29 */
30
31 #include "../SDL_internal.h"
32 #include "SDL_loadso.h"
33
34 #ifdef SDL_JOYSTICK_HIDAPI
35
36 /* Platform HIDAPI Implementation */
37
38 #define hid_device_ PLATFORM_hid_device_
39 #define hid_device PLATFORM_hid_device
40 #define hid_device_info PLATFORM_hid_device_info
41 #define hid_init PLATFORM_hid_init
42 #define hid_exit PLATFORM_hid_exit
43 #define hid_enumerate PLATFORM_hid_enumerate
44 #define hid_free_enumeration PLATFORM_hid_free_enumeration
45 #define hid_open PLATFORM_hid_open
46 #define hid_open_path PLATFORM_hid_open_path
47 #define hid_write PLATFORM_hid_write
48 #define hid_read_timeout PLATFORM_hid_read_timeout
49 #define hid_read PLATFORM_hid_read
50 #define hid_set_nonblocking PLATFORM_hid_set_nonblocking
51 #define hid_send_feature_report PLATFORM_hid_send_feature_report
52 #define hid_get_feature_report PLATFORM_hid_get_feature_report
53 #define hid_close PLATFORM_hid_close
54 #define hid_get_manufacturer_string PLATFORM_hid_get_manufacturer_string
55 #define hid_get_product_string PLATFORM_hid_get_product_string
56 #define hid_get_serial_number_string PLATFORM_hid_get_serial_number_string
57 #define hid_get_indexed_string PLATFORM_hid_get_indexed_string
58 #define hid_error PLATFORM_hid_error
59 #define new_hid_device PLATFORM_new_hid_device
60 #define free_hid_device PLATFORM_free_hid_device
61 #define input_report PLATFORM_input_report
62 #define return_data PLATFORM_return_data
63 #define make_path PLATFORM_make_path
64 #define read_thread PLATFORM_read_thread
65
66 #if __LINUX__
67
68 #include "../../core/linux/SDL_udev.h"
69 #if SDL_USE_LIBUDEV
70 static const SDL_UDEV_Symbols *udev_ctx = NULL;
71
72 #define udev_device_get_sysattr_value udev_ctx->udev_device_get_sysattr_value
73 #define udev_new udev_ctx->udev_new
74 #define udev_unref udev_ctx->udev_unref
75 #define udev_device_new_from_devnum udev_ctx->udev_device_new_from_devnum
76 #define udev_device_get_parent_with_subsystem_devtype udev_ctx->udev_device_get_parent_with_subsystem_devtype
77 #define udev_device_unref udev_ctx->udev_device_unref
78 #define udev_enumerate_new udev_ctx->udev_enumerate_new
79 #define udev_enumerate_add_match_subsystem udev_ctx->udev_enumerate_add_match_subsystem
80 #define udev_enumerate_scan_devices udev_ctx->udev_enumerate_scan_devices
81 #define udev_enumerate_get_list_entry udev_ctx->udev_enumerate_get_list_entry
82 #define udev_list_entry_get_name udev_ctx->udev_list_entry_get_name
83 #define udev_device_new_from_syspath udev_ctx->udev_device_new_from_syspath
84 #define udev_device_get_devnode udev_ctx->udev_device_get_devnode
85 #define udev_list_entry_get_next udev_ctx->udev_list_entry_get_next
86 #define udev_enumerate_unref udev_ctx->udev_enumerate_unref
87
88 #include "linux/hid.c"
89 #define HAVE_PLATFORM_BACKEND 1
90 #endif /* SDL_USE_LIBUDEV */
91
92 #elif __MACOSX__
93 #include "mac/hid.c"
94 #define HAVE_PLATFORM_BACKEND 1
95 #define udev_ctx 1
96 #elif __WINDOWS__
97 #include "windows/hid.c"
98 #define HAVE_PLATFORM_BACKEND 1
99 #define udev_ctx 1
100 #else
101 #error Need a hid.c for this platform!
102 #endif
103
104 #undef hid_device_
105 #undef hid_device
106 #undef hid_device_info
107 #undef hid_init
108 #undef hid_exit
109 #undef hid_enumerate
110 #undef hid_free_enumeration
111 #undef hid_open
112 #undef hid_open_path
113 #undef hid_write
114 #undef hid_read_timeout
115 #undef hid_read
116 #undef hid_set_nonblocking
117 #undef hid_send_feature_report
118 #undef hid_get_feature_report
119 #undef hid_close
120 #undef hid_get_manufacturer_string
121 #undef hid_get_product_string
122 #undef hid_get_serial_number_string
123 #undef hid_get_indexed_string
124 #undef hid_error
125 #undef new_hid_device
126 #undef free_hid_device
127 #undef input_report
128 #undef return_data
129 #undef make_path
130 #undef read_thread
131
132 #ifdef SDL_LIBUSB_DYNAMIC
133 /* libusb HIDAPI Implementation */
134
135 /* Include this now, for our dynamically-loaded libusb context */
136 #include <libusb.h>
137
138 static struct
139 {
140 void* libhandle;
141
142 int (*init)(libusb_context **ctx);
143 void (*exit)(libusb_context *ctx);
144 ssize_t (*get_device_list)(libusb_context *ctx, libusb_device ***list);
145 void (*free_device_list)(libusb_device **list, int unref_devices);
146 int (*get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc);
147 int (*get_active_config_descriptor)(libusb_device *dev, struct libusb_config_descriptor **config);
148 int (*get_config_descriptor)(
149 libusb_device *dev,
150 uint8_t config_index,
151 struct libusb_config_descriptor **config
152 );
153 void (*free_config_descriptor)(struct libusb_config_descriptor *config);
154 uint8_t (*get_bus_number)(libusb_device *dev);
155 uint8_t (*get_device_address)(libusb_device *dev);
156 int (*open)(libusb_device *dev, libusb_device_handle **dev_handle);
157 void (*close)(libusb_device_handle *dev_handle);
158 int (*claim_interface)(libusb_device_handle *dev_handle, int interface_number);
159 int (*release_interface)(libusb_device_handle *dev_handle, int interface_number);
160 int (*kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number);
161 int (*detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
162 int (*attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
163 int (*set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting);
164 struct libusb_transfer * (*alloc_transfer)(int iso_packets);
165 int (*submit_transfer)(struct libusb_transfer *transfer);
166 int (*cancel_transfer)(struct libusb_transfer *transfer);
167 void (*free_transfer)(struct libusb_transfer *transfer);
168 int (*control_transfer)(
169 libusb_device_handle *dev_handle,
170 uint8_t request_type,
171 uint8_t bRequest,
172 uint16_t wValue,
173 uint16_t wIndex,
174 unsigned char *data,
175 uint16_t wLength,
176 unsigned int timeout
177 );
178 int (*interrupt_transfer)(
179 libusb_device_handle *dev_handle,
180 unsigned char endpoint,
181 unsigned char *data,
182 int length,
183 int *actual_length,
184 unsigned int timeout
185 );
186 int (*handle_events)(libusb_context *ctx);
187 int (*handle_events_completed)(libusb_context *ctx, int *completed);
188 } libusb_ctx;
189
190 #define libusb_init libusb_ctx.init
191 #define libusb_exit libusb_ctx.exit
192 #define libusb_get_device_list libusb_ctx.get_device_list
193 #define libusb_free_device_list libusb_ctx.free_device_list
194 #define libusb_get_device_descriptor libusb_ctx.get_device_descriptor
195 #define libusb_get_active_config_descriptor libusb_ctx.get_active_config_descriptor
196 #define libusb_get_config_descriptor libusb_ctx.get_config_descriptor
197 #define libusb_free_config_descriptor libusb_ctx.free_config_descriptor
198 #define libusb_get_bus_number libusb_ctx.get_bus_number
199 #define libusb_get_device_address libusb_ctx.get_device_address
200 #define libusb_open libusb_ctx.open
201 #define libusb_close libusb_ctx.close
202 #define libusb_claim_interface libusb_ctx.claim_interface
203 #define libusb_release_interface libusb_ctx.release_interface
204 #define libusb_kernel_driver_active libusb_ctx.kernel_driver_active
205 #define libusb_detach_kernel_driver libusb_ctx.detach_kernel_driver
206 #define libusb_attach_kernel_driver libusb_ctx.attach_kernel_driver
207 #define libusb_set_interface_alt_setting libusb_ctx.set_interface_alt_setting
208 #define libusb_alloc_transfer libusb_ctx.alloc_transfer
209 #define libusb_submit_transfer libusb_ctx.submit_transfer
210 #define libusb_cancel_transfer libusb_ctx.cancel_transfer
211 #define libusb_free_transfer libusb_ctx.free_transfer
212 #define libusb_control_transfer libusb_ctx.control_transfer
213 #define libusb_interrupt_transfer libusb_ctx.interrupt_transfer
214 #define libusb_handle_events libusb_ctx.handle_events
215 #define libusb_handle_events_completed libusb_ctx.handle_events_completed
216
217 #define hid_device_ LIBUSB_hid_device_
218 #define hid_device LIBUSB_hid_device
219 #define hid_device_info LIBUSB_hid_device_info
220 #define hid_init LIBUSB_hid_init
221 #define hid_exit LIBUSB_hid_exit
222 #define hid_enumerate LIBUSB_hid_enumerate
223 #define hid_free_enumeration LIBUSB_hid_free_enumeration
224 #define hid_open LIBUSB_hid_open
225 #define hid_open_path LIBUSB_hid_open_path
226 #define hid_write LIBUSB_hid_write
227 #define hid_read_timeout LIBUSB_hid_read_timeout
228 #define hid_read LIBUSB_hid_read
229 #define hid_set_nonblocking LIBUSB_hid_set_nonblocking
230 #define hid_send_feature_report LIBUSB_hid_send_feature_report
231 #define hid_get_feature_report LIBUSB_hid_get_feature_report
232 #define hid_close LIBUSB_hid_close
233 #define hid_get_manufacturer_string LIBUSB_hid_get_manufacturer_string
234 #define hid_get_product_string LIBUSB_hid_get_product_string
235 #define hid_get_serial_number_string LIBUSB_hid_get_serial_number_string
236 #define hid_get_indexed_string LIBUSB_hid_get_indexed_string
237 #define hid_error LIBUSB_hid_error
238 #define new_hid_device LIBUSB_new_hid_device
239 #define free_hid_device LIBUSB_free_hid_device
240 #define input_report LIBUSB_input_report
241 #define return_data LIBUSB_return_data
242 #define make_path LIBUSB_make_path
243 #define read_thread LIBUSB_read_thread
244
245 #ifndef __FreeBSD__
246 /* this is awkwardly inlined, so we need to re-implement it here
247 * so we can override the libusb_control_transfer call */
248 static int
SDL_libusb_get_string_descriptor(libusb_device_handle * dev,uint8_t descriptor_index,uint16_t lang_id,unsigned char * data,int length)249 SDL_libusb_get_string_descriptor(libusb_device_handle *dev,
250 uint8_t descriptor_index, uint16_t lang_id,
251 unsigned char *data, int length)
252 {
253 return libusb_control_transfer(dev,
254 LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
255 LIBUSB_REQUEST_GET_DESCRIPTOR,
256 (LIBUSB_DT_STRING << 8) | descriptor_index,
257 lang_id,
258 data,
259 (uint16_t) length,
260 1000);
261 }
262 #define libusb_get_string_descriptor SDL_libusb_get_string_descriptor
263 #endif /* __FreeBSD__ */
264
265 #undef HIDAPI_H__
266 #include "libusb/hid.c"
267
268 #undef hid_device_
269 #undef hid_device
270 #undef hid_device_info
271 #undef hid_init
272 #undef hid_exit
273 #undef hid_enumerate
274 #undef hid_free_enumeration
275 #undef hid_open
276 #undef hid_open_path
277 #undef hid_write
278 #undef hid_read_timeout
279 #undef hid_read
280 #undef hid_set_nonblocking
281 #undef hid_send_feature_report
282 #undef hid_get_feature_report
283 #undef hid_close
284 #undef hid_get_manufacturer_string
285 #undef hid_get_product_string
286 #undef hid_get_serial_number_string
287 #undef hid_get_indexed_string
288 #undef hid_error
289 #undef new_hid_device
290 #undef free_hid_device
291 #undef input_report
292 #undef return_data
293 #undef make_path
294 #undef read_thread
295
296 #endif /* SDL_LIBUSB_DYNAMIC */
297
298 /* Shared HIDAPI Implementation */
299
300 #undef HIDAPI_H__
301 #include "hidapi.h"
302
303 struct hidapi_backend {
304 #define F(x) typeof(x) *x
305 F(hid_write);
306 F(hid_read_timeout);
307 F(hid_read);
308 F(hid_set_nonblocking);
309 F(hid_send_feature_report);
310 F(hid_get_feature_report);
311 F(hid_close);
312 F(hid_get_manufacturer_string);
313 F(hid_get_product_string);
314 F(hid_get_serial_number_string);
315 F(hid_get_indexed_string);
316 F(hid_error);
317 #undef F
318 };
319
320 #if HAVE_PLATFORM_BACKEND
321 static const struct hidapi_backend PLATFORM_Backend = {
322 (void*)PLATFORM_hid_write,
323 (void*)PLATFORM_hid_read_timeout,
324 (void*)PLATFORM_hid_read,
325 (void*)PLATFORM_hid_set_nonblocking,
326 (void*)PLATFORM_hid_send_feature_report,
327 (void*)PLATFORM_hid_get_feature_report,
328 (void*)PLATFORM_hid_close,
329 (void*)PLATFORM_hid_get_manufacturer_string,
330 (void*)PLATFORM_hid_get_product_string,
331 (void*)PLATFORM_hid_get_serial_number_string,
332 (void*)PLATFORM_hid_get_indexed_string,
333 (void*)PLATFORM_hid_error
334 };
335 #endif /* HAVE_PLATFORM_BACKEND */
336
337 #ifdef SDL_LIBUSB_DYNAMIC
338 static const struct hidapi_backend LIBUSB_Backend = {
339 (void*)LIBUSB_hid_write,
340 (void*)LIBUSB_hid_read_timeout,
341 (void*)LIBUSB_hid_read,
342 (void*)LIBUSB_hid_set_nonblocking,
343 (void*)LIBUSB_hid_send_feature_report,
344 (void*)LIBUSB_hid_get_feature_report,
345 (void*)LIBUSB_hid_close,
346 (void*)LIBUSB_hid_get_manufacturer_string,
347 (void*)LIBUSB_hid_get_product_string,
348 (void*)LIBUSB_hid_get_serial_number_string,
349 (void*)LIBUSB_hid_get_indexed_string,
350 (void*)LIBUSB_hid_error
351 };
352 #endif /* SDL_LIBUSB_DYNAMIC */
353
354 typedef struct _HIDDeviceWrapper HIDDeviceWrapper;
355 struct _HIDDeviceWrapper
356 {
357 hid_device *device; /* must be first field */
358 const struct hidapi_backend *backend;
359 };
360
361 static HIDDeviceWrapper *
CreateHIDDeviceWrapper(hid_device * device,const struct hidapi_backend * backend)362 CreateHIDDeviceWrapper(hid_device *device, const struct hidapi_backend *backend)
363 {
364 HIDDeviceWrapper *ret = SDL_malloc(sizeof(*ret));
365 ret->device = device;
366 ret->backend = backend;
367 return ret;
368 }
369
370 static hid_device *
WrapHIDDevice(HIDDeviceWrapper * wrapper)371 WrapHIDDevice(HIDDeviceWrapper *wrapper)
372 {
373 return (hid_device *)wrapper;
374 }
375
376 static HIDDeviceWrapper *
UnwrapHIDDevice(hid_device * device)377 UnwrapHIDDevice(hid_device *device)
378 {
379 return (HIDDeviceWrapper *)device;
380 }
381
382 static void
DeleteHIDDeviceWrapper(HIDDeviceWrapper * device)383 DeleteHIDDeviceWrapper(HIDDeviceWrapper *device)
384 {
385 SDL_free(device);
386 }
387
388 #define COPY_IF_EXISTS(var) \
389 if (pSrc->var != NULL) { \
390 pDst->var = SDL_strdup(pSrc->var); \
391 } else { \
392 pDst->var = NULL; \
393 }
394 #define WCOPY_IF_EXISTS(var) \
395 if (pSrc->var != NULL) { \
396 pDst->var = SDL_wcsdup(pSrc->var); \
397 } else { \
398 pDst->var = NULL; \
399 }
400
401 #ifdef SDL_LIBUSB_DYNAMIC
402 static void
LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info * pSrc,struct hid_device_info * pDst)403 LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
404 struct hid_device_info *pDst)
405 {
406 COPY_IF_EXISTS(path)
407 pDst->vendor_id = pSrc->vendor_id;
408 pDst->product_id = pSrc->product_id;
409 WCOPY_IF_EXISTS(serial_number)
410 pDst->release_number = pSrc->release_number;
411 WCOPY_IF_EXISTS(manufacturer_string)
412 WCOPY_IF_EXISTS(product_string)
413 pDst->usage_page = pSrc->usage_page;
414 pDst->usage = pSrc->usage;
415 pDst->interface_number = pSrc->interface_number;
416 pDst->interface_class = pSrc->interface_class;
417 pDst->interface_subclass = pSrc->interface_subclass;
418 pDst->interface_protocol = pSrc->interface_protocol;
419 pDst->next = NULL;
420 }
421 #endif /* SDL_LIBUSB_DYNAMIC */
422
423 #if HAVE_PLATFORM_BACKEND
424 static void
PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info * pSrc,struct hid_device_info * pDst)425 PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
426 struct hid_device_info *pDst)
427 {
428 COPY_IF_EXISTS(path)
429 pDst->vendor_id = pSrc->vendor_id;
430 pDst->product_id = pSrc->product_id;
431 WCOPY_IF_EXISTS(serial_number)
432 pDst->release_number = pSrc->release_number;
433 WCOPY_IF_EXISTS(manufacturer_string)
434 WCOPY_IF_EXISTS(product_string)
435 pDst->usage_page = pSrc->usage_page;
436 pDst->usage = pSrc->usage;
437 pDst->interface_number = pSrc->interface_number;
438 pDst->interface_class = pSrc->interface_class;
439 pDst->interface_subclass = pSrc->interface_subclass;
440 pDst->interface_protocol = pSrc->interface_protocol;
441 pDst->next = NULL;
442 }
443 #endif /* HAVE_PLATFORM_BACKEND */
444
445 #undef COPY_IF_EXISTS
446 #undef WCOPY_IF_EXISTS
447
448 static SDL_bool SDL_hidapi_wasinit = SDL_FALSE;
449
hid_init(void)450 int HID_API_EXPORT HID_API_CALL hid_init(void)
451 {
452 int err;
453
454 if (SDL_hidapi_wasinit == SDL_TRUE) {
455 return 0;
456 }
457
458 #ifdef SDL_LIBUSB_DYNAMIC
459 libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
460 if (libusb_ctx.libhandle != NULL) {
461 #define LOAD_LIBUSB_SYMBOL(func) \
462 libusb_ctx.func = SDL_LoadFunction(libusb_ctx.libhandle, "libusb_" #func);
463 LOAD_LIBUSB_SYMBOL(init)
464 LOAD_LIBUSB_SYMBOL(exit)
465 LOAD_LIBUSB_SYMBOL(get_device_list)
466 LOAD_LIBUSB_SYMBOL(free_device_list)
467 LOAD_LIBUSB_SYMBOL(get_device_descriptor)
468 LOAD_LIBUSB_SYMBOL(get_active_config_descriptor)
469 LOAD_LIBUSB_SYMBOL(get_config_descriptor)
470 LOAD_LIBUSB_SYMBOL(free_config_descriptor)
471 LOAD_LIBUSB_SYMBOL(get_bus_number)
472 LOAD_LIBUSB_SYMBOL(get_device_address)
473 LOAD_LIBUSB_SYMBOL(open)
474 LOAD_LIBUSB_SYMBOL(close)
475 LOAD_LIBUSB_SYMBOL(claim_interface)
476 LOAD_LIBUSB_SYMBOL(release_interface)
477 LOAD_LIBUSB_SYMBOL(kernel_driver_active)
478 LOAD_LIBUSB_SYMBOL(detach_kernel_driver)
479 LOAD_LIBUSB_SYMBOL(attach_kernel_driver)
480 LOAD_LIBUSB_SYMBOL(set_interface_alt_setting)
481 LOAD_LIBUSB_SYMBOL(alloc_transfer)
482 LOAD_LIBUSB_SYMBOL(submit_transfer)
483 LOAD_LIBUSB_SYMBOL(cancel_transfer)
484 LOAD_LIBUSB_SYMBOL(free_transfer)
485 LOAD_LIBUSB_SYMBOL(control_transfer)
486 LOAD_LIBUSB_SYMBOL(interrupt_transfer)
487 LOAD_LIBUSB_SYMBOL(handle_events)
488 LOAD_LIBUSB_SYMBOL(handle_events_completed)
489 #undef LOAD_LIBUSB_SYMBOL
490
491 if ((err = LIBUSB_hid_init()) < 0) {
492 SDL_UnloadObject(libusb_ctx.libhandle);
493 return err;
494 }
495 }
496 #endif /* SDL_LIBUSB_DYNAMIC */
497
498 #if HAVE_PLATFORM_BACKEND
499 #if __LINUX__
500 udev_ctx = SDL_UDEV_GetUdevSyms();
501 #endif /* __LINUX __ */
502 if (udev_ctx && (err = PLATFORM_hid_init()) < 0) {
503 #ifdef SDL_LIBUSB_DYNAMIC
504 if (libusb_ctx.libhandle) {
505 SDL_UnloadObject(libusb_ctx.libhandle);
506 }
507 #endif /* SDL_LIBUSB_DYNAMIC */
508 return err;
509 }
510 #endif /* HAVE_PLATFORM_BACKEND */
511
512 return 0;
513 }
514
hid_exit(void)515 int HID_API_EXPORT HID_API_CALL hid_exit(void)
516 {
517 int err = 0;
518
519 if (SDL_hidapi_wasinit == SDL_FALSE) {
520 return 0;
521 }
522
523 #if HAVE_PLATFORM_BACKEND
524 if (udev_ctx) {
525 err = PLATFORM_hid_exit();
526 }
527 #endif /* HAVE_PLATFORM_BACKEND */
528 #ifdef SDL_LIBUSB_DYNAMIC
529 if (libusb_ctx.libhandle) {
530 err |= LIBUSB_hid_exit(); /* Ehhhhh */
531 SDL_UnloadObject(libusb_ctx.libhandle);
532 }
533 #endif /* SDL_LIBUSB_DYNAMIC */
534 return err;
535 }
536
hid_enumerate(unsigned short vendor_id,unsigned short product_id)537 struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
538 {
539 #ifdef SDL_LIBUSB_DYNAMIC
540 struct LIBUSB_hid_device_info *usb_devs = NULL;
541 struct LIBUSB_hid_device_info *usb_dev;
542 #endif
543 #if HAVE_PLATFORM_BACKEND
544 struct PLATFORM_hid_device_info *raw_devs = NULL;
545 struct PLATFORM_hid_device_info *raw_dev;
546 #endif
547 struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
548
549 if (SDL_hidapi_wasinit == SDL_FALSE) {
550 hid_init();
551 }
552
553 #ifdef SDL_LIBUSB_DYNAMIC
554 if (libusb_ctx.libhandle) {
555 usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
556 for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
557 new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
558 LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
559
560 if (last != NULL) {
561 last->next = new_dev;
562 } else {
563 devs = new_dev;
564 }
565 last = new_dev;
566 }
567 }
568 #endif /* SDL_LIBUSB_DYNAMIC */
569
570 #if HAVE_PLATFORM_BACKEND
571 if (udev_ctx) {
572 raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
573 for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
574 SDL_bool bFound = SDL_FALSE;
575 #ifdef SDL_LIBUSB_DYNAMIC
576 for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
577 if (raw_dev->vendor_id == usb_dev->vendor_id &&
578 raw_dev->product_id == usb_dev->product_id &&
579 (raw_dev->interface_number < 0 || raw_dev->interface_number == usb_dev->interface_number)) {
580 bFound = SDL_TRUE;
581 break;
582 }
583 }
584 #endif
585 if (!bFound) {
586 new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
587 PLATFORM_CopyHIDDeviceInfo(raw_dev, new_dev);
588 new_dev->next = NULL;
589
590 if (last != NULL) {
591 last->next = new_dev;
592 } else {
593 devs = new_dev;
594 }
595 last = new_dev;
596 }
597 }
598 PLATFORM_hid_free_enumeration(raw_devs);
599 }
600 #endif /* HAVE_PLATFORM_BACKEND */
601
602 #ifdef SDL_LIBUSB_DYNAMIC
603 if (libusb_ctx.libhandle) {
604 LIBUSB_hid_free_enumeration(usb_devs);
605 }
606 #endif
607 return devs;
608 }
609
hid_free_enumeration(struct hid_device_info * devs)610 void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
611 {
612 while (devs) {
613 struct hid_device_info *next = devs->next;
614 SDL_free(devs->path);
615 SDL_free(devs->serial_number);
616 SDL_free(devs->manufacturer_string);
617 SDL_free(devs->product_string);
618 SDL_free(devs);
619 devs = next;
620 }
621 }
622
hid_open(unsigned short vendor_id,unsigned short product_id,const wchar_t * serial_number)623 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
624 {
625 hid_device *pDevice = NULL;
626
627 if (SDL_hidapi_wasinit == SDL_FALSE) {
628 hid_init();
629 }
630
631 #if HAVE_PLATFORM_BACKEND
632 if (udev_ctx &&
633 (pDevice = (hid_device*) PLATFORM_hid_open(vendor_id, product_id, serial_number)) != NULL) {
634
635 HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
636 return WrapHIDDevice(wrapper);
637 }
638 #endif /* HAVE_PLATFORM_BACKEND */
639 #ifdef SDL_LIBUSB_DYNAMIC
640 if (libusb_ctx.libhandle &&
641 (pDevice = (hid_device*) LIBUSB_hid_open(vendor_id, product_id, serial_number)) != NULL) {
642
643 HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
644 return WrapHIDDevice(wrapper);
645 }
646 #endif /* SDL_LIBUSB_DYNAMIC */
647 return NULL;
648 }
649
hid_open_path(const char * path,int bExclusive)650 HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */)
651 {
652 hid_device *pDevice = NULL;
653
654 if (SDL_hidapi_wasinit == SDL_FALSE) {
655 hid_init();
656 }
657
658 #if HAVE_PLATFORM_BACKEND
659 if (udev_ctx &&
660 (pDevice = (hid_device*) PLATFORM_hid_open_path(path, bExclusive)) != NULL) {
661
662 HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
663 return WrapHIDDevice(wrapper);
664 }
665 #endif /* HAVE_PLATFORM_BACKEND */
666 #ifdef SDL_LIBUSB_DYNAMIC
667 if (libusb_ctx.libhandle &&
668 (pDevice = (hid_device*) LIBUSB_hid_open_path(path, bExclusive)) != NULL) {
669
670 HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
671 return WrapHIDDevice(wrapper);
672 }
673 #endif /* SDL_LIBUSB_DYNAMIC */
674 return NULL;
675 }
676
hid_write(hid_device * device,const unsigned char * data,size_t length)677 int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
678 {
679 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
680 return wrapper->backend->hid_write(wrapper->device, data, length);
681 }
682
hid_read_timeout(hid_device * device,unsigned char * data,size_t length,int milliseconds)683 int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
684 {
685 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
686 return wrapper->backend->hid_read_timeout(wrapper->device, data, length, milliseconds);
687 }
688
hid_read(hid_device * device,unsigned char * data,size_t length)689 int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
690 {
691 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
692 return wrapper->backend->hid_read(wrapper->device, data, length);
693 }
694
hid_set_nonblocking(hid_device * device,int nonblock)695 int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
696 {
697 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
698 return wrapper->backend->hid_set_nonblocking(wrapper->device, nonblock);
699 }
700
hid_send_feature_report(hid_device * device,const unsigned char * data,size_t length)701 int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
702 {
703 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
704 return wrapper->backend->hid_send_feature_report(wrapper->device, data, length);
705 }
706
hid_get_feature_report(hid_device * device,unsigned char * data,size_t length)707 int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
708 {
709 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
710 return wrapper->backend->hid_get_feature_report(wrapper->device, data, length);
711 }
712
hid_close(hid_device * device)713 void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
714 {
715 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
716 wrapper->backend->hid_close(wrapper->device);
717 DeleteHIDDeviceWrapper(wrapper);
718 }
719
hid_get_manufacturer_string(hid_device * device,wchar_t * string,size_t maxlen)720 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
721 {
722 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
723 return wrapper->backend->hid_get_manufacturer_string(wrapper->device, string, maxlen);
724 }
725
hid_get_product_string(hid_device * device,wchar_t * string,size_t maxlen)726 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
727 {
728 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
729 return wrapper->backend->hid_get_product_string(wrapper->device, string, maxlen);
730 }
731
hid_get_serial_number_string(hid_device * device,wchar_t * string,size_t maxlen)732 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
733 {
734 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
735 return wrapper->backend->hid_get_serial_number_string(wrapper->device, string, maxlen);
736 }
737
hid_get_indexed_string(hid_device * device,int string_index,wchar_t * string,size_t maxlen)738 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
739 {
740 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
741 return wrapper->backend->hid_get_indexed_string(wrapper->device, string_index, string, maxlen);
742 }
743
hid_error(hid_device * device)744 HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
745 {
746 HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
747 return wrapper->backend->hid_error(wrapper->device);
748 }
749
750 #endif /* SDL_JOYSTICK_HIDAPI */
751
752 /* vi: set sts=4 ts=4 sw=4 expandtab: */
753