* [Qemu-devel] [PATCH] Add USB sys file-system support (v5)
@ 2008-09-17 22:47 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-09-17 22:47 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
On Wed, 2008-09-17 at 15:31 -0500, Anthony Liguori wrote:
> Signed-off-by: TJ <linux@tjworld.net>
> >
>
> A valid Signed-off-by requires a full name, not just an abbreviation.
This is valid and full.
> usb_host_device_path please. Also, the explicit initialization to 0 is
> unnecessary. This should probably be a const char * too?
If it were 'const' it would cause a compiler warning with
strcpy(usb_host_device_path, devpath) in usb_host_scan().
>
> > if (fd < 0) {
> > perror(buf);
> > goto fail;
> > }
> > + printf("husb: opened %s\n", buf);
> >
>
> Please don't add unconditional printfs.
This was changed to dprintf() as described in the previous precis but
the patch-generation accidentally came from older code.
> This indenting is wrong. QEMU uses 4-space tabs.
Hmmm... something certainly went wrong. The source has 4-space tabs...
aha! Forgot to do a "git-add" after "git-reset --soft" when modifying
white-space (an interim text editor decided to silently translate spaces
to tabs), before "git-commit -C", thus ending up with the working
directory copy more recent than the commit, which was the source of
"git-format-patch -1".
The attached patch *should* be tab-free.
>
> > static int usb_host_scan(void *opaque, USBScanFunc *func)
> > {
> > - FILE *f;
> > - 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];
> > + FILE *f = 0;
> > + DIR *dir = 0;
> > + int ret = 0;
> > + char *devices = "/devices";
> > + char *trying = "husb: trying to open %s%s\n";
> > + char *failed = "husb: could not open %s%s\n";
> > + char devpath[PATH_MAX];
> > +
> > + // only check the host once
> > + if (!USBfs) {
> > + // test for dev file-system access in /proc/
> > + term_printf(trying, USBPROCBUS_PATH, devices);
> > + f = fopen(USBPROCBUS_PATH "/devices", "r");
> > + if (!f) {
> > + term_printf(failed, USBPROCBUS_PATH, devices);
> > + // maybe it has been moved to the /dev/ base
> > + term_printf(trying, USBDEVBUS_PATH, devices);
> > + f = fopen(USBDEVBUS_PATH "/devices", "r");
> > + if (!f) {
> > + term_printf(failed, USBDEVBUS_PATH, devices);
> > + // test for newer sys file-system access
> > + term_printf(trying, USBSYSBUS_PATH, devices);
> > + dir = opendir(USBSYSBUS_PATH "/devices");
> > + if (!dir) {
> > + term_printf(failed, USBSYSBUS_PATH, devices);
> > + goto the_end;
> > + }
> > + else { // devices found in /dev/bus/usb/ (yes - not a mistake!)
> > + strcpy(devpath, USBDEVBUS_PATH);
> > + USBfs = USB_FS_SYS;
> > + }
> > + if (dir) closedir(dir);
> > + }
> > + else { // devices found in /dev/bus/usb/
> > + strcpy(devpath, USBDEVBUS_PATH);
> > + USBfs = USB_FS_DEV;
> > + }
> > + }
> > + else { // devices found in /proc/bus/usb/
> > + strcpy(devpath, USBPROCBUS_PATH);
> > + USBfs = USB_FS_PROC;
> > + }
> > + if (f) fclose(f);
> >
>
> The term_printfs are also way too verbose.
Demoted to dprintf().
--------------------------------------
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 <linux@tjworld.net>
---
--- 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 <linux@tjworld.net>
+ * 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;
}
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v5)
2008-09-17 22:47 ` [Qemu-devel] " TJ
(?)
@ 2008-09-22 19:47 ` Rick Vernam
2008-09-22 22:38 ` Anthony Liguori
-1 siblings, 1 reply; 46+ messages in thread
From: Rick Vernam @ 2008-09-22 19:47 UTC (permalink / raw)
To: qemu-devel
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 <linux@tjworld.net>
> ---
> --- 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 <linux@tjworld.net>
> + * 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;
> }
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v5)
2008-09-22 19:47 ` Rick Vernam
@ 2008-09-22 22:38 ` Anthony Liguori
2008-09-25 17:34 ` Rick Vernam
0 siblings, 1 reply; 46+ messages in thread
From: Anthony Liguori @ 2008-09-22 22:38 UTC (permalink / raw)
To: qemu-devel
Rick Vernam wrote:
> 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?
Sorry, due to how my email is setup, it's easier for me to miss a patch
when it goes CC's both qemu-devel and kvm-devel.
The patch still needs some cleanup, but once it's done, I will commit it.
Regards,
Anthony Liguori
>
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v5)
2008-09-22 22:38 ` Anthony Liguori
@ 2008-09-25 17:34 ` Rick Vernam
2008-09-25 17:45 ` Anthony Liguori
0 siblings, 1 reply; 46+ messages in thread
From: Rick Vernam @ 2008-09-25 17:34 UTC (permalink / raw)
To: qemu-devel
On Monday 22 September 2008 05:38:39 pm Anthony Liguori wrote:
> Rick Vernam wrote:
> > 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?
>
> Sorry, due to how my email is setup, it's easier for me to miss a patch
> when it goes CC's both qemu-devel and kvm-devel.
>
> The patch still needs some cleanup, but once it's done, I will commit it.
>
> Regards,
>
> Anthony Liguori
Fantastic.
I see TJ posted another patch, so I will look for your comments and/or commit.
Again, Thanks for your time & effort.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v5)
2008-09-25 17:34 ` Rick Vernam
@ 2008-09-25 17:45 ` Anthony Liguori
0 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-25 17:45 UTC (permalink / raw)
To: qemu-devel
Rick Vernam wrote:
> On Monday 22 September 2008 05:38:39 pm Anthony Liguori wrote:
>
>> Rick Vernam wrote:
>>
>>> 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?
>>>
>> Sorry, due to how my email is setup, it's easier for me to miss a patch
>> when it goes CC's both qemu-devel and kvm-devel.
>>
>> The patch still needs some cleanup, but once it's done, I will commit it.
>>
>> Regards,
>>
>> Anthony Liguori
>>
>
> Fantastic.
> I see TJ posted another patch, so I will look for your comments and/or commit.
> Again, Thanks for your time & effort.
>
Still whitespace damaged and I again didn't notice the patch. Thanks
for pointing me to it.
Regards,
Anthony Liguori
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH] Add USB sys file-system support (v5)
2008-09-17 22:47 ` [Qemu-devel] " TJ
@ 2008-09-22 22:37 ` Anthony Liguori
-1 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-22 22:37 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> Demoted to dprintf().
>
> --------------------------------------
> 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 <linux@tjworld.net>
>
This patch is still white spaced damaged.
> ---
> --- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
> +++ b/usb-linux.c 2008-09-17 23:42:32.000000000 +0100
>
This chunk:
> - 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: ;
>
Is identical to this chunk with the exception of whitespace. But
curiously, not enough white space to warrant such a large diff. I broke
out ediff-buffers to verify this. Did you reformat this whole region
and then just query-replace the tabs with spaces? I can't see how diff
would generate this chunk otherwise.
There should be no changes here. I don't mean to be pedantic but it's
extremely difficult to review a patch like this.
> + 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);
>
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v5)
@ 2008-09-22 22:37 ` Anthony Liguori
0 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-22 22:37 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> Demoted to dprintf().
>
> --------------------------------------
> 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 <linux@tjworld.net>
>
This patch is still white spaced damaged.
> ---
> --- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
> +++ b/usb-linux.c 2008-09-17 23:42:32.000000000 +0100
>
This chunk:
> - 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: ;
>
Is identical to this chunk with the exception of whitespace. But
curiously, not enough white space to warrant such a large diff. I broke
out ediff-buffers to verify this. Did you reformat this whole region
and then just query-replace the tabs with spaces? I can't see how diff
would generate this chunk otherwise.
There should be no changes here. I don't mean to be pedantic but it's
extremely difficult to review a patch like this.
> + 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);
>
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v5)
2008-09-22 22:37 ` [Qemu-devel] " Anthony Liguori
(?)
@ 2008-09-23 1:23 ` TJ
-1 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-09-23 1:23 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
On Mon, 2008-09-22 at 17:37 -0500, Anthony Liguori wrote:
> This patch is still white spaced damaged.
> Is identical to this chunk with the exception of whitespace. But
> curiously, not enough white space to warrant such a large diff. I broke
> out ediff-buffers to verify this. Did you reformat this whole region
> and then just query-replace the tabs with spaces? I can't see how diff
> would generate this chunk otherwise.
>
> There should be no changes here. I don't mean to be pedantic but it's
> extremely difficult to review a patch like this.
I suspect it is because I copy/pasted that code from its original
location in usb_host_scan() to the new usb_host_scan_dev(), and
subsequently did some shuffling about.
Could it also be because that hunk has moved both location and
containing function? I was trying to figure out in my head how diff
would efficiently handle that but gave up :)
It looks as if I need to recreate the new source version again manually,
making sure the editor doesn't mess with tabs.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH] Add USB sys file-system support (v6)
2008-09-22 22:37 ` [Qemu-devel] " Anthony Liguori
@ 2008-09-23 1:33 ` TJ
-1 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-09-23 1:33 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
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 <linux@tjworld.net>
---
--- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
+++ b/usb-linux.c 2008-09-23 02:28:48.000000000 +0100
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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,23 +1058,29 @@
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;
@@ -1106,12 +1132,191 @@
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;
}
^ permalink raw reply [flat|nested] 46+ messages in thread* [Qemu-devel] [PATCH] Add USB sys file-system support (v6)
@ 2008-09-23 1:33 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-09-23 1:33 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
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 <linux@tjworld.net>
---
--- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
+++ b/usb-linux.c 2008-09-23 02:28:48.000000000 +0100
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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,23 +1058,29 @@
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;
@@ -1106,12 +1132,191 @@
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;
}
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH] Add USB sys file-system support (v6)
2008-09-23 1:33 ` [Qemu-devel] " TJ
@ 2008-09-25 17:45 ` Anthony Liguori
-1 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-25 17:45 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> 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 <linux@tjworld.net>
> ---
> --- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
> +++ b/usb-linux.c 2008-09-23 02:28:48.000000000 +0100
> @@ -7,6 +7,10 @@
> * Support for host device auto connect & disconnect
> * Major rewrite to support fully async operation
> *
> + * Copyright 2008 TJ <linux@tjworld.net>
> + * 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);
>
You have tabs here.
> 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,23 +1058,29 @@
> 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;
> }
>
And here and almost everywhere.
> +
> 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;
> @@ -1106,12 +1132,191 @@
> 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;
>
This is indented wrong.
> +
> + 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!)
>
else belongs on the same line as curly brackets. Please avoid C99
comments too.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
@ 2008-09-25 17:45 ` Anthony Liguori
0 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-25 17:45 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> 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 <linux@tjworld.net>
> ---
> --- a/usb-linux.c 2008-09-17 22:39:38.000000000 +0100
> +++ b/usb-linux.c 2008-09-23 02:28:48.000000000 +0100
> @@ -7,6 +7,10 @@
> * Support for host device auto connect & disconnect
> * Major rewrite to support fully async operation
> *
> + * Copyright 2008 TJ <linux@tjworld.net>
> + * 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);
>
You have tabs here.
> 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,23 +1058,29 @@
> 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;
> }
>
And here and almost everywhere.
> +
> 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;
> @@ -1106,12 +1132,191 @@
> 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;
>
This is indented wrong.
> +
> + 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!)
>
else belongs on the same line as curly brackets. Please avoid C99
comments too.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-25 17:45 ` [Qemu-devel] " Anthony Liguori
(?)
@ 2008-09-26 13:57 ` Jason Wessel
2008-09-26 14:27 ` Anthony Liguori
-1 siblings, 1 reply; 46+ messages in thread
From: Jason Wessel @ 2008-09-26 13:57 UTC (permalink / raw)
To: qemu-devel; +Cc: TJ
[-- Attachment #1: Type: text/plain, Size: 1071 bytes --]
Anthony Liguori wrote:
> TJ wrote:
>
>> + snprintf(buf, sizeof(buf), "%s/%03d/%03d", usb_host_device_path,
>> bus_num, addr);
>>
>>
>
> You have tabs here.
>
>
>> fd = open(buf, O_RDWR | O_NONBLOCK);
>> }
>>
>>
>
> And here and almost everywhere.
>
>
>> + 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;
>>
>>
>
> This is indented wrong.
>
>
>> + }
>> + else { // devices found in /dev/bus/usb/ (yes - not a mistake!)
>>
>>
>
> else belongs on the same line as curly brackets. Please avoid C99
> comments too.
>
>
Anthony if that is all that you consider to be blocking a commit,
attached is a fixed version with white space and comments fixups.
It would be good to get this applied because it actually makes the usb
pass through usable on a significant number of hosts.
Thanks,
Jason.
[-- Attachment #2: sys-usb.patch --]
[-- Type: text/x-diff, Size: 10320 bytes --]
From: TJ <linux@tjworld.net>
Subject: [PATCH] Add USB sys file-system support
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 <linux@tjworld.net>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
usb-linux.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 217 insertions(+), 11 deletions(-)
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbu
#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 @@ static USBDevice *usb_host_device_open_a
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,23 +1058,29 @@ static int get_tag_value(char *buf, int
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;
@@ -1108,10 +1134,190 @@ static int usb_host_scan(void *opaque, U
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);
+ 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;
}
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 13:57 ` Jason Wessel
@ 2008-09-26 14:27 ` Anthony Liguori
2008-09-26 14:35 ` Robert Riebisch
2008-09-26 15:13 ` Jason Wessel
0 siblings, 2 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-26 14:27 UTC (permalink / raw)
To: Jason Wessel; +Cc: TJ, qemu-devel
Jason Wessel wrote:
> Anthony if that is all that you consider to be blocking a commit,
> attached is a fixed version with white space and comments fixups.
>
Hi Jason,
Thanks for trying to help, but it's *still* whitespace damaged. This
may seem like a minor nit but not taking the time to try and make code
match up with the rest of the source tree doesn't suggest that much time
has been taking to make the code fit in architecturally or to think
about any sort of wider interactions. I also like to give an author the
chance to fix something because it helps encourage people to do the
right thing the first time around.
> It would be good to get this applied because it actually makes the usb
> pass through usable on a significant number of hosts.
>
Honestly, I still haven't done a thorough review because as soon as I've
seen the whitespace damage I've stopped looking. Early versions of the
patch were impossible to review too because they reformatted huge chunks
of code.
> ret = func(opaque, bus_num, addr, class_id, vendor_id,
> - product_id, product_name, speed);
> + product_id, product_name, speed);
This line not only shouldn't be here, but it's breaking the previously
correct indentation.
> + 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;
This is not how switch statements should be indented.
Regards,
Anthony Liguori
> Thanks,
> Jason.
>
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 14:27 ` Anthony Liguori
@ 2008-09-26 14:35 ` Robert Riebisch
2008-09-26 14:37 ` Anthony Liguori
2008-09-26 15:13 ` Jason Wessel
1 sibling, 1 reply; 46+ messages in thread
From: Robert Riebisch @ 2008-09-26 14:35 UTC (permalink / raw)
To: qemu-devel
Anthony Liguori wrote:
> Thanks for trying to help, but it's *still* whitespace damaged. This
> may seem like a minor nit but not taking the time to try and make code
> match up with the rest of the source tree doesn't suggest that much time
> has been taking to make the code fit in architecturally or to think
> about any sort of wider interactions. I also like to give an author the
> chance to fix something because it helps encourage people to do the
> right thing the first time around.
Isn't there an official GNU indent guide for the QEMU sources?
Robert Riebisch
--
BTTR Software
http://www.bttr-software.de/
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 14:35 ` Robert Riebisch
@ 2008-09-26 14:37 ` Anthony Liguori
0 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-09-26 14:37 UTC (permalink / raw)
To: qemu-devel
Robert Riebisch wrote:
> Anthony Liguori wrote:
>
>
>> Thanks for trying to help, but it's *still* whitespace damaged. This
>> may seem like a minor nit but not taking the time to try and make code
>> match up with the rest of the source tree doesn't suggest that much time
>> has been taking to make the code fit in architecturally or to think
>> about any sort of wider interactions. I also like to give an author the
>> chance to fix something because it helps encourage people to do the
>> right thing the first time around.
>>
>
> Isn't there an official GNU indent guide for the QEMU sources?
>
Perhaps, but I use the following in emacs:
(c-add-style "qemu"
'("stroustrup"
(indent-tabs-mode . nil)
(c-basic-offset . 4)
(tab-width . 8)
)
nil)
Perhaps someone can post the appropriate vim-fu too.
Regards,
Anthony Liguori
> Robert Riebisch
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 14:27 ` Anthony Liguori
2008-09-26 14:35 ` Robert Riebisch
@ 2008-09-26 15:13 ` Jason Wessel
2008-09-26 15:37 ` Anthony Liguori
1 sibling, 1 reply; 46+ messages in thread
From: Jason Wessel @ 2008-09-26 15:13 UTC (permalink / raw)
To: Anthony Liguori; +Cc: TJ, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1609 bytes --]
Anthony Liguori wrote:
> Jason Wessel wrote:
>> Anthony if that is all that you consider to be blocking a commit,
>> attached is a fixed version with white space and comments fixups.
>>
>
> Hi Jason,
>
> Thanks for trying to help, but it's *still* whitespace damaged. This
> may seem like a minor nit but not taking the time to try and make code
> match up with the rest of the source tree doesn't suggest that much time
> has been taking to make the code fit in architecturally or to think
> about any sort of wider interactions. I also like to give an author the
> chance to fix something because it helps encourage people to do the
> right thing the first time around.
>
While I agree in part, it is also frustrating when you want to put
changes on top someone else's work that is changing. It is in the
spirit of trying to stabilize this patch that I offered a bit of
assistance.
The rest of your concerns to the white space fixes are addressed in
the next version here.
I also fixed the instances of:
if (f) ...
to be:
if (f)
...
As well a closing else {} problem:
if () {
...
} else
...
to be:
if () {
...
} else {
...
}
Perhaps further technical review can occur with no more white space issues?
My comment on technical content would be that the several places that
atoi() and strtoul() the values are not checked for any kind of
correctness and subsequently pass on. Perhaps no validity check is
needed because it is dealt with in the later call to the passed in
function... It just was not immediately obvious.
Jason.
[-- Attachment #2: sys-usb-v2.patch --]
[-- Type: text/x-diff, Size: 10063 bytes --]
From: TJ <linux@tjworld.net>
Subject: [PATCH] Add USB sys file-system support
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 <linux@tjworld.net>
---
usb-linux.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 219 insertions(+), 10 deletions(-)
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbu
#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 @@ static USBDevice *usb_host_device_open_a
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,23 +1058,29 @@ static int get_tag_value(char *buf, int
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;
@@ -1111,7 +1137,190 @@ static int usb_host_scan(void *opaque, U
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ 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:
return ret;
}
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 15:13 ` Jason Wessel
@ 2008-09-26 15:37 ` Anthony Liguori
2008-09-30 20:53 ` TJ
0 siblings, 1 reply; 46+ messages in thread
From: Anthony Liguori @ 2008-09-26 15:37 UTC (permalink / raw)
To: Jason Wessel; +Cc: TJ, qemu-devel
Jason Wessel wrote:
> Anthony Liguori wrote:
>
> My comment on technical content would be that the several places that
> atoi() and strtoul() the values are not checked for any kind of
> correctness and subsequently pass on. Perhaps no validity check is
> needed because it is dealt with in the later call to the passed in
> function... It just was not immediately obvious.
>
Okay, the patch needs some refactoring. I can commit and refactor or
someone else can refactor and resubmit. Either works for me. Anyway:
> +/*
> + * 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);
>
This pattern, snprintf() of a filename, open, read from it, then parse
the output is very frequently repeated. It could be collapsed into:
if (usb_host_read_file(buffer, sizeof(buffer), USBSYSBUS_PATH
"/devices/%s/devnum", de->d_name))
goto the_end;
if (sscanf(buffer, "%d", &addr) != 1)
goto the_end;
And it would greatly simplify the code.
> +/*
> + * 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) {
>
We really want an affirmative test here, that goto's the switch
statement instead of nesting deeply.
With those changes, the patch is ready to apply.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v6)
2008-09-26 15:37 ` Anthony Liguori
@ 2008-09-30 20:53 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-09-30 20:53 UTC (permalink / raw)
To: qemu-devel
On Fri, 2008-09-26 at 10:37 -0500, Anthony Liguori wrote:
> Okay, the patch needs some refactoring. I can commit and refactor or
> someone else can refactor and resubmit. Either works for me. Anyway:
Anthony, sorry for all the white-space damage issues. Somehow my
original git working source got mangled so every adaption based on it
was inheriting the mess. I'd been doing a lot of other development work
mainly in my kvm git and exported the patch from there originally and
then later re-based it against the latest qemu.
I've got some more time now to focus on it so I'll get a clean patch
sorted incorporating your suggested changes. I hadn't touched the
original sys-fs code written by Robert Schiele at Novell, but I'll give
it a polish now.
TJ.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH] Add USB sys file-system support (v7)
2008-09-23 1:33 ` [Qemu-devel] " TJ
@ 2008-10-01 21:21 ` TJ
-1 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-10-01 21:21 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
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 <linux@tjworld.net>
---
usb-linux.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 218 insertions(+), 10 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index c5da5b5..5f0eeaf 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
#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;
/* endpoint association data */
struct endp_data {
@@ -890,13 +905,18 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
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,23 +1058,33 @@ static int get_tag_value(char *buf, int buf_size,
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");
+ if (!usb_host_device_path) {
+ perror("husb: USB Host Device Path not set");
+ goto the_end;
+ }
+ 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;
@@ -1111,7 +1141,185 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ if (f)
+ fclose(f);
+ return ret;
+}
+
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+{
+ FILE *f;
+ int ret = 0;
+ char filename[PATH_MAX];
+
+ snprintf(filename, PATH_MAX, device_file, device_name);
+ f = fopen(filename, "r");
+ if (f) {
+ fgets(line, line_size, f);
+ fclose(f);
+ ret = 1;
+ } else {
+ term_printf("husb: could not open %s\n", filename);
+ }
+
+ return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on 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)
+{
+ 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 *tmpstr = de->d_name;
+ if (!strncmp(de->d_name, "usb", 3))
+ tmpstr += 3;
+ bus_num = atoi(tmpstr);
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/devnum", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%d", &addr) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/bDeviceClass", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &class_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idVendor", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &vendor_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idProduct", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &product_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/product", de->d_name)) {
+ *product_name = 0;
+ } else {
+ if (strlen(line) > 0)
+ line[strlen(line) - 1] = '\0';
+ pstrcpy(product_name, sizeof(product_name), line);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/speed", de->d_name))
+ goto the_end;
+ 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 *opened = "husb: opened %s%s\n";
+ const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
+ char devpath[PATH_MAX];
+
+ /* only check the host once */
+ if (!usb_fs_type) {
+ f = fopen(USBPROCBUS_PATH "/devices", "r");
+ if (f) {
+ /* devices found in /proc/bus/usb/ */
+ strcpy(devpath, USBPROCBUS_PATH);
+ usb_fs_type = USB_FS_PROC;
+ fclose(f);
+ dprintf(opened, USBPROCBUS_PATH, devices);
+ }
+ /* try additional methods if an access method hasn't been found yet */
+ f = fopen(USBDEVBUS_PATH "/devices", "r");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_DEV;
+ fclose(f);
+ dprintf(opened, USBDEVBUS_PATH, devices);
+ }
+ dir = opendir(USBSYSBUS_PATH "/devices");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_SYS;
+ closedir(dir);
+ dprintf(opened, USBSYSBUS_PATH, devices);
+ } else {
+ term_printf("husb: unable to access USB devices\n");
+ goto the_end;
+ }
+
+ /* 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 file-system with %s\n", fs_type[usb_fs_type], 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:
return ret;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 46+ messages in thread* [Qemu-devel] [PATCH] Add USB sys file-system support (v7)
@ 2008-10-01 21:21 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-10-01 21:21 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
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 <linux@tjworld.net>
---
usb-linux.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 218 insertions(+), 10 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index c5da5b5..5f0eeaf 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
#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;
/* endpoint association data */
struct endp_data {
@@ -890,13 +905,18 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
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,23 +1058,33 @@ static int get_tag_value(char *buf, int buf_size,
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");
+ if (!usb_host_device_path) {
+ perror("husb: USB Host Device Path not set");
+ goto the_end;
+ }
+ 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;
@@ -1111,7 +1141,185 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ if (f)
+ fclose(f);
+ return ret;
+}
+
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+{
+ FILE *f;
+ int ret = 0;
+ char filename[PATH_MAX];
+
+ snprintf(filename, PATH_MAX, device_file, device_name);
+ f = fopen(filename, "r");
+ if (f) {
+ fgets(line, line_size, f);
+ fclose(f);
+ ret = 1;
+ } else {
+ term_printf("husb: could not open %s\n", filename);
+ }
+
+ return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on 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)
+{
+ 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 *tmpstr = de->d_name;
+ if (!strncmp(de->d_name, "usb", 3))
+ tmpstr += 3;
+ bus_num = atoi(tmpstr);
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/devnum", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%d", &addr) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/bDeviceClass", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &class_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idVendor", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &vendor_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idProduct", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &product_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/product", de->d_name)) {
+ *product_name = 0;
+ } else {
+ if (strlen(line) > 0)
+ line[strlen(line) - 1] = '\0';
+ pstrcpy(product_name, sizeof(product_name), line);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/speed", de->d_name))
+ goto the_end;
+ 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 *opened = "husb: opened %s%s\n";
+ const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
+ char devpath[PATH_MAX];
+
+ /* only check the host once */
+ if (!usb_fs_type) {
+ f = fopen(USBPROCBUS_PATH "/devices", "r");
+ if (f) {
+ /* devices found in /proc/bus/usb/ */
+ strcpy(devpath, USBPROCBUS_PATH);
+ usb_fs_type = USB_FS_PROC;
+ fclose(f);
+ dprintf(opened, USBPROCBUS_PATH, devices);
+ }
+ /* try additional methods if an access method hasn't been found yet */
+ f = fopen(USBDEVBUS_PATH "/devices", "r");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_DEV;
+ fclose(f);
+ dprintf(opened, USBDEVBUS_PATH, devices);
+ }
+ dir = opendir(USBSYSBUS_PATH "/devices");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_SYS;
+ closedir(dir);
+ dprintf(opened, USBSYSBUS_PATH, devices);
+ } else {
+ term_printf("husb: unable to access USB devices\n");
+ goto the_end;
+ }
+
+ /* 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 file-system with %s\n", fs_type[usb_fs_type], 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:
return ret;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 46+ messages in thread* [PATCH] Add USB sys file-system support (v8)
2008-10-01 21:21 ` [Qemu-devel] " TJ
@ 2008-10-01 23:19 ` TJ
-1 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-10-01 23:19 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
A bug crept into the version 7 patch whilst editing to help pass
checkpatch.pl tests. Inadvertently, in moving an assignment out of an
if() condition I replaced it with a test against the wrong variable.
This is the corrected patch.
======
Add USB sys file-system support
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 <linux@tjworld.net>
---
usb-linux.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 218 insertions(+), 10 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index c5da5b5..6113a0c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
#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;
/* endpoint association data */
struct endp_data {
@@ -890,13 +905,18 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
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,23 +1058,33 @@ static int get_tag_value(char *buf, int buf_size,
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");
+ if (!usb_host_device_path) {
+ perror("husb: USB Host Device Path not set");
+ goto the_end;
+ }
+ 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;
@@ -1111,7 +1141,185 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ if (f)
+ fclose(f);
+ return ret;
+}
+
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+{
+ FILE *f;
+ int ret = 0;
+ char filename[PATH_MAX];
+
+ snprintf(filename, PATH_MAX, device_file, device_name);
+ f = fopen(filename, "r");
+ if (f) {
+ fgets(line, line_size, f);
+ fclose(f);
+ ret = 1;
+ } else {
+ term_printf("husb: could not open %s\n", filename);
+ }
+
+ return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on 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)
+{
+ 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 *tmpstr = de->d_name;
+ if (!strncmp(de->d_name, "usb", 3))
+ tmpstr += 3;
+ bus_num = atoi(tmpstr);
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/devnum", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%d", &addr) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/bDeviceClass", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &class_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idVendor", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &vendor_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idProduct", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &product_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/product", de->d_name)) {
+ *product_name = 0;
+ } else {
+ if (strlen(line) > 0)
+ line[strlen(line) - 1] = '\0';
+ pstrcpy(product_name, sizeof(product_name), line);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/speed", de->d_name))
+ goto the_end;
+ 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 *opened = "husb: opened %s%s\n";
+ const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
+ char devpath[PATH_MAX];
+
+ /* only check the host once */
+ if (!usb_fs_type) {
+ f = fopen(USBPROCBUS_PATH "/devices", "r");
+ if (f) {
+ /* devices found in /proc/bus/usb/ */
+ strcpy(devpath, USBPROCBUS_PATH);
+ usb_fs_type = USB_FS_PROC;
+ fclose(f);
+ dprintf(opened, USBPROCBUS_PATH, devices);
+ }
+ /* try additional methods if an access method hasn't been found yet */
+ f = fopen(USBDEVBUS_PATH "/devices", "r");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_DEV;
+ fclose(f);
+ dprintf(opened, USBDEVBUS_PATH, devices);
+ }
+ dir = opendir(USBSYSBUS_PATH "/devices");
+ if (!usb_fs_type && dir) {
+ /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_SYS;
+ closedir(dir);
+ dprintf(opened, USBSYSBUS_PATH, devices);
+ } else {
+ term_printf("husb: unable to access USB devices\n");
+ goto the_end;
+ }
+
+ /* 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 file-system with %s\n", fs_type[usb_fs_type], 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:
return ret;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 46+ messages in thread* [Qemu-devel] [PATCH] Add USB sys file-system support (v8)
@ 2008-10-01 23:19 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-10-01 23:19 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm
A bug crept into the version 7 patch whilst editing to help pass
checkpatch.pl tests. Inadvertently, in moving an assignment out of an
if() condition I replaced it with a test against the wrong variable.
This is the corrected patch.
======
Add USB sys file-system support
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 <linux@tjworld.net>
---
usb-linux.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 218 insertions(+), 10 deletions(-)
diff --git a/usb-linux.c b/usb-linux.c
index c5da5b5..6113a0c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
#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;
/* endpoint association data */
struct endp_data {
@@ -890,13 +905,18 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
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,23 +1058,33 @@ static int get_tag_value(char *buf, int buf_size,
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");
+ if (!usb_host_device_path) {
+ perror("husb: USB Host Device Path not set");
+ goto the_end;
+ }
+ 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;
@@ -1111,7 +1141,185 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ if (f)
+ fclose(f);
+ return ret;
+}
+
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+{
+ FILE *f;
+ int ret = 0;
+ char filename[PATH_MAX];
+
+ snprintf(filename, PATH_MAX, device_file, device_name);
+ f = fopen(filename, "r");
+ if (f) {
+ fgets(line, line_size, f);
+ fclose(f);
+ ret = 1;
+ } else {
+ term_printf("husb: could not open %s\n", filename);
+ }
+
+ return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on 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)
+{
+ 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 *tmpstr = de->d_name;
+ if (!strncmp(de->d_name, "usb", 3))
+ tmpstr += 3;
+ bus_num = atoi(tmpstr);
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/devnum", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%d", &addr) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/bDeviceClass", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &class_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idVendor", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &vendor_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idProduct", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &product_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/product", de->d_name)) {
+ *product_name = 0;
+ } else {
+ if (strlen(line) > 0)
+ line[strlen(line) - 1] = '\0';
+ pstrcpy(product_name, sizeof(product_name), line);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/speed", de->d_name))
+ goto the_end;
+ 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 *opened = "husb: opened %s%s\n";
+ const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
+ char devpath[PATH_MAX];
+
+ /* only check the host once */
+ if (!usb_fs_type) {
+ f = fopen(USBPROCBUS_PATH "/devices", "r");
+ if (f) {
+ /* devices found in /proc/bus/usb/ */
+ strcpy(devpath, USBPROCBUS_PATH);
+ usb_fs_type = USB_FS_PROC;
+ fclose(f);
+ dprintf(opened, USBPROCBUS_PATH, devices);
+ }
+ /* try additional methods if an access method hasn't been found yet */
+ f = fopen(USBDEVBUS_PATH "/devices", "r");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_DEV;
+ fclose(f);
+ dprintf(opened, USBDEVBUS_PATH, devices);
+ }
+ dir = opendir(USBSYSBUS_PATH "/devices");
+ if (!usb_fs_type && dir) {
+ /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_SYS;
+ closedir(dir);
+ dprintf(opened, USBSYSBUS_PATH, devices);
+ } else {
+ term_printf("husb: unable to access USB devices\n");
+ goto the_end;
+ }
+
+ /* 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 file-system with %s\n", fs_type[usb_fs_type], 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:
return ret;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 46+ messages in thread* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v8)
2008-10-01 23:19 ` [Qemu-devel] " TJ
(?)
@ 2008-10-06 16:03 ` Rick Vernam
2008-10-07 8:46 ` TJ
-1 siblings, 1 reply; 46+ messages in thread
From: Rick Vernam @ 2008-10-06 16:03 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 245 bytes --]
I continued to have problems getting this patch to apply & build - maybe it's
just me, I don't know.
Anyway, I applied it by hand, built it, and ran it, although I would hardly
say I tested it.
Attached is the resulting svn diff usb-linux.c
[-- Attachment #2: usb-linux.diff --]
[-- Type: text/x-diff, Size: 9444 bytes --]
svn diff usb-linux.c
Index: usb-linux.c
===================================================================
--- usb-linux.c (revision 5434)
+++ usb-linux.c (working copy)
@@ -7,6 +7,10 @@
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
+ * Copyright 2008 TJ <linux@tjworld.net>
+ * 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,10 +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;
+
/* endpoint association data */
struct endp_data {
uint8_t type;
@@ -890,13 +904,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,23 +1057,33 @@
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;
+ int ret = 0;
char product_name[512];
- f = fopen(USBDEVFS_PATH "/devices", "r");
+ if (!usb_host_device_path) {
+ perror("husb: USB Host Device Path not set");
+ goto the_end;
+ }
+ 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;
@@ -1111,10 +1140,186 @@
product_id, product_name, speed);
}
the_end:
- fclose(f);
+ if (f)
+ fclose(f);
return ret;
}
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+{
+ FILE *f;
+ int ret = 0;
+ char filename[PATH_MAX];
+
+ snprintf(filename, PATH_MAX, device_file, device_name);
+ f = fopen(filename, "r");
+ if (f) {
+ fgets(line, line_size, f);
+ fclose(f);
+ ret = 1;
+ } else {
+ term_printf("husb: could not open %s\n", filename);
+ }
+
+ return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on 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)
+{
+ 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 *tmpstr = de->d_name;
+ if (!strncmp(de->d_name, "usb", 3))
+ tmpstr += 3;
+ bus_num = atoi(tmpstr);
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/devnum", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%d", &addr) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/bDeviceClass", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &class_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idVendor", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &vendor_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/idProduct", de->d_name))
+ goto the_end;
+ if (sscanf(line, "%x", &product_id) != 1)
+ goto the_end;
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/product", de->d_name)) {
+ *product_name = 0;
+ } else {
+ if (strlen(line) > 0)
+ line[strlen(line) - 1] = '\0';
+ pstrcpy(product_name, sizeof(product_name), line);
+ }
+
+ if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/devices/%s/speed", de->d_name))
+ goto the_end;
+ 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 *fs_type[] = {"unknown", "proc", "dev", "sys"};
+ char devpath[PATH_MAX];
+
+ /* only check the host once */
+ if (!usb_fs_type) {
+ f = fopen(USBPROCBUS_PATH "/devices", "r");
+ if (f) {
+ /* devices found in /proc/bus/usb/ */
+ strcpy(devpath, USBPROCBUS_PATH);
+ usb_fs_type = USB_FS_PROC;
+ fclose(f);
+ dprintf(opened, USBPROCBUS_PATH, devices);
+ }
+ /* try additional methods if an access method hasn't been found yet */
+ f = fopen(USBDEVBUS_PATH "/devices", "r");
+ if (!usb_fs_type && f) {
+ /* devices found in /dev/bus/usb/ */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_DEV;
+ fclose(f);
+ dprintf(opened, USBDEVBUS_PATH, devices);
+ }
+ dir = opendir(USBSYSBUS_PATH "/devices");
+ if (!usb_fs_type && dir) {
+ /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
+ strcpy(devpath, USBDEVBUS_PATH);
+ usb_fs_type = USB_FS_SYS;
+ closedir(dir);
+ dprintf(opened, USBSYSBUS_PATH, devices);
+ } else {
+ term_printf("husb: unable to access USB devices\n");
+ goto the_end;
+ }
+
+ /* 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 file-system with %s\n", fs_type[usb_fs_type], 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:
+ return ret;
+}
+
struct USBAutoFilter {
struct USBAutoFilter *next;
int bus_num;
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v8)
2008-10-06 16:03 ` Rick Vernam
@ 2008-10-07 8:46 ` TJ
0 siblings, 0 replies; 46+ messages in thread
From: TJ @ 2008-10-07 8:46 UTC (permalink / raw)
To: qemu-devel
On Mon, 2008-10-06 at 11:03 -0500, Rick Vernam wrote:
> I continued to have problems getting this patch to apply & build - maybe it's
> just me, I don't know.
I think it could be. The patch was generated against a clean r5369,
built, and tested with Linux Ubuntu Hardy and Windows XP SP2 guests.
(qemu) info version
0.9.1
(qemu) info usbhost
Device 1.1, speed 12 Mb/s
Hub: USB device 0000:0000, UHCI Host Controller
Device 2.1, speed 12 Mb/s
Hub: USB device 0000:0000, UHCI Host Controller
Device 3.1, speed 12 Mb/s
Hub: USB device 0000:0000, UHCI Host Controller
Device 4.1, speed 12 Mb/s
Hub: USB device 0000:0000, UHCI Host Controller
Device 5.1, speed 480 Mb/s
Hub: USB device 0000:0000, EHCI Host Controller
Device 5.3, speed 480 Mb/s
Class 00: USB device 054c:0281, UMH-U09
husb: could not open /sys/bus/usb/devices/5-8/product
Device 5.4, speed 480 Mb/s
Class ef: USB device 05ca:1836
Device 3.2, speed 12 Mb/s
Class e0: USB device 044e:300d, UGX
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH] Add USB sys file-system support (v8)
2008-10-01 23:19 ` [Qemu-devel] " TJ
@ 2008-10-07 20:09 ` Anthony Liguori
-1 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-10-07 20:09 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> A bug crept into the version 7 patch whilst editing to help pass
> checkpatch.pl tests. Inadvertently, in moving an assignment out of an
> if() condition I replaced it with a test against the wrong variable.
> This is the corrected patch.
> ======
> Add USB sys file-system support
>
> 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 <linux@tjworld.net>
>
Applied. Thanks for keeping up with this patch. I'm very happy with
how it turned out. One minor nit:
> +static int usb_host_scan(void *opaque, USBScanFunc *func)
> +{
> + FILE *f = 0;
> + DIR *dir = 0;
> + int ret = 0;
> + const char *devices = "/devices";
>
> + const char *opened = "husb: opened %s%s\n";
>
When debug isn't enabled, these variables are unused and result in
warnings (since they are only used in dprintf()). Could you follow up
with a patch that either stuck these variables in an #ifdef or
refactored the code to make these warnings disappear?
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread* [Qemu-devel] Re: [PATCH] Add USB sys file-system support (v8)
@ 2008-10-07 20:09 ` Anthony Liguori
0 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2008-10-07 20:09 UTC (permalink / raw)
To: TJ; +Cc: qemu-devel, kvm
TJ wrote:
> A bug crept into the version 7 patch whilst editing to help pass
> checkpatch.pl tests. Inadvertently, in moving an assignment out of an
> if() condition I replaced it with a test against the wrong variable.
> This is the corrected patch.
> ======
> Add USB sys file-system support
>
> 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 <linux@tjworld.net>
>
Applied. Thanks for keeping up with this patch. I'm very happy with
how it turned out. One minor nit:
> +static int usb_host_scan(void *opaque, USBScanFunc *func)
> +{
> + FILE *f = 0;
> + DIR *dir = 0;
> + int ret = 0;
> + const char *devices = "/devices";
>
> + const char *opened = "husb: opened %s%s\n";
>
When debug isn't enabled, these variables are unused and result in
warnings (since they are only used in dprintf()). Could you follow up
with a patch that either stuck these variables in an #ifdef or
refactored the code to make these warnings disappear?
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 46+ messages in thread