qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] Large USB patch


From: Lonnie Mendez
Subject: Re: [Qemu-devel] Large USB patch
Date: Sat, 22 Apr 2006 22:38:31 -0500
User-agent: Mozilla Thunderbird 1.0.7 (X11/20050923)

address@hidden wrote:

Lonnie Mendez wrote:
address@hidden 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.

--- 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 );

reply via email to

[Prev in Thread] Current Thread [Next in Thread]