Remove USBI_OS_HANDLES_TIMEOUT and fix int/isoc timeouts on Darwin
authorNathan Hjelm <hjelmn@me.com>
Wed, 6 Oct 2010 01:48:39 +0000 (19:48 -0600)
committerPeter Stuge <peter@stuge.se>
Fri, 26 Nov 2010 19:47:23 +0000 (20:47 +0100)
Backends set USBI_TRANSFER_OS_HANDLES_TIMEOUT for transfers instead.
Darwin only handles timeouts for bulk and control transfers, so the
backend now sets that flag accordingly, making libusb core handle
timeouts for interrupt and isochronous transfers. Fixes #31.

Signed-off-by: Nathan Hjelm <hjelmn@me.com>
[stuge: rework libusb_get_next_timeout() and enum usbi_transfer_flags]
[stuge: fix typo; set USBI_TRANSFER_TIMED_OUT flag correctly]

configure.ac
libusb/io.c
libusb/libusbi.h
libusb/os/darwin_usb.c

index af63aef..3dcb02d 100644 (file)
@@ -54,7 +54,6 @@ case $host in
        AC_DEFINE(OS_DARWIN, [], [Darwin backend])
        AC_SUBST(OS_DARWIN)
        AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads])
-       AC_DEFINE(USBI_OS_HANDLES_TIMEOUT, [], [Backend handles timeout])
        AC_MSG_RESULT([Darwin/MacOS X])
        backend="darwin"
        threads="posix"
index ab37e8d..c6b42fe 100644 (file)
@@ -1710,16 +1710,6 @@ static void handle_timeout(struct usbi_transfer *itransfer)
                        "async cancel failed %d errno=%d", r, errno);
 }
 
-#ifdef USBI_OS_HANDLES_TIMEOUT
-static int handle_timeouts_locked(struct libusb_context *ctx)
-{
-       return 0;
-}
-static int handle_timeouts(struct libusb_context *ctx)
-{
-       return 0;
-}
-#else
 static int handle_timeouts_locked(struct libusb_context *ctx)
 {
        int r;
@@ -1747,7 +1737,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
                        return 0;
 
                /* ignore timeouts we've already handled */
-               if (transfer->flags & USBI_TRANSFER_TIMED_OUT)
+               if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
                        continue;
 
                /* if transfer has non-expired timeout, nothing more to do */
@@ -1771,7 +1761,6 @@ static int handle_timeouts(struct libusb_context *ctx)
        usbi_mutex_unlock(&ctx->flying_transfers_lock);
        return r;
 }
-#endif
 
 #ifdef USBI_TIMERFD_AVAILABLE
 static int handle_timerfd_trigger(struct libusb_context *ctx)
@@ -2073,9 +2062,7 @@ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
  */
 int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
 {
-#if defined(USBI_OS_HANDLES_TIMEOUT)
-       return 1;
-#elif defined(USBI_TIMERFD_AVAILABLE)
+#if defined(USBI_TIMERFD_AVAILABLE)
        USBI_GET_CONTEXT(ctx);
        return usbi_using_timerfd(ctx);
 #else
@@ -2114,7 +2101,6 @@ int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
 int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
        struct timeval *tv)
 {
-#ifndef USBI_OS_HANDLES_TIMEOUT
        struct usbi_transfer *transfer;
        struct timespec cur_ts;
        struct timeval cur_tv;
@@ -2135,10 +2121,11 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
 
        /* find next transfer which hasn't already been processed as timed out */
        list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
-               if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
-                       found = 1;
-                       break;
-               }
+               if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
+                       continue;
+
+               found = 1;
+               break;
        }
        usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
@@ -2171,9 +2158,6 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
        }
 
        return 1;
-#else
-       return 0;
-#endif
 }
 
 /** \ingroup poll
index 78a2a35..974b108 100644 (file)
@@ -288,8 +288,6 @@ struct libusb_device_handle {
        unsigned char os_priv[0];
 };
 
-#define USBI_TRANSFER_TIMED_OUT                                (1<<0)
-
 enum {
   USBI_CLOCK_MONOTONIC,
   USBI_CLOCK_REALTIME
@@ -325,6 +323,14 @@ struct usbi_transfer {
        usbi_mutex_t lock;
 };
 
+enum usbi_transfer_flags {
+       /* The transfer has timed out */
+       USBI_TRANSFER_TIMED_OUT = 1 << 0,
+
+       /* Set by backend submit_transfer() if the OS handles timeout */
+       USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 1
+};
+
 #define __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
        ((struct libusb_transfer *)(((unsigned char *)(transfer)) \
                + sizeof(struct usbi_transfer)))
index 646c938..37b8e2c 100644 (file)
@@ -1137,6 +1137,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
       ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
                                                       transfer->length, darwin_async_io_callback, itransfer);
   } else {
+    itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
+
     if (is_read)
       ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
                                                        transfer->length, transfer->timeout, transfer->timeout,
@@ -1244,6 +1246,8 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
   tpriv->req.completionTimeout = transfer->timeout;
   tpriv->req.noDataTimeout     = transfer->timeout;
 
+  itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
+
   /* all transfers in libusb-1.0 are async */
   kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
 
@@ -1358,6 +1362,9 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
 }
 
 static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
+  if (itransfer->flags & USBI_TRANSFER_TIMED_OUT)
+    result = kIOUSBTransactionTimeout;
+
   switch (result) {
   case kIOReturnUnderrun:
   case kIOReturnSuccess:
@@ -1372,6 +1379,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
     return LIBUSB_TRANSFER_OVERFLOW;
   case kIOUSBTransactionTimeout:
     usbi_err (ITRANSFER_CTX (itransfer), "transfer error: timed out");
+    itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
     return LIBUSB_TRANSFER_TIMED_OUT;
   default:
     usbi_err (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);