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 the functional
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.

Signed-off-by: Tormod Volden <debian.tor...@gmail.com>
---

I am pretty sure all supported devices return this descriptor? So
we can bail out if we can't retrieve it.

The program banner announces it only supports DFU 1.0 but the fact is
that it uses a few 1.1-only features. We should try to cover both in
the long run, and I think we should also follow the standard strictly,
and rather add device-specific quirks if needed.


 src/main.c |   48 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/main.c b/src/main.c
index 819e26c..f6b0ac8 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,21 @@ 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) {
+               fprintf(stderr, "Error obtaining DFU functional descriptor\n");
+               exit(1);
+       }
+       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 +904,27 @@ 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) {
+               fprintf(stderr, "Error obtaining DFU functional descriptor\n");
+               exit(1);
+       }
+       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

Reply via email to