dfu: handle short frame result of UPLOAD in state_dfu_idle
authorPatrick Delaunay <patrick.delaunay@foss.st.com>
Wed, 13 Oct 2021 15:01:37 +0000 (17:01 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 28 Jan 2022 15:21:51 +0000 (10:21 -0500)
In DFU v1.1 specification [1] the DFU_UPLOAD (Short Frame)
is handled only in dfuUPLOADIDLE state:

- Figure A.1 Interface state transition diagram

- the state description in chapter A.2

A.2.3 State 2 dfuIDLE
  on Receipt of the DFU_UPLOAD request,and bitCanUpload = 1
  the Next State is dfuUPLOADIDLE

A.2.10 State 9 dfuUPLOAD-IDLE
  When the length of the data transferred by the device in response
  to a DFU_UPLOAD request is less than wLength. (Short frame)
  the Next State is dfuIDLE

In current code, when an UPLOAD is completely performed after the first
request (for example with wLength=200 and data read = 9), the DFU state
stay at dfuUPLOADIDLE until receiving a DFU_UPLOAD or a DFU_ABORT request
even it is unnecessary as the previous DFU_UPLOAD request already reached
the EOF.

This patch proposes to finish the DFU uploading (don't go to dfuUPLOADIDLE)
and completes the control-read operation (go to DFU_STATE_dfuIDLE) when
the first UPLOAD response has a short frame as an end of file (EOF)
indicator even if it is not explicitly allowed in the DFU specification
but this seems logical.

[1] https://www.usb.org/sites/default/files/DFU_1.1.pdf

Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
drivers/usb/gadget/f_dfu.c

index 4bedc7d..e9340ff 100644 (file)
@@ -336,6 +336,8 @@ static int state_dfu_idle(struct f_dfu *f_dfu,
                f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
                f_dfu->blk_seq_num = 0;
                value = handle_upload(req, len);
+               if (value >= 0 && value < len)
+                       f_dfu->dfu_state = DFU_STATE_dfuIDLE;
                break;
        case USB_REQ_DFU_ABORT:
                /* no zlp? */