From 60fe249ba6002242df014905e6a52b3b20b96b83 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Fri, 29 Apr 2011 23:03:49 +0300 Subject: [PATCH] hiddev: Add support for opening hid devices by vendor and product IDs. Signed-off-by: Timo Kokkonen --- hiddev.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- hiddev.h | 1 + 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/hiddev.c b/hiddev.c index b442019..7cf7239 100644 --- a/hiddev.c +++ b/hiddev.c @@ -2,16 +2,20 @@ #include #include #include +#include #include #include #include #include +#include #include "hiddev.h" #include "utils.h" #define PRINT_FIELD(level, field) trace(level, #field ": %04x\n", field) +#define HIDDEV_PATH "/dev/usb/" + int hiddev_read(unsigned char *data, int bufsize, int fd) { struct hiddev_event readBuffer[READ_BUFFER_LENGTH]; @@ -87,23 +91,25 @@ static int get_usagecode(int fd) return uref.usage_code; } -int hiddev_open(const char *device_path, int *usage_code) +static int _hiddev_open(const char *device_path, int *usage_code, + int vendor_id, int product_id) { struct hiddev_devinfo device_info; struct hiddev_report_info rinfo; int ret, error; int fd; + + trace(3, "Opening device %s\n", device_path); fd = ret = open(device_path, O_RDWR); if (fd < 0) goto err; - rinfo.report_type = HID_REPORT_TYPE_OUTPUT; rinfo.report_id = HID_REPORT_ID_FIRST; ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo); if (ret < 0) - goto err; + goto err_close; PRINT_FIELD(3, rinfo.report_type); PRINT_FIELD(3, rinfo.report_id); @@ -112,12 +118,12 @@ int hiddev_open(const char *device_path, int *usage_code) *usage_code = get_usagecode(fd); if (*usage_code < 0) - return -8; + goto err_close; ret = ioctl(fd, HIDIOCGDEVINFO, &device_info); if (ret < 0) - goto err; + goto err_close; PRINT_FIELD(3, device_info.bustype); PRINT_FIELD(3, device_info.busnum); @@ -128,11 +134,65 @@ int hiddev_open(const char *device_path, int *usage_code) PRINT_FIELD(3, device_info.version); PRINT_FIELD(3, device_info.num_applications); + if (product_id && vendor_id) { + if (product_id == device_info.product && + vendor_id == device_info.vendor) + return fd; + trace(3, "Vendor and product IDs don't match\n"); + goto err_close; + } + return fd; +err_close: + close(fd); err: error = errno; printf("Error opening device %s: %s\n", device_path, strerror(error)); return ret; } +int hiddev_open(const char *device_path, int *usage_code) +{ + return _hiddev_open(device_path, usage_code, 0, 0); +} + +int hiddev_open_by_id(int vendor_id, int product_id, int *usage_code) +{ + struct dirent *dirent; + DIR *dir; + int error, fd; + char path[256]; + + dir = opendir(HIDDEV_PATH); + if (dir == NULL) { + error = errno; + printf("Failed to open directory %s: %s\n", HIDDEV_PATH, + strerror(error)); + return -error; + } + + while ((dirent = readdir(dir))) { + if (strncmp(dirent->d_name, "hiddev", sizeof("hiddev") - 1)) + continue; + + path[0] = 0; + strncat(path, HIDDEV_PATH, sizeof(path) - 1); + strncat(path, dirent->d_name, sizeof(path) - 1); + + fd = _hiddev_open(path, usage_code, product_id, vendor_id); + if (fd < 0) + continue; + return fd; + } + + if (errno) { + error = errno; + trace(0, "Error reading directory %s: %s\n", HIDDEV_PATH, + strerror(error)); + return -error; + } + + trace(0, "Canno't find any mathing hiddev devices\n"); + return -1; +} diff --git a/hiddev.h b/hiddev.h index a37c60f..2d5f948 100644 --- a/hiddev.h +++ b/hiddev.h @@ -6,5 +6,6 @@ int hiddev_read(unsigned char *data, int bufsize, int fd); int hiddev_write(const unsigned char data[64], int fd , int usage_code); int hiddev_open(const char *device_path, int *usage_code); +int hiddev_open_by_id(int vendor_id, int product_id, int *usage_code); #endif -- 2.45.0