1
/*******************************************************
2
HIDAPI - Multi-Platform library for
3
communication with HID devices.
9
Linux Version - 6/2/2009
11
Copyright 2009, All Rights Reserved.
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
********************************************************/
33
#include <sys/types.h>
35
#include <sys/ioctl.h>
36
#include <sys/utsname.h>
41
#include <linux/hidraw.h>
42
#include <linux/version.h>
47
/* Definitions from linux/hidraw.h. Since these are new, some distros
48
may not have header files which contain them. */
49
#ifndef HIDIOCSFEATURE
50
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
52
#ifndef HIDIOCGFEATURE
53
#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
59
int uses_numbered_reports;
63
static __u32 kernel_version = 0;
65
hid_device *new_hid_device()
67
hid_device *dev = calloc(1, sizeof(hid_device));
68
dev->device_handle = -1;
70
dev->uses_numbered_reports = 0;
75
static void register_error(hid_device *device, const char *op)
80
/* Get an attribute value from a udev_device and return it as a whar_t
81
string. The returned string must be freed with free() when done.*/
82
static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
86
str = udev_device_get_sysattr_value(dev, udev_name);
88
/* Convert the string from UTF-8 to wchar_t */
89
size_t wlen = mbstowcs(NULL, str, 0);
90
ret = calloc(wlen+1, sizeof(wchar_t));
91
mbstowcs(ret, str, wlen+1);
98
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
99
which contains numbered reports. */
100
static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
103
int data_len, key_size;
106
int key = report_descriptor[i];
108
/* Check for the Report ID key */
109
if (key == 0x85/*Report ID*/) {
110
/* This device has a Report ID, which means it uses
115
//printf("key: %02hhx\n", key);
117
if ((key & 0xf0) == 0xf0) {
118
/* This is a Long Item. The next byte contains the
119
length of the data section (value) for this key.
120
See the HID specification, version 1.11, section
121
6.2.2.3, titled "Long Items." */
123
data_len = report_descriptor[i+1];
125
data_len = 0; /* malformed report */
129
/* This is a Short Item. The bottom two bits of the
130
key contain the size code for the data section
131
(value) for this key. Refer to the HID
132
specification, version 1.11, section 6.2.2.2,
133
titled "Short Items." */
134
size_code = key & 0x3;
139
data_len = size_code;
145
/* Can't ever happen since size_code is & 0x3 */
152
/* Skip over this key and it's associated data */
153
i += data_len + key_size;
156
/* Didn't find a Report ID key. Device doesn't use numbered reports. */
160
static int get_device_string(hid_device *dev, const char *key, wchar_t *string, size_t maxlen)
163
struct udev_device *udev_dev, *parent;
167
setlocale(LC_ALL,"");
169
/* Create the udev object */
172
printf("Can't create udev\n");
176
/* Get the dev_t (major/minor numbers) from the file handle. */
177
fstat(dev->device_handle, &s);
178
/* Open a udev device from the dev_t. 'c' means character device. */
179
udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
182
/* Find the parent USB Device */
183
parent = udev_device_get_parent_with_subsystem_devtype(
188
str = udev_device_get_sysattr_value(parent, key);
190
/* Convert the string from UTF-8 to wchar_t */
191
ret = mbstowcs(string, str, maxlen);
198
udev_device_unref(udev_dev);
199
// parent doesn't need to be (and can't be) unref'd.
200
// I'm not sure why, but it'll throw double-free() errors.
206
int HID_API_EXPORT hid_init(void)
208
/* Nothing to do for this in the Linux/hidraw implementation. */
212
int HID_API_EXPORT hid_exit(void)
214
/* Nothing to do for this in the Linux/hidraw implementation. */
218
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
221
struct udev_enumerate *enumerate;
222
struct udev_list_entry *devices, *dev_list_entry;
224
struct hid_device_info *root = NULL; // return object
225
struct hid_device_info *cur_dev = NULL;
227
setlocale(LC_ALL,"");
229
/* Create the udev object */
232
printf("Can't create udev\n");
236
/* Create a list of the devices in the 'hidraw' subsystem. */
237
enumerate = udev_enumerate_new(udev);
238
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
239
udev_enumerate_scan_devices(enumerate);
240
devices = udev_enumerate_get_list_entry(enumerate);
241
/* For each item, see if it matches the vid/pid, and if so
242
create a udev_device record for it */
243
udev_list_entry_foreach(dev_list_entry, devices) {
244
const char *sysfs_path;
245
const char *dev_path;
247
struct udev_device *hid_dev; // The device's HID udev node.
248
struct udev_device *dev; // The actual hardware device.
249
struct udev_device *intf_dev; // The device's interface (in the USB sense).
250
unsigned short dev_vid;
251
unsigned short dev_pid;
253
/* Get the filename of the /sys entry for the device
254
and create a udev_device object (dev) representing it */
255
sysfs_path = udev_list_entry_get_name(dev_list_entry);
256
hid_dev = udev_device_new_from_syspath(udev, sysfs_path);
257
dev_path = udev_device_get_devnode(hid_dev);
259
/* The device pointed to by hid_dev contains information about
260
the hidraw device. In order to get information about the
261
USB device, get the parent device with the
262
subsystem/devtype pair of "usb"/"usb_device". This will
263
be several levels up the tree, but the function will find
265
dev = udev_device_get_parent_with_subsystem_devtype(
270
/* Unable to find parent usb device. */
274
/* Get the VID/PID of the device */
275
str = udev_device_get_sysattr_value(dev,"idVendor");
276
dev_vid = (str)? strtol(str, NULL, 16): 0x0;
277
str = udev_device_get_sysattr_value(dev, "idProduct");
278
dev_pid = (str)? strtol(str, NULL, 16): 0x0;
280
/* Check the VID/PID against the arguments */
281
if ((vendor_id == 0x0 && product_id == 0x0) ||
282
(vendor_id == dev_vid && product_id == dev_pid)) {
283
struct hid_device_info *tmp;
286
/* VID/PID match. Create the record. */
287
tmp = malloc(sizeof(struct hid_device_info));
296
/* Fill out the record */
297
cur_dev->next = NULL;
301
cur_dev->path = calloc(len+1, sizeof(char));
302
strncpy(cur_dev->path, str, len+1);
303
cur_dev->path[len] = '\0';
306
cur_dev->path = NULL;
309
cur_dev->serial_number
310
= copy_udev_string(dev, "serial");
312
/* Manufacturer and Product strings */
313
cur_dev->manufacturer_string
314
= copy_udev_string(dev, "manufacturer");
315
cur_dev->product_string
316
= copy_udev_string(dev, "product");
319
cur_dev->vendor_id = dev_vid;
320
cur_dev->product_id = dev_pid;
323
str = udev_device_get_sysattr_value(dev, "bcdDevice");
324
cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
326
/* Interface Number */
327
cur_dev->interface_number = -1;
328
/* Get a handle to the interface's udev node. */
329
intf_dev = udev_device_get_parent_with_subsystem_devtype(
334
str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
335
cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
342
udev_device_unref(hid_dev);
343
/* dev and intf_dev don't need to be (and can't be)
344
unref()d. It will cause a double-free() error. I'm not
347
/* Free the enumerator and udev objects. */
348
udev_enumerate_unref(enumerate);
354
void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
356
struct hid_device_info *d = devs;
358
struct hid_device_info *next = d->next;
360
free(d->serial_number);
361
free(d->manufacturer_string);
362
free(d->product_string);
368
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number)
370
struct hid_device_info *devs, *cur_dev;
371
const char *path_to_open = NULL;
372
hid_device *handle = NULL;
374
devs = hid_enumerate(vendor_id, product_id);
377
if (cur_dev->vendor_id == vendor_id &&
378
cur_dev->product_id == product_id) {
380
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
381
path_to_open = cur_dev->path;
386
path_to_open = cur_dev->path;
390
cur_dev = cur_dev->next;
394
/* Open the device */
395
handle = hid_open_path(path_to_open);
398
hid_free_enumeration(devs);
403
hid_device * HID_API_EXPORT hid_open_path(const char *path)
405
hid_device *dev = NULL;
407
dev = new_hid_device();
409
if (kernel_version == 0) {
411
int major, minor, release;
414
ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
416
kernel_version = major << 16 | minor << 8 | release;
417
//printf("Kernel Version: %d\n", kernel_version);
420
printf("Couldn't sscanf() version string %s\n", name.release);
425
dev->device_handle = open(path, O_RDWR);
427
// If we have a good handle, return it.
428
if (dev->device_handle > 0) {
430
/* Get the report descriptor */
431
int res, desc_size = 0;
432
struct hidraw_report_descriptor rpt_desc;
434
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
436
/* Get Report Descriptor Size */
437
res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
439
perror("HIDIOCGRDESCSIZE");
442
/* Get Report Descriptor */
443
rpt_desc.size = desc_size;
444
res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
446
perror("HIDIOCGRDESC");
448
/* Determine if this device uses numbered reports. */
449
dev->uses_numbered_reports =
450
uses_numbered_reports(rpt_desc.value,
457
// Unable to open any devices.
464
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
468
bytes_written = write(dev->device_handle, data, length);
470
return bytes_written;
474
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
478
if (milliseconds != 0) {
479
/* milliseconds is -1 or > 0. In both cases, we want to
480
call poll() and wait for data to arrive. -1 means
485
fds.fd = dev->device_handle;
488
ret = poll(&fds, 1, milliseconds);
489
if (ret == -1 || ret == 0)
490
/* Error or timeout */
494
bytes_read = read(dev->device_handle, data, length);
495
if (bytes_read < 0 && errno == EAGAIN)
498
if (bytes_read >= 0 &&
499
kernel_version < KERNEL_VERSION(2,6,34) &&
500
dev->uses_numbered_reports) {
501
/* Work around a kernel bug. Chop off the first byte. */
502
memmove(data, data+1, bytes_read);
509
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
511
return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
514
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
518
flags = fcntl(dev->device_handle, F_GETFL, 0);
521
res = fcntl(dev->device_handle, F_SETFL, flags | O_NONBLOCK);
523
res = fcntl(dev->device_handle, F_SETFL, flags & ~O_NONBLOCK);
532
dev->blocking = !nonblock;
533
return 0; /* Success */
538
int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
542
res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
544
perror("ioctl (SFEATURE)");
549
int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
553
res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
555
perror("ioctl (GFEATURE)");
562
void HID_API_EXPORT hid_close(hid_device *dev)
566
close(dev->device_handle);
571
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
573
return get_device_string(dev, "manufacturer", string, maxlen);
576
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
578
return get_device_string(dev, "product", string, maxlen);
581
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
583
return get_device_string(dev, "serial", string, maxlen);
586
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
592
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)