From 7e827bcde81cc702f232a53d84506cf065274ded Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 26 Feb 2009 17:05:58 +0100 Subject: [PATCH] usb_id: add ID_USB_INTERFACES=:0e0100:0e0200:010100:010200: --- extras/usb_id/usb_id.c | 82 +++++++++++++++++++++++- rules/rules.d/60-persistent-input.rules | 2 +- rules/rules.d/60-persistent-serial.rules | 2 +- rules/rules.d/60-persistent-v4l.rules | 2 +- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c index 39576e45..489f97e5 100644 --- a/extras/usb_id/usb_id.c +++ b/extras/usb_id/usb_id.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,7 @@ static char model_str[64]; static char model_str_enc[256]; static char vendor_str_enc[256]; static char serial_str[UTIL_NAME_SIZE]; +static char packed_if_str[UTIL_NAME_SIZE]; static char revision_str[64]; static char type_str[64]; static char instance_str[64]; @@ -163,6 +165,77 @@ static void set_scsi_type(char *to, const char *from, size_t len) util_strlcpy(to, type, len); } +#define USB_DT_DEVICE 0x01 +#define USB_DT_INTERFACE 0x04 + +static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len) +{ + char *filename = NULL; + int fd; + ssize_t size; + unsigned char buf[18 + 65535]; + unsigned int pos, strpos; + struct usb_interface_descriptor { + u_int8_t bLength; + u_int8_t bDescriptorType; + u_int8_t bInterfaceNumber; + u_int8_t bAlternateSetting; + u_int8_t bNumEndpoints; + u_int8_t bInterfaceClass; + u_int8_t bInterfaceSubClass; + u_int8_t bInterfaceProtocol; + u_int8_t iInterface; + } __attribute__((packed)); + int err; + + if (asprintf(&filename, "%s/descriptors", udev_device_get_syspath(dev)) < 0) { + err = -1; + goto out; + } + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "error opening USB device 'descriptors' file\n"); + err = -1; + goto out; + } + size = read(fd, buf, sizeof(buf)); + close(fd); + if (size < 18 || size == sizeof(buf)) { + err = -1; + goto out; + } + + pos = 0; + strpos = 0; + while (pos < sizeof(buf) && strpos+7 < len) { + struct usb_interface_descriptor *desc; + char if_str[8]; + + desc = (struct usb_interface_descriptor *) &buf[pos]; + if (desc->bLength < 3) + break; + pos += desc->bLength; + + if (desc->bDescriptorType != USB_DT_INTERFACE) + continue; + + if (snprintf(if_str, 8, "%02x%02x%02x:", + desc->bInterfaceClass, + desc->bInterfaceSubClass, + desc->bInterfaceProtocol) != 7) + continue; + + if (strstr(ifs_str, if_str) != NULL) + continue; + + memcpy(&ifs_str[strpos], if_str, 8), + strpos += 7; + } +out: + free(filename); + return 0; +} + /* * A unique USB identification is generated like this: * @@ -228,6 +301,9 @@ static int usb_id(struct udev_device *dev) return 1; } + /* all interfaces of the device in a single string */ + dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str)); + /* mass storage : SCSI or ATAPI */ if ((protocol == 6 || protocol == 2) && !use_usb_info) { struct udev_device *dev_scsi; @@ -410,9 +486,7 @@ int main(int argc, char **argv) } } - devpath = getenv("DEVPATH"); - if (devpath == NULL) - devpath = argv[optind]; + devpath = argv[optind]; if (devpath == NULL) { fprintf(stderr, "No device specified\n"); retval = 1; @@ -456,6 +530,8 @@ int main(int argc, char **argv) if (instance_str[0] != '\0') printf("ID_INSTANCE=%s\n", instance_str); printf("ID_BUS=usb\n"); + if (packed_if_str[0] != '\0') + printf("ID_USB_INTERFACES=:%s\n", packed_if_str); } else printf("%s\n", serial); } diff --git a/rules/rules.d/60-persistent-input.rules b/rules/rules.d/60-persistent-input.rules index 7a4b23c6..fff766fb 100644 --- a/rules/rules.d/60-persistent-input.rules +++ b/rules/rules.d/60-persistent-input.rules @@ -5,7 +5,7 @@ SUBSYSTEM!="input", GOTO="persistent_input_end" KERNEL=="input[0-9]*", GOTO="persistent_input_end" # usb devices -SUBSYSTEMS=="usb", IMPORT{program}="usb_id --export" +SUBSYSTEMS=="usb", IMPORT{program}="usb_id --export %p" SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="03", ATTRS{bInterfaceProtocol}=="01", ENV{ID_CLASS}="kbd" SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="03", ATTRS{bInterfaceProtocol}=="02", ENV{ID_CLASS}="mouse" diff --git a/rules/rules.d/60-persistent-serial.rules b/rules/rules.d/60-persistent-serial.rules index df10606e..6d09506d 100644 --- a/rules/rules.d/60-persistent-serial.rules +++ b/rules/rules.d/60-persistent-serial.rules @@ -10,7 +10,7 @@ ENV{ID_PORT}=="", GOTO="persistent_serial_end" IMPORT="path_id" ENV{ID_PATH}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{ID_PORT}" -IMPORT="usb_id --export" +IMPORT="usb_id --export %p" ENV{ID_SERIAL}=="", GOTO="persistent_serial_end" SUBSYSTEMS=="usb", ENV{ID_IFACE}="$attr{bInterfaceNumber}" ENV{ID_IFACE}=="", GOTO="persistent_serial_end" diff --git a/rules/rules.d/60-persistent-v4l.rules b/rules/rules.d/60-persistent-v4l.rules index fb961b79..8415cd05 100644 --- a/rules/rules.d/60-persistent-v4l.rules +++ b/rules/rules.d/60-persistent-v4l.rules @@ -3,7 +3,7 @@ ACTION!="add|change", GOTO="persistent_v4l_end" SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end" -SUBSYSTEMS=="usb", IMPORT{program}="usb_id --export" +SUBSYSTEMS=="usb", IMPORT{program}="usb_id --export %p" KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}" # check for valid "index" number -- 2.39.5