diff options
Diffstat (limited to 'emulators/qemu-devel/files/patch-usb-hubfixups')
-rw-r--r-- | emulators/qemu-devel/files/patch-usb-hubfixups | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/emulators/qemu-devel/files/patch-usb-hubfixups b/emulators/qemu-devel/files/patch-usb-hubfixups new file mode 100644 index 000000000000..17db3bd32806 --- /dev/null +++ b/emulators/qemu-devel/files/patch-usb-hubfixups @@ -0,0 +1,87 @@ +Index: qemu/hw/usb.c +@@ -330,9 +330,9 @@ + 0x0a, /* u16 wHubCharacteristics; */ + 0x00, /* (per-port OC, no power switching) */ + 0x01, /* u8 bPwrOn2pwrGood; 2ms */ +- 0x00, /* u8 bHubContrCurrent; 0 mA */ +- 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */ +- 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */ ++ 0x00 /* u8 bHubContrCurrent; 0 mA */ ++ ++ /* DeviceRemovable and PortPwrCtrlMask patched in later */ + }; + + static void usb_hub_attach(USBPort *port1, USBDevice *dev) +@@ -391,6 +391,12 @@ + } + ret = 0; + break; ++ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: ++ if (value == 0 && index != 0x81) { /* clear ep halt */ ++ goto fail; ++ } ++ ret = 0; ++ break; + case DeviceOutRequest | USB_REQ_SET_FEATURE: + if (value == USB_DEVICE_REMOTE_WAKEUP) { + dev->remote_wakeup = 1; +@@ -408,6 +414,11 @@ + case USB_DT_DEVICE: + memcpy(data, qemu_hub_dev_descriptor, + sizeof(qemu_hub_dev_descriptor)); ++ ++ /* status change endpoint size based on number ++ * of ports */ ++ data[22] = (s->nb_ports + 1 + 7) / 8; ++ + ret = sizeof(qemu_hub_dev_descriptor); + break; + case USB_DT_CONFIG: +@@ -558,11 +569,29 @@ + } + break; + case GetHubDescriptor: +- memcpy(data, qemu_hub_hub_descriptor, +- sizeof(qemu_hub_hub_descriptor)); +- data[2] = s->nb_ports; +- ret = sizeof(qemu_hub_hub_descriptor); +- break; ++ { ++ unsigned int n, limit, var_hub_size = 0; ++ memcpy(data, qemu_hub_hub_descriptor, ++ sizeof(qemu_hub_hub_descriptor)); ++ data[2] = s->nb_ports; ++ ++ /* fill DeviceRemovable bits */ ++ limit = ((s->nb_ports + 1 + 7) / 8) + 7; ++ for (n = 7; n < limit; n++) { ++ data[n] = 0x00; ++ var_hub_size++; ++ } ++ ++ /* fill PortPwrCtrlMask bits */ ++ limit = limit + ((s->nb_ports + 7) / 8); ++ for (;n < limit; n++) { ++ data[n] = 0xff; ++ var_hub_size++; ++ } ++ ++ ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size; ++ break; ++ } + default: + fail: + ret = USB_RET_STALL; +@@ -584,8 +613,11 @@ + unsigned int status; + int i, n; + n = (s->nb_ports + 1 + 7) / 8; +- if (n > len) ++ if (len == 1) { /* FreeBSD workaround */ ++ n = 1; ++ } else if (n > len) { + return USB_RET_BABBLE; ++ } + status = 0; + for(i = 0; i < s->nb_ports; i++) { + port = &s->ports[i]; |