Commit b9dc033c0dea8e1113110a903799c5b31bb2104d

Authored by balrog
1 parent 80f515e6

USB iso transfers support for the linux redirector and for UHCI, by Arnon Gilboa.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3328 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 621 additions and 89 deletions
hw/usb-uhci.c
... ... @@ -25,6 +25,7 @@
25 25  
26 26 //#define DEBUG
27 27 //#define DEBUG_PACKET
  28 +//#define DEBUG_ISOCH
28 29  
29 30 #define UHCI_CMD_FGR (1 << 4)
30 31 #define UHCI_CMD_EGSM (1 << 3)
... ... @@ -88,6 +89,7 @@ typedef struct UHCIState {
88 89 other queues will not be processed until the next frame. The solution
89 90 is to allow multiple pending requests. */
90 91 uint32_t async_qh;
  92 + uint32_t async_frame_addr;
91 93 USBPacket usb_packet;
92 94 uint8_t usb_buf[2048];
93 95 } UHCIState;
... ... @@ -146,6 +148,58 @@ static void uhci_reset(UHCIState *s)
146 148 }
147 149 }
148 150  
  151 +static void uhci_save(QEMUFile *f, void *opaque)
  152 +{
  153 + UHCIState *s = opaque;
  154 + uint8_t num_ports = NB_PORTS;
  155 + int i;
  156 +
  157 + pci_device_save(&s->dev, f);
  158 +
  159 + qemu_put_8s(f, &num_ports);
  160 + for (i = 0; i < num_ports; ++i)
  161 + qemu_put_be16s(f, &s->ports[i].ctrl);
  162 + qemu_put_be16s(f, &s->cmd);
  163 + qemu_put_be16s(f, &s->status);
  164 + qemu_put_be16s(f, &s->intr);
  165 + qemu_put_be16s(f, &s->frnum);
  166 + qemu_put_be32s(f, &s->fl_base_addr);
  167 + qemu_put_8s(f, &s->sof_timing);
  168 + qemu_put_8s(f, &s->status2);
  169 + qemu_put_timer(f, s->frame_timer);
  170 +}
  171 +
  172 +static int uhci_load(QEMUFile *f, void *opaque, int version_id)
  173 +{
  174 + UHCIState *s = opaque;
  175 + uint8_t num_ports;
  176 + int i, ret;
  177 +
  178 + if (version_id > 1)
  179 + return -EINVAL;
  180 +
  181 + ret = pci_device_load(&s->dev, f);
  182 + if (ret < 0)
  183 + return ret;
  184 +
  185 + qemu_get_8s(f, &num_ports);
  186 + if (num_ports != NB_PORTS)
  187 + return -EINVAL;
  188 +
  189 + for (i = 0; i < num_ports; ++i)
  190 + qemu_get_be16s(f, &s->ports[i].ctrl);
  191 + qemu_get_be16s(f, &s->cmd);
  192 + qemu_get_be16s(f, &s->status);
  193 + qemu_get_be16s(f, &s->intr);
  194 + qemu_get_be16s(f, &s->frnum);
  195 + qemu_get_be32s(f, &s->fl_base_addr);
  196 + qemu_get_8s(f, &s->sof_timing);
  197 + qemu_get_8s(f, &s->status2);
  198 + qemu_get_timer(f, s->frame_timer);
  199 +
  200 + return 0;
  201 +}
  202 +
149 203 static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
150 204 {
151 205 UHCIState *s = opaque;
... ... @@ -449,10 +503,11 @@ static void uhci_async_complete_packet(USBPacket * packet, void *opaque);
449 503 0 if TD successful
450 504 1 if TD unsuccessful or inactive
451 505 */
452   -static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
  506 +static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask,
  507 + int completion)
