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