diff options
Diffstat (limited to 'fastboot')
-rw-r--r-- | fastboot/engine.c | 7 | ||||
-rw-r--r-- | fastboot/fastboot.c | 33 | ||||
-rw-r--r-- | fastboot/fastboot.h | 1 | ||||
-rw-r--r-- | fastboot/usb.h | 1 | ||||
-rw-r--r-- | fastboot/usb_linux.c | 41 | ||||
-rw-r--r-- | fastboot/usb_osx.c | 8 | ||||
-rw-r--r-- | fastboot/usb_windows.c | 2 |
7 files changed, 86 insertions, 7 deletions
diff --git a/fastboot/engine.c b/fastboot/engine.c index 93be3de..8d7b68a 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -565,6 +565,8 @@ int fb_execute_queue(usb_handle *usb) int status = 0; a = action_list; + if (!a) + return status; resp[FB_RESPONSE_SZ] = 0; double start = -1; @@ -605,3 +607,8 @@ int fb_execute_queue(usb_handle *usb) fprintf(stderr,"finished. total time: %.3fs\n", (now() - start)); return status; } + +int fb_queue_is_empty(void) +{ + return (action_list == NULL); +} diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index b6eab8c..898d452 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -70,6 +70,7 @@ static const char *product = 0; static const char *cmdline = 0; static int wipe_data = 0; static unsigned short vendor_id = 0; +static int long_listing = 0; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; @@ -187,6 +188,11 @@ oops: int match_fastboot(usb_ifc_info *info) { + return match_fastboot_with_serial(info, serial); +} + +int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) +{ if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x8087) && // Intel @@ -204,15 +210,16 @@ int match_fastboot(usb_ifc_info *info) if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_protocol != 0x03) return -1; - // require matching serial number if a serial number is specified + // require matching serial number or device path if requested // at the command line with the -s option. - if (serial && strcmp(serial, info->serial_number) != 0) return -1; + if (local_serial && (strcmp(local_serial, info->serial_number) != 0 && + strcmp(local_serial, info->device_path) != 0)) return -1; return 0; } int list_devices_callback(usb_ifc_info *info) { - if (match_fastboot(info) == 0) { + if (match_fastboot_with_serial(info, NULL) == 0) { char* serial = info->serial_number; if (!info->writable) { serial = "no permissions"; // like "adb devices" @@ -221,7 +228,13 @@ int list_devices_callback(usb_ifc_info *info) serial = "????????????"; } // output compatible with "adb devices" - printf("%s\tfastboot\n", serial); + if (!long_listing) { + printf("%s\tfastboot\n", serial); + } else if (!info->device_path) { + printf("%-22s fastboot\n", serial); + } else { + printf("%-22s fastboot %s\n", serial, info->device_path); + } } return -1; @@ -275,7 +288,9 @@ void usage(void) "\n" "options:\n" " -w erase userdata and cache\n" - " -s <serial number> specify device serial number\n" + " -s <specific device> specify device serial number\n" + " or path to device port\n" + " -l with \"devices\", lists device paths\n" " -p <product> specify product name\n" " -c <cmdline> override kernel commandline\n" " -i <vendor id> specify a custom USB vendor id\n" @@ -767,7 +782,7 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { - c = getopt_long(argc, argv, "wb:n:s:S:p:c:i:m:h", &longopts, NULL); + c = getopt_long(argc, argv, "wb:n:s:S:lp:c:i:m:h", &longopts, NULL); if (c < 0) { break; } @@ -792,6 +807,9 @@ int main(int argc, char **argv) die("invalid sparse limit"); } break; + case 'l': + long_listing = 1; + break; case 'p': product = optarg; break; @@ -943,6 +961,9 @@ int main(int argc, char **argv) fb_queue_command("reboot-bootloader", "rebooting into bootloader"); } + if (fb_queue_is_empty()) + return 0; + status = fb_execute_queue(usb); return (status) ? 1 : 0; } diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index 9177932..b4cf195 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -58,6 +58,7 @@ void fb_queue_command(const char *cmd, const char *msg); void fb_queue_download(const char *name, void *data, unsigned size); void fb_queue_notice(const char *notice); int fb_execute_queue(usb_handle *usb); +int fb_queue_is_empty(void); /* util stuff */ void die(const char *fmt, ...); diff --git a/fastboot/usb.h b/fastboot/usb.h index df9efde..d504ee2 100644 --- a/fastboot/usb.h +++ b/fastboot/usb.h @@ -53,6 +53,7 @@ struct usb_ifc_info unsigned char writable; char serial_number[256]; + char device_path[256]; }; typedef int (*ifc_match_func)(usb_ifc_info *ifc); 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; diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c index cbce9bd..1548ba8 100644 --- a/fastboot/usb_osx.c +++ b/fastboot/usb_osx.c @@ -264,6 +264,7 @@ static int try_device(io_service_t device, usb_handle *handle) { SInt32 score; HRESULT result; UInt8 serialIndex; + UInt32 locationId; // Create an intermediate plugin. kr = IOCreatePlugInInterfaceForService(device, @@ -322,6 +323,13 @@ static int try_device(io_service_t device, usb_handle *handle) { goto error; } + kr = (*dev)->GetLocationID(dev, &locationId); + if (kr != 0) { + ERR("GetLocationId"); + goto error; + } + snprintf(handle->info.device_path, sizeof(handle->info.device_path), "usb:%lX", locationId); + kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); if (serialIndex > 0) { diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c index 99027cc..7aa36b2 100644 --- a/fastboot/usb_windows.c +++ b/fastboot/usb_windows.c @@ -311,6 +311,8 @@ int recognized_device(usb_handle* handle, ifc_match_func callback) { info.serial_number[0] = 0; } + info.device_path[0] = 0; + if (callback(&info) == 0) { return 1; } |