diff options
-rw-r--r-- | configure.ac | 103 | ||||
-rw-r--r-- | libusb/Makefile.am | 2 | ||||
-rw-r--r-- | libusb/io.c | 63 | ||||
-rw-r--r-- | libusb/libusb-1.0.def | 20 | ||||
-rw-r--r-- | libusb/libusbi.h | 6 | ||||
-rw-r--r-- | libusb/os/darwin_usb.c | 57 | ||||
-rw-r--r-- | libusb/os/darwin_usb.h | 2 | ||||
-rw-r--r-- | libusb/os/linux_usbfs.c | 162 | ||||
-rw-r--r-- | libusb/os/poll_posix.h | 2 | ||||
-rw-r--r-- | libusb/os/poll_windows.h | 2 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 4 | ||||
-rw-r--r-- | libusb/sync.c | 8 | ||||
-rw-r--r-- | msvc/config.h | 10 |
13 files changed, 187 insertions, 254 deletions
diff --git a/configure.ac b/configure.ac index 630d76b..e6e085e 100644 --- a/configure.ac +++ b/configure.ac @@ -17,11 +17,11 @@ AC_SUBST([LIBUSB_VERSION_NANO], [LIBUSB_NANO]) lt_current="1" lt_revision="0" lt_age="1" -AC_SUBST(lt_current) -AC_SUBST(lt_revision) -AC_SUBST(lt_age) +LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}" AM_INIT_AUTOMAKE +AM_MAINTAINER_MODE + AC_CONFIG_SRCDIR([libusb/core.c]) AC_CONFIG_MACRO_DIR([m4]) AM_CONFIG_HEADER([config.h]) @@ -32,75 +32,71 @@ AC_PROG_CC AC_PROG_LIBTOOL AC_C_INLINE AM_PROG_CC_C_O -AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) +AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions]) -AM_MAINTAINER_MODE +LTLDFLAGS="${LTLDFLAGS} -no-undefined" AC_MSG_CHECKING([operating system]) -PC_LIBS_PRIVATE= case $host in *-linux*) - AC_DEFINE(OS_LINUX, [], [Linux backend]) + AC_DEFINE(OS_LINUX, 1, [Linux backend]) AC_SUBST(OS_LINUX) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) AC_MSG_RESULT([Linux]) backend="linux" AC_CHECK_LIB(rt, clock_gettime, PC_LIBS_PRIVATE="-lrt") - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" threads="posix" THREAD_CFLAGS="-pthread" PC_LIBS_PRIVATE="${PC_LIBS_PRIVATE} -pthread" - AM_CFLAGS="-std=gnu99" - AM_LDFLAGS="" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) ;; *-darwin*) - AC_DEFINE(OS_DARWIN, [], [Darwin backend]) + AC_DEFINE(OS_DARWIN, 1, [Darwin backend]) AC_SUBST(OS_DARWIN) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) - AC_MSG_RESULT([Darwin/MacOS X]) + AC_MSG_RESULT([Darwin/Mac OS X]) backend="darwin" threads="posix" - THREAD_CFLAGS="-pthread" - AM_CFLAGS="-std=gnu99" - PC_LIBS_PRIVATE="-Wl,-framework,IOKit -Wl,-framework,CoreFoundation -Wl,-prebind -no-undefined -pthread" - AM_LDFLAGS=${PC_LIBS_PRIVATE} + PC_LIBS_PRIVATE="-Wl,-framework,IOKit -Wl,-framework,CoreFoundation" + LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind" + AC_CHECK_HEADERS([poll.h]) + AC_CHECK_TYPE([nfds_t], + [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])], + [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])], + [#include <poll.h>]) ;; *-mingw*) - AC_DEFINE(OS_WINDOWS, [], [Windows backend]) - AC_SUBST(OS_WINDOWS) AC_MSG_RESULT([Windows]) backend="windows" - threads="windows" - create_import_lib="yes" - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" - # -avoid-version to avoid a naming scheme such as libusb-0.dll - AM_LDFLAGS="-no-undefined -avoid-version -Wl,--add-stdcall-alias" - AM_CFLAGS="-std=gnu99" - AC_CHECK_TOOL(RC, windres, no) AC_CHECK_TOOL(DLLTOOL, dlltool, false) ;; *-cygwin*) - AC_DEFINE(OS_WINDOWS, [], [Windows backend]) - AC_SUBST(OS_WINDOWS) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) - AC_MSG_RESULT([Windows]) + AC_MSG_RESULT([Cygwin (using Windows backend)]) backend="windows" threads="posix" - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" - AM_CFLAGS="-std=gnu99" - AM_LDFLAGS="-no-undefined -avoid-version" - AC_CHECK_TOOL(RC, windres, no) ;; *) AC_MSG_ERROR([unsupported operating system]) esac +if test "$backend" = windows; then + AC_DEFINE(OS_WINDOWS, 1, [Windows backend]) + AC_SUBST(OS_WINDOWS) + PC_LIBS_PRIVATE="-lsetupapi -lole32 -ladvapi32" + LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias" + AC_CHECK_TOOL(RC, windres, no) + AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) +fi +AC_SUBST(THREAD_CFLAGS) AC_SUBST(PC_LIBS_PRIVATE) - -AM_CONDITIONAL([OS_LINUX], [test "x$backend" = "xlinux"]) -AM_CONDITIONAL([OS_DARWIN], [test "x$backend" = "xdarwin"]) -AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" = "xwindows"]) -AM_CONDITIONAL([THREADS_POSIX], [test "x$threads" = "xposix"]) -AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = "xyes"]) +LIBS="${LIBS} ${PC_LIBS_PRIVATE}" + +AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux) +AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) +AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) +AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) +AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") +if test "$threads" = posix; then + AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) +fi # timerfd AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0]) @@ -124,7 +120,7 @@ if test "x$use_timerfd" = "xno"; then else if test "x$timerfd_h" = "x1" -a "x$tfd_hdr_ok" = "xyes"; then AC_MSG_RESULT([yes]) - AC_DEFINE(USBI_TIMERFD_AVAILABLE, [], [timerfd headers available]) + AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available]) else AC_MSG_RESULT([no (header not available)]) fi @@ -168,14 +164,14 @@ AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"]) # Restore gnu89 inline semantics on gcc 4.3 and newer saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -fgnu89-inline" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), inline_cflags="-fgnu89-inline", inline_cflags="") +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], inline_cflags="-fgnu89-inline", inline_cflags="") CFLAGS="$saved_cflags" # check for -fvisibility=hidden compiler support (GCC >= 3.4) saved_cflags="$CFLAGS" # -Werror required for cygwin CFLAGS="$CFLAGS -Werror -fvisibility=hidden" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [VISIBILITY_CFLAGS="-fvisibility=hidden" AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility]) ], [ VISIBILITY_CFLAGS="" @@ -186,7 +182,7 @@ CFLAGS="$saved_cflags" # check for -Wno-pointer-sign compiler support (GCC >= 4) saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Wno-pointer-sign" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="") CFLAGS="$saved_cflags" @@ -197,14 +193,17 @@ AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"]) # headers not available on all platforms but required on others AC_CHECK_HEADERS([sys/time.h]) -AC_SUBST([THREAD_CFLAGS]) - -AM_CFLAGS="$AM_CFLAGS $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" +AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" AC_SUBST(VISIBILITY_CFLAGS) AC_SUBST(AM_CFLAGS) -AC_SUBST(AM_LDFLAGS) - -AC_CONFIG_FILES([libusb-1.0.pc] [Makefile] [libusb/Makefile] [libusb/libusb_version.h] [examples/Makefile] [doc/Makefile] [doc/doxygen.cfg]) +AC_SUBST(LTLDFLAGS) + +AC_CONFIG_FILES([libusb-1.0.pc]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([libusb/Makefile]) +AC_CONFIG_FILES([libusb/libusb_version.h]) +AC_CONFIG_FILES([examples/Makefile]) +AC_CONFIG_FILES([doc/Makefile]) +AC_CONFIG_FILES([doc/doxygen.cfg]) AC_OUTPUT - diff --git a/libusb/Makefile.am b/libusb/Makefile.am index b7890b1..2b6ca7b 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -34,7 +34,7 @@ endif endif libusb_1_0_la_CFLAGS = $(VISIBILITY_CFLAGS) $(AM_CFLAGS) $(THREAD_CFLAGS) -libusb_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(lt_current):$(lt_revision):$(lt_age) +libusb_1_0_la_LDFLAGS = $(LTLDFLAGS) libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c sync.c $(OS_SRC) \ os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h \ os/threads_posix.h os/threads_windows.h \ diff --git a/libusb/io.c b/libusb/io.c index b23c76b..dd56857 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1793,7 +1793,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) { int r; struct usbi_pollfd *ipollfd; - nfds_t nfds = 0; + POLL_NFDS_TYPE nfds = 0; struct pollfd *fds; int i = -1; int timeout_ms; @@ -1937,8 +1937,8 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, * non-blocking mode * \returns 0 on success, or a LIBUSB_ERROR code on failure */ -int API_EXPORTED libusb_handle_events_timeout_check(libusb_context *ctx, - struct timeval *tv, int *completed) +int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv) { int r; struct timeval poll_timeout; @@ -1952,12 +1952,8 @@ int API_EXPORTED libusb_handle_events_timeout_check(libusb_context *ctx, retry: if (libusb_try_lock_events(ctx) == 0) { - r = 0; - if (completed == NULL || !*completed) { - /* we obtained the event lock: do our own event handling */ - usbi_dbg("doing our own event handling"); - r = handle_events(ctx, &poll_timeout); - } + /* we obtained the event lock: do our own event handling */ + r = handle_events(ctx, &poll_timeout); libusb_unlock_events(ctx); return r; } @@ -1966,18 +1962,16 @@ retry: * notify event completion. */ libusb_lock_event_waiters(ctx); - if (completed == NULL || !*completed) { - if (!libusb_event_handler_active(ctx)) { - /* we hit a race: whoever was event handling earlier finished in the - * time it took us to reach this point. try the cycle again. */ - libusb_unlock_event_waiters(ctx); - usbi_dbg("event handler was active but went away, retrying"); - goto retry; - } - - usbi_dbg("another thread is doing event handling, wait for notification"); - r = libusb_wait_for_event(ctx, &poll_timeout); + if (!libusb_event_handler_active(ctx)) { + /* we hit a race: whoever was event handling earlier finished in the + * time it took us to reach this point. try the cycle again. */ + libusb_unlock_event_waiters(ctx); + usbi_dbg("event handler was active but went away, retrying"); + goto retry; } + + usbi_dbg("another thread is doing event handling"); + r = libusb_wait_for_event(ctx, &poll_timeout); libusb_unlock_event_waiters(ctx); if (r < 0) @@ -1988,21 +1982,6 @@ retry: return 0; } -int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv) -{ - return libusb_handle_events_timeout_check(ctx, tv, NULL); -} - -int API_EXPORTED libusb_handle_events_check(libusb_context *ctx, - int *completed) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_check(ctx, &tv, completed); -} - /** \ingroup poll * Handle any pending events in blocking mode. There is currently a timeout * hardcoded at 60 seconds but we plan to make it unlimited in future. For @@ -2017,7 +1996,7 @@ int API_EXPORTED libusb_handle_events(libusb_context *ctx) struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; - return libusb_handle_events_timeout_check(ctx, &tv, NULL); + return libusb_handle_events_timeout(ctx, &tv); } /** \ingroup poll @@ -2145,24 +2124,22 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) continue; + /* no timeout for this transfer? */ + if (!timerisset(&transfer->timeout)) + continue; + found = 1; break; } usbi_mutex_unlock(&ctx->flying_transfers_lock); if (!found) { - usbi_dbg("all URBs have already been processed for timeouts"); + usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); return 0; } next_timeout = &transfer->timeout; - /* no timeout for next transfer */ - if (!timerisset(next_timeout)) { - usbi_dbg("no URBs with timeouts, no timeout!"); - return 0; - } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); if (r < 0) { usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index bce31fb..1ae2756 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -340,16 +340,6 @@ EXPORTS libusb_handle_events@32 = libusb_handle_events libusb_handle_events@4 = libusb_handle_events libusb_handle_events@8 = libusb_handle_events - libusb_handle_events_check - libusb_handle_events_check@0 = libusb_handle_events_check - libusb_handle_events_check@12 = libusb_handle_events_check - libusb_handle_events_check@16 = libusb_handle_events_check - libusb_handle_events_check@20 = libusb_handle_events_check - libusb_handle_events_check@24 = libusb_handle_events_check - libusb_handle_events_check@28 = libusb_handle_events_check - libusb_handle_events_check@32 = libusb_handle_events_check - libusb_handle_events_check@4 = libusb_handle_events_check - libusb_handle_events_check@8 = libusb_handle_events_check libusb_handle_events_locked libusb_handle_events_locked@0 = libusb_handle_events_locked libusb_handle_events_locked@12 = libusb_handle_events_locked @@ -370,16 +360,6 @@ EXPORTS libusb_handle_events_timeout@32 = libusb_handle_events_timeout libusb_handle_events_timeout@4 = libusb_handle_events_timeout libusb_handle_events_timeout@8 = libusb_handle_events_timeout - libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@0 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@12 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@16 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@20 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@24 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@28 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@32 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@4 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@8 = libusb_handle_events_timeout_check libusb_init libusb_init@0 = libusb_init libusb_init@12 = libusb_init diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 8ade9c7..322ebbc 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -26,6 +26,9 @@ #include <stddef.h> #include <stdint.h> #include <time.h> +#ifdef HAVE_POLL_H +#include <poll.h> +#endif #include <libusb.h> #include "libusb_version.h" @@ -194,6 +197,7 @@ static inline void usbi_dbg(const char *format, ...) #endif #if defined(OS_LINUX) || defined(OS_DARWIN) +#include <unistd.h> #include <os/poll_posix.h> #elif defined(OS_WINDOWS) #include <os/poll_windows.h> @@ -831,7 +835,7 @@ struct usbi_os_backend { * Return 0 on success, or a LIBUSB_ERROR code on failure. */ int (*handle_events)(struct libusb_context *ctx, - struct pollfd *fds, nfds_t nfds, int num_ready); + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); /* Get time from specified clock. At least two clocks must be implemented by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 37b8e2c..169fa1a 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -672,10 +672,19 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { return darwin_to_libusb (kresult); } } else { - priv->is_open = 1; - /* create async event source */ kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); + if (kresult != kIOReturnSuccess) { + usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); + + (*(dpriv->device))->USBDeviceClose (dpriv->device); + (*(dpriv->device))->Release (dpriv->device); + + dpriv->device = NULL; + return darwin_to_libusb (kresult); + } + + priv->is_open = 1; CFRetain (libusb_darwin_acfl); @@ -1173,10 +1182,18 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* are we reading or writing? */ is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN; - /* construct an array of IOUSBIsocFrames */ - tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); - if (!tpriv->isoc_framelist) - return LIBUSB_ERROR_NO_MEM; + /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ + if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { + free(tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + } + + if (!tpriv->isoc_framelist) { + tpriv->num_iso_packets = transfer->num_iso_packets; + tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); + if (!tpriv->isoc_framelist) + return LIBUSB_ERROR_NO_MEM; + } /* copy the frame list from the libusb descriptor (the structures differ only is member order) */ for (i = 0 ; i < transfer->num_iso_packets ; i++) @@ -1202,7 +1219,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { } /* schedule for a frame a little in the future */ - frame += 2; + frame += 4; + + if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) + frame = cInterface->frames[transfer->endpoint]; /* submit the request */ if (is_read) @@ -1214,6 +1234,8 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, itransfer); + cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets / 8; + if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", darwin_error_str(kresult)); @@ -1228,6 +1250,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv; + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); IOReturn kresult; @@ -1249,7 +1272,23 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { 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); + + if (transfer->endpoint) { + struct __darwin_interface *cInterface; + uint8_t pipeRef, iface; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + cInterface = &priv->interfaces[iface]; + + kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); + } else + /* control request on endpoint 0 */ + kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); @@ -1421,7 +1460,7 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result)); } -static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) { +static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct usbi_transfer *itransfer; UInt32 io_size; IOReturn kresult; diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h index a71d464..9ffd6df 100644 --- a/libusb/os/darwin_usb.h +++ b/libusb/os/darwin_usb.h @@ -139,6 +139,7 @@ struct darwin_device_handle_priv { usb_interface_t **interface; uint8_t num_endpoints; CFRunLoopSourceRef cfSource; + uint64_t frames[256]; uint8_t endpoint_addrs[USB_MAXENDPOINTS]; } interfaces[USB_MAXINTERFACES]; }; @@ -146,6 +147,7 @@ struct darwin_device_handle_priv { struct darwin_transfer_priv { /* Isoc */ IOUSBIsocFrame *isoc_framelist; + size_t num_iso_packets; /* Control */ #if !defined (LIBUSB_NO_TIMEOUT_DEVICE) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 867893c..72db57a 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -363,7 +363,7 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config) char tmp[4] = {0, 0, 0, 0}; long num; int fd; - size_t r; + ssize_t r; fd = __open_sysfs_attr(dev, "bConfigurationValue"); if (fd < 0) @@ -407,7 +407,7 @@ static int seek_to_next_config(struct libusb_context *ctx, int fd, struct libusb_config_descriptor config; unsigned char tmp[6]; off_t off; - int r; + ssize_t r; /* read first 6 bytes of descriptor */ r = read(fd, tmp, sizeof(tmp)); @@ -1331,6 +1331,39 @@ static void op_destroy_device(struct libusb_device *dev) free(priv->sysfs_dir); } +/* URBs are discarded in reverse order of submission to avoid races. */ +static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one) +{ + struct libusb_transfer *transfer = + __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = + usbi_transfer_get_os_priv(itransfer); + struct linux_device_handle_priv *dpriv = + __device_handle_priv(transfer->dev_handle); + int i, ret = 0; + struct usbfs_urb *urb; + + for (i = last_plus_one - 1; i >= first; i--) { + if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type) + urb = tpriv->iso_urbs[i]; + else + urb = &tpriv->urbs[i]; + + if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb)) + continue; + + if (EINVAL == errno) { + usbi_dbg("URB not found --> assuming ready to be reaped"); + ret = LIBUSB_ERROR_NOT_FOUND; + } else { + usbi_warn(TRANSFER_CTX(transfer), + "unrecognised discard errno %d", errno); + ret = LIBUSB_ERROR_OTHER; + } + } + return ret; +} + static void free_iso_urbs(struct linux_transfer_priv *tpriv) { int i; @@ -1409,8 +1442,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); if (r < 0) { - int j; - if (errno == ENODEV) { r = LIBUSB_ERROR_NO_DEVICE; } else { @@ -1454,14 +1485,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, if (COMPLETED_EARLY == tpriv->reap_action) return 0; - /* The URBs are discarded in reverse order of - * submission, to avoid races. */ - for (j = i - 1; j >= 0; j--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &urbs[j]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, 0, i); usbi_dbg("reporting successful submission but waiting for %d " "discards before reporting error", i); @@ -1577,8 +1601,6 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) for (i = 0; i < num_urbs; i++) { int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]); if (r < 0) { - int j; - if (errno == ENODEV) { r = LIBUSB_ERROR_NO_DEVICE; } else { @@ -1613,12 +1635,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) /* The URBs we haven't submitted yet we count as already * retired. */ tpriv->num_retired = num_urbs - i; - for (j = i - 1; j >= 0; j--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urbs[j]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, 0, i); usbi_dbg("reporting successful submission but waiting for %d " "discards before reporting error", i); @@ -1650,6 +1667,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) return LIBUSB_ERROR_NO_MEM; memset(urb, 0, sizeof(struct usbfs_urb)); tpriv->urbs = urb; + tpriv->num_urbs = 1; tpriv->reap_action = NORMAL; urb->usercontext = itransfer; @@ -1693,98 +1711,32 @@ static int op_submit_transfer(struct usbi_transfer *itransfer) } } -static int cancel_control_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int r; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - tpriv->reap_action = CANCELLED; - r = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, tpriv->urbs); - if(r) { - if (errno == EINVAL) { - usbi_dbg("URB not found --> assuming ready to be reaped"); - return 0; - } else { - usbi_err(TRANSFER_CTX(transfer), - "unrecognised DISCARD code %d", errno); - return LIBUSB_ERROR_OTHER; - } - } - - return 0; -} - -static int cancel_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int i; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - if (tpriv->reap_action != ERROR) - tpriv->reap_action = CANCELLED; - - for (i = tpriv->num_urbs - 1; i >= 0; i--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &tpriv->urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } - return 0; -} - -static int cancel_iso_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int i; - - if (!tpriv->iso_urbs) - return LIBUSB_ERROR_NOT_FOUND; - - tpriv->reap_action = CANCELLED; - for (i = tpriv->num_urbs - 1; i >= 0; i--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, tpriv->iso_urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } - return 0; -} - static int op_cancel_transfer(struct usbi_transfer *itransfer) { + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return cancel_control_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK: + if (tpriv->reap_action == ERROR) + break; + /* else, fall through */ + case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return cancel_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return cancel_iso_transfer(itransfer); + tpriv->reap_action = CANCELLED; + break; default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } + + if (!tpriv->urbs) + return LIBUSB_ERROR_NOT_FOUND; + + return discard_urbs(itransfer, 0, tpriv->num_urbs); } static void op_clear_transfer_priv(struct usbi_transfer *itransfer) @@ -1814,7 +1766,6 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, { struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = __device_handle_priv(transfer->dev_handle); int urb_idx = urb - tpriv->urbs; usbi_mutex_lock(&itransfer->lock); @@ -1928,16 +1879,7 @@ cancel_remaining: /* cancel remaining urbs and wait for their completion before * reporting results */ - for (int i = tpriv->num_urbs - 1; i > urb_idx; i--) { - /* remaining URBs with continuation flag are - * automatically cancelled by the kernel */ - if (tpriv->urbs[i].flags & USBFS_URB_BULK_CONTINUATION) - continue; - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &tpriv->urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs); out_unlock: usbi_mutex_unlock(&itransfer->lock); @@ -2142,7 +2084,7 @@ static int reap_for_handle(struct libusb_device_handle *handle) } static int op_handle_events(struct libusb_context *ctx, - struct pollfd *fds, nfds_t nfds, int num_ready) + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { int r; int i = 0; diff --git a/libusb/os/poll_posix.h b/libusb/os/poll_posix.h index 17298a5..f8c9e21 100644 --- a/libusb/os/poll_posix.h +++ b/libusb/os/poll_posix.h @@ -1,8 +1,6 @@ #ifndef __LIBUSB_POLL_POSIX_H__ #define __LIBUSB_POLL_POSIX_H__ -#include <unistd.h> -#include <poll.h> #define usbi_write write #define usbi_read read #define usbi_close close diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h index 36e3915..fee89f5 100644 --- a/libusb/os/poll_windows.h +++ b/libusb/os/poll_windows.h @@ -63,8 +63,6 @@ struct pollfd { short revents; /* returned events */ }; -typedef unsigned int nfds_t; - // access modes enum rw_type { RW_NONE, diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 8001a9a..38704ac 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -1970,10 +1970,10 @@ static void windows_handle_callback (struct usbi_transfer *itransfer, uint32_t i } } -static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) +static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct windows_transfer_priv* transfer_priv = NULL; - nfds_t i = 0; + POLL_NFDS_TYPE i = 0; bool found = false; struct usbi_transfer *transfer; DWORD io_size, io_result; diff --git a/libusb/sync.c b/libusb/sync.c index d040d98..f6dc2a7 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -102,13 +102,13 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, } while (!completed) { - r = libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed); + r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) - if (libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed) < 0) + if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; @@ -172,13 +172,13 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, } while (!completed) { - r = libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed); + r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) - if (libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed) < 0) + if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; diff --git a/msvc/config.h b/msvc/config.h index 29261fe..0430858 100644 --- a/msvc/config.h +++ b/msvc/config.h @@ -20,11 +20,5 @@ /* Windows backend */ #define OS_WINDOWS /**/ -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Backend handles timeout */ -/* #undef USBI_OS_HANDLES_TIMEOUT */ - -/* timerfd headers available */ -/* #undef USBI_TIMERFD_AVAILABLE */ +/* type of second poll() argument */ +#define POLL_NFDS_TYPE unsigned int |