453 508 {
454 509 uint8_t pid;
455   - int len, max_len, err, ret;
  510 + int len = 0, max_len, err, ret = 0;
456 511  
457 512 /* ??? This is wrong for async completion. */
458 513 if (td->ctrl & TD_CTRL_IOC) {
... ... @@ -465,7 +520,8 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
465 520 /* TD is active */
466 521 max_len = ((td->token >> 21) + 1) & 0x7ff;
467 522 pid = td->token & 0xff;
468   - if (s->async_qh) {
  523 +
  524 + if (completion && (s->async_qh || s->async_frame_addr)) {
469 525 ret = s->usb_packet.len;
470 526 if (ret >= 0) {
471 527 len = ret;
... ... @@ -481,7 +537,8 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
481 537 len = 0;
482 538 }
483 539 s->async_qh = 0;
484   - } else {
  540 + s->async_frame_addr = 0;
  541 + } else if (!completion) {
485 542 s->usb_packet.pid = pid;
486 543 s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
487 544 s->usb_packet.devep = (td->token >> 15) & 0xf;
... ... @@ -519,6 +576,7 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
519 576 return -1;
520 577 }
521 578 }
  579 +
522 580 if (ret == USB_RET_ASYNC) {
523 581 return 2;
524 582 }
... ... @@ -584,8 +642,42 @@ static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
584 642 uint32_t link;
585 643 uint32_t old_td_ctrl;
586 644 uint32_t val;
  645 + uint32_t frame_addr;
587 646 int ret;
588 647  
  648 + /* Handle async isochronous packet completion */
  649 + frame_addr = s->async_frame_addr;
  650 + if (frame_addr) {
  651 + cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
  652 + le32_to_cpus(&link);
  653 +
  654 + cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
  655 + le32_to_cpus(&td.link);
  656 + le32_to_cpus(&td.ctrl);
  657 + le32_to_cpus(&td.token);
  658 + le32_to_cpus(&td.buffer);
  659 + old_td_ctrl = td.ctrl;
  660 + ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
  661 +
  662 + /* update the status bits of the TD */
  663 + if (old_td_ctrl != td.ctrl) {
  664 + val = cpu_to_le32(td.ctrl);
  665 + cpu_physical_memory_write((link & ~0xf) + 4,
  666 + (const uint8_t *)&val,
  667 + sizeof(val));
  668 + }
  669 + if (ret == 2) {
  670 + s->async_frame_addr = frame_addr;
  671 + } else if (ret == 0) {
  672 + /* update qh element link */
  673 + val = cpu_to_le32(td.link);
  674 + cpu_physical_memory_write(frame_addr,
  675 + (const uint8_t *)&val,
  676 + sizeof(val));
  677 + }
  678 + return;
  679 + }
  680 +
589 681 link = s->async_qh;
590 682 if (!link) {
591 683 /* This should never happen. It means a TD somehow got removed
... ... @@ -604,7 +696,8 @@ static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
604 696 le32_to_cpus(&td.token);
605 697 le32_to_cpus(&td.buffer);
606 698 old_td_ctrl = td.ctrl;
607   - ret = uhci_handle_td(s, &td, &s->pending_int_mask);
  699 + ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
  700 +
608 701 /* update the status bits of the TD */
609 702 if (old_td_ctrl != td.ctrl) {
610 703 val = cpu_to_le32(td.ctrl);
... ... @@ -697,7 +790,8 @@ static void uhci_frame_timer(void *opaque)
697 790 le32_to_cpus(&td.token);
698 791 le32_to_cpus(&td.buffer);
699 792 old_td_ctrl = td.ctrl;
700   - ret = uhci_handle_td(s, &td, &int_mask);
  793 + ret = uhci_handle_td(s, &td, &int_mask, 0);
  794 +
701 795 /* update the status bits of the TD */
702 796 if (old_td_ctrl != td.ctrl) {
703 797 val = cpu_to_le32(td.ctrl);
... ... @@ -731,27 +825,23 @@ static void uhci_frame_timer(void *opaque)
731 825 le32_to_cpus(&td.ctrl);
732 826 le32_to_cpus(&td.token);
733 827 le32_to_cpus(&td.buffer);
734   - /* Ignore isochonous transfers while there is an async packet
735   - pending. This is wrong, but we don't implement isochronous
736   - transfers anyway. */
737   - if (s->async_qh == 0) {
738   - old_td_ctrl = td.ctrl;
739   - ret = uhci_handle_td(s, &td, &int_mask);
740   - /* update the status bits of the TD */
741   - if (old_td_ctrl != td.ctrl) {
742   - val = cpu_to_le32(td.ctrl);
743   - cpu_physical_memory_write((link & ~0xf) + 4,
744   - (const uint8_t *)&val,
745   - sizeof(val));
746   - }
747   - if (ret < 0)
748   - break; /* interrupted frame */
749   - if (ret == 2) {
750   - /* We can't handle async isochronous transfers.
751   - Cancel The packet. */
752   - fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
753   - usb_cancel_packet(&s->usb_packet);
754   - }
  828 +
  829 + /* Handle isochonous transfer. */
  830 + /* FIXME: might be more than one isoc in frame */
  831 + old_td_ctrl = td.ctrl;
  832 + ret = uhci_handle_td(s, &td, &int_mask, 0);
  833 +
  834 + /* update the status bits of the TD */
  835 + if (old_td_ctrl != td.ctrl) {
  836 + val = cpu_to_le32(td.ctrl);
  837 + cpu_physical_memory_write((link & ~0xf) + 4,
  838 + (const uint8_t *)&val,
  839 + sizeof(val));
  840 + }
  841 + if (ret < 0)
  842 + break; /* interrupted frame */
  843 + if (ret == 2) {
  844 + s->async_frame_addr = frame_addr;
755 845 }
756 846 link = td.link;
757 847 }
... ... @@ -767,6 +857,7 @@ static void uhci_frame_timer(void *opaque)
767 857 usb_cancel_packet(&s->usb_packet);
768 858 s->async_qh = 0;
769 859 }
  860 +
770 861 /* prepare the timer for the next frame */
771 862 expire_time = qemu_get_clock(vm_clock) +
772 863 (ticks_per_sec / FRAME_TIMER_FREQ);
... ... @@ -855,4 +946,3 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn)
855 946 pci_register_io_region(&s->dev, 4, 0x20,
856 947 PCI_ADDRESS_SPACE_IO, uhci_map);
857 948 }
858   -
... ...
usb-linux.c
... ... @@ -28,6 +28,7 @@
28 28 #include <sys/ioctl.h>
29 29 #include <linux/usbdevice_fs.h>
30 30 #include <linux/version.h>
  31 +#include <signal.h>
31 32  
32 33 /* We redefine it to avoid version problems */
33 34 struct usb_ctrltransfer {
... ... @@ -48,15 +49,172 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
48 49 const char *devname);
49 50  
50 51 //#define DEBUG
  52 +//#define DEBUG_ISOCH
  53 +//#define USE_ASYNCIO
51 54  
52 55 #define USBDEVFS_PATH "/proc/bus/usb"
53 56 #define PRODUCT_NAME_SZ 32
  57 +#define SIG_ISOCOMPLETE (SIGRTMIN+7)
  58 +#define MAX_ENDPOINTS 16
54 59  
  60 +struct sigaction sigact;
  61 +
  62 +/* endpoint association data */
  63 +struct endp_data {
  64 + uint8_t type;
  65 +};
  66 +
  67 +/* FIXME: move USBPacket to PendingURB */
55 68 typedef struct USBHostDevice {
56 69 USBDevice dev;
57 70 int fd;
  71 + USBPacket *packet;
  72 + struct endp_data endp_table[MAX_ENDPOINTS];
  73 + int configuration;
  74 + uint8_t descr[1024];
  75 + int descr_len;
  76 + int urbs_ready;
58 77 } USBHostDevice;
59 78  
  79 +typedef struct PendingURB {
  80 + struct usbdevfs_urb *urb;
  81 + USBHostDevice *dev;
  82 + QEMUBH *bh;
  83 + int status;
  84 + struct PendingURB *next;
  85 +} PendingURB;
  86 +
  87 +PendingURB *pending_urbs = NULL;
  88 +
  89 +int add_pending_urb(struct usbdevfs_urb *urb)
  90 +{
  91 + PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
  92 + if (purb) {
  93 + purb->urb = urb;
  94 + purb->dev = NULL;
  95 + purb->bh = NULL;
  96 + purb->status = 0;
  97 + purb->next = pending_urbs;
  98 + pending_urbs = purb;
  99 + return 1;
  100 + }
  101 + return 0;
  102 +}
  103 +
  104 +int del_pending_urb(struct usbdevfs_urb *urb)
  105 +{
  106 + PendingURB *purb = pending_urbs;
  107 + PendingURB *prev = NULL;
  108 +
  109 + while (purb && purb->urb != urb) {
  110 + prev = purb;
  111 + purb = purb->next;
  112 + }
  113 +
  114 + if (purb && purb->urb == urb) {
  115 + if (prev) {
  116 + prev->next = purb->next;
  117 + } else {
  118 + pending_urbs = purb->next;
  119 + }
  120 + qemu_free(purb);
  121 + return 1;
  122 + }
  123 + return 0;
  124 +}
  125 +
  126 +PendingURB *get_pending_urb(struct usbdevfs_urb *urb)
  127 +{
  128 + PendingURB *purb = pending_urbs;
  129 +
  130 + while (purb && purb->urb != urb) {
  131 + purb = purb->next;
  132 + }
  133 +
  134 + if (purb && purb->urb == urb) {
  135 + return purb;
  136 + }
  137 + return NULL;
  138 +}
  139 +
  140 +static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
  141 +{
  142 + int dev_descr_len, config_descr_len;
  143 + int interface, nb_interfaces, nb_configurations;
  144 + int ret, i;
  145 +
  146 + if (configuration == 0) /* address state - ignore */
  147 + return 1;
  148 +
  149 + i = 0;
  150 + dev_descr_len = dev->descr[0];
  151 + if (dev_descr_len > dev->descr_len)
  152 + goto fail;
  153 + nb_configurations = dev->descr[17];
  154 +
  155 + i += dev_descr_len;
  156 + while (i < dev->descr_len) {
  157 +#ifdef DEBUG
  158 + printf("i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
  159 + dev->descr[i], dev->descr[i+1]);
  160 +#endif
  161 + if (dev->descr[i+1] != USB_DT_CONFIG) {
  162 + i += dev->descr[i];
  163 + continue;
  164 + }
  165 + config_descr_len = dev->descr[i];
  166 +
  167 + if (configuration == dev->descr[i + 5])
  168 + break;
  169 +
  170 + i += config_descr_len;
  171 + }
  172 +
  173 + if (i >= dev->descr_len) {
  174 + printf("usb_host: error - device has no matching configuration\n");
  175 + goto fail;
  176 + }
  177 + nb_interfaces = dev->descr[i + 4];
  178 +
  179 +#ifdef USBDEVFS_DISCONNECT
  180 + /* earlier Linux 2.4 do not support that */
  181 + {
  182 + struct usbdevfs_ioctl ctrl;
  183 + for (interface = 0; interface < nb_interfaces; interface++) {
  184 + ctrl.ioctl_code = USBDEVFS_DISCONNECT;
  185 + ctrl.ifno = interface;
  186 + ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
  187 + if (ret < 0 && errno != ENODATA) {
  188 + perror("USBDEVFS_DISCONNECT");
  189 + goto fail;
  190 + }
  191 + }
  192 + }
  193 +#endif
  194 +
  195 + /* XXX: only grab if all interfaces are free */
  196 + for (interface = 0; interface < nb_interfaces; interface++) {
  197 + ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
  198 + if (ret < 0) {
  199 + if (errno == EBUSY) {
  200 + fprintf(stderr,
  201 + "usb_host: warning - device already grabbed\n");
  202 + } else {
  203 + perror("USBDEVFS_CLAIMINTERFACE");
  204 + }
  205 + fail:
  206 + return 0;
  207 + }
  208 + }
  209 +
  210 +#ifdef DEBUG
  211 + printf("usb_host: %d interfaces claimed for configuration %d\n",
  212 + nb_interfaces, configuration);
  213 +#endif
  214 +
  215 + return 1;
  216 +}
  217 +
60 218 static void usb_host_handle_reset(USBDevice *dev)
61 219 {
62 220 #if 0
... ... @@ -76,6 +234,8 @@ static void usb_host_handle_destroy(USBDevice *dev)
76 234 qemu_free(s);
77 235 }
78 236  
  237 +static int usb_linux_update_endp_table(USBHostDevice *s);
  238 +
79 239 static int usb_host_handle_control(USBDevice *dev,
80 240 int request,
81 241 int value,
... ... @@ -85,13 +245,33 @@ static int usb_host_handle_control(USBDevice *dev,
85 245 {
86 246 USBHostDevice *s = (USBHostDevice *)dev;
87 247 struct usb_ctrltransfer ct;
  248 + struct usbdevfs_setinterface si;
  249 + int intf_update_required = 0;
88 250 int ret;
89 251  
90 252 if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
91 253 /* specific SET_ADDRESS support */
92 254 dev->addr = value;
93 255 return 0;
  256 + } else if (request == ((USB_RECIP_INTERFACE << 8) |
  257 + USB_REQ_SET_INTERFACE)) {
  258 + /* set alternate setting for the interface */
  259 + si.interface = index;
  260 + si.altsetting = value;
  261 + ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
  262 + usb_linux_update_endp_table(s);
  263 + } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
  264 +#ifdef DEBUG
  265 + printf("usb_host_handle_control: SET_CONFIGURATION request - "
  266 + "config %d\n", value & 0xff);
  267 +#endif
  268 + if (s->configuration != (value & 0xff)) {
  269 + s->configuration = (value & 0xff);
  270 + intf_update_required = 1;
  271 + }
  272 + goto do_request;
94 273 } else {
  274 + do_request:
95 275 ct.bRequestType = request >> 8;
96 276 ct.bRequest = request;
97 277 ct.wValue = value;
... ... @@ -100,19 +280,28 @@ static int usb_host_handle_control(USBDevice *dev,
100 280 ct.timeout = 50;
101 281 ct.data = data;
102 282 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
103   - if (ret < 0) {
104   - switch(errno) {
105   - case ETIMEDOUT:
106   - return USB_RET_NAK;
107   - default:
108   - return USB_RET_STALL;
109   - }
110   - } else {
111   - return ret;
  283 + }
  284 +
  285 + if (ret < 0) {
  286 + switch(errno) {
  287 + case ETIMEDOUT:
  288 + return USB_RET_NAK;
  289 + default:
  290 + return USB_RET_STALL;
  291 + }
  292 + } else {
  293 + if (intf_update_required) {
  294 +#ifdef DEBUG
  295 + printf("usb_host_handle_control: updating interfaces\n");
  296 +#endif
  297 + usb_host_update_interfaces(s, value & 0xff);
112 298 }
113   - }
  299 + return ret;
  300 + }
114 301 }
115 302  
  303 +static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p);
  304 +
116 305 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
117 306 {
118 307 USBHostDevice *s = (USBHostDevice *)dev;
... ... @@ -120,6 +309,10 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
120 309 int ret;
121 310 uint8_t devep = p->devep;
122 311  
  312 + if (s->endp_table[p->devep - 1].type == USBDEVFS_URB_TYPE_ISO) {
  313 + return usb_host_handle_isoch(dev, p);
  314 + }
  315 +
123 316 /* XXX: optimize and handle all data types by looking at the
124 317 config descriptor */
125 318 if (p->pid == USB_TOKEN_IN)
... ... @@ -145,18 +338,276 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
145 338 }
146 339 }
147 340  
  341 +static void usb_linux_bh_cb(void *opaque);
  342 +
  343 +void isoch_done(int signum, siginfo_t *info, void *context) {
  344 + struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
  345 + USBHostDevice *s = (USBHostDevice *)urb->usercontext;
  346 + PendingURB *purb;
  347 +
  348 + if (info->si_code != SI_ASYNCIO ||
  349 + info->si_signo != SIG_ISOCOMPLETE) {
  350 + return;
  351 + }
  352 +
  353 + purb = get_pending_urb(urb);
  354 + if (purb) {
  355 + purb->bh = qemu_bh_new(usb_linux_bh_cb, purb);
  356 + if (purb->bh) {
  357 + purb->dev = s;
  358 + purb->status = info->si_errno;
  359 + qemu_bh_schedule(purb->bh);
  360 + }
  361 + }
  362 +}
  363 +
  364 +static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p)
  365 +{
  366 + USBHostDevice *s = (USBHostDevice *)dev;
  367 + struct usbdevfs_urb *urb, *purb = NULL;
  368 + int ret;
  369 + uint8_t devep = p->devep;
  370 +
  371 + if (p->pid == USB_TOKEN_IN)
  372 + devep |= 0x80;
  373 +
  374 + urb = qemu_mallocz(sizeof(struct usbdevfs_urb) +
  375 + sizeof(struct usbdevfs_iso_packet_desc));
  376 + if (!urb) {
  377 + printf("usb_host_handle_isoch: malloc failed\n");
  378 + return 0;
  379 + }
  380 +
  381 + urb->type = USBDEVFS_URB_TYPE_ISO;
  382 + urb->endpoint = devep;
  383 + urb->status = 0;
  384 + urb->flags = USBDEVFS_URB_ISO_ASAP;
  385 + urb->buffer = p->data;
  386 + urb->buffer_length = p->len;
  387 + urb->actual_length = 0;
  388 + urb->start_frame = 0;
  389 + urb->error_count = 0;
  390 +#ifdef USE_ASYNCIO
  391 + urb->signr = SIG_ISOCOMPLETE;
  392 +#else
  393 + urb->signr = 0;
  394 +#endif
  395 + urb->usercontext = s;
  396 + urb->number_of_packets = 1;
  397 + urb->iso_frame_desc[0].length = p->len;
  398 + urb->iso_frame_desc[0].actual_length = 0;
  399 + urb->iso_frame_desc[0].status = 0;
  400 + ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
  401 + if (ret == 0) {
  402 + if (!add_pending_urb(urb)) {
  403 + printf("usb_host_handle_isoch: add_pending_urb failed %p\n", urb);
  404 + }
  405 + } else {
  406 + printf("usb_host_handle_isoch: SUBMITURB ioctl=%d errno=%d\n",
  407 + ret, errno);
  408 + qemu_free(urb);
  409 + switch(errno) {
  410 + case ETIMEDOUT:
  411 + return USB_RET_NAK;
  412 + case EPIPE:
  413 + default:
  414 + return USB_RET_STALL;
  415 + }
  416 + }
  417 +#ifdef USE_ASYNCIO
  418 + /* FIXME: handle urbs_ready together with sync io
  419 + * workaround for injecting the signaled urbs into current frame */
  420 + if (s->urbs_ready > 0) {
  421 + ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
  422 + if (ret == 0) {
  423 + ret = purb->actual_length;
  424 + qemu_free(purb);
  425 + s->urbs_ready--;
  426 + }
  427 + return ret;
  428 + }
  429 + s->packet = p;
  430 + return USB_RET_ASYNC;
  431 +#else
  432 + ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
  433 + if (ret == 0) {
  434 + if (del_pending_urb(purb)) {
  435 + ret = purb->actual_length;
  436 + qemu_free(purb);
  437 + } else {
  438 + printf("usb_host_handle_isoch: del_pending_urb failed %p\n", purb);
  439 + }
  440 + } else {
  441 +#ifdef DEBUG_ISOCH
  442 + printf("usb_host_handle_isoch: REAPURBNDELAY ioctl=%d errno=%d\n",
  443 + ret, errno);
  444 +#endif
  445 + }
  446 + return ret;
  447 +#endif
  448 +}
  449 +
  450 +static void usb_linux_bh_cb(void *opaque)
  451 +{
  452 + PendingURB *pending_urb = (PendingURB *)opaque;
  453 + USBHostDevice *s = pending_urb->dev;
  454 + struct usbdevfs_urb *purb = NULL;
  455 + USBPacket *p = s->packet;
  456 + int ret;
  457 +
  458 + /* FIXME: handle purb->status */
  459 + qemu_free(pending_urb->bh);
  460 + del_pending_urb(pending_urb->urb);
  461 +
  462 + if (!p) {
  463 + s->urbs_ready++;
  464 + return;
  465 + }
  466 +
  467 + ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
  468 + if (ret < 0) {
  469 + printf("usb_linux_bh_cb: REAPURBNDELAY ioctl=%d errno=%d\n",
  470 + ret, errno);
  471 + return;
  472 + }
  473 +
  474 +#ifdef DEBUG_ISOCH
  475 + if (purb == pending_urb->urb) {
  476 + printf("usb_linux_bh_cb: urb mismatch reaped=%p pending=%p\n",
  477 + purb, urb);
  478 + }
  479 +#endif
  480 +
  481 + p->len = purb->actual_length;
  482 + usb_packet_complete(p);
  483 + qemu_free(purb);
  484 + s->packet = NULL;
  485 +}
  486 +
  487 +/* returns 1 on problem encountered or 0 for success */
  488 +static int usb_linux_update_endp_table(USBHostDevice *s)
  489 +{
  490 + uint8_t *descriptors;
  491 + uint8_t devep, type, configuration, alt_interface;
  492 + struct usb_ctrltransfer ct;
  493 + int interface, ret, length, i;
  494 +
  495 + ct.bRequestType = USB_DIR_IN;
  496 + ct.bRequest = USB_REQ_GET_CONFIGURATION;
  497 + ct.wValue = 0;
  498 + ct.wIndex = 0;
  499 + ct.wLength = 1;
  500 + ct.data = &configuration;
  501 + ct.timeout = 50;
  502 +
  503 + ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
  504 + if (ret < 0) {
  505 + perror("usb_linux_update_endp_table");
  506 + return 1;
  507 + }
  508 +
  509 + /* in address state */
  510 + if (configuration == 0)
  511 + return 1;
  512 +
  513 + /* get the desired configuration, interface, and endpoint descriptors
  514 + * from device description */
  515 + descriptors = &s->descr[18];
  516 + length = s->descr_len - 18;
  517 + i = 0;
  518 +
  519 + if (descriptors[i + 1] != USB_DT_CONFIG ||
  520 + descriptors[i + 5] != configuration) {
  521 + printf("invalid descriptor data - configuration\n");
  522 + return 1;
  523 + }
  524 + i += descriptors[i];
  525 +
  526 + while (i < length) {
  527 + if (descriptors[i + 1] != USB_DT_INTERFACE ||
  528 + (descriptors[i + 1] == USB_DT_INTERFACE &&
  529 + descriptors[i + 4] == 0)) {
  530 + i += descriptors[i];
  531 + continue;
  532 + }
  533 +
  534 + interface = descriptors[i + 2];
  535 +
  536 + ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
  537 + ct.bRequest = USB_REQ_GET_INTERFACE;
  538 + ct.wValue = 0;
  539 + ct.wIndex = interface;
  540 + ct.wLength = 1;
  541 + ct.data = &alt_interface;
  542 + ct.timeout = 50;
  543 +
  544 + ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
  545 + if (ret < 0) {
  546 + perror("usb_linux_update_endp_table");
  547 + return 1;
  548 + }
  549 +
  550 + /* the current interface descriptor is the active interface
  551 + * and has endpoints */
  552 + if (descriptors[i + 3] != alt_interface) {
  553 + i += descriptors[i];
  554 + continue;
  555 + }
  556 +
  557 + /* advance to the endpoints */
  558 + while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
  559 + i += descriptors[i];
  560 +
  561 + if (i >= length)
  562 + break;
  563 +
  564 + while (i < length) {
  565 + if (descriptors[i + 1] != USB_DT_ENDPOINT)
  566 + break;
  567 +
  568 + devep = descriptors[i + 2];
  569 + switch (descriptors[i + 3] & 0x3) {
  570 + case 0x00:
  571 + type = USBDEVFS_URB_TYPE_CONTROL;
  572 + break;
  573 + case 0x01:
  574 + type = USBDEVFS_URB_TYPE_ISO;
  575 + break;
  576 + case 0x02:
  577 + type = USBDEVFS_URB_TYPE_BULK;
  578 + break;
  579 + case 0x03:
  580 + type = USBDEVFS_URB_TYPE_INTERRUPT;
  581 + break;
  582 + default:
  583 + printf("usb_host: malformed endpoint type\n");
  584 + type = USBDEVFS_URB_TYPE_BULK;
  585 + }
  586 + s->endp_table[(devep & 0xf) - 1].type = type;
  587 +
  588 + i += descriptors[i];
  589 + }
  590 + }
  591 + return 0;
  592 +}
  593 +
148 594 /* XXX: exclude high speed devices or implement EHCI */
149 595 USBDevice *usb_host_device_open(const char *devname)
150 596 {
151   - int fd, interface, ret, i;
152   - USBHostDevice *dev;
  597 + int fd = -1, ret;
  598 + USBHostDevice *dev = NULL;
153 599 struct usbdevfs_connectinfo ci;
154   - uint8_t descr[1024];
155 600 char buf[1024];
156   - int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
157 601 int bus_num, addr;
158 602 char product_name[PRODUCT_NAME_SZ];
159 603  
  604 + dev = qemu_mallocz(sizeof(USBHostDevice));
  605 + if (!dev)
  606 + goto fail;
  607 +
  608 +#ifdef DEBUG_ISOCH
  609 + printf("usb_host_device_open %s\n", devname);
  610 +#endif
160 611 if (usb_host_find_device(&bus_num, &addr,
161 612 product_name, sizeof(product_name),
162 613 devname) < 0)
... ... @@ -164,61 +615,35 @@ USBDevice *usb_host_device_open(const char *devname)
164 615  
165 616 snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
166 617 bus_num, addr);
167   - fd = open(buf, O_RDWR);
  618 + fd = open(buf, O_RDWR | O_NONBLOCK);
168 619 if (fd < 0) {
169 620 perror(buf);
170 621 return NULL;
171 622 }
172 623  
173   - /* read the config description */
174   - descr_len = read(fd, descr, sizeof(descr));
175   - if (descr_len <= 0) {
176   - perror("read descr");
  624 + /* read the device description */
  625 + dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
  626 + if (dev->descr_len <= 0) {
  627 + perror("usb_host_update_interfaces: reading device data failed");
177 628 goto fail;
178 629 }
179 630  
180   - i = 0;
181   - dev_descr_len = descr[0];
182   - if (dev_descr_len > descr_len)
183   - goto fail;
184   - i += dev_descr_len;
185   - config_descr_len = descr[i];
186   - if (i + config_descr_len > descr_len)
187   - goto fail;
188   - nb_interfaces = descr[i + 4];
189   - if (nb_interfaces != 1) {
190   - /* NOTE: currently we grab only one interface */
191   - fprintf(stderr, "usb_host: only one interface supported\n");
192   - goto fail;
193   - }
194   -
195   -#ifdef USBDEVFS_DISCONNECT
196   - /* earlier Linux 2.4 do not support that */
  631 +#ifdef DEBUG
197 632 {
198   - struct usbdevfs_ioctl ctrl;
199   - ctrl.ioctl_code = USBDEVFS_DISCONNECT;
200   - ctrl.ifno = 0;
201   - ret = ioctl(fd, USBDEVFS_IOCTL, &ctrl);
202   - if (ret < 0 && errno != ENODATA) {
203   - perror("USBDEVFS_DISCONNECT");
204   - goto fail;
205   - }
  633 + int x;
  634 + printf("=== begin dumping device descriptor data ===\n");
  635 + for (x = 0; x < dev->descr_len; x++)
  636 + printf("%02x ", dev->descr[x]);
  637 + printf("\n=== end dumping device descriptor data ===\n");
206 638 }
207 639 #endif
208 640  
209   - /* XXX: only grab if all interfaces are free */
210   - interface = 0;
211   - ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
212   - if (ret < 0) {
213   - if (errno == EBUSY) {
214   - fprintf(stderr, "usb_host: device already grabbed\n");
215   - } else {
216   - perror("USBDEVFS_CLAIMINTERFACE");
217   - }
218   - fail:
219   - close(fd);
220   - return NULL;
221   - }
  641 + dev->fd = fd;
  642 + dev->configuration = 1;
  643 +
  644 + /* XXX - do something about initial configuration */
  645 + if (!usb_host_update_interfaces(dev, 1))
  646 + goto fail;
222 647  
223 648 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
224 649 if (ret < 0) {
... ... @@ -230,10 +655,10 @@ USBDevice *usb_host_device_open(const char *devname)
230 655 printf("host USB device %d.%d grabbed\n", bus_num, addr);
231 656 #endif
232 657  
233   - dev = qemu_mallocz(sizeof(USBHostDevice));
234   - if (!dev)
  658 + ret = usb_linux_update_endp_table(dev);
  659 + if (ret)
235 660 goto fail;
236   - dev->fd = fd;
  661 +
237 662 if (ci.slow)
238 663 dev->dev.speed = USB_SPEED_LOW;
239 664 else
... ... @@ -252,7 +677,24 @@ USBDevice *usb_host_device_open(const char *devname)
252 677 pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
253 678 product_name);
254 679  
  680 +#ifdef USE_ASYNCIO
  681 + /* set up the signal handlers */
  682 + sigemptyset(&sigact.sa_mask);
  683 + sigact.sa_sigaction = isoch_done;
  684 + sigact.sa_flags = SA_SIGINFO;
  685 + sigact.sa_restorer = 0;
  686 + ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
  687 + if (ret < 0) {
  688 + printf("sigaction SIG_ISOCOMPLETE=%d errno=%d\n", ret, errno);
  689 + }
  690 +#endif
  691 + dev->urbs_ready = 0;
255 692 return (USBDevice *)dev;
  693 +fail:
  694 + if (dev)
  695 + qemu_free(dev);
  696 + close(fd);
  697 + return NULL;
256 698 }
257 699  
258 700 static int get_tag_value(char *buf, int buf_size,
... ... @@ -438,7 +880,7 @@ static const struct usb_class_info usb_class_info[] = {
438 880 { USB_CLASS_APP_SPEC, "Application Specific" },
439 881 { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
440 882 { USB_CLASS_STILL_IMAGE, "Still Image" },
441   - { USB_CLASS_CSCID, "Smart Card" },
  883 + { USB_CLASS_CSCID, "Smart Card" },
442 884 { USB_CLASS_CONTENT_SEC, "Content Security" },
443 885 { -1, NULL }
444 886 };
... ...