mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
usb: dfu: introduce dfuMANIFEST state
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> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
This commit is contained in:
parent
a2199afea1
commit
001a831986
4 changed files with 55 additions and 10 deletions
10
README
10
README
|
@ -1525,6 +1525,16 @@ The following options need to be configured:
|
||||||
this to the maximum filesize (in bytes) for the buffer.
|
this to the maximum filesize (in bytes) for the buffer.
|
||||||
Default is 4 MiB if undefined.
|
Default is 4 MiB if undefined.
|
||||||
|
|
||||||
|
DFU_DEFAULT_POLL_TIMEOUT
|
||||||
|
Poll timeout [ms], is the timeout a device can send to the
|
||||||
|
host. The host must wait for this timeout before sending
|
||||||
|
a subsequent DFU_GET_STATUS request to the device.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
- Journaling Flash filesystem support:
|
- Journaling Flash filesystem support:
|
||||||
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
|
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
|
||||||
CONFIG_JFFS2_NAND_DEV
|
CONFIG_JFFS2_NAND_DEV
|
||||||
|
|
|
@ -218,10 +218,6 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
|
||||||
ret = tret;
|
ret = tret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end? */
|
|
||||||
if (size == 0)
|
|
||||||
ret = dfu_flush(dfu, buf, size, blk_seq_num);
|
|
||||||
|
|
||||||
return ret = 0 ? size : ret;
|
return ret = 0 ? size : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,9 +164,14 @@ static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
|
||||||
|
|
||||||
dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
|
dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
|
||||||
req->length, f_dfu->blk_seq_num);
|
req->length, f_dfu->blk_seq_num);
|
||||||
|
}
|
||||||
|
|
||||||
if (req->length == 0)
|
static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
|
||||||
puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
|
{
|
||||||
|
struct f_dfu *f_dfu = req->context;
|
||||||
|
|
||||||
|
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)
|
static void handle_getstatus(struct usb_request *req)
|
||||||
|
@ -174,19 +179,22 @@ static void handle_getstatus(struct usb_request *req)
|
||||||
struct dfu_status *dstat = (struct dfu_status *)req->buf;
|
struct dfu_status *dstat = (struct dfu_status *)req->buf;
|
||||||
struct f_dfu *f_dfu = req->context;
|
struct f_dfu *f_dfu = req->context;
|
||||||
|
|
||||||
|
dfu_set_poll_timeout(dstat, 0);
|
||||||
|
|
||||||
switch (f_dfu->dfu_state) {
|
switch (f_dfu->dfu_state) {
|
||||||
case DFU_STATE_dfuDNLOAD_SYNC:
|
case DFU_STATE_dfuDNLOAD_SYNC:
|
||||||
case DFU_STATE_dfuDNBUSY:
|
case DFU_STATE_dfuDNBUSY:
|
||||||
f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
|
f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
|
||||||
break;
|
break;
|
||||||
case DFU_STATE_dfuMANIFEST_SYNC:
|
case DFU_STATE_dfuMANIFEST_SYNC:
|
||||||
|
f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
|
||||||
break;
|
break;
|
||||||
|
case DFU_STATE_dfuMANIFEST:
|
||||||
|
dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfu_set_poll_timeout(dstat, 0);
|
|
||||||
|
|
||||||
if (f_dfu->poll_timeout)
|
if (f_dfu->poll_timeout)
|
||||||
if (!(f_dfu->blk_seq_num %
|
if (!(f_dfu->blk_seq_num %
|
||||||
(dfu_get_buf_size() / DFU_USB_BUFSIZ)))
|
(dfu_get_buf_size() / DFU_USB_BUFSIZ)))
|
||||||
|
@ -446,10 +454,11 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
|
||||||
switch (ctrl->bRequest) {
|
switch (ctrl->bRequest) {
|
||||||
case USB_REQ_DFU_GETSTATUS:
|
case USB_REQ_DFU_GETSTATUS:
|
||||||
/* We're MainfestationTolerant */
|
/* We're MainfestationTolerant */
|
||||||
f_dfu->dfu_state = DFU_STATE_dfuIDLE;
|
f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
|
||||||
handle_getstatus(req);
|
handle_getstatus(req);
|
||||||
f_dfu->blk_seq_num = 0;
|
f_dfu->blk_seq_num = 0;
|
||||||
value = RET_STAT_LEN;
|
value = RET_STAT_LEN;
|
||||||
|
req->complete = dnload_request_flush;
|
||||||
break;
|
break;
|
||||||
case USB_REQ_DFU_GETSTATE:
|
case USB_REQ_DFU_GETSTATE:
|
||||||
handle_getstate(req);
|
handle_getstate(req);
|
||||||
|
@ -463,6 +472,33 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
|
||||||
return value;
|
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 */
|
||||||
|
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,
|
static int state_dfu_upload_idle(struct f_dfu *f_dfu,
|
||||||
const struct usb_ctrlrequest *ctrl,
|
const struct usb_ctrlrequest *ctrl,
|
||||||
struct usb_gadget *gadget,
|
struct usb_gadget *gadget,
|
||||||
|
@ -539,7 +575,7 @@ static dfu_state_fn dfu_state[] = {
|
||||||
state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */
|
state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */
|
||||||
state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */
|
state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */
|
||||||
state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
|
state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
|
||||||
NULL, /* DFU_STATE_dfuMANIFEST */
|
state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */
|
||||||
NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */
|
NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */
|
||||||
state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */
|
state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */
|
||||||
state_dfu_error /* DFU_STATE_dfuERROR */
|
state_dfu_error /* DFU_STATE_dfuERROR */
|
||||||
|
|
|
@ -80,6 +80,9 @@ static inline unsigned int get_mmc_blk_size(int dev)
|
||||||
#ifndef DFU_DEFAULT_POLL_TIMEOUT
|
#ifndef DFU_DEFAULT_POLL_TIMEOUT
|
||||||
#define DFU_DEFAULT_POLL_TIMEOUT 0
|
#define DFU_DEFAULT_POLL_TIMEOUT 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef DFU_MANIFEST_POLL_TIMEOUT
|
||||||
|
#define DFU_MANIFEST_POLL_TIMEOUT DFU_DEFAULT_POLL_TIMEOUT
|
||||||
|
#endif
|
||||||
|
|
||||||
struct dfu_entity {
|
struct dfu_entity {
|
||||||
char name[DFU_NAME_SIZE];
|
char name[DFU_NAME_SIZE];
|
||||||
|
|
Loading…
Reference in a new issue