summaryrefslogtreecommitdiff
path: root/emulators/qemu-devel/files/patch-usb-hubfixups
diff options
context:
space:
mode:
Diffstat (limited to 'emulators/qemu-devel/files/patch-usb-hubfixups')
-rw-r--r--emulators/qemu-devel/files/patch-usb-hubfixups87
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];