Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/hidapi/hidapi_linux.c

Issue 25666010: Adding third party library hidapi (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
83 static hid_device *new_hid_device(void)
84 {
85 hid_device *dev = calloc(1, sizeof(hid_device));
Kees Cook 2013/12/04 20:49:36 Need to check for NULL return here to avoid crashi
Bei Zhang 2013/12/10 22:24:11 Done.
86 dev->device_handle = -1;
87 dev->blocking = 1;
88 dev->uses_numbered_reports = 0;
89
90 return dev;
91 }
92
93
94 /* The caller must free the returned string with free(). */
95 static wchar_t *utf8_to_wchar_t(const char *utf8)
96 {
97 wchar_t *ret = NULL;
98
99 if (utf8) {
100 size_t wlen = mbstowcs(NULL, utf8, 0);
101 if ((size_t) -1 == wlen) {
102 return wcsdup(L"");
103 }
104 ret = calloc(wlen+1, sizeof(wchar_t));
Kees Cook 2013/12/04 20:49:36 NULL check needed.
Bei Zhang 2013/12/10 22:24:11 Done.
105 mbstowcs(ret, utf8, wlen+1);
106 ret[wlen] = 0x0000;
107 }
108
109 return ret;
110 }
111
112 /* Get an attribute value from a udev_device and return it as a whar_t
113 string. The returned string must be freed with free() when done.*/
114 static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
115 {
116 return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
117 }
118
119 /* uses_numbered_reports() returns 1 if report_descriptor describes a device
120 which contains numbered reports. */
121 static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
122 unsigned int i = 0;
123 int size_code;
124 int data_len, key_size;
125
126 while (i < size) {
127 int key = report_descriptor[i];
Kees Cook 2013/12/04 20:49:36 Why is "key" an int here? Would make more sense to
Bei Zhang 2013/12/10 22:24:11 Done.
128
129 /* Check for the Report ID key */
130 if (key == 0x85/*Report ID*/) {
131 /* This device has a Report ID, which means it uses
132 numbered reports. */
133 return 1;
134 }
135
136 //printf("key: %02hhx\n", key);
137
138 if ((key & 0xf0) == 0xf0) {
139 /* This is a Long Item. The next byte contains the
140 length of the data section (value) for this key.
141 See the HID specification, version 1.11, section
142 6.2.2.3, titled "Long Items." */
143 if (i+1 < size)
144 data_len = report_descriptor[i+1];
145 else
146 data_len = 0; /* malformed report */
147 key_size = 3;
148 }
149 else {
150 /* This is a Short Item. The bottom two bits of the
151 key contain the size code for the data section
152 (value) for this key. Refer to the HID
153 specification, version 1.11, section 6.2.2.2,
154 titled "Short Items." */
155 size_code = key & 0x3;
156 switch (size_code) {
157 case 0:
158 case 1:
159 case 2:
160 data_len = size_code;
161 break;
162 case 3:
163 data_len = 4;
164 break;
165 default:
166 /* Can't ever happen since size_code is & 0x3 */
167 data_len = 0;
168 break;
169 };
170 key_size = 1;
171 }
172
173 /* Skip over this key and it's associated data */
174 i += data_len + key_size;
175 }
176
177 /* Didn't find a Report ID key. Device doesn't use numbered reports. */
178 return 0;
179 }
180
181 /*
182 * The caller is responsible for free()ing the (newly-allocated) character
183 * strings pointed to by serial_number_utf8 and product_name_utf8 after use.
184 */
185 static int
186 parse_uevent_info(const char *uevent, int *bus_type,
187 unsigned short *vendor_id, unsigned short *product_id,
188 char **serial_number_utf8, char **product_name_utf8)
189 {
190 char *tmp = strdup(uevent);
191 char *saveptr = NULL;
192 char *line;
193 char *key;
194 char *value;
195
196 int found_id = 0;
197 int found_serial = 0;
198 int found_name = 0;
199
200 line = strtok_r(tmp, "\n", &saveptr);
201 while (line != NULL) {
202 /* line: "KEY=value" */
203 key = line;
204 value = strchr(line, '=');
205 if (!value) {
206 goto next_line;
207 }
208 *value = '\0';
209 value++;
Kees Cook 2013/12/04 20:49:36 Is a zero-length string in "value" considered vali
Bei Zhang 2013/12/10 22:24:11 I don't think it will cause any problem here. On
210
211 if (strcmp(key, "HID_ID") == 0) {
212 /**
213 * type vendor product
214 * HID_ID=0003:000005AC:00008242
215 **/
216 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_i d, product_id);
217 if (ret == 3) {
218 found_id = 1;
219 }
220 } else if (strcmp(key, "HID_NAME") == 0) {
221 /* The caller has to free the product name */
222 *product_name_utf8 = strdup(value);
223 found_name = 1;
224 } else if (strcmp(key, "HID_UNIQ") == 0) {
225 /* The caller has to free the serial number */
226 *serial_number_utf8 = strdup(value);
227 found_serial = 1;
228 }
229
230 next_line:
231 line = strtok_r(NULL, "\n", &saveptr);
232 }
233
234 free(tmp);
235 return (found_id && found_name && found_serial);
236 }
237
238
239 static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen)
240 {
241 struct udev *udev;
242 struct udev_device *udev_dev, *parent, *hid_dev;
243 struct stat s;
244 int ret = -1;
245 char *serial_number_utf8 = NULL;
246 char *product_name_utf8 = NULL;
Kees Cook 2013/12/04 20:49:36 space vs tab indenting?
Bei Zhang 2013/12/10 22:24:11 Done. Converted all tabs to spaces.
247
248 /* Create the udev object */
249 udev = udev_new();
250 if (!udev) {
251 printf("Can't create udev\n");
252 return -1;
253 }
254
255 /* Get the dev_t (major/minor numbers) from the file handle. */
256 fstat(dev->device_handle, &s);
257 /* Open a udev device from the dev_t. 'c' means character device. */
258 udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
259 if (udev_dev) {
260 hid_dev = udev_device_get_parent_with_subsystem_devtype(
261 udev_dev,
262 "hid",
263 NULL);
264 if (hid_dev) {
265 unsigned short dev_vid;
266 unsigned short dev_pid;
267 int bus_type;
268 size_t retm;
269
270 ret = parse_uevent_info(
271 udev_device_get_sysattr_value(hid_dev, "ueven t"),
272 &bus_type,
273 &dev_vid,
274 &dev_pid,
275 &serial_number_utf8,
276 &product_name_utf8);
Kees Cook 2013/12/04 20:49:36 "ret" is unchecked, yet things like product_name_u
Bei Zhang 2013/12/10 22:24:11 Done.
277
278 if (bus_type == BUS_BLUETOOTH) {
279 switch (key) {
280 case DEVICE_STRING_MANUFACTURER:
281 wcsncpy(string, L"", maxlen);
282 ret = 0;
283 break;
284 case DEVICE_STRING_PRODUCT:
285 retm = mbstowcs(string, product_ name_utf8, maxlen);
Kees Cook 2013/12/04 20:49:36 If retm == maxlen, this string will not be NULL te
Bei Zhang 2013/12/10 22:24:11 Done.
286 ret = (retm == (size_t)-1)? -1: 0;
287 break;
288 case DEVICE_STRING_SERIAL:
289 retm = mbstowcs(string, serial_n umber_utf8, maxlen);
290 ret = (retm == (size_t)-1)? -1: 0;
291 break;
292 case DEVICE_STRING_COUNT:
293 default:
294 ret = -1;
295 break;
296 }
297 }
298 else {
299 /* This is a USB device. Find its parent USB Dev ice node. */
300 parent = udev_device_get_parent_with_subsystem_d evtype(
301 udev_dev,
302 "usb",
303 "usb_device");
304 if (parent) {
305 const char *str;
306 const char *key_str = NULL;
307
308 if (key < DEVICE_STRING_COUNT) {
309 key_str = device_string_names[ke y];
310 } else {
311 ret = -1;
312 goto end;
313 }
314
315 str = udev_device_get_sysattr_value(pare nt, key_str);
316 if (str) {
317 /* Convert the string from UTF-8 to wchar_t */
318 retm = mbstowcs(string, str, max len);
319 ret = (retm == (size_t)-1)? -1: 0;
320 goto end;
321 }
322 }
323 }
324 }
325 }
326
327 end:
328 free(serial_number_utf8);
329 free(product_name_utf8);
Kees Cook 2013/12/04 20:49:36 space vs tab indenting.
Bei Zhang 2013/12/10 22:24:11 Ditto. On 2013/12/04 20:49:36, Kees Cook wrote:
330
331 udev_device_unref(udev_dev);
332 /* parent and hid_dev don't need to be (and can't be) unref'd.
333 I'm not sure why, but they'll throw double-free() errors. */
334 udev_unref(udev);
335
336 return ret;
337 }
338
339 int HID_API_EXPORT hid_init(void)
340 {
341 const char *locale;
342
343 /* Set the locale if it's not set. */
344 locale = setlocale(LC_CTYPE, NULL);
345 if (!locale)
346 setlocale(LC_CTYPE, "");
347
348 return 0;
349 }
350
351 int HID_API_EXPORT hid_exit(void)
352 {
353 /* Nothing to do for this in the Linux/hidraw implementation. */
354 return 0;
355 }
356
357
358 struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
359 {
360 struct udev *udev;
361 struct udev_enumerate *enumerate;
362 struct udev_list_entry *devices, *dev_list_entry;
363
364 struct hid_device_info *root = NULL; /* return object */
365 struct hid_device_info *cur_dev = NULL;
366 struct hid_device_info *prev_dev = NULL; /* previous device */
367
368 hid_init();
369
370 /* Create the udev object */
371 udev = udev_new();
372 if (!udev) {
373 printf("Can't create udev\n");
374 return NULL;
375 }
376
377 /* Create a list of the devices in the 'hidraw' subsystem. */
378 enumerate = udev_enumerate_new(udev);
379 udev_enumerate_add_match_subsystem(enumerate, "hidraw");
380 udev_enumerate_scan_devices(enumerate);
381 devices = udev_enumerate_get_list_entry(enumerate);
382 /* For each item, see if it matches the vid/pid, and if so
383 create a udev_device record for it */
384 udev_list_entry_foreach(dev_list_entry, devices) {
385 const char *sysfs_path;
386 const char *dev_path;
387 const char *str;
388 struct udev_device *raw_dev; /* The device's hidraw udev node. * /
389 struct udev_device *hid_dev; /* The device's HID udev node. */
390 struct udev_device *usb_dev; /* The device's USB udev node. */
391 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */
392 unsigned short dev_vid;
393 unsigned short dev_pid;
394 char *serial_number_utf8 = NULL;
395 char *product_name_utf8 = NULL;
396 int bus_type;
397 int result;
398
399 /* Get the filename of the /sys entry for the device
400 and create a udev_device object (dev) representing it */
401 sysfs_path = udev_list_entry_get_name(dev_list_entry);
402 raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
403 dev_path = udev_device_get_devnode(raw_dev);
404
405 hid_dev = udev_device_get_parent_with_subsystem_devtype(
406 raw_dev,
407 "hid",
408 NULL);
409
410 if (!hid_dev) {
411 /* Unable to find parent hid device. */
412 goto next;
413 }
414
415 result = parse_uevent_info(
416 udev_device_get_sysattr_value(hid_dev, "uevent"),
417 &bus_type,
418 &dev_vid,
419 &dev_pid,
420 &serial_number_utf8,
421 &product_name_utf8);
422
423 if (!result) {
424 /* parse_uevent_info() failed for at least one field. */
425 goto next;
426 }
427
428 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
429 /* We only know how to handle USB and BT devices. */
430 goto next;
431 }
432
433 /* Check the VID/PID against the arguments */
434 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
435 (product_id == 0x0 || product_id == dev_pid)) {
436 struct hid_device_info *tmp;
437
438 /* VID/PID match. Create the record. */
439 tmp = malloc(sizeof(struct hid_device_info));
Kees Cook 2013/12/04 20:49:36 Check for NULL return.
Bei Zhang 2013/12/10 22:24:11 Done.
440 if (cur_dev) {
441 cur_dev->next = tmp;
442 }
443 else {
444 root = tmp;
445 }
446 prev_dev = cur_dev;
447 cur_dev = tmp;
448
449 /* Fill out the record */
450 cur_dev->next = NULL;
451 cur_dev->path = dev_path? strdup(dev_path): NULL;
452
453 /* VID/PID */
454 cur_dev->vendor_id = dev_vid;
455 cur_dev->product_id = dev_pid;
456
457 /* Serial Number */
458 cur_dev->serial_number = utf8_to_wchar_t(serial_number_u tf8);
459
460 /* Release Number */
461 cur_dev->release_number = 0x0;
462
463 /* Interface Number */
464 cur_dev->interface_number = -1;
465
466 switch (bus_type) {
467 case BUS_USB:
468 /* The device pointed to by raw_dev cont ains information about
469 the hidraw device. In order to get in formation about the
470 USB device, get the parent device wit h the
471 subsystem/devtype pair of "usb"/"usb_ device". This will
472 be several levels up the tree, but th e function will find
473 it. */
474 usb_dev = udev_device_get_parent_with_su bsystem_devtype(
475 raw_dev,
476 "usb",
477 "usb_device");
478
479 if (!usb_dev) {
480 /* Free this device */
481 free(cur_dev->serial_number);
482 free(cur_dev->path);
483 free(cur_dev);
484
485 /* Take it off the device list. */
486 if (prev_dev) {
487 prev_dev->next = NULL;
488 cur_dev = prev_dev;
489 }
490 else {
491 cur_dev = root = NULL;
492 }
493
494 goto next;
495 }
496
497 /* Manufacturer and Product strings */
498 cur_dev->manufacturer_string = copy_udev _string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
499 cur_dev->product_string = copy_udev_stri ng(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
500
501 /* Release Number */
502 str = udev_device_get_sysattr_value(usb_ dev, "bcdDevice");
503 cur_dev->release_number = (str)? strtol( str, NULL, 16): 0x0;
504
505 /* Get a handle to the interface's udev node. */
506 intf_dev = udev_device_get_parent_with_s ubsystem_devtype(
507 raw_dev,
508 "usb",
509 "usb_interface");
510 if (intf_dev) {
511 str = udev_device_get_sysattr_va lue(intf_dev, "bInterfaceNumber");
512 cur_dev->interface_number = (str )? strtol(str, NULL, 16): -1;
513 }
514
515 break;
516
517 case BUS_BLUETOOTH:
518 /* Manufacturer and Product strings */
519 cur_dev->manufacturer_string = wcsdup(L" ");
520 cur_dev->product_string = utf8_to_wchar_ t(product_name_utf8);
521
522 break;
523
524 default:
525 /* Unknown device type - this should nev er happen, as we
526 * check for USB and Bluetooth devices a bove */
527 break;
528 }
529 }
530
531 next:
532 free(serial_number_utf8);
533 free(product_name_utf8);
534 udev_device_unref(raw_dev);
535 /* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
536 unref()d. It will cause a double-free() error. I'm not
537 sure why. */
538 }
539 /* Free the enumerator and udev objects. */
540 udev_enumerate_unref(enumerate);
541 udev_unref(udev);
542
543 return root;
544 }
545
546 void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
547 {
548 struct hid_device_info *d = devs;
549 while (d) {
550 struct hid_device_info *next = d->next;
551 free(d->path);
552 free(d->serial_number);
553 free(d->manufacturer_string);
554 free(d->product_string);
555 free(d);
556 d = next;
557 }
558 }
559
560 hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
561 {
562 struct hid_device_info *devs, *cur_dev;
563 const char *path_to_open = NULL;
564 hid_device *handle = NULL;
565
566 devs = hid_enumerate(vendor_id, product_id);
567 cur_dev = devs;
568 while (cur_dev) {
569 if (cur_dev->vendor_id == vendor_id &&
570 cur_dev->product_id == product_id) {
571 if (serial_number) {
572 if (wcscmp(serial_number, cur_dev->serial_number ) == 0) {
573 path_to_open = cur_dev->path;
574 break;
575 }
576 }
577 else {
578 path_to_open = cur_dev->path;
579 break;
580 }
581 }
582 cur_dev = cur_dev->next;
583 }
584
585 if (path_to_open) {
586 /* Open the device */
587 handle = hid_open_path(path_to_open);
588 }
589
590 hid_free_enumeration(devs);
591
592 return handle;
593 }
594
595 hid_device * HID_API_EXPORT hid_open_path(const char *path)
596 {
597 hid_device *dev = NULL;
598
599 hid_init();
600
601 dev = new_hid_device();
602
603 if (kernel_version == 0) {
604 struct utsname name;
605 int major, minor, release;
606 int ret;
607 uname(&name);
608 ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release) ;
609 if (ret == 3) {
610 kernel_version = major << 16 | minor << 8 | release;
611 //printf("Kernel Version: %d\n", kernel_version);
612 }
613 else {
614 printf("Couldn't sscanf() version string %s\n", name.rel ease);
615 }
616 }
617
618 /* OPEN HERE */
619 dev->device_handle = open(path, O_RDWR);
620
621 /* If we have a good handle, return it. */
622 if (dev->device_handle > 0) {
623
624 /* Get the report descriptor */
625 int res, desc_size = 0;
626 struct hidraw_report_descriptor rpt_desc;
627
628 memset(&rpt_desc, 0x0, sizeof(rpt_desc));
629
630 /* Get Report Descriptor Size */
631 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
632 if (res < 0)
633 perror("HIDIOCGRDESCSIZE");
Kees Cook 2013/12/04 20:49:36 Reports failure but continues execution? desc_size
Bei Zhang 2013/12/10 22:24:11 Done. Hidapi supports devices that does not contai
634
635
636 /* Get Report Descriptor */
637 rpt_desc.size = desc_size;
638 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
639 if (res < 0) {
640 perror("HIDIOCGRDESC");
641 } else {
642 /* Determine if this device uses numbered reports. */
643 dev->uses_numbered_reports =
644 uses_numbered_reports(rpt_desc.value,
645 rpt_desc.size);
646 }
647
648 return dev;
649 }
650 else {
651 /* Unable to open any devices. */
652 free(dev);
653 return NULL;
654 }
655 }
656
657
658 int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
659 {
660 int bytes_written;
661
662 bytes_written = write(dev->device_handle, data, length);
663
664 return bytes_written;
665 }
666
667
668 int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
669 {
670 int bytes_read;
671
672 if (milliseconds >= 0) {
673 /* Milliseconds is either 0 (non-blocking) or > 0 (contains
674 a valid timeout). In both cases we want to call poll()
675 and wait for data to arrive. Don't rely on non-blocking
676 operation (O_NONBLOCK) since some kernels don't seem to
677 properly report device disconnection through read() when
678 in non-blocking mode. */
679 int ret;
680 struct pollfd fds;
681
682 fds.fd = dev->device_handle;
683 fds.events = POLLIN;
684 fds.revents = 0;
685 ret = poll(&fds, 1, milliseconds);
686 if (ret == -1 || ret == 0) {
687 /* Error or timeout */
688 return ret;
689 }
690 else {
691 /* Check for errors on the file descriptor. This will
692 indicate a device disconnection. */
693 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
694 return -1;
695 }
696 }
697
698 bytes_read = read(dev->device_handle, data, length);
699 if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
700 bytes_read = 0;
701
702 if (bytes_read >= 0 &&
Kees Cook 2013/12/04 20:49:36 This needs to be > 0, otherwise bytes_read-- will
Bei Zhang 2013/12/10 22:24:11 Done.
703 kernel_version < KERNEL_VERSION(2,6,34) &&
704 dev->uses_numbered_reports) {
705 /* Work around a kernel bug. Chop off the first byte. */
706 memmove(data, data+1, bytes_read);
707 bytes_read--;
708 }
709
710 return bytes_read;
711 }
712
713 int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
714 {
715 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
716 }
717
718 int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
719 {
720 /* Do all non-blocking in userspace using poll(), since it looks
721 like there's a bug in the kernel in some versions where
722 read() will not return -1 on disconnection of the USB device */
723
724 dev->blocking = !nonblock;
725 return 0; /* Success */
726 }
727
728
729 int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
730 {
731 int res;
732
733 res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
734 if (res < 0)
735 perror("ioctl (SFEATURE)");
736
737 return res;
738 }
739
740 int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
741 {
742 int res;
743
744 res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
745 if (res < 0)
746 perror("ioctl (GFEATURE)");
747
748
749 return res;
750 }
751
752
753 void HID_API_EXPORT hid_close(hid_device *dev)
754 {
755 if (!dev)
756 return;
757 close(dev->device_handle);
758 free(dev);
759 }
760
761
762 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *st ring, size_t maxlen)
763 {
764 return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen );
765 }
766
767 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
768 {
769 return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen);
770 }
771
772 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s tring, size_t maxlen)
773 {
774 return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen);
775 }
776
777 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index , wchar_t *string, size_t maxlen)
778 {
779 return -1;
780 }
781
782
783 HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
784 {
785 return NULL;
786 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698