123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- migrate to libusb-1 by me (Mike Frysinger)
- workaround kernel/libusb transfer sizes by Julius Werner
- --- a/Makefile
- +++ b/Makefile
- @@ -10,8 +10,8 @@
- CFLAGS ?= -O2 -g
- CFLAGS += -Wall
- PKG_CONFIG ?= pkg-config
- -CPPFLAGS += $(shell $(PKG_CONFIG) --cflags libusb)
- -LDLIBS = $(shell $(PKG_CONFIG) --libs libusb)
- +CPPFLAGS += $(shell $(PKG_CONFIG) --cflags libusb-1.0)
- +LDLIBS = $(shell $(PKG_CONFIG) --libs libusb-1.0)
-
- all: dltool
-
- --- a/dltool.c
- +++ b/dltool.c
- @@ -7,15 +7,25 @@
-
- #include <sys/types.h>
- #include <sys/stat.h>
- +#include <sys/param.h>
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <getopt.h>
- #include <fcntl.h>
- +#include <errno.h>
- +#include <unistd.h>
-
-
- -#include <usb.h>
- +#include <libusb.h>
- +
- +/* The kernel USB layer is restrictive in the max size in a single URB.
- + * When we exceed that, the kernel throws ENOMEM, but the libusb layer
- + * doesn't handle things gracefully. So manually split up into chunks
- + * ourselves so we can avoid that failure case.
- + */
- +#define CHUNKSIZE (1 << 18)
-
- unsigned int debug = 0;
- unsigned long dl_addr = 0x30000000L;
- @@ -23,12 +33,22 @@ unsigned long dl_size = 0L;
- unsigned char *dl_data = NULL;
-
- char *dl_file = "download.dat";
- -char *dl_udev = NULL;
- -char *dl_ubus = NULL;
- +libusb_context *ctx = NULL;
- +libusb_device_handle *devh = NULL;
-
- int ep_out = 0;
-
- #define DBG(x) if (debug) { printf x; }
- +#define err(fmt, args...) \
- + do { \
- + if (devh) \
- + libusb_close(devh); \
- + if (ctx) \
- + libusb_exit(ctx); \
- + fprintf(stderr, "dltool: " fmt "\n", ## args); \
- + exit(1); \
- + } while (0)
- +#define errp(fmt, args...) err(fmt ": %s", ## args, strerror(errno))
-
- void write_u32(unsigned char *dp, unsigned long val)
- {
- @@ -108,25 +128,30 @@ void calc_cksum(unsigned char *data, ssize_t len)
- cp[1] = cksum >> 8;
- }
-
- -int verify_device(struct usb_device *dev)
- +int verify_device(libusb_device *dev)
- {
- + struct libusb_device_descriptor desc;
- +
- + if (libusb_get_device_descriptor(dev, &desc))
- + return 0;
- +
- DBG(("dev %p: configurations %d\n",
- - dev, dev->descriptor.bNumConfigurations));
- + dev, desc.bNumConfigurations));
-
- - if (dev->descriptor.bNumConfigurations != 1)
- + if (desc.bNumConfigurations != 1)
- return 0;
-
- - DBG(("\t=> bLength %d\n", dev->descriptor.bLength));
- - DBG(("\t=> bType %d\n", dev->descriptor.bDescriptorType));
- - DBG(("\t=> bcdUSB %x\n", dev->descriptor.bcdUSB));
- - DBG(("\t=> idVendor %x\n", dev->descriptor.idVendor));
- - DBG(("\t=> idProduct %x\n", dev->descriptor.idProduct));
- + DBG(("\t=> bLength %d\n", desc.bLength));
- + DBG(("\t=> bType %d\n", desc.bDescriptorType));
- + DBG(("\t=> bcdUSB %x\n", desc.bcdUSB));
- + DBG(("\t=> idVendor %x\n", desc.idVendor));
- + DBG(("\t=> idProduct %x\n", desc.idProduct));
-
- - if (dev->descriptor.idVendor == 0x5345 && dev->descriptor.idProduct == 0x1234) {
- + if (desc.idVendor == 0x5345 && desc.idProduct == 0x1234) {
- ep_out = 3;
- return 1;
- }
- - else if(dev->descriptor.idVendor == 0x4e8 && dev->descriptor.idProduct == 0x1234){
- + else if(desc.idVendor == 0x4e8 && desc.idProduct == 0x1234){
- printf("S3C64XX Detected!\n");
- ep_out = 2;
- return 1;
- @@ -173,6 +198,12 @@ struct option long_opts[] = {
- .val = 'x',
- },
- {
- + .name = "help",
- + .has_arg = 0,
- + .flag = NULL,
- + .val = 'h',
- + },
- + {
- .name = NULL
- }
- };
- @@ -181,12 +212,14 @@ int flg_show = 0;
-
- int main(int argc, char **argv)
- {
- - struct usb_bus *bus, *busp;
- - struct usb_device *result = NULL;
- - struct usb_device *found = NULL;
- + ssize_t num_devs, i;
- + libusb_device **list;
- + libusb_device *found;
- + int dl_ubus = -1;
- + int dl_udev = -1;
- + uint8_t bus_num, dev_num;
- unsigned long fsize;
- - usb_dev_handle *devh;
- - int ret;
- + int ret, transferred;
-
- printf("SMDK42XX,S3C64XX USB Download Tool\n");
- printf("Version 0.20 (c) 2004,2005,2006"
- @@ -197,7 +230,7 @@ int main(int argc, char **argv)
- int index = 0;
- int c;
-
- - c = getopt_long(argc, argv, "a:b:d:f:s", long_opts, &index);
- + c = getopt_long(argc, argv, "a:b:d:f:shx", long_opts, &index);
-
- DBG(("option index %d\n",c ));
-
- @@ -218,117 +251,134 @@ int main(int argc, char **argv)
- break;
-
- case 'b':
- - dl_ubus = optarg;
- + dl_ubus = atoi(optarg);
- break;
-
- case 'd':
- - dl_udev = optarg;
- + dl_udev = atoi(optarg);
- break;
-
- case 'x':
- debug = 1;
- + break;
- +
- + case 'h':
- + puts(
- + "Usage: dltool [options]\n"
- + "\n"
- + "-a <download addr>\n"
- + "-b <bus #>\n"
- + "-d <dev #>\n"
- + "-f <file>\n"
- + "-s Show found devices\n"
- + "-x Enable debug\n"
- + );
- + return 0;
- }
- }
-
- - usb_init();
- - usb_find_busses();
- - usb_find_devices();
- -
- - bus = usb_get_busses();
- -
- - DBG(("usb_get_busses: %p\n", bus));
- -
- - for (busp = bus; busp != NULL; busp = busp->next) {
- - struct usb_device *dev;
- -
- - DBG(("bus %p: dirname %s\n", busp, busp->dirname));
- -
- - if (dl_ubus) {
- - if (strcmp(busp->dirname, dl_ubus) != 0)
- - continue;
- - }
- + ret = libusb_init(&ctx);
- + if (ret)
- + errp("could not initialize usb stack");
-
- - for (dev = busp->devices; dev != NULL; dev = dev->next) {
- - DBG(("dev %p filename %s\n", dev, dev->filename));
- + bus_num = dev_num = 0;
- + found = NULL;
- + num_devs = libusb_get_device_list(ctx, &list);
- + for (i = 0; i < num_devs; ++i) {
- + libusb_device *dev = list[i];
- + bus_num = libusb_get_bus_number(dev);
- + dev_num = libusb_get_device_address(dev);
-
- - if (!verify_device(dev))
- - continue;
- + DBG(("bus %u; dev %u (%p)\n", bus_num, dev_num, dev));
-
- - if (flg_show) {
- - printf("bus %s: device %s\n",
- - busp->dirname, dev->filename);
- - continue;
- - }
- + if (dl_ubus >= 0 && bus_num != dl_ubus)
- + continue;
-
- - found = dev;
- + if (!verify_device(dev))
- + continue;
-
- - if (dl_udev) {
- - if (strcmp(dev->filename, dl_udev) == 0) {
- - result = dev;
- - break;
- - }
- - }
- + if (flg_show) {
- + printf("bus %u: device %u\n", bus_num, dev_num);
- + continue;
- }
-
- - if (result != NULL)
- - break;
- + if (dl_udev >= 0 && dev_num != dl_udev)
- + continue;
- +
- + found = dev;
- + break;
- }
-
- if (flg_show)
- return 0;
-
- - DBG(("device %p, found %p\n", result, found));
- + DBG(("found %p\n", found));
-
- - if (result == NULL && found != NULL)
- - result = found;
- -
- - if (result == NULL) {
- - fprintf(stderr, "failed to find device\n");
- - return 1;
- - }
- + if (found == NULL)
- + err("failed to find device\n");
-
- - printf("=> found device: bus %s, dev %s\n",
- - result->bus->dirname, result->filename);
- + printf("=> found device: bus %u, dev %u\n",
- + bus_num, dev_num);
-
- dl_data = load_file(dl_file, &dl_size, &fsize);
- - if (dl_data == NULL) {
- - printf("failed to load %s\n", dl_file);
- - return 1;
- - }
- + if (dl_data == NULL)
- + errp("failed to load %s", dl_file);
-
- printf("=> loaded %ld bytes from %s\n", fsize, dl_file);
-
- - devh = usb_open(result);
- - if (devh == NULL) {
- - perror("usb_open");
- - return 1;
- - }
- + ret = libusb_open(found, &devh);
- + if (ret == 0) {
- + /*
- + * Seems to break some recovery modes :(
- + * http://crosbug.com/26083
- + * These fail:
- + * smdk-dltool -a 0x02021400 -f bl1.bin
- + * smdk-dltool -a 0x02023400 -f bl2.bin
- + */
- +#if 0
- + uint8_t configuration;
- + struct libusb_config_descriptor *config;
- + libusb_get_active_config_descriptor(found, &config);
- + configuration = config->bConfigurationValue;
- + libusb_free_config_descriptor(config);
- + libusb_set_configuration(devh, configuration);
- +#endif
- + } else
- + errp("libusb_open");
-
- DBG(("claim interface\n"));
-
- - if (usb_claim_interface(devh, 0) < 0) {
- - perror("usb_claim_interface");
- - usb_close(devh);
- - return 1;
- - }
- + ret = libusb_claim_interface(devh, 0);
- + if (ret)
- + errp("libusb_claim_interface");
-
- printf("=> Downloading %ld bytes to 0x%08lx\n", dl_size, dl_addr);
-
- write_header(dl_data, dl_addr, dl_size);
- calc_cksum(dl_data, dl_size);
-
- - //ret = usb_bulk_write(devh, 3, (void *)dl_data, dl_size, 5*1000*1000);
- - ret = usb_bulk_write(devh, ep_out, (void *)dl_data, dl_size, 5*1000*1000);
- - printf("=> usb_bulk_write() returned %d\n", ret);
- -
- - if (ret != dl_size) {
- - printf("failed to write %ld bytes\n", dl_size);
- + transferred = 0;
- + while (transferred < dl_size) {
- + int actual, expected = MIN(dl_size - transferred, CHUNKSIZE);
- + ret = libusb_bulk_transfer(devh, ep_out, dl_data + transferred,
- + expected, &actual, 5 * 1000 * 1000);
- + printf("=> usb_bulk_write(%d) returned %d, wrote %d\n",
- + expected, ret, actual);
- + transferred += actual;
- +
- + if (ret || (expected != actual)) {
- + printf("failed to write %ld bytes (wrote %d): %s\n",
- + dl_size, transferred, strerror(errno));
- + ret = 1;
- + break;
- + }
- }
-
- free(dl_data);
-
- - usb_release_interface(devh, 0);
- - usb_close(devh);
- + libusb_release_interface(devh, 0);
- + libusb_close(devh);
- + libusb_exit(ctx);
-
- - return 0;
- + return ret;
- }
|