public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Lukasz Majewski <l.majewski@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/3] usb: dfu: introduce dfuMANIFEST state
Date: Fri, 14 Mar 2014 11:47:49 +0100	[thread overview]
Message-ID: <20140314114749.285b3a09@amdc2363> (raw)
In-Reply-To: <1394618481-9572-3-git-send-email-hs@denx.de>

Hi Heiko,

> on nand flash using ubi, after the download of the new image into
> the flash, the "rest" of the nand sectors get erased while flushing
> the medium. With current u-boot version dfu-util may show:
> 
> Starting download:
> [##################################################] finished!
> state(7) = dfuMANIFEST, status(0) = No error condition is present
> unable to read DFU status
> 
> as get_status is not answered while erasing sectors, if erasing
> needs some time.
> 
> So do the following changes to prevent this:
> 
> - introduce dfuManifest state
>   According to dfu specification
>   ( http://www.usb.org/developers/devclass_docs/usbdfu10.pdf )
> section 7: "the device enters the dfuMANIFEST-SYNC state and awaits
> the solicitation of the status report by the host. Upon receipt of
> the anticipated DFU_GETSTATUS, the device enters the dfuMANIFEST
> state, where it completes its reprogramming operations."
> 
> - when stepping into dfuManifest state, sending a PollTimeout
>   DFU_MANIFEST_POLL_TIMEOUT in ms, to the host, so the host
>   (dfu-util) waits the PollTimeout before sending a get_status again.
> 
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Cc: Lukasz Majewski <l.majewski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
>  README                     |  5 ++++
>  drivers/dfu/dfu.c          |  1 -
>  drivers/usb/gadget/f_dfu.c | 60
> +++++++++++++++++++++++++++++++++++++++-------
> include/dfu.h              |  3 +++ 4 files changed, 59
> insertions(+), 10 deletions(-)
> 
> diff --git a/README b/README
> index 216f0c7..5076248 100644
> --- a/README
> +++ b/README
> @@ -1525,6 +1525,11 @@ The following options need to be configured:
>  		this to the maximum filesize (in bytes) for the
> buffer. Default is 4 MiB if undefined.
>  
> +		DFU_MANIFEST_POLL_TIMEOUT
> +		Poll timeout [ms], which the device sends to the
> host when
> +		entering dfuMANIFEST state. Host waits this timeout,
> before
> +		sending again an USB request to the device.
> +

Could you also add information about the DFU_DEFAULT_POLL_TIMEOUT to
the README, please (I've forgotten to do that)? 

>  - Journaling Flash filesystem support:
>  		CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF,
> CONFIG_JFFS2_NAND_SIZE, CONFIG_JFFS2_NAND_DEV
> diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
> index 193e047..f61e166 100644
> --- a/drivers/dfu/dfu.c
> +++ b/drivers/dfu/dfu.c
> @@ -222,7 +222,6 @@ int dfu_write(struct dfu_entity *dfu, void *buf,
> int size, int blk_seq_num) ret = tret;
>  	}
>  
> -	ret = dfu_flush(dfu, buf, size, blk_seq_num);
>  	return ret = 0 ? size : ret;
>  }
>  
> diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
> index a045864..f4bf918 100644
> --- a/drivers/usb/gadget/f_dfu.c
> +++ b/drivers/usb/gadget/f_dfu.c
> @@ -164,15 +164,22 @@ static void dnload_request_complete(struct
> usb_ep *ep, struct usb_request *req) 
>  	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
>  		  req->length, f_dfu->blk_seq_num);
> +}
>  
> -	if (req->length == 0)
> -		puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
> +static void dnload_request_flush(struct usb_ep *ep, struct
> usb_request *req) +{
> +	struct f_dfu *f_dfu = req->context;
> +
> +	req->length = 0;
> +	dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
> +		  req->length, f_dfu->blk_seq_num);
>  }
>  
>  static void handle_getstatus(struct usb_request *req)
>  {
>  	struct dfu_status *dstat = (struct dfu_status *)req->buf;
>  	struct f_dfu *f_dfu = req->context;
> +	int setpolltimeout = 1;

We can go away with this flag. Please see below.

>  
>  	switch (f_dfu->dfu_state) {
>  	case DFU_STATE_dfuDNLOAD_SYNC:
> @@ -180,17 +187,24 @@ static void handle_getstatus(struct usb_request
> *req) f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
>  		break;
>  	case DFU_STATE_dfuMANIFEST_SYNC:
> +		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
>  		break;
> +	case DFU_STATE_dfuMANIFEST:
> +		dfu_set_poll_timeout(dstat,
> DFU_MANIFEST_POLL_TIMEOUT);
> +		setpolltimeout = 0;
>  	default:
>  		break;
>  	}
>  
> -	dfu_set_poll_timeout(dstat, 0);
> +	if (setpolltimeout) {
> +		dfu_set_poll_timeout(dstat, 0);
>  
> -	if (f_dfu->poll_timeout)
> -		if (!(f_dfu->blk_seq_num %
> -		      (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
> -			dfu_set_poll_timeout(dstat,
> f_dfu->poll_timeout);
> +		if (f_dfu->poll_timeout)
> +			if (!(f_dfu->blk_seq_num %
> +			      (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
> +				dfu_set_poll_timeout(dstat,
> +
> f_dfu->poll_timeout);
> +	}

What about this solution:

	dfu_set_poll_timeout(dstat, 0);

	switch (f_dfu->dfu_state) {
	case DFU_STATE_dfuDNLOAD_SYNC:
	case DFU_STATE_dfuDNBUSY:
		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
		break;
	case DFU_STATE_dfuMANIFEST_SYNC:
		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
		break;
	case DFU_STATE_dfuMANIFEST:
		dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT);
	default:
		break;
	}

	if (f_dfu->poll_timeout)
		if (!(f_dfu->blk_seq_num %
		      (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
			dfu_set_poll_timeout(dstat,f_dfu->poll_timeout);

Then we could avoid setpolltimeout flag.

>  
>  	/* send status response */
>  	dstat->bStatus = f_dfu->dfu_status;
> @@ -446,10 +460,11 @@ static int state_dfu_manifest_sync(struct f_dfu
> *f_dfu, switch (ctrl->bRequest) {
>  	case USB_REQ_DFU_GETSTATUS:
>  		/* We're MainfestationTolerant */
> -		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
> +		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
>  		handle_getstatus(req);
>  		f_dfu->blk_seq_num = 0;
>  		value = RET_STAT_LEN;
> +		req->complete = dnload_request_flush;
>  		break;
>  	case USB_REQ_DFU_GETSTATE:
>  		handle_getstate(req);
> @@ -463,6 +478,33 @@ static int state_dfu_manifest_sync(struct f_dfu
> *f_dfu, return value;
>  }
>  
> +static int state_dfu_manifest(struct f_dfu *f_dfu,
> +			      const struct usb_ctrlrequest *ctrl,
> +			      struct usb_gadget *gadget,
> +			      struct usb_request *req)
> +{
> +	int value = 0;
> +
> +	switch (ctrl->bRequest) {
> +	case USB_REQ_DFU_GETSTATUS:
> +		/* We're MainfestationTolerant */

Please look into the comments globally - we do now support the
DFU_STATE_dfuMANIFEST_* states

> +		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
> +		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:
> +		handle_getstate(req);
> +		break;
> +	default:
> +		f_dfu->dfu_state = DFU_STATE_dfuERROR;
> +		value = RET_STALL;
> +		break;
> +	}
> +	return value;
> +}
> +
>  static int state_dfu_upload_idle(struct f_dfu *f_dfu,
>  				 const struct usb_ctrlrequest *ctrl,
>  				 struct usb_gadget *gadget,
> @@ -539,7 +581,7 @@ static dfu_state_fn dfu_state[] = {
>  	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
>  	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
>  	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
> -	NULL,                    /* DFU_STATE_dfuMANIFEST */
> +	state_dfu_manifest,	 /* DFU_STATE_dfuMANIFEST */
>  	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
>  	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
>  	state_dfu_error          /* DFU_STATE_dfuERROR */
> diff --git a/include/dfu.h b/include/dfu.h
> index 272a245..6c71ecb 100644
> --- a/include/dfu.h
> +++ b/include/dfu.h
> @@ -80,6 +80,9 @@ static inline unsigned int get_mmc_blk_size(int dev)
>  #ifndef DFU_DEFAULT_POLL_TIMEOUT
>  #define DFU_DEFAULT_POLL_TIMEOUT 0
>  #endif
> +#ifndef DFU_MANIFEST_POLL_TIMEOUT
> +#define DFU_MANIFEST_POLL_TIMEOUT	DFU_DEFAULT_POLL_TIMEOUT
> +#endif
>  
>  struct dfu_entity {
>  	char			name[DFU_NAME_SIZE];

I did some preliminary DFU testing and it seems to not introduce any
regressions. 

I'm looking forward for v2.

-- 
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

  reply	other threads:[~2014-03-14 10:47 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-12 10:01 [U-Boot] [PATCH 0/3] usb: dfu: introduce dfuMANIFEST state Heiko Schocher
2014-03-12 10:01 ` [U-Boot] [PATCH 1/3] usb, dfu: extract flush code into seperate function Heiko Schocher
2014-03-12 11:43   ` Marek Vasut
2014-03-13  5:31     ` Heiko Schocher
2014-03-13 12:38       ` Marek Vasut
2014-03-14 10:36       ` Lukasz Majewski
2014-03-12 10:01 ` [U-Boot] [PATCH 2/3] usb: dfu: introduce dfuMANIFEST state Heiko Schocher
2014-03-14 10:47   ` Lukasz Majewski [this message]
2014-03-17  6:34     ` Heiko Schocher
2014-03-17  9:46       ` Lukasz Majewski
2014-03-17 10:11         ` Heiko Schocher
2014-03-17 10:42           ` Lukasz Majewski
2014-03-12 10:01 ` [U-Boot] [PATCH 3/3] am335x, dfu: add DFU_MANIFEST_POLL_TIMEOUT to the siemens boards Heiko Schocher
2014-03-14 10:48   ` Lukasz Majewski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140314114749.285b3a09@amdc2363 \
    --to=l.majewski@samsung.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox