summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Hanko <james.hanko@tridentmicro.com>2011-10-20 00:32:34 -0700
committerPete Batard <pete@akeo.ie>2012-04-22 13:58:45 +0100
commitb92720842b719300df06a482ab0cd01ddd4e23da (patch)
tree5ee98db0954c73e0251b073eb322b3d565b252e7
parent35c3189a70771dddb70ccf196c7bfd82d556f443 (diff)
downloadlibusb-b92720842b719300df06a482ab0cd01ddd4e23da.tar.gz
Linux: Search for /dev/usbdev<bus>.<device> USB device special files
If neither the (now deprecated) usbfs filesystem nor udev is available then libusbx searches for device nodes also in /dev where they may be created if the kernel was built with the option CONFIG_USB_DEVICE_CLASS. This helps on embedded systems such as Android, and all mdev users.
-rw-r--r--libusb/os/linux_usbfs.c81
-rw-r--r--libusb/version.h2
2 files changed, 71 insertions, 12 deletions
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 23454cb..a6114ca 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -71,6 +71,9 @@
static const char *usbfs_path = NULL;
+/* use usbdev*.* device names in /dev instead of the usbfs bus directories */
+static int usbdev_names = 0;
+
/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically
* allows us to mark URBs as being part of a specific logical transfer when
* we submit them to the kernel. then, on any error except a cancellation, all
@@ -148,8 +151,12 @@ struct linux_transfer_priv {
static void _get_usbfs_path(struct libusb_device *dev, char *path)
{
- snprintf(path, PATH_MAX, "%s/%03d/%03d", usbfs_path, dev->bus_number,
- dev->device_address);
+ if (usbdev_names)
+ snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
+ usbfs_path, dev->bus_number, dev->device_address);
+ else
+ snprintf(path, PATH_MAX, "%s/%03d/%03d",
+ usbfs_path, dev->bus_number, dev->device_address);
}
static struct linux_device_priv *_device_priv(struct libusb_device *dev)
@@ -163,6 +170,23 @@ static struct linux_device_handle_priv *_device_handle_priv(
return (struct linux_device_handle_priv *) handle->os_priv;
}
+/* check dirent for a /dev/usbdev%d.%d name
+ * optionally return bus/device on success */
+static int _is_usbdev_entry(struct dirent *entry, int *bus_p, int *dev_p)
+{
+ int busnum, devnum;
+
+ if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2)
+ return 0;
+
+ usbi_dbg("found: %s", entry->d_name);
+ if (bus_p != NULL)
+ *bus_p = busnum;
+ if (dev_p != NULL)
+ *dev_p = devnum;
+ return 1;
+}
+
static int check_usb_vfs(const char *dirname)
{
DIR *dir;
@@ -199,7 +223,29 @@ static const char *find_usbfs_path(void)
ret = path;
}
- usbi_dbg("found usbfs at %s", ret);
+ /* look for /dev/usbdev*.* if the normal places fail */
+ if (ret == NULL) {
+ struct dirent *entry;
+ DIR *dir;
+
+ path = "/dev";
+ dir = opendir(path);
+ if (dir != NULL) {
+ while ((entry = readdir(dir)) != NULL) {
+ if (_is_usbdev_entry(entry, NULL, NULL)) {
+ /* found one; that's enough */
+ ret = path;
+ usbdev_names = 1;
+ break;
+ }
+ }
+ closedir(dir);
+ }
+ }
+
+ if (ret != NULL)
+ usbi_dbg("found usbfs at %s", ret);
+
return ret;
}
@@ -1055,15 +1101,28 @@ static int usbfs_get_device_list(struct libusb_context *ctx,
if (entry->d_name[0] == '.')
continue;
- busnum = atoi(entry->d_name);
- if (busnum == 0) {
- usbi_dbg("unknown dir entry %s", entry->d_name);
- continue;
- }
+ if (usbdev_names) {
+ int devaddr;
+ if (!_is_usbdev_entry(entry, &busnum, &devaddr))
+ continue;
- r = usbfs_scan_busdir(ctx, &discdevs_new, busnum);
- if (r < 0)
- goto out;
+ r = 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;
+ }
+ } else {
+ busnum = atoi(entry->d_name);
+ if (busnum == 0) {
+ usbi_dbg("unknown dir entry %s", entry->d_name);
+ continue;
+ }
+
+ r = usbfs_scan_busdir(ctx, &discdevs_new, busnum);
+ if (r < 0)
+ goto out;
+ }
discdevs = discdevs_new;
}
diff --git a/libusb/version.h b/libusb/version.h
index 2ebe01f..583e128 100644
--- a/libusb/version.h
+++ b/libusb/version.h
@@ -9,7 +9,7 @@
#define LIBUSB_MICRO 10
#endif
#ifndef LIBUSB_NANO
-#define LIBUSB_NANO 10483
+#define LIBUSB_NANO 10484
#endif
/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
#ifndef LIBUSB_RC