From: Tormod Volden <debian.tor...@gmail.com> It should exist both in run-time and DFU mode, and should report the transfer size.
Also print out the device DFU version as reported by this descriptor. For DFU 1.0 devices the descriptor does not contain the version field, so set it to 1.00 if the field is missing. Some devices seems to not provide the descriptor at all, for now assume they are otherwise conforming to DFU 1.0 and use the default transfer size of 1024. Signed-off-by: Tormod Volden <debian.tor...@gmail.com> --- Please consider this patch instead. Once we know more about the broken devices we can add quirks, but for now this will provide enough compatibility. Tormod src/main.c | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index 819e26c..e03ec3f 100644 --- a/src/main.c +++ b/src/main.c @@ -106,6 +106,7 @@ static int find_dfu_if(libusb_device *dev, intf->bInterfaceNumber; dfu_if->altsetting = intf->bAlternateSetting; + /* FIXME: always 0 for DFU 1.0 */ if (intf->bInterfaceProtocol == 2) dfu_if->flags |= DFU_IFF_DFU; else @@ -517,7 +518,7 @@ int main(int argc, char **argv) unsigned int host_page_size; enum mode mode = MODE_NONE; struct dfu_status status; - struct usb_dfu_func_descriptor func_dfu; + struct usb_dfu_func_descriptor func_dfu, func_dfu_rt; libusb_context *ctx; struct dfu_file file; char *alt_name = NULL; /* query alt name if non-NULL */ @@ -682,6 +683,22 @@ int main(int argc, char **argv) /* find set of quirks for this device */ set_quirks(_rt_dif.vendor, _rt_dif.product); + /* Retrieve run-time DFU functional descriptor */ + ret = usb_get_extra_descriptor(&_rt_dif, USB_DT_DFU, _rt_dif.interface, + &func_dfu_rt, sizeof(func_dfu_rt)); + if (ret == 7) { + /* DFU 1.0 does not have this field */ + printf("Deducing device DFU version from functional descriptor " + "length\n"); + func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (ret < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } + printf("Run-time device DFU version %x\n", + libusb_le16_to_cpu(func_dfu_rt.bcdDFUVersion)); + 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. */ @@ -888,19 +905,30 @@ status_again: break; } + /* Retrieve DFU mode DFU functional descriptor */ + ret = usb_get_extra_descriptor(dif, USB_DT_DFU, dif->interface, + &func_dfu, sizeof(func_dfu)); + if (ret == 7) { + /* DFU 1.0 does not have this field */ + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (ret < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + printf("Warning: Transfer size can not be detected\n"); + func_dfu.wTransferSize = 0; + } + if (func_dfu.bcdDFUVersion != func_dfu_rt.bcdDFUVersion) { + fprintf(stderr, "DFU functional descriptor mismatch\n"); + exit(1); + } + + /* if not specified by user */ if (!transfer_size) { - /* Obtain DFU functional descriptor */ - ret = usb_get_extra_descriptor(dif, USB_DT_DFU, - dif->interface, &func_dfu, sizeof(func_dfu)); - if (ret < 0) { - fprintf(stderr, "Error obtaining DFU functional " - "descriptor\n"); - } else { - transfer_size = libusb_le16_to_cpu(func_dfu.wTransferSize); - printf("Device returned transfer size %i\n", - transfer_size); - } + transfer_size = libusb_le16_to_cpu(func_dfu.wTransferSize); + printf("Device reported transfer size %i\n", transfer_size); } + /* if returned zero or not detected (and not user specified) */ if (!transfer_size) { transfer_size = DEFAULT_TRANSFER_SIZE; -- 1.7.5.4 _______________________________________________ devel mailing list devel@lists.openmoko.org https://lists.openmoko.org/mailman/listinfo/devel