diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/imx/imx-usb-loader.c | 99 |
1 files changed, 86 insertions, 13 deletions
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index 4105adeda9..2c8a118923 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -45,6 +45,12 @@ #define FT_DCD 0xee #define FT_LOAD_ONLY 0x00 +/* + * comment from libusb: + * As per the USB 3.0 specs, the current maximum limit for the depth is 7. + */ +#define MAX_USB_PORTS 7 + int verbose; static struct libusb_device_handle *usb_dev_handle; static struct usb_id *usb_id; @@ -197,9 +203,64 @@ static const struct mach_id *imx_device(unsigned short vid, unsigned short pid) return NULL; } -static libusb_device *find_imx_dev(libusb_device **devs, const struct mach_id **pp_id) +static int device_location_equal(libusb_device *device, const char *location) +{ + uint8_t port_path[MAX_USB_PORTS]; + uint8_t dev_bus; + int path_step, path_len; + int result = 0; + char *ptr, *loc; + + /* strtok need non const char */ + loc = strdup(location); + + path_len = libusb_get_port_numbers(device, port_path, MAX_USB_PORTS); + if (path_len == LIBUSB_ERROR_OVERFLOW) { + fprintf(stderr, "cannot determine path to usb device! (more than %i ports in path)\n", + MAX_USB_PORTS); + goto done; + } + + ptr = strtok(loc, "-"); + if (ptr == NULL) { + printf("no '-' in path\n"); + goto done; + } + + dev_bus = libusb_get_bus_number(device); + /* check bus mismatch */ + if (atoi(ptr) != dev_bus) + goto done; + + path_step = 0; + while (path_step < MAX_USB_PORTS) { + ptr = strtok(NULL, "."); + + /* no more tokens in path */ + if (ptr == NULL) + break; + + /* path mismatch at some step */ + if (path_step < path_len && atoi(ptr) != port_path[path_step]) + break; + + path_step++; + }; + + /* walked the full path, all elements match */ + if (path_step == path_len) + result = 1; + +done: + free(loc); + return result; +} + +static libusb_device *find_imx_dev(libusb_device **devs, const struct mach_id **pp_id, + const char *location) { int i = 0; + int err; const struct mach_id *p; for (;;) { @@ -217,10 +278,24 @@ static libusb_device *find_imx_dev(libusb_device **devs, const struct mach_id ** } p = imx_device(desc.idVendor, desc.idProduct); - if (p) { - *pp_id = p; - return dev; + if (!p) + continue; + + err = libusb_open(dev, &usb_dev_handle); + if (err) { + fprintf(stderr, "Could not open device vid=0x%x pid=0x%x err=%d\n", + p->vid, p->pid, err); + continue; } + + if (location && !device_location_equal(dev, location)) { + libusb_close(usb_dev_handle); + usb_dev_handle = NULL; + continue; + } + + *pp_id = p; + return dev; } *pp_id = NULL; @@ -1378,6 +1453,7 @@ static void usage(const char *prgname) fprintf(stderr, "usage: %s [OPTIONS] [FILENAME]\n\n" "-c check correctness of flashed image\n" "-i <cfgfile> Specify custom SoC initialization file\n" + "-p <devpath> Specify device path: <bus>-<port>[.<port>]...\n" "-s skip DCD included in image\n" "-v verbose (give multiple times to increase)\n" "-h this help\n", prgname); @@ -1398,10 +1474,11 @@ int main(int argc, char *argv[]) struct usb_work w = {}; int opt; char *initfile = NULL; + char *devpath = NULL; w.do_dcd_once = 1; - while ((opt = getopt(argc, argv, "cvhi:s")) != -1) { + while ((opt = getopt(argc, argv, "cvhi:p:s")) != -1) { switch (opt) { case 'c': verify = 1; @@ -1414,6 +1491,9 @@ int main(int argc, char *argv[]) case 'i': initfile = optarg; break; + case 'p': + devpath = optarg; + break; case 's': w.do_dcd_once = 0; break; @@ -1441,19 +1521,12 @@ int main(int argc, char *argv[]) goto out; } - dev = find_imx_dev(devs, &mach); + dev = find_imx_dev(devs, &mach, devpath); if (!dev) { fprintf(stderr, "no supported device found\n"); goto out; } - err = libusb_open(dev, &usb_dev_handle); - if (err) { - fprintf(stderr, "Could not open device vid=0x%x pid=0x%x err=%d\n", - mach->vid, mach->pid, err); - goto out; - } - libusb_free_device_list(devs, 1); libusb_get_configuration(usb_dev_handle, &config); |