Skip to contentSkip to conversation

Guest OS hangs on usb_add

PATCH New TJ 1 participant 1 message Jun 24, 2010

lore
Share & tools
lore

TJ

author
#0 lore raw

PATCH 1/1 Guest OS hangs on usb_add

This is a small patch to sligtly "intelligentify" usb device and config descriptor parsing and to handle bug with certain usb device reporting device desriptor length as 0x18 (instead of 18)

---
 hw/usb.h    |    5 +++++
 usb-linux.c |   36 +++++++++++++++++++++---------------
 2 files changed, 26 insertions(+), 15 deletions(-)
hw/usb.h +5 -0
index 00d2802..5c3528f 100644
@@ -117,6 +117,11 @@
 #define USB_DT_INTERFACE		0x04
 #define USB_DT_ENDPOINT			0x05
 
+#define USB_DT_DEVICE_LEN		18
+#define USB_DT_CONFIG_LEN		9
+#define USB_DT_INTERFACE_LEN		9
+#define USB_DT_ENDPOINT_LEN		7
+
 #define USB_ENDPOINT_XFER_CONTROL	0
 #define USB_ENDPOINT_XFER_ISOC		1
 #define USB_ENDPOINT_XFER_BULK		2
usb-linux.c +1 -1
index 88273ff..3ff0856 100644
@@ -288,7 +288,7 @@ static void async_cancel(USBPacket *unused, void *opaque)
 
 static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
 {
-    int dev_descr_len, config_descr_len;
+    int dev_descr_len, config_descr_total_len;
     int interface, nb_interfaces;
     int ret, i;
 
@@ -297,32 +297,38 @@ static int usb_host_claim_interfaces(USBHostDevice *dev,

int configuration)

     DPRINTF("husb: claiming interfaces. config %d\n", configuration);
-    i = 0;
     dev_descr_len = dev->descr[0];

- if (dev_descr_len > dev->descr_len) {
+ if (dev_descr_len == 0x18)
+ dev_descr_len = USB_DT_DEVICE_LEN; /* for buggy device(s) reporting len
in hex */
+
+ if (dev_descr_len > dev->descr_len || dev_descr_len < USB_DT_DEVICE_LEN ||
dev->descr[1] != USB_DT_DEVICE) {

+        fprintf(stderr, "husb: invalid device descriptor\n");
         goto fail;
     }
-    i += dev_descr_len;
-    while (i < dev->descr_len) {
+    for (i = dev_descr_len; i < dev->descr_len; ) {
         DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
                 i, dev->descr_len,
                dev->descr[i], dev->descr[i+1]);

- if (dev->descr[i+1] != USB_DT_CONFIG) {
- i += dev->descr[i];
- continue;
+ if (dev->descr[i] < 2) {
+ fprintf(stderr, "husb: invalid descriptor\n");

+            goto fail;
         }

- config_descr_len = dev->descr[i];
+ if (dev->descr[i+1] == USB_DT_CONFIG) {
+ config_descr_total_len = dev->descr[i+2] + (dev->descr[i+3] << 8);

- printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
+ printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);

- if (configuration < 0 || configuration == dev->descr[i + 5]) {
- configuration = dev->descr[i + 5];
- break;
- }
+ if (configuration < 0 || configuration == dev->descr[i + 5]) {
+ configuration = dev->descr[i + 5];
+ break;
+ }

- i += config_descr_len;
+ i += config_descr_total_len;
+ }
+ else

+            i += dev->descr[i];
     }

     if (i >= dev->descr_len) {