summaryrefslogtreecommitdiffstats
path: root/fastboot/usb_linux.c
diff options
context:
space:
mode:
authorScott Anderson <saa@android.com>2012-05-01 18:34:22 -0700
committerScott Anderson <saa@android.com>2012-05-01 18:34:22 -0700
commita61bcad58ba1f7359183a333ee58303ed67e4a2f (patch)
treec30d316882119d9acbc9fa9adaf3c0fce11d219b /fastboot/usb_linux.c
parent048f24600f389bb756cf9c6ea93774f31fd588ad (diff)
parent13081c6915220db03886b177f1a8e0b2c63467c9 (diff)
downloadsystem_core-a61bcad58ba1f7359183a333ee58303ed67e4a2f.zip
system_core-a61bcad58ba1f7359183a333ee58303ed67e4a2f.tar.gz
system_core-a61bcad58ba1f7359183a333ee58303ed67e4a2f.tar.bz2
resolved conflicts for merge of 13081c69 to master
Change-Id: I631e466fc53e9b0f4a39f24f959b4ae9b626bdda
Diffstat (limited to 'fastboot/usb_linux.c')
-rw-r--r--fastboot/usb_linux.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 83c6de9..b7a9ca3 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
@@ -107,6 +108,9 @@ static int filter_usb_device(int fd, char *ptr, int len, int writable,
int in, out;
unsigned i;
unsigned e;
+
+ struct stat st;
+ int result;
if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
return -1;
@@ -134,7 +138,6 @@ static int filter_usb_device(int fd, char *ptr, int len, int writable,
// Keep it short enough because some bootloaders are borked if the URB len is > 255
// 128 is too big by 1.
__u16 buffer[127];
- int result;
memset(buffer, 0, sizeof(buffer));
@@ -158,6 +161,42 @@ static int filter_usb_device(int fd, char *ptr, int len, int writable,
}
}
+ /* We need to get a path that represents a particular port on a particular
+ * hub. We are passed an fd that was obtained by opening an entry under
+ * /dev/bus/usb. Unfortunately, the names of those entries change each
+ * time devices are plugged and unplugged. So how to get a repeatable
+ * path? udevadm provided the inspiration. We can get the major and
+ * minor of the device file, read the symlink that can be found here:
+ * /sys/dev/char/<major>:<minor>
+ * and then use the last element of that path. As a concrete example, I
+ * have an Android device at /dev/bus/usb/001/027 so working with bash:
+ * $ ls -l /dev/bus/usb/001/027
+ * crw-rw-r-- 1 root plugdev 189, 26 Apr 9 11:03 /dev/bus/usb/001/027
+ * $ ls -l /sys/dev/char/189:26
+ * lrwxrwxrwx 1 root root 0 Apr 9 11:03 /sys/dev/char/189:26 ->
+ * ../../devices/pci0000:00/0000:00:1a.7/usb1/1-4/1-4.2/1-4.2.3
+ * So our device_path would be 1-4.2.3 which says my device is connected
+ * to port 3 of a hub on port 2 of a hub on port 4 of bus 1 (per
+ * http://www.linux-usb.org/FAQ.html).
+ */
+ info.device_path[0] = '\0';
+ result = fstat(fd, &st);
+ if (!result && S_ISCHR(st.st_mode)) {
+ char cdev[128];
+ char link[256];
+ char *slash;
+ ssize_t link_len;
+ snprintf(cdev, sizeof(cdev), "/sys/dev/char/%d:%d",
+ major(st.st_rdev), minor(st.st_rdev));
+ link_len = readlink(cdev, link, sizeof(link) - 1);
+ if (link_len > 0) {
+ link[link_len] = '\0';
+ slash = strrchr(link, '/');
+ if (slash)
+ snprintf(info.device_path, sizeof(info.device_path), "usb:%s", slash+1);
+ }
+ }
+
for(i = 0; i < cfg->bNumInterfaces; i++) {
if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE))
return -1;