]> Git Repo - qemu.git/commitdiff
usb: add USBEndpoint
authorGerd Hoffmann <[email protected]>
Mon, 29 Aug 2011 10:49:46 +0000 (12:49 +0200)
committerGerd Hoffmann <[email protected]>
Tue, 17 Jan 2012 08:44:50 +0000 (09:44 +0100)
Start maintaining endpoint state at USBDevice level.  Add USBEndpoint
struct and some helper functions to deal with it.  For now it contains
the endpoint type only.  Moved over some bits from usb-linux.c

Signed-off-by: Gerd Hoffmann <[email protected]>
hw/usb-bus.c
hw/usb.c
hw/usb.h
usb-linux.c

index bd4afa7e2b9dfd9c68ce2239442b99a18cf43206..016a3f2bb40ca39384280e08c87c42fe966632ba 100644 (file)
@@ -75,6 +75,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     dev->info = info;
     dev->auto_attach = 1;
     QLIST_INIT(&dev->strings);
+    usb_ep_init(dev);
     rc = usb_claim_port(dev);
     if (rc != 0) {
         return rc;
index 2216efe077a1f84075005d51ef75cc62261d75e3..5d6baaf490708a4bb289d72dae422b5b45ea2da4 100644 (file)
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -414,3 +414,33 @@ void usb_packet_cleanup(USBPacket *p)
 {
     qemu_iovec_destroy(&p->iov);
 }
+
+void usb_ep_init(USBDevice *dev)
+{
+    int ep;
+
+    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;
+    }
+}
+
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev->ep_in : dev->ep_out;
+    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;
+}
index b2c9479594703be5dc4474008680e588f7083cd7..85cbe71f6350788eb1a3a8dd79eee4de3750b479 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
 #define USB_ENDPOINT_XFER_ISOC         1
 #define USB_ENDPOINT_XFER_BULK         2
 #define USB_ENDPOINT_XFER_INT          3
+#define USB_ENDPOINT_XFER_INVALID     255
 
 typedef struct USBBus USBBus;
 typedef struct USBBusOps USBBusOps;
@@ -151,6 +152,7 @@ typedef struct USBPort USBPort;
 typedef struct USBDevice USBDevice;
 typedef struct USBDeviceInfo USBDeviceInfo;
 typedef struct USBPacket USBPacket;
+typedef struct USBEndpoint USBEndpoint;
 
 typedef struct USBDesc USBDesc;
 typedef struct USBDescID USBDescID;
@@ -171,6 +173,10 @@ struct USBDescString {
 #define USB_MAX_ENDPOINTS  15
 #define USB_MAX_INTERFACES 16
 
+struct USBEndpoint {
+    uint8_t type;
+};
+
 /* definition of a USB device */
 struct USBDevice {
     DeviceState qdev;
@@ -196,6 +202,9 @@ struct USBDevice {
     int32_t setup_len;
     int32_t setup_index;
 
+    USBEndpoint ep_in[USB_MAX_ENDPOINTS];
+    USBEndpoint ep_out[USB_MAX_ENDPOINTS];
+
     QLIST_HEAD(, USBDescString) strings;
     const USBDescDevice *device;
 
@@ -322,6 +331,11 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
 
+void usb_ep_init(USBDevice *dev);
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type);
+
 void usb_attach(USBPort *port);
 void usb_detach(USBPort *port);
 void usb_reset(USBPort *port);
index ded0726dade20daaa0cb2f49d5240f6409aa00b7..9967975f2be2cae82a5507c80211d533ac0a9e23 100644 (file)
@@ -67,12 +67,10 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
 #endif
 
 #define PRODUCT_NAME_SZ 32
-#define MAX_ENDPOINTS 15
 #define MAX_PORTLEN 16
 
 /* endpoint association data */
 #define ISO_FRAME_DESC_PER_URB 32
-#define INVALID_EP_TYPE 255
 
 /* devio.c limits single requests to 16k */
 #define MAX_USBFS_BUFFER_SIZE 16384
@@ -80,7 +78,6 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
 typedef struct AsyncURB AsyncURB;
 
 struct endp_data {
-    uint8_t type;
     uint8_t halted;
     uint8_t iso_started;
     AsyncURB *iso_urb;
@@ -110,8 +107,8 @@ typedef struct USBHostDevice {
     uint32_t  iso_urb_count;
     Notifier  exit;
 
-    struct endp_data ep_in[MAX_ENDPOINTS];
-    struct endp_data ep_out[MAX_ENDPOINTS];
+    struct endp_data ep_in[USB_MAX_ENDPOINTS];
+    struct endp_data ep_out[USB_MAX_ENDPOINTS];
     QLIST_HEAD(, AsyncURB) aurbs;
 
     /* Host side address */
@@ -133,6 +130,19 @@ static int usb_host_read_file(char *line, size_t line_size,
                             const char *device_file, const char *device_name);
 static int usb_linux_update_endp_table(USBHostDevice *s);
 
+static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
+{
+    static const int usbfs[] = {
+        [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL,
+        [USB_ENDPOINT_XFER_ISOC]    = USBDEVFS_URB_TYPE_ISO,
+        [USB_ENDPOINT_XFER_BULK]    = USBDEVFS_URB_TYPE_BULK,
+        [USB_ENDPOINT_XFER_INT]     = USBDEVFS_URB_TYPE_INTERRUPT,
+    };
+    uint8_t type = usb_ep_get_type(&s->dev, p->pid, p->devep);
+    assert(type < ARRAY_SIZE(usbfs));
+    return usbfs[type];
+}
+
 static int usb_host_do_reset(USBHostDevice *dev)
 {
     struct timeval s, e;
@@ -156,18 +166,18 @@ static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
 {
     struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
     assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
-    assert(ep > 0 && ep <= MAX_ENDPOINTS);
+    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
     return eps + ep - 1;
 }
 
 static int is_isoc(USBHostDevice *s, int pid, int ep)
 {
-    return get_endp(s, pid, ep)->type == USBDEVFS_URB_TYPE_ISO;
+    return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC;
 }
 
 static int is_valid(USBHostDevice *s, int pid, int ep)
 {
-    return get_endp(s, pid, ep)->type != INVALID_EP_TYPE;
+    return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID;
 }
 
 static int is_halted(USBHostDevice *s, int pid, int ep)
@@ -896,7 +906,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
 
         urb = &aurb->urb;
         urb->endpoint      = ep;
-        urb->type          = USBDEVFS_URB_TYPE_BULK;
+        urb->type          = usb_host_usbfs_type(s, p);
         urb->usercontext   = s;
         urb->buffer        = pbuf;
         urb->buffer_length = prem;
@@ -992,7 +1002,7 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
 
     trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
 
-    for (i = 1; i <= MAX_ENDPOINTS; i++) {
+    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
         if (is_isoc(s, USB_TOKEN_IN, i)) {
             usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
         }
@@ -1126,10 +1136,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
     int interface, length, i, ep, pid;
     struct endp_data *epd;
 
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        s->ep_in[i].type = INVALID_EP_TYPE;
-        s->ep_out[i].type = INVALID_EP_TYPE;
-    }
+    usb_ep_init(&s->dev);
 
     if (s->dev.configuration == 0) {
         /* not configured yet -- leave all endpoints disabled */
@@ -1192,27 +1199,15 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
                 return 1;
             }
 
-            switch (descriptors[i + 3] & 0x3) {
-            case 0x00:
-                type = USBDEVFS_URB_TYPE_CONTROL;
-                break;
-            case 0x01:
-                type = USBDEVFS_URB_TYPE_ISO;
+            type = descriptors[i + 3] & 0x3;
+            if (type == USB_ENDPOINT_XFER_ISOC) {
                 set_max_packet_size(s, pid, ep, descriptors + i);
-                break;
-            case 0x02:
-                type = USBDEVFS_URB_TYPE_BULK;
-                break;
-            case 0x03:
-                type = USBDEVFS_URB_TYPE_INTERRUPT;
-                break;
-            default:
-                DPRINTF("usb_host: malformed endpoint type\n");
-                type = USBDEVFS_URB_TYPE_BULK;
-            }
+            };
+            assert(usb_ep_get_type(&s->dev, pid, ep) ==
+                   USB_ENDPOINT_XFER_INVALID);
+            usb_ep_set_type(&s->dev, pid, ep, type);
+
             epd = get_endp(s, pid, ep);
-            assert(epd->type == INVALID_EP_TYPE);
-            epd->type = type;
             epd->halted = 0;
 
             i += descriptors[i];
@@ -1371,7 +1366,7 @@ static int usb_host_close(USBHostDevice *dev)
 
     qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
     dev->closing = 1;
-    for (i = 1; i <= MAX_ENDPOINTS; i++) {
+    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
         if (is_isoc(dev, USB_TOKEN_IN, i)) {
             usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
         }
This page took 0.036873 seconds and 4 git commands to generate.