summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorikarienator@chromium.org <ikarienator@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-25 04:08:25 +0000
committerikarienator@chromium.org <ikarienator@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-25 04:08:25 +0000
commit957b2fd4c5155b3af6fe7e8f175b8edfeea3561b (patch)
tree97499bd8b5e2a4231bd38c76c801b33085c77cce
parent9774828ef9335061effda32bed169e72a962efe8 (diff)
downloadchromium_src-957b2fd4c5155b3af6fe7e8f175b8edfeea3561b.zip
chromium_src-957b2fd4c5155b3af6fe7e8f175b8edfeea3561b.tar.gz
chromium_src-957b2fd4c5155b3af6fe7e8f175b8edfeea3561b.tar.bz2
Recommit: Roll libusbx to 1.0.17
Original: https://codereview.chromium.org/24227008/ > Roll libusbx to 1.0.17 > > R=meacer@chromium.org > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=225105 TBR=meacer@chromium.org,xiyuan@chromium.org Review URL: https://codereview.chromium.org/24470004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225137 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--third_party/libusb/README.chromium2
-rw-r--r--third_party/libusb/src/libusb/core.c90
-rw-r--r--third_party/libusb/src/libusb/descriptor.c6
-rw-r--r--third_party/libusb/src/libusb/hotplug.c46
-rw-r--r--third_party/libusb/src/libusb/io.c10
-rw-r--r--third_party/libusb/src/libusb/libusb.h24
-rw-r--r--third_party/libusb/src/libusb/libusbi.h5
-rw-r--r--third_party/libusb/src/libusb/os/darwin_usb.c35
-rw-r--r--third_party/libusb/src/libusb/os/linux_netlink.c131
-rw-r--r--third_party/libusb/src/libusb/os/linux_udev.c65
-rw-r--r--third_party/libusb/src/libusb/os/linux_usbfs.c71
-rw-r--r--third_party/libusb/src/libusb/os/linux_usbfs.h2
-rw-r--r--third_party/libusb/src/libusb/os/openbsd_usb.c333
-rw-r--r--third_party/libusb/src/libusb/os/poll_posix.h16
-rw-r--r--third_party/libusb/src/libusb/os/poll_windows.c2
-rw-r--r--third_party/libusb/src/libusb/os/threads_posix.c4
-rw-r--r--third_party/libusb/src/libusb/os/wince_usb.c13
-rw-r--r--third_party/libusb/src/libusb/os/windows_usb.c15
-rw-r--r--third_party/libusb/src/libusb/strerror.c2
-rw-r--r--third_party/libusb/src/libusb/version.h2
-rw-r--r--third_party/libusb/src/libusb/version_nano.h2
21 files changed, 586 insertions, 290 deletions
diff --git a/third_party/libusb/README.chromium b/third_party/libusb/README.chromium
index 348d919..134cbed 100644
--- a/third_party/libusb/README.chromium
+++ b/third_party/libusb/README.chromium
@@ -1,6 +1,6 @@
Name: libusbx
URL: http://libusb.org
-Version: 1.0.16
+Version: 1.0.17
License: LGPL 2.1
License File: src/COPYING
Security Critical: yes
diff --git a/third_party/libusb/src/libusb/core.c b/third_party/libusb/src/libusb/core.c
index e29e8df..e816284 100644
--- a/third_party/libusb/src/libusb/core.c
+++ b/third_party/libusb/src/libusb/core.c
@@ -33,6 +33,9 @@
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
#ifdef __ANDROID__
#include <android/log.h>
@@ -47,6 +50,8 @@ const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend;
const struct usbi_os_backend * const usbi_backend = &darwin_backend;
#elif defined(OS_OPENBSD)
const struct usbi_os_backend * const usbi_backend = &openbsd_backend;
+#elif defined(OS_NETBSD)
+const struct usbi_os_backend * const usbi_backend = &netbsd_backend;
#elif defined(OS_WINDOWS)
const struct usbi_os_backend * const usbi_backend = &windows_backend;
#elif defined(OS_WINCE)
@@ -56,7 +61,7 @@ const struct usbi_os_backend * const usbi_backend = &wince_backend;
#endif
struct libusb_context *usbi_default_context = NULL;
-const struct libusb_version libusb_version_internal =
+static const struct libusb_version libusb_version_internal =
{ LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO,
LIBUSB_RC, "http://libusbx.org" };
static int default_context_refcnt = 0;
@@ -564,6 +569,10 @@ void usbi_disconnect_device(struct libusb_device *dev)
dev->attached = 0;
usbi_mutex_unlock(&dev->lock);
+ usbi_mutex_lock(&ctx->usb_devs_lock);
+ list_del(&dev->list);
+ usbi_mutex_unlock(&ctx->usb_devs_lock);
+
/* Signal that an event has occurred for this device if we support hotplug AND
* the hotplug pipe is ready. This prevents an event from getting raised during
* initial enumeration. libusb_handle_events will take care of dereferencing the
@@ -574,10 +583,6 @@ void usbi_disconnect_device(struct libusb_device *dev)
usbi_err(DEVICE_CTX(dev), "error writing hotplug message");
}
}
-
- usbi_mutex_lock(&ctx->usb_devs_lock);
- list_del(&dev->list);
- usbi_mutex_unlock(&ctx->usb_devs_lock);
}
/* Perform some final sanity checks on a newly discovered device. If this
@@ -1873,10 +1878,6 @@ err_free_ctx:
if (ctx == usbi_default_context)
usbi_default_context = NULL;
- usbi_mutex_destroy(&ctx->open_devs_lock);
- usbi_mutex_destroy(&ctx->usb_devs_lock);
- usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
-
usbi_mutex_static_lock(&active_contexts_lock);
list_del (&ctx->list);
usbi_mutex_static_unlock(&active_contexts_lock);
@@ -1888,6 +1889,10 @@ err_free_ctx:
}
usbi_mutex_unlock(&ctx->usb_devs_lock);
+ usbi_mutex_destroy(&ctx->open_devs_lock);
+ usbi_mutex_destroy(&ctx->usb_devs_lock);
+ usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
+
free(ctx);
err_unlock:
usbi_mutex_static_unlock(&default_context_lock);
@@ -2026,10 +2031,42 @@ int usbi_gettimeofday(struct timeval *tp, void *tzp)
}
#endif
-static void usbi_log_str(struct libusb_context *ctx, const char * str)
+static void usbi_log_str(struct libusb_context *ctx,
+ enum libusb_log_level level, const char * str)
{
- UNUSED(ctx);
+#if defined(USE_SYSTEM_LOGGING_FACILITY)
+#if defined(OS_WINDOWS) || defined(OS_WINCE)
+ /* Windows CE only supports the Unicode version of OutputDebugString. */
+ WCHAR wbuf[USBI_MAX_LOG_LEN];
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf));
+ OutputDebugStringW(wbuf);
+#elif defined(__ANDROID__)
+ int priority = ANDROID_LOG_UNKNOWN;
+ switch (level) {
+ case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break;
+ case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break;
+ case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break;
+ case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break;
+ }
+ __android_log_write(priority, "libusb", str);
+#elif defined(HAVE_SYSLOG_FUNC)
+ int syslog_level = LOG_INFO;
+ switch (level) {
+ case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break;
+ case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break;
+ case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break;
+ case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break;
+ }
+ syslog(syslog_level, "%s", str);
+#else /* All of gcc, Clang, XCode seem to use #warning */
+#warning System logging is not supported on this platform. Logging to stderr will be used instead.
+ fputs(str, stderr);
+#endif
+#else
fputs(str, stderr);
+#endif /* USE_SYSTEM_LOGGING_FACILITY */
+ UNUSED(ctx);
+ UNUSED(level);
}
void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
@@ -2059,33 +2096,11 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
return;
#endif
-#ifdef __ANDROID__
- int prio;
- switch (level) {
- case LOG_LEVEL_INFO:
- prio = ANDROID_LOG_INFO;
- break;
- case LOG_LEVEL_WARNING:
- prio = ANDROID_LOG_WARN;
- break;
- case LOG_LEVEL_ERROR:
- prio = ANDROID_LOG_ERROR;
- break;
- case LOG_LEVEL_DEBUG:
- prio = ANDROID_LOG_DEBUG;
- break;
- default:
- prio = ANDROID_LOG_UNKNOWN;
- break;
- }
-
- __android_log_vprint(prio, "LibUsb", format, args);
-#else
usbi_gettimeofday(&now, NULL);
if ((global_debug) && (!has_debug_header_been_displayed)) {
has_debug_header_been_displayed = 1;
- usbi_log_str(ctx, "[timestamp] [threadID] facility level [function call] <message>\n");
- usbi_log_str(ctx, "--------------------------------------------------------------------------------\n");
+ usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>\n");
+ usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------\n");
}
if (now.tv_usec < timestamp_origin.tv_usec) {
now.tv_sec--;
@@ -2108,7 +2123,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
prefix = "debug";
break;
case LIBUSB_LOG_LEVEL_NONE:
- break;
+ return;
default:
prefix = "unknown";
break;
@@ -2143,8 +2158,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
}
strcpy(buf + header_len + text_len, USBI_LOG_LINE_END);
- usbi_log_str(ctx, buf);
-#endif
+ usbi_log_str(ctx, level, buf);
}
void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
diff --git a/third_party/libusb/src/libusb/descriptor.c b/third_party/libusb/src/libusb/descriptor.c
index ba6d1467..e1c4915 100644
--- a/third_party/libusb/src/libusb/descriptor.c
+++ b/third_party/libusb/src/libusb/descriptor.c
@@ -660,7 +660,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
/* iterate through all configurations, returning the index of the configuration
* matching a specific bConfigurationValue in the idx output parameter, or -1
* if the config was not found.
- * returns 0 or a LIBUSB_ERROR code
+ * returns 0 on success or a LIBUSB_ERROR code
*/
int usbi_get_config_index_by_value(struct libusb_device *dev,
uint8_t bConfigurationValue, int *idx)
@@ -673,8 +673,10 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
int host_endian;
int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
&host_endian);
- if (r < 0)
+ if (r < 0) {
+ *idx = -1;
return r;
+ }
if (tmp[5] == bConfigurationValue) {
*idx = i;
return 0;
diff --git a/third_party/libusb/src/libusb/hotplug.c b/third_party/libusb/src/libusb/hotplug.c
index 6b04342..081bc79 100644
--- a/third_party/libusb/src/libusb/hotplug.c
+++ b/third_party/libusb/src/libusb/hotplug.c
@@ -59,7 +59,11 @@
*
* A callback function must return an int (0 or 1) indicating whether the callback is
* expecting additional events. Returning 0 will rearm the callback and 1 will cause
- * the callback to be deregistered.
+ * the callback to be deregistered. Note that when callbacks are called from
+ * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
+ * flag, the callback return value is ignored, iow you cannot cause a callback
+ * to be deregistered by returning 1 when it is called from
+ * libusb_hotplug_register_callback().
*
* Callbacks for a particular context are automatically deregistered by libusb_exit().
*
@@ -167,8 +171,7 @@ static int usbi_hotplug_match_cb (struct libusb_context *ctx,
return 0;
}
- return hotplug_cb->cb (ctx == usbi_default_context ? NULL : ctx,
- dev, event, hotplug_cb->user_data);
+ return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
}
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
@@ -192,18 +195,7 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
- /* loop through and disconnect all open handles for this device */
- if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
- struct libusb_device_handle *handle;
-
- usbi_mutex_lock(&ctx->open_devs_lock);
- list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
- if (dev == handle->dev) {
- usbi_handle_disconnect (handle);
- }
- }
- usbi_mutex_unlock(&ctx->open_devs_lock);
- }
+ /* the backend is expected to call the callback for each active transfer */
}
int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
@@ -253,19 +245,29 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
list_add(&new_callback->list, &ctx->hotplug_cbs);
- if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
- struct libusb_device *dev;
+ usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
- usbi_mutex_lock(&ctx->usb_devs_lock);
- list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
- (void) usbi_hotplug_match_cb (ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, new_callback);
+ if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
+ int i, len;
+ struct libusb_device **devs;
+
+ len = (int) libusb_get_device_list(ctx, &devs);
+ if (len < 0) {
+ libusb_hotplug_deregister_callback(ctx,
+ new_callback->handle);
+ return len;
+ }
+
+ for (i = 0; i < len; i++) {
+ usbi_hotplug_match_cb(ctx, devs[i],
+ LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
+ new_callback);
}
- usbi_mutex_unlock(&ctx->usb_devs_lock);
+ libusb_free_device_list(devs, 1);
}
- usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
if (handle) {
*handle = new_callback->handle;
diff --git a/third_party/libusb/src/libusb/io.c b/third_party/libusb/src/libusb/io.c
index 4368b99..4f22963 100644
--- a/third_party/libusb/src/libusb/io.c
+++ b/third_party/libusb/src/libusb/io.c
@@ -787,7 +787,7 @@ void cb(struct libusb_transfer *transfer)
void myfunc() {
struct libusb_transfer *transfer;
- unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE];
+ unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2)));
int completed = 0;
transfer = libusb_alloc_transfer(0);
@@ -1459,6 +1459,8 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
}
usbi_mutex_unlock(&ctx->flying_transfers_lock);
+ /* keep a reference to this device */
+ libusb_ref_device(transfer->dev_handle->dev);
out:
updated_fds = (itransfer->flags & USBI_TRANSFER_UPDATED_FDS);
usbi_mutex_unlock(&itransfer->lock);
@@ -1522,6 +1524,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
struct libusb_transfer *transfer =
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_context *ctx = TRANSFER_CTX(transfer);
+ struct libusb_device_handle *handle = transfer->dev_handle;
uint8_t flags;
int r = 0;
@@ -1562,6 +1565,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
usbi_mutex_lock(&ctx->event_waiters_lock);
usbi_cond_broadcast(&ctx->event_waiters_cond);
usbi_mutex_unlock(&ctx->event_waiters_lock);
+ libusb_unref_device(handle->dev);
return 0;
}
@@ -1996,8 +2000,8 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
/* read the message from the hotplug thread */
ret = usbi_read(ctx->hotplug_pipe[0], &message, sizeof (message));
- if (ret < sizeof(message)) {
- usbi_err(ctx, "hotplug pipe read error %d < %d",
+ if (ret != sizeof(message)) {
+ usbi_err(ctx, "hotplug pipe read error %d != %u",
ret, sizeof(message));
r = LIBUSB_ERROR_OTHER;
goto handled;
diff --git a/third_party/libusb/src/libusb/libusb.h b/third_party/libusb/src/libusb/libusb.h
index 15bd0d5..d144b3e 100644
--- a/third_party/libusb/src/libusb/libusb.h
+++ b/third_party/libusb/src/libusb/libusb.h
@@ -156,7 +156,7 @@ typedef unsigned __int32 uint32_t;
extern "C" {
#endif
-/** \def libusb_cpu_to_le16
+/** \fn libusb_cpu_to_le16
* \ingroup misc
* Convert a 16-bit value from host-endian to little-endian format. On
* little endian systems, this function does nothing. On big endian systems,
@@ -1434,7 +1434,7 @@ static inline unsigned char *libusb_control_transfer_get_data(
static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
struct libusb_transfer *transfer)
{
- return (struct libusb_control_setup *) transfer->buffer;
+ return (struct libusb_control_setup *)(void *) transfer->buffer;
}
/** \ingroup asyncio
@@ -1443,6 +1443,7 @@ static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
* be given in host-endian byte order.
*
* \param buffer buffer to output the setup packet into
+ * This pointer must be aligned to at least 2 bytes boundary.
* \param bmRequestType see the
* \ref libusb_control_setup::bmRequestType "bmRequestType" field of
* \ref libusb_control_setup
@@ -1463,7 +1464,7 @@ static inline void libusb_fill_control_setup(unsigned char *buffer,
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
uint16_t wLength)
{
- struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer;
+ struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
setup->bmRequestType = bmRequestType;
setup->bRequest = bRequest;
setup->wValue = libusb_cpu_to_le16(wValue);
@@ -1499,6 +1500,7 @@ void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer);
* \param dev_handle handle of the device that will handle the transfer
* \param buffer data buffer. If provided, this function will interpret the
* first 8 bytes as a setup packet and infer the transfer length from that.
+ * This pointer must be aligned to at least 2 bytes boundary.
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
@@ -1508,7 +1510,7 @@ static inline void libusb_fill_control_transfer(
unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data,
unsigned int timeout)
{
- struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer;
+ struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
transfer->dev_handle = dev_handle;
transfer->endpoint = 0;
transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
@@ -1883,7 +1885,7 @@ typedef enum {
*
* Since version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102
*
- * \param libusb_context context of this notification
+ * \param ctx context of this notification
* \param device libusb_device this event occurred on
* \param event event that occurred
* \param user_data user data provided when this callback was registered
@@ -1903,6 +1905,18 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx,
* armed until either it is deregistered with libusb_hotplug_deregister_callback()
* or the supplied callback returns 1 to indicate it is finished processing events.
*
+ * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be
+ * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices
+ * already plugged into the machine. Note that libusbx modifies its internal
+ * device list from a separate thread, while calling hotplug callbacks from
+ * libusb_handle_events(), so it is possible for a device to already be present
+ * on, or removed from, its internal device list, while the hotplug callbacks
+ * still need to be dispatched. This means that when using \ref
+ * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival
+ * of the same device, once from libusb_hotplug_register_callback() and once
+ * from libusb_handle_events(); and/or your callback may be called for the
+ * removal of a device for which an arrived call was never made.
+ *
* Since version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102
*
* \param[in] ctx context to register this callback with
diff --git a/third_party/libusb/src/libusb/libusbi.h b/third_party/libusb/src/libusb/libusbi.h
index 02efae30..bc608b92 100644
--- a/third_party/libusb/src/libusb/libusbi.h
+++ b/third_party/libusb/src/libusb/libusbi.h
@@ -23,6 +23,8 @@
#include "config.h"
+#include <stdlib.h>
+
#include <stddef.h>
#include <stdint.h>
#include <time.h>
@@ -433,7 +435,7 @@ void usbi_connect_device (struct libusb_device *dev);
void usbi_disconnect_device (struct libusb_device *dev);
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
-#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD)
+#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD)
#include <unistd.h>
#include "os/poll_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE)
@@ -995,6 +997,7 @@ extern const struct usbi_os_backend * const usbi_backend;
extern const struct usbi_os_backend linux_usbfs_backend;
extern const struct usbi_os_backend darwin_backend;
extern const struct usbi_os_backend openbsd_backend;
+extern const struct usbi_os_backend netbsd_backend;
extern const struct usbi_os_backend windows_backend;
extern const struct usbi_os_backend wince_backend;
diff --git a/third_party/libusb/src/libusb/os/darwin_usb.c b/third_party/libusb/src/libusb/os/darwin_usb.c
index 3f315e8..58467c3 100644
--- a/third_party/libusb/src/libusb/os/darwin_usb.c
+++ b/third_party/libusb/src/libusb/os/darwin_usb.c
@@ -210,6 +210,7 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca
return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
}
+/* Returns 1 on success, 0 on failure. */
static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
int ret = 0;
@@ -287,7 +288,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
usbi_dbg ("notifying context %p of device disconnect", ctx);
- dev = usbi_get_device_by_session_id(ctx, session);
+ dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
if (dev) {
/* signal the core that this device has been disconnected. the core will tear down this device
when the reference count reaches 0 */
@@ -701,7 +702,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
else
usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
idVendor, idProduct, darwin_error_str (ret), ret);
- return -1;
+ return darwin_to_libusb (ret);
}
/* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */
@@ -709,7 +710,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
/* not a valid device */
usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
- return -1;
+ return LIBUSB_ERROR_NO_DEVICE;
}
usbi_dbg ("cached device descriptor:");
@@ -729,21 +730,19 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
dev->can_enumerate = 1;
- return 0;
+ return LIBUSB_SUCCESS;
}
static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
struct darwin_cached_device **cached_out) {
struct darwin_cached_device *new_device;
- UInt64 sessionID, parent_sessionID;
+ UInt64 sessionID = 0, parent_sessionID = 0;
int ret = LIBUSB_SUCCESS;
usb_device_t **device;
io_service_t parent;
kern_return_t result;
UInt8 port = 0;
- *cached_out = NULL;
-
/* get some info from the io registry */
(void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
(void) get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, &port);
@@ -759,6 +758,8 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
usbi_mutex_lock(&darwin_cached_devices_lock);
do {
+ *cached_out = NULL;
+
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
usbi_dbg("matching sessionID 0x%x against cached device with sessionID 0x%x", sessionID, new_device->session);
if (new_device->session == sessionID) {
@@ -773,17 +774,15 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
usbi_dbg("caching new device with sessionID 0x%x\n", sessionID);
- new_device = calloc (1, sizeof (*new_device));
- if (!new_device) {
- ret = LIBUSB_ERROR_NO_MEM;
- break;
- }
-
device = darwin_device_from_service (service);
if (!device) {
ret = LIBUSB_ERROR_NO_DEVICE;
- free (new_device);
- new_device = NULL;
+ break;
+ }
+
+ new_device = calloc (1, sizeof (*new_device));
+ if (!new_device) {
+ ret = LIBUSB_ERROR_NO_MEM;
break;
}
@@ -833,7 +832,7 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
do {
ret = darwin_get_cached_device (ctx, service, &cached_device);
- if (ret < 0 || (cached_device && !cached_device->can_enumerate)) {
+ if (ret < 0 || !cached_device->can_enumerate) {
return ret;
}
@@ -846,7 +845,7 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
usbi_dbg ("allocating new device in context %p for with session 0x%08x",
ctx, cached_device->session);
- dev = usbi_alloc_device(ctx, cached_device->session);
+ dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
if (!dev) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -857,7 +856,7 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
darwin_ref_cached_device (priv->dev);
if (cached_device->parent_session > 0) {
- dev->parent_dev = usbi_get_device_by_session_id (ctx, cached_device->parent_session);
+ dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
} else {
dev->parent_dev = NULL;
}
diff --git a/third_party/libusb/src/libusb/os/linux_netlink.c b/third_party/libusb/src/libusb/os/linux_netlink.c
index 3a68f69..f1c1be1 100644
--- a/third_party/libusb/src/libusb/os/linux_netlink.c
+++ b/third_party/libusb/src/libusb/os/linux_netlink.c
@@ -21,6 +21,10 @@
*/
#include "config.h"
+#include "libusb.h"
+#include "libusbi.h"
+#include "linux_usbfs.h"
+
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@@ -30,46 +34,113 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
-#include <arpa/inet.h>
+#endif
-#include "libusb.h"
-#include "libusbi.h"
-#include "linux_usbfs.h"
+#include <arpa/inet.h>
+#ifdef HAVE_LINUX_NETLINK_H
#include <linux/netlink.h>
+#endif
+
+#ifdef HAVE_LINUX_FILTER_H
#include <linux/filter.h>
+#endif
#define KERNEL 1
static int linux_netlink_socket = -1;
+static int netlink_control_pipe[2] = { -1, -1 };
static pthread_t libusb_linux_event_thread;
static void *linux_netlink_event_thread_main(void *arg);
struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL };
+static int set_fd_cloexec_nb (int fd)
+{
+ int flags;
+
+#if defined(FD_CLOEXEC)
+ flags = fcntl (linux_netlink_socket, F_GETFD);
+ if (0 > flags) {
+ return -1;
+ }
+
+ if (!(flags & FD_CLOEXEC)) {
+ fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC);
+ }
+#endif
+
+ flags = fcntl (linux_netlink_socket, F_GETFL);
+ if (0 > flags) {
+ return -1;
+ }
+
+ if (!(flags & O_NONBLOCK)) {
+ fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK);
+ }
+
+ return 0;
+}
+
int linux_netlink_start_event_monitor(void)
{
+ int socktype = SOCK_RAW;
int ret;
snl.nl_groups = KERNEL;
- linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
+#if defined(SOCK_CLOEXEC)
+ socktype |= SOCK_CLOEXEC;
+#endif
+#if defined(SOCK_NONBLOCK)
+ socktype |= SOCK_NONBLOCK;
+#endif
+
+ linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
+ if (-1 == linux_netlink_socket && EINVAL == errno) {
+ linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+ }
+
if (-1 == linux_netlink_socket) {
return LIBUSB_ERROR_OTHER;
}
+ ret = set_fd_cloexec_nb (linux_netlink_socket);
+ if (0 != ret) {
+ close (linux_netlink_socket);
+ linux_netlink_socket = -1;
+ return LIBUSB_ERROR_OTHER;
+ }
+
ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl));
if (0 != ret) {
+ close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
/* TODO -- add authentication */
/* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */
+ ret = usbi_pipe(netlink_control_pipe);
+ if (ret) {
+ usbi_err(NULL, "could not create netlink control pipe");
+ close(linux_netlink_socket);
+ return LIBUSB_ERROR_OTHER;
+ }
+
ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
if (0 != ret) {
+ close(netlink_control_pipe[0]);
+ close(netlink_control_pipe[1]);
+ close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
@@ -79,22 +150,30 @@ int linux_netlink_start_event_monitor(void)
int linux_netlink_stop_event_monitor(void)
{
int r;
+ char dummy = 1;
if (-1 == linux_netlink_socket) {
/* already closed. nothing to do */
return LIBUSB_SUCCESS;
}
- r = close(linux_netlink_socket);
- if (0 > r) {
- usbi_err(NULL, "error closing netlink socket. %s", strerror(errno));
- return LIBUSB_ERROR_OTHER;
+ /* Write some dummy data to the control pipe and
+ * wait for the thread to exit */
+ r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "netlink control pipe signal failed");
}
+ pthread_join(libusb_linux_event_thread, NULL);
- pthread_cancel(libusb_linux_event_thread);
-
+ close(linux_netlink_socket);
linux_netlink_socket = -1;
+ /* close and reset control pipe */
+ close(netlink_control_pipe[0]);
+ close(netlink_control_pipe[1]);
+ netlink_control_pipe[0] = -1;
+ netlink_control_pipe[1] = -1;
+
return LIBUSB_SUCCESS;
}
@@ -214,7 +293,7 @@ static int linux_netlink_read_message(void)
/* signal device is available (or not) to all contexts */
if (detached)
- linux_hotplug_disconnected(busnum, devaddr, sys_name);
+ linux_device_disconnected(busnum, devaddr, sys_name);
else
linux_hotplug_enumerate(busnum, devaddr, sys_name);
@@ -223,20 +302,32 @@ static int linux_netlink_read_message(void)
static void *linux_netlink_event_thread_main(void *arg)
{
- struct pollfd fds = {.fd = linux_netlink_socket,
- .events = POLLIN};
+ char dummy;
+ int r;
+ struct pollfd fds[] = {
+ { .fd = netlink_control_pipe[0],
+ .events = POLLIN },
+ { .fd = linux_netlink_socket,
+ .events = POLLIN },
+ };
/* silence compiler warning */
(void) arg;
- while (1 == poll(&fds, 1, -1)) {
- if (POLLIN != fds.revents) {
+ while (poll(fds, 2, -1) >= 0) {
+ if (fds[0].revents & POLLIN) {
+ /* activity on control pipe, read the byte and exit */
+ r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "netlink control pipe read failed");
+ }
break;
}
-
- usbi_mutex_static_lock(&linux_hotplug_lock);
- linux_netlink_read_message();
- usbi_mutex_static_unlock(&linux_hotplug_lock);
+ if (fds[1].revents & POLLIN) {
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ linux_netlink_read_message();
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+ }
}
return NULL;
diff --git a/third_party/libusb/src/libusb/os/linux_udev.c b/third_party/libusb/src/libusb/os/linux_udev.c
index 5a2aadf..99ac943 100644
--- a/third_party/libusb/src/libusb/os/linux_udev.c
+++ b/third_party/libusb/src/libusb/os/linux_udev.c
@@ -46,6 +46,7 @@
/* udev context */
static struct udev *udev_ctx = NULL;
static int udev_monitor_fd = -1;
+static int udev_control_pipe[2] = {-1, -1};
static struct udev_monitor *udev_monitor = NULL;
static pthread_t linux_event_thread;
@@ -95,14 +96,23 @@ int linux_udev_start_event_monitor(void)
goto err_free_monitor;
}
+ r = usbi_pipe(udev_control_pipe);
+ if (r) {
+ usbi_err(NULL, "could not create udev control pipe");
+ goto err_free_monitor;
+ }
+
r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
if (r) {
usbi_err(NULL, "creating hotplug event thread (%d)", r);
- goto err_free_monitor;
+ goto err_close_pipe;
}
return LIBUSB_SUCCESS;
+err_close_pipe:
+ close(udev_control_pipe[0]);
+ close(udev_control_pipe[1]);
err_free_monitor:
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
@@ -115,14 +125,19 @@ err_free_ctx:
int linux_udev_stop_event_monitor(void)
{
+ char dummy = 1;
+ int r;
+
assert(udev_ctx != NULL);
assert(udev_monitor != NULL);
assert(udev_monitor_fd != -1);
- /* Cancel the event thread. This is the only way to guarantee the
- thread exits since closing the monitor fd won't necessarily cause
- poll to return. */
- pthread_cancel(linux_event_thread);
+ /* Write some dummy data to the control pipe and
+ * wait for the thread to exit */
+ r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "udev control pipe signal failed");
+ }
pthread_join(linux_event_thread, NULL);
/* Release the udev monitor */
@@ -134,27 +149,45 @@ int linux_udev_stop_event_monitor(void)
udev_unref(udev_ctx);
udev_ctx = NULL;
+ /* close and reset control pipe */
+ close(udev_control_pipe[0]);
+ close(udev_control_pipe[1]);
+ udev_control_pipe[0] = -1;
+ udev_control_pipe[1] = -1;
+
return LIBUSB_SUCCESS;
}
static void *linux_udev_event_thread_main(void *arg)
{
+ char dummy;
+ int r;
struct udev_device* udev_dev;
- struct pollfd fds = {.fd = udev_monitor_fd,
- .events = POLLIN};
+ struct pollfd fds[] = {
+ {.fd = udev_control_pipe[0],
+ .events = POLLIN},
+ {.fd = udev_monitor_fd,
+ .events = POLLIN},
+ };
usbi_dbg("udev event thread entering.");
- while (1 == poll(&fds, 1, -1)) {
- if (NULL == udev_monitor || POLLIN != fds.revents) {
+ while (poll(fds, 2, -1) >= 0) {
+ if (fds[0].revents & POLLIN) {
+ /* activity on control pipe, read the byte and exit */
+ r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "udev control pipe read failed");
+ }
break;
}
-
- usbi_mutex_static_lock(&linux_hotplug_lock);
- udev_dev = udev_monitor_receive_device(udev_monitor);
- if (udev_dev)
- udev_hotplug_event(udev_dev);
- usbi_mutex_static_unlock(&linux_hotplug_lock);
+ if (fds[1].revents & POLLIN) {
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ udev_dev = udev_monitor_receive_device(udev_monitor);
+ if (udev_dev)
+ udev_hotplug_event(udev_dev);
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+ }
}
usbi_dbg("udev event thread exiting");
@@ -207,7 +240,7 @@ static void udev_hotplug_event(struct udev_device* udev_dev)
if (strncmp(udev_action, "add", 3) == 0) {
linux_hotplug_enumerate(busnum, devaddr, sys_name);
} else if (detached) {
- linux_hotplug_disconnected(busnum, devaddr, sys_name);
+ linux_device_disconnected(busnum, devaddr, sys_name);
} else {
usbi_err(NULL, "ignoring udev action %s", udev_action);
}
diff --git a/third_party/libusb/src/libusb/os/linux_usbfs.c b/third_party/libusb/src/libusb/os/linux_usbfs.c
index 09288af..142fa2b 100644
--- a/third_party/libusb/src/libusb/os/linux_usbfs.c
+++ b/third_party/libusb/src/libusb/os/linux_usbfs.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
/*
* Linux usbfs backend for libusbx
* Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
@@ -120,7 +121,9 @@ static int sysfs_has_descriptors = -1;
/* how many times have we initted (and not exited) ? */
static volatile int init_count = 0;
-/* Serialize hotplug start/stop, scan-devices, event-thread, and poll */
+/* Serialize hotplug start/stop */
+usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER;
+/* Serialize scan-devices, event-thread, and poll */
usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER;
static int linux_start_event_monitor(void);
@@ -419,7 +422,7 @@ static int op_init(struct libusb_context *ctx)
if (sysfs_has_descriptors)
usbi_dbg("sysfs has complete descriptors");
- usbi_mutex_static_lock(&linux_hotplug_lock);
+ usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
r = LIBUSB_SUCCESS;
if (init_count == 0) {
/* start up hotplug event handler */
@@ -433,20 +436,20 @@ static int op_init(struct libusb_context *ctx)
linux_stop_event_monitor();
} else
usbi_err(ctx, "error starting hotplug event monitor");
- usbi_mutex_static_unlock(&linux_hotplug_lock);
+ usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
return r;
}
static void op_exit(void)
{
- usbi_mutex_static_lock(&linux_hotplug_lock);
+ usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
assert(init_count != 0);
if (!--init_count) {
/* tear down event handler */
(void)linux_stop_event_monitor();
}
- usbi_mutex_static_unlock(&linux_hotplug_lock);
+ usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
}
static int linux_start_event_monitor(void)
@@ -469,11 +472,19 @@ static int linux_stop_event_monitor(void)
static int linux_scan_devices(struct libusb_context *ctx)
{
+ int ret;
+
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+
#if defined(USE_UDEV)
- return linux_udev_scan_devices(ctx);
+ ret = linux_udev_scan_devices(ctx);
#else
- return linux_default_scan_devices(ctx);
+ ret = linux_default_scan_devices(ctx);
#endif
+
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+
+ return ret;
}
static void op_hotplug_poll(void)
@@ -596,6 +607,8 @@ int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr,const char *dev_node,
const char *sys_name)
{
+ int sysfs_attr;
+
usbi_dbg("getting address for device: %s detached: %d", sys_name, detached);
/* can't use sysfs to read the bus and device number if the
* device has been detached */
@@ -616,17 +629,22 @@ int linux_get_device_address (struct libusb_context *ctx, int detached,
usbi_dbg("scan %s", sys_name);
- *busnum = __read_sysfs_attr(ctx, sys_name, "busnum");
- if (0 > *busnum)
- return *busnum;
+ sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum");
+ if (0 > sysfs_attr)
+ return sysfs_attr;
+ if (sysfs_attr > 255)
+ return LIBUSB_ERROR_INVALID_PARAM;
+ *busnum = (uint8_t) sysfs_attr;
+
+ sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum");
+ if (0 > sysfs_attr)
+ return sysfs_attr;
+ if (sysfs_attr > 255)
+ return LIBUSB_ERROR_INVALID_PARAM;
- *devaddr = __read_sysfs_attr(ctx, sys_name, "devnum");
- if (0 > *devaddr)
- return *devaddr;
+ *devaddr = (uint8_t) sysfs_attr;
usbi_dbg("bus=%d dev=%d", *busnum, *devaddr);
- if (*busnum > 255 || *devaddr > 255)
- return LIBUSB_ERROR_INVALID_PARAM;
return LIBUSB_SUCCESS;
}
@@ -1072,7 +1090,7 @@ void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_na
usbi_mutex_static_unlock(&active_contexts_lock);
}
-void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
+void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
{
struct libusb_context *ctx;
struct libusb_device *dev;
@@ -1247,8 +1265,20 @@ static int op_open(struct libusb_device_handle *handle)
int r;
hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
- if (hpriv->fd < 0)
+ if (hpriv->fd < 0) {
+ if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
+ /* device will still be marked as attached if hotplug monitor thread
+ * hasn't processed remove event yet */
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ if (handle->dev->attached) {
+ usbi_dbg("open failed with no device, but device still attached");
+ linux_device_disconnected(handle->dev->bus_number,
+ handle->dev->device_address, NULL);
+ }
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+ }
return hpriv->fd;
+ }
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
if (r < 0) {
@@ -2482,6 +2512,13 @@ static int op_handle_events(struct libusb_context *ctx,
if (pollfd->revents & POLLERR) {
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd);
usbi_handle_disconnect(handle);
+ /* device will still be marked as attached if hotplug monitor thread
+ * hasn't processed remove event yet */
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ if (handle->dev->attached)
+ linux_device_disconnected(handle->dev->bus_number,
+ handle->dev->device_address, NULL);
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
continue;
}
diff --git a/third_party/libusb/src/libusb/os/linux_usbfs.h b/third_party/libusb/src/libusb/os/linux_usbfs.h
index 499bab7..1f5b191 100644
--- a/third_party/libusb/src/libusb/os/linux_usbfs.h
+++ b/third_party/libusb/src/libusb/os/linux_usbfs.h
@@ -170,7 +170,7 @@ void linux_netlink_hotplug_poll(void);
#endif
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
-void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
+void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
diff --git a/third_party/libusb/src/libusb/os/openbsd_usb.c b/third_party/libusb/src/libusb/os/openbsd_usb.c
index f4fd454..2997e53 100644
--- a/third_party/libusb/src/libusb/os/openbsd_usb.c
+++ b/third_party/libusb/src/libusb/os/openbsd_usb.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Martin Pieuchot <mpi@openbsd.org>
+ * Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -32,8 +32,8 @@
#include "libusbi.h"
struct device_priv {
- char devnode[16];
- int fd;
+ char *devname; /* name of the ugen(4) node */
+ int fd; /* device file descriptor */
unsigned char *cdesc; /* active config descriptor */
usb_device_descriptor_t ddesc; /* usb device descriptor */
@@ -82,11 +82,14 @@ static int obsd_clock_gettime(int, struct timespec *);
* Private functions
*/
static int _errno_to_libusb(int);
-static int _cache_active_config_descriptor(struct libusb_device *, int);
+static int _cache_active_config_descriptor(struct libusb_device *);
static int _sync_control_transfer(struct usbi_transfer *);
static int _sync_gen_transfer(struct usbi_transfer *);
static int _access_endpoint(struct libusb_transfer *);
+static int _bus_open(int);
+
+
const struct usbi_os_backend openbsd_backend = {
"Synchronous OpenBSD backend",
0,
@@ -131,79 +134,105 @@ const struct usbi_os_backend openbsd_backend = {
0, /* add_iso_packet_size */
};
+#define DEVPATH "/dev/"
+#define USBDEV DEVPATH "usb"
+
int
obsd_get_device_list(struct libusb_context * ctx,
struct discovered_devs **discdevs)
{
+ struct discovered_devs *ddd;
struct libusb_device *dev;
struct device_priv *dpriv;
struct usb_device_info di;
+ struct usb_device_ddesc dd;
unsigned long session_id;
- char devnode[16];
- int fd, err, i;
+ char devices[USB_MAX_DEVICES];
+ char busnode[16];
+ char *udevname;
+ int fd, addr, i, j;
usbi_dbg("");
- /* Only ugen(4) is supported */
- for (i = 0; i < USB_MAX_DEVICES; i++) {
- /* Control endpoint is always .00 */
- snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
+ for (i = 0; i < 8; i++) {
+ snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
- if ((fd = open(devnode, O_RDONLY)) < 0) {
+ if ((fd = open(busnode, O_RDWR)) < 0) {
if (errno != ENOENT && errno != ENXIO)
- usbi_err(ctx, "could not open %s", devnode);
+ usbi_err(ctx, "could not open %s", busnode);
continue;
}
- if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
- continue;
-
- session_id = (di.udi_bus << 8 | di.udi_addr);
- dev = usbi_get_device_by_session_id(ctx, session_id);
-
- if (dev) {
- dev = libusb_ref_device(dev);
- } else {
- dev = usbi_alloc_device(ctx, session_id);
- if (dev == NULL)
- return (LIBUSB_ERROR_NO_MEM);
-
- dev->bus_number = di.udi_bus;
- dev->device_address = di.udi_addr;
- dev->speed = di.udi_speed;
-
- dpriv = (struct device_priv *)dev->os_priv;
- strlcpy(dpriv->devnode, devnode, sizeof(devnode));
- dpriv->fd = -1;
-
- if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
- err = errno;
- goto error;
+ bzero(devices, sizeof(devices));
+ for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
+ if (devices[addr])
+ continue;
+
+ di.udi_addr = addr;
+ if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
+ continue;
+
+ /*
+ * XXX If ugen(4) is attached to the USB device
+ * it will be used.
+ */
+ udevname = NULL;
+ for (j = 0; j < USB_MAX_DEVNAMES; j++)
+ if (!strncmp("ugen", di.udi_devnames[j], 4)) {
+ udevname = strdup(di.udi_devnames[j]);
+ break;
+ }
+
+ session_id = (di.udi_bus << 8 | di.udi_addr);
+ dev = usbi_get_device_by_session_id(ctx, session_id);
+
+ if (dev == NULL) {
+ dev = usbi_alloc_device(ctx, session_id);
+ if (dev == NULL) {
+ close(fd);
+ return (LIBUSB_ERROR_NO_MEM);
+ }
+
+ dev->bus_number = di.udi_bus;
+ dev->device_address = di.udi_addr;
+ dev->speed = di.udi_speed;
+
+ dpriv = (struct device_priv *)dev->os_priv;
+ dpriv->fd = -1;
+ dpriv->cdesc = NULL;
+ dpriv->devname = udevname;
+
+ dd.udd_bus = di.udi_bus;
+ dd.udd_addr = di.udi_addr;
+ if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
+ libusb_unref_device(dev);
+ continue;
+ }
+ dpriv->ddesc = dd.udd_desc;
+
+ if (_cache_active_config_descriptor(dev)) {
+ libusb_unref_device(dev);
+ continue;
+ }
+
+ if (usbi_sanitize_device(dev))
+ libusb_unref_device(dev);
}
- dpriv->cdesc = NULL;
- if (_cache_active_config_descriptor(dev, fd)) {
- err = errno;
- goto error;
+ ddd = discovered_devs_append(*discdevs, dev);
+ if (ddd == NULL) {
+ close(fd);
+ return (LIBUSB_ERROR_NO_MEM);
}
- if ((err = usbi_sanitize_device(dev)))
- goto error;
+ *discdevs = ddd;
+ devices[addr] = 1;
}
- close(fd);
- if (discovered_devs_append(*discdevs, dev) == NULL)
- return (LIBUSB_ERROR_NO_MEM);
-
- libusb_unref_device(dev);
+ close(fd);
}
return (LIBUSB_SUCCESS);
-
-error:
- close(fd);
- libusb_unref_device(dev);
- return _errno_to_libusb(err);
}
int
@@ -211,15 +240,21 @@ obsd_open(struct libusb_device_handle *handle)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+ char devnode[16];
- dpriv->fd = open(dpriv->devnode, O_RDWR);
- if (dpriv->fd < 0) {
- dpriv->fd = open(dpriv->devnode, O_RDONLY);
+ if (dpriv->devname) {
+ /*
+ * Only open ugen(4) attached devices read-write, all
+ * read-only operations are done through the bus node.
+ */
+ snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
+ dpriv->devname);
+ dpriv->fd = open(devnode, O_RDWR);
if (dpriv->fd < 0)
return _errno_to_libusb(errno);
- }
- usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
+ usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
+ }
if (pipe(hpriv->pipe) < 0)
return _errno_to_libusb(errno);
@@ -233,10 +268,12 @@ obsd_close(struct libusb_device_handle *handle)
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
- usbi_dbg("close: fd %d", dpriv->fd);
+ if (dpriv->devname) {
+ usbi_dbg("close: fd %d", dpriv->fd);
- close(dpriv->fd);
- dpriv->fd = -1;
+ close(dpriv->fd);
+ dpriv->fd = -1;
+ }
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
@@ -264,9 +301,8 @@ obsd_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
- usb_config_descriptor_t *ucd;
+ usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
- ucd = (usb_config_descriptor_t *) dpriv->cdesc;
len = MIN(len, UGETW(ucd->wTotalLength));
usbi_dbg("len %d", len);
@@ -275,58 +311,48 @@ obsd_get_active_config_descriptor(struct libusb_device *dev,
*host_endian = 0;
- return len;
+ return (len);
}
int
obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
unsigned char *buf, size_t len, int *host_endian)
{
- struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
- struct usb_full_desc ufd;
+ struct usb_device_fdesc udf;
int fd, err;
- usbi_dbg("index %d, len %d", idx, len);
+ if ((fd = _bus_open(dev->bus_number)) < 0)
+ return _errno_to_libusb(errno);
- /* A config descriptor may be requested before opening the device */
- if (dpriv->fd >= 0) {
- fd = dpriv->fd;
- } else {
- fd = open(dpriv->devnode, O_RDONLY);
- if (fd < 0)
- return _errno_to_libusb(errno);
- }
+ udf.udf_bus = dev->bus_number;
+ udf.udf_addr = dev->device_address;
+ udf.udf_config_index = idx;
+ udf.udf_size = len;
+ udf.udf_data = buf;
- ufd.ufd_config_index = idx;
- ufd.ufd_size = len;
- ufd.ufd_data = buf;
+ usbi_dbg("index %d, len %d", udf.udf_config_index, len);
- if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
+ if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
err = errno;
- if (dpriv->fd < 0)
- close(fd);
+ close(fd);
return _errno_to_libusb(err);
}
-
- if (dpriv->fd < 0)
- close(fd);
+ close(fd);
*host_endian = 0;
- return len;
+ return (len);
}
int
obsd_get_configuration(struct libusb_device_handle *handle, int *config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
+ usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
- usbi_dbg("");
+ *config = ucd->bConfigurationValue;
- if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
- return _errno_to_libusb(errno);
-
- usbi_dbg("configuration %d", *config);
+ usbi_dbg("bConfigurationValue %d", *config);
return (LIBUSB_SUCCESS);
}
@@ -336,12 +362,15 @@ obsd_set_configuration(struct libusb_device_handle *handle, int config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
- usbi_dbg("configuration %d", config);
+ if (dpriv->devname == NULL)
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
+
+ usbi_dbg("bConfigurationValue %d", config);
if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
return _errno_to_libusb(errno);
- return _cache_active_config_descriptor(handle->dev, dpriv->fd);
+ return _cache_active_config_descriptor(handle->dev);
}
int
@@ -376,6 +405,9 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_alt_interface intf;
+ if (dpriv->devname == NULL)
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
+
usbi_dbg("iface %d, setting %d", iface, altsetting);
memset(&intf, 0, sizeof(intf));
@@ -392,19 +424,27 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
int
obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
- struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_ctl_request req;
+ int fd, err;
+
+ if ((fd = _bus_open(handle->dev->bus_number)) < 0)
+ return _errno_to_libusb(errno);
usbi_dbg("");
+ req.ucr_addr = handle->dev->device_address;
req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
req.ucr_request.bRequest = UR_CLEAR_FEATURE;
USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
USETW(req.ucr_request.wIndex, endpoint);
USETW(req.ucr_request.wLength, 0);
- if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
- return _errno_to_libusb(errno);
+ if (ioctl(fd, USB_REQUEST, &req) < 0) {
+ err = errno;
+ close(fd);
+ return _errno_to_libusb(err);
+ }
+ close(fd);
return (LIBUSB_SUCCESS);
}
@@ -425,6 +465,7 @@ obsd_destroy_device(struct libusb_device *dev)
usbi_dbg("");
free(dpriv->cdesc);
+ free(dpriv->devname);
}
int
@@ -564,6 +605,8 @@ obsd_clock_gettime(int clkid, struct timespec *tp)
int
_errno_to_libusb(int err)
{
+ usbi_dbg("error: %s (%d)", strerror(err), err);
+
switch (err) {
case EIO:
return (LIBUSB_ERROR_IO);
@@ -573,52 +616,64 @@ _errno_to_libusb(int err)
return (LIBUSB_ERROR_NO_DEVICE);
case ENOMEM:
return (LIBUSB_ERROR_NO_MEM);
+ case ETIMEDOUT:
+ return (LIBUSB_ERROR_TIMEOUT);
}
- usbi_dbg("error: %s", strerror(err));
-
return (LIBUSB_ERROR_OTHER);
}
int
-_cache_active_config_descriptor(struct libusb_device *dev, int fd)
+_cache_active_config_descriptor(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
- struct usb_config_desc ucd;
- struct usb_full_desc ufd;
+ struct usb_device_cdesc udc;
+ struct usb_device_fdesc udf;
unsigned char* buf;
- int len;
+ int fd, len, err;
- usbi_dbg("fd %d", fd);
+ if ((fd = _bus_open(dev->bus_number)) < 0)
+ return _errno_to_libusb(errno);
- ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
+ usbi_dbg("fd %d, addr %d", fd, dev->device_address);
- if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
+ udc.udc_bus = dev->bus_number;
+ udc.udc_addr = dev->device_address;
+ udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
+ if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
+ err = errno;
+ close(fd);
return _errno_to_libusb(errno);
+ }
- usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
+ usbi_dbg("active bLength %d", udc.udc_desc.bLength);
- len = UGETW(ucd.ucd_desc.wTotalLength);
+ len = UGETW(udc.udc_desc.wTotalLength);
buf = malloc(len);
if (buf == NULL)
return (LIBUSB_ERROR_NO_MEM);
- ufd.ufd_config_index = ucd.ucd_config_index;
- ufd.ufd_size = len;
- ufd.ufd_data = buf;
+ udf.udf_bus = dev->bus_number;
+ udf.udf_addr = dev->device_address;
+ udf.udf_config_index = udc.udc_config_index;
+ udf.udf_size = len;
+ udf.udf_data = buf;
- usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
+ usbi_dbg("index %d, len %d", udf.udf_config_index, len);
- if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
+ if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
+ err = errno;
+ close(fd);
free(buf);
- return _errno_to_libusb(errno);
+ return _errno_to_libusb(err);
}
+ close(fd);
if (dpriv->cdesc)
free(dpriv->cdesc);
dpriv->cdesc = buf;
- return (0);
+ return (LIBUSB_SUCCESS);
}
int
@@ -633,12 +688,13 @@ _sync_control_transfer(struct usbi_transfer *itransfer)
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
setup = (struct libusb_control_setup *)transfer->buffer;
- usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
+ usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
setup->bmRequestType, setup->bRequest,
libusb_le16_to_cpu(setup->wValue),
libusb_le16_to_cpu(setup->wIndex),
libusb_le16_to_cpu(setup->wLength), transfer->timeout);
+ req.ucr_addr = transfer->dev_handle->dev->device_address;
req.ucr_request.bmRequestType = setup->bmRequestType;
req.ucr_request.bRequest = setup->bRequest;
/* Don't use USETW, libusbx already deals with the endianness */
@@ -650,11 +706,30 @@ _sync_control_transfer(struct usbi_transfer *itransfer)
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
req.ucr_flags = USBD_SHORT_XFER_OK;
- if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
- return _errno_to_libusb(errno);
+ if (dpriv->devname == NULL) {
+ /*
+ * XXX If the device is not attached to ugen(4) it is
+ * XXX still possible to submit a control transfer but
+ * XXX with the default timeout only.
+ */
+ int fd, err;
- if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
- return _errno_to_libusb(errno);
+ if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
+ return _errno_to_libusb(errno);
+
+ if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
+ err = errno;
+ close(fd);
+ return _errno_to_libusb(err);
+ }
+ close(fd);
+ } else {
+ if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
+ return _errno_to_libusb(errno);
+
+ if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
+ return _errno_to_libusb(errno);
+ }
itransfer->transferred = req.ucr_actlen;
@@ -668,7 +743,7 @@ _access_endpoint(struct libusb_transfer *transfer)
{
struct handle_priv *hpriv;
struct device_priv *dpriv;
- char *s, devnode[16];
+ char devnode[16];
int fd, endpt;
mode_t mode;
@@ -681,10 +756,9 @@ _access_endpoint(struct libusb_transfer *transfer)
usbi_dbg("endpoint %d mode %d", endpt, mode);
if (hpriv->endpoints[endpt] < 0) {
- /* Pick the right node given the control one */
- strlcpy(devnode, dpriv->devnode, sizeof(devnode));
- s = strchr(devnode, '.');
- snprintf(s, 4, ".%02d", endpt);
+ /* Pick the right endpoint node */
+ snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
+ dpriv->devname, endpt);
/* We may need to read/write to the same endpoint later. */
if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
@@ -701,9 +775,14 @@ int
_sync_gen_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
+ struct device_priv *dpriv;
int fd, nr = 1;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+ dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
+
+ if (dpriv->devname == NULL)
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
/*
* Bulk, Interrupt or Isochronous transfer depends on the
@@ -732,3 +811,13 @@ _sync_gen_transfer(struct usbi_transfer *itransfer)
return (0);
}
+
+int
+_bus_open(int number)
+{
+ char busnode[16];
+
+ snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
+
+ return open(busnode, O_RDWR);
+}
diff --git a/third_party/libusb/src/libusb/os/poll_posix.h b/third_party/libusb/src/libusb/os/poll_posix.h
index 64c9bb7..5b4b2c9 100644
--- a/third_party/libusb/src/libusb/os/poll_posix.h
+++ b/third_party/libusb/src/libusb/os/poll_posix.h
@@ -1,19 +1,3 @@
-/*
- * 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_POLL_POSIX_H
#define LIBUSB_POLL_POSIX_H
diff --git a/third_party/libusb/src/libusb/os/poll_windows.c b/third_party/libusb/src/libusb/os/poll_windows.c
index 7ed19ba..abe8761 100644
--- a/third_party/libusb/src/libusb/os/poll_windows.c
+++ b/third_party/libusb/src/libusb/os/poll_windows.c
@@ -428,7 +428,7 @@ struct winfd fd_to_winfd(int fd)
CHECK_INIT_POLLING;
- if (fd <= 0)
+ if (fd < 0)
return INVALID_WINFD;
for (i=0; i<MAX_FDS; i++) {
diff --git a/third_party/libusb/src/libusb/os/threads_posix.c b/third_party/libusb/src/libusb/os/threads_posix.c
index 46f6db7..cd985fa 100644
--- a/third_party/libusb/src/libusb/os/threads_posix.c
+++ b/third_party/libusb/src/libusb/os/threads_posix.c
@@ -58,7 +58,9 @@ finish:
int usbi_get_tid(void)
{
int ret = -1;
-#if defined(__linux__)
+#if defined(__ANDROID__)
+ ret = gettid();
+#elif defined(__linux__)
ret = syscall(SYS_gettid);
#elif defined(__OpenBSD__)
/* The following only works with OpenBSD > 5.1 as it requires
diff --git a/third_party/libusb/src/libusb/os/wince_usb.c b/third_party/libusb/src/libusb/os/wince_usb.c
index e4a6633..90c129b 100644
--- a/third_party/libusb/src/libusb/os/wince_usb.c
+++ b/third_party/libusb/src/libusb/os/wince_usb.c
@@ -234,6 +234,12 @@ static int wince_init(struct libusb_context *ctx)
usbi_err(ctx, "Unable to create timer thread - aborting");
goto init_exit;
}
+
+ // Wait for timer thread to init before continuing.
+ if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
+ usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
+ goto init_exit;
+ }
}
// At this stage, either we went through full init successfully, or didn't need to
r = LIBUSB_SUCCESS;
@@ -877,6 +883,11 @@ unsigned __stdcall wince_clock_gettime_threaded(void* param)
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
}
+ // Signal wince_init() that we're ready to service requests
+ if (ReleaseSemaphore(timer_response, 1, NULL) == 0) {
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
+ }
+
// Main loop - wait for requests
while (1) {
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0;
@@ -911,7 +922,7 @@ unsigned __stdcall wince_clock_gettime_threaded(void* param)
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
if ( (nb_responses)
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
- usbi_dbg("unable to release timer semaphore %d: %s", windows_error_str(0));
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
}
continue;
case 1: // time to quit
diff --git a/third_party/libusb/src/libusb/os/windows_usb.c b/third_party/libusb/src/libusb/os/windows_usb.c
index 51ce55d..9ae11b1 100644
--- a/third_party/libusb/src/libusb/os/windows_usb.c
+++ b/third_party/libusb/src/libusb/os/windows_usb.c
@@ -886,6 +886,12 @@ static int windows_init(struct libusb_context *ctx)
}
SetThreadAffinityMask(timer_thread, 0);
+ // Wait for timer thread to init before continuing.
+ if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
+ usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
+ goto init_exit;
+ }
+
// Create a hash table to store session ids. Second parameter is better if prime
htab_create(ctx, HTAB_SIZE);
}
@@ -1759,7 +1765,7 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf
memcpy(buffer, priv->config_descriptor[config_index], size);
*host_endian = 0;
- return size;
+ return (int)size;
}
/*
@@ -2173,6 +2179,11 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
}
+ // Signal windows_init() that we're ready to service requests
+ if (ReleaseSemaphore(timer_response, 1, NULL) == 0) {
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
+ }
+
// Main loop - wait for requests
while (1) {
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0;
@@ -2207,7 +2218,7 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
if ( (nb_responses)
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
- usbi_dbg("unable to release timer semaphore %d: %s", windows_error_str(0));
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
}
continue;
case 1: // time to quit
diff --git a/third_party/libusb/src/libusb/strerror.c b/third_party/libusb/src/libusb/strerror.c
index a3c3afa..0212df8 100644
--- a/third_party/libusb/src/libusb/strerror.c
+++ b/third_party/libusb/src/libusb/strerror.c
@@ -53,7 +53,7 @@ static size_t usbi_locale = 0;
* }
* };\endcode </li>
* <li> Translate each of the English messages from the section you copied into your language </li>
- * <li> Save the file (in UTF-8 format) and send it to \c libusbx-devel@lists.sourceforge.net </li>
+ * <li> Save the file (in UTF-8 format) and send it to \c libusbx-devel\@lists.sourceforge.net </li>
* </ol>
*/
diff --git a/third_party/libusb/src/libusb/version.h b/third_party/libusb/src/libusb/version.h
index fbb9f4c..f82e8c8 100644
--- a/third_party/libusb/src/libusb/version.h
+++ b/third_party/libusb/src/libusb/version.h
@@ -23,7 +23,7 @@
#define LIBUSB_MINOR 0
#endif
#ifndef LIBUSB_MICRO
-#define LIBUSB_MICRO 16
+#define LIBUSB_MICRO 17
#endif
#ifndef LIBUSB_NANO
#define LIBUSB_NANO 0
diff --git a/third_party/libusb/src/libusb/version_nano.h b/third_party/libusb/src/libusb/version_nano.h
index 522c6fd..1e3fc7b 100644
--- a/third_party/libusb/src/libusb/version_nano.h
+++ b/third_party/libusb/src/libusb/version_nano.h
@@ -14,4 +14,4 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define LIBUSB_NANO 10774
+#define LIBUSB_NANO 10830