summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMengsk <[email protected]>2021-07-05 17:56:21 +0200
committerMengsk <[email protected]>2021-07-05 17:56:21 +0200
commitc2d8ed3fd1fdb722d67a30a6768720c9ed578779 (patch)
tree3cafa16736a498e689ea25f42635b18db62ae762 /src
parent2ae19ce40dec5aa13d9eca9b990aa704c2579581 (diff)
Add alt settings support in DFU class.
Diffstat (limited to 'src')
-rw-r--r--src/class/dfu/dfu_device.c46
-rw-r--r--src/class/dfu/dfu_device.h10
-rw-r--r--src/device/usbd.h8
3 files changed, 40 insertions, 24 deletions
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)