r1081 - trunk/src/host/dfu-util/src
laforge at sita.openmoko.org
laforge at sita.openmoko.org
Fri Feb 23 04:00:01 CET 2007
Author: laforge
Date: 2007-02-23 04:00:00 +0100 (Fri, 23 Feb 2007)
New Revision: 1081
Modified:
trunk/src/host/dfu-util/src/main.c
Log:
this is now 'barely working', after having hunted down a number of bugs.
Modified: trunk/src/host/dfu-util/src/main.c
===================================================================
--- trunk/src/host/dfu-util/src/main.c 2007-02-22 22:49:54 UTC (rev 1080)
+++ trunk/src/host/dfu-util/src/main.c 2007-02-23 03:00:00 UTC (rev 1081)
@@ -33,10 +33,9 @@
int debug;
-
static int verbose = 0;
-#define DFU_INTF_FLAG_DFU 0x0001 /* DFU Mode, (not Runtime) */
+#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */
#define DFU_IFF_VENDOR 0x0100
#define DFU_IFF_PRODUCT 0x0200
#define DFU_IFF_CONFIG 0x0400
@@ -54,17 +53,18 @@
u_int8_t configuration;
u_int8_t interface;
u_int8_t altsetting;
- u_int8_t flags;
+ unsigned int flags;
+ struct usb_device *dev;
- struct usb_device *dev;
struct usb_dev_handle *dev_handle;
};
-static int _assign_first_cb(struct dfu_if *dif, void *v)
+static int _get_first_cb(struct dfu_if *dif, void *v)
{
- struct dfu_if **v_dif = v;
- *v_dif = dif;
+ struct dfu_if *v_dif = v;
+ memcpy(v_dif, dif, sizeof(*v_dif)-sizeof(struct usb_dev_handle *));
+
/* return a value that makes find_dfu_if return immediately */
return 1;
}
@@ -78,6 +78,8 @@
struct dfu_if _dif, *dfu_if = &_dif;
int cfg_idx, intf_idx, alt_idx;
int rc;
+
+ memset(dfu_if, 0, sizeof(*dfu_if));
for (cfg_idx = 0; cfg_idx < dev->descriptor.bNumConfigurations;
cfg_idx++) {
@@ -96,14 +98,16 @@
dfu_if->product =
dev->descriptor.idProduct;
dfu_if->configuration = cfg_idx;
- dfu_if->interface = intf_idx;
+ dfu_if->interface =
+ intf->bInterfaceNumber;
dfu_if->altsetting =
intf->bAlternateSetting;
if (intf->bInterfaceProtocol == 2)
- dfu_if->flags =
- DFU_INTF_FLAG_DFU;
+ dfu_if->flags |=
+ DFU_IFF_DFU;
else
- dfu_if->flags = 0;
+ dfu_if->flags &=
+ ~DFU_IFF_DFU;
if (!handler)
return 1;
rc = handler(dfu_if, v);
@@ -117,15 +121,28 @@
return 0;
}
+static int get_first_dfu_if(struct dfu_if *dif)
+{
+ return find_dfu_if(dif->dev, &_get_first_cb, (void *) dif);
+}
+
+#define MAX_STR_LEN 64
+
static int print_dfu_if(struct dfu_if *dfu_if, void *v)
{
struct usb_device *dev = dfu_if->dev;
+ int if_name_str_idx;
+ char name[MAX_STR_LEN+1] = "UNDEFINED";
- printf("Found DFU %s: [0x%04x:0x%04x] devnum=%u, cfg=%u, intf=%u, alt=%u\n",
- dfu_if->flags & DFU_INTF_FLAG_DFU ? "DFU" : "Runtime",
+ if_name_str_idx = dev->config[dfu_if->configuration].interface[dfu_if->interface].altsetting[dfu_if->altsetting].iInterface;
+ if (if_name_str_idx && dfu_if->dev_handle)
+ usb_get_string_simple(dfu_if->dev_handle, if_name_str_idx, name, MAX_STR_LEN);
+
+ printf("Found DFU %s: [0x%04x:0x%04x] devnum=%u, cfg=%u, intf=%u, alt=%u, name=%s\n",
+ dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime",
dev->descriptor.idVendor, dev->descriptor.idProduct,
dev->devnum, dfu_if->configuration, dfu_if->interface,
- dfu_if->altsetting);
+ dfu_if->altsetting, name);
return 0;
}
@@ -149,6 +166,30 @@
return num_found;
}
+/* Find the first DFU-capable device, save it in dfu_if->dev */
+static int get_first_dfu_device(struct dfu_if *dif)
+{
+ struct usb_bus *usb_bus;
+ struct usb_device *dev;
+
+ for (usb_bus = usb_get_busses(); NULL != usb_bus;
+ usb_bus = usb_bus->next) {
+ for (dev = usb_bus->devices; NULL != dev; dev = dev->next) {
+ if (!dif ||
+ (dif->flags & (DFU_IFF_VENDOR|DFU_IFF_PRODUCT)) == 0 ||
+ (dev->descriptor.idVendor == dif->vendor &&
+ dev->descriptor.idProduct == dif->product)) {
+ if (count_dfu_interfaces(dev) >= 1) {
+ dif->dev = dev;
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
/* Count DFU capable devices within system */
static int count_dfu_devices(struct dfu_if *dif)
{
@@ -161,10 +202,9 @@
usb_bus = usb_bus->next) {
for (dev = usb_bus->devices; NULL != dev; dev = dev->next) {
if (!dif ||
- (dif->flags & (DFU_IFF_VENDOR|DFU_IFF_PRODUCT) == 0) ||
+ (dif->flags & (DFU_IFF_VENDOR|DFU_IFF_PRODUCT)) == 0 ||
(dev->descriptor.idVendor == dif->vendor &&
dev->descriptor.idProduct == dif->product)) {
- dif->dev = dev;
if (count_dfu_interfaces(dev) >= 1)
num_found++;
}
@@ -185,6 +225,7 @@
find_dfu_if(dev, &print_dfu_if, NULL);
}
}
+ return 0;
}
static int parse_vendprod(struct usb_vendprod *vp, const char *str)
@@ -248,12 +289,13 @@
int main(int argc, char **argv)
{
struct usb_vendprod vendprod;
- struct dfu_if _dif, *dif = &_dif;
+ struct dfu_if _rt_dif, _dif, *dif = &_dif;
int num_devs;
int num_ifs;
- enum mode mode;
+ enum mode mode = MODE_NONE;
struct dfu_status status;
struct usb_dfu_func_descriptor func_dfu;
+ char *filename;
printf("dfu-util - (C) 2007 by OpenMoko Inc.\n"
"This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
@@ -261,6 +303,7 @@
memset(dif, 0, sizeof(*dif));
usb_init();
+ //usb_set_debug(255);
usb_find_busses();
usb_find_devices();
@@ -312,9 +355,11 @@
break;
case 'U':
mode = MODE_UPLOAD;
+ filename = optarg;
break;
case 'D':
mode = MODE_DOWNLOAD;
+ filename = optarg;
break;
default:
help();
@@ -322,6 +367,14 @@
}
}
+ if (mode == MODE_NONE) {
+ fprintf(stderr, "You need to specify one of -D or -U\n");
+ help();
+ exit(2);
+ }
+
+ dfu_init(5000);
+
num_devs = count_dfu_devices(dif);
if (num_devs == 0) {
fprintf(stderr, "No DFU capable USB device found\n");
@@ -336,42 +389,126 @@
"device\n");
exit(3);
}
+ if (!get_first_dfu_device(dif))
+ exit(3);
+
/* We have exactly one device. It's usb_device is now in dif->dev */
- if (mode == MODE_NONE) {
- fprintf(stderr, "You need to specify one of -D or -U\n");
- help();
- exit(2);
+ printf("Opening USB Device 0x%04x:0x%04x...\n", dif->vendor, dif->product);
+ dif->dev_handle = usb_open(dif->dev);
+ if (!dif->dev_handle) {
+ fprintf(stderr, "Cannot open device: %s\n", usb_strerror());
+ exit(1);
}
- /* FIXME: check if there's only one interface/altsetting and use it */
- if (!dif->flags & (DFU_IFF_CONFIG|DFU_IFF_ALT) != DFU_IFF_CONFIG|DFU_IFF_ALT) {
- fprintf(stderr, "You have to specify --cfg and --alt!\n");
- help();
+ /* try to find first DFU interface of device */
+ memcpy(&_rt_dif, dif, sizeof(_rt_dif));
+ if (!get_first_dfu_if(&_rt_dif))
exit(1);
- }
-retry:
- /* FIXME: need to re-scan and re-select same device after reset*/
- if (find_dfu_if(dif->dev, NULL, NULL) != 1) {
- fprintf(stderr, "Can't find device anymore !?!\n");
- exit(1);
+ print_dfu_if(&_rt_dif, NULL);
+
+ if (!_rt_dif.flags & DFU_IFF_DFU) {
+ /* In the 'first round' during runtime mode, there can only be one
+ * DFU Interface descriptor according to the DFU Spec. */
+
+ /* FIXME: check if the selected device really has only one */
+
+ printf("Claiming USB DFU Runtime Interface...\n");
+ if (usb_claim_interface(_rt_dif.dev_handle, _rt_dif.interface) < 0) {
+ fprintf(stderr, "Cannot claim interface: %s\n", usb_strerror());
+ exit(1);
+ }
+
+ printf("Determining device status: ");
+ if (dfu_get_status(_rt_dif.dev_handle, _rt_dif.interface, &status ) < 0) {
+ fprintf(stderr, "error get_status: %s\n", usb_strerror());
+ exit(1);
+ }
+ printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus);
+
+ switch (status.bState) {
+ case STATE_APP_IDLE:
+ printf("Device really in Runtime Mode, send DFU detach request...\n");
+ if (dfu_detach(_rt_dif.dev_handle, _rt_dif.interface, 1000) < 0) {
+ fprintf(stderr, "error detaching: %s\n", usb_strerror());
+ exit(1);
+ break;
+ }
+ printf("Resetting USB...\n");
+ if (usb_reset(_rt_dif.dev_handle) < 0) {
+ fprintf(stderr, "error resetting after detach: %s\n", usb_strerror());
+ }
+ sleep(2);
+ break;
+ case STATE_DFU_ERROR:
+ printf("dfuERROR, clearing status\n");
+ if (dfu_clear_status(_rt_dif.dev_handle, _rt_dif.interface) < 0) {
+ fprintf(stderr, "error clear_status: %s\n", usb_strerror());
+ exit(1);
+ break;
+ }
+ break;
+ case STATE_DFU_IDLE:
+ printf("Device already in dfuIDLE ?!?, continuing\n");
+ goto already_idle;
+ break;
+ }
+
+ /* now we need to re-scan the bus and locate our device */
+ if (usb_find_devices() < 2)
+ printf("not at least 2 device changes found ?!?\n");
+
+ num_devs = count_dfu_devices(dif);
+ if (num_devs == 0) {
+ fprintf(stderr, "Lost device after RESET?\n");
+ exit(1);
+ } else if (num_devs > 1) {
+ fprintf(stderr, "More than one DFU capable USB device found, "
+ "you might try `--list' and then disconnect all but one "
+ "device\n");
+ exit(1);
+ }
+
+ printf("Opening USB Device...\n");
+ dif->dev_handle = usb_open(dif->dev);
+ if (!dif->dev_handle) {
+ fprintf(stderr, "Cannot open device: %s\n", usb_strerror());
+ exit(1);
+ }
+ } else {
+ /* we're already in DFU mode, so we can skip the detach/reset
+ * procedure */
}
- printf("Opening USB Device...\n");
- dif->dev_handle = usb_open(dif->dev);
- if (!dif->dev_handle) {
- fprintf(stderr, "Cannot open device: %s\n", usb_strerror());
+already_idle:
+ printf("%p (%d)\n", dif->dev_handle, *(int *)dif->dev_handle);
+ num_ifs = count_dfu_interfaces(dif->dev);
+ printf("%p (%d)\n", dif->dev_handle, *(int *)dif->dev_handle);
+ if (num_ifs < 0) {
+ fprintf(stderr, "No DFU Interface after RESET?!?\n");
exit(1);
+ } else if (num_ifs == 1) {
+ if (!get_first_dfu_if(dif)) {
+ fprintf(stderr, "Can't find the single available DFU IF\n");
+ exit(1);
+ }
+ } else if (num_ifs > 1 && !dif->flags & (DFU_IFF_IFACE|DFU_IFF_ALT)) {
+ fprintf(stderr, "We have %u DFU Interfaces/Altsettings, "
+ "you have to specify one via --intf / --alt options\n",
+ num_ifs);
+ exit(1);
}
+#if 0
printf("Setting Configuration...\n");
if (usb_set_configuration(dif->dev_handle, dif->configuration) < 0) {
fprintf(stderr, "Cannot set configuration: %s\n", usb_strerror());
exit(1);
}
-
- printf("Claiming USB Interface...\n");
+#endif
+ printf("Claiming USB DFU Interface...\n");
+ printf("%p (%d)\n", dif->dev_handle, *(int *)dif->dev_handle);
if (usb_claim_interface(dif->dev_handle, dif->interface) < 0) {
fprintf(stderr, "Cannot claim interface: %s\n", usb_strerror());
exit(1);
@@ -389,37 +526,26 @@
fprintf(stderr, "error get_status: %s\n", usb_strerror());
exit(1);
}
- printf("state = %d, status = %d\n", status.bState, status.bStatus);
+ printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus);
switch (status.bState) {
case STATE_APP_IDLE:
- printf("Device in Runtime Mode, send DFU detach request...\n");
- if (dfu_detach(dif->dev_handle, dif->interface, 1000) < 0) {
- fprintf(stderr, "error detaching: %s\n", usb_strerror());
- exit(1);
- break;
- }
- printf("Resetting USB...\n");
- if (usb_reset(dif->dev_handle) < 0) {
- fprintf(stderr, "error resetting after detach: %s\n", usb_strerror());
- }
- sleep(2);
- goto retry;
+ fprintf(stderr, "Device still in Runtime Mode!\n");
+ exit(1);
break;
case STATE_DFU_ERROR:
printf("dfuERROR, clearing status\n");
if (dfu_clear_status(dif->dev_handle, dif->interface) < 0) {
fprintf(stderr, "error clear_status: %s\n", usb_strerror());
exit(1);
- break;
}
- goto retry;
break;
case STATE_DFU_IDLE:
printf("dfuIDLE, continuing\n");
break;
}
+ /* Obtain DFU functional descriptor */
{
int ret;
@@ -445,14 +571,19 @@
exit(1);
}
}
-#if 0
- sam7dfu_do_upload(usb_handle, interface, func_dfu.wTransferSize,
- "/tmp/dfu_upload.img");
- //sam7dfu_do_dnload(usb_handle, interface, 252,
- sam7dfu_do_dnload(usb_handle, interface, func_dfu.wTransferSize,
- "/tmp/dfu_upload.img");
-#endif
+ switch (mode) {
+ case MODE_UPLOAD:
+ //sam7dfu_do_upload(usb_handle, interface, func_dfu.wTransferSize, filename);
+ break;
+ case MODE_DOWNLOAD:
+ //sam7dfu_do_dnload(usb_handle, interface, func_dfu.wTransferSize, filename);
+ break;
+ default:
+ fprintf(stderr, "Unsupported mode: %u\n", mode);
+ exit(1);
+ }
+
exit(0);
}
More information about the commitlog
mailing list