diff options
author | Pete Batard <pbatard@gmail.com> | 2010-02-24 11:29:43 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-02-24 11:29:43 +0000 |
commit | c83b94c78f1cc5c823b677c9963d133a2d408776 (patch) | |
tree | 1fbc38157c924eafb8134d863fbe449b52114655 /libusb | |
parent | 1d8a2cc6ae71cc445bc6d1c3f43a803e24a8fbb9 (diff) | |
download | libusb-c83b94c78f1cc5c823b677c9963d133a2d408776.tar.gz |
merge abstraction for POSIX Threads and integration changes (Michael Plante, Peter Stuge)r169
v1.0.6 release
Darwin: support multiple calls to libusb_init
Credit to Orin Eman for finding this bug.
Darwin: use logging functions
Use usbi_warn, usbi_err, and usbi_info instead of _usbi_log.
Darwin: fix memory leak in process_device
Credit to Mike Colagrosso for finding this bug.
Add internal abstraction for POSIX Threads
This prepares for a Windows backend without dependency on pthreads-w32.
pthread_* is renamed to usbi_* and PTHREAD_* to USBI_*.
A usbi_mutex_static_t and usbi_mutex_static_lock() and _unlock() are
introduced for statically initialized mutexes, since they may be
implemented using other types when pthreads mutexes aren't used.
Move -pthread from libusb/Makefile.am to host-specific AM_CFLAGS in
configure.ac. AM_CFLAGS is already used in Makefile.am.
(Numerous merge conflicts resolved by Michael Plante)
misc fixes to pthreads abstraction
* windows_compat.h should not be directly included (use libusbi.h)
* windows_usb.c still had some references to pthread_mutex_[un]lock
Add libusb_strerror() to get short error message in English from enum
(Merge conflicts resolved by Michael Plante)
Better cleanup on errors, stricter types and some good casts
Avoid various memory leaks in error code paths and remove warnings. Also
add usbi_cond_destroy in os/threads_posix.h because it's used for cleanup
now.
(Merge conflicts resolved by Michael Plante)
Rename all interface parameters to usb_interface or interface_number
(Merge conflicts resolved by Michael Plante)
Add type parameter to the list_for_each_entry() and _safe() macros
(Merge conflicts resolved by Michael Plante)
VA_ARGS workaround for logging with MSVC6
(Merge conflicts resolved by Michael Plante)
Fix context memory leak in libusb_init()
* Now holds default_context_lock for duration of libusb_init
* Doesn't allocate it if not needed
Fix the last MSVC /W3 warning
removal of pthreads from MSVC and mingw
* removed pthread*.lib from linking in msvc6 (2005/8 not yet edited)
* added threads_windows.[ch] to all project files in msvc6
* added usbi_cond_signal to both threading versions, unused
* added native windows threading code, now used
removed redundant time.h includes
removed pthread-win32 informational solution files
updated MSVC 2005/2008 for thread abstraction
fixed DDK build
fixed cygwin's use of POSIX threads
fixed dpfp/dpfp_threaded for MinGW compatibility
config_msvc.h -> msvc/config.h
pthread abstraction for DLL project files
fixed bad reference to thread_windows in 2005 DLL vcproj
cygwin ifdef is not required in threads_windows.h - removed
fixed residuals from previous patches
moved thread source detection into autotool scripts
Diffstat (limited to 'libusb')
-rw-r--r-- | libusb/Makefile.am | 12 | ||||
-rw-r--r-- | libusb/core.c | 129 | ||||
-rw-r--r-- | libusb/io.c | 177 | ||||
-rw-r--r-- | libusb/libusb.h | 14 | ||||
-rw-r--r-- | libusb/libusbi.h | 79 | ||||
-rw-r--r-- | libusb/os/darwin_usb.c | 211 | ||||
-rw-r--r-- | libusb/os/linux_usbfs.c | 30 | ||||
-rw-r--r-- | libusb/os/sources | 10 | ||||
-rw-r--r-- | libusb/os/threads_posix.h | 46 | ||||
-rw-r--r-- | libusb/os/threads_windows.c | 207 | ||||
-rw-r--r-- | libusb/os/threads_windows.h | 83 | ||||
-rw-r--r-- | libusb/os/windows_compat.c | 4 | ||||
-rw-r--r-- | libusb/os/windows_compat.h | 3 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 8 | ||||
-rw-r--r-- | libusb/sync.c | 4 |
15 files changed, 684 insertions, 333 deletions
diff --git a/libusb/Makefile.am b/libusb/Makefile.am index fb470d2..dc7ac45 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -1,8 +1,14 @@ lib_LTLIBRARIES = libusb-1.0.la -LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c -DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c -WINDOWS_USB_SRC = os/windows_usb.h os/windows_usb.c os/windows_compat.h os/windows_compat.c +if POSIX_THREADS +THREADS_SRC = os/threads_posix.h +else +THREADS_SRC = os/threads_windows.h os/threads_windows.c +endif + +LINUX_USBFS_SRC = $(THREADS_SRC) os/linux_usbfs.h os/linux_usbfs.c +DARWIN_USB_SRC = $(THREADS_SRC) os/darwin_usb.h os/darwin_usb.c +WINDOWS_USB_SRC = $(THREADS_SRC) os/windows_usb.h os/windows_usb.c os/windows_compat.h os/windows_compat.c EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(WINDOWS_USB_SRC) diff --git a/libusb/core.c b/libusb/core.c index 4e812ed..de16ea2 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -18,11 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> #include <stdarg.h> #include <stdio.h> @@ -53,7 +49,7 @@ const struct usbi_os_backend * const usbi_backend = &windows_backend; #endif struct libusb_context *usbi_default_context = NULL; -static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER; +usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; /** * \mainpage libusb-1.0 API Reference @@ -518,7 +514,7 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, if (!dev) return NULL; - r = pthread_mutex_init(&dev->lock, NULL); + r = usbi_mutex_init(&dev->lock, NULL); if (r) { free(dev); return NULL; @@ -529,9 +525,9 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, dev->session_data = session_id; memset(&dev->os_priv, 0, priv_size); - pthread_mutex_lock(&ctx->usb_devs_lock); + usbi_mutex_lock(&ctx->usb_devs_lock); list_add(&dev->list, &ctx->usb_devs); - pthread_mutex_unlock(&ctx->usb_devs_lock); + usbi_mutex_unlock(&ctx->usb_devs_lock); return dev; } @@ -571,13 +567,13 @@ struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, struct libusb_device *dev; struct libusb_device *ret = NULL; - pthread_mutex_lock(&ctx->usb_devs_lock); + usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) if (dev->session_data == session_id) { ret = dev; break; } - pthread_mutex_unlock(&ctx->usb_devs_lock); + usbi_mutex_unlock(&ctx->usb_devs_lock); return ret; } @@ -812,9 +808,9 @@ API_EXPORTED int libusb_get_max_iso_packet_size(libusb_device *dev, */ API_EXPORTED libusb_device *libusb_ref_device(libusb_device *dev) { - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); dev->refcnt++; - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return dev; } @@ -830,9 +826,9 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev) if (!dev) return; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); refcnt = --dev->refcnt; - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); if (refcnt == 0) { usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address); @@ -840,9 +836,9 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev) if (usbi_backend->destroy_device) usbi_backend->destroy_device(dev); - pthread_mutex_lock(&dev->ctx->usb_devs_lock); + usbi_mutex_lock(&dev->ctx->usb_devs_lock); list_del(&dev->list); - pthread_mutex_unlock(&dev->ctx->usb_devs_lock); + usbi_mutex_unlock(&dev->ctx->usb_devs_lock); free(dev); } @@ -880,7 +876,7 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) if (!_handle) return LIBUSB_ERROR_NO_MEM; - r = pthread_mutex_init(&_handle->lock, NULL); + r = usbi_mutex_init(&_handle->lock, NULL); if (r) { free(_handle); return LIBUSB_ERROR_OTHER; @@ -893,14 +889,14 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) r = usbi_backend->open(_handle); if (r < 0) { libusb_unref_device(dev); - pthread_mutex_destroy(&_handle->lock); + usbi_mutex_destroy(&_handle->lock); free(_handle); return (int)r; } - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_add(&_handle->list, &ctx->open_devs); - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); *handle = _handle; @@ -912,17 +908,17 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) * so that it picks up the new fd, and then continues. */ /* record that we are messing with poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify++; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* write some data on control pipe to interrupt event handlers */ r = _libusb_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(ctx, "internal signalling write failed"); - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); return 0; } @@ -935,9 +931,9 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) usbi_warn(ctx, "internal signalling read failed"); /* we're done with modifying poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* Release event handling lock and wake up event waiters */ libusb_unlock_events(ctx); @@ -999,13 +995,13 @@ out: static void do_close(struct libusb_context *ctx, struct libusb_device_handle *dev_handle) { - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_del(&dev_handle->list); - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); usbi_backend->close(dev_handle); libusb_unref_device(dev_handle->dev); - pthread_mutex_destroy(&dev_handle->lock); + usbi_mutex_destroy(&dev_handle->lock); free(dev_handle); } @@ -1039,18 +1035,18 @@ API_EXPORTED void libusb_close(libusb_device_handle *dev_handle) * descriptor from the polling loop. */ /* record that we are messing with poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify++; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* write some data on control pipe to interrupt event handlers */ r = _libusb_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(ctx, "internal signalling write failed, closing anyway"); do_close(ctx, dev_handle); - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); return; } @@ -1066,9 +1062,9 @@ API_EXPORTED void libusb_close(libusb_device_handle *dev_handle) do_close(ctx, dev_handle); /* we're done with modifying poll fds */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); /* Release event handling lock and wake up event waiters */ libusb_unlock_events(ctx); @@ -1215,7 +1211,7 @@ API_EXPORTED int libusb_claim_interface(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (dev->claimed_interfaces & (1 << interface_number)) goto out; @@ -1224,7 +1220,7 @@ API_EXPORTED int libusb_claim_interface(libusb_device_handle *dev, dev->claimed_interfaces |= 1 << interface_number; out: - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return r; } @@ -1252,7 +1248,7 @@ API_EXPORTED int libusb_release_interface(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (!(dev->claimed_interfaces & (1 << interface_number))) { r = LIBUSB_ERROR_NOT_FOUND; goto out; @@ -1263,7 +1259,7 @@ API_EXPORTED int libusb_release_interface(libusb_device_handle *dev, dev->claimed_interfaces &= ~(1 << interface_number); out: - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return r; } @@ -1296,12 +1292,12 @@ API_EXPORTED int libusb_set_interface_alt_setting(libusb_device_handle *dev, if (interface_number >= sizeof(dev->claimed_interfaces) * 8) return LIBUSB_ERROR_INVALID_PARAM; - pthread_mutex_lock(&dev->lock); + usbi_mutex_lock(&dev->lock); if (!(dev->claimed_interfaces & (1 << interface_number))) { - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return LIBUSB_ERROR_NOT_FOUND; } - pthread_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev->lock); return usbi_backend->set_interface_altsetting(dev, interface_number, alternate_setting); @@ -1472,12 +1468,23 @@ API_EXPORTED void libusb_set_debug(libusb_context *ctx, int level) API_EXPORTED int libusb_init(libusb_context **context) { char *dbg = getenv("LIBUSB_DEBUG"); - struct libusb_context *ctx = malloc(sizeof(*ctx)); + struct libusb_context *ctx; int r; - if (!ctx) + usbi_mutex_static_lock(&default_context_lock); + if (!context && usbi_default_context) { + usbi_mutex_static_unlock(&default_context_lock); + return 0; /* using default; nothing to do. */ + } + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + usbi_mutex_static_unlock(&default_context_lock); return LIBUSB_ERROR_NO_MEM; + } memset(ctx, 0, sizeof(*ctx)); +#ifdef USBI_TIMERFD_AVAILABLE + ctx->timerfd = -1; +#endif if (dbg) { ctx->debug = atoi(dbg); @@ -1487,17 +1494,17 @@ API_EXPORTED int libusb_init(libusb_context **context) usbi_dbg(""); + usbi_mutex_init(&ctx->usb_devs_lock, NULL); + usbi_mutex_init(&ctx->open_devs_lock, NULL); + list_init(&ctx->usb_devs); + list_init(&ctx->open_devs); + if (usbi_backend->init) { r = usbi_backend->init(ctx); if (r) goto err; } - pthread_mutex_init(&ctx->usb_devs_lock, NULL); - pthread_mutex_init(&ctx->open_devs_lock, NULL); - list_init(&ctx->usb_devs); - list_init(&ctx->open_devs); - r = usbi_io_init(ctx); if (r < 0) { if (usbi_backend->exit) @@ -1505,24 +1512,20 @@ API_EXPORTED int libusb_init(libusb_context **context) goto err; } - pthread_mutex_lock(&default_context_lock); if (!usbi_default_context) { usbi_dbg("created default context"); usbi_default_context = ctx; - } else if (!context) { - pthread_mutex_unlock(&default_context_lock); - libusb_exit(ctx); /* free superfluous context; use default context */ - return 0; } - pthread_mutex_unlock(&default_context_lock); + usbi_mutex_static_unlock(&default_context_lock); if (context) *context = ctx; return 0; err: - pthread_mutex_destroy(&ctx->open_devs_lock); - pthread_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_static_unlock(&default_context_lock); + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); free(ctx); return r; } @@ -1546,15 +1549,15 @@ API_EXPORTED void libusb_exit(struct libusb_context *ctx) if (usbi_backend->exit) usbi_backend->exit(); - pthread_mutex_lock(&default_context_lock); + usbi_mutex_static_lock(&default_context_lock); if (ctx == usbi_default_context) { usbi_dbg("freeing default context"); usbi_default_context = NULL; } - pthread_mutex_unlock(&default_context_lock); + usbi_mutex_static_unlock(&default_context_lock); - pthread_mutex_destroy(&ctx->open_devs_lock); - pthread_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); free(ctx); } @@ -1617,8 +1620,8 @@ void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, * Returns a constant string with an English short description of the given * error code. The caller should never free() the returned pointer since it * points to a constant string. - * The returned string is encoded in ASCII form and always starts with a capital - * letter and ends without any dot. + * The returned string is encoded in ASCII form and always starts with a + * capital letter and ends without any dot. * \param errcode the error code whose description is desired * \returns a short description of the error code in English */ diff --git a/libusb/io.c b/libusb/io.c index 728d85f..198c48b 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -18,20 +18,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> -#include <pthread.h> #include <signal.h> #include <stdint.h> #include <stdlib.h> #include <string.h> -#if defined(_MSC_VER) -#include <time.h> -#else +#if !defined(_MSC_VER) #include <sys/time.h> #endif #include <time.h> @@ -1011,27 +1004,27 @@ printf("completed!\n"); int usbi_io_init(struct libusb_context *ctx) { - int r; - - /* We could destroy these mutexes in all the failure cases below, - * but that would substantially complicate the code. */ - pthread_mutex_init(&ctx->flying_transfers_lock, NULL); - pthread_mutex_init(&ctx->pollfds_lock, NULL); - pthread_mutex_init(&ctx->pollfd_modify_lock, NULL); - pthread_mutex_init(&ctx->events_lock, NULL); - pthread_mutex_init(&ctx->event_waiters_lock, NULL); - pthread_cond_init(&ctx->event_waiters_cond, NULL); + int p, r; + + usbi_mutex_init(&ctx->flying_transfers_lock, NULL); + usbi_mutex_init(&ctx->pollfds_lock, NULL); + usbi_mutex_init(&ctx->pollfd_modify_lock, NULL); + usbi_mutex_init(&ctx->events_lock, NULL); + usbi_mutex_init(&ctx->event_waiters_lock, NULL); + usbi_cond_init(&ctx->event_waiters_cond, NULL); list_init(&ctx->flying_transfers); list_init(&ctx->pollfds); /* FIXME should use an eventfd on kernels that support it */ - r = _libusb_pipe(ctx->ctrl_pipe); - if (r < 0) - return LIBUSB_ERROR_OTHER; + p = _libusb_pipe(ctx->ctrl_pipe); + if (p < 0) { + r = LIBUSB_ERROR_OTHER; + goto err; + } r = usbi_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN); if (r < 0) - return r; + goto err; #ifdef USBI_TIMERFD_AVAILABLE ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), @@ -1039,10 +1032,8 @@ int usbi_io_init(struct libusb_context *ctx) if (ctx->timerfd >= 0) { usbi_dbg("using timerfd for timeouts"); r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); - if (r < 0) { - close(ctx->timerfd); - return r; - } + if (r < 0) + goto err; } else { usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); ctx->timerfd = -1; @@ -1050,6 +1041,24 @@ int usbi_io_init(struct libusb_context *ctx) #endif return 0; + +err: +#ifdef USBI_TIMERFD_AVAILABLE + if (ctx->timerfd != -1) + _libusb_close(ctx->timerfd); +#endif + if (0 == p) { + usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]); + _libusb_close(ctx->ctrl_pipe[0]); + _libusb_close(ctx->ctrl_pipe[1]); + } + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); + return r; } void usbi_io_exit(struct libusb_context *ctx) @@ -1063,16 +1072,14 @@ void usbi_io_exit(struct libusb_context *ctx) _libusb_close(ctx->timerfd); } #endif - pthread_mutex_destroy(&ctx->flying_transfers_lock); - pthread_mutex_destroy(&ctx->pollfds_lock); - pthread_mutex_destroy(&ctx->pollfd_modify_lock); - pthread_mutex_destroy(&ctx->events_lock); - pthread_mutex_destroy(&ctx->event_waiters_lock); - pthread_cond_destroy(&ctx->event_waiters_cond); + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); } -/* Converts the relative timeout in the libusb_transfer "rider" - * to an absolute timeout in usbi_transfer */ static int calculate_timeout(struct usbi_transfer *transfer) { int r; @@ -1113,7 +1120,7 @@ static int add_to_flying_list(struct usbi_transfer *transfer) int r = 0; int first = 1; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); /* if we have no other flying transfers, start the list with this one */ if (list_empty(&ctx->flying_transfers)) { @@ -1147,7 +1154,7 @@ static int add_to_flying_list(struct usbi_transfer *transfer) /* otherwise we need to be inserted at the end */ list_add_tail(&transfer->list, &ctx->flying_transfers); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } @@ -1188,7 +1195,7 @@ API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(int iso_packets) memset(itransfer, 0, alloc_size); itransfer->num_iso_packets = iso_packets; - pthread_mutex_init(&itransfer->lock, NULL); + usbi_mutex_init(&itransfer->lock, NULL); return __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); } @@ -1219,7 +1226,7 @@ API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer) free(transfer->buffer); itransfer = __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - pthread_mutex_destroy(&itransfer->lock); + usbi_mutex_destroy(&itransfer->lock); free(itransfer); } @@ -1241,7 +1248,7 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) int r; int first; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); itransfer->transferred = 0; itransfer->flags = 0; r = calculate_timeout(itransfer); @@ -1253,9 +1260,9 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) first = add_to_flying_list(itransfer); r = usbi_backend->submit_transfer(itransfer); if (r) { - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); } #ifdef USBI_TIMERFD_AVAILABLE else if (first && usbi_using_timerfd(ctx)) { @@ -1271,7 +1278,7 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) #endif out: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1296,12 +1303,12 @@ API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer) int r; usbi_dbg(""); - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); r = usbi_backend->cancel_transfer(itransfer); if (r < 0) usbi_err(TRANSFER_CTX(transfer), "cancel transfer failed error %d", r); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1385,10 +1392,10 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * to rearm the timerfd if the transfer that expired was the one with * the shortest timeout. */ - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); r = arm_timerfd_for_next_timeout(ctx); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (r < 0) { return r; @@ -1418,9 +1425,9 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * this point. */ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) libusb_free_transfer(transfer); - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); return 0; } @@ -1468,15 +1475,15 @@ API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * start event handling */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 1; } - r = pthread_mutex_trylock(&ctx->events_lock); + r = usbi_mutex_trylock(&ctx->events_lock); if (r) return 1; @@ -1505,7 +1512,7 @@ API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) API_EXPORTED void libusb_lock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->events_lock); + usbi_mutex_lock(&ctx->events_lock); ctx->event_handler_active = 1; } @@ -1521,14 +1528,14 @@ API_EXPORTED void libusb_unlock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); ctx->event_handler_active = 0; - pthread_mutex_unlock(&ctx->events_lock); + usbi_mutex_unlock(&ctx->events_lock); /* FIXME: perhaps we should be a bit more efficient by not broadcasting * the availability of the events lock when we are modifying pollfds * (check ctx->pollfd_modify)? */ - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1559,9 +1566,9 @@ API_EXPORTED int libusb_event_handling_ok(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * continue event handling */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 0; @@ -1587,9 +1594,9 @@ API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) /* is someone else waiting to modify poll fds? if so, don't let this thread * start event handling -- indicate that event handling is happening */ - pthread_mutex_lock(&ctx->pollfd_modify_lock); + usbi_mutex_lock(&ctx->pollfd_modify_lock); r = ctx->pollfd_modify; - pthread_mutex_unlock(&ctx->pollfd_modify_lock); + usbi_mutex_unlock(&ctx->pollfd_modify_lock); if (r) { usbi_dbg("someone else is modifying poll fds"); return 1; @@ -1620,7 +1627,7 @@ API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1631,7 +1638,7 @@ API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) API_EXPORTED void libusb_unlock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_unlock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1666,7 +1673,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) USBI_GET_CONTEXT(ctx); if (tv == NULL) { - pthread_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); + usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); return 0; } @@ -1683,7 +1690,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) timeout.tv_sec++; } - r = pthread_cond_timedwait(&ctx->event_waiters_cond, + r = usbi_cond_timedwait(&ctx->event_waiters_cond, &ctx->event_waiters_lock, &timeout); return (r == ETIMEDOUT); } @@ -1757,9 +1764,9 @@ static int handle_timeouts(struct libusb_context *ctx) { int r; USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); r = handle_timeouts_locked(ctx); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } #endif @@ -1773,7 +1780,7 @@ static int handle_timerfd_trigger(struct libusb_context *ctx) if (r < 0) return r; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); /* process the timeout that just happened */ r = handle_timeouts_locked(ctx); @@ -1784,7 +1791,7 @@ static int handle_timerfd_trigger(struct libusb_context *ctx) r = arm_timerfd_for_next_timeout(ctx); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } #endif @@ -1800,14 +1807,14 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) int i = -1; int timeout_ms; - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) nfds++; /* TODO: malloc when number of fd's changes, not on every poll */ fds = malloc(sizeof(*fds) * nfds); if (!fds) { - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return LIBUSB_ERROR_NO_MEM; } @@ -1819,7 +1826,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) fds[i].events = pollfd->events; fds[i].revents = 0; } - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); timeout_ms = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); @@ -1960,7 +1967,7 @@ retry: return r; } - /* another thread is doing event handling. wait for pthread events that + /* another thread is doing event handling. wait for thread events that * notify event completion. */ libusb_lock_event_waiters(ctx); @@ -2117,9 +2124,9 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, if (usbi_using_timerfd(ctx)) return 0; - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); if (list_empty(&ctx->flying_transfers)) { - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); usbi_dbg("no URBs, no timeout!"); return 0; } @@ -2131,7 +2138,7 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, break; } } - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (!found) { usbi_dbg("all URBs have already been processed for timeouts"); @@ -2210,9 +2217,9 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) usbi_dbg("add fd %d events %d", fd, events); ipollfd->pollfd.fd = fd; ipollfd->pollfd.events = events; - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_add_tail(&ipollfd->list, &ctx->pollfds); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); if (ctx->fd_added_cb) ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); @@ -2226,7 +2233,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) int found = 0; usbi_dbg("remove fd %d", fd); - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) if (ipollfd->pollfd.fd == fd) { found = 1; @@ -2235,12 +2242,12 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) if (!found) { usbi_dbg("couldn't find fd %d to remove", fd); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return; } list_del(&ipollfd->list); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); free(ipollfd); if (ctx->fd_removed_cb) ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); @@ -2266,7 +2273,7 @@ API_EXPORTED const struct libusb_pollfd **libusb_get_pollfds( size_t cnt = 0; USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) cnt++; @@ -2279,7 +2286,7 @@ API_EXPORTED const struct libusb_pollfd **libusb_get_pollfds( ret[cnt] = NULL; out: - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return (const struct libusb_pollfd **) ret; } @@ -2308,14 +2315,14 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) */ while (1) { - pthread_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); to_cancel = NULL; list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list, struct usbi_transfer) if (__USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) { to_cancel = cur; break; } - pthread_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); if (!to_cancel) break; diff --git a/libusb/libusb.h b/libusb/libusb.h index 1c3e9c8..0127d9f 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -24,7 +24,6 @@ #include <stdint.h> #ifdef _MSC_VER #define inline __inline -#include <time.h> #else #include <sys/time.h> #endif @@ -659,9 +658,9 @@ enum libusb_error { /** Other error */ LIBUSB_ERROR_OTHER = -99 - - /* IMPORTANT: when adding new values to this enum, remember to update the - libusb_strerror() function implementation! */ + + /* IMPORTANT: when adding new values to this enum, remember to + update the libusb_strerror() function implementation! */ }; /** \ingroup asyncio @@ -1173,8 +1172,8 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) { return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, - (uint16_t) length, 1000); + LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, + 0, data, (uint16_t)length, 1000); } /** \ingroup desc @@ -1195,7 +1194,8 @@ static inline int libusb_get_string_descriptor(libusb_device_handle *dev, uint8_t desc_index, uint16_t langid, unsigned char *data, int length) { return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, + LIBUSB_REQUEST_GET_DESCRIPTOR, + (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), langid, data, (uint16_t)length, 1000); } diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 2355535..3dfcfd0 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -21,18 +21,10 @@ #ifndef __LIBUSBI_H__ #define __LIBUSBI_H__ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif -#include <pthread.h> #include <stddef.h> #include <time.h> -#ifdef OS_WINDOWS -#include <windows.h> -#include "os/windows_compat.h" -#else +#if !defined(OS_WINDOWS) || defined(__CYGWIN__) #include <poll.h> #endif @@ -60,16 +52,16 @@ struct list_head { * pos - A structure pointer has a "member" element * head - list head * member - the list_head element in "pos" - * type - the type of the first parameter + * type - the type of the first parameter */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ +#define list_for_each_entry(pos, head, member, type) \ + for (pos = list_entry((head)->next, type, member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) -#define list_for_each_entry_safe(pos, n, head, member, type) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ +#define list_for_each_entry_safe(pos, n, head, member, type) \ + for (pos = list_entry((head)->next, type, member), \ + n = list_entry(pos->member.next, type, member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, type, member)) @@ -124,10 +116,8 @@ enum usbi_log_level { void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, const char *function, const char *format, ...); - #if !defined(_MSC_VER) || _MSC_VER > 1200 - #ifdef ENABLE_LOGGING #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) #else @@ -144,9 +134,7 @@ void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, #define usbi_warn(ctx, ...) _usbi_log(ctx, LOG_LEVEL_WARNING, __VA_ARGS__) #define usbi_err(ctx, ...) _usbi_log(ctx, LOG_LEVEL_ERROR, __VA_ARGS__) - -#else - +#else /* !defined(_MSC_VER) || _MSC_VER > 1200 */ void usbi_log_v(struct libusb_context *ctx, enum usbi_log_level level, const char *function, const char *format, va_list args); @@ -177,10 +165,7 @@ void inline usbi_dbg(const char *format, ...) { } #endif - -#endif - - +#endif /* !defined(_MSC_VER) || _MSC_VER > 1200 */ #define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context #define DEVICE_CTX(dev) ((dev)->ctx) @@ -189,6 +174,17 @@ void inline usbi_dbg(const char *format, ...) #define ITRANSFER_CTX(transfer) \ (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) +/* Internal abstraction for thread synchronization */ +#if defined(OS_LINUX) || defined(OS_DARWIN) +#include <os/threads_posix.h> +#elif defined(OS_WINDOWS) && (defined(__CYGWIN__) || defined(USE_PTHREAD)) +#include <os/threads_posix.h> +#include <os/windows_compat.h> +#elif defined(OS_WINDOWS) +#include <os/threads_windows.h> +#include <os/windows_compat.h> +#endif + extern struct libusb_context *usbi_default_context; struct libusb_context { @@ -200,28 +196,28 @@ struct libusb_context { int ctrl_pipe[2]; struct list_head usb_devs; - pthread_mutex_t usb_devs_lock; + usbi_mutex_t usb_devs_lock; /* A list of open handles. Backends are free to traverse this if required. */ struct list_head open_devs; - pthread_mutex_t open_devs_lock; + usbi_mutex_t open_devs_lock; /* this is a list of in-flight transfer handles, sorted by timeout * expiration. URBs to timeout the soonest are placed at the beginning of * the list, URBs that will time out later are placed after, and urbs with * infinite timeout are always placed at the very end. */ struct list_head flying_transfers; - pthread_mutex_t flying_transfers_lock; + usbi_mutex_t flying_transfers_lock; /* list of poll fds */ struct list_head pollfds; - pthread_mutex_t pollfds_lock; + usbi_mutex_t pollfds_lock; /* a counter that is set when we want to interrupt event handling, in order * to modify the poll fd set. and a lock to protect it. */ unsigned int pollfd_modify; - pthread_mutex_t pollfd_modify_lock; + usbi_mutex_t pollfd_modify_lock; /* user callbacks for pollfd changes */ libusb_pollfd_added_cb fd_added_cb; @@ -229,15 +225,15 @@ struct libusb_context { void *fd_cb_user_data; /* ensures that only one thread is handling events at any one time */ - pthread_mutex_t events_lock; + usbi_mutex_t events_lock; /* used to see if there is an active thread doing event handling */ int event_handler_active; /* used to wait for event completion in threads other than the one that is * event handling */ - pthread_mutex_t event_waiters_lock; - pthread_cond_t event_waiters_cond; + usbi_mutex_t event_waiters_lock; + usbi_cond_t event_waiters_cond; #ifdef USBI_TIMERFD_AVAILABLE /* used for timeout handling, if supported by OS. @@ -255,7 +251,7 @@ struct libusb_context { struct libusb_device { /* lock protects refcnt, everything else is finalized at initialization * time */ - pthread_mutex_t lock; + usbi_mutex_t lock; int refcnt; struct libusb_context *ctx; @@ -271,7 +267,7 @@ struct libusb_device { struct libusb_device_handle { /* lock protects claimed_interfaces */ - pthread_mutex_t lock; + usbi_mutex_t lock; unsigned long claimed_interfaces; struct list_head list; @@ -313,7 +309,7 @@ struct usbi_transfer { * cancelling the transfer from another thread while you are processing * its completion (presumably there would be races within your OS backend * if this were possible). */ - pthread_mutex_t lock; + usbi_mutex_t lock; }; #define __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ @@ -628,7 +624,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*claim_interface)(struct libusb_device_handle *handle, int iface); + int (*claim_interface)(struct libusb_device_handle *handle, int interface_number); /* Release a previously claimed interface. * @@ -645,7 +641,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*release_interface)(struct libusb_device_handle *handle, int iface); + int (*release_interface)(struct libusb_device_handle *handle, int interface_number); /* Set the alternate setting for an interface. * @@ -662,7 +658,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*set_interface_altsetting)(struct libusb_device_handle *handle, - int iface, int altsetting); + int interface_number, int altsetting); /* Clear a halt/stall condition on an endpoint. * @@ -709,7 +705,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*kernel_driver_active)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Detach a kernel driver from an interface. Optional. * @@ -725,7 +721,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*detach_kernel_driver)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Attach a kernel driver to an interface. Optional. * @@ -742,7 +738,7 @@ struct usbi_os_backend { * - another LIBUSB_ERROR code on other failure */ int (*attach_kernel_driver)(struct libusb_device_handle *handle, - int iface); + int interface_number); /* Destroy a device. Optional. * @@ -859,3 +855,4 @@ extern const struct usbi_os_backend darwin_backend; extern const struct usbi_os_backend windows_backend; #endif + diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index de3e9a6..1fc6a0e 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1,6 +1,6 @@ /* * darwin backend for libusb 1.0 - * Copyright (C) 2008-2009 Nathan Hjelm <hjelmn@users.sourceforge.net> + * Copyright (C) 2008-2010 Nathan Hjelm <hjelmn@users.sourceforge.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,6 +44,7 @@ static mach_port_t libusb_darwin_mp = 0; /* master port */ static CFRunLoopRef libusb_darwin_acfl = NULL; /* async cf loop */ +static int initCount = 0; /* async event thread */ static pthread_t libusb_darwin_at; @@ -83,6 +84,8 @@ static const char *darwin_error_str (int result) { return "device not responding"; case kIOReturnOverrun: return "data overrun"; + case kIOReturnCannotWire: + return "physical memory can not be wired down"; default: return "unknown error"; } @@ -121,7 +124,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui int8_t i, iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "converting ep address 0x%02x to pipeRef and interface", ep); + usbi_info (HANDLE_CTX(dev_handle), "converting ep address 0x%02x to pipeRef and interface", ep); for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { cInterface = &priv->interfaces[iface]; @@ -131,7 +134,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui if (cInterface->endpoint_addrs[i] == ep) { *pipep = i + 1; *ifcp = iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "pipe %d on interface %d matches", *pipep, *ifcp); + usbi_info (HANDLE_CTX(dev_handle), "pipe %d on interface %d matches", *pipep, *ifcp); return 0; } } @@ -139,7 +142,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui } /* No pipe found with the correct endpoint address */ - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_WARNING, "no pipeRef found with endpoint address 0x%02x.", ep); + usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); return -1; } @@ -218,7 +221,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFTypeRef locationCF; UInt32 message; - _usbi_log (ctx, LOG_LEVEL_INFO, "a device has been detached"); + usbi_info (ctx, "a device has been detached"); while ((device = IOIteratorNext (rem_devices)) != 0) { /* get the location from the i/o registry */ @@ -228,7 +231,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFRelease (locationCF); IOObjectRelease (device); - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { dpriv = (struct darwin_device_priv *)handle->dev->os_priv; @@ -241,7 +244,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); } } @@ -261,7 +264,7 @@ static void *event_thread_main (void *arg0) { io_notification_port_t libusb_notification_port; io_iterator_t libusb_rem_device_iterator; - _usbi_log (ctx, LOG_LEVEL_INFO, "creating hotplug event source"); + usbi_info (ctx, "creating hotplug event source"); CFRetain (CFRunLoopGetCurrent ()); @@ -277,7 +280,7 @@ static void *event_thread_main (void *arg0) { (void *)ctx, &libusb_rem_device_iterator); if (kresult != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_ERROR, "could not add hotplug event source: %s", darwin_error_str (kresult)); + usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); pthread_exit ((void *)kresult); } @@ -288,12 +291,12 @@ static void *event_thread_main (void *arg0) { /* let the main thread know about the async runloop */ libusb_darwin_acfl = CFRunLoopGetCurrent (); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); /* run the runloop */ CFRunLoopRun(); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread exiting"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread exiting"); /* delete notification port */ CFRunLoopSourceInvalidate (libusb_notification_cfsource); @@ -309,33 +312,37 @@ static void *event_thread_main (void *arg0) { static int darwin_init(struct libusb_context *ctx) { IOReturn kresult; - /* Create the master port for talking to IOKit */ - if (!libusb_darwin_mp) { - kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); + if (!(initCount++)) { + /* Create the master port for talking to IOKit */ + if (!libusb_darwin_mp) { + kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); - if (kresult != kIOReturnSuccess || !libusb_darwin_mp) - return darwin_to_libusb (kresult); - } + if (kresult != kIOReturnSuccess || !libusb_darwin_mp) + return darwin_to_libusb (kresult); + } - pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); + pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); - while (!libusb_darwin_acfl) - usleep (10); + while (!libusb_darwin_acfl) + usleep (10); + } return 0; } static void darwin_exit (void) { - void *ret; + if (!(--initCount)) { + void *ret; - /* stop the async runloop */ - CFRunLoopStop (libusb_darwin_acfl); - pthread_join (libusb_darwin_at, &ret); + /* stop the async runloop */ + CFRunLoopStop (libusb_darwin_acfl); + pthread_join (libusb_darwin_at, &ret); - if (libusb_darwin_mp) - mach_port_deallocate(mach_task_self(), libusb_darwin_mp); + if (libusb_darwin_mp) + mach_port_deallocate(mach_task_self(), libusb_darwin_mp); - libusb_darwin_mp = 0; + libusb_darwin_mp = 0; + } } static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { @@ -400,7 +407,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi if (!priv->device) { kresult = darwin_get_device (priv->location, &device); if (kresult || !device) { - _usbi_log (DEVICE_CTX (dev), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (DEVICE_CTX (dev), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -434,12 +441,13 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device UInt16 address, idVendor, idProduct; UInt8 bDeviceClass, bDeviceSubClass; IOUSBDevRequest req; - int ret; + int ret, need_unref = 0; dev = usbi_get_device_by_session_id(ctx, locationID); if (!dev) { - _usbi_log (ctx, LOG_LEVEL_INFO, "allocating new device for location 0x%08x", locationID); + usbi_info (ctx, "allocating new device for location 0x%08x", locationID); dev = usbi_alloc_device(ctx, locationID); + need_unref = 1; if (!dev) return LIBUSB_ERROR_NO_MEM; @@ -490,8 +498,9 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device (*device)->USBDeviceClose (device); if (ret != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_WARNING, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); - libusb_unref_device(dev); + usbi_warn (ctx, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); + if (need_unref) + libusb_unref_device(dev); return -1; } /**** end: retrieve device descriptors ****/ @@ -499,7 +508,7 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ if (libusb_le16_to_cpu (priv->dev_descriptor.idProduct) != idProduct) { /* not a valid device */ - _usbi_log (ctx, LOG_LEVEL_WARNING, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", + usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", idProduct, libusb_le16_to_cpu (priv->dev_descriptor.idProduct)); libusb_unref_device(dev); return -1; @@ -515,13 +524,14 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device ret = usbi_sanitize_device(dev); if (ret < 0) { - libusb_unref_device(dev); + if (need_unref) + libusb_unref_device(dev); return -1; } } else { priv = (struct darwin_device_priv *)dev->os_priv; - _usbi_log (ctx, LOG_LEVEL_INFO, "using existing device for location 0x%08x", locationID); + usbi_info (ctx, "using existing device for location 0x%08x", locationID); } /* append the device to the list of discovered devices */ @@ -531,8 +541,11 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device *_discdevs = discdevs; - _usbi_log (ctx, LOG_LEVEL_INFO, "found device with address %d at %s", dev->device_address, priv->sys_path); + usbi_info (ctx, "found device with address %d at %s", dev->device_address, priv->sys_path); + if (need_unref) + libusb_unref_device(dev); + return 0; } @@ -569,7 +582,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { if (0 == dpriv->open_count) { kresult = darwin_get_device (dpriv->location, &darwin_device); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -579,7 +592,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); switch (kresult) { case kIOReturnExclusiveAccess: @@ -616,7 +629,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device open for access"); + usbi_info (HANDLE_CTX (dev_handle), "device open for access"); return 0; } @@ -629,7 +642,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (dpriv->open_count == 0) { /* something is probably very wrong if this is the case */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Close called on a device that was not open!\n"); + usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n"); return; } @@ -653,7 +666,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (kresult) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); } } @@ -661,7 +674,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (kresult) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); } dpriv->device = NULL; @@ -752,12 +765,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { u_int16_t dont_care2; int i; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "building table of endpoints."); + usbi_info (HANDLE_CTX (dev_handle), "building table of endpoints."); /* retrieve the total number of endpoints on this interface */ kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -767,12 +780,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { &dont_care2, &dont_care3); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); return darwin_to_libusb (kresult); } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); + usbi_info (HANDLE_CTX (dev_handle), "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); cInterface->endpoint_addrs[i - 1] = ((direction << 7 & LIBUSB_ENDPOINT_DIR_MASK) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } @@ -806,50 +819,50 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i be configured. Otherwise, we need to do it ourselves, or there will be no interfaces for the device. */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "no interface found; selecting configuration" ); + usbi_info (HANDLE_CTX (dev_handle), "no interface found; selecting configuration" ); kresult = (*(dpriv->device))->GetNumberOfConfigurations (dpriv->device, &nConfig); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); return darwin_to_libusb(kresult); } if (nConfig < 1) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: no configurations"); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: no configurations"); return LIBUSB_ERROR_OTHER; } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device has %d configuration%s. using the first", + usbi_info (HANDLE_CTX (dev_handle), "device has %d configuration%s. using the first", (int)nConfig, (nConfig > 1 ? "s" : "") ); /* Always use the first configuration */ kresult = (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, 0, &configDesc); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetConfigurationDescriptorPtr: %s", + usbi_err (HANDLE_CTX (dev_handle), "GetConfigurationDescriptorPtr: %s", darwin_error_str(kresult)); new_config = 1; } else new_config = configDesc->bConfigurationValue; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "new configuration value is %d", new_config); + usbi_info (HANDLE_CTX (dev_handle), "new configuration value is %d", new_config); /* set the configuration */ kresult = darwin_set_configuration (dev_handle, new_config); if (kresult != LIBUSB_SUCCESS) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not set configuration"); + usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); return kresult; } kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } } if (!usbInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -857,12 +870,12 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } if (!plugInInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "plugin interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -874,7 +887,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)&cInterface->interface); if (kresult || !cInterface->interface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "QueryInterface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -884,7 +897,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* claim the interface */ kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); if (kresult) { - _usbi_log(HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -893,7 +906,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -902,7 +915,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* create async event source */ kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not create async event source"); + usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); /* can't continue without an async event source */ (void)darwin_release_interface (dev_handle, iface); @@ -913,7 +926,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* add the cfSource to the async thread's run loop */ CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface opened"); + usbi_info (HANDLE_CTX (dev_handle), "interface opened"); return 0; } @@ -940,11 +953,11 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); kresult = (*(cInterface->interface))->Release(cInterface->interface); if (kresult != kIOReturnSuccess) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); cInterface->interface = IO_OBJECT_NULL; @@ -970,7 +983,7 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -987,7 +1000,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c /* determine the interface/endpoint to use */ if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, &iface) != 0) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1001,7 +1014,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); #endif if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ClearPipeStall: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1012,7 +1025,7 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->ResetDevice (dpriv->device); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ResetDevice: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1025,7 +1038,7 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1072,7 +1085,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1103,8 +1116,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { } if (ret) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "bulk transfer failed (dir = %s): %s", is_read ? "In" : "Out", - darwin_error_str(ret)); + usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", is_read ? "In" : "Out", + darwin_error_str(ret), ret); return darwin_to_libusb (ret); } @@ -1137,7 +1150,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* determine the interface/endpoint to use */ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1147,7 +1160,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* Last but not least we need the bus frame number */ kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); if (kresult) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "failed to get bus frame number: %d", kresult); + usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); free(tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1168,7 +1181,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { itransfer); if (kresult != kIOReturnSuccess) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", + usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", darwin_error_str(kresult)); free (tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1203,7 +1216,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "control request failed: %s", darwin_error_str(kresult)); + usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1220,7 +1233,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return submit_iso_transfer(itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1230,7 +1243,7 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) { struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv; IOReturn kresult; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions control pipe"); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions control pipe"); kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); @@ -1245,19 +1258,19 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { IOReturn kresult; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } cInterface = &priv->interfaces[iface]; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); /* abort transactions */ (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "calling clear pipe stall to clear the data toggle bit"); + usbi_info (ITRANSFER_CTX (itransfer), "calling clear pipe stall to clear the data toggle bit"); /* clear the data toggle bit */ #if (InterfaceVersion < 190) @@ -1281,7 +1294,7 @@ static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return darwin_abort_transfers (itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1302,7 +1315,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; UInt32 message; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "an async io operation has completed"); + usbi_info (ITRANSFER_CTX (itransfer), "an async io operation has completed"); /* send a completion message to the device's file descriptor */ message = MESSAGE_ASYNC_IO_COMPLETE; @@ -1315,7 +1328,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { enum libusb_transfer_status status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling bulk completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling bulk completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1326,17 +1339,17 @@ static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "bulk error. pipe is stalled"); + usbi_warn (ITRANSFER_CTX (itransfer), "bulk error. pipe is stalled"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); status = LIBUSB_TRANSFER_ERROR; } @@ -1348,7 +1361,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int i, status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling isoc completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling isoc completion with status %d", result); if (result == kIOReturnSuccess && tpriv->isoc_framelist) { /* copy isochronous results back */ @@ -1368,17 +1381,17 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1388,7 +1401,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t static void darwin_control_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { int status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling control completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling control completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1399,12 +1412,12 @@ static void darwin_control_callback (struct usbi_transfer *itransfer, kern_retur usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1426,7 +1439,7 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return darwin_isoc_callback (itransfer, result); break; default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); } } @@ -1437,13 +1450,13 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds int i = 0, ret; UInt32 message; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { struct pollfd *pollfd = &fds[i]; struct libusb_device_handle *handle; struct darwin_device_handle_priv *hpriv = NULL; - _usbi_log (ctx, LOG_LEVEL_INFO, "checking fd %i with revents = %x", fds[i], pollfd->revents); + usbi_info (ctx, "checking fd %i with revents = %x", fds[i], pollfd->revents); if (!pollfd->revents) continue; @@ -1486,11 +1499,11 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds darwin_handle_callback (itransfer, kresult, io_size); break; default: - _usbi_log (ctx, LOG_LEVEL_ERROR, "unknown message received from device pipe"); + usbi_err (ctx, "unknown message received from device pipe"); } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return 0; } diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 3888aa9..dd38e65 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1775,7 +1775,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; int r = 0; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, urb_idx + 1, num_urbs); @@ -1819,7 +1819,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, if (tpriv->reap_action == CANCELLED) { free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); r = usbi_handle_transfer_cancellation(itransfer); goto out_unlock; } @@ -1897,10 +1897,10 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, completed: free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); out_unlock: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1914,7 +1914,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, int urb_idx = 0; int i; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); for (i = 0; i < num_urbs; i++) { if (urb == tpriv->iso_urbs[i]) { urb_idx = i + 1; @@ -1923,7 +1923,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, } if (urb_idx == 0) { usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return LIBUSB_ERROR_NOT_FOUND; } @@ -1951,10 +1951,10 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, usbi_dbg("CANCEL: last URB handled, reporting"); free_iso_urbs(tpriv); if (tpriv->reap_action == CANCELLED) { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } else { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_ERROR); } @@ -1981,12 +1981,12 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, if (urb_idx == num_urbs) { usbi_dbg("last URB in transfer --> complete!"); free_iso_urbs(tpriv); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); } out: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return 0; } @@ -1996,7 +1996,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int status; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d", urb->status); if (urb->status == 0) @@ -2008,7 +2008,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, "cancel: unrecognised urb status %d", urb->status); free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } @@ -2036,7 +2036,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); } @@ -2087,7 +2087,7 @@ static int op_handle_events(struct libusb_context *ctx, int r; int i = 0; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { struct pollfd *pollfd = &fds[i]; struct libusb_device_handle *handle; @@ -2118,7 +2118,7 @@ static int op_handle_events(struct libusb_context *ctx, r = 0; out: - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return r; } diff --git a/libusb/os/sources b/libusb/os/sources index c4d0163..669e32a 100644 --- a/libusb/os/sources +++ b/libusb/os/sources @@ -7,12 +7,6 @@ DLLDEF=..\libusb-1.0.def MSC_WARNING_LEVEL=/W3 !ENDIF -!IF "$(_BUILDARCH)"=="AMD64" -PTHREAD_LIB=pthreadVC2_x64.lib -!ELSE -PTHREAD_LIB=pthreadVC2.lib -!ENDIF - USE_MSVCRT=1 INCLUDES=..;..\..;..\..\msvc;$(DDK_INC_PATH) @@ -22,13 +16,13 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\advapi32.lib \ $(SDK_LIB_PATH)\user32.lib \ $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - ..\..\msvc\$(PTHREAD_LIB) + $(SDK_LIB_PATH)\ole32.lib SOURCES=..\core.c \ ..\descriptor.c \ ..\io.c \ ..\sync.c \ + threads_windows.c \ windows_compat.c \ windows_usb.c \ libusb-1.0.rc diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h new file mode 100644 index 0000000..7e34dc5 --- /dev/null +++ b/libusb/os/threads_posix.h @@ -0,0 +1,46 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright (C) 2010 Peter Stuge <peter@stuge.se> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBUSB_THREADS_POSIX_H__ +#define __LIBUSB_THREADS_POSIX_H__ + +#include <pthread.h> + +#define usbi_mutex_static_t static pthread_mutex_t +#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define usbi_mutex_static_lock pthread_mutex_lock +#define usbi_mutex_static_unlock pthread_mutex_unlock + +#define usbi_mutex_t pthread_mutex_t +#define usbi_mutex_init pthread_mutex_init +#define usbi_mutex_lock pthread_mutex_lock +#define usbi_mutex_unlock pthread_mutex_unlock +#define usbi_mutex_trylock pthread_mutex_trylock +#define usbi_mutex_destroy pthread_mutex_destroy + +#define usbi_cond_t pthread_cond_t +#define usbi_cond_init pthread_cond_init +#define usbi_cond_wait pthread_cond_wait +#define usbi_cond_timedwait pthread_cond_timedwait +#define usbi_cond_broadcast pthread_cond_broadcast +#define usbi_cond_destroy pthread_cond_destroy +#define usbi_cond_signal pthread_cond_signal + +#endif /* __LIBUSB_THREADS_POSIX_H__ */ diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c new file mode 100644 index 0000000..f0704b2 --- /dev/null +++ b/libusb/os/threads_windows.c @@ -0,0 +1,207 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 2010 Michael Plante <michael.plante@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> +#include <objbase.h> +#include <errno.h> +#include <stdarg.h> + +#include "libusb.h" +#include "libusbi.h" + + +int usbi_mutex_init(usbi_mutex_t *mutex, + const usbi_mutexattr_t *attr) { + if(! mutex) return ((errno=EINVAL)); + *mutex = CreateMutex(NULL, FALSE, NULL); + if(!*mutex) return ((errno=ENOMEM)); + return 0; +} +int usbi_mutex_destroy(usbi_mutex_t *mutex) { + // It is not clear if CloseHandle failure is due to failure to unlock. + // If so, this should be errno=EBUSY. + if(!mutex || !CloseHandle(*mutex)) return ((errno=EINVAL)); + *mutex = NULL; + return 0; +} +int usbi_mutex_trylock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, 0); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + if(result == WAIT_TIMEOUT) + return ((errno=EBUSY)); + return ((errno=EINVAL)); // don't know how this would happen + // so don't know proper errno +} +int usbi_mutex_lock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, INFINITE); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + return ((errno=EINVAL)); // don't know how this would happen + // so don't know proper errno +} +int usbi_mutex_unlock(usbi_mutex_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + if(!ReleaseMutex(mutex)) return ((errno=EPERM )); + return 0; +} + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + while (InterlockedExchange((LONG *)mutex, 1) == 1) { + SleepEx(0, TRUE); + } + return 0; +} +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + *mutex = 0; + return 0; +} + + + +int usbi_cond_init(usbi_cond_t *cond, + const usbi_condattr_t *attr) { + if(!cond) return ((errno=EINVAL)); + list_init(&cond->waiters ); + list_init(&cond->not_waiting); + return 0; +} +int usbi_cond_destroy(usbi_cond_t *cond) { + // This assumes no one is using this anymore. The check MAY NOT BE safe. + struct usbi_cond_perthread *pos, *prev_pos = NULL; + if(!cond) return ((errno=EINVAL)); + if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!) + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + free(prev_pos); + list_del(&pos->list); + prev_pos = pos; + } + free(prev_pos); + prev_pos = pos = NULL; + + return 0; +} + +int usbi_cond_broadcast(usbi_cond_t *cond) { + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + int fail = 0; + struct usbi_cond_perthread *pos; + if(!cond) return ((errno=EINVAL)); + list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { + if(!SetEvent(pos->event)) + fail = 1; + } + // The wait function will remove its respective item from the list. + return fail ? ((errno=EINVAL)) : 0; +} +int usbi_cond_signal(usbi_cond_t *cond) { + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + struct usbi_cond_perthread *pos; + if(!cond) return ((errno=EINVAL)); + if(list_empty(&cond->waiters)) return 0; // no one to wakeup. + pos = list_entry(&cond->waiters.next, struct usbi_cond_perthread, list); + // The wait function will remove its respective item from the list. + return SetEvent(pos->event) ? 0 : ((errno=EINVAL)); +} +static int __inline usbi_cond_intwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + DWORD timeout_ms) { + struct usbi_cond_perthread *pos; + int found = 0, r; + DWORD r2,tid = GetCurrentThreadId(); + if(!cond || !mutex) return ((errno=EINVAL)); + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + if(tid == pos->tid) { + found = 1; + break; + } + } + if(!found) { + pos = malloc(sizeof(struct usbi_cond_perthread)); + if(!pos) return ((errno=ENOMEM)); // This errno is not POSIX-allowed. + pos->tid = tid; + pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. + if(!pos->event) { + free(pos); + return ((errno=ENOMEM)); + } + list_add(&pos->list, &cond->not_waiting); + } + + list_del(&pos->list); // remove from not_waiting list. + list_add(&pos->list, &cond->waiters); + + r = usbi_mutex_unlock(mutex); + if(r) return r; + r2 = WaitForSingleObject(pos->event, timeout_ms); + r = usbi_mutex_lock(mutex); + if(r) return r; + + list_del(&pos->list); + list_add(&pos->list, &cond->not_waiting); + + if(r2 == WAIT_TIMEOUT) return ((errno=ETIMEDOUT)); + + return 0; +} +// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) { + return usbi_cond_intwait(cond, mutex, INFINITE); +} +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + const struct timespec *abstime) { + FILETIME ftime; + ULARGE_INTEGER rtime; + struct timeval targ_time, cur_time, delta_time; + struct timespec cur_time_ns; + DWORD millis; + extern const uint64_t epoch_time; + + GetSystemTimeAsFileTime(&ftime); + rtime.LowPart = ftime.dwLowDateTime; + rtime.HighPart = ftime.dwHighDateTime; + rtime.QuadPart -= epoch_time; + cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000); + cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000)*100); + TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns); + + TIMESPEC_TO_TIMEVAL(&targ_time, abstime); + timersub(&targ_time, &cur_time, &delta_time); + if(delta_time.tv_sec <= 0) // abstime already passed? + millis = 0; + else { + millis = delta_time.tv_usec/1000; + millis += delta_time.tv_sec *1000; + } + + return usbi_cond_intwait(cond, mutex, millis); +} + diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h new file mode 100644 index 0000000..52ae9c1 --- /dev/null +++ b/libusb/os/threads_windows.h @@ -0,0 +1,83 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 2010 Michael Plante <michael.plante@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBUSB_THREADS_WINDOWS_H__ +#define __LIBUSB_THREADS_WINDOWS_H__ + +#define usbi_mutex_static_t volatile LONG +#define USBI_MUTEX_INITIALIZER 0 + +#define usbi_mutex_t HANDLE + +struct usbi_cond_perthread { + struct list_head list; + DWORD tid; + HANDLE event; +}; +struct usbi_cond_t_ { + // Every time a thread touches the CV, it winds up in one of these lists. + // It stays there until the CV is destroyed, even if the thread + // terminates. + struct list_head waiters; + struct list_head not_waiting; +}; +typedef struct usbi_cond_t_ usbi_cond_t; + +// We *were* getting timespec from pthread.h: +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +// We *were* getting ETIMEDOUT from pthread.h: +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#define usbi_mutexattr_t void +#define usbi_condattr_t void + + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); + + +int usbi_mutex_init(usbi_mutex_t *mutex, + const usbi_mutexattr_t *attr); +int usbi_mutex_lock(usbi_mutex_t *mutex); +int usbi_mutex_unlock(usbi_mutex_t *mutex); +int usbi_mutex_trylock(usbi_mutex_t *mutex); +int usbi_mutex_destroy(usbi_mutex_t *mutex); + +int usbi_cond_init(usbi_cond_t *cond, + const usbi_condattr_t *attr); +int usbi_cond_destroy(usbi_cond_t *cond); +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + const struct timespec *abstime); +int usbi_cond_broadcast(usbi_cond_t *cond); +int usbi_cond_signal(usbi_cond_t *cond); + +#endif /* __LIBUSB_THREADS_WINDOWS_H__ */ + diff --git a/libusb/os/windows_compat.c b/libusb/os/windows_compat.c index 9b74d35..bd5a948 100644 --- a/libusb/os/windows_compat.c +++ b/libusb/os/windows_compat.c @@ -68,7 +68,7 @@ #include <stdint.h> #include <io.h> -#include "windows_compat.h" +#include "libusbi.h" // Uncomment to debug the polling layer //#define DEBUG_WINDOWS_COMPAT @@ -88,7 +88,7 @@ #pragma warning(disable:28719) #endif -#if defined(__CYGWIN__ ) +#if defined(__CYGWIN__) // cygwin produces a warning unless these prototypes are defined extern int _close(int fd); extern int _snprintf(char *buffer, size_t count, const char *format, ...); diff --git a/libusb/os/windows_compat.h b/libusb/os/windows_compat.h index 322ce78..12de260 100644 --- a/libusb/os/windows_compat.h +++ b/libusb/os/windows_compat.h @@ -43,6 +43,7 @@ extern enum windows_version windows_version; #define MAX_FDS 256 +#if !defined(__CYGWIN__) #define POLLIN 0x0001 /* There is data to read */ #define POLLPRI 0x0002 /* There is urgent data to read */ #define POLLOUT 0x0004 /* Writing now will not block */ @@ -55,6 +56,7 @@ struct pollfd { short events; /* requested events */ short revents; /* returned events */ }; +#endif typedef unsigned int nfds_t; // access modes @@ -129,3 +131,4 @@ do { \ } \ } while (0) #endif + diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index dae05ef..f6a0796 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -35,11 +35,7 @@ // ***USE AT YOUR OWN RISKS*** //#define FORCE_INSTANT_TIMEOUTS -#if defined(_MSC_VER) -#include <config_msvc.h> -#else #include <config.h> -#endif #include <windows.h> #include <setupapi.h> #include <ctype.h> @@ -1876,7 +1872,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, struct usbi_transfer *transfer; DWORD io_size, io_result; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); @@ -1918,7 +1914,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return LIBUSB_SUCCESS; } diff --git a/libusb/sync.c b/libusb/sync.c index 6e65bce..bd4d970 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -17,11 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef _MSC_VER -#include <config_msvc.h> -#else #include <config.h> -#endif #include <errno.h> #include <stdint.h> #include <stdlib.h> |