[PATCH] main: New default (1024) and clamping of transfer size

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


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

DFU dictates that the effective transfer size is chosen from
bMaxPacketSIze0 (often 64) up to the real wTransferSize in the device.
If we can not detect the real value of wTransferSize, lower guesses can
only be safer. The previous default was the host kernel page size which
is the higher limit on the host side (on Linux). This would usually
translate into 4096, which possibly is too high for some devices.

1024 bytes seems like a reasonable trade-off for a default size, when
one is needed. At any rate, it should really be determined from the DFU
functional descriptor, so this default should not matter much.
---

Digging through the git/svn log, I found the explanation for clamping
transfer size to host kernel page_size:
http://git.openezx.org/dfu-util.git?a=commitdiff;h=e62a198670accf9e47176ba6434c84c41df32201
So I have left this check in (and documented it better).

Does anyone know if USB control transfers are still limited to the kernel
page size on Linux? Is it Linux-only?

In any case, I am pretty convinced we should not /default/ to the host
kernel page_size.

Also got rid of the FIXME in this version :)

 src/main.c |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/main.c b/src/main.c
index 0f45117..1862bad 100644
--- a/src/main.c
+++ b/src/main.c
@@ -459,6 +459,8 @@ int main(int argc, char **argv)
 	int num_devs;
 	int num_ifs;
 	unsigned int transfer_size = 0;
+	unsigned int default_transfer_size = 1024;
+	unsigned int host_page_size;
 	enum mode mode = MODE_NONE;
 	struct dfu_status status;
 	struct usb_dfu_func_descriptor func_dfu;
@@ -466,7 +468,6 @@ int main(int argc, char **argv)
 	char *alt_name = NULL; /* query alt name if non-NULL */
 	char *end;
 	int final_reset = 0;
-	int page_size = getpagesize();
 	int ret;
 	
 	printf("dfu-util - (C) 2007-2008 by OpenMoko Inc.\n"
@@ -474,6 +475,7 @@ int main(int argc, char **argv)
 
 	printf("dfu-util does currently only support DFU version 1.0\n\n");
 
+	host_page_size = getpagesize();
 	memset(dif, 0, sizeof(*dif));
 
 	usb_init();
@@ -829,16 +831,28 @@ status_again:
 		if (ret < 0) {
 			fprintf(stderr, "Error obtaining DFU functional "
 				"descriptor: %s\n", usb_strerror());
-			transfer_size = page_size;
 		} else {
 			transfer_size = get_int16_le(&func_dfu.wTransferSize);
+			printf("Device returned transfer size %i\n",
+				transfer_size);
 		}
 	}
-
-	if (transfer_size > page_size)
-		transfer_size = page_size;
-	
-	printf("Transfer Size = 0x%04x\n", transfer_size);
+	/* if returned zero or not detected (and not user specified) */
+	if (!transfer_size) {
+		transfer_size = default_transfer_size;
+		printf("Warning: Trying default transfer size %i\n",
+			transfer_size);
+	}
+	/* limitation of Linux usbdevio */
+	if (transfer_size > host_page_size) {
+		transfer_size = host_page_size;
+		printf("Limited transfer size to %i\n", transfer_size);
+	}
+	/* DFU specification */
+	if (transfer_size < dif->dev->descriptor.bMaxPacketSize0) {
+		transfer_size = dif->dev->descriptor.bMaxPacketSize0;
+		printf("Adjusted transfer size to %i\n", transfer_size);
+	}
 
 	if (DFU_STATUS_OK != status.bStatus ) {
 		printf("WARNING: DFU Status: '%s'\n",
-- 
1.7.0.4




More information about the devel mailing list