summary refs log tree commit diff stats
path: root/hw/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb.c')
-rw-r--r--hw/usb.c125
1 files changed, 123 insertions, 2 deletions
diff --git a/hw/usb.c b/hw/usb.c
index 2216efe077..860538ad3b 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -329,7 +329,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
     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_packet_complete(USBDevice *dev, USBPacket *p)
 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;
 }
 
@@ -414,3 +414,124 @@ void usb_packet_cleanup(USBPacket *p)
 {
     qemu_iovec_destroy(&p->iov);
 }
+
+void usb_ep_init(USBDevice *dev)
+{
+    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;
+    }
+}
+
+void usb_ep_dump(USBDevice *dev)
+{
+    static const char *tname[] = {
+        [USB_ENDPOINT_XFER_CONTROL] = "control",
+        [USB_ENDPOINT_XFER_ISOC]    = "isoc",
+        [USB_ENDPOINT_XFER_BULK]    = "bulk",
+        [USB_ENDPOINT_XFER_INT]     = "int",
+    };
+    int ifnum, ep, first;
+
+    fprintf(stderr, "Device \"%s\", config %d\n",
+            dev->product_desc, dev->configuration);
+    for (ifnum = 0; ifnum < 16; ifnum++) {
+        first = 1;
+        for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+            if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
+                dev->ep_in[ep].ifnum == ifnum) {
+                if (first) {
+                    first = 0;
+                    fprintf(stderr, "  Interface %d, alternative %d\n",
+                            ifnum, dev->altsetting[ifnum]);
+                }
+                fprintf(stderr, "    Endpoint %d, IN, %s, %d max\n", ep,
+                        tname[dev->ep_in[ep].type],
+                        dev->ep_in[ep].max_packet_size);
+            }
+            if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
+                dev->ep_out[ep].ifnum == ifnum) {
+                if (first) {
+                    first = 0;
+                    fprintf(stderr, "  Interface %d, alternative %d\n",
+                            ifnum, dev->altsetting[ifnum]);
+                }
+                fprintf(stderr, "    Endpoint %d, OUT, %s, %d max\n", ep,
+                        tname[dev->ep_out[ep].type],
+                        dev->ep_out[ep].max_packet_size);
+            }
+        }
+    }
+    fprintf(stderr, "--\n");
+}
+
+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;
+}
+
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->type;
+}
+
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->type = type;
+}
+
+uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->ifnum;
+}
+
+void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->ifnum = ifnum;
+}
+
+void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
+                                uint16_t raw)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    int size, microframes;
+
+    size = raw & 0x7ff;
+    switch ((raw >> 11) & 3) {
+    case 1:
+        microframes = 2;
+        break;
+    case 2:
+        microframes = 3;
+        break;
+    default:
+        microframes = 1;
+        break;
+    }
+    uep->max_packet_size = size * microframes;
+}
+
+int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->max_packet_size;
+}