DFU: include more common infrastructure for download and upload handling
This commit is contained in:
parent
541bc5bdae
commit
141a11409e
|
@ -116,13 +116,16 @@ struct dfu {
|
|||
uint8_t status;
|
||||
uint32_t state;
|
||||
int past_manifest;
|
||||
unsigned int total_bytes;
|
||||
};
|
||||
|
||||
extern struct dfu dfu;
|
||||
|
||||
/* call-backs by the board/SOC */
|
||||
extern int USBDFU_handle_dnload(uint16_t val, uint16_t len, int first);
|
||||
extern int USBDFU_handle_upload(uint16_t val, uint16_t len, int first);
|
||||
extern int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
||||
uint8_t *data, unsigned int len);
|
||||
extern int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
|
||||
uint8_t *data, unsigned int req_len);
|
||||
|
||||
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
|
||||
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request);
|
||||
|
|
|
@ -41,6 +41,7 @@ static USBDDriver usbdDriver;
|
|||
__dfudata struct dfu dfu = {
|
||||
.state = DFU_STATE_appIDLE,
|
||||
.past_manifest = 0,
|
||||
.total_bytes = 0,
|
||||
};
|
||||
|
||||
static __dfufunc void handle_getstatus(void)
|
||||
|
@ -82,6 +83,119 @@ static void TerminateCtrlInWithNull(void *pArg,
|
|||
(void *) 0);
|
||||
}
|
||||
|
||||
static uint8_t dfu_buf[BOARD_DFU_PAGE_SIZE];
|
||||
|
||||
/* download of a single page has completed */
|
||||
static void dnload_cb(void *arg, unsigned char status, unsigned int transferred,
|
||||
unsigned int remaining)
|
||||
{
|
||||
int rc;
|
||||
|
||||
TRACE_DEBUG("COMPLETE\n\r");
|
||||
|
||||
if (status != USBD_STATUS_SUCCESS) {
|
||||
TRACE_ERROR("USBD download callback status %d\n\r", status);
|
||||
USBD_Stall(0);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = USBDFU_handle_dnload(0, dfu.total_bytes, dfu_buf, transferred);
|
||||
switch (rc) {
|
||||
case DFU_RET_ZLP:
|
||||
dfu.total_bytes += transferred;
|
||||
dfu.state = DFU_STATE_dfuDNLOAD_IDLE;
|
||||
TerminateCtrlInWithNull(0,0,0,0);
|
||||
break;
|
||||
case DFU_RET_STALL:
|
||||
dfu.state = DFU_STATE_dfuERROR;
|
||||
USBD_Stall(0);
|
||||
break;
|
||||
case DFU_RET_NOTHING:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int handle_dnload(uint16_t val, uint16_t len, int first)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (len > BOARD_DFU_PAGE_SIZE) {
|
||||
TRACE_ERROR("DFU length exceeds flash page size\n\r");
|
||||
dfu.state = DFU_STATE_dfuERROR;
|
||||
dfu.status = DFU_STATUS_errADDRESS;
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
if (len & 0x03) {
|
||||
TRACE_ERROR("DFU length not four-byte-aligned\n\r");
|
||||
dfu.state = DFU_STATE_dfuERROR;
|
||||
dfu.status = DFU_STATUS_errADDRESS;
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
if (first)
|
||||
dfu.total_bytes = 0;
|
||||
|
||||
if (len == 0) {
|
||||
TRACE_DEBUG("zero-size write -> MANIFEST_SYNC\n\r");
|
||||
dfu.state = DFU_STATE_dfuMANIFEST_SYNC;
|
||||
return DFU_RET_ZLP;
|
||||
}
|
||||
|
||||
/* else: actually read data */
|
||||
rc = USBD_Read(0, dfu_buf, len, &dnload_cb, 0);
|
||||
if (rc == USBD_STATUS_SUCCESS)
|
||||
return DFU_RET_NOTHING;
|
||||
else
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
/* upload of a single page has completed */
|
||||
static void upload_cb(void *arg, unsigned char status, unsigned int transferred,
|
||||
unsigned int remaining)
|
||||
{
|
||||
int rc;
|
||||
|
||||
TRACE_DEBUG("COMPLETE\n\r");
|
||||
|
||||
if (status != USBD_STATUS_SUCCESS) {
|
||||
TRACE_ERROR("USBD upload callback status %d\n\r", status);
|
||||
USBD_Stall(0);
|
||||
return;
|
||||
}
|
||||
|
||||
dfu.total_bytes += transferred;
|
||||
}
|
||||
|
||||
static int handle_upload(uint16_t val, uint16_t len, int first)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (first)
|
||||
dfu.total_bytes = 0;
|
||||
|
||||
if (len > BOARD_DFU_PAGE_SIZE) {
|
||||
TRACE_ERROR("DFU length exceeds flash page size\n\r");
|
||||
dfu.state = DFU_STATE_dfuERROR;
|
||||
dfu.status = DFU_STATUS_errADDRESS;
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
/* FIXME: altif */
|
||||
rc = USBDFU_handle_upload(0, dfu.total_bytes, dfu_buf, len);
|
||||
if (rc < 0) {
|
||||
TRACE_ERROR("application handle_upload() returned %d\n\r", rc);
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
rc = USBD_Write(0, dfu_buf, rc, &upload_cb, 0);
|
||||
if (rc == USBD_STATUS_SUCCESS)
|
||||
return DFU_RET_NOTHING;
|
||||
else
|
||||
return DFU_RET_STALL;
|
||||
}
|
||||
|
||||
/* this function gets daisy-chained into processing EP0 requests */
|
||||
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
||||
{
|
||||
|
@ -90,7 +204,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
|||
uint16_t val = USBGenericRequest_GetValue(request);
|
||||
int rc, ret;
|
||||
|
||||
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n",
|
||||
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
|
||||
USBGenericRequest_GetType(request),
|
||||
USBGenericRequest_GetRecipient(request),
|
||||
val, len);
|
||||
|
@ -166,11 +280,11 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
|||
goto out;
|
||||
}
|
||||
dfu.state = DFU_STATE_dfuDNLOAD_SYNC;
|
||||
ret = USBDFU_handle_dnload(val, len, 1);
|
||||
ret = handle_dnload(val, len, 1);
|
||||
break;
|
||||
case USB_REQ_DFU_UPLOAD:
|
||||
dfu.state = DFU_STATE_dfuUPLOAD_IDLE;
|
||||
USBDFU_handle_upload(val, len, 1);
|
||||
handle_upload(val, len, 1);
|
||||
break;
|
||||
case USB_REQ_DFU_ABORT:
|
||||
/* no zlp? */
|
||||
|
@ -221,7 +335,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
|||
switch (req) {
|
||||
case USB_REQ_DFU_DNLOAD:
|
||||
dfu.state = DFU_STATE_dfuDNLOAD_SYNC;
|
||||
ret = USBDFU_handle_dnload(val, len, 0);
|
||||
ret = handle_dnload(val, len, 0);
|
||||
break;
|
||||
case USB_REQ_DFU_ABORT:
|
||||
dfu.state = DFU_STATE_dfuIDLE;
|
||||
|
@ -284,7 +398,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
|||
switch (req) {
|
||||
case USB_REQ_DFU_UPLOAD:
|
||||
/* state transition if less data then requested */
|
||||
rc = USBDFU_handle_upload(val, len, 0);
|
||||
rc = handle_upload(val, len, 0);
|
||||
if (rc >= 0 && rc < len)
|
||||
dfu.state = DFU_STATE_dfuIDLE;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue