Hi Judd,
Attached is a patch to remove hotplug functionality from the Linux backend,
while still retaining all other fixes. This essentially gives you 1.0.18
without hotplug.
If you have time to try it, please let me know how it works out.
Chris
From c79d3eec1a54e5555a2f2da4a383d1f186fa9587 Mon Sep 17 00:00:00 2001
From: Chris Dickens <christopher.a.dick...@gmail.com>
Date: Thu, 30 Jan 2014 01:40:55 -0800
Subject: [PATCH] Remove hotplug functionality for Linux backend.
---
configure.ac | 21 ----
libusb/Makefile.am | 10 +-
libusb/os/linux_usbfs.c | 253 ++++++++++++++----------------------------------
libusb/os/linux_usbfs.h | 22 -----
4 files changed, 73 insertions(+), 233 deletions(-)
diff --git a/configure.ac b/configure.ac
index 3495acf..5063e6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,26 +98,6 @@ linux)
AC_DEFINE(OS_LINUX, 1, [Linux backend])
AC_SUBST(OS_LINUX)
AC_SEARCH_LIBS(clock_gettime, rt, [], [], -pthread)
- AC_ARG_ENABLE([udev],
- [AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])],
- [], [enable_udev="yes"])
- if test "x$enable_udev" = "xyes" ; then
- # system has udev. use it or fail!
- AC_CHECK_HEADERS([libudev.h],[],[AC_ERROR(["udev support requested but libudev not installed"])])
- AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])])
- AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug])
- else
- AC_CHECK_HEADERS([asm/types.h sys/socket.h], [], [])
- AC_CHECK_HEADERS([linux/netlink.h linux/filter.h], [], [AC_ERROR(["Linux netlink headers not found"])], [
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-])
- fi
- AC_SUBST(USE_UDEV)
case $is_backend_android in
yes)
@@ -180,7 +160,6 @@ AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd)
AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows)
AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix)
AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes")
-AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes)
if test "$threads" = posix; then
AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads])
fi
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index 80e3705..e842fc4 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -19,15 +19,7 @@ EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
os/linux_udev.c os/linux_netlink.c
if OS_LINUX
-
-if USE_UDEV
-OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
- os/linux_udev.c
-else
-OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
- os/linux_netlink.c
-endif
-
+OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC)
endif
if OS_DARWIN
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index a95d099..50bf89d 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -118,23 +118,8 @@ static int sysfs_can_relate_devices = -1;
* descriptors file, so from then on we can use them. */
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 */
-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);
-static int linux_stop_event_monitor(void);
-static int linux_scan_devices(struct libusb_context *ctx);
-static int sysfs_scan_device(struct libusb_context *ctx, const char *devname);
static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
-
-#if !defined(USE_UDEV)
-static int linux_default_scan_devices (struct libusb_context *ctx);
-#endif
+static int sysfs_scan_device(struct libusb_context *ctx, struct discovered_devs **_discdevs, const char *devname);
struct linux_device_priv {
char *sysfs_dir;
@@ -422,78 +407,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_startstop_lock);
- r = LIBUSB_SUCCESS;
- if (init_count == 0) {
- /* start up hotplug event handler */
- r = linux_start_event_monitor();
- }
- if (r == LIBUSB_SUCCESS) {
- r = linux_scan_devices(ctx);
- if (r == LIBUSB_SUCCESS)
- init_count++;
- else if (init_count == 0)
- linux_stop_event_monitor();
- } else
- usbi_err(ctx, "error starting hotplug event monitor");
- usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
-
- return r;
-}
-
-static void op_exit(void)
-{
- 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_startstop_lock);
-}
-
-static int linux_start_event_monitor(void)
-{
-#if defined(USE_UDEV)
- return linux_udev_start_event_monitor();
-#else
- return linux_netlink_start_event_monitor();
-#endif
-}
-
-static int linux_stop_event_monitor(void)
-{
-#if defined(USE_UDEV)
- return linux_udev_stop_event_monitor();
-#else
- return linux_netlink_stop_event_monitor();
-#endif
-}
-
-static int linux_scan_devices(struct libusb_context *ctx)
-{
- int ret;
-
- usbi_mutex_static_lock(&linux_hotplug_lock);
-
-#if defined(USE_UDEV)
- ret = linux_udev_scan_devices(ctx);
-#else
- ret = linux_default_scan_devices(ctx);
-#endif
-
- usbi_mutex_static_unlock(&linux_hotplug_lock);
-
- return ret;
-}
-
-static void op_hotplug_poll(void)
-{
-#if defined(USE_UDEV)
- linux_udev_hotplug_poll();
-#else
- linux_netlink_hotplug_poll();
-#endif
+ return 0;
}
static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
@@ -971,7 +885,8 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
return r;
}
-static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir)
+static int linux_get_parent_info(struct discovered_devs **_discdevs,
+ struct libusb_device *dev, const char *sysfs_dir)
{
struct libusb_context *ctx = DEVICE_CTX(dev);
struct libusb_device *it;
@@ -1021,7 +936,7 @@ retry:
if (!dev->parent_dev && add_parent) {
usbi_dbg("parent_dev %s not enumerated yet, enumerating now",
parent_sysfs_dir);
- sysfs_scan_device(ctx, parent_sysfs_dir);
+ sysfs_scan_device(ctx, _discdevs, parent_sysfs_dir);
add_parent = 0;
goto retry;
}
@@ -1035,11 +950,13 @@ retry:
}
int linux_enumerate_device(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs,
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir)
{
+ struct discovered_devs *discdevs;
unsigned long session_id;
struct libusb_device *dev;
- int r = 0;
+ int i, r = 0;
/* FIXME: session ID is not guaranteed unique as addresses can wrap and
* will be reused. instead we should add a simple sysfs attribute with
@@ -1052,72 +969,51 @@ int linux_enumerate_device(struct libusb_context *ctx,
if (dev) {
/* device already exists in the context */
usbi_dbg("session_id %ld already exists", session_id);
- libusb_unref_device(dev);
- return LIBUSB_SUCCESS;
+ /* check if already in discovered device list */
+ for (i = 0; i < (*_discdevs)->len; i++) {
+ if ((*_discdevs)->devices[i] == dev)
+ goto out;
+ }
}
+ else {
+ usbi_dbg("allocating new device for %d/%d (session %ld)",
+ busnum, devaddr, session_id);
+ dev = usbi_alloc_device(ctx, session_id);
+ if (!dev)
+ return LIBUSB_ERROR_NO_MEM;
- usbi_dbg("allocating new device for %d/%d (session %ld)",
- busnum, devaddr, session_id);
- dev = usbi_alloc_device(ctx, session_id);
- if (!dev)
- return LIBUSB_ERROR_NO_MEM;
+ r = initialize_device(dev, busnum, devaddr, sysfs_dir);
+ if (r < 0)
+ goto out;
+ r = usbi_sanitize_device(dev);
+ if (r < 0)
+ goto out;
- r = initialize_device(dev, busnum, devaddr, sysfs_dir);
- if (r < 0)
- goto out;
- r = usbi_sanitize_device(dev);
- if (r < 0)
- goto out;
+ r = linux_get_parent_info(_discdevs, dev, sysfs_dir);
+ if (r < 0)
+ goto out;
+ }
- r = linux_get_parent_info(dev, sysfs_dir);
- if (r < 0)
- goto out;
-out:
- if (r < 0)
- libusb_unref_device(dev);
+ discdevs = discovered_devs_append(*_discdevs, dev);
+ if (!discdevs)
+ r = LIBUSB_ERROR_NO_MEM;
else
- usbi_connect_device(dev);
+ *_discdevs = discdevs;
- return r;
-}
-
-void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name)
-{
- struct libusb_context *ctx;
-
- usbi_mutex_static_lock(&active_contexts_lock);
- list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
- linux_enumerate_device(ctx, busnum, devaddr, sys_name);
- }
- usbi_mutex_static_unlock(&active_contexts_lock);
-}
+out:
+ libusb_unref_device(dev);
-void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
-{
- struct libusb_context *ctx;
- struct libusb_device *dev;
- unsigned long session_id = busnum << 8 | devaddr;
-
- usbi_mutex_static_lock(&active_contexts_lock);
- list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
- dev = usbi_get_device_by_session_id (ctx, session_id);
- if (NULL != dev) {
- usbi_disconnect_device (dev);
- libusb_unref_device(dev);
- } else {
- usbi_dbg("device not found for session %x", session_id);
- }
- }
- usbi_mutex_static_unlock(&active_contexts_lock);
+ return r;
}
-#if !defined(USE_UDEV)
/* open a bus directory and adds all discovered devices to the context */
-static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
+static int usbfs_scan_busdir(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs, uint8_t busnum)
{
DIR *dir;
char dirpath[PATH_MAX];
struct dirent *entry;
+ struct discovered_devs *discdevs = *_discdevs;
int r = LIBUSB_ERROR_IO;
snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum);
@@ -1142,7 +1038,7 @@ static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
continue;
}
- if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) {
+ if (linux_enumerate_device(ctx, &discdevs, busnum, (uint8_t) devaddr, NULL)) {
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
continue;
}
@@ -1150,14 +1046,18 @@ static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
r = 0;
}
+ if (!r)
+ *_discdevs = discdevs;
closedir(dir);
return r;
}
-static int usbfs_get_device_list(struct libusb_context *ctx)
+static int usbfs_get_device_list(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs)
{
struct dirent *entry;
DIR *buses = opendir(usbfs_path);
+ struct discovered_devs *discdevs = *_discdevs;
int r = 0;
if (!buses) {
@@ -1166,6 +1066,7 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
}
while ((entry = readdir(buses))) {
+ struct discovered_devs *discdevs_new = discdevs;
int busnum;
if (entry->d_name[0] == '.')
@@ -1176,7 +1077,7 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
if (!_is_usbdev_entry(entry, &busnum, &devaddr))
continue;
- r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL);
+ r = linux_enumerate_device(ctx, &discdevs_new, busnum, (uint8_t) devaddr, NULL);
if (r < 0) {
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
continue;
@@ -1188,19 +1089,22 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
continue;
}
- r = usbfs_scan_busdir(ctx, busnum);
+ r = usbfs_scan_busdir(ctx, &discdevs_new, busnum);
if (r < 0)
- break;
+ goto out;
}
+ discdevs = discdevs_new;
}
+out:
closedir(buses);
+ *_discdevs = discdevs;
return r;
}
-#endif
-static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
+static int sysfs_scan_device(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs, const char *devname)
{
uint8_t busnum, devaddr;
int ret;
@@ -1210,13 +1114,14 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
return ret;
}
- return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff,
+ return linux_enumerate_device(ctx, _discdevs, busnum & 0xff, devaddr & 0xff,
devname);
}
-#if !defined(USE_UDEV)
-static int sysfs_get_device_list(struct libusb_context *ctx)
+static int sysfs_get_device_list(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs)
{
+ struct discovered_devs *discdevs = *_discdevs;
DIR *devices = opendir(SYSFS_DEVICE_PATH);
struct dirent *entry;
int r = LIBUSB_ERROR_IO;
@@ -1227,23 +1132,29 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
}
while ((entry = readdir(devices))) {
+ struct discovered_devs *discdevs_new = discdevs;
+
if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3))
|| strchr(entry->d_name, ':'))
continue;
- if (sysfs_scan_device(ctx, entry->d_name)) {
+ if (sysfs_scan_device(ctx, &discdevs_new, entry->d_name)) {
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
continue;
}
r = 0;
+ discdevs = discdevs_new;
}
+ if (!r)
+ *_discdevs = discdevs;
closedir(devices);
return r;
}
-static int linux_default_scan_devices (struct libusb_context *ctx)
+static int op_get_device_list(struct libusb_context *ctx,
+ struct discovered_devs **_discdevs)
{
/* we can retrieve device list and descriptors from sysfs or usbfs.
* sysfs is preferable, because if we use usbfs we end up resuming
@@ -1256,11 +1167,10 @@ static int linux_default_scan_devices (struct libusb_context *ctx)
* adequacy of sysfs and sets sysfs_can_relate_devices.
*/
if (sysfs_can_relate_devices != 0)
- return sysfs_get_device_list(ctx);
+ return sysfs_get_device_list(ctx, _discdevs);
else
- return usbfs_get_device_list(ctx);
+ return usbfs_get_device_list(ctx, _discdevs);
}
-#endif
static int op_open(struct libusb_device_handle *handle)
{
@@ -1268,20 +1178,8 @@ 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 == 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);
- }
+ if (hpriv->fd < 0)
return hpriv->fd;
- }
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
if (r < 0) {
@@ -2515,13 +2413,6 @@ 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;
}
@@ -2564,9 +2455,9 @@ const struct usbi_os_backend linux_usbfs_backend = {
.name = "Linux usbfs",
.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
.init = op_init,
- .exit = op_exit,
- .get_device_list = NULL,
- .hotplug_poll = op_hotplug_poll,
+ .exit = NULL,
+ .get_device_list = op_get_device_list,
+ .hotplug_poll = NULL,
.get_device_descriptor = op_get_device_descriptor,
.get_active_config_descriptor = op_get_active_config_descriptor,
.get_config_descriptor = op_get_config_descriptor,
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index 1f5b191..3ee80ff 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -156,26 +156,4 @@ struct usbfs_disconnect_claim {
#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim)
-extern usbi_mutex_static_t linux_hotplug_lock;
-
-#if defined(HAVE_LIBUDEV)
-int linux_udev_start_event_monitor(void);
-int linux_udev_stop_event_monitor(void);
-int linux_udev_scan_devices(struct libusb_context *ctx);
-void linux_udev_hotplug_poll(void);
-#else
-int linux_netlink_start_event_monitor(void);
-int linux_netlink_stop_event_monitor(void);
-void linux_netlink_hotplug_poll(void);
-#endif
-
-void linux_hotplug_enumerate(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,
- const char *sys_name);
-int linux_enumerate_device(struct libusb_context *ctx,
- uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
-
#endif
--
1.8.5.3
------------------------------------------------------------------------------
WatchGuard Dimension instantly turns raw network data into actionable
security intelligence. It gives you real-time visual feedback on key
security issues and trends. Skip the complicated setup - simply import
a virtual appliance and go from zero to informed in seconds.
http://pubads.g.doubleclick.net/gampad/clk?id=123612991&iu=/4140/ostg.clktrk
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel