diff options
| author | Mengsk <[email protected]> | 2021-07-05 17:56:21 +0200 |
|---|---|---|
| committer | Mengsk <[email protected]> | 2021-07-05 17:56:21 +0200 |
| commit | c2d8ed3fd1fdb722d67a30a6768720c9ed578779 (patch) | |
| tree | 3cafa16736a498e689ea25f42635b18db62ae762 | |
| parent | 2ae19ce40dec5aa13d9eca9b990aa704c2579581 (diff) | |
Add alt settings support in DFU class.
| -rw-r--r-- | examples/device/dfu/src/main.c | 25 | ||||
| -rw-r--r-- | examples/device/dfu/src/usb_descriptors.c | 8 | ||||
| -rw-r--r-- | src/class/dfu/dfu_device.c | 46 | ||||
| -rw-r--r-- | src/class/dfu/dfu_device.h | 10 | ||||
| -rw-r--r-- | src/device/usbd.h | 8 |
5 files changed, 56 insertions, 41 deletions
diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1c09066a8..81532ee90 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -115,25 +115,20 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -// Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_runtime_reboot_to_dfu_cb(void) -{ - blink_interval_ms = BLINK_DFU_MODE; -} - //--------------------------------------------------------------------+ // Class callbacks //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(void) +bool tud_dfu_firmware_valid_check_cb(uint8_t alt) { + (void) alt; printf(" Firmware check\r\n"); return true; } -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; i<length; i++) @@ -145,8 +140,9 @@ void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t leng tud_dfu_dnload_complete(); } -bool tud_dfu_device_data_done_check_cb(void) +bool tud_dfu_device_data_done_check_cb(uint8_t alt) { + (void) alt; printf(" Host said no more data... Returning true\r\n"); return true; } @@ -156,15 +152,16 @@ void tud_dfu_abort_cb(void) printf(" Host aborted transfer\r\n"); } -#define UPLOAD_SIZE (29) -const uint8_t upload_test[UPLOAD_SIZE] = "Hello world from TinyUSB DFU!"; +#define UPLOAD_SIZE 43 +const uint8_t upload_test[2][UPLOAD_SIZE] = {"Hello world from TinyUSB DFU! - Partition 0", + "Hello world from TinyUSB DFU! - Partition 1"}; -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length) +uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) { (void) block_num; (void) length; - memcpy(data, upload_test, UPLOAD_SIZE); + memcpy(data, upload_test[alt], UPLOAD_SIZE); return UPLOAD_SIZE; } diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 8ad64354b..9565da9b2 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -97,7 +97,8 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -120,7 +121,8 @@ char const* string_desc_arr [] = "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product "123456", // 3: Serials, should use chip ID - "TinyUSB DFU", // 4: DFU + "FLASH", // 4: DFU Partition 1 + "EEPROM", // 5: DFU Partition 2 }; static uint16_t _desc_str[32]; diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index c696d70a2..0570b5958 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,6 +46,7 @@ typedef struct TU_ATTR_PACKED dfu_state_t state; uint8_t attrs; bool blk_transfer_in_proc; + uint8_t alt; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -165,22 +166,29 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, (void) rhport; (void) max_len; - // Ensure this is DFU Mode - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + uint16_t drv_len = 0; + uint8_t const * p_desc = (uint8_t*)itf_desc; - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + while (max_len) { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - + // Ensure this is DFU Mode + TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); + + p_desc = tu_desc_next( p_desc ); drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + max_len -= drv_len; + } return drv_len; } @@ -200,6 +208,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && TUSB_REQ_SET_INTERFACE == request->bRequest ) { + // Save Alt interface + _dfu_state_ctx.alt = request->wValue; tud_control_status(rhport, request); return true; } @@ -248,7 +258,11 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + uint16_t retval = 0; + if (tud_dfu_req_upload_data_cb) + { + tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -285,7 +299,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -426,7 +440,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb() ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -481,7 +495,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb() ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 9a09a46b1..d5bc88ab2 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -39,13 +39,14 @@ //--------------------------------------------------------------------+ // Invoked during DFU_MANIFEST_SYNC get status request to check if firmware // is valid -bool tud_dfu_firmware_valid_check_cb(void); +bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data // provided by tud_dfu_req_dnload_data_cb @@ -56,7 +57,7 @@ void tud_dfu_dnload_complete(void); // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(void); +bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer TU_ATTR_WEAK void tud_dfu_abort_cb(void); @@ -64,7 +65,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..41c78de10 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -603,11 +603,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Length of template descriptr: 18 bytes #define TUD_DFU_MODE_DESC_LEN (9 + 9) -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ +// DFU mode descriptor +// Interface number, alt settings, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 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) |
