diff options
Diffstat (limited to 'common/usbx_device_classes')
20 files changed, 919 insertions, 359 deletions
diff --git a/common/usbx_device_classes/CMakeLists.txt b/common/usbx_device_classes/CMakeLists.txt index 10f9996..0cf623a 100644 --- a/common/usbx_device_classes/CMakeLists.txt +++ b/common/usbx_device_classes/CMakeLists.txt @@ -52,6 +52,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_deactivate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_state_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_state_sync.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_control_request.c diff --git a/common/usbx_device_classes/inc/ux_device_class_audio10.h b/common/usbx_device_classes/inc/ux_device_class_audio10.h index add1f9e..e03003f 100644 --- a/common/usbx_device_classes/inc/ux_device_class_audio10.h +++ b/common/usbx_device_classes/inc/ux_device_class_audio10.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_audio10.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +43,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added volume RES support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -341,6 +344,7 @@ typedef struct UX_DEVICE_CLASS_AUDIO10_CONTROL_STRUCT USHORT ux_device_class_audio10_control_mute[1]; SHORT ux_device_class_audio10_control_volume_min[1]; SHORT ux_device_class_audio10_control_volume_max[1]; + USHORT ux_device_class_audio10_control_volume_res[1]; SHORT ux_device_class_audio10_control_volume[1]; } UX_DEVICE_CLASS_AUDIO10_CONTROL; diff --git a/common/usbx_device_classes/inc/ux_device_class_audio20.h b/common/usbx_device_classes/inc/ux_device_class_audio20.h index f55df76..058657d 100644 --- a/common/usbx_device_classes/inc/ux_device_class_audio20.h +++ b/common/usbx_device_classes/inc/ux_device_class_audio20.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_audio20.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +43,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added volume RES support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -398,6 +401,7 @@ typedef struct UX_DEVICE_CLASS_AUDIO20_CONTROL_STRUCT USHORT ux_device_class_audio20_control_mute[1]; SHORT ux_device_class_audio20_control_volume_min[1]; SHORT ux_device_class_audio20_control_volume_max[1]; + USHORT ux_device_class_audio20_control_volume_res[1]; SHORT ux_device_class_audio20_control_volume[1]; } UX_DEVICE_CLASS_AUDIO20_CONTROL; diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h index 3934fc9..eb8840c 100644 --- a/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_cdc_acm.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +44,10 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -150,6 +154,7 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT UCHAR ux_slave_class_cdc_acm_data_bit; UCHAR ux_slave_class_cdc_acm_data_dtr_state; UCHAR ux_slave_class_cdc_acm_data_rts_state; +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE UX_THREAD ux_slave_class_cdc_acm_bulkin_thread; UX_THREAD ux_slave_class_cdc_acm_bulkout_thread; UCHAR *ux_slave_class_cdc_acm_bulkin_thread_stack; @@ -162,7 +167,7 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT ULONG ux_slave_class_cdc_acm_callback_total_length; UCHAR *ux_slave_class_cdc_acm_callback_data_pointer; UCHAR *ux_slave_class_cdc_acm_callback_current_data_pointer; - +#endif } UX_SLAVE_CLASS_CDC_ACM; /* Define some CDC Class structures */ diff --git a/common/usbx_device_classes/inc/ux_device_class_dfu.h b/common/usbx_device_classes/inc/ux_device_class_dfu.h index 10e3985..16ffde8 100644 --- a/common/usbx_device_classes/inc/ux_device_class_dfu.h +++ b/common/usbx_device_classes/inc/ux_device_class_dfu.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_dfu.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +44,12 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added DFU_UPLOAD support, */ +/* refined dfu_read prototype, */ +/* removed block count (it's */ +/* from host request wValue), */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -115,14 +121,37 @@ #define UX_SLAVE_CLASS_DFU_GET_STATUS_STRING 5 #define UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH 6 +/* Status mode for DFU_GETSTATUS + 0 - simple mode, + status is queried from application in dfuDNLOAD-SYNC and dfuMANIFEST-SYNC state, + no bwPollTimeout. + 1 - status is queried from application once requested, + b0-3 : media status + b4-7 : bStatus + b8-31: bwPollTimeout + bwPollTimeout supported. +*/ +#ifndef UX_DEVICE_CLASS_DFU_STATUS_MODE +#define UX_DEVICE_CLASS_DFU_STATUS_MODE (0) +#endif + +/* Status mode 0 bwPollTimeout (width: 3 bytes, ~0xFFFFFF). */ +#ifndef UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT +#define UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT (1) +#endif + + /* Define DFU class GET_STATE command response. */ #define UX_SLAVE_CLASS_DFU_GET_STATE_STATE 0 #define UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH 1 /* Define DFU application notification signals. */ -#define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD 1 -#define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD 2 -#define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD 3 +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD 0x1u +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD 0x2u +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD 0x3u +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_UPLOAD 0x5u +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_UPLOAD 0x6u +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_UPLOAD 0x7u /* Define DFU application notification signals. */ #define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK 0 @@ -142,10 +171,13 @@ typedef struct UX_SLAVE_CLASS_DFU_PARAMETER_STRUCT ULONG ux_slave_class_dfu_parameter_capabilities; VOID (*ux_slave_class_dfu_parameter_instance_activate)(VOID *); VOID (*ux_slave_class_dfu_parameter_instance_deactivate)(VOID *); - UINT (*ux_slave_class_dfu_parameter_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_parameter_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length); UINT (*ux_slave_class_dfu_parameter_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); UINT (*ux_slave_class_dfu_parameter_get_status)(VOID *dfu, ULONG *media_status); UINT (*ux_slave_class_dfu_parameter_notify)(VOID *dfu, ULONG notification); +#ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE + UINT (*ux_device_class_dfu_parameter_custom_request)(VOID *dfu, UX_SLAVE_TRANSFER *transfer); +#endif UCHAR *ux_slave_class_dfu_parameter_framework; ULONG ux_slave_class_dfu_parameter_framework_length; @@ -157,15 +189,15 @@ typedef struct UX_SLAVE_CLASS_DFU_STRUCT { UX_SLAVE_INTERFACE *ux_slave_class_dfu_interface; ULONG ux_slave_class_dfu_status; - ULONG ux_slave_class_dfu_state; VOID (*ux_slave_class_dfu_instance_activate)(VOID *); VOID (*ux_slave_class_dfu_instance_deactivate)(VOID *); - UINT (*ux_slave_class_dfu_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length); UINT (*ux_slave_class_dfu_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); UINT (*ux_slave_class_dfu_get_status)(VOID *dfu, ULONG *media_status); UINT (*ux_slave_class_dfu_notify)(VOID *dfu, ULONG notification); - ULONG ux_slave_class_dfu_download_block_count; - ULONG ux_slave_class_dfu_upload_block_count; +#ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE + UINT (*ux_device_class_dfu_custom_request)(VOID *dfu, UX_SLAVE_TRANSFER *transfer); +#endif UX_THREAD ux_slave_class_dfu_thread; UCHAR *ux_slave_class_dfu_thread_stack; UX_EVENT_FLAGS_GROUP ux_slave_class_dfu_event_flags_group; @@ -181,8 +213,13 @@ UINT _ux_device_class_dfu_entry(UX_SLAVE_CLASS_COMMAND *command); UINT _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command); VOID _ux_device_class_dfu_thread(ULONG dfu_class); +UCHAR _ux_device_class_dfu_state_get(UX_SLAVE_CLASS_DFU *dfu); +VOID _ux_device_class_dfu_state_sync(UX_SLAVE_CLASS_DFU *dfu); + /* Define Device DFU Class API prototypes. */ #define ux_device_class_dfu_entry _ux_device_class_dfu_entry +#define ux_device_class_dfu_state_get _ux_device_class_dfu_state_get +#define ux_device_class_dfu_state_sync _ux_device_class_dfu_state_sync #endif /* UX_DEVICE_CLASS_DFU_H */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c b/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c index 0e32334..f8091ba 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c +++ b/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio10_control_process PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added volume RES support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio10_control_process(UX_DEVICE_CLASS_AUDIO *audio, @@ -208,7 +211,7 @@ ULONG i; _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer, (USHORT) (request == UX_DEVICE_CLASS_AUDIO10_GET_MIN ? control -> ux_device_class_audio10_control_volume_min[0] : (request == UX_DEVICE_CLASS_AUDIO10_GET_MAX ? control -> ux_device_class_audio10_control_volume_max[0] : - (request == UX_DEVICE_CLASS_AUDIO10_GET_RES ? 0x0001 : + (request == UX_DEVICE_CLASS_AUDIO10_GET_RES ? UX_MAX(1, control -> ux_device_class_audio10_control_volume_res[0]) : control -> ux_device_class_audio10_control_volume[0])))); _ux_device_stack_transfer_request(transfer, 2, request_length); diff --git a/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c index a5b92f4..20fb743 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c +++ b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio20_control_process PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added volume RES support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio20_control_process(UX_DEVICE_CLASS_AUDIO *audio, @@ -271,7 +274,7 @@ ULONG i; _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 0, 1); _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 2, (USHORT)control -> ux_device_class_audio20_control_volume_min[0]); _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 4, (USHORT)control -> ux_device_class_audio20_control_volume_max[0]); - _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 6, 1); + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 6, (USHORT)UX_MAX(1, control -> ux_device_class_audio20_control_volume_res[0])); _ux_device_stack_transfer_request(transfer, 8, request_length); /* Done success. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c index b72f9be..4583a20 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c @@ -28,12 +28,14 @@ #include "ux_device_class_cdc_acm.h" #include "ux_device_stack.h" + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_bulkin_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +74,10 @@ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_acm_bulkin_thread(ULONG cdc_acm_class) @@ -213,4 +219,4 @@ ULONG sent_length; _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); } } - +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c index 4003f54..301f368 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c @@ -28,12 +28,14 @@ #include "ux_device_class_cdc_acm.h" #include "ux_device_stack.h" + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_bulkout_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +70,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG cdc_acm_class) @@ -148,4 +154,4 @@ UINT status; _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); } } - +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c index ba7c9da..1612759 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c @@ -28,12 +28,16 @@ #include "ux_device_stack.h" +#if UX_OVERFLOW_CHECK_MULC_ULONG(UX_THREAD_STACK_SIZE, 2) +#error UX_THREAD_STACK_SIZE too large +#endif + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +72,12 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* moved transmission resource */ +/* allocate to here (init), */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -136,6 +146,114 @@ UINT status; cdc_acm -> ux_slave_class_cdc_acm_parity = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY; cdc_acm -> ux_slave_class_cdc_acm_data_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT; +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + + /* We need to prepare the 2 threads for sending and receiving. */ + /* Allocate some memory for the bulk out and in thread stack. */ + cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE * 2); + + /* Check for successful allocation. */ + if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack == UX_NULL) + + /* Return the status to the caller. */ + status = (UX_MEMORY_INSUFFICIENT); + + /* If success, go on to create event flags. */ + if (status == UX_SUCCESS) + { + + /* Allocate some memory for the bulk in thread stack. */ + cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack = + cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack + UX_THREAD_STACK_SIZE; + + /* Create a event flag group for the cdc_acm class to synchronize with the application writing event . */ + status = _ux_utility_event_flags_create( + &cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, + "ux_device_class_cdc_acm_event_flag"); + + /* Check status. */ + if (status != UX_SUCCESS) + { + status = (UX_EVENT_ERROR); + } + } + + /* If success, go on to create bulkin thread. */ + if (status == UX_SUCCESS) + { + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create( + &cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread, + "ux_slave_class_cdc_acm_bulkin_thread", + _ux_device_class_cdc_acm_bulkin_thread, + (ULONG) (ALIGN_TYPE) cdc_acm, + (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + { + status = (UX_THREAD_ERROR); + } + else + { + UX_THREAD_EXTENSION_PTR_SET( + &(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread), cdc_acm) + } + } + + /* If success, go on to create bulkout thread. */ + if (status == UX_SUCCESS) + { + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create( + &cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread, + "ux_slave_class_cdc_acm_bulkout_thread", + _ux_device_class_cdc_acm_bulkout_thread, + (ULONG) (ALIGN_TYPE) cdc_acm, + (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + { + status = (UX_THREAD_ERROR); + } + else + { + UX_THREAD_EXTENSION_PTR_SET( + &(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread), cdc_acm) + } + } + + /* Check error. */ + if (status != UX_SUCCESS) + { + + /* Free resources and return error. */ + if (cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread.tx_thread_id) + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + if (cdc_acm -> ux_slave_class_cdc_acm_event_flags_group.tx_event_flags_group_id) + _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack) + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack); + _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + _ux_utility_memory_free(cdc_acm); + return(status); + } + +#endif + /* Return completion status. */ return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c index 8c42688..2d8dd0a 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c @@ -79,6 +79,12 @@ /* 03-02-2021 Xiuwen Cai Modified comment(s), removed */ /* unreachable statement, */ /* resulting in version 6.1.5 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* moved transmission resource */ +/* management to init/uninit, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_ioctl(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, @@ -230,8 +236,9 @@ UX_SLAVE_TRANSFER *transfer_request; break; - case UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_START: +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_START: /* Check if we are in callback transmission already. */ if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) @@ -244,108 +251,16 @@ UX_SLAVE_TRANSFER *transfer_request; /* Properly cast the parameter pointer. */ callback = (UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER *) parameter; - /* We need to start the 2 threads for sending and receiving. */ - /* Allocate some memory for the bulk out thread stack. */ - cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack = - _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); - - /* Check for successful allocation. */ - if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack == UX_NULL) - { - - /* Return the status to the caller. */ - return(UX_MEMORY_INSUFFICIENT); - } - - /* Allocate some memory for the bulk in thread stack. */ - cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack = - _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); - - /* Check for successful allocation. */ - if (cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack == UX_NULL) - { - - /* Free resources. */ - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); - - /* Return the status to the caller. */ - return(UX_MEMORY_INSUFFICIENT); - } - - /* Create a event flag group for the cdc_acm class to synchronize with the application writing event . */ - status = _ux_utility_event_flags_create(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, "ux_device_class_cdc_acm_event_flag"); - - /* Check status. */ - if (status != UX_SUCCESS) - { - - /* Free resources. */ - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); - - /* Do not proceed. */ - return(UX_EVENT_ERROR); - } - - /* Bulk endpoint treatment needs to be running in a different thread. So start - a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread - does not start until we have a instance of the class. */ - status = _ux_utility_thread_create(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread , "ux_slave_class_cdc_acm_bulkin_thread", - _ux_device_class_cdc_acm_bulkin_thread, - (ULONG) (ALIGN_TYPE) cdc_acm, (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack , - UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, - UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_AUTO_START); - - /* Check the creation of this thread. */ - if (status != UX_SUCCESS) - { - - /* Delete the event flag group for the acm class. */ - _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); - - /* Free some of the resource used. */ - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); - - return(UX_THREAD_ERROR); - } - - UX_THREAD_EXTENSION_PTR_SET(&(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread), cdc_acm) - - /* Bulk endpoint treatment needs to be running in a different thread. So start - a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread - does not start until we have a instance of the class. */ - status = _ux_utility_thread_create(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread , "ux_slave_class_cdc_acm_bulkout_thread", - _ux_device_class_cdc_acm_bulkout_thread, - (ULONG) (ALIGN_TYPE) cdc_acm, (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack , - UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, - UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_AUTO_START); - - /* Check the creation of this thread. */ - if (status != UX_SUCCESS) - { - - /* Delete the event flag group for the acm class. */ - _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); - - /* Delete bulk in thread. */ - _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); - - /* Free some of the resource used. */ - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); - - return(UX_THREAD_ERROR); - } - - UX_THREAD_EXTENSION_PTR_SET(&(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread), cdc_acm) - /* Save the callback function for write. */ cdc_acm -> ux_device_class_cdc_acm_write_callback = callback -> ux_device_class_cdc_acm_parameter_write_callback; /* Save the callback function for read. */ cdc_acm -> ux_device_class_cdc_acm_read_callback = callback -> ux_device_class_cdc_acm_parameter_read_callback; + /* Start transmission threads. */ + _ux_utility_thread_resume(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_utility_thread_resume(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + /* Declare the transmission with callback on. */ cdc_acm -> ux_slave_class_cdc_acm_transmission_status = UX_TRUE; @@ -367,40 +282,21 @@ UX_SLAVE_TRANSFER *transfer_request; /* Get the transfer request associated with the endpoint. */ transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; - /* Check the status of the transfer. */ - if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) - { - /* Abort the transfer. */ _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - } - /* Next endpoint. */ endpoint = endpoint -> ux_slave_endpoint_next_endpoint; /* Get the transfer request associated with the endpoint. */ transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; - /* Check the status of the transfer. */ - if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) - { - /* Abort the transfer. */ _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - } - - /* Terminate threads. */ - _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); - _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); - - /* Free resources. */ - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); - _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); - - /* Delete the event flag group for the acm class. */ - _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + /* Suspend threads. */ + _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); /* Clear scheduled write flag. */ cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; @@ -414,6 +310,7 @@ UX_SLAVE_TRANSFER *transfer_request; return(UX_ERROR); break; +#endif default: diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c index fc7742c..3df8ba9 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_uninitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,12 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* moved transmission resource */ +/* free to here (uninit), */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -91,6 +97,15 @@ UX_SLAVE_CLASS *class; /* Out Mutex. */ _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + + /* Free resources and return error. */ + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack); +#endif + /* Free the resources. */ _ux_utility_memory_free(cdc_acm); diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c index 3aba3d2..1915a6a 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_write_with_callback PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,12 +72,21 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added macro to disable */ +/* transmission support, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, ULONG requested_length) { - +#ifdef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + UX_PARAMETER_NOT_USED(cdc_acm); + UX_PARAMETER_NOT_USED(buffer); + UX_PARAMETER_NOT_USED(requested_length); + return(UX_FUNCTION_NOT_SUPPORTED); +#else UX_SLAVE_DEVICE *device; UINT status; @@ -132,6 +141,6 @@ UINT status; /* Simply return the last function result. When we leave this function, the deferred writing has been scheduled. */ return(status); - +#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_activate.c b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c index 259a6a4..db08875 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* removed block count (it's */ +/* from host request wValue), */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -116,10 +120,6 @@ UX_SLAVE_CLASS *class; /* In the system, state the DFU state machine to DFU idle. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; - /* Reset the download/upload parameters. */ - dfu -> ux_slave_class_dfu_download_block_count = 0; - dfu -> ux_slave_class_dfu_upload_block_count = 0; - /* Set the mode to DFU mode. */ _ux_system_slave -> ux_system_slave_device_dfu_mode = UX_DEVICE_CLASS_DFU_MODE_DFU ; diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c index ebf023b..89927d7 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c @@ -11,8 +11,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device DFU Class */ /** */ @@ -29,48 +29,59 @@ #include "ux_device_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_dfu_control_request PORTABLE C */ -/* 6.1 */ +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 +static inline VOID _ux_device_class_dfu_status_get(UX_SLAVE_CLASS_DFU *, + UX_SLAVE_TRANSFER *, UCHAR, UCHAR, UCHAR, UCHAR); +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_control_request PORTABLE C */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function manages the based sent by the host on the control */ -/* endpoints with a CLASS or VENDOR SPECIFIC type. */ -/* */ -/* INPUT */ -/* */ -/* dfu Pointer to dfu class */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_endpoint_stall Endpoint stall */ -/* _ux_device_stack_transfer_request Transfer request */ -/* */ -/* CALLED BY */ -/* */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* dfu Pointer to dfu class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ /* DFU Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* used UX prefix to refer to */ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* added DFU_UPLOAD support, */ +/* removed block count (it's */ +/* from host request wValue), */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_control_request(UX_SLAVE_CLASS_COMMAND *command) @@ -82,6 +93,7 @@ UX_SLAVE_CLASS *class; UX_SLAVE_CLASS_DFU *dfu; ULONG request; +ULONG request_value; ULONG request_length; ULONG actual_length; ULONG media_status; @@ -92,80 +104,104 @@ ULONG media_status; /* Get the class container. */ class = command -> ux_slave_class_command_class_ptr; - + /* Get the storage instance from this class container. */ dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; /* Get the pointer to the transfer request associated with the control endpoint. */ transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; +#ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE + if (dfu -> ux_device_class_dfu_custom_request) + { + + /* The status simply tells us if the registered callback handled the + request - if there was an issue processing the request, it would've + stalled the control endpoint, notifying the host (and not us). */ + media_status = dfu -> ux_device_class_dfu_custom_request(dfu, transfer_request); + + /* Custom request handled. */ + if (media_status == UX_SUCCESS) + return(media_status); + + /* Try to handle with standard handler. */ + } +#endif + /* Extract all necessary fields of the request. */ request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); - /* Pickup the request length. */ + /* Pickup the request wValue. */ + request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + + /* Pickup the request wLength. */ request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); /* What state are we in ? */ - switch (_ux_system_slave -> ux_system_slave_device_dfu_state_machine) + switch (_ux_system_slave -> ux_system_slave_device_dfu_state_machine) { - + case UX_SYSTEM_DFU_STATE_APP_IDLE : /* Here we process only the request we can accept in the APP IDLE state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_DETACH : - + /* The host is asking for a Detach and switch to the DFU mode. Either we force the reset here or - we wait for a specified timer. If there is no reset while this timer is running we abandon + we wait for a specified timer. If there is no reset while this timer is running we abandon the DFU Detach.*/ if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH) { - + /* Wake up the DFU thread and send a detach request.. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); } else { /* We expect the host to issue a reset. Arm a timer in the DFU thread. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET, UX_OR); + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET, UX_OR); } /* We can switch dfu state machine. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_DETACH; - + break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : - + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_FALSE, 0, 0, 0); +#else /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); @@ -173,66 +209,71 @@ ULONG media_status; break; default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); break; } break; - + case UX_SYSTEM_DFU_STATE_APP_DETACH : /* Here we process only the request we can accept in the APP DETACH state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : - + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_FALSE, 0, 0, 0); +#else + /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); - + break; default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); break; } break; - + case UX_SYSTEM_DFU_STATE_DFU_IDLE : /* Here we process only the request we can accept in the DFU mode IDLE state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD : /* We received a DOWNLOAD command. Check the length field of the request. It cannot be 0. */ @@ -252,84 +293,117 @@ ULONG media_status; /* Have we declared a DOWNLOAD possible in our device framework ? */ if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD) { - + /* Send a notification to the application. Begin of transfer. */ dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD); - + /* Write the first block to the firmware. */ - dfu -> ux_slave_class_dfu_write(dfu, dfu -> ux_slave_class_dfu_download_block_count, + dfu -> ux_slave_class_dfu_write(dfu, request_value, transfer_request -> ux_slave_transfer_request_data_pointer, - request_length, + request_length, &actual_length); - + /* In the system, state the DFU state machine to dfu DOWNLOAD SYNC. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC; - - /* Increase the block count. */ - dfu -> ux_slave_class_dfu_download_block_count++; - + } else { - + /* Download is not accepted. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); - + /* In the system, state the DFU state machine to dfu ERROR. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; - + } } break; - + case UX_SLAVE_CLASS_DFU_COMMAND_ABORT : /* Send a notification to the application. */ dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD); - + /* In the system, state the DFU state machine to dfu IDLE. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; - - /* Reset the download/upload parameters. */ - dfu -> ux_slave_class_dfu_download_block_count = 0; - dfu -> ux_slave_class_dfu_upload_block_count = 0; - + break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : - + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_FALSE, 0, 0, 0); +#else + /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) UX_SYSTEM_DFU_STATE_DFU_IDLE; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); - + break; - + +#ifndef UX_DEVICE_CLASS_DFU_UPLOAD_DISABLE + case UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD: + + /* bitCanUpload != 1, or length = 0. */ + if (!(_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD) || + request_length == 0) + { + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + break; + } + + /* bitCanUpload = 1. */ + + /* Send a notification to the application. Begin of transfer. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_UPLOAD); + + /* Read the first block to the firmware. */ + dfu -> ux_slave_class_dfu_read(dfu, request_value, + transfer_request -> ux_slave_transfer_request_data_pointer, + request_length, + &actual_length); + + /* In the system, state the DFU state machine to dfu UPLOAD IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_UPLOAD_IDLE; + + /* We have a request to upload DFU firmware block. */ + _ux_device_stack_transfer_request(transfer_request, actual_length, request_length); + + break; +#endif + default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); @@ -340,19 +414,26 @@ ULONG media_status; } break; - + case UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC : /* Here we process only the request we can accept in the DFU mode DOWNLOAD state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_TRUE, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR); +#else + /* Check if the device is still buys performing the write. Write could be delayed. */ dfu -> ux_slave_class_dfu_get_status(dfu, &media_status); - + /* Check status of device. */ switch (media_status) { @@ -363,14 +444,14 @@ ULONG media_status; dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE; break; - + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY : - + /* Set the next state for busy but no error status. */ dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY; break; - + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR : /* Set the next state for busy and error status. */ @@ -381,36 +462,37 @@ ULONG media_status; } /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); - + break; - + default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); @@ -427,7 +509,7 @@ ULONG media_status; /* Here we process only the request we can accept in the DFU mode DNLOAD state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD : /* We received a DOWNLOAD command. Check the length field of the request. If it is 0, @@ -437,7 +519,7 @@ ULONG media_status; /* Send the notification of end of download to application. */ dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD); - + /* In the system, state the DFU state machine to DFU MANIFEST SYNCH. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC; @@ -445,70 +527,67 @@ ULONG media_status; else { - + /* Write the next block to the firmware. */ - dfu -> ux_slave_class_dfu_write(dfu, dfu -> ux_slave_class_dfu_download_block_count, + dfu -> ux_slave_class_dfu_write(dfu, request_value, transfer_request -> ux_slave_transfer_request_data_pointer, - request_length, + request_length, &actual_length); /* In the system, state the DFU state machine to dfu DOWNLOAD SYNC. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC; - - /* Increase the block count. */ - dfu -> ux_slave_class_dfu_download_block_count++; - } break; - + case UX_SLAVE_CLASS_DFU_COMMAND_ABORT : - /* Send a notification to the application. */ - dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD); - - /* In the system, state the DFU state machine to dfu IDLE. */ - _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + /* Send a notification to the application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD); + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; - /* Reset the download/upload parameters. */ - dfu -> ux_slave_class_dfu_download_block_count = 0; - dfu -> ux_slave_class_dfu_upload_block_count = 0; - break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : - + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_FALSE, 0, 0, 0); +#else + /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); - + break; - + default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); @@ -525,12 +604,30 @@ ULONG media_status; /* Here we process only the request we can accept in the MANIFEST SYNCH state. */ switch (request) { - + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : - + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_TRUE, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST, + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR); + if ((_ux_system_slave -> ux_system_slave_device_dfu_state_machine == + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET) && + (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & + UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH)) + { + + /* Wake up the DFU thread and send a detach request.. */ + _ux_utility_event_flags_set( + &dfu -> ux_slave_class_dfu_event_flags_group, + UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); + } +#else + /* Check if the device is still buys performing the write. Write could be delayed. */ dfu -> ux_slave_class_dfu_get_status(dfu, &media_status); - + /* Check status of device. */ switch (media_status) { @@ -544,21 +641,21 @@ ULONG media_status; /* Check who is responsible for the RESET. */ if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH) { - + /* Wake up the DFU thread and send a detach request.. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); } break; - + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY : - + /* Set the next state for busy but no error status. */ dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST; break; - + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR : /* Set the next state for busy and error status. */ @@ -568,58 +665,93 @@ ULONG media_status; } /* Fill the status data payload. First with status. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; /* Poll time out value is set to 1ms. */ - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; - *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); /* Next state. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* String index set to 0. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; - +#endif + /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); - + break; case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : - + /* Fill the status data payload. First with state. */ - *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; /* We have a request to obtain the status of the DFU instance. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); - + break; default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); break; } break; - + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR : /* Here we process only the request we can accept in the ERROR state. */ switch (request) { - + +#ifdef UX_DEVICE_CLASS_DFU_ERROR_GET_ENABLE + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; +#endif + case UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS : /* In the system, state the DFU state machine to dfu IDLE. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK; _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; - + break; default: - + /* Unknown function. Stall the endpoint. */ _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); break; @@ -628,6 +760,102 @@ ULONG media_status; break; +#ifndef UX_DEVICE_CLASS_DFU_UPLOAD_DISABLE + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_UPLOAD_IDLE: + + /* Here we process only the request we can accept in the DFU mode UPLOAD IDLE state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD: + + /* Length 0 case undefined, just keep state. */ + if (request_length == 0) + break; + + /* We received a UPLOAD command with length > 0. */ + + /* Read the next block from the firmware. */ + dfu -> ux_slave_class_dfu_read(dfu, request_value, + transfer_request -> ux_slave_transfer_request_data_pointer, + request_length, + &actual_length); + + /* If it's short frame, switch to dfu IDLE. */ + if (actual_length < request_length) + { + + /* Send a notification to the application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_END_UPLOAD); + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + } + + /* We have a request to upload DFU firmware block. */ + _ux_device_stack_transfer_request(transfer_request, actual_length, request_length); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_ABORT : + + /* Send a notification to the application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_UPLOAD); + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 + _ux_device_class_dfu_status_get(dfu, transfer_request, UX_FALSE, 0, 0, 0); +#else + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT); + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; +#endif + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + break; + } + + break; +#endif default: @@ -638,3 +866,58 @@ ULONG media_status; return(UX_SUCCESS); } +#if UX_DEVICE_CLASS_DFU_STATUS_MODE == 1 +static inline VOID _ux_device_class_dfu_status_get(UX_SLAVE_CLASS_DFU *dfu, + UX_SLAVE_TRANSFER *transfer, + UCHAR move_state, + UCHAR state_ok, UCHAR state_busy, UCHAR state_error) +{ +ULONG media_status = ((UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK) | + (UX_SLAVE_CLASS_DFU_STATUS_OK << 4) | + (UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT << 8)); +UCHAR *buffer = transfer -> ux_slave_transfer_request_data_pointer; +ULONG dfu_status, dfu_polltimeout; + + /* Get status from application. */ + dfu -> ux_slave_class_dfu_get_status(dfu, &media_status); + + /* Extract bStatus and bwPollTimeout. */ + dfu_status = (media_status >> 4) & 0xFu; + dfu_polltimeout = (media_status >> 8) & 0xFFFFFFu; + dfu -> ux_slave_class_dfu_status = dfu_status; + + /* Move state based on returned status. */ + if (move_state) + { + + /* OK/BUSY/ERROR ? */ + switch((media_status & 0xF)) + { + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK: + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = state_ok; + break; + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY: + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = state_busy; + break; + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR: + default: + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = state_error; + break; + } + } + + /* Fill the status data payload. First with status. */ + *buffer = (UCHAR) dfu_status; + + /* Poll time out value is set to 1ms. */ + *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(dfu_polltimeout); + *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(dfu_polltimeout); + *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(dfu_polltimeout); + + /* Next state. */ + *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c b/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c index 96132e2..dfc42d5 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,50 +66,24 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* removed endpoints aborting, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_deactivate(UX_SLAVE_CLASS_COMMAND *command) { -UX_SLAVE_INTERFACE *interface; UX_SLAVE_CLASS_DFU *dfu; -UX_SLAVE_ENDPOINT *endpoint_in; -UX_SLAVE_ENDPOINT *endpoint_out; UX_SLAVE_CLASS *class; + /* Get the class container. */ class = command -> ux_slave_class_command_class_ptr; /* Get the class instance in the container. */ dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; - /* We need the interface to the class. */ - interface = dfu -> ux_slave_class_dfu_interface; - - /* Locate the endpoints. */ - endpoint_in = interface -> ux_slave_interface_first_endpoint; - - /* Check the endpoint direction, if IN we have the correct endpoint. */ - if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) - { - - /* Wrong direction, we found the OUT endpoint first. */ - endpoint_out = endpoint_in; - - /* So the next endpoint has to be the IN endpoint. */ - endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; - } - else - { - - /* We found the endpoint IN first, so next endpoint is OUT. */ - endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; - } - - /* Terminate the transactions pending on the endpoints. */ - _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); - _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); - /* If there is a deactivate function call it. */ if (dfu -> ux_slave_class_dfu_instance_deactivate != UX_NULL) { diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c index 165fdf4..a7571e0 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,10 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* fixed max transfer size, */ +/* added max size limit check, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -111,7 +115,10 @@ ULONG descriptor_length; dfu -> ux_slave_class_dfu_write = dfu_parameter -> ux_slave_class_dfu_parameter_write; dfu -> ux_slave_class_dfu_get_status = dfu_parameter -> ux_slave_class_dfu_parameter_get_status; dfu -> ux_slave_class_dfu_notify = dfu_parameter -> ux_slave_class_dfu_parameter_notify; - +#ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE + dfu -> ux_device_class_dfu_custom_request = dfu_parameter -> ux_device_class_dfu_parameter_custom_request; +#endif + /* Store the device dfu in the project structure. */ _ux_system_slave -> ux_system_slave_dfu_framework = dfu_parameter -> ux_slave_class_dfu_parameter_framework; _ux_system_slave -> ux_system_slave_dfu_framework_length = dfu_parameter -> ux_slave_class_dfu_parameter_framework_length; @@ -122,12 +129,18 @@ ULONG descriptor_length; dfu_framework_length = _ux_system_slave -> ux_system_slave_dfu_framework_length; /* Parse the device framework and locate interfaces and endpoint descriptor(s). */ + status = UX_DESCRIPTOR_CORRUPTED; while (dfu_framework_length != 0) { /* Get the length of this descriptor. */ descriptor_length = (ULONG) *dfu_framework; + /* Length validation. */ + if (descriptor_length < 2 || + descriptor_length > dfu_framework_length) + break; + /* And its type. */ descriptor_type = *(dfu_framework + 1); @@ -141,6 +154,10 @@ ULONG descriptor_length; UX_DFU_FUNCTIONAL_DESCRIPTOR_ENTRIES, (UCHAR *) &dfu_functional_descriptor); + /* Control transfer limit validation. */ + if (dfu_functional_descriptor.wTransferSize > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + break; + /* Retrieve the DFU capabilities and store them in the system. */ _ux_system_slave -> ux_system_slave_device_dfu_capabilities = dfu_functional_descriptor.bmAttributes; @@ -148,11 +165,14 @@ ULONG descriptor_length; _ux_system_slave -> ux_system_slave_device_dfu_detach_timeout = dfu_functional_descriptor.wDetachTimeOut; /* Retrieve the DFU transfer size value. */ - _ux_system_slave -> ux_system_slave_device_dfu_transfer_size = dfu_functional_descriptor.wDetachTimeOut; - + _ux_system_slave -> ux_system_slave_device_dfu_transfer_size = dfu_functional_descriptor.wTransferSize; + /* In the system, state the DFU state machine. */ _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE; + /* DFU descriptor parsed, done. */ + status = UX_SUCCESS; + break; } /* Adjust what is left of the device framework. */ diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_state_get.c b/common/usbx_device_classes/src/ux_device_class_dfu_state_get.c new file mode 100644 index 0000000..67730ad --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_state_get.c @@ -0,0 +1,73 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_state_get PORTABLE C */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the USB DFU device state. */ +/* */ +/* INPUT */ +/* */ +/* dfu Pointer to DFU instance */ +/* */ +/* OUTPUT */ +/* */ +/* DFU state */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-02-2021 Chaoqiong Xiao Initial Version 6.1.6 */ +/* */ +/**************************************************************************/ +UCHAR _ux_device_class_dfu_state_get(UX_SLAVE_CLASS_DFU *dfu) +{ + UX_PARAMETER_NOT_USED(dfu); + return (UCHAR)_ux_system_slave -> ux_system_slave_device_dfu_state_machine; +} diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_state_sync.c b/common/usbx_device_classes/src/ux_device_class_dfu_state_sync.c new file mode 100644 index 0000000..c2e6e0d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_state_sync.c @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_state_sync PORTABLE C */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function syncs the USB DFU device state. */ +/* This allows application to move DFU state out of follow: */ +/* - dfuDNBUSY -> dfuDNLOAD-SYNC */ +/* - dfuMANIFEST -> dfuMANIFEST-SYNC */ +/* Other states will be kept. */ +/* Note the dfuDNBUSY and dfuMANIFEST is involved by returning busy */ +/* status in application ux_slave_class_dfu_get_status callback, and */ +/* needs application to issue ux_device_class_dfu_state_sync to go */ +/* out of the state. */ +/* */ +/* INPUT */ +/* */ +/* dfu Pointer to DFU instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-02-2021 Chaoqiong Xiao Initial Version 6.1.6 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_dfu_state_sync(UX_SLAVE_CLASS_DFU *dfu) +{ +UX_INTERRUPT_SAVE_AREA + + UX_PARAMETER_NOT_USED(dfu); + UX_DISABLE + switch(_ux_system_slave -> ux_system_slave_device_dfu_state_machine) + { + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY: + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_SYNC; + break; + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST: + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = + UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC; + break; + default: + break; + } + UX_RESTORE +} diff --git a/common/usbx_device_classes/src/ux_device_class_storage_thread.c b/common/usbx_device_classes/src/ux_device_class_storage_thread.c index 5f6983a..5f189f6 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_thread PORTABLE C */ -/* 6.1.3 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -103,6 +103,10 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile issues with */ +/* some macro options, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _ux_device_class_storage_thread(ULONG storage_class) @@ -351,9 +355,9 @@ UCHAR *cbw_cb; /* Special treatment of TOC command. If error, default to Stall endpoint. */ if (status == UX_SUCCESS) break; - /* fall through */ #endif + /* fall through */ default: /* The command is unknown or unsupported, so we stall the endpoint. */ |
