[U-Boot] [PATCH 0/2] Series to clean handle_XXX() in f_dfu.c

1/ DFU_GETSTATE response error
when the DFU device state is requested using libusb with DFU_GETSTATUS a error is generated : LIBUSB_ERROR_IO
I see the issue with my programmer tools based on dfu with libusb and I don't understood the actual code in U-Boot (req->actual is updated but not req->lenght ?)
With the proposed patch, I aligned the code on the GETSTATUS behavior: the correct lenght is provided in req->lenght as the other answer and the issue is solved.
PS: the issue not see with dfu-util as the existing function dfu_get_state() is never called in main (with dfu-util 0.9)
But I can reproduce the same issue with patched version of dfu-util to add call to this function, on the dfu-util master branch
diff --git a/src/main.c b/src/main.c index 7f31d4c..d99ace9 100644 --- a/src/main.c +++ b/src/main.c @@ -535,6 +535,13 @@ dfustate: }
status_again: + printf("Determining device state: "); + ret = dfu_get_state(dfu_root->dev_handle, dfu_root->interface); + if (ret < 0) { + errx(EX_IOERR, "error get_state: %s", libusb_error_name(ret)); + } + printf("state = %s\n", dfu_state_to_string(ret)); + printf("Determining device status: "); ret = dfu_get_status(dfu_root, &status ); if (ret < 0) {
2/ harmonize handle_getstatus() with other function
=> add return value with size of the buffer as - handle_getstate() add in part 1 or existing functions - handle_dnload() - handle_upload()
Patrick Delaunay (2): usb: gadget: dfu: correct size for USB_REQ_DFU_GETSTATE result usb: gadget: dfu: add result for handle_getstatus()
drivers/usb/gadget/f_dfu.c | 56 ++++++++++++++++++++-------------------------- drivers/usb/gadget/f_dfu.h | 1 - 2 files changed, 24 insertions(+), 33 deletions(-)

From: Patrick Delaunay patrick.delaunay@st.com
return the correct size for DFU_GETSTATE result (1 byte in DFU 1.1 spec) to avoid issue in USB protocol and the variable "value" is propagated to req->lenght as all the in the other request with answer - DFU_GETSTATUS - DFU_DNLOAD - DFU_UPLOAD Then the buffer is correctly treated in USB driver
NB: it was the only request witch directly change "req->actual"
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrick Delaunay patrick.delaunay73@gmail.com ---
drivers/usb/gadget/f_dfu.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 8e7c981..2790ddb 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -212,12 +212,12 @@ static void handle_getstatus(struct usb_request *req) dstat->iString = 0; }
-static void handle_getstate(struct usb_request *req) +static int handle_getstate(struct usb_request *req) { struct f_dfu *f_dfu = req->context;
((u8 *)req->buf)[0] = f_dfu->dfu_state; - req->actual = sizeof(u8); + return sizeof(u8); }
static inline void to_dfu_mode(struct f_dfu *f_dfu) @@ -272,7 +272,7 @@ static int state_app_idle(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; case USB_REQ_DFU_DETACH: f_dfu->dfu_state = DFU_STATE_appDETACH; @@ -300,7 +300,7 @@ static int state_app_detach(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_appIDLE; @@ -345,7 +345,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; case USB_REQ_DFU_DETACH: /* @@ -385,7 +385,7 @@ static int state_dfu_dnload_sync(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -441,7 +441,7 @@ static int state_dfu_dnload_idle(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -469,7 +469,7 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu, req->complete = dnload_request_flush; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -497,7 +497,7 @@ static int state_dfu_manifest(struct f_dfu *f_dfu, puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -534,7 +534,7 @@ static int state_dfu_upload_idle(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -558,7 +558,7 @@ static int state_dfu_error(struct f_dfu *f_dfu, value = RET_STAT_LEN; break; case USB_REQ_DFU_GETSTATE: - handle_getstate(req); + value = handle_getstate(req); break; case USB_REQ_DFU_CLRSTATUS: f_dfu->dfu_state = DFU_STATE_dfuIDLE;

From: Patrick Delaunay patrick.delaunay@st.com
harmonize result with other handle_XXX() functions: return int for size remove the define RET_STAT_LEN : no more necessary
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrick Delaunay patrick.delaunay73@gmail.com ---
drivers/usb/gadget/f_dfu.c | 34 +++++++++++++--------------------- drivers/usb/gadget/f_dfu.h | 1 - 2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 2790ddb..b9dd170 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -178,7 +178,7 @@ static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu) DFU_MANIFEST_POLL_TIMEOUT; }
-static void handle_getstatus(struct usb_request *req) +static int handle_getstatus(struct usb_request *req) { struct dfu_status *dstat = (struct dfu_status *)req->buf; struct f_dfu *f_dfu = req->context; @@ -210,6 +210,8 @@ static void handle_getstatus(struct usb_request *req) dstat->bStatus = f_dfu->dfu_status; dstat->bState = f_dfu->dfu_state; dstat->iString = 0; + + return sizeof(struct dfu_status); }
static int handle_getstate(struct usb_request *req) @@ -268,8 +270,7 @@ static int state_app_idle(struct f_dfu *f_dfu,
switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -296,8 +297,7 @@ static int state_app_detach(struct f_dfu *f_dfu,
switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -341,8 +341,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu, value = RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -381,8 +380,7 @@ static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -405,8 +403,7 @@ static int state_dfu_dnbusy(struct f_dfu *f_dfu,
switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; default: f_dfu->dfu_state = DFU_STATE_dfuERROR; @@ -437,8 +434,7 @@ static int state_dfu_dnload_idle(struct f_dfu *f_dfu, value = RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -463,9 +459,8 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu, case USB_REQ_DFU_GETSTATUS: /* We're MainfestationTolerant */ f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; - handle_getstatus(req); + value = handle_getstatus(req); f_dfu->blk_seq_num = 0; - value = RET_STAT_LEN; req->complete = dnload_request_flush; break; case USB_REQ_DFU_GETSTATE: @@ -491,9 +486,8 @@ static int state_dfu_manifest(struct f_dfu *f_dfu, case USB_REQ_DFU_GETSTATUS: /* We're MainfestationTolerant */ f_dfu->dfu_state = DFU_STATE_dfuIDLE; - handle_getstatus(req); + value = handle_getstatus(req); f_dfu->blk_seq_num = 0; - value = RET_STAT_LEN; puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); break; case USB_REQ_DFU_GETSTATE: @@ -530,8 +524,7 @@ static int state_dfu_upload_idle(struct f_dfu *f_dfu, value = RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); @@ -554,8 +547,7 @@ static int state_dfu_error(struct f_dfu *f_dfu,
switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; + value = handle_getstatus(req); break; case USB_REQ_DFU_GETSTATE: value = handle_getstate(req); diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h index 0c29954..a256577 100644 --- a/drivers/usb/gadget/f_dfu.h +++ b/drivers/usb/gadget/f_dfu.h @@ -51,7 +51,6 @@
#define RET_STALL -1 #define RET_ZLP 0 -#define RET_STAT_LEN 6
enum dfu_state { DFU_STATE_appIDLE = 0,

Hi Patrick,
1/ DFU_GETSTATE response error
when the DFU device state is requested using libusb with DFU_GETSTATUS a error is generated : LIBUSB_ERROR_IO
I see the issue with my programmer tools based on dfu with libusb and I don't understood the actual code in U-Boot (req->actual is updated but not req->lenght ?)
With the proposed patch, I aligned the code on the GETSTATUS behavior: the correct lenght is provided in req->lenght as the other answer and the issue is solved.
PS: the issue not see with dfu-util as the existing function dfu_get_state() is never called in main (with dfu-util 0.9)
But I can reproduce the same issue with patched version of
dfu-util to add call to this function, on the dfu-util master branch
diff --git a/src/main.c b/src/main.c index 7f31d4c..d99ace9 100644 --- a/src/main.c +++ b/src/main.c @@ -535,6 +535,13 @@ dfustate: }
status_again:
printf("Determining device state: ");
ret = dfu_get_state(dfu_root->dev_handle,
dfu_root->interface);
if (ret < 0) {
errx(EX_IOERR, "error get_state: %s",
libusb_error_name(ret));
}
printf("state = %s\n", dfu_state_to_string(ret));
printf("Determining device status: "); ret = dfu_get_status(dfu_root, &status ); if (ret < 0) {
2/ harmonize handle_getstatus() with other function
=> add return value with size of the buffer as
- handle_getstate() add in part 1
or existing functions
- handle_dnload()
- handle_upload()
Patrick Delaunay (2): usb: gadget: dfu: correct size for USB_REQ_DFU_GETSTATE result usb: gadget: dfu: add result for handle_getstatus()
First of all thank you very much for fixing several DFU issues.
Secondly, please find my deepest apologies for such long delay. It will NOT happen again.
Your patches have been added to -dfu tree. I will send PR tomorrow.
I've also added following patch: http://patchwork.ozlabs.org/patch/704131/
For all of them:
Acked-by: Lukasz Majewski lukma@denx.de Tested-by: Lukasz Majewski lukma@denx.de
Test HW: BBB (am335x) Test SW: test/py/dfu
drivers/usb/gadget/f_dfu.c | 56 ++++++++++++++++++++-------------------------- drivers/usb/gadget/f_dfu.h | 1 - 2 files changed, 24 insertions(+), 33 deletions(-)
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
participants (2)
-
Lukasz Majewski
-
Patrick Delaunay