From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KhrO0-0008E5-UG for qemu-devel@nongnu.org; Mon, 22 Sep 2008 15:47:56 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KhrNz-0008Dj-NG for qemu-devel@nongnu.org; Mon, 22 Sep 2008 15:47:56 -0400 Received: from [199.232.76.173] (port=35142 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KhrNz-0008De-I2 for qemu-devel@nongnu.org; Mon, 22 Sep 2008 15:47:55 -0400 Received: from hobi.com ([130.94.185.247]:2523) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KhrNy-0003eH-L8 for qemu-devel@nongnu.org; Mon, 22 Sep 2008 15:47:55 -0400 Received: from unknown (HELO ricklap) ([68.23.60.237]) (envelope-sender ) by 130.94.185.247 (qmail-ldap-1.03) with SMTP for ; 22 Sep 2008 19:47:52 -0000 From: Rick Vernam Subject: Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v5) Date: Mon, 22 Sep 2008 14:47:51 -0500 References: <1220571341.2638.6.camel@hephaestion> <48D16904.30104@codemonkey.ws> <1221691647.17792.55.camel@hephaestion> In-Reply-To: <1221691647.17792.55.camel@hephaestion> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200809221447.51855.rickv@hobi.com> Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org So is anything going to come of this? I tried to apply this patch to my local svn checkout - but apparently I'm too bone-headed to apply the patch correctly. I'd love to test it, so I inquire - are there any plans to commit this? Or can anyone suggest how I might apply this patch? Thanks. On Wednesday 17 September 2008 05:47:27 pm TJ wrote: [snip} > -------------------------------------- > This patch adds support for host USB devices discovered via: > > /sys/bus/usb/devices/* and opened from /dev/bus/usb/*/* > /dev/bus/usb/devices and opened from /dev/bus/usb/*/* > > in addition to the existing discovery via: > > /proc/bus/usb/devices and opened from /proc/bus/usb/*/* > > Signed-off-by: TJ > --- > --- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100 > +++ b/usb-linux.c 2008-09-17 23:42:32.000000000 +0100 > @@ -7,6 +7,10 @@ > * Support for host device auto connect & disconnect > * Major rewrite to support fully async operation > * > + * Copyright 2008 TJ > + * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in > addition + * to the legacy /proc/bus/usb USB device discovery and > handling + * > * Permission is hereby granted, free of charge, to any person obtaining a > copy * of this software and associated documentation files (the > "Software"), to deal * in the Software without restriction, including > without limitation the rights @@ -72,9 +76,20 @@ > #define dprintf(...) > #endif > > -#define USBDEVFS_PATH "/proc/bus/usb" > +#define USBPROCBUS_PATH "/proc/bus/usb" > #define PRODUCT_NAME_SZ 32 > #define MAX_ENDPOINTS 16 > +#define USBDEVBUS_PATH "/dev/bus/usb" > +#define USBSYSBUS_PATH "/sys/bus/usb" > + > +static char *usb_host_device_path; > + > +#define USB_FS_NONE 0 > +#define USB_FS_PROC 1 > +#define USB_FS_DEV 2 > +#define USB_FS_SYS 3 > + > +static int usb_fs_type = 0; > > /* endpoint association data */ > struct endp_data { > @@ -890,13 +905,18 @@ > > printf("husb: open device %d.%d\n", bus_num, addr); > > - snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", > + if (!usb_host_device_path) { > + perror("husb: USB Host Device Path not set"); > + goto fail; > + } > + snprintf(buf, sizeof(buf), "%s/%03d/%03d", usb_host_device_path, > bus_num, addr); > fd = open(buf, O_RDWR | O_NONBLOCK); > if (fd < 0) { > perror(buf); > goto fail; > } > + dprintf("husb: opened %s\n", buf); > > /* read the device description */ > dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); > @@ -1038,80 +1058,275 @@ > return q - buf; > } > > -static int usb_host_scan(void *opaque, USBScanFunc *func) > +/* > + Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine > + host's USB devices. This is legacy support since many distributions > + are moving to /sys/bus/usb > +*/ > +static int usb_host_scan_dev(void *opaque, USBScanFunc *func) > { > - FILE *f; > + FILE *f = 0; > char line[1024]; > char buf[1024]; > int bus_num, addr, speed, device_count, class_id, product_id, > vendor_id; - int ret; > char product_name[512]; > + int ret = 0; > > - f = fopen(USBDEVFS_PATH "/devices", "r"); > + snprintf(line, sizeof(line), "%s/devices", usb_host_device_path); > + f = fopen(line, "r"); > if (!f) { > - term_printf("husb: could not open %s\n", USBDEVFS_PATH > "/devices"); - return 0; > + perror("husb: cannot open devices file"); > + goto the_end; > } > + > device_count = 0; > bus_num = addr = speed = class_id = product_id = vendor_id = 0; > - ret = 0; > for(;;) { > - if (fgets(line, sizeof(line), f) == NULL) > - break; > - if (strlen(line) > 0) > - line[strlen(line) - 1] = '\0'; > - if (line[0] == 'T' && line[1] == ':') { > - if (device_count && (vendor_id || product_id)) { > - /* New device. Add the previously discovered device. */ > - ret = func(opaque, bus_num, addr, class_id, vendor_id, > - product_id, product_name, speed); > - if (ret) > - goto the_end; > - } > - if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) > - goto fail; > - bus_num = atoi(buf); > - if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) > - goto fail; > - addr = atoi(buf); > - if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) > - goto fail; > - if (!strcmp(buf, "480")) > - speed = USB_SPEED_HIGH; > - else if (!strcmp(buf, "1.5")) > - speed = USB_SPEED_LOW; > - else > - speed = USB_SPEED_FULL; > - product_name[0] = '\0'; > - class_id = 0xff; > - device_count++; > - product_id = 0; > - vendor_id = 0; > - } else if (line[0] == 'P' && line[1] == ':') { > - if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) > - goto fail; > - vendor_id = strtoul(buf, NULL, 16); > - if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) > - goto fail; > - product_id = strtoul(buf, NULL, 16); > - } else if (line[0] == 'S' && line[1] == ':') { > - if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) > - goto fail; > - pstrcpy(product_name, sizeof(product_name), buf); > - } else if (line[0] == 'D' && line[1] == ':') { > - if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) > - goto fail; > - class_id = strtoul(buf, NULL, 16); > - } > - fail: ; > + if (fgets(line, sizeof(line), f) == NULL) > + break; > + if (strlen(line) > 0) > + line[strlen(line) - 1] = '\0'; > + if (line[0] == 'T' && line[1] == ':') { > + if (device_count && (vendor_id || product_id)) { > + /* New device. Add the previously discovered device. */ > + ret = func(opaque, bus_num, addr, class_id, vendor_id, > + product_id, product_name, speed); > + if (ret) > + goto the_end; > + } > + if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) > + goto fail; > + > + bus_num = atoi(buf); > + if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) > + goto fail; > + > + addr = atoi(buf); > + if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) > + goto fail; > + > + if (!strcmp(buf, "480")) > + speed = USB_SPEED_HIGH; > + else if (!strcmp(buf, "1.5")) > + speed = USB_SPEED_LOW; > + else > + speed = USB_SPEED_FULL; > + product_name[0] = '\0'; > + class_id = 0xff; > + device_count++; > + product_id = 0; > + vendor_id = 0; > + } > + else if (line[0] == 'P' && line[1] == ':') { > + if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) > + goto fail; > + > + vendor_id = strtoul(buf, NULL, 16); > + if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) > + goto fail; > + > + product_id = strtoul(buf, NULL, 16); > + } > + else if (line[0] == 'S' && line[1] == ':') { > + if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) > + goto fail; > + > + pstrcpy(product_name, sizeof(product_name), buf); > + } > + else if (line[0] == 'D' && line[1] == ':') { > + if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) > + goto fail; > + > + class_id = strtoul(buf, NULL, 16); > + } > + fail: ; > } > if (device_count && (vendor_id || product_id)) { > - /* Add the last device. */ > - ret = func(opaque, bus_num, addr, class_id, vendor_id, > - product_id, product_name, speed); > + /* Add the last device. */ > + ret = func(opaque, bus_num, addr, class_id, vendor_id, > + product_id, product_name, speed); > + } > + the_end: > + if (f) fclose(f); > + return ret; > +} > + > +/* > + Use /sys/bus/usb/devices/ directory to determine host's USB devices. > + > + This code is taken from Robert Schiele's original patches posted to the > + Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950 > +*/ > +static int usb_host_scan_sys(void *opaque, USBScanFunc *func) > +{ > + FILE *f; > + DIR *dir = 0; > + char line[1024]; > + int bus_num, addr, speed, class_id, product_id, vendor_id; > + int ret = 0; > + char product_name[512]; > + struct dirent* de; > + > + dir = opendir(USBSYSBUS_PATH "/devices"); > + if (!dir) { > + perror("husb: cannot open devices directory"); > + goto the_end; > + } > + > + while ((de = readdir(dir))) { > + if (de->d_name[0] != '.' && ! strchr(de->d_name, ':')) { > + char filename[PATH_MAX]; > + char* tmpstr = de->d_name; > + if (!strncmp(de->d_name, "usb", 3)) > + tmpstr += 3; > + > + bus_num = atoi(tmpstr); > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/devnum", de->d_name); + f = fopen(filename, "r"); > + if (!f) { > + term_printf("Could not open %s\n", filename); > + goto the_end; > + } > + fgets(line, sizeof(line), f); > + fclose(f); > + addr = atoi(line); > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/bDeviceClass", de->d_name); + f = fopen(filename, > "r"); > + if (!f) { > + term_printf("Could not open %s\n", filename); > + goto the_end; > + } > + fgets(line, sizeof(line), f); > + fclose(f); > + class_id = strtoul(line, NULL, 16); > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/idVendor", de->d_name); + f = fopen(filename, "r"); > + if (!f) { > + term_printf("Could not open %s\n", filename); > + goto the_end; > + } > + fgets(line, sizeof(line), f); > + fclose(f); > + vendor_id = strtoul(line, NULL, 16); > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/idProduct", de->d_name); + f = fopen(filename, > "r"); > + if (!f) { > + term_printf("Could not open %s\n", filename); > + goto the_end; > + } > + fgets(line, sizeof(line), f); > + fclose(f); > + product_id = strtoul(line, NULL, 16); > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/product", de->d_name); + f = fopen(filename, "r"); > + if (f) { > + fgets(line, sizeof(line), f); > + fclose(f); > + if (strlen(line) > 0) > + line[strlen(line) - 1] = '\0'; > + > + pstrcpy(product_name, sizeof(product_name), line); > + } else > + *product_name = 0; > + > + snprintf(filename, PATH_MAX, USBSYSBUS_PATH > "/devices/%s/speed", de->d_name); + f = fopen(filename, "r"); > + if (!f) { > + term_printf("Could not open %s\n", filename); > + goto the_end; > + } > + fgets(line, sizeof(line), f); > + fclose(f); > + if (!strcmp(line, "480\n")) > + speed = USB_SPEED_HIGH; > + else if (!strcmp(line, "1.5\n")) > + speed = USB_SPEED_LOW; > + else > + speed = USB_SPEED_FULL; > + > + ret = func(opaque, bus_num, addr, class_id, vendor_id, > + product_id, product_name, speed); > + if (ret) > + goto the_end; > + } > + } > + the_end: > + if (dir) closedir(dir); > + return ret; > +} > + > +/* > + Determine how to access the host's USB devices and call the specific > + support function. > + */ > +static int usb_host_scan(void *opaque, USBScanFunc *func) > +{ > + FILE *f = 0; > + DIR *dir = 0; > + int ret = 0; > + const char *devices = "/devices"; > + const char *trying = "husb: trying to open %s%s\n"; > + const char *failed = "husb: could not open %s%s\n"; > + char devpath[PATH_MAX]; > + > + // only check the host once > + if (!usb_fs_type) { > + // test for dev file-system access in /proc/ > + dprintf(trying, USBPROCBUS_PATH, devices); > + f = fopen(USBPROCBUS_PATH "/devices", "r"); > + if (!f) { > + dprintf(failed, USBPROCBUS_PATH, devices); > + // maybe it has been moved to the /dev/ base > + dprintf(trying, USBDEVBUS_PATH, devices); > + f = fopen(USBDEVBUS_PATH "/devices", "r"); > + if (!f) { > + dprintf(failed, USBDEVBUS_PATH, devices); > + // test for newer sys file-system access > + dprintf(trying, USBSYSBUS_PATH, devices); > + dir = opendir(USBSYSBUS_PATH "/devices"); > + if (!dir) { > + dprintf(failed, USBSYSBUS_PATH, devices); > + goto the_end; > + } > + else { // devices found in /dev/bus/usb/ (yes - not a > mistake!) + strcpy(devpath, USBDEVBUS_PATH); > + usb_fs_type = USB_FS_SYS; > + } > + if (dir) closedir(dir); > + } > + else { // devices found in /dev/bus/usb/ > + strcpy(devpath, USBDEVBUS_PATH); > + usb_fs_type = USB_FS_DEV; > + } > + } > + else { // devices found in /proc/bus/usb/ > + strcpy(devpath, USBPROCBUS_PATH); > + usb_fs_type = USB_FS_PROC; > + } > + if (f) fclose(f); > + > + // the module setting (used later for opening devices) > + usb_host_device_path = qemu_mallocz(strlen(devpath)+1); > + if (usb_host_device_path) { > + strcpy(usb_host_device_path, devpath); > + term_printf("husb: using %s\n", usb_host_device_path); > + } > + else { // out of memory? > + perror("husb: unable to allocate memory for device path"); > + goto the_end; > + } > + } > + > + switch (usb_fs_type) { > + case USB_FS_PROC: > + case USB_FS_DEV: > + ret = usb_host_scan_dev(opaque, func); > + break; > + case USB_FS_SYS: > + ret = usb_host_scan_sys(opaque, func); > + break; > } > the_end: > - fclose(f); > return ret; > }