diff options
-rw-r--r-- | usb-linux.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/usb-linux.c b/usb-linux.c index f65dcb7ad..42baafe0a 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -100,6 +100,7 @@ struct endp_data { int iso_urb_idx; int iso_buffer_used; int max_packet_size; + int inflight; }; struct USBAutoFilter { @@ -184,7 +185,19 @@ static void clear_iso_started(USBHostDevice *s, int ep) static void set_iso_started(USBHostDevice *s, int ep) { - get_endp(s, ep)->iso_started = 1; + struct endp_data *e = get_endp(s, ep); + if (!e->iso_started) { + e->iso_started = 1; + e->inflight = 0; + } +} + +static int change_iso_inflight(USBHostDevice *s, int ep, int value) +{ + struct endp_data *e = get_endp(s, ep); + + e->inflight += value; + return e->inflight; } static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb) @@ -282,6 +295,7 @@ static void async_complete(void *opaque) { USBHostDevice *s = opaque; AsyncURB *aurb; + int urbs = 0; while (1) { USBPacket *p; @@ -289,6 +303,9 @@ static void async_complete(void *opaque) int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb); if (r < 0) { if (errno == EAGAIN) { + if (urbs > 2) { + fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs); + } return; } if (errno == ENODEV && !s->closing) { @@ -306,10 +323,16 @@ static void async_complete(void *opaque) /* If this is a buffered iso urb mark it as complete and don't do anything else (it is handled further in usb_host_handle_iso_data) */ if (aurb->iso_frame_idx == -1) { + int inflight; if (aurb->urb.status == -EPIPE) { set_halt(s, aurb->urb.endpoint & 0xf); } aurb->iso_frame_idx = 0; + urbs++; + inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1); + if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) { + fprintf(stderr, "husb: out of buffers for iso stream\n"); + } continue; } @@ -670,6 +693,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) break; } aurb[i].iso_frame_idx = -1; + change_iso_inflight(s, p->devep, +1); } } } |