summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/imx/imx-usb-loader.c99
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);