[PATCH] main: Look for DFU functional descriptor among all descriptors

Tormod Volden lists.tormod at gmail.com
Sat Nov 13 10:29:21 CET 2010


From: Tormod Volden <debian.tormod at gmail.com>

Some devices are not able to return non-standard type descriptors when
asked explicitly, but will include them within the configuration
hierarchy returned when requesting the full configuration descriptor.

Section 9.4.3 of the USB 1.1 specification does not dictate support
for requesting a "DFU functional descriptor" type, as I read it:

"The standard request to a device supports three types of descriptors:
DEVICE, CONFIGURATION, and STRING." and further "Class-specific and/or
vendor-specific descriptors follow the standard descriptors they
extend or modify."

This patch first looks for the functional descriptor in the full set of
descriptors. If it is not found, it will do the direct type=0x21 request
like before.

The patch also replaces a magic 0x21 with its more verbose DEFINE.
---
 src/main.c |   38 ++++++++++++++++++++++++++++++++++++--
 1 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/main.c b/src/main.c
index fd373fc..0f45117 100644
--- a/src/main.c
+++ b/src/main.c
@@ -368,6 +368,40 @@ static int resolve_device_path(struct dfu_if *dif)
 
 #endif /* !HAVE_USBPATH_H */
 
+/* Look for descriptor in the configuration descriptor output */
+static int usb_get_extra_descriptor(usb_dev_handle *udev, unsigned char type,
+			unsigned char index, void *resbuf, int size)
+{
+	char *cbuf;
+	int desclen, conflen, smallest;
+	int ret;
+	int p = 0;
+	int foundlen = 0;
+
+	conflen = (usb_device(udev))->config->wTotalLength;
+	cbuf = malloc(conflen);
+	ret = usb_get_descriptor(udev, USB_DT_CONFIG, index, cbuf, conflen);
+	if (ret < conflen) {
+		fprintf(stderr, "Warning: failed to retrieve complete"
+			"configuration descriptor\n");
+		conflen = ret;
+	}
+	while (p + 1 < conflen) {
+		desclen = (int) cbuf[p];
+		if (cbuf[p + 1] == type) {
+			smallest = desclen < size ? desclen : size;
+			memcpy(resbuf, &cbuf[p], smallest);
+			foundlen = smallest;
+			break;
+		}
+		p += desclen;
+	}
+	free(cbuf);
+	if (foundlen > 1)
+		return foundlen;
+	/* try to retrieve it through usb_get_descriptor directly */
+	return usb_get_descriptor(udev, type, index, resbuf, size);
+}
 
 static void help(void)
 {
@@ -790,8 +824,8 @@ status_again:
 
 	if (!transfer_size) {
 		/* Obtain DFU functional descriptor */
-		ret = usb_get_descriptor(dif->dev_handle, 0x21, dif->interface,
-					 &func_dfu, sizeof(func_dfu));
+		ret = usb_get_extra_descriptor(dif->dev_handle, USB_DT_DFU,
+				dif->interface, &func_dfu, sizeof(func_dfu));
 		if (ret < 0) {
 			fprintf(stderr, "Error obtaining DFU functional "
 				"descriptor: %s\n", usb_strerror());
-- 
1.7.0.4




More information about the devel mailing list