summaryrefslogtreecommitdiff
path: root/common/usbx_device_classes
diff options
context:
space:
mode:
Diffstat (limited to 'common/usbx_device_classes')
-rw-r--r--common/usbx_device_classes/CMakeLists.txt2
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_audio10.h6
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_audio20.h6
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_cdc_acm.h9
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_dfu.h55
-rw-r--r--common/usbx_device_classes/src/ux_device_class_audio10_control_process.c7
-rw-r--r--common/usbx_device_classes/src/ux_device_class_audio20_control_process.c7
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c10
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c10
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c120
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c135
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c17
-rw-r--r--common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c15
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_activate.c10
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_control_request.c627
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c36
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_initialize.c28
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_state_get.c73
-rw-r--r--common/usbx_device_classes/src/ux_device_class_dfu_state_sync.c97
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_thread.c8
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. */