blob: 675b06cb814c51aec3d3b0a95e24330b9c6b9504 [file] [log] [blame]
From 5f0cc26af63c811143975061ada9af4093a3f95e Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <dtor@chromium.org>
Date: Tue, 4 Jun 2019 12:51:45 -0700
Subject: [PATCH 06/11] CHROMIUM: linux_usbfs: tease apart
linux_device_address()
The function has become a kitchen sink and hard to follow, let's split
it apart so we can call individual parts, as needed.
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
---
libusb/os/linux_udev.c | 2 +-
libusb/os/linux_usbfs.c | 121 +++++++++++++++++++++++++---------------
libusb/os/linux_usbfs.h | 2 +-
3 files changed, 78 insertions(+), 47 deletions(-)
diff --git a/libusb/os/linux_udev.c b/libusb/os/linux_udev.c
index bea03e3..c97806b 100644
--- a/libusb/os/linux_udev.c
+++ b/libusb/os/linux_udev.c
@@ -232,7 +232,7 @@ static int udev_device_info(struct libusb_context *ctx, int detached,
}
return linux_get_device_address(ctx, detached, busnum, devaddr,
- dev_node, *sys_name, -1);
+ dev_node, *sys_name);
}
static void udev_hotplug_event(struct udev_device* udev_dev)
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 2e7add4..b55b86d 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -686,40 +686,13 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config)
return 0;
}
-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 fd)
+static int device_address_from_sysfs(struct libusb_context *ctx,
+ const char *sys_name, uint8_t *busnum, uint8_t *devaddr)
{
- char proc_path[PATH_MAX], fd_path[PATH_MAX];
int sysfs_attr;
- ssize_t r;
-
- 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 */
- if (!sysfs_can_relate_devices || detached || NULL == sys_name) {
- if (NULL == dev_node && fd >= 0) {
- /* try to retrieve the device node from fd */
- snprintf(proc_path, PATH_MAX, "/proc/self/fd/%d", fd);
- r = readlink(proc_path, fd_path, PATH_MAX);
- if (r > 0)
- dev_node = fd_path;
- }
- if (NULL == dev_node) {
- return LIBUSB_ERROR_OTHER;
- }
- /* will this work with all supported kernel versions? */
- if (!strncmp(dev_node, "/dev/bus/usb", 12)) {
- sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
- } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
- sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
- } else {
- return LIBUSB_ERROR_OTHER;
- }
-
- return LIBUSB_SUCCESS;
- }
+ if (!sysfs_can_relate_devices || NULL == sys_name)
+ return LIBUSB_ERROR_OTHER;
usbi_dbg("scan %s", sys_name);
@@ -743,6 +716,74 @@ int linux_get_device_address (struct libusb_context *ctx, int detached,
return LIBUSB_SUCCESS;
}
+static int device_address_from_path(struct libusb_context *ctx,
+ const char *path, uint8_t *busnum, uint8_t *devaddr)
+{
+ int ret = 0;
+
+ if (NULL == path)
+ return LIBUSB_ERROR_OTHER;
+
+ /* will this work with all supported kernel versions? */
+ if (!strncmp(path, "/dev/bus/usb", 12)) {
+ ret = sscanf(path, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
+ } else if (!strncmp(path, "/proc/bus/usb", 13)) {
+ ret = sscanf(path, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
+ }
+
+ return ret == 2 ? LIBUSB_SUCCESS : LIBUSB_ERROR_OTHER;
+}
+
+static int device_address_from_fd(struct libusb_context *ctx,
+ int fd, uint8_t *busnum, uint8_t *devaddr)
+{
+ struct usbfs_connectinfo ci;
+ char proc_path[PATH_MAX], fd_path[PATH_MAX];
+ ssize_t r;
+ int ret;
+
+ /* Try to see if we can deduce the address from file our
+ * file descriptor points to.
+ */
+ snprintf(proc_path, PATH_MAX, "/proc/self/fd/%d", fd);
+ r = readlink(proc_path, fd_path, PATH_MAX);
+ if (r > 0) {
+ ret = device_address_from_path(ctx, fd_path, busnum, devaddr);
+ if (ret == LIBUSB_SUCCESS)
+ return ret;
+ }
+
+ ret = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
+ if (ret < 0) {
+ usbi_err(ctx, "connectinfo failed (%d)", errno);
+ return LIBUSB_ERROR_IO;
+ }
+
+ /* IOCTL_USBFS_CONNECTINFO does not return the bus number.
+ * We choose 0 here as linux starts numbering buses from 1. */
+ *busnum = 0;
+ *devaddr = ci.devnum;
+
+ return LIBUSB_SUCCESS;
+}
+
+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)
+{
+ 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 */
+ if (!sysfs_can_relate_devices || detached) {
+ if (dev_node)
+ return device_address_from_path(ctx, dev_node,
+ busnum, devaddr);
+ return LIBUSB_ERROR_OTHER;
+ }
+
+ return device_address_from_sysfs(ctx, sys_name, busnum, devaddr);
+}
+
/* Return offset of the next descriptor with the given type */
static int seek_to_next_descriptor(struct libusb_context *ctx,
uint8_t descriptor_type, unsigned char *buffer, int size)
@@ -1314,7 +1355,7 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
uint8_t busnum, devaddr;
int ret;
- ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname, -1);
+ ret = device_address_from_sysfs(ctx, devname, &busnum, &devaddr);
if (LIBUSB_SUCCESS != ret) {
return ret;
}
@@ -1408,22 +1449,12 @@ static int op_wrap_sys_device(struct libusb_context *ctx,
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
int fd = (int)sys_dev;
uint8_t busnum, devaddr;
- struct usbfs_connectinfo ci;
struct libusb_device *dev;
int r;
- r = linux_get_device_address(ctx, 1, &busnum, &devaddr, NULL, NULL, fd);
- if (r < 0) {
- r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
- if (r < 0) {
- usbi_err(ctx, "connectinfo failed (%d)", errno);
- return LIBUSB_ERROR_IO;
- }
- /* There is no ioctl to get the bus number. We choose 0 here
- * as linux starts numbering buses from 1. */
- busnum = 0;
- devaddr = ci.devnum;
- }
+ r = device_address_from_fd(ctx, fd, &busnum, &devaddr);
+ if (r != LIBUSB_SUCCESS)
+ return r;
/* Session id is unused as we do not add the device to the list of
* connected devices. */
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index a57eb41..2449632 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -187,7 +187,7 @@ void linux_device_disconnected(uint8_t busnum, uint8_t devaddr);
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 fd);
+ const char *sys_name);
int linux_enumerate_device(struct libusb_context *ctx,
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
--
2.22.0.rc2.383.gf4fbbf30c2-goog