From 282b72082f68254edd9631c8c04354e0fb63c2f6 Mon Sep 17 00:00:00 2001 From: Vincent Tinelli Date: Tue, 14 Feb 2017 17:16:25 +0300 Subject: [PATCH 1/7] usb: dwc3: gadget: Remove unused header inclusion Remove sys_proto.h inclusion which is not used by the driver. Signed-off-by: Vincent Tinelli Signed-off-by: Andy Shevchenko --- drivers/usb/dwc3/gadget.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 25ccc01..1156662 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -23,7 +23,6 @@ #include #include -#include #include "core.h" #include "gadget.h" From 8987012fe5a8bc226d1b3f5187c152b8d85a2dcd Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 8 Dec 2016 18:10:49 +0100 Subject: [PATCH 2/7] usb: gadget: dfu: add functional descriptor in descriptor set The "DFU descriptor set" must contain the "DFU functional descriptor" but it is missing today in U-Boot code (cf: DFU spec 1.1, chapter 4.2 DFU Mode Descriptor Set) This patch only allocate buffer and copy DFU functional descriptor after interfaces. Signed-off-by: Patrick Delaunay Signed-off-by: Patrick Delaunay --- drivers/usb/gadget/f_dfu.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 8e7c981..73b32f8 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -654,7 +654,7 @@ static int dfu_prepare_function(struct f_dfu *f_dfu, int n) struct usb_interface_descriptor *d; int i = 0; - f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1); + f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 2); if (!f_dfu->function) goto enomem; @@ -673,6 +673,14 @@ static int dfu_prepare_function(struct f_dfu *f_dfu, int n) f_dfu->function[i] = (struct usb_descriptor_header *)d; } + + /* add DFU Functional Descriptor */ + f_dfu->function[i] = calloc(sizeof(dfu_func), 1); + if (!f_dfu->function[i]) + goto enomem; + memcpy(f_dfu->function[i], &dfu_func, sizeof(dfu_func)); + + i++; f_dfu->function[i] = NULL; return 0; From f11bb2524541556682b83ee694829208b960b56c Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 16 Dec 2016 18:41:31 +0100 Subject: [PATCH 3/7] usb: gadget: dfu: correct size for USB_REQ_DFU_GETSTATE result 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 Signed-off-by: Patrick Delaunay --- 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 73b32f8..69d2de6 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 d428776657154f57b89913ffb0c5a23cb5b595f7 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 16 Dec 2016 18:41:32 +0100 Subject: [PATCH 4/7] usb: gadget: dfu: add result for handle_getstatus() 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 Signed-off-by: Patrick Delaunay --- 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 69d2de6..26b3e6e 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, From 00e9d69629eb026a2ccc9e2526e365b1e796a14d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 10 Feb 2017 19:32:31 +0300 Subject: [PATCH 5/7] usb: gadget: f_dfu: write req->actual bytes If last packet is short, we shouldn't write req->length bytes to non-volatile media, we should write only what's available to us, which is held in req->actual. Signed-off-by: Felipe Balbi Signed-off-by: Andy Shevchenko --- drivers/usb/gadget/f_dfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 26b3e6e..81929d3 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -159,7 +159,7 @@ static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) int ret; ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, - req->length, f_dfu->blk_seq_num); + req->actual, f_dfu->blk_seq_num); if (ret) { f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; f_dfu->dfu_state = DFU_STATE_dfuERROR; From 949bf79e73a12961cf1310baf411647083f34b34 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 22 Feb 2017 11:22:37 +0200 Subject: [PATCH 6/7] usb: gadget: g_dnl: fix g_dnl_set_serialnumber() instead of only copying if strlen(s) is less than 32 characters, let's just copy at most 31 characters regardless of the size of serial#. This will guarantee that we always have a serial number if serial# environment variable is set to anything. Note that without a proper serial number, USB Command Verifier fails our test of Device Descriptor since we will claim to have a serial number without really providing one when requested. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/g_dnl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c index 45a484c..4ba7c1d 100644 --- a/drivers/usb/gadget/g_dnl.c +++ b/drivers/usb/gadget/g_dnl.c @@ -49,8 +49,7 @@ static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER; void g_dnl_set_serialnumber(char *s) { memset(g_dnl_serial, 0, MAX_STRING_SERIAL); - if (strlen(s) < MAX_STRING_SERIAL) - strncpy(g_dnl_serial, s, strlen(s)); + strncpy(g_dnl_serial, s, MAX_STRING_SERIAL - 1); } static struct usb_device_descriptor device_desc = { From 9bf9e813584c23b677e92d8dca742ae9ef27fc94 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 22 Feb 2017 11:22:38 +0200 Subject: [PATCH 7/7] usb: gadget: f_dfu: set serial number if serial# is valid With this patch, USB Command Verifier is happy with our DFU implementation on Chapter 9 tests. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_dfu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 81929d3..dfa4359 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -691,6 +691,7 @@ static int dfu_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_dfu *f_dfu = func_to_dfu(f); + const char *s; int alt_num = dfu_get_alt_number(); int rv, id, i; @@ -724,6 +725,10 @@ static int dfu_bind(struct usb_configuration *c, struct usb_function *f) cdev->req->context = f_dfu; + s = getenv("serial#"); + if (s) + g_dnl_set_serialnumber((char *)s); + error: return rv; }