From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KmsYk-0000xd-TA for qemu-devel@nongnu.org; Mon, 06 Oct 2008 12:03:46 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KmsYj-0000x1-Mo for qemu-devel@nongnu.org; Mon, 06 Oct 2008 12:03:46 -0400 Received: from [199.232.76.173] (port=57314 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KmsYj-0000wt-Gx for qemu-devel@nongnu.org; Mon, 06 Oct 2008 12:03:45 -0400 Received: from hobi.com ([130.94.185.247]:2910) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KmsYi-0002HT-OX for qemu-devel@nongnu.org; Mon, 06 Oct 2008 12:03:45 -0400 Received: from unknown (HELO ricklap) ([68.23.60.237]) (envelope-sender ) by 130.94.185.247 (qmail-ldap-1.03) with SMTP for ; 6 Oct 2008 16:03:40 -0000 From: Rick Vernam Subject: Re: [Qemu-devel] [PATCH] Add USB sys file-system support (v8) Date: Mon, 6 Oct 2008 11:03:39 -0500 References: <1220571341.2638.6.camel@hephaestion> <1222896100.25554.3.camel@hephaestion> <1222903175.25554.28.camel@hephaestion> In-Reply-To: <1222903175.25554.28.camel@hephaestion> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_bbj6IerTkc/+gTK" Message-Id: <200810061103.39452.rickv@hobi.com> Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --Boundary-00=_bbj6IerTkc/+gTK Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 --Boundary-00=_bbj6IerTkc/+gTK Content-Type: text/x-diff; charset="iso-8859-1"; name="usb-linux.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="usb-linux.diff" svn diff usb-linux.c Index: usb-linux.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =2D-- 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 + * =A0 =A0 =A0Added flexible support for /dev/bus/usb /sys/bus/usb/devices= in addition + * =A0 =A0 =A0to 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"), t= o deal * in the Software without restriction, including without limitation the r= ights @@ -72,10 +76,20 @@ #define dprintf(...) #endif =2D#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); =2D 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 =3D 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 =3D read(fd, dev->descr, sizeof(dev->descr)); @@ -1038,23 +1057,33 @@ return q - buf; } =2Dstatic 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) { =2D FILE *f; + FILE *f =3D 0; char line[1024]; char buf[1024]; int bus_num, addr, speed, device_count, class_id, product_id, vendor_i= d; =2D int ret; + int ret =3D 0; char product_name[512]; =2D f =3D 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 =3D fopen(line, "r"); if (!f) { =2D term_printf("husb: could not open %s\n", USBDEVFS_PATH "/devices= "); =2D return 0; + perror("husb: cannot open devices file"); + goto the_end; } + device_count =3D 0; bus_num =3D addr =3D speed =3D class_id =3D product_id =3D vendor_id = =3D 0; =2D ret =3D 0; for(;;) { if (fgets(line, sizeof(line), f) =3D=3D NULL) break; @@ -1111,10 +1140,186 @@ product_id, product_name, speed); } the_end: =2D 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 *de= vice_file, const char *device_name) +{ + FILE *f; + int ret =3D 0; + char filename[PATH_MAX]; + + snprintf(filename, PATH_MAX, device_file, device_name); + f =3D fopen(filename, "r"); + if (f) { + fgets(line, line_size, f); + fclose(f); + ret =3D 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=3D24= 1950 + */ +static int usb_host_scan_sys(void *opaque, USBScanFunc *func) +{ + DIR *dir =3D 0; + char line[1024]; + int bus_num, addr, speed, class_id, product_id, vendor_id; + int ret =3D 0; + char product_name[512]; + struct dirent *de; + + dir =3D opendir(USBSYSBUS_PATH "/devices"); + if (!dir) { + perror("husb: cannot open devices directory"); + goto the_end; + } + + while ((de =3D readdir(dir))) { + if (de->d_name[0] !=3D '.' && !strchr(de->d_name, ':')) { + char *tmpstr =3D de->d_name; + if (!strncmp(de->d_name, "usb", 3)) + tmpstr +=3D 3; + bus_num =3D atoi(tmpstr); + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/devnum", de->d_name)) + goto the_end; + if (sscanf(line, "%d", &addr) !=3D 1) + goto the_end; + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/bDeviceClass", de->d_name)) + goto the_end; + if (sscanf(line, "%x", &class_id) !=3D 1) + goto the_end; + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/idVendor", de->d_name)) + goto the_end; + if (sscanf(line, "%x", &vendor_id) !=3D 1) + goto the_end; + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/idProduct", de->d_name)) + goto the_end; + if (sscanf(line, "%x", &product_id) !=3D 1) + goto the_end; + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/product", de->d_name)) { + *product_name =3D 0; + } else { + if (strlen(line) > 0) + line[strlen(line) - 1] =3D '\0'; + pstrcpy(product_name, sizeof(product_name), line); + } + + if (!usb_host_read_file(line, sizeof(line), USBSYSBUS_PATH "/d= evices/%s/speed", de->d_name)) + goto the_end; + if (!strcmp(line, "480\n")) + speed =3D USB_SPEED_HIGH; + else if (!strcmp(line, "1.5\n")) + speed =3D USB_SPEED_LOW; + else + speed =3D USB_SPEED_FULL; + + ret =3D 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 =3D 0; + DIR *dir =3D 0; + int ret =3D 0; + const char *fs_type[] =3D {"unknown", "proc", "dev", "sys"}; + char devpath[PATH_MAX]; + + /* only check the host once */ + if (!usb_fs_type) { + f =3D fopen(USBPROCBUS_PATH "/devices", "r"); + if (f) { + /* devices found in /proc/bus/usb/ */ + strcpy(devpath, USBPROCBUS_PATH); + usb_fs_type =3D USB_FS_PROC; + fclose(f); + dprintf(opened, USBPROCBUS_PATH, devices); + } + /* try additional methods if an access method hasn't been found ye= t */ + f =3D fopen(USBDEVBUS_PATH "/devices", "r"); + if (!usb_fs_type && f) { + /* devices found in /dev/bus/usb/ */ + strcpy(devpath, USBDEVBUS_PATH); + usb_fs_type =3D USB_FS_DEV; + fclose(f); + dprintf(opened, USBDEVBUS_PATH, devices); + } + dir =3D 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 =3D 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 =3D 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[us= b_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 =3D usb_host_scan_dev(opaque, func); + break; + case USB_FS_SYS: + ret =3D usb_host_scan_sys(opaque, func); + break; + } + the_end: + return ret; +} + struct USBAutoFilter { struct USBAutoFilter *next; int bus_num; --Boundary-00=_bbj6IerTkc/+gTK--