diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d4c3ecb62f..e107b12916 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -34,6 +34,9 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +#define EP_CTR_IN 0x00 + typedef enum { DFU_REQUEST_DETACH = 0, DFU_REQUEST_DNLOAD = 1, @@ -57,11 +60,12 @@ typedef struct TU_ATTR_PACKED //--------------------------------------------------------------------+ void dfu_rtd_init(void) { + tud_dfu_rt_init(); } void dfu_rtd_reset(uint8_t rhport) { - (void) rhport; + tud_dfu_rt_reset(rhport); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -71,7 +75,8 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // Ensure this is DFU Runtime TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT || + itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -85,15 +90,6 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui return drv_len; } -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); @@ -112,30 +108,51 @@ bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * requ switch ( request->bRequest ) { case DFU_REQUEST_DETACH: - tud_control_status(rhport, request); tud_dfu_rt_reboot_to_dfu(); break; - case DFU_REQUEST_GETSTATUS: - { - // status = OK, poll timeout = 0, state = app idle, istring = 0 - uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; + case DFU_REQUEST_GETSTATUS: { + uint8_t error = 0; + uint8_t state = 0; + + tud_dfu_get_status(&error, &state); + // status = OK (1), poll timeout = 0 (3), state = app idle = 0 (1), istring = 0 (1) + uint8_t status_response[6] = { error, 0, 0, 0, state, 0 }; tud_control_xfer(rhport, request, status_response, sizeof(status_response)); } break; - default: return false; // stall unsupported request - } + case DFU_REQUEST_DNLOAD: { + uint8_t buffer[request->wLength]; - return true; -} + memset(buffer, 0, sizeof(buffer)); -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; + usbd_edpt_xfer(rhport, EP_CTR_IN, buffer, request->wLength); + tud_dfu_download(buffer, request->wLength); + } + break; + + case DFU_REQUEST_UPLOAD: + break; + + case DFU_REQUEST_CLRSTATUS: + tud_dfu_clear_status(); + break; + + case DFU_REQUEST_GETSTATE: { + uint8_t state = 0; + + state = tud_dfu_get_state(); + tud_control_xfer(rhport, request, &state, sizeof(state)); + } + break; + + case DFU_REQUEST_ABORT: + tud_dfu_abort(); + break; + + default: return false; // stall unsupported request + } return true; } diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 91ead88c6a..cd75aaa76f 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -57,9 +57,28 @@ typedef enum // Application Callback API (weak is optional) //--------------------------------------------------------------------+ +// Invoked to init the DFU +TU_ATTR_WEAK void tud_dfu_rt_init(void); + +// Invoked to reset the DFU +TU_ATTR_WEAK void tud_dfu_rt_reset(uint8_t rhport); + // Invoked when received new data TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention +// Invoked to get DFU status and get state +TU_ATTR_WEAK void tud_dfu_get_status(uint8_t *error, uint8_t *state); +TU_ATTR_WEAK uint8_t tud_dfu_get_state(void); + +// Invoked to clear DFU error state and get back to DFUidle +TU_ATTR_WEAK void tud_dfu_clear_status(void); + +// Invoked to abort a download +TU_ATTR_WEAK void tud_dfu_abort(void); + +// Invoked to do a download +TU_ATTR_WEAK void tud_dfu_download(uint8_t *buffer, uint16_t length); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index d1e984a0e6..cdcec275b3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -172,8 +172,8 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_rtd_reset, .open = dfu_rtd_open, .control_request = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, - .xfer_cb = dfu_rtd_xfer_cb, + .control_complete = NULL, + .xfer_cb = NULL, .sof = NULL }, #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 5338be157d..2fbf312b6a 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -371,6 +371,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//--------------- DFU ---------------// +#define TUD_DFU_DESCRIPTOR(_stridx, _attr, _timeout, _xfer_size) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, 0, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) //------------- CDC-ECM -------------//