| migrate to libusb-1 by me (Mike Frysinger) |
| |
| --- 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 |
| @@ -13,9 +13,11 @@ |
| #include <stdio.h> |
| #include <getopt.h> |
| #include <fcntl.h> |
| +#include <errno.h> |
| +#include <unistd.h> |
| |
| |
| -#include <usb.h> |
| +#include <libusb.h> |
| |
| unsigned int debug = 0; |
| unsigned long dl_addr = 0x30000000L; |
| @@ -23,12 +25,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 +120,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 +190,12 @@ struct option long_opts[] = { |
| .val = 'x', |
| }, |
| { |
| + .name = "help", |
| + .has_arg = 0, |
| + .flag = NULL, |
| + .val = 'h', |
| + }, |
| + { |
| .name = NULL |
| } |
| }; |
| @@ -181,12 +204,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 +222,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 +243,127 @@ 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"); |
| + |
| + 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); |
| + |
| + DBG(("bus %u; dev %u (%p)\n", bus_num, dev_num, dev)); |
| + |
| + if (dl_ubus >= 0 && bus_num != dl_ubus) |
| + continue; |
| + |
| + if (!verify_device(dev)) |
| + continue; |
| + |
| + if (flg_show) { |
| + printf("bus %u: device %u\n", bus_num, dev_num); |
| + continue; |
| } |
| |
| - for (dev = busp->devices; dev != NULL; dev = dev->next) { |
| - DBG(("dev %p filename %s\n", dev, dev->filename)); |
| + if (dl_udev >= 0 && dev_num != dl_udev) |
| + continue; |
| |
| - if (!verify_device(dev)) |
| - continue; |
| - |
| - if (flg_show) { |
| - printf("bus %s: device %s\n", |
| - busp->dirname, dev->filename); |
| - continue; |
| - } |
| - |
| - found = dev; |
| - |
| - if (dl_udev) { |
| - if (strcmp(dev->filename, dl_udev) == 0) { |
| - result = dev; |
| - break; |
| - } |
| - } |
| - } |
| - |
| - if (result != NULL) |
| - break; |
| + 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); |
| + //ret = libusb_bulk_transfer(devh, 3, dl_data, dl_size, &transferred, 5*1000*1000); |
| + ret = libusb_bulk_transfer(devh, ep_out, dl_data, dl_size, &transferred, 5*1000*1000); |
| printf("=> usb_bulk_write() returned %d\n", ret); |
| |
| - if (ret != dl_size) { |
| - printf("failed to write %ld bytes\n", dl_size); |
| + if (ret || transferred != dl_size) { |
| + printf("failed to write %ld bytes (wrote %d): %s\n", |
| + dl_size, transferred, strerror(errno)); |
| + ret = 1; |
| } |
| |
| 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; |
| } |