[PATCH 4/4 dfu-util] main: Always retrieve the DFU functional descriptor

Tormod Volden lists.tormod at gmail.com
Thu Sep 15 22:08:03 CEST 2011


From: Tormod Volden <debian.tormod at 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.tormod at 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




More information about the devel mailing list