chiark / gitweb /
usb_id: add ID_USB_INTERFACES=:0e0100:0e0200:010100:010200:
authorKay Sievers <kay.sievers@vrfy.org>
Thu, 26 Feb 2009 16:05:58 +0000 (17:05 +0100)
committerKay Sievers <kay.sievers@vrfy.org>
Thu, 26 Feb 2009 16:05:58 +0000 (17:05 +0100)
extras/usb_id/usb_id.c
rules/rules.d/60-persistent-input.rules
rules/rules.d/60-persistent-serial.rules
rules/rules.d/60-persistent-v4l.rules

index 39576e4..489f97e 100644 (file)
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <getopt.h>
 
@@ -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);
        }
index 7a4b23c..fff766f 100644 (file)
@@ -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"
 
index df10606..6d09506 100644 (file)
@@ -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"
index fb961b7..8415cd0 100644 (file)
@@ -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