1 /***********************************************************************
2 HIDAPI - Multi-Platform library for communication with HID devices.
3
4 hid_lin.cxx
5
6 Alan Ott
7 Signal 11 Software
8 Copyright 2009, All Rights Reserved.
9
10 C++ implementation
11 * Copyright 2021
12 * David Freese, W1HKJ
13 * for use in fldigi
14
15 This software is licensed under the terms of the GNU General Public
16 License v3.
17
18 ***********************************************************************/
19
20 #include <iostream>
21
22 /* C */
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <locale.h>
27 #include <errno.h>
28
29 /* Unix */
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/ioctl.h>
34 #include <sys/utsname.h>
35 #include <fcntl.h>
36 #include <poll.h>
37
38 /* Linux */
39 #include <linux/hidraw.h>
40 #include <linux/version.h>
41 #include <linux/input.h>
42 #include <libudev.h>
43
44 #include "hidapi.h"
45
46 /* Definitions from linux/hidraw.h. Since these are new, some distros
47 may not have header files which contain them. */
48 #ifndef HIDIOCSFEATURE
49 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
50 #endif
51 #ifndef HIDIOCGFEATURE
52 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
53 #endif
54
55
56 /* uses_numbered_reports() returns 1 if report_descriptor describes a device
57 which contains numbered reports. */
uses_numbered_reports(__u8 * report_descriptor,__u32 size)58 static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
59 unsigned int i = 0;
60 int size_code;
61 int data_len, key_size;
62
63 while (i < size) {
64 int key = report_descriptor[i];
65
66 /* Check for the Report ID key */
67 if (key == 0x85/*Report ID*/) {
68 /* This device has a Report ID, which means it uses
69 numbered reports. */
70 return 1;
71 }
72
73 //printf("key: %02hhx\n", key);
74
75 if ((key & 0xf0) == 0xf0) {
76 /* This is a Long Item. The next byte contains the
77 length of the data section (value) for this key.
78 See the HID specification, version 1.11, section
79 6.2.2.3, titled "Long Items." */
80 if (i+1 < size)
81 data_len = report_descriptor[i+1];
82 else
83 data_len = 0; /* malformed report */
84 key_size = 3;
85 }
86 else {
87 /* This is a Short Item. The bottom two bits of the
88 key contain the size code for the data section
89 (value) for this key. Refer to the HID
90 specification, version 1.11, section 6.2.2.2,
91 titled "Short Items." */
92 size_code = key & 0x3;
93 switch (size_code) {
94 case 0:
95 case 1:
96 case 2:
97 data_len = size_code;
98 break;
99 case 3:
100 data_len = 4;
101 break;
102 default:
103 /* Can't ever happen since size_code is & 0x3 */
104 data_len = 0;
105 break;
106 };
107 key_size = 1;
108 }
109
110 /* Skip over this key and it's associated data */
111 i += data_len + key_size;
112 }
113
114 /* Didn't find a Report ID key. Device doesn't use numbered reports. */
115 return 0;
116 }
117
118 /*
119 * The caller is responsible for free()ing the (newly-allocated) character
120 * strings pointed to by serial_number_utf8 and product_name_utf8 after use.
121 */
122 static int
parse_uevent_info(const char * uevent,int * bus_type,unsigned short * vendor_id,unsigned short * product_id,char ** serial_number_utf8,char ** product_name_utf8)123 parse_uevent_info(const char *uevent, int *bus_type,
124 unsigned short *vendor_id, unsigned short *product_id,
125 char **serial_number_utf8, char **product_name_utf8)
126 {
127 char *tmp = strdup(uevent);
128 char *saveptr = NULL;
129 char *line;
130 char *key;
131 char *value;
132
133 int found_id = 0;
134 int found_serial = 0;
135 int found_name = 0;
136
137 line = strtok_r(tmp, "\n", &saveptr);
138 while (line != NULL) {
139 /* line: "KEY=value" */
140 key = line;
141 value = strchr(line, '=');
142 if (!value) {
143 goto next_line;
144 }
145 *value = '\0';
146 value++;
147
148 if (strcmp(key, "HID_ID") == 0) {
149 /**
150 * type vendor product
151 * HID_ID=0003:000005AC:00008242
152 **/
153 int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id);
154 if (ret == 3) {
155 found_id = 1;
156 }
157 } else if (strcmp(key, "HID_NAME") == 0) {
158 /* The caller has to free the product name */
159 *product_name_utf8 = strdup(value);
160 found_name = 1;
161 } else if (strcmp(key, "HID_UNIQ") == 0) {
162 /* The caller has to free the serial number */
163 *serial_number_utf8 = strdup(value);
164 found_serial = 1;
165 }
166
167 next_line:
168 line = strtok_r(NULL, "\n", &saveptr);
169 }
170
171 free(tmp);
172 return (found_id && found_name && found_serial);
173 }
174
hid_init(void)175 int hid_init(void)
176 {
177 const char *locale;
178
179 /* Set the locale if it's not set. */
180 locale = setlocale(LC_CTYPE, NULL);
181 if (!locale)
182 setlocale(LC_CTYPE, "");
183
184 return 0;
185 }
186
hid_exit(void)187 int hid_exit(void)
188 {
189 /* Nothing to do for this in the Linux/hidraw implementation. */
190 return 0;
191 }
192
193
hid_enumerate(unsigned short vendor_id,unsigned short product_id)194 hid_device_info *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
195 {
196 struct udev *udev;
197 struct udev_enumerate *enumerate;
198 struct udev_list_entry *devices, *dev_list_entry;
199
200 hid_device_info *root = NULL; /* return object */
201 hid_device_info *cur_dev = NULL;
202 hid_device_info *prev_dev = NULL; /* previous device */
203
204 hid_init();
205
206 /* Create the udev object */
207 udev = udev_new();
208 if (!udev) {
209 printf("Can't create udev\n");
210 return NULL;
211 }
212
213 /* Create a list of the devices in the 'hidraw' subsystem. */
214 enumerate = udev_enumerate_new(udev);
215 udev_enumerate_add_match_subsystem(enumerate, "hidraw");
216 udev_enumerate_scan_devices(enumerate);
217 devices = udev_enumerate_get_list_entry(enumerate);
218 /* For each item, see if it matches the vid/pid, and if so
219 create a udev_device record for it */
220 udev_list_entry_foreach(dev_list_entry, devices) {
221 const char *sysfs_path;
222 const char *dev_path;
223 const char *str;
224 struct udev_device *raw_dev; /* The device's hidraw udev node. */
225 struct udev_device *hid_dev; /* The device's HID udev node. */
226 struct udev_device *usb_dev; /* The device's USB udev node. */
227 struct udev_device *intf_dev; /* The device's interface (in the USB sense). */
228 unsigned short dev_vid;
229 unsigned short dev_pid;
230 char *serial_number_utf8 = NULL;
231 char *product_name_utf8 = NULL;
232 int bus_type;
233 int result;
234
235 /* Get the filename of the /sys entry for the device
236 and create a udev_device object (dev) representing it */
237 sysfs_path = udev_list_entry_get_name(dev_list_entry);
238 raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
239 dev_path = udev_device_get_devnode(raw_dev);
240
241 hid_dev = udev_device_get_parent_with_subsystem_devtype(
242 raw_dev,
243 "hid",
244 NULL);
245
246 if (!hid_dev) {
247 /* Unable to find parent hid device. */
248 goto next;
249 }
250
251 result = parse_uevent_info(
252 udev_device_get_sysattr_value(hid_dev, "uevent"),
253 &bus_type,
254 &dev_vid,
255 &dev_pid,
256 &serial_number_utf8,
257 &product_name_utf8);
258
259 if (!result) {
260 /* parse_uevent_info() failed for at least one field. */
261 goto next;
262 }
263
264 if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
265 /* We only know how to handle USB and BT devices. */
266 goto next;
267 }
268
269 /* Check the VID/PID against the arguments */
270 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
271 (product_id == 0x0 || product_id == dev_pid)) {
272
273 hid_device_info *tmp = new hid_device_info;
274
275 if (cur_dev) {
276 cur_dev->next = tmp;
277 }
278 else {
279 root = tmp;
280 }
281 prev_dev = cur_dev;
282 cur_dev = tmp;
283
284 /* Fill out the record */
285 cur_dev->next = NULL;
286 cur_dev->path.assign(dev_path ? dev_path : "");
287
288 /* VID/PID */
289 cur_dev->vendor_id = dev_vid;
290 cur_dev->product_id = dev_pid;
291
292 /* Serial Number */
293 cur_dev->str_serial_number.assign(serial_number_utf8);
294
295 /* Release Number */
296 cur_dev->release_number = 0x0;
297
298 /* Interface Number */
299 cur_dev->interface_number = -1;
300
301 switch (bus_type) {
302 case BUS_USB:
303 /* The device pointed to by raw_dev contains information about
304 the hidraw device. In order to get information about the
305 USB device, get the parent device with the
306 subsystem/devtype pair of "usb"/"usb_device". This will
307 be several levels up the tree, but the function will find
308 it. */
309 usb_dev = udev_device_get_parent_with_subsystem_devtype(
310 raw_dev,
311 "usb",
312 "usb_device");
313
314 if (!usb_dev) {
315 delete cur_dev;
316
317 /* Take it off the device list. */
318 if (prev_dev) {
319 prev_dev->next = NULL;
320 cur_dev = prev_dev;
321 }
322 else {
323 cur_dev = root = NULL;
324 }
325
326 goto next;
327 }
328
329 /* Manufacturer and Product strings */
330 str = udev_device_get_sysattr_value(usb_dev, "manufacturer");
331 if (str) cur_dev->str_manufacturer_string.assign(str);
332
333 str = udev_device_get_sysattr_value(usb_dev, "product");
334 if (str) cur_dev->str_product_string.assign(str);
335
336 /* Release Number */
337 str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
338 if (str) cur_dev->release_number = strtol(str, NULL, 16);
339 else cur_dev = 0x0;
340
341 /* Get a handle to the interface's udev node. */
342 intf_dev = udev_device_get_parent_with_subsystem_devtype(
343 raw_dev,
344 "usb",
345 "usb_interface");
346 if (intf_dev) {
347 str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
348 cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
349 }
350
351 break;
352
353 case BUS_BLUETOOTH:
354 /* Manufacturer and Product strings */
355 cur_dev->str_product_string.assign(product_name_utf8);
356
357 break;
358
359 default:
360 /* Unknown device type - this should never happen, as we
361 * check for USB and Bluetooth devices above */
362 break;
363 }
364 }
365
366 next:
367 free(serial_number_utf8);
368 free(product_name_utf8);
369 udev_device_unref(raw_dev);
370 /* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
371 unref()d. It will cause a double-free() error. I'm not
372 sure why. */
373 }
374 /* Free the enumerator and udev objects. */
375 udev_enumerate_unref(enumerate);
376 udev_unref(udev);
377
378 return root;
379 }
380
hid_free_enumeration(hid_device_info * devs)381 void hid_free_enumeration(hid_device_info *devs)
382 {
383 hid_device_info *d = devs;
384 while (d) {
385 hid_device_info *next = d->next;
386 delete d;
387 d = next;
388 }
389 }
390
hid_open(unsigned short vendor_id,unsigned short product_id,std::string serial_number)391 hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, std::string serial_number)
392 {
393 hid_device_info *devs, *cur_dev;
394 hid_device *device = NULL;
395 std::string path_to_open;
396
397 devs = hid_enumerate(vendor_id, product_id);
398 cur_dev = devs;
399 while (cur_dev) {
400 if (cur_dev->vendor_id == vendor_id &&
401 cur_dev->product_id == product_id) {
402 if (!serial_number.empty() &&
403 (cur_dev->str_serial_number == serial_number) ) {
404 path_to_open = cur_dev->path;
405 break;
406 }
407 else {
408 path_to_open = cur_dev->path;
409 break;
410 }
411 }
412 cur_dev = cur_dev->next;
413 }
414
415 if (!path_to_open.empty()) {
416 /* Open the device */
417 device = hid_open_path(path_to_open);
418 }
419
420 hid_free_enumeration(devs);
421
422 return device;
423 }
424
hid_open_path(std::string path)425 hid_device * hid_open_path(std::string path)
426 {
427 hid_device *dev = new hid_device;
428
429 hid_init();
430
431 /* OPEN HERE */
432 dev->device_handle = open(path.c_str(), O_RDWR);
433
434 /* If we have a good handle, return it. */
435 if (dev->device_handle > 0) {
436
437 /* Get the report descriptor */
438 int res, desc_size = 0;
439 struct hidraw_report_descriptor rpt_desc;
440
441 memset(&rpt_desc, 0x0, sizeof(rpt_desc));
442
443 /* Get Report Descriptor Size */
444 res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
445 if (res < 0)
446 perror("HIDIOCGRDESCSIZE");
447
448
449 /* Get Report Descriptor */
450 rpt_desc.size = desc_size;
451 res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
452 if (res < 0) {
453 perror("HIDIOCGRDESC");
454 } else {
455 /* Determine if this device uses numbered reports. */
456 dev->uses_numbered_reports =
457 uses_numbered_reports(rpt_desc.value,
458 rpt_desc.size);
459 }
460
461 return dev;
462 }
463 else {
464 /* Unable to open any devices. */
465 delete dev;
466 return (hid_device *)0;
467 }
468 }
469
470
hid_write(const unsigned char * data,size_t length)471 int hid_device::hid_write(const unsigned char *data, size_t length)
472 {
473 int bytes_written;
474 bytes_written = write(device_handle, data, length);
475 return bytes_written;
476 }
477
478
hid_read_timeout(unsigned char * data,size_t length,int milliseconds)479 int hid_device::hid_read_timeout(unsigned char *data, size_t length, int milliseconds)
480 {
481 int bytes_read;
482
483 if (milliseconds >= 0) {
484 /* Milliseconds is either 0 (non-blocking) or > 0 (contains
485 a valid timeout). In both cases we want to call poll()
486 and wait for data to arrive. Don't rely on non-blocking
487 operation (O_NONBLOCK) since some kernels don't seem to
488 properly report device disconnection through read() when
489 in non-blocking mode. */
490 int ret;
491 struct pollfd fds;
492
493 fds.fd = device_handle;
494 fds.events = POLLIN;
495 fds.revents = 0;
496 ret = poll(&fds, 1, milliseconds);
497 if (ret == -1 || ret == 0) {
498 /* Error or timeout */
499 return ret;
500 }
501 else {
502 /* Check for errors on the file descriptor. This will
503 indicate a device disconnection. */
504 if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
505 return -1;
506 }
507 }
508
509 bytes_read = read(device_handle, data, length);
510 if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
511 bytes_read = 0;
512
513 return bytes_read;
514 }
515
hid_read(unsigned char * data,size_t length)516 int hid_device::hid_read(unsigned char *data, size_t length)
517 {
518 return hid_read_timeout(data, length, (blocking)? -1: 0);
519 }
520
hid_set_nonblocking(int nonblock)521 int hid_device::hid_set_nonblocking(int nonblock)
522 {
523 /* Do all non-blocking in userspace using poll(), since it looks
524 like there's a bug in the kernel in some versions where
525 read() will not return -1 on disconnection of the USB device */
526 blocking = !nonblock;
527 return 0; /* Success */
528 }
529
530
hid_send_feature_report(const unsigned char * data,size_t length)531 int hid_device::hid_send_feature_report(const unsigned char *data, size_t length)
532 {
533 int res;
534 res = ioctl(device_handle, HIDIOCSFEATURE(length), data);
535 if (res < 0)
536 perror("ioctl (SFEATURE)");
537 return res;
538 }
539
hid_get_feature_report(unsigned char * data,size_t length)540 int hid_device::hid_get_feature_report(unsigned char *data, size_t length)
541 {
542 int res;
543
544 res = ioctl(device_handle, HIDIOCGFEATURE(length), data);
545 if (res < 0)
546 perror("ioctl (GFEATURE)");
547
548 return res;
549 }
550
551
hid_close()552 void hid_device::hid_close()
553 {
554 close(device_handle);
555 }
556
557
hid_error()558 const char *hid_device::hid_error()
559 {
560 return "HID error string not implemented";
561 }
562
563