diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2011-08-29 12:49:46 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2012-01-17 09:44:50 +0100 |
commit | d8e17efdecaaa1a2d5c8f422fc44ae229e7f4fb4 (patch) | |
tree | 367a6b5453fc02d0b9b2b33d1a6da607fe1d83a4 /usb-linux.c | |
parent | 62c6ae04cf4334ef2ab5ef04581394850f4ea714 (diff) |
usb: add USBEndpoint
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 <kraxel@redhat.com>
Diffstat (limited to 'usb-linux.c')
-rw-r--r-- | usb-linux.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/usb-linux.c b/usb-linux.c index ded0726dad..9967975f2b 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -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); } |