Include hidapi library
[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 /* 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 __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
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(). */
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.*/
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. */
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
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
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         ret = fstat(dev->device_handle, &s);
278         if (-1 == ret)
279                 return ret;
280         /* Open a udev device from the dev_t. 'c' means character device. */
281         udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
282         if (udev_dev) {
283                 hid_dev = udev_device_get_parent_with_subsystem_devtype(
284                         udev_dev,
285                         "hid",
286                         NULL);
287                 if (hid_dev) {
288                         unsigned short dev_vid;
289                         unsigned short dev_pid;
290                         int bus_type;
291                         size_t retm;
292
293                         ret = parse_uevent_info(
294                                    udev_device_get_sysattr_value(hid_dev, "uevent"),
295                                    &bus_type,
296                                    &dev_vid,
297                                    &dev_pid,
298                                    &serial_number_utf8,
299                                    &product_name_utf8);
300
301                         if (bus_type == BUS_BLUETOOTH) {
302                                 switch (key) {
303                                         case DEVICE_STRING_MANUFACTURER:
304                                                 wcsncpy(string, L"", maxlen);
305                                                 ret = 0;
306                                                 break;
307                                         case DEVICE_STRING_PRODUCT:
308                                                 retm = mbstowcs(string, product_name_utf8, maxlen);
309                                                 ret = (retm == (size_t)-1)? -1: 0;
310                                                 break;
311                                         case DEVICE_STRING_SERIAL:
312                                                 retm = mbstowcs(string, serial_number_utf8, maxlen);
313                                                 ret = (retm == (size_t)-1)? -1: 0;
314                                                 break;
315                                         case DEVICE_STRING_COUNT:
316                                         default:
317                                                 ret = -1;
318                                                 break;
319                                 }
320                         }
321                         else {
322                                 /* This is a USB device. Find its parent USB Device node. */
323                                 parent = udev_device_get_parent_with_subsystem_devtype(
324                                            udev_dev,
325                                            "usb",
326                                            "usb_device");
327                                 if (parent) {
328                                         const char *str;
329                                         const char *key_str = NULL;
330
331                                         if (key >= 0 && key < DEVICE_STRING_COUNT) {
332                                                 key_str = device_string_names[key];
333                                         } else {
334                                                 ret = -1;
335                                                 goto end;
336                                         }
337
338                                         str = udev_device_get_sysattr_value(parent, key_str);
339                                         if (str) {
340                                                 /* Convert the string from UTF-8 to wchar_t */
341                                                 retm = mbstowcs(string, str, maxlen);
342                                                 ret = (retm == (size_t)-1)? -1: 0;
343                                                 goto end;
344                                         }
345                                 }
346                         }
347                 }
348         }
349
350 end:
351         free(serial_number_utf8);
352         free(product_name_utf8);
353
354         udev_device_unref(udev_dev);
355         /* parent and hid_dev don't need to be (and can't be) unref'd.
356            I'm not sure why, but they'll throw double-free() errors. */
357         udev_unref(udev);
358
359         return ret;
360 }
361
362 int HID_API_EXPORT hid_init(void)
363 {
364         const char *locale;
365
366         /* Set the locale if it's not set. */
367         locale = setlocale(LC_CTYPE, NULL);
368         if (!locale)
369                 setlocale(LC_CTYPE, "");
370
371         kernel_version = detect_kernel_version();
372
373         return 0;
374 }
375
376 int HID_API_EXPORT hid_exit(void)
377 {
378         /* Nothing to do for this in the Linux/hidraw implementation. */
379         return 0;
380 }
381
382
383 struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
384 {
385         struct udev *udev;
386         struct udev_enumerate *enumerate;
387         struct udev_list_entry *devices, *dev_list_entry;
388
389         struct hid_device_info *root = NULL; /* return object */
390         struct hid_device_info *cur_dev = NULL;
391         struct hid_device_info *prev_dev = NULL; /* previous device */
392
393         hid_init();
394
395         /* Create the udev object */
396         udev = udev_new();
397         if (!udev) {
398                 printf("Can't create udev\n");
399                 return NULL;
400         }
401
402         /* Create a list of the devices in the 'hidraw' subsystem. */
403         enumerate = udev_enumerate_new(udev);
404         udev_enumerate_add_match_subsystem(enumerate, "hidraw");
405         udev_enumerate_scan_devices(enumerate);
406         devices = udev_enumerate_get_list_entry(enumerate);
407         /* For each item, see if it matches the vid/pid, and if so
408            create a udev_device record for it */
409         udev_list_entry_foreach(dev_list_entry, devices) {
410                 const char *sysfs_path;
411                 const char *dev_path;
412                 const char *str;
413                 struct udev_device *raw_dev; /* The device's hidraw udev node. */
414                 struct udev_device *hid_dev; /* The device's HID udev node. */
415                 struct udev_device *usb_dev; /* The device's USB udev node. */
416                 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */
417                 unsigned short dev_vid;
418                 unsigned short dev_pid;
419                 char *serial_number_utf8 = NULL;
420                 char *product_name_utf8 = NULL;
421                 int bus_type;
422                 int result;
423
424                 /* Get the filename of the /sys entry for the device
425                    and create a udev_device object (dev) representing it */
426                 sysfs_path = udev_list_entry_get_name(dev_list_entry);
427                 raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
428                 dev_path = udev_device_get_devnode(raw_dev);
429
430                 hid_dev = udev_device_get_parent_with_subsystem_devtype(
431                         raw_dev,
432                         "hid",
433                         NULL);
434
435                 if (!hid_dev) {
436                         /* Unable to find parent hid device. */
437                         goto next;
438                 }
439
440                 result = parse_uevent_info(
441                         udev_device_get_sysattr_value(hid_dev, "uevent"),
442                         &bus_type,
443                         &dev_vid,
444                         &dev_pid,
445                         &serial_number_utf8,
446                         &product_name_utf8);
447
448                 if (!result) {
449                         /* parse_uevent_info() failed for at least one field. */
450                         goto next;
451                 }
452
453                 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
454                         /* We only know how to handle USB and BT devices. */
455                         goto next;
456                 }
457
458                 /* Check the VID/PID against the arguments */
459                 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
460                     (product_id == 0x0 || product_id == dev_pid)) {
461                         struct hid_device_info *tmp;
462
463                         /* VID/PID match. Create the record. */
464                         tmp = malloc(sizeof(struct hid_device_info));
465                         if (cur_dev) {
466                                 cur_dev->next = tmp;
467                         }
468                         else {
469                                 root = tmp;
470                         }
471                         prev_dev = cur_dev;
472                         cur_dev = tmp;
473
474                         /* Fill out the record */
475                         cur_dev->next = NULL;
476                         cur_dev->path = dev_path? strdup(dev_path): NULL;
477
478                         /* VID/PID */
479                         cur_dev->vendor_id = dev_vid;
480                         cur_dev->product_id = dev_pid;
481
482                         /* Serial Number */
483                         cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8);
484
485                         /* Release Number */
486                         cur_dev->release_number = 0x0;
487
488                         /* Interface Number */
489                         cur_dev->interface_number = -1;
490
491                         switch (bus_type) {
492                                 case BUS_USB:
493                                         /* The device pointed to by raw_dev contains information about
494                                            the hidraw device. In order to get information about the
495                                            USB device, get the parent device with the
496                                            subsystem/devtype pair of "usb"/"usb_device". This will
497                                            be several levels up the tree, but the function will find
498                                            it. */
499                                         usb_dev = udev_device_get_parent_with_subsystem_devtype(
500                                                         raw_dev,
501                                                         "usb",
502                                                         "usb_device");
503
504                                         if (!usb_dev) {
505                                                 /* Free this device */
506                                                 free(cur_dev->serial_number);
507                                                 free(cur_dev->path);
508                                                 free(cur_dev);
509
510                                                 /* Take it off the device list. */
511                                                 if (prev_dev) {
512                                                         prev_dev->next = NULL;
513                                                         cur_dev = prev_dev;
514                                                 }
515                                                 else {
516                                                         cur_dev = root = NULL;
517                                                 }
518
519                                                 goto next;
520                                         }
521
522                                         /* Manufacturer and Product strings */
523                                         cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
524                                         cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
525
526                                         /* Release Number */
527                                         str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
528                                         cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
529
530                                         /* Get a handle to the interface's udev node. */
531                                         intf_dev = udev_device_get_parent_with_subsystem_devtype(
532                                                         raw_dev,
533                                                         "usb",
534                                                         "usb_interface");
535                                         if (intf_dev) {
536                                                 str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
537                                                 cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
538                                         }
539
540                                         break;
541
542                                 case BUS_BLUETOOTH:
543                                         /* Manufacturer and Product strings */
544                                         cur_dev->manufacturer_string = wcsdup(L"");
545                                         cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
546
547                                         break;
548
549                                 default:
550                                         /* Unknown device type - this should never happen, as we
551                                          * check for USB and Bluetooth devices above */
552                                         break;
553                         }
554                 }
555
556         next:
557                 free(serial_number_utf8);
558                 free(product_name_utf8);
559                 udev_device_unref(raw_dev);
560                 /* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
561                    unref()d.  It will cause a double-free() error.  I'm not
562                    sure why.  */
563         }
564         /* Free the enumerator and udev objects. */
565         udev_enumerate_unref(enumerate);
566         udev_unref(udev);
567
568         return root;
569 }
570
571 void  HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
572 {
573         struct hid_device_info *d = devs;
574         while (d) {
575                 struct hid_device_info *next = d->next;
576                 free(d->path);
577                 free(d->serial_number);
578                 free(d->manufacturer_string);
579                 free(d->product_string);
580                 free(d);
581                 d = next;
582         }
583 }
584
585 hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
586 {
587         struct hid_device_info *devs, *cur_dev;
588         const char *path_to_open = NULL;
589         hid_device *handle = NULL;
590
591         devs = hid_enumerate(vendor_id, product_id);
592         cur_dev = devs;
593         while (cur_dev) {
594                 if (cur_dev->vendor_id == vendor_id &&
595                     cur_dev->product_id == product_id) {
596                         if (serial_number) {
597                                 if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
598                                         path_to_open = cur_dev->path;
599                                         break;
600                                 }
601                         }
602                         else {
603                                 path_to_open = cur_dev->path;
604                                 break;
605                         }
606                 }
607                 cur_dev = cur_dev->next;
608         }
609
610         if (path_to_open) {
611                 /* Open the device */
612                 handle = hid_open_path(path_to_open);
613         }
614
615         hid_free_enumeration(devs);
616
617         return handle;
618 }
619
620 hid_device * HID_API_EXPORT hid_open_path(const char *path)
621 {
622         hid_device *dev = NULL;
623
624         hid_init();
625
626         dev = new_hid_device();
627
628         /* OPEN HERE */
629         dev->device_handle = open(path, O_RDWR);
630
631         /* If we have a good handle, return it. */
632         if (dev->device_handle > 0) {
633
634                 /* Get the report descriptor */
635                 int res, desc_size = 0;
636                 struct hidraw_report_descriptor rpt_desc;
637
638                 memset(&rpt_desc, 0x0, sizeof(rpt_desc));
639
640                 /* Get Report Descriptor Size */
641                 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
642                 if (res < 0)
643                         perror("HIDIOCGRDESCSIZE");
644
645
646                 /* Get Report Descriptor */
647                 rpt_desc.size = desc_size;
648                 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
649                 if (res < 0) {
650                         perror("HIDIOCGRDESC");
651                 } else {
652                         /* Determine if this device uses numbered reports. */
653                         dev->uses_numbered_reports =
654                                 uses_numbered_reports(rpt_desc.value,
655                                                       rpt_desc.size);
656                 }
657
658                 return dev;
659         }
660         else {
661                 /* Unable to open any devices. */
662                 free(dev);
663                 return NULL;
664         }
665 }
666
667
668 int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
669 {
670         int bytes_written;
671
672         bytes_written = write(dev->device_handle, data, length);
673
674         return bytes_written;
675 }
676
677
678 int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
679 {
680         int bytes_read;
681
682         if (milliseconds >= 0) {
683                 /* Milliseconds is either 0 (non-blocking) or > 0 (contains
684                    a valid timeout). In both cases we want to call poll()
685                    and wait for data to arrive.  Don't rely on non-blocking
686                    operation (O_NONBLOCK) since some kernels don't seem to
687                    properly report device disconnection through read() when
688                    in non-blocking mode.  */
689                 int ret;
690                 struct pollfd fds;
691
692                 fds.fd = dev->device_handle;
693                 fds.events = POLLIN;
694                 fds.revents = 0;
695                 ret = poll(&fds, 1, milliseconds);
696                 if (ret == -1 || ret == 0) {
697                         /* Error or timeout */
698                         return ret;
699                 }
700                 else {
701                         /* Check for errors on the file descriptor. This will
702                            indicate a device disconnection. */
703                         if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
704                                 return -1;
705                 }
706         }
707
708         bytes_read = read(dev->device_handle, data, length);
709         if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
710                 bytes_read = 0;
711
712         if (bytes_read >= 0 &&
713             kernel_version != 0 &&
714             kernel_version < KERNEL_VERSION(2,6,34) &&
715             dev->uses_numbered_reports) {
716                 /* Work around a kernel bug. Chop off the first byte. */
717                 memmove(data, data+1, bytes_read);
718                 bytes_read--;
719         }
720
721         return bytes_read;
722 }
723
724 int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
725 {
726         return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
727 }
728
729 int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
730 {
731         /* Do all non-blocking in userspace using poll(), since it looks
732            like there's a bug in the kernel in some versions where
733            read() will not return -1 on disconnection of the USB device */
734
735         dev->blocking = !nonblock;
736         return 0; /* Success */
737 }
738
739
740 int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
741 {
742         int res;
743
744         res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
745         if (res < 0)
746                 perror("ioctl (SFEATURE)");
747
748         return res;
749 }
750
751 int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
752 {
753         int res;
754
755         res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
756         if (res < 0)
757                 perror("ioctl (GFEATURE)");
758
759
760         return res;
761 }
762
763
764 void HID_API_EXPORT hid_close(hid_device *dev)
765 {
766         if (!dev)
767                 return;
768         close(dev->device_handle);
769         free(dev);
770 }
771
772
773 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
774 {
775         return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen);
776 }
777
778 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
779 {
780         return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen);
781 }
782
783 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
784 {
785         return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen);
786 }
787
788 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
789 {
790         return -1;
791 }
792
793
794 HID_API_EXPORT const wchar_t * HID_API_CALL  hid_error(hid_device *dev)
795 {
796         return NULL;
797 }