usb: link packets to endpoints not devices

Add USBEndpoint for the control endpoint to USBDevices.  Link async
packets to the USBEndpoint instead of the USBDevice.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 7c926c0..a305661 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -715,7 +715,8 @@
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
-        if (q->packet.owner != dev) {
+        if (q->packet.owner == NULL ||
+            q->packet.owner->dev != dev) {
             continue;
         }
         ehci_free_queue(q);
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 01e2e7c..4f528d2 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -812,7 +812,8 @@
 
     for (ep = 0; ep < 16; ep++) {
         for (dir = 0; dir < 2; dir++) {
-            if (s->ep[ep].packey[dir].p.owner != dev) {
+            if (s->ep[ep].packey[dir].p.owner == NULL ||
+                s->ep[ep].packey[dir].p.owner->dev != dev) {
                 continue;
             }
             usb_cancel_packet(&s->ep[ep].packey[dir].p);
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 81488c4..69463d2 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1707,7 +1707,9 @@
 
 static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
 {
-    if (ohci->async_td && ohci->usb_packet.owner == dev) {
+    if (ohci->async_td &&
+        ohci->usb_packet.owner != NULL &&
+        ohci->usb_packet.owner->dev == dev) {
         usb_cancel_packet(&ohci->usb_packet);
         ohci->async_td = 0;
     }
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index f8912e2..25d4e8c 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -245,7 +245,8 @@
     UHCIAsync *curr, *n;
 
     QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
-        if (curr->packet.owner != dev) {
+        if (curr->packet.owner == NULL ||
+            curr->packet.owner->dev != dev) {
             continue;
         }
         uhci_async_unlink(s, curr);
diff --git a/hw/usb.c b/hw/usb.c
index 0f163b4..860538a 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -329,7 +329,7 @@
     ret = dev->info->handle_packet(dev, p);
     if (ret == USB_RET_ASYNC) {
         if (p->owner == NULL) {
-            p->owner = dev;
+            p->owner = usb_ep_get(dev, p->pid, p->devep);
         } else {
             /* We'll end up here when usb_handle_packet is called
              * recursively due to a hub being in the chain.  Nothing
@@ -357,7 +357,7 @@
 void usb_cancel_packet(USBPacket * p)
 {
     assert(p->owner != NULL);
-    p->owner->info->cancel_packet(p->owner, p);
+    p->owner->dev->info->cancel_packet(p->owner->dev, p);
     p->owner = NULL;
 }
 
@@ -419,11 +419,16 @@
 {
     int ep;
 
+    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
+    dev->ep_ctl.ifnum = 0;
+    dev->ep_ctl.dev = dev;
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
         dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
         dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
         dev->ep_in[ep].ifnum = 0;
         dev->ep_out[ep].ifnum = 0;
+        dev->ep_in[ep].dev = dev;
+        dev->ep_out[ep].dev = dev;
     }
 }
 
@@ -472,6 +477,9 @@
 struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
 {
     struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev->ep_in : dev->ep_out;
+    if (ep == 0) {
+        return &dev->ep_ctl;
+    }
     assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
     assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
     return eps + ep - 1;
diff --git a/hw/usb.h b/hw/usb.h
index 5ea984c..0776463 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -177,6 +177,7 @@
     uint8_t type;
     uint8_t ifnum;
     int max_packet_size;
+    USBDevice *dev;
 };
 
 /* definition of a USB device */
@@ -204,6 +205,7 @@
     int32_t setup_len;
     int32_t setup_index;
 
+    USBEndpoint ep_ctl;
     USBEndpoint ep_in[USB_MAX_ENDPOINTS];
     USBEndpoint ep_out[USB_MAX_ENDPOINTS];
 
@@ -317,7 +319,7 @@
     QEMUIOVector iov;
     int result; /* transfer length or USB_RET_* status code */
     /* Internal use by the USB layer.  */
-    USBDevice *owner;
+    USBEndpoint *owner;
 };
 
 void usb_packet_init(USBPacket *p);