All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add USB sys file-system support
@ 2008-09-04 23:35 TJ
  2008-09-05  2:06 ` [PATCH] Add USB sys file-system support (v2) TJ
  0 siblings, 1 reply; 20+ messages in thread
From: TJ @ 2008-09-04 23:35 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>
---
 qemu/usb-linux.c |  329 +++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 253 insertions(+), 76 deletions(-)

diff --git a/qemu/usb-linux.c b/qemu/usb-linux.c
index 8ee789f..f263f0c 100644
--- a/qemu/usb-linux.c
+++ b/qemu/usb-linux.c
@@ -7,6 +7,10 @@
  *      Support for host device auto connect & disconnect
  *      Magor 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
@@ -65,9 +69,13 @@ 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 *USBHostDevicePath;
 
 struct sigaction sigact;
 
@@ -600,13 +608,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 (!USBHostDevicePath) {
+		perror("husb: USB Host Device Path not set");
+		goto fail;
+	}
+    snprintf(buf, sizeof(buf), "%s/%03d/%03d", USBHostDevicePath,
              bus_num, addr);
     fd = open(buf, O_RDWR | O_NONBLOCK);
     if (fd < 0) {
         perror(buf);
         goto fail;
     }
+    printf("husb: opened %s\n", buf);
 
     /* read the device description */
     dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
@@ -629,9 +642,10 @@ static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
     dev->configuration = 1;
 
     /* XXX - do something about initial configuration */
-    if (!usb_host_update_interfaces(dev, -1))
+    if (!usb_host_update_interfaces(dev, -1)) {
+        perror("usb_host_device_open: update interfaces");
         goto fail;
-
+    }
     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
     if (ret < 0) {
         perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
@@ -717,81 +731,244 @@ 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(FILE *f, 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];
+	char line[1024];
+	char buf[1024];
+	int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
+	char product_name[512];
+	int ret = 0;
+
+	device_count = 0;
+	bus_num = addr = speed = class_id = product_id = vendor_id = 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 (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);
+	}
+ the_end:
+	return ret;
+}
 
-    f = fopen(USBDEVFS_PATH "/devices", "r");
-    if (!f) {
-        term_printf("husb: could not open %s\n", USBDEVFS_PATH "/devices");
-        return 0;
-    }
-    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 (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);
-    }
+/*
+ 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(DIR *dir, void *opaque, USBScanFunc *func)
+{
+	FILE *f;
+	char line[1024];
+	int bus_num, addr, speed, class_id, product_id, vendor_id;
+	int ret = 0;
+	char product_name[512];
+	struct dirent* de;
+
+	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, "/sys/bus/usb/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, "/sys/bus/usb/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, "/sys/bus/usb/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, "/sys/bus/usb/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, "/sys/bus/usb/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, "/sys/bus/usb/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);
+		}
+	}
+ the_end:
+     return ret;
+}
+
+/*
+ Determine how to access the host's USB devices and call the specific
+ support function.
+
+ Introduced to fix Ubuntu LP #156085
+ https://bugs.launchpad.net/ubuntu/+bug/156085
+ */
+static int usb_host_scan(void *opaque, USBScanFunc *func)
+{
+	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];
+
+	// initialise the module setting
+	USBHostDevicePath = 0;
+
+	// 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);
+		}
+		else // devices found in /dev/bus/usb/
+			strcpy(devpath, USBDEVBUS_PATH);
+	}
+	else // devices found in /proc/bus/usb/
+		strcpy(devpath, USBPROCBUS_PATH);
+
+	// the module setting (used later for opening devices)
+	USBHostDevicePath = qemu_mallocz(strlen(devpath)+1);
+	strcpy(USBHostDevicePath, devpath);
+	term_printf("husb: using %s\n", USBHostDevicePath);
+
+	if(f) { // dev file-system access
+		ret = usb_host_scan_dev(f, opaque, func);
+		fclose(f);
+	} else if(dir) { // sys file-system access
+		ret = usb_host_scan_sys(dir, opaque, func);
+		closedir(dir);
+	}
  the_end:
-    fclose(f);
-    return ret;
+	return ret;
 }
 
 struct USBAutoFilter {
-- 
1.5.4.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2008-10-07 20:09 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-04 23:35 [PATCH] Add USB sys file-system support TJ
2008-09-05  2:06 ` [PATCH] Add USB sys file-system support (v2) TJ
2008-09-05 13:30   ` [Qemu-devel] " Jason Wessel
2008-09-05 18:51     ` TJ
2008-09-05 19:19       ` Jason Wessel
2008-09-05 20:28         ` TJ
2008-09-05 20:54           ` Jason Wessel
2008-09-05 21:13         ` [PATCH] Add USB sys file-system support (v3) TJ
2008-09-08 14:47           ` Jason Wessel
2008-09-17 19:31             ` [PATCH] Add USB sys file-system support (v4) TJ
2008-09-17 20:31               ` Anthony Liguori
2008-09-17 22:47                 ` [PATCH] Add USB sys file-system support (v5) TJ
2008-09-22 22:37                   ` Anthony Liguori
2008-09-23  1:23                     ` [Qemu-devel] " TJ
2008-09-23  1:33                     ` [PATCH] Add USB sys file-system support (v6) TJ
2008-09-25 17:45                       ` Anthony Liguori
2008-10-01 21:21                       ` [PATCH] Add USB sys file-system support (v7) TJ
2008-10-01 23:19                         ` [PATCH] Add USB sys file-system support (v8) TJ
2008-10-07 20:09                           ` Anthony Liguori
2008-09-05 19:20     ` [Qemu-devel] [PATCH] Add USB sys file-system support (v2) TJ

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.