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