Subversion Repositories seema-scanner

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 jakw 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 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));
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));
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];
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++;
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_id, 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;
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, "uevent"),
272
			           &bus_type,
273
			           &dev_vid,
274
			           &dev_pid,
275
			           &serial_number_utf8,
276
			           &product_name_utf8);
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);
286
						ret = (retm == (size_t)-1)? -1: 0;
287
						break;
288
					case DEVICE_STRING_SERIAL:
289
						retm = mbstowcs(string, serial_number_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 Device node. */
300
				parent = udev_device_get_parent_with_subsystem_devtype(
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 >= 0 && key < DEVICE_STRING_COUNT) {
309
						key_str = device_string_names[key];
310
					} else {
311
						ret = -1;
312
						goto end;
313
					}
314
 
315
					str = udev_device_get_sysattr_value(parent, key_str);
316
					if (str) {
317
						/* Convert the string from UTF-8 to wchar_t */
318
						retm = mbstowcs(string, str, maxlen);
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);
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));
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_utf8);
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 contains information about
469
					   the hidraw device. In order to get information about the
470
					   USB device, get the parent device with the
471
					   subsystem/devtype pair of "usb"/"usb_device". This will
472
					   be several levels up the tree, but the function will find
473
					   it. */
474
					usb_dev = udev_device_get_parent_with_subsystem_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_string(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_subsystem_devtype(
507
							raw_dev,
508
							"usb",
509
							"usb_interface");
510
					if (intf_dev) {
511
						str = udev_device_get_sysattr_value(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 never happen, as we
526
					 * check for USB and Bluetooth devices above */
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.release);
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");
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 &&
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 *string, 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 *string, 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
}