From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1FXVQj-0001TS-27 for qemu-devel@nongnu.org; Sat, 22 Apr 2006 23:38:37 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1FXVQi-0001TG-87 for qemu-devel@nongnu.org; Sat, 22 Apr 2006 23:38:36 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FXVQi-0001TD-25 for qemu-devel@nongnu.org; Sat, 22 Apr 2006 23:38:36 -0400 Received: from [24.93.47.42] (helo=ms-smtp-03.texas.rr.com) by monty-python.gnu.org with esmtp (Exim 4.52) id 1FXVSd-00048c-0A for qemu-devel@nongnu.org; Sat, 22 Apr 2006 23:40:35 -0400 Received: from [192.168.0.11] (cpe-67-9-160-120.austin.res.rr.com [67.9.160.120]) by ms-smtp-03.texas.rr.com (8.13.4/8.13.4) with ESMTP id k3N3cXLl003092 for ; Sat, 22 Apr 2006 22:38:34 -0500 (CDT) Message-ID: <444AF6B7.1030606@austin.rr.com> Date: Sat, 22 Apr 2006 22:38:31 -0500 From: Lonnie Mendez MIME-Version: 1.0 Subject: Re: [Qemu-devel] Large USB patch References: <4447E811.1040403@gmx.de> <4448F1F6.4090609@austin.rr.com> <4448FF3F.3030009@austin.rr.com> <44490614.50406@austin.rr.com> <44490852.2080608@gmx.de> <44491659.30804@austin.rr.com> <44491F0A.2090608@austin.rr.com> <444926AC.3070104@austin.rr.com> <44494596.3070808@austin.rr.com> <4449F860.1060809@gmx.de> <444A3F7E.6070107@austin.rr.com> <444A5336.4040102@gmx.de> <444A578E.6000702@austin.rr.com> <444A5B65.8010104@gmx.de> In-Reply-To: <444A5B65.8010104@gmx.de> Content-Type: multipart/mixed; boundary="------------070006000003000101080402" 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 This is a multi-part message in MIME format. --------------070006000003000101080402 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit nix.wie.weg@gmx.de wrote: >Lonnie Mendez wrote: > > >>nix.wie.weg@gmx.de wrote: >> >>Sorry about that. I was used to the previous syntax: >>usb_add host:04b6:0005 >> >> My guess is that the new syntax is to distinguish it from the >>busaddr:addr syntax? It would seem checking for length would >>differentiate the two in that case. >> >> >Yes maybe, but not a real good solution, especially if you know that >with the solution we have now, you can omit leading zeros. > > Aye. > >I have attached a small patch, with which you can really add a device to >a hub, if this is then working is another question, but it should only >depend on the implementation of usb-hub.c > > That works but not in the literal means of the attached device actually functioning (see below). Here is something interesting: (qemu) usb_add mouse Controller 001: uhci 001:001 = mouse Summary: 1 USB Controller, 1 USB Devices (qemu) usb_add tablet,addto 001:001:001 (qemu) info usb Controller 001: uhci 001:001 = mouse 001:001:001 = tablet Summary: 1 USB Controller, 2 USB Devices (qemu) The device attached on the hub doesn't seem to be receiving transactions (like before with the emulated devices): frame 1227: pid=SETUP addr=0x00 ep=0 len=8 data_out= 80 06 00 01 00 00 40 00 uhci readw port=0x0002 val=0x0001 uhci writew port=0x0002 val=0x0001 uhci readw port=0x0006 val=0x04cc frame 1228: pid=SETUP addr=0x00 ep=0 len=8 data_out= 80 06 00 01 00 00 40 00 frame 1229: pid=SETUP addr=0x00 ep=0 len=8 data_out= 80 06 00 01 00 00 40 00 uhci readw port=0x0002 val=0x0002 uhci writew port=0x0002 val=0x0002 There are some problems with the port status request traffic from the hub as well: frame 1174: pid=SETUP addr=0x03 ep=0 len=8 data_out= 23 03 04 00 01 00 00 00 error usb_generic_handle_packet: unknown USB-Token - 258 ret=0 The interface is also giving incorrect errors at certain times: (qemu) usb_add usbhub usb_add: extraneous characters at the end of line (qemu) Attached is a patch to get the linux redirector working with the changes. It has a few other modifications as well but nothing radical. The default redirector for linux host was changed to the linux redirector as well (just a heads up). I'm still using the libusb redirector for testing here but it's good to restore the linux redirector as default on linux host. --------------070006000003000101080402 Content-Type: text/plain; name="lusb-upd4.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="lusb-upd4.diff" --- a/qemu/configure 2006-04-22 21:58:54.000000000 -0500 +++ b/qemu/configure 2006-04-22 22:00:43.000000000 -0500 @@ -105,7 +105,7 @@ ;; MINGW32*) mingw32="yes" -usb="linux" +usb="generic" ;; FreeBSD) bsd="yes" @@ -130,7 +130,7 @@ oss="yes" linux="yes" user="yes" -usb="generic" +usb="linux" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" fi --- a/qemu/usb-linux.c 2006-04-22 21:58:54.000000000 -0500 +++ b/qemu/usb-linux.c 2006-04-22 22:02:10.000000000 -0500 @@ -42,11 +42,14 @@ void *data; }; -typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, +typedef int USBScanFunc(void *opaque, int bus_num, int addr, int vendor_id, int product_id, - const char *product_name, int speed); + const char *spec_version, + const char *manf_string, + const char *prod_string); static int usb_host_find_device(int *pbus_num, int *paddr, const char *devname); +int usb_host_handle_close(USBDevice *opaque); //#define DEBUG @@ -63,32 +66,19 @@ "error code: %i\n", ret ); # endif switch(ret) { - case -ETIMEDOUT: + case ETIMEDOUT: # ifdef DEBUG printf( "USB_ERROR: ETIMEDOUT\n" ); #endif return USB_RET_NAK; break; - case -EIO: -# ifdef DEBUG - printf( "USB_ERROR: EIO\n" ); -#endif - /* stall condition on win32 */ - /* XXX: clear stall */ - return USB_RET_STALL; - break; - case -EBUSY: - /* stall on linux */ - /* XXX: clear stall */ - return USB_RET_STALL; - break; - case -EPIPE: + case EPIPE: default: return USB_RET_STALL; } } -static void usb_host_handle_reset(USBDevice *dev) +static int usb_host_handle_reset(USBDevice *dev) { #if 0 USBHostDevice *s = (USBHostDevice *)dev; @@ -96,6 +86,7 @@ done by the host OS */ ioctl(s->fd, USBDEVFS_RESET); #endif + return USB_RET_ACK; } static int usb_host_handle_control(USBDevice *dev, @@ -118,7 +109,7 @@ ct.data = data; ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); if (ret < 0) { - usb_host_handle_error( ret ); + return usb_host_handle_error( errno ); } else { return ret; } @@ -142,14 +133,14 @@ bt.data = data; ret = ioctl(s->fd, USBDEVFS_BULK, &bt); if (ret < 0) { - usb_host_handle_error( ret ); + return usb_host_handle_error( errno ); } else { return ret; } } /* XXX: exclude high speed devices or implement EHCI */ -USBDevice *usb_host_device_open(const char *devname) +USBDevice *usb_host_init(const char *devname) { int fd, interface, ret, i; USBHostDevice *hostdev; @@ -162,7 +153,7 @@ if (usb_host_find_device(&bus_num, &addr, devname) < 0) return NULL; - + snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", bus_num, addr); fd = open(buf, O_RDWR); @@ -272,12 +263,16 @@ return q - buf; } -void usb_host_device_close(USBDevice *opaque) +int usb_host_handle_close(USBDevice *opaque) { USBHostDevice *s = (USBHostDevice *)opaque; - if (s->fd >= 0) + if (s->fd >= 0) { close(s->fd); + return 1; + } + + return -1; } static int usb_host_scan(void *opaque, USBScanFunc *func) @@ -285,9 +280,11 @@ FILE *f; char line[1024]; char buf[1024]; - int bus_num, addr, speed, device_count, class_id, product_id, vendor_id; + int bus_num, addr, device_count, product_id, vendor_id; int ret; - char product_name[512]; + char manf_name[512]; + char prod_name[512]; + char spec_version[6]; f = fopen(USBDEVFS_PATH "/devices", "r"); if (!f) { @@ -295,7 +292,7 @@ return 0; } device_count = 0; - bus_num = addr = speed = class_id = product_id = vendor_id = 0; + bus_num = addr = product_id = vendor_id = 0; ret = 0; for(;;) { if (fgets(line, sizeof(line), f) == NULL) @@ -305,8 +302,8 @@ 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); + ret = func(opaque, bus_num, addr, vendor_id, product_id, + spec_version, manf_name, prod_name); if (ret) goto the_end; } @@ -316,19 +313,17 @@ 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; + strcpy(spec_version, "01.10"); + strcpy(manf_name, "unknown"); + strcpy(prod_name, "unknown"); device_count++; product_id = 0; vendor_id = 0; + } else if (line[0] == 'D' && line[1] == ':') { + if (get_tag_value(&buf[1], sizeof(buf) - 1, line, "Ver=", " ") < 0) + goto fail; + buf[0] = '0'; + pstrcpy(spec_version, sizeof(spec_version), buf); } else if (line[0] == 'P' && line[1] == ':') { if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) goto fail; @@ -337,20 +332,22 @@ 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); + if (get_tag_value(buf, sizeof(buf), line, "Manufacturer=", "") < 0) { + if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) { + goto fail; + } else { + pstrcpy(prod_name, sizeof(prod_name), buf); + } + } else { + pstrcpy(manf_name, sizeof(manf_name), buf); + } } 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); + ret = func(opaque, bus_num, addr, vendor_id, product_id, spec_version, + manf_name, prod_name); } the_end: fclose(f); @@ -364,10 +361,11 @@ int addr; } FindDeviceState; -static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, - int class_id, - int vendor_id, int product_id, - const char *product_name, int speed) +static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, + int vendor_id, int product_id, + const char *spec_version, + const char *manf_string, + const char *prod_string) { FindDeviceState *s = opaque; if (vendor_id == s->vendor_id && @@ -386,108 +384,38 @@ static int usb_host_find_device(int *pbus_num, int *paddr, const char *devname) { - const char *p; - int ret; FindDeviceState fs; - p = strchr(devname, '.'); - if (p) { - *pbus_num = strtoul(devname, NULL, 0); - *paddr = strtoul(p + 1, NULL, 0); - return 0; - } - p = strchr(devname, ':'); - if (p) { - fs.vendor_id = strtoul(devname, NULL, 16); - fs.product_id = strtoul(p + 1, NULL, 16); - ret = usb_host_scan(&fs, usb_host_find_device_scan); - if (ret) { - *pbus_num = fs.bus_num; - *paddr = fs.addr; - return 0; + if (sscanf(devname, "host:%03d:%03d", pbus_num, paddr) != 2) { + if (sscanf(devname, "host:%04xx%04x", &fs.vendor_id, &fs.product_id) == 2) { + if (usb_host_scan(&fs, usb_host_find_device_scan)) { + *pbus_num = fs.bus_num; + *paddr = fs.addr; + return 0; + } else { + return -1; + } + } else { + return -1; } + } else { + return 0; } - return -1; } /**********************/ /* USB host device info */ -struct usb_class_info { - int class; - const char *class_name; -}; - -static const struct usb_class_info usb_class_info[] = { - { USB_CLASS_AUDIO, "Audio"}, - { USB_CLASS_COMM, "Communication"}, - { USB_CLASS_HID, "HID"}, - { USB_CLASS_HUB, "Hub" }, - { USB_CLASS_PHYSICAL, "Physical" }, - { USB_CLASS_PRINTER, "Printer" }, - { USB_CLASS_MASS_STORAGE, "Storage" }, - { USB_CLASS_CDC_DATA, "Data" }, - { USB_CLASS_APP_SPEC, "Application Specific" }, - { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, - { USB_CLASS_STILL_IMAGE, "Still Image" }, - { USB_CLASS_CSCID, "Smart Card" }, - { USB_CLASS_CONTENT_SEC, "Content Security" }, - { -1, NULL } -}; - -static const char *usb_class_str(uint8_t class) -{ - const struct usb_class_info *p; - for(p = usb_class_info; p->class != -1; p++) { - if (p->class == class) - break; - } - return p->class_name; -} - -void usb_info_device(int bus_num, int addr, int class_id, - int vendor_id, int product_id, - const char *product_name, - int speed) -{ - const char *class_str, *speed_str; - - switch(speed) { - case USB_SPEED_LOW: - speed_str = "1.5"; - break; - case USB_SPEED_FULL: - speed_str = "12"; - break; - case USB_SPEED_HIGH: - speed_str = "480"; - break; - default: - speed_str = "?"; - break; - } - - term_printf(" Device %d.%d, speed %s Mb/s\n", - bus_num, addr, speed_str); - class_str = usb_class_str(class_id); - if (class_str) - term_printf(" %s:", class_str); - else - term_printf(" Class %02x:", class_id); - term_printf(" USB device %04x:%04x", vendor_id, product_id); - if (product_name[0] != '\0') - term_printf(", %s", product_name); - term_printf("\n"); -} - static int usb_host_info_device(void *opaque, int bus_num, int addr, - int class_id, - int vendor_id, int product_id, - const char *product_name, - int speed) -{ - usb_info_device(bus_num, addr, class_id, vendor_id, product_id, - product_name, speed); + int vendor_id, int product_id, + const char *spec_ver, + const char *manf_string, + const char *prod_string) +{ + term_printf(" Device host:%03d:%03d, Manufacturer %s, Product %s\n", + bus_num, addr, manf_string, prod_string ); + term_printf(" VendorID:ProductID %04xx%04x, USB-Standard: %s\n", + vendor_id, product_id, spec_ver ); return 0; } --- a/qemu/usb-libusb.c 2006-04-22 21:59:14.000000000 -0500 +++ b/qemu/usb-libusb.c 2006-04-22 22:03:02.000000000 -0500 @@ -368,12 +368,7 @@ /**********************/ /* USB host device info */ -struct usb_class_info { - int class; - const char *class_name; -}; - void usb_host_info_device( struct usb_bus *bus, struct usb_device *dev, struct usb_dev_handle *handle ) { char str1[256], str2[256]; --- a/qemu/hw/usb-hub.c 2006-04-22 21:59:14.000000000 -0500 +++ b/qemu/hw/usb-hub.c 2006-04-22 13:51:23.000000000 -0500 @@ -177,7 +177,7 @@ int i; if (dev) { - if (portnum >= MAX_PORTS || portnum < 0) { + if (portnum >= s->nb_ports || portnum < 0) { #ifdef DEBUG printf( "This usb hub port does not exist.\n" ); #endif @@ -188,7 +188,7 @@ printf( "Hub Port %i is allready occupied! \n", portnum ); #endif portnum= -1; - for (i= 0; i < MAX_PORTS; i++) { + for (i= 0; i < s->nb_ports; i++) { if (s->ports[i].dev == NULL) { #ifdef DEBUG printf( "Will use Hub Port %i instead! \n", i ); --------------070006000003000101080402--