1 /*******************************************************
2 HIDAPI - Multi-Platform library for
3 communication with HID devices.
4
5 Alan Ott
6 Signal 11 Software
7
8 8/22/2009
9 Linux Version - 6/2/2009
10
11 Copyright 2009, All Rights Reserved.
12
13 At the discretion of the user of this library,
14 this software may be licensed under the terms of the
15 GNU General Public License v3, a BSD-Style license, or the
16 original HIDAPI license as outlined in the LICENSE.txt,
17 LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
18 files located at the root of the source distribution.
19 These files may also be found in the public source
20 code repository located at:
21 http://github.com/signal11/hidapi .
22 ********************************************************/
23
24 /* C */
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <locale.h>
29 #include <errno.h>
30
31 /* Unix */
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <sys/utsname.h>
37 #include <fcntl.h>
38 #include <poll.h>
39
40 /* Linux */
41 #include <linux/hidraw.h>
42 #include <linux/version.h>
43 #include <linux/input.h>
44 #include <libudev.h>
45
46 #include "hidapi.h"
47
48 /* Definitions from linux/hidraw.h. Since these are new, some distros
49 may not have header files which contain them. */
50 #ifndef HIDIOCSFEATURE
51 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
52 #endif
53 #ifndef HIDIOCGFEATURE
54 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
55 #endif
56
57
58 /* USB HID device property names */
59 const char *device_string_names[] = {
60 "manufacturer",
61 "product",
62 "serial",
63 };
64
65 /* Symbolic names for the properties above */
66 enum device_string_id {
67 DEVICE_STRING_MANUFACTURER,
68 DEVICE_STRING_PRODUCT,
69 DEVICE_STRING_SERIAL,
70
71 DEVICE_STRING_COUNT,
72 };
73
74 struct hid_device_ {
75 int device_handle;
76 int blocking;
77 int uses_numbered_reports;
78 };
79
80
81 static __u32 kernel_version = 0;
82
detect_kernel_version(void)83 static __u32 detect_kernel_version(void)
84 {
85 struct utsname name;
86 int major, minor, release;
87 int ret;
88
89 uname(&name);
90 ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
91 if (ret == 3) {
92 return KERNEL_VERSION(major, minor, release);
93 }
94
95 ret = sscanf(name.release, "%d.%d", &major, &minor);
96 if (ret == 2) {
97 return KERNEL_VERSION(major, minor, 0);
98 }
99
100 printf("Couldn't determine kernel version from version string \"%s\"\n", name.release);
101 return 0;
102 }
103
new_hid_device(void)104 static hid_device *new_hid_device(void)
105 {
106 hid_device *dev = calloc(1, sizeof(hid_device));
107 dev->device_handle = -1;
108 dev->blocking = 1;
109 dev->uses_numbered_reports = 0;
110
111 return dev;
112 }
113
114
115 /* The caller must free the returned string with free(). */
utf8_to_wchar_t(const char * utf8)116 static wchar_t *utf8_to_wchar_t(const char *utf8)
117 {
118 wchar_t *ret = NULL;
119
120 if (utf8) {
121 size_t wlen = mbstowcs(NULL, utf8, 0);
122 if ((size_t) -1 == wlen) {
123 return wcsdup(L"");
124 }
125 ret = calloc(wlen+1, sizeof(wchar_t));
126 mbstowcs(ret, utf8, wlen+1);
127 ret[wlen] = 0x0000;
128 }
129
130 return ret;
131 }
132
133 /* Get an attribute value from a udev_device and return it as a whar_t
134 string. The returned string must be freed with free() when done.*/
copy_udev_string(struct udev_device * dev,const char * udev_name)135 static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
136 {
137 return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
138 }
139
140 /* uses_numbered_reports() returns 1 if report_descriptor describes a device
141 which contains numbered reports. */
uses_numbered_reports(__u8 * report_descriptor,__u32 size)142 static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
143 unsigned int i = 0;
144 int size_code;
145 int data_len, key_size;
146
147 while (i < size) {
148 int key = report_descriptor[i];
149
150 /* Check for the Report ID key */
151 if (key == 0x85/*Report ID*/) {
152 /* This device has a Report ID, which means it uses
153 numbered reports. */
154 return 1;
155 }
156
157 //printf("key: %02hhx\n", key);
158
159 if ((key & 0xf0) == 0xf0) {
160 /* This is a Long Item. The next byte contains the
161 length of the data section (value) for this key.
162 See the HID specification, version 1.11, section
163 6.2.2.3, titled "Long Items." */
164 if (i+1 < size)
165 data_len = report_descriptor[i+1];
166 else
167 data_len = 0; /* malformed report */
168 key_size = 3;
169 }
170 else {
171 /* This is a Short Item. The bottom two bits of the
172 key contain the size code for the data section
173 (value) for this key. Refer to the HID
174 specification, version 1.11, section 6.2.2.2,
175 titled "Short Items." */
176 size_code = key & 0x3;
177 switch (size_code) {
178 case 0:
179 case 1:
180 case 2:
181 data_len = size_code;
182 break;
183 case 3:
184 data_len = 4;
185 break;
186 default:
187 /* Can't ever happen since size_code is & 0x3 */
188 data_len = 0;
189 break;
190 };
191 key_size = 1;
192 }
193
194 /* Skip over this key and it's associated data */
195 i += data_len + key_size;
196 }
197
198 /* Didn't find a Report ID key. Device doesn't use numbered reports. */
199 return 0;
200 }
201
202 /*
203 * The caller is responsible for free()ing the (newly-allocated) character
204 * strings pointed to by serial_number_utf8 and product_name_utf8 after use.
205 */
206 static int
parse_uevent_info(const char * uevent,int * bus_type,unsigned short * vendor_id,unsigned short * product_id,char ** serial_number_utf8,char ** product_name_utf8)207 parse_uevent_info(const char *uevent, int *bus_type,
208 unsigned short *vendor_id, unsigned short *product_id,
209 char **serial_number_utf8, char **product_name_utf8)
210 {
211 char *tmp = strdup(uevent);
212 char *saveptr = NULL;
213 char *line;
214 char *key;
215 char *value;
216
217 int found_id = 0;
218 int found_serial = 0;
219 int found_name = 0;
220
221 line = strtok_r(tmp, "\n", &saveptr);
222 while (line != NULL) {
223 /* line: "KEY=value" */
224 key = line;
225 value = strchr(line, '=');
226 if (!value) {
227 goto next_line;
228 }
229 *value = '\0';
230 value++;
231
232 if (strcmp(key, "HID_ID") == 0) {
233 /**
234 * type vendor product
235 * HID_ID=0003:000005AC:00008242
236 **/
237 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id);
238 if (ret == 3) {
239 found_id = 1;
240 }
241 } else if (strcmp(key, "HID_NAME") == 0) {
242 /* The caller has to free the product name */
243 *product_name_utf8 = strdup(value);
244 found_name = 1;
245 } else if (strcmp(key, "HID_UNIQ") == 0) {
246 /* The caller has to free the serial number */
247 *serial_number_utf8 = strdup(value);
248 found_serial = 1;
249 }
250
251 next_line:
252 line = strtok_r(NULL, "\n", &saveptr);
253 }
254
255 free(tmp);
256 return (found_id && found_name && found_serial);
257 }
258
259
get_device_string(hid_device * dev,enum device_string_id key,wchar_t * string,size_t maxlen)260 static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen)
261 {
262 struct udev *udev;
263 struct udev_device *udev_dev, *parent, *hid_dev;
264 struct stat s;
265 int ret = -1;
266 char *serial_number_utf8 = NULL;
267 char *product_name_utf8 = NULL;
268
269 /* Create the udev object */
270 udev = udev_new();
271 if (!udev) {
272 printf("Can't create udev\n");
273 return -1;
274 }
275
276 /* Get the dev_t (major/minor numbers) from the file handle. */
277 fstat(dev->device_handle, &s);
278 /* Open a udev device from the dev_t. 'c' means character device. */
279 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
280 if (udev_dev) {
281 hid_dev = udev_device_get_parent_with_subsystem_devtype(
282 udev_dev,
283 "hid",
284 NULL);
285 if (hid_dev) {
286 unsigned short dev_vid;
287 unsigned short dev_pid;
288 int bus_type;
289 size_t retm;
290
291 ret = parse_uevent_info(
292 udev_device_get_sysattr_value(hid_dev, "uevent"),
293 &bus_type,
294 &dev_vid,
295 &dev_pid,
296 &serial_number_utf8,
297 &product_name_utf8);
298
299 if (bus_type == BUS_BLUETOOTH) {
300 switch (key) {
301 case DEVICE_STRING_MANUFACTURER:
302 wcsncpy(string, L"", maxlen);
303 ret = 0;
304 break;
305 case DEVICE_STRING_PRODUCT:
306 retm = mbstowcs(string, product_name_utf8, maxlen);
307 ret = (retm == (size_t)-1)? -1: 0;
308 break;
309 case DEVICE_STRING_SERIAL:
310 retm = mbstowcs(string, serial_number_utf8, maxlen);
311 ret = (retm == (size_t)-1)? -1: 0;
312 break;
313 case DEVICE_STRING_COUNT:
314 default:
315 ret = -1;
316 break;
317 }
318 }
319 else {
320 if (key == DEVICE_STRING_SERIAL) {
321 /* work around */
322 retm = mbstowcs(string, serial_number_utf8, maxlen);
323 ret = (retm == (size_t)-1)? -1: 0;
324 goto end;
325 }
326
327 /* This is a USB device. Find its parent USB Device node. */
328 parent = udev_device_get_parent_with_subsystem_devtype(
329 udev_dev,
330 "usb",
331 "usb_device");
332 if (parent) {
333 const char *str;
334 const char *key_str = NULL;
335
336 if (key >= 0 && key < DEVICE_STRING_COUNT) {
337 key_str = device_string_names[key];
338 } else {
339 ret = -1;
340 goto end;
341 }
342
343 str = udev_device_get_sysattr_value(parent, key_str);
344 if (str) {
345 /* Convert the string from UTF-8 to wchar_t */
346 retm = mbstowcs(string, str, maxlen);
347 ret = (retm == (size_t)-1)? -1: 0;
348 goto end;
349 }
350 }
351 }
352 }
353 }
354
355 end:
356 free(serial_number_utf8);
357 free(product_name_utf8);
358
359 udev_device_unref(udev_dev);
360 /* parent and hid_dev don't need to be (and can't be) unref'd.
361 I'm not sure why, but they'll throw double-free() errors. */
362 udev_unref(udev);
363
364 return ret;
365 }
366
hid_init(void)367 int HID_API_EXPORT hid_init(void)
368 {
369 const char *locale;
370
371 /* Set the locale if it's not set. */
372 locale = setlocale(LC_CTYPE, NULL);
373 if (!locale)
374 setlocale(LC_CTYPE, "");
375
376 kernel_version = detect_kernel_version();
377
378 return 0;
379 }
380
hid_exit(void)381 int HID_API_EXPORT hid_exit(void)
382 {
383 /* Nothing to do for this in the Linux/hidraw implementation. */
384 return 0;
385 }
386
387
hid_enumerate(unsigned short vendor_id,unsigned short product_id)388 struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
389 {
390 struct udev *udev;
391 struct udev_enumerate *enumerate;
392 struct udev_list_entry *devices, *dev_list_entry;
393
394 struct hid_device_info *root = NULL; /* return object */
395 struct hid_device_info *cur_dev = NULL;
396 struct hid_device_info *prev_dev = NULL; /* previous device */
397
398 hid_init();
399
400 /* Create the udev object */
401 udev = udev_new();
402 if (!udev) {
403 printf("Can't create udev\n");
404 return NULL;
405 }
406
407 /* Create a list of the devices in the 'hidraw' subsystem. */
408 enumerate = udev_enumerate_new(udev);
409 udev_enumerate_add_match_subsystem(enumerate, "hidraw");
410 udev_enumerate_scan_devices(enumerate);
411 devices = udev_enumerate_get_list_entry(enumerate);
412 /* For each item, see if it matches the vid/pid, and if so
413 create a udev_device record for it */
414 udev_list_entry_foreach(dev_list_entry, devices) {
415 const char *sysfs_path;
416 const char *dev_path;
417 const char *str;
418 struct udev_device *raw_dev; /* The device's hidraw udev node. */
419 struct udev_device *hid_dev; /* The device's HID udev node. */
420 struct udev_device *usb_dev; /* The device's USB udev node. */
421 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */
422 unsigned short dev_vid;
423 unsigned short dev_pid;
424 char *serial_number_utf8 = NULL;
425 char *product_name_utf8 = NULL;
426 int bus_type;
427 int result;
428
429 /* Get the filename of the /sys entry for the device
430 and create a udev_device object (dev) representing it */
431 sysfs_path = udev_list_entry_get_name(dev_list_entry);
432 raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
433 dev_path = udev_device_get_devnode(raw_dev);
434
435 hid_dev = udev_device_get_parent_with_subsystem_devtype(
436 raw_dev,
437 "hid",
438 NULL);
439
440 if (!hid_dev) {
441 /* Unable to find parent hid device. */
442 goto next;
443 }
444
445 result = parse_uevent_info(
446 udev_device_get_sysattr_value(hid_dev, "uevent"),
447 &bus_type,
448 &dev_vid,
449 &dev_pid,
450 &serial_number_utf8,
451 &product_name_utf8);
452
453 if (!result) {
454 /* parse_uevent_info() failed for at least one field. */
455 goto next;
456 }
457
458 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
459 /* We only know how to handle USB and BT devices. */
460 goto next;
461 }
462
463 /* Check the VID/PID against the arguments */
464 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
465 (product_id == 0x0 || product_id == dev_pid)) {
466 struct hid_device_info *tmp;
467
468 /* VID/PID match. Create the record. */
469 tmp = malloc(sizeof(struct hid_device_info));
470 if (cur_dev) {
471 cur_dev->next = tmp;
472 }
473 else {
474 root = tmp;
475 }
476 prev_dev = cur_dev;
477 cur_dev = tmp;
478
479 /* Fill out the record */
480 cur_dev->next = NULL;
481 cur_dev->path = dev_path? strdup(dev_path): NULL;
482
483 /* VID/PID */
484 cur_dev->vendor_id = dev_vid;
485 cur_dev->product_id = dev_pid;
486
487 /* Serial Number */
488 cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8);
489
490 /* Release Number */
491 cur_dev->release_number = 0x0;
492
493 /* Interface Number */
494 cur_dev->interface_number = -1;
495
496 switch (bus_type) {
497 case BUS_USB:
498 /* The device pointed to by raw_dev contains information about
499 the hidraw device. In order to get information about the
500 USB device, get the parent device with the
501 subsystem/devtype pair of "usb"/"usb_device". This will
502 be several levels up the tree, but the function will find
503 it. */
504 usb_dev = udev_device_get_parent_with_subsystem_devtype(
505 raw_dev,
506 "usb",
507 "usb_device");
508
509 if (!usb_dev) {
510 /* Free this device */
511 free(cur_dev->serial_number);
512 free(cur_dev->path);
513 free(cur_dev);
514
515 /* Take it off the device list. */
516 if (prev_dev) {
517 prev_dev->next = NULL;
518 cur_dev = prev_dev;
519 }
520 else {
521 cur_dev = root = NULL;
522 }
523
524 goto next;
525 }
526
527 /* Manufacturer and Product strings */
528 cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
529 cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
530
531 /* Release Number */
532 str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
533 cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
534
535 /* Get a handle to the interface's udev node. */
536 intf_dev = udev_device_get_parent_with_subsystem_devtype(
537 raw_dev,
538 "usb",
539 "usb_interface");
540 if (intf_dev) {
541 str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
542 cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
543 }
544
545 break;
546
547 case BUS_BLUETOOTH:
548 /* Manufacturer and Product strings */
549 cur_dev->manufacturer_string = wcsdup(L"");
550 cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
551
552 break;
553
554 default:
555 /* Unknown device type - this should never happen, as we
556 * check for USB and Bluetooth devices above */
557 break;
558 }
559 }
560
561 next:
562 free(serial_number_utf8);
563 free(product_name_utf8);
564 udev_device_unref(raw_dev);
565 /* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
566 unref()d. It will cause a double-free() error. I'm not
567 sure why. */
568 }
569 /* Free the enumerator and udev objects. */
570 udev_enumerate_unref(enumerate);
571 udev_unref(udev);
572
573 return root;
574 }
575
hid_free_enumeration(struct hid_device_info * devs)576 void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
577 {
578 struct hid_device_info *d = devs;
579 while (d) {
580 struct hid_device_info *next = d->next;
581 free(d->path);
582 free(d->serial_number);
583 free(d->manufacturer_string);
584 free(d->product_string);
585 free(d);
586 d = next;
587 }
588 }
589
hid_open(unsigned short vendor_id,unsigned short product_id,const wchar_t * serial_number)590 hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
591 {
592 struct hid_device_info *devs, *cur_dev;
593 const char *path_to_open = NULL;
594 hid_device *handle = NULL;
595
596 devs = hid_enumerate(vendor_id, product_id);
597 cur_dev = devs;
598 while (cur_dev) {
599 if (cur_dev->vendor_id == vendor_id &&
600 cur_dev->product_id == product_id) {
601 if (serial_number) {
602 if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
603 path_to_open = cur_dev->path;
604 break;
605 }
606 }
607 else {
608 path_to_open = cur_dev->path;
609 break;
610 }
611 }
612 cur_dev = cur_dev->next;
613 }
614
615 if (path_to_open) {
616 /* Open the device */
617 handle = hid_open_path(path_to_open);
618 }
619
620 hid_free_enumeration(devs);
621
622 return handle;
623 }
624
hid_open_path(const char * path)625 hid_device * HID_API_EXPORT hid_open_path(const char *path)
626 {
627 hid_device *dev = NULL;
628
629 hid_init();
630
631 dev = new_hid_device();
632
633 /* OPEN HERE */
634 dev->device_handle = open(path, O_RDWR);
635
636 /* If we have a good handle, return it. */
637 /* test test shoud be >= 0 even if it is not so likely (I guess) */
638 if (dev->device_handle > 0) {
639
640 /* Get the report descriptor */
641 int res, desc_size = 0;
642 struct hidraw_report_descriptor rpt_desc;
643
644 memset(&rpt_desc, 0x0, sizeof(rpt_desc));
645
646 /* Get Report Descriptor Size */
647 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
648 if (res < 0)
649 perror("HIDIOCGRDESCSIZE");
650
651
652 /* Get Report Descriptor */
653 rpt_desc.size = desc_size;
654 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
655 if (res < 0) {
656 perror("HIDIOCGRDESC");
657 } else {
658 /* Determine if this device uses numbered reports. */
659 dev->uses_numbered_reports =
660 uses_numbered_reports(rpt_desc.value,
661 rpt_desc.size);
662 }
663
664 return dev;
665 }
666 else {
667 /* Unable to open any devices. */
668 free(dev);
669 return NULL;
670 }
671 }
672
hid_get_report_descriptor(hid_device * dev,unsigned char * data,size_t length)673 int HID_API_EXPORT hid_get_report_descriptor(hid_device *dev, unsigned char *data, size_t length)
674 {
675 int res;
676 struct hidraw_report_descriptor rpt_desc;
677 memset(&rpt_desc, 0x0, sizeof(rpt_desc));
678 /* Get Report Descriptor Size */
679 if (dev->device_handle > 0) {
680 int desc_size;
681 /* Get Report Descriptor Size */
682 if (ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size) < 0)
683 return -1;
684 if (desc_size > length) {
685 errno = ERANGE;
686 return -1;
687 }
688 rpt_desc.size = desc_size;
689 if (ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc) < 0)
690 return -1;
691 memcpy(data, rpt_desc.value, rpt_desc.size);
692 return rpt_desc.size;
693 }
694 errno = EINVAL;
695 return -1;
696 }
697
hid_write(hid_device * dev,const unsigned char * data,size_t length)698 int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
699 {
700 int bytes_written;
701
702 bytes_written = write(dev->device_handle, data, length);
703
704 return bytes_written;
705 }
706
707
hid_read_timeout(hid_device * dev,unsigned char * data,size_t length,int milliseconds)708 int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
709 {
710 int bytes_read;
711
712 if (milliseconds >= 0) {
713 /* Milliseconds is either 0 (non-blocking) or > 0 (contains
714 a valid timeout). In both cases we want to call poll()
715 and wait for data to arrive. Don't rely on non-blocking
716 operation (O_NONBLOCK) since some kernels don't seem to
717 properly report device disconnection through read() when
718 in non-blocking mode. */
719 int ret;
720 struct pollfd fds;
721
722 fds.fd = dev->device_handle;
723 fds.events = POLLIN;
724 fds.revents = 0;
725 ret = poll(&fds, 1, milliseconds);
726 if (ret == -1 || ret == 0) {
727 /* Error or timeout */
728 return ret;
729 }
730 else {
731 /* Check for errors on the file descriptor. This will
732 indicate a device disconnection. */
733 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
734 return -1;
735 }
736 }
737
738 bytes_read = read(dev->device_handle, data, length);
739 if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
740 bytes_read = 0;
741
742 if (bytes_read >= 0 &&
743 kernel_version != 0 &&
744 kernel_version < KERNEL_VERSION(2,6,34) &&
745 dev->uses_numbered_reports) {
746 /* Work around a kernel bug. Chop off the first byte. */
747 memmove(data, data+1, bytes_read);
748 bytes_read--;
749 }
750
751 return bytes_read;
752 }
753
hid_read(hid_device * dev,unsigned char * data,size_t length)754 int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
755 {
756 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
757 }
758
hid_set_nonblocking(hid_device * dev,int nonblock)759 int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
760 {
761 /* Do all non-blocking in userspace using poll(), since it looks
762 like there's a bug in the kernel in some versions where
763 read() will not return -1 on disconnection of the USB device */
764
765 dev->blocking = !nonblock;
766 return 0; /* Success */
767 }
768
769 // return an event handle that can be used for poll/epoll/select etc
hid_get_event_handle(hid_device * dev)770 hid_handle_t HID_API_EXPORT hid_get_event_handle(hid_device *dev)
771 {
772 return (hid_handle_t) ((intptr_t)dev->device_handle);
773 }
774
775
hid_send_feature_report(hid_device * dev,const unsigned char * data,size_t length)776 int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
777 {
778 int res;
779
780 res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
781 if (res < 0)
782 perror("ioctl (SFEATURE)");
783
784 return res;
785 }
786
hid_get_feature_report(hid_device * dev,unsigned char * data,size_t length)787 int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
788 {
789 int res;
790
791 res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
792 if (res < 0)
793 perror("ioctl (GFEATURE)");
794
795
796 return res;
797 }
798
799
hid_close(hid_device * dev)800 void HID_API_EXPORT hid_close(hid_device *dev)
801 {
802 if (!dev)
803 return;
804 close(dev->device_handle);
805 free(dev);
806 }
807
808
hid_get_manufacturer_string(hid_device * dev,wchar_t * string,size_t maxlen)809 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
810 {
811 return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen);
812 }
813
hid_get_product_string(hid_device * dev,wchar_t * string,size_t maxlen)814 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
815 {
816 return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen);
817 }
818
hid_get_serial_number_string(hid_device * dev,wchar_t * string,size_t maxlen)819 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
820 {
821 return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen);
822 }
823
hid_get_indexed_string(hid_device * dev,int string_index,wchar_t * string,size_t maxlen)824 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
825 {
826 return -1;
827 }
828
829
hid_error(hid_device * dev)830 HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
831 {
832 return NULL;
833 }
834