Loading libusbhost/include/usbhost/usbhost.h +3 −2 Original line number Diff line number Diff line Loading @@ -232,10 +232,11 @@ void usb_request_free(struct usb_request *req); /* Submits a read or write request on the specified device */ int usb_request_queue(struct usb_request *req); /* Waits for the results of a previous usb_request_queue operation. /* Waits for the results of a previous usb_request_queue operation. timeoutMillis == -1 requests * to wait forever. * Returns a usb_request, or NULL for error. */ struct usb_request *usb_request_wait(struct usb_device *dev); struct usb_request *usb_request_wait(struct usb_device *dev, int timeoutMillis); /* Cancels a pending usb_request_queue() operation. */ int usb_request_cancel(struct usb_request *req); Loading libusbhost/usbhost.c +33 −19 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ * limitations under the License. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif // #define DEBUG 1 #if DEBUG Loading Loading @@ -43,6 +47,7 @@ #include <fcntl.h> #include <errno.h> #include <ctype.h> #include <poll.h> #include <pthread.h> #include <linux/usbdevice_fs.h> Loading Loading @@ -683,30 +688,39 @@ int usb_request_queue(struct usb_request *req) return res; } struct usb_request *usb_request_wait(struct usb_device *dev) struct usb_request *usb_request_wait(struct usb_device *dev, int timeoutMillis) { // Poll until a request becomes available if there is a timeout if (timeoutMillis > 0) { struct pollfd p = {.fd = dev->fd, .events = POLLOUT, .revents = 0}; int res = poll(&p, 1, timeoutMillis); if (res != 1 || p.revents != POLLOUT) { D("[ poll - event %d, error %d]\n", p.revents, errno); return NULL; } } // Read the request. This should usually succeed as we polled before, but it can fail e.g. when // two threads are reading usb requests at the same time and only a single request is available. struct usbdevfs_urb *urb = NULL; struct usb_request *req = NULL; int res = TEMP_FAILURE_RETRY(ioctl(dev->fd, timeoutMillis == -1 ? USBDEVFS_REAPURB : USBDEVFS_REAPURBNDELAY, &urb)); D("%s returned %d\n", timeoutMillis == -1 ? "USBDEVFS_REAPURB" : "USBDEVFS_REAPURBNDELAY", res); while (1) { int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb); D("USBDEVFS_REAPURB returned %d\n", res); if (res < 0) { if(errno == EINTR) { continue; } D("[ reap urb - error ]\n"); D("[ reap urb - error %d]\n", errno); return NULL; } else { D("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); req = (struct usb_request*)urb->usercontext; D("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); struct usb_request *req = (struct usb_request*)urb->usercontext; req->actual_length = urb->actual_length; } break; } return req; } } int usb_request_cancel(struct usb_request *req) { Loading Loading
libusbhost/include/usbhost/usbhost.h +3 −2 Original line number Diff line number Diff line Loading @@ -232,10 +232,11 @@ void usb_request_free(struct usb_request *req); /* Submits a read or write request on the specified device */ int usb_request_queue(struct usb_request *req); /* Waits for the results of a previous usb_request_queue operation. /* Waits for the results of a previous usb_request_queue operation. timeoutMillis == -1 requests * to wait forever. * Returns a usb_request, or NULL for error. */ struct usb_request *usb_request_wait(struct usb_device *dev); struct usb_request *usb_request_wait(struct usb_device *dev, int timeoutMillis); /* Cancels a pending usb_request_queue() operation. */ int usb_request_cancel(struct usb_request *req); Loading
libusbhost/usbhost.c +33 −19 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ * limitations under the License. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif // #define DEBUG 1 #if DEBUG Loading Loading @@ -43,6 +47,7 @@ #include <fcntl.h> #include <errno.h> #include <ctype.h> #include <poll.h> #include <pthread.h> #include <linux/usbdevice_fs.h> Loading Loading @@ -683,30 +688,39 @@ int usb_request_queue(struct usb_request *req) return res; } struct usb_request *usb_request_wait(struct usb_device *dev) struct usb_request *usb_request_wait(struct usb_device *dev, int timeoutMillis) { // Poll until a request becomes available if there is a timeout if (timeoutMillis > 0) { struct pollfd p = {.fd = dev->fd, .events = POLLOUT, .revents = 0}; int res = poll(&p, 1, timeoutMillis); if (res != 1 || p.revents != POLLOUT) { D("[ poll - event %d, error %d]\n", p.revents, errno); return NULL; } } // Read the request. This should usually succeed as we polled before, but it can fail e.g. when // two threads are reading usb requests at the same time and only a single request is available. struct usbdevfs_urb *urb = NULL; struct usb_request *req = NULL; int res = TEMP_FAILURE_RETRY(ioctl(dev->fd, timeoutMillis == -1 ? USBDEVFS_REAPURB : USBDEVFS_REAPURBNDELAY, &urb)); D("%s returned %d\n", timeoutMillis == -1 ? "USBDEVFS_REAPURB" : "USBDEVFS_REAPURBNDELAY", res); while (1) { int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb); D("USBDEVFS_REAPURB returned %d\n", res); if (res < 0) { if(errno == EINTR) { continue; } D("[ reap urb - error ]\n"); D("[ reap urb - error %d]\n", errno); return NULL; } else { D("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); req = (struct usb_request*)urb->usercontext; D("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); struct usb_request *req = (struct usb_request*)urb->usercontext; req->actual_length = urb->actual_length; } break; } return req; } } int usb_request_cancel(struct usb_request *req) { Loading