See https://github.com/linux-sunxi/sunxi-tools/issues/37
The patch was originally inspired by https://github.com/NextThingCo/sunxi-tools/commit/16386a7 and https://github.com/NextThingCo/sunxi-tools/commit/47bafaf It introduces a "--dev" (-d) option to specify the desired FEL device. This is useful if multiple target devices are connected to the same host. Signed-off-by: Bernhard Nortmann <bernhard.nortm...@web.de> --- fel.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 26 deletions(-) diff --git a/fel.c b/fel.c index 59f0f72..dc27ecc 100644 --- a/fel.c +++ b/fel.c @@ -37,6 +37,9 @@ #include "endian_compat.h" #include "progress.h" +static const uint16_t AW_USB_VENDOR_ID = 0x1F3A; +static const uint16_t AW_USB_PRODUCT_ID = 0XEFE8; + struct aw_usb_request { char signature[8]; uint32_t length; @@ -1270,20 +1273,92 @@ static unsigned int file_upload(libusb_device_handle *handle, size_t count, return i; // return number of files that were processed } +/* open libusb handle to desired FEL device */ +static libusb_device_handle *open_fel_device(int busnum, int devnum, + uint16_t vendor_id, uint16_t product_id) +{ + libusb_device_handle *result = NULL; + + if (busnum < 0 || devnum < 0) { + /* With the default values (busnum -1, devnum -1) we don't care + * for a specific USB device; so let libusb open the first + * device that matches VID/PID. + */ + result = libusb_open_device_with_vid_pid(NULL, vendor_id, product_id); + if (!result) { + switch (errno) { + case EACCES: + fprintf(stderr, "ERROR: You don't have permission to access Allwinner USB FEL device\n"); + break; + default: + fprintf(stderr, "ERROR: Allwinner USB FEL device not found!\n"); + break; + } + exit(1); + } + return result; + } + + /* look for specific bus and device number */ + pr_info("Selecting USB Bus %03d Device %03d\n", busnum, devnum); + bool found = false; + ssize_t rc, i; + libusb_device **list; + + rc = libusb_get_device_list(NULL, &list); + if (rc < 0) { + fprintf(stderr, "libusb_get_device_list() ERROR: %s\n", + libusb_strerror(rc)); + exit(1); + } + for (i = 0; i < rc; i++) { + if (libusb_get_bus_number(list[i]) == busnum + && libusb_get_device_address(list[i]) == devnum) { + found = true; /* bus:devnum matched */ + struct libusb_device_descriptor desc; + libusb_get_device_descriptor(list[i], &desc); + if (desc.idVendor != vendor_id + || desc.idProduct != product_id) { + fprintf(stderr, "ERROR: Bus %03d Device %03d not a FEL device " + "(expected %04x:%04x, got %04x:%04x)\n", busnum, devnum, + vendor_id, product_id, desc.idVendor, desc.idProduct); + exit(1); + } + /* open handle to this specific device (incrementing its refcount) */ + rc = libusb_open(list[i], &result); + if (rc != 0) { + fprintf(stderr, "libusb_open() ERROR: %s\n", + libusb_strerror(rc)); + exit(1); + } + break; + } + } + libusb_free_device_list(list, true); + + if (!found) { + fprintf(stderr, "ERROR: Bus %03d Device %03d not found in libusb device list\n", + busnum, devnum); + exit(1); + } + return result; +} + int main(int argc, char **argv) { bool uboot_autostart = false; /* flag for "uboot" command = U-Boot autostart */ bool pflag_active = false; /* -p switch, causing "write" to output progress */ - int rc; - libusb_device_handle *handle = NULL; + libusb_device_handle *handle; + int busnum = -1, devnum = -1; int iface_detached = -1; - rc = libusb_init(NULL); + int rc = libusb_init(NULL); assert(rc == 0); if (argc <= 1) { printf("Usage: %s [options] command arguments... [command...]\n" " -v, --verbose Verbose logging\n" " -p, --progress \"write\" transfers show a progress bar\n" + " -d, --dev bus:devnum Use specific USB bus and device number\n" "\n" " spl file Load and execute U-Boot SPL\n" " If file additionally contains a main U-Boot binary\n" @@ -1316,18 +1391,32 @@ int main(int argc, char **argv) ); } - handle = libusb_open_device_with_vid_pid(NULL, 0x1f3a, 0xefe8); - if (!handle) { - switch (errno) { - case EACCES: - fprintf(stderr, "ERROR: You don't have permission to access Allwinner USB FEL device\n"); - break; - default: - fprintf(stderr, "ERROR: Allwinner USB FEL device not found!\n"); - break; - } - exit(1); + /* process all "prefix"-type arguments first */ + while (argc > 1) { + if (strcmp(argv[1], "--verbose") == 0 || strcmp(argv[1], "-v") == 0) + verbose = true; + else if (strcmp(argv[1], "--progress") == 0 || strcmp(argv[1], "-p") == 0) + pflag_active = true; + else if (strncmp(argv[1], "--dev", 5) == 0 || strncmp(argv[1], "-d", 2) == 0) { + char *dev_arg = argv[1]; + dev_arg += strspn(dev_arg, "-dev="); /* skip option chars, ignore '=' */ + if (*dev_arg == 0 && argc > 2) { /* at end of argument, use the next one instead */ + dev_arg = argv[2]; + argc -= 1; + argv += 1; + } + if (sscanf(dev_arg, "%d:%d", &busnum, &devnum) != 2) { + fprintf(stderr, "ERROR: Expected 'bus:devnum', got '%s'.\n", dev_arg); + exit(1); + } + } else + break; /* no valid (prefix) option detected, exit loop */ + argc -= 1; + argv += 1; } + + handle = open_fel_device(busnum, devnum, AW_USB_VENDOR_ID, AW_USB_PRODUCT_ID); + assert(handle != NULL); rc = libusb_claim_interface(handle, 0); #if defined(__linux__) if (rc != LIBUSB_SUCCESS) { @@ -1343,18 +1432,6 @@ int main(int argc, char **argv) exit(1); } - /* process all "prefix"-type arguments first */ - while (argc > 1) { - if (strcmp(argv[1], "--verbose") == 0 || strcmp(argv[1], "-v") == 0) - verbose = true; - else if (strcmp(argv[1], "--progress") == 0 || strcmp(argv[1], "-p") == 0) - pflag_active = true; - else - break; /* no valid (prefix) option detected, exit loop */ - argc -= 1; - argv += 1; - } - while (argc > 1 ) { int skip = 1; -- 2.4.10 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.