diff options
Diffstat (limited to 'common/usbx_device_classes')
48 files changed, 2546 insertions, 256 deletions
diff --git a/common/usbx_device_classes/CMakeLists.txt b/common/usbx_device_classes/CMakeLists.txt index f3c3867..5291d4b 100644 --- a/common/usbx_device_classes/CMakeLists.txt +++ b/common/usbx_device_classes/CMakeLists.txt @@ -10,14 +10,17 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_set.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_frame_write.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_send.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_free.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_reception_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read16.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read24.c @@ -30,6 +33,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_commit.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_task_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_auto_seq_done.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_auto_seq_start.c @@ -144,9 +149,11 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_read_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_soft_reset.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_write_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkin_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkout_thread.c @@ -201,13 +208,16 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_max_payload_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_payload_free.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_thread_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_reception_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_stream_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_transmission_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_payload_commit.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_thread_entry.c # {{END_TARGET_SOURCES}} diff --git a/common/usbx_device_classes/inc/ux_device_class_audio.h b/common/usbx_device_classes/inc/ux_device_class_audio.h index 8ce47fa..4cc5be3 100644 --- a/common/usbx_device_classes/inc/ux_device_class_audio.h +++ b/common/usbx_device_classes/inc/ux_device_class_audio.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_audio.h PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,6 +59,9 @@ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* added interrupt support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -310,6 +313,17 @@ extern "C" { #define UX_DEVICE_CLASS_AUDIO_IOCTL_GET_ARG 1 +/* Define Audio Class Task states. */ +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT (UX_STATE_STEP + 2) + +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT (UX_STATE_STEP + 2) + +#define UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT (UX_STATE_STEP + 1) /* Define Audio Class callback structure. */ @@ -336,11 +350,20 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS_STRUCT typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER_STRUCT { +#if !defined(UX_DEVICE_STANDALONE) ULONG ux_device_class_audio_stream_parameter_thread_stack_size; VOID (*ux_device_class_audio_stream_parameter_thread_entry)(ULONG id); +#else + UINT (*ux_device_class_audio_stream_parameter_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); +#endif + #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) ULONG ux_device_class_audio_stream_parameter_feedback_thread_stack_size; VOID (*ux_device_class_audio_stream_parameter_feedback_thread_entry)(ULONG id); +#else + UINT (*ux_device_class_audio_stream_parameter_feedback_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); +#endif #endif UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_parameter_callbacks; @@ -386,6 +409,10 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_audio_stream_feedback_thread_stack; UX_THREAD ux_device_class_audio_stream_feedback_thread; +#else + UINT (*ux_device_class_audio_stream_feedback_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); + UINT ux_device_class_audio_stream_feedback_task_state; + UINT ux_device_class_audio_stream_feedback_task_status; #endif #endif @@ -394,11 +421,16 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_audio_stream_thread_stack; UX_THREAD ux_device_class_audio_stream_thread; +#else + UINT (*ux_device_class_audio_stream_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); + UINT ux_device_class_audio_stream_task_state; + UINT ux_device_class_audio_stream_task_status; #endif UCHAR *ux_device_class_audio_stream_buffer; ULONG ux_device_class_audio_stream_buffer_size; ULONG ux_device_class_audio_stream_frame_buffer_size; + ULONG ux_device_class_audio_stream_buffer_error_count; UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_transfer_pos; UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_access_pos; @@ -429,6 +461,9 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STRUCT #if !defined(UX_DEVICE_STANDALONE) UX_SEMAPHORE ux_device_class_audio_status_semaphore; UX_MUTEX ux_device_class_audio_status_mutex; +#else + UINT ux_device_class_audio_interrupt_task_state; + UINT ux_device_class_audio_interrupt_task_status; #endif #endif } UX_DEVICE_CLASS_AUDIO; @@ -452,7 +487,8 @@ UINT _ux_device_class_audio_stream_get(UX_DEVICE_CLASS_AUDIO *audio, ULONG st VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream); VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream); - +UINT _ux_device_class_audio_write_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); +UINT _ux_device_class_audio_read_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *audio); UINT _ux_device_class_audio_sample_read8(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *sample); UINT _ux_device_class_audio_sample_read16(UX_DEVICE_CLASS_AUDIO_STREAM *audio, USHORT *sample); @@ -469,13 +505,18 @@ UINT _ux_device_class_audio_write_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *aud UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM *audio, ULONG length); VOID _ux_device_class_audio_feedback_thread_entry(ULONG audio_stream); +UINT _ux_device_class_audio_feedback_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); UINT _ux_device_class_audio_feedback_set(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *encoded_feedback); UINT _ux_device_class_audio_feedback_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *encoded_feedback); ULONG _ux_device_class_audio_speed_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio); VOID _ux_device_class_audio_interrupt_thread_entry(ULONG audio_inst); +UINT _ux_device_class_audio_interrupt_task_function(UX_DEVICE_CLASS_AUDIO *audio); UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data); +#if defined(UX_DEVICE_STANDALONE) +UINT _ux_device_class_audio_tasks_run(VOID *instance); +#endif /* Define Device Class Audio API prototypes. */ @@ -484,6 +525,9 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA #define ux_device_class_audio_read_thread_entry _ux_device_class_audio_read_thread_entry #define ux_device_class_audio_write_thread_entry _ux_device_class_audio_write_thread_entry +#define ux_device_class_audio_read_task_function _ux_device_class_audio_read_task_function +#define ux_device_class_audio_write_task_function _ux_device_class_audio_write_task_function + #define ux_device_class_audio_stream_get _ux_device_class_audio_stream_get #define ux_device_class_audio_reception_start _ux_device_class_audio_reception_start @@ -505,6 +549,7 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA #define ux_device_class_audio_speed_get _ux_device_class_audio_speed_get #define ux_device_class_audio_feedback_thread_entry _ux_device_class_audio_feedback_thread_entry +#define ux_device_class_audio_feedback_task_function _ux_device_class_audio_feedback_task_function #define ux_device_class_audio_feedback_get _ux_device_class_audio_feedback_get #define ux_device_class_audio_feedback_set _ux_device_class_audio_feedback_set diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h index 3f662d8..54f3ac7 100644 --- a/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_cdc_ecm.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added wait definitions, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -274,6 +277,12 @@ VOID _ux_network_driver_link_down(VOID *ux_network_handle); #define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT 1000 #endif +#ifndef UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT +#define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT 1000 +#endif + +#define UX_DEVICE_CLASS_CDC_ECM_LINK_CHECK_WAIT 10 + /* Define Slave CDC_ECM Class Calling Parameter structure */ typedef struct UX_SLAVE_CLASS_CDC_ECM_PARAMETER_STRUCT @@ -316,7 +325,6 @@ typedef struct UX_SLAVE_CLASS_CDC_ECM_STRUCT UCHAR ux_slave_class_cdc_ecm_remote_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; ULONG ux_slave_class_cdc_ecm_nx_ip_address; ULONG ux_slave_class_cdc_ecm_nx_ip_network_mask; - UCHAR *ux_slave_class_cdc_ecm_pool_memory; #if !defined(UX_DEVICE_STANDALONE) NX_IP *ux_slave_class_cdc_ecm_nx_ip; @@ -324,7 +332,7 @@ typedef struct UX_SLAVE_CLASS_CDC_ECM_STRUCT NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue; NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue_tail; NX_PACKET *ux_slave_class_cdc_ecm_receive_queue; - NX_PACKET_POOL ux_slave_class_cdc_ecm_packet_pool; + NX_PACKET_POOL *ux_slave_class_cdc_ecm_packet_pool; #endif #if !defined(UX_DEVICE_STANDALONE) diff --git a/common/usbx_device_classes/inc/ux_device_class_printer.h b/common/usbx_device_classes/inc/ux_device_class_printer.h index a77aff5..52ae8ce 100644 --- a/common/usbx_device_classes/inc/ux_device_class_printer.h +++ b/common/usbx_device_classes/inc/ux_device_class_printer.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_printer.h PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* resulting in version 6.1.11 */ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -92,6 +95,16 @@ extern "C" { #define UX_DEVICE_CLASS_PRINTER_IOCTL_READ_TIMEOUT_SET 2 #define UX_DEVICE_CLASS_PRINTER_IOCTL_WRITE_TIMEOUT_SET 3 +#if defined(UX_DEVICE_STANDALONE) + +/* Printer read state machine states. */ +#define UX_DEVICE_CLASS_PRINTER_READ_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_PRINTER_READ_WAIT (UX_STATE_STEP + 2) + +/* Printer write state machine states. */ +#define UX_DEVICE_CLASS_PRINTER_WRITE_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_PRINTER_WRITE_WAIT (UX_STATE_STEP + 2) +#endif /* Define Device Printer Class Calling Parameter structure */ @@ -117,6 +130,21 @@ typedef struct UX_DEVICE_CLASS_PRINTER_STRUCT #if !defined(UX_DEVICE_STANDALONE) UX_MUTEX ux_device_class_printer_endpoint_out_mutex; UX_MUTEX ux_device_class_printer_endpoint_in_mutex; +#else + UCHAR *ux_device_class_printer_read_buffer; + ULONG ux_device_class_printer_read_requested_length; + ULONG ux_device_class_printer_read_transfer_length; + ULONG ux_device_class_printer_read_actual_length; + UINT ux_device_class_printer_read_status; + UINT ux_device_class_printer_read_state; + + UCHAR *ux_device_class_printer_write_buffer; + ULONG ux_device_class_printer_write_transfer_length; + ULONG ux_device_class_printer_write_host_length; + ULONG ux_device_class_printer_write_requested_length; + ULONG ux_device_class_printer_write_actual_length; + UINT ux_device_class_printer_write_status; + UINT ux_device_class_printer_write_state; #endif } UX_DEVICE_CLASS_PRINTER; @@ -139,7 +167,12 @@ UINT _ux_device_class_printer_read(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buf UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioctl_function, VOID *parameter); - +#if defined(UX_DEVICE_STANDALONE) +UINT _ux_device_class_printer_write_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_printer_read_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +#endif /* Define Device Printer Class API prototypes. */ @@ -148,6 +181,11 @@ UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioc #define ux_device_class_printer_write _ux_device_class_printer_write #define ux_device_class_printer_ioctl _ux_device_class_printer_ioctl +#if defined(UX_DEVICE_STANDALONE) +#define ux_device_class_printer_read_run _ux_device_class_printer_read_run +#define ux_device_class_printer_write_run _ux_device_class_printer_write_run +#endif + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/common/usbx_device_classes/inc/ux_device_class_rndis.h b/common/usbx_device_classes/inc/ux_device_class_rndis.h index 7ac55d8..abcd833 100644 --- a/common/usbx_device_classes/inc/ux_device_class_rndis.h +++ b/common/usbx_device_classes/inc/ux_device_class_rndis.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_rndis.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added wait and length DEFs, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -478,6 +481,16 @@ VOID _ux_network_driver_link_down(VOID *ux_network_handle); #define UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT 10 #endif +#ifndef UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT +#define UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT 100 +#endif + +/* Calculate message buffer length (not overflow). */ +#define UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH (UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) +#if UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH > UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#error "Error: the maximum-sized RNDIS response cannot fit inside the control endpoint's data buffer. Increase UX_SLAVE_REQUEST_DATA_MAX_LENGTH." +#endif + /* Calculate response buffer length. */ #define UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_LIST_LENGTH * 4) #define UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH) @@ -544,7 +557,6 @@ typedef struct UX_SLAVE_CLASS_RNDIS_STRUCT ULONG ux_slave_class_rndis_statistics_xmit_more_collisions; UCHAR ux_slave_class_rndis_local_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; UCHAR ux_slave_class_rndis_remote_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; - UCHAR *ux_slave_class_rndis_pool_memory; ULONG ux_slave_class_rndis_nx_ip_address; ULONG ux_slave_class_rndis_nx_ip_network_mask; @@ -553,7 +565,7 @@ typedef struct UX_SLAVE_CLASS_RNDIS_STRUCT NX_INTERFACE *ux_slave_class_rndis_nx_interface; NX_PACKET *ux_slave_class_rndis_xmit_queue; NX_PACKET *ux_slave_class_rndis_receive_queue; - NX_PACKET_POOL ux_slave_class_rndis_packet_pool; + NX_PACKET_POOL *ux_slave_class_rndis_packet_pool; #endif #if !defined(UX_DEVICE_STANDALONE) diff --git a/common/usbx_device_classes/inc/ux_device_class_video.h b/common/usbx_device_classes/inc/ux_device_class_video.h index 4c6d3e8..9851532 100644 --- a/common/usbx_device_classes/inc/ux_device_class_video.h +++ b/common/usbx_device_classes/inc/ux_device_class_video.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_video.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -41,6 +41,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -508,6 +511,12 @@ typedef struct UX_DEVICE_CLASS_VIDEO_PAYLOAD_HEADER_STRUCT #define UX_DEVICE_CLASS_VIDEO_STREAM_ERROR_CODE_STILL_IMAGE_CAPTURE_ERROR 7 +/* Define Video Class Task states. */ +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT (UX_STATE_STEP + 2) + + /* Define Video Class callback structure. */ struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT; @@ -541,8 +550,12 @@ typedef struct UX_DEVICE_CLASS_VIDEO_PAYLOAD_STRUCT typedef struct UX_DEVICE_CLASS_VIDEO_STREAM_PARAMETER_STRUCT { +#if defined(UX_DEVICE_STANDALONE) + UINT (*ux_device_class_video_stream_parameter_task_function)(struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT*); +#else ULONG ux_device_class_video_stream_parameter_thread_stack_size; VOID (*ux_device_class_video_stream_parameter_thread_entry)(ULONG id); +#endif UX_DEVICE_CLASS_VIDEO_STREAM_CALLBACKS ux_device_class_video_stream_parameter_callbacks; ULONG ux_device_class_video_stream_parameter_max_payload_buffer_size; @@ -572,8 +585,13 @@ typedef struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_video_stream_thread_stack; UX_THREAD ux_device_class_video_stream_thread; +#else + UINT (*ux_device_class_video_stream_task_function)(struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT*); + UINT ux_device_class_video_stream_task_state; + UINT ux_device_class_video_stream_task_status; #endif + ULONG ux_device_class_video_stream_buffer_error_count; UCHAR *ux_device_class_video_stream_buffer; ULONG ux_device_class_video_stream_buffer_size; ULONG ux_device_class_video_stream_payload_buffer_size; @@ -636,6 +654,9 @@ UINT _ux_device_class_video_transmission_start(UX_DEVICE_CLASS_VIDEO_STREAM * UINT _ux_device_class_video_write_payload_get(UX_DEVICE_CLASS_VIDEO_STREAM *video, UCHAR **buffer, ULONG *max_length); UINT _ux_device_class_video_write_payload_commit(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG length); +UINT _ux_device_class_video_tasks_run(VOID *instance); +UINT _ux_device_class_video_read_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream); +UINT _ux_device_class_video_write_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream); /* Define Video Class API prototypes. */ @@ -663,6 +684,9 @@ UINT _ux_device_class_video_write_payload_commit(UX_DEVICE_CLASS_VIDEO_STREAM #define ux_device_class_video_ioctl _ux_device_class_video_ioctl +#define ux_device_class_video_read_task_function _ux_device_class_video_read_task_function +#define ux_device_class_video_write_task_function _ux_device_class_video_write_task_function + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_activate.c b/common/usbx_device_classes/src/ux_device_class_audio_activate.c index 53163cf..2f9b89d 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* names conflict C++ keyword, */ /* added interrupt support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -166,6 +169,12 @@ ULONG stream_index; /* Store the class instance into the interface. */ stream_interface -> ux_slave_interface_class_instance = (VOID *)audio; +#if defined(UX_DEVICE_STANDALONE) + + /* Reset stream task state. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_state = UX_SUCCESS; +#endif } /* If there is a activate function call it. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_change.c b/common/usbx_device_classes/src/ux_device_class_audio_change.c index 35d4a3a..9ac4e67 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_change.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_change PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* rx full packet for */ /* feedback, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_change(UX_SLAVE_CLASS_COMMAND *command) @@ -137,8 +140,9 @@ ULONG endpoint_dir; /* Parse all endpoints. */ #if defined(UX_DEVICE_STANDALONE) - /* Standalone mode not supported. */ - endpoint_dir = 0; + endpoint_dir = (stream -> ux_device_class_audio_stream_task_function == + _ux_device_class_audio_read_task_function) ? + UX_ENDPOINT_OUT: UX_ENDPOINT_IN; #else endpoint_dir = (stream -> ux_device_class_audio_stream_thread.tx_thread_entry == @@ -229,6 +233,15 @@ ULONG endpoint_dir; return(UX_DESCRIPTOR_CORRUPTED); } +#if defined(UX_DEVICE_STANDALONE) + + /* Reset background transfer state. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; +#endif + + /* Now reset payload buffer error count. */ + stream -> ux_device_class_audio_stream_buffer_error_count = 0; + /* Now reset frame buffers. */ frame_buffer = stream -> ux_device_class_audio_stream_buffer; while(frame_buffer < stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) @@ -243,7 +256,7 @@ ULONG endpoint_dir; } stream -> ux_device_class_audio_stream_transfer_pos = stream -> ux_device_class_audio_stream_access_pos; -#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) && !defined(UX_DEVICE_STANDALONE) /* If feedback supported, resume the thread. */ if (stream -> ux_device_class_audio_stream_feedback_thread_stack) diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c new file mode 100644 index 0000000..8bcf857 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* 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 Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) && defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_feedback_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is background task of ISO OUT/IN (feedback of IN/OUT) */ +/* for the Audio class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to audio stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No feedback transfer running */ +/* UX_STATE_WAIT Feedback transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class (task) */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_feedback_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + +UINT status; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +ULONG transfer_length; + + + /* Get stack device instance. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get endpoint instance. */ + endpoint = stream -> ux_device_class_audio_stream_feedback; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Length is pre-set on interface alternate setting activate. */ + transfer_length = transfer -> ux_slave_transfer_request_requested_length; + + switch (stream -> ux_device_class_audio_stream_feedback_task_state) + { + case UX_STATE_RESET: + stream -> ux_device_class_audio_stream_feedback_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT; + stream -> ux_device_class_audio_stream_feedback_task_status = UX_TRANSFER_NO_ANSWER; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT: + + /* Issue transfer request. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Any error or success case. */ + if (status < UX_STATE_NEXT) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_feedback_task_status = transfer -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + stream -> ux_device_class_audio_stream_feedback_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT; + stream -> ux_device_class_audio_stream_feedback_task_status = transfer -> ux_slave_transfer_request_completion_code; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_feedback_task_status = UX_INVALID_STATE; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c index 88525f1..f71c0bd 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_feedback_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,11 +70,17 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_feedback_thread_entry(ULONG audio_stream) { - +#if defined(UX_DEVICE_STANDALONE) + UX_PARAMETER_NOT_USED(audio_stream); + return; +#else UINT status; UX_DEVICE_CLASS_AUDIO_STREAM *stream; UX_SLAVE_DEVICE *device; @@ -128,5 +134,6 @@ ULONG transfer_length; /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ _ux_utility_thread_suspend(&stream -> ux_device_class_audio_stream_feedback_thread); } +#endif } #endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_initialize.c b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c index 4887494..4ba297a 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -84,14 +84,13 @@ /* added interrupt support, */ /* refined internal logic, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UINT status = UX_SUCCESS; UX_DEVICE_CLASS_AUDIO *audio; @@ -153,8 +152,7 @@ ULONG i; audio_parameter -> ux_device_class_audio_parameter_status_size; audio -> ux_device_class_audio_status_queue_bytes = memory_size; -#if defined(UX_DEVICE_STANDALONE) -#else +#if !defined(UX_DEVICE_STANDALONE) if (UX_OVERFLOW_CHECK_ADD_ULONG(memory_size, UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE)) { _ux_utility_memory_free(audio); @@ -217,6 +215,15 @@ ULONG i; audio -> ux_device_class_audio_status_queue = (UCHAR *)audio_class -> ux_slave_class_thread_stack + UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE; +#else + audio -> ux_device_class_audio_status_queue = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (audio -> ux_device_class_audio_status_queue == UX_NULL) + { + _ux_utility_memory_free(audio); + return(UX_MEMORY_INSUFFICIENT); + } #endif #endif @@ -268,6 +275,8 @@ ULONG i; stream -> ux_device_class_audio_stream_transfer_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)stream -> ux_device_class_audio_stream_buffer; stream -> ux_device_class_audio_stream_access_pos = stream -> ux_device_class_audio_stream_transfer_pos; +#if !defined(UX_DEVICE_STANDALONE) + /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size == 0) memory_size = UX_DEVICE_CLASS_AUDIO_FEEDBACK_THREAD_STACK_SIZE; @@ -298,13 +307,19 @@ ULONG i; } UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_thread), stream) +#else + + /* Save task function for streaming. */ + stream -> ux_device_class_audio_stream_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_task_function; +#endif #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) + /* Check entry to confirm feedback is supported. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_entry) { - /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_stack_size == 0) memory_size = UX_THREAD_STACK_SIZE; @@ -336,6 +351,14 @@ ULONG i; UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_feedback_thread), stream) } +#else + if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function) + { + + /* Save task function for streaming. */ + stream -> ux_device_class_audio_stream_feedback_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function; + } +#endif #endif /* Save callbacks. */ @@ -365,6 +388,12 @@ ULONG i; &audio_parameter -> ux_device_class_audio_parameter_callbacks, sizeof(UX_DEVICE_CLASS_AUDIO_CALLBACKS)); /* Use case of memcpy is verified. */ +#if defined(UX_DEVICE_STANDALONE) + + /* Link task function. */ + audio_class -> ux_slave_class_task_function = _ux_device_class_audio_tasks_run; +#endif + /* Return completion status. */ return(UX_SUCCESS); } @@ -377,24 +406,27 @@ ULONG i; for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) { #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_audio_stream_feedback_thread_stack) { _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_feedback_thread); _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack); } #endif +#endif +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_audio_stream_thread_stack) { _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_thread); _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); } +#endif if (stream -> ux_device_class_audio_stream_buffer) _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer); stream ++; } #if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) -#if defined(UX_DEVICE_STANDALONE) -#else +#if !defined(UX_DEVICE_STANDALONE) if (audio_class -> ux_slave_class_thread_stack) { _ux_device_thread_delete(&audio_class -> ux_slave_class_thread); @@ -403,10 +435,14 @@ ULONG i; _ux_device_semaphore_delete(&audio -> ux_device_class_audio_status_semaphore); _ux_device_mutex_delete(&audio -> ux_device_class_audio_status_mutex); } +#else + if (audio -> ux_device_class_audio_status_queue) + { + _ux_utility_memory_free(audio -> ux_device_class_audio_status_queue); + } #endif #endif _ux_utility_memory_free(audio); return(status); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c index 72c51fb..eb5d438 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_interrupt_send PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data) @@ -77,11 +80,6 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA UX_PARAMETER_NOT_USED(int_data); return(UX_FUNCTION_NOT_SUPPORTED); #else -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(audio); - UX_PARAMETER_NOT_USED(int_data); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_DEVICE *device; UX_SLAVE_ENDPOINT *endpoint; @@ -169,5 +167,4 @@ ULONG i; /* Return success. */ return(UX_SUCCESS); #endif -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c new file mode 100644 index 0000000..eeac5c2 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c @@ -0,0 +1,198 @@ +/**************************************************************************/ +/* */ +/* 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 Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + +#if defined(UX_DEVICE_STANDALONE) && defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_interrupt_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is task of INTERRUPT IN from the Audio class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio instance */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* UX_STATE_IDLE No interrupt transfer running */ +/* UX_STATE_WAIT Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_stack_transfer_run Run Transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class (task) */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_interrupt_task_function(UX_DEVICE_CLASS_AUDIO *audio) +{ + +UINT status; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *buff; + + + /* Get stack device instance. */ + device = audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get endpoint instance. */ + endpoint = audio -> ux_device_class_audio_interrupt; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } + + /* No packet in queue */ + if (audio -> ux_device_class_audio_status_queued == 0) + { + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_TRANSFER_NOT_READY; + return(UX_STATE_EXIT); + } + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(audio -> ux_device_class_audio_interrupt_task_state) + { + case UX_STATE_RESET: + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_START; + audio -> ux_device_class_audio_interrupt_task_status = UX_TRANSFER_NO_ANSWER; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_INTERRUPT_START: + if (audio -> ux_device_class_audio_status_size > transfer -> ux_slave_transfer_request_transfer_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_ERROR; + return(UX_STATE_EXIT); + } + + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + audio -> ux_device_class_audio_status_tail, audio -> ux_device_class_audio_status_size); /* Use case of memcpy is verified. */ + + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT: + + /* Start frame transfer anyway. */ + status = _ux_device_stack_transfer_run(transfer, audio -> ux_device_class_audio_status_size, + audio -> ux_device_class_audio_status_size); + + /* Any error or success case. */ + if (status < UX_STATE_NEXT) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = + transfer -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + buff = audio -> ux_device_class_audio_status_tail; + buff += audio -> ux_device_class_audio_status_size; + + if (buff >= (audio -> ux_device_class_audio_status_queue + audio -> ux_device_class_audio_status_queue_bytes)) + buff = audio -> ux_device_class_audio_status_queue; + + audio -> ux_device_class_audio_status_tail = buff; + audio -> ux_device_class_audio_status_queued -= audio -> ux_device_class_audio_status_size; + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_START; + audio -> ux_device_class_audio_interrupt_task_status = + transfer -> ux_slave_transfer_request_completion_code; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_INVALID_STATE; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c new file mode 100644 index 0000000..03d43d8 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* 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 Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_read_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio stream read. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to audio stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_read_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG max_packet_size; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_audio_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, reset transfer and start polling. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT; + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Run transfer state machine. */ + max_packet_size = endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length; + status = _ux_device_stack_transfer_run(transfer, max_packet_size, max_packet_size); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Frame received, log it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = actual_length; + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_pos = 0; + _ux_utility_memory_copy(stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, + transfer -> ux_slave_transfer_request_data_pointer, + actual_length); /* Use case of memcpy is verified. */ + + /* For simple, do not advance the transfer position if there is overflow. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Check overflow! */ + if (next_frame -> ux_device_class_audio_frame_length > 0) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + else + + /* Update transfer position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c index 6046051..8af97f0 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_read_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream) @@ -133,6 +136,7 @@ ULONG actual_length; /* Error notification! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + stream -> ux_device_class_audio_stream_buffer_error_count ++; break; } @@ -159,6 +163,7 @@ ULONG actual_length; /* Error notification! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; } else diff --git a/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c index 120eb1e..078ce81 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_reception_start PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -103,7 +106,15 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length > 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start read task. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; +#else + /* Start read thread. */ _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); +#endif return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c new file mode 100644 index 0000000..2518ef2 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* 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 Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_tasks_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_audio_stream_task_function) */ +/* Run stream task */ +/* (ux_device_class_audio_stream_feedback_task_function) */ +/* Run stream feedback task */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_tasks_run(VOID *instance) +{ +UX_SLAVE_DEVICE *device; +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +ULONG stream_index; +UINT status; +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) +ULONG interrupt_running_count = 0; +#endif +ULONG stream_running_count = 0; +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +ULONG feedback_running_count = 0; +#endif + + /* Get audio instance. */ + audio = (UX_DEVICE_CLASS_AUDIO *) instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return(UX_STATE_EXIT); + +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) + + /* Run audio status tasks. */ + status = _ux_device_class_audio_interrupt_task_function(audio); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + interrupt_running_count++; +#endif + + for (stream_index = 0; + stream_index < audio -> ux_device_class_audio_streams_nb; + stream_index ++) + { + stream = &audio -> ux_device_class_audio_streams[stream_index]; + status = stream -> ux_device_class_audio_stream_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + stream_running_count ++; + +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + if (stream -> ux_device_class_audio_stream_feedback_task_function != UX_NULL) + { + status = stream -> ux_device_class_audio_stream_feedback_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + feedback_running_count ++; + } +#endif + } + + if ((stream_running_count > 0) +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) + || (interrupt_running_count > 0) +#endif +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + || (feedback_running_count > 0) +#endif + ) + { + return UX_STATE_WAIT; + } + else + { + return UX_STATE_IDLE; + } +} + +#endif
\ No newline at end of file diff --git a/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c index 050390c..69b58c5 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_transmission_start PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_transmission_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -103,7 +106,15 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length == 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start write task. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; +#else + /* Start write thread. */ _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); +#endif return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c new file mode 100644 index 0000000..2c30a3c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* 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 Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_write_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio stream write. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* audio_class Address of audio class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_write_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG transfer_length; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_audio_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, prepare data, reset transfer and start polling. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT; + + /* Start frame transfer anyway (even ZLP). */ + transfer_length = stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length; + if (transfer_length) + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, transfer_length); /* Use case of memcpy is verified. */ + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Get current transfer length. */ + transfer_length = stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length; + + /* Run transfer states. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Frame sent, free it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = 0; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Calculate next position. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Underflow check! */ + if (transfer_length) + { + + /* Advance position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Error trap! */ + if (next_frame -> ux_device_class_audio_frame_length == 0) + { + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + } + else + { + + /* Advance position if next payload available. */ + if (next_frame -> ux_device_class_audio_frame_length) + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + else + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + } + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c index f6c1cf0..ce6bd7b 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_write_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream) @@ -153,7 +156,10 @@ ULONG actual_length; /* Error trap! */ if (next_frame -> ux_device_class_audio_frame_length == 0) + { + stream -> ux_device_class_audio_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } else { @@ -162,9 +168,12 @@ ULONG actual_length; if (next_frame -> ux_device_class_audio_frame_length) stream -> ux_device_class_audio_stream_transfer_pos = next_frame; else + { /* Error trap! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } } /* Invoke notification callback. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c index 4086b03..e89212a 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_read_run PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -79,6 +79,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* fixed return code, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, @@ -200,7 +203,7 @@ UINT status = UX_SUCCESS; cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_read_status = transfer_request -> ux_slave_transfer_request_completion_code; - return(UX_STATE_EXIT); + return(UX_STATE_ERROR); } /* Success case. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c index 63c4e8f..55f5ddd 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c @@ -31,8 +31,11 @@ #if defined(UX_DEVICE_STANDALONE) + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE static inline VOID _ux_device_class_cdc_acm_transmission_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm); static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm); +#endif /**************************************************************************/ @@ -40,7 +43,7 @@ static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLAS /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_tasks_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,21 +83,23 @@ static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLAS /* names conflict C++ keyword, */ /* supported write auto ZLP, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile warnings, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_tasks_run(VOID *instance) { -UX_SLAVE_DEVICE *device; -UX_SLAVE_CLASS_CDC_ACM *cdc_acm; UINT status = UX_STATE_IDLE; +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; /* Get CDC ACM instance. */ cdc_acm = (UX_SLAVE_CLASS_CDC_ACM*) instance; -#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE - /* Check if transmission is started. */ if (!cdc_acm -> ux_slave_class_cdc_acm_transmission_status) return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c index 630bea7..35ea2ad 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_write_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* names conflict C++ keyword, */ /* added auto ZLP support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* fixed return code, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, @@ -125,7 +128,7 @@ UINT status = 0; cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_write_status = UX_CONFIGURATION_HANDLE_UNKNOWN; - return(UX_CONFIGURATION_HANDLE_UNKNOWN); + return(UX_STATE_EXIT); } /* We need the interface to the class. */ @@ -224,7 +227,7 @@ UINT status = 0; cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_write_status = transfer_request -> ux_slave_transfer_request_completion_code; - return(UX_STATE_EXIT); + return(UX_STATE_ERROR); } /* Success case. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c index a30a9bd..57968f6 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkin_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkin_thread(ULONG cdc_ecm_class) @@ -95,8 +98,8 @@ UX_SLAVE_TRANSFER *transfer_request; UINT status; ULONG actual_flags; NX_PACKET *current_packet; -UCHAR *packet_header; ULONG transfer_length; +ULONG copied; /* Cast properly the cdc_ecm instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class) @@ -148,24 +151,26 @@ ULONG transfer_length; if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) { - /* Load the address of the current packet header at the physical header. */ - packet_header = current_packet -> nx_packet_prepend_ptr; - /* Can the packet fit in the transfer requests data buffer? */ if (current_packet -> nx_packet_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH) { /* Copy the packet in the transfer descriptor buffer. */ - _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, packet_header, current_packet -> nx_packet_length); /* Use case of memcpy is verified. */ + status = nx_packet_data_extract_offset(current_packet, 0, + transfer_request -> ux_slave_transfer_request_data_pointer, + current_packet -> nx_packet_length, &copied); + if (status == UX_SUCCESS) + { - /* Calculate the transfer length. */ - transfer_length = current_packet -> nx_packet_length; - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + /* Calculate the transfer length. */ + transfer_length = current_packet -> nx_packet_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE); + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE + 1); + } /* Check error code. */ if (status != UX_SUCCESS) diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c index 6b0ba9f..8b1cc26 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkout_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,11 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed EP not ready issue, */ +/* used pool from NX IP inst, */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class) @@ -94,7 +99,7 @@ UX_SLAVE_DEVICE *device; UX_SLAVE_TRANSFER *transfer_request; UINT status; NX_PACKET *packet; -ULONG ip_given_length; +USB_NETWORK_DEVICE_TYPE *ux_nx_device; /* Cast properly the cdc_ecm instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class) @@ -113,8 +118,38 @@ ULONG ip_given_length; while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) { + /* Check if packet pool is ready. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool == UX_NULL) + { + + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + + /* Get packet pool from IP instance (if available). */ + if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL) + { + cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool; + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR); + + _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT); + continue; + } + } + + /* Check if Bulk OUT endpoint is ready. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL) + { + _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_LINK_CHECK_WAIT); + continue; + } + /* We can accept new reception. Get a NX Packet */ - status = nx_packet_allocate(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet, + status = nx_packet_allocate(cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet, NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT)); if (status == NX_SUCCESS) @@ -136,7 +171,7 @@ ULONG ip_given_length; /* Send the request to the device controller. */ status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH, UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH); - + /* Check the completion code. */ if (status == UX_SUCCESS) { @@ -147,26 +182,27 @@ ULONG ip_given_length; /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ packet -> nx_packet_prepend_ptr += sizeof(USHORT); - - /* Set the prepend, length, and append fields. */ - packet -> nx_packet_length = transfer_request -> ux_slave_transfer_request_actual_length; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + transfer_request -> ux_slave_transfer_request_actual_length; - + packet -> nx_packet_append_ptr += sizeof(USHORT); + /* Copy the received packet in the IP packet data area. */ - _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer, packet -> nx_packet_length); /* Use case of memcpy is verified. */ - - /* Calculate the accurate packet length from ip header. */ - if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && - (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + status = nx_packet_data_append(packet, + transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length, + cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, + UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT)); + if (status == NX_SUCCESS) + { + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet); + } + else { - ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; - packet -> nx_packet_length = ip_given_length ; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); } - - /* Send that packet to the NetX USB broker. */ - _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet); } else diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c index f1723be..84ae21b 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c @@ -27,14 +27,13 @@ #include "ux_device_class_cdc_ecm.h" #include "ux_device_stack.h" -UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +60,6 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* _ux_utility_event_flags_delete Delete Flag group */ /* _ux_device_thread_create Create Thread */ /* _ux_device_thread_delete Delete Thread */ -/* nx_packet_pool_create Create NetX packet pool */ -/* nx_packet_pool_delete Delete NetX packet pool */ /* */ /* CALLED BY */ /* */ @@ -89,6 +86,9 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -153,28 +153,6 @@ UINT status; status = (UX_MEMORY_INSUFFICIENT); } - /* Allocate some packet pool for reception. */ - if (status == UX_SUCCESS) - { - - /* UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory = - _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check for successful allocation. */ - if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory == UX_NULL) - status = (UX_MEMORY_INSUFFICIENT); - else - { - /* Create a packet pool. */ - status = nx_packet_pool_create(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, "CDC ECM Device Packet Pool", - UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory, - UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); - } - } - /* Interrupt endpoint treatment needs to be running in a different thread. So start a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread does not start until we have a instance of the class. */ @@ -267,10 +245,6 @@ UINT status; /* Free allocated resources. */ - if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool.nx_packet_pool_id) - nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); - if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory) - _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack) _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack); if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack) diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c index c429632..43ae217 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_uninitialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -131,14 +134,8 @@ UX_SLAVE_CLASS *class_ptr; /* Delete the interrupt thread sync event flags group. */ _ux_device_event_flags_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group); - /* Delete the reception packet pool. */ - nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); - #endif - /* Free the packet pool memory. */ - _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); - /* Free the resources. */ _ux_utility_memory_free(cdc_ecm); } diff --git a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c index 4d04c38..4d04c38 100755..100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c diff --git a/common/usbx_device_classes/src/ux_device_class_hid_initialize.c b/common/usbx_device_classes/src/ux_device_class_hid_initialize.c index 22f8e46..74fc89b 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile warnings, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -228,8 +231,13 @@ UINT status = UX_SUCCESS; } +#if !defined(UX_DEVICE_STANDALONE) || defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* There is still initialization activities after array creation, + * and some error occurs in this stage. */ /* Free allocated event array memory. */ _ux_utility_memory_free(hid -> ux_device_class_hid_event_array); +#endif } else diff --git a/common/usbx_device_classes/src/ux_device_class_printer_initialize.c b/common/usbx_device_classes/src/ux_device_class_printer_initialize.c index 1007d29..f07e446 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_initialize PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,19 +69,20 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_DEVICE_CLASS_PRINTER *printer; UX_DEVICE_CLASS_PRINTER_PARAMETER *printer_parameter; UX_SLAVE_CLASS *printer_class; +#if !defined(UX_DEVICE_STANDALONE) UINT status; +#endif /* Get the class container. */ printer_class = command -> ux_slave_class_command_class_ptr; @@ -105,6 +106,7 @@ UINT status; printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_deactivate = printer_parameter -> ux_device_class_printer_instance_deactivate; printer -> ux_device_class_printer_parameter.ux_device_class_printer_soft_reset = printer_parameter -> ux_device_class_printer_soft_reset; +#if !defined(UX_DEVICE_STANDALONE) /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time. */ status = _ux_utility_mutex_create(&printer -> ux_device_class_printer_endpoint_in_mutex, "ux_device_class_printer_in_mutex"); @@ -135,11 +137,14 @@ UINT status; /* Return fatal error. */ return(UX_MUTEX_ERROR); } +#else + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; +#endif /* Reset port status. */ printer -> ux_device_class_printer_port_status = 0; /* Return completion status. */ return(UX_SUCCESS); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_read_run.c b/common/usbx_device_classes/src/ux_device_class_printer_read_run.c new file mode 100644 index 0000000..acfb390 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_read_run.c @@ -0,0 +1,238 @@ +/**************************************************************************/ +/* */ +/* 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 Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_printer.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_read_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the Printer class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* received data */ +/* requested_length Length of bytes to read */ +/* actual_length Pointer to save number of */ +/* bytes read */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_NEXT Transfer done, to next state */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* (others) Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_read_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +ULONG max_transfer_length; +UINT status = UX_SUCCESS; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* Locate the endpoint. */ + endpoint = printer -> ux_device_class_printer_endpoint_out; + + /* All Printer reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(printer -> ux_device_class_printer_read_state) + { + case UX_STATE_RESET: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START; + printer -> ux_device_class_printer_read_status = UX_TRANSFER_NO_ANSWER; + printer -> ux_device_class_printer_read_buffer = buffer; + printer -> ux_device_class_printer_read_requested_length = requested_length; + printer -> ux_device_class_printer_read_actual_length = 0; + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_READ_START: + + /* Get remaining transfer length. */ + requested_length = printer -> ux_device_class_printer_read_requested_length - + printer -> ux_device_class_printer_read_actual_length; + + /* There is nothing remaining, it's done. */ + if (requested_length == 0) + { + *actual_length = printer -> ux_device_class_printer_read_actual_length; + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_SUCCESS; + return(UX_STATE_NEXT); + } + + printer -> ux_device_class_printer_read_transfer_length = requested_length; + + /* Next state. */ + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_READ_WAIT: + + /* Get a full packet each time */ + max_transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + /* Run the transfer state machine. */ + status = _ux_device_stack_transfer_run(transfer_request, + max_transfer_length, + max_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_ERROR); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + /* Check overflow */ + if (printer -> ux_device_class_printer_read_transfer_length < + transfer_request -> ux_slave_transfer_request_actual_length) + { + printer -> ux_device_class_printer_read_state = UX_STATE_ERROR; + printer -> ux_device_class_printer_read_status = UX_TRANSFER_BUFFER_OVERFLOW; + return(UX_STATE_ERROR); + } + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(printer -> ux_device_class_printer_read_buffer, + transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */ + + /* Next buffer address. */ + printer -> ux_device_class_printer_read_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + printer -> ux_device_class_printer_read_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + printer -> ux_device_class_printer_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual length. */ + *actual_length = printer -> ux_device_class_printer_read_actual_length; + + /* Check short packet. */ + if (transfer_request -> ux_slave_transfer_request_actual_length < + transfer_request -> ux_slave_transfer_request_requested_length) + { + + /* It's done. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_INVALID_STATE; + break; + } + + /* Error cases. */ + return(UX_STATE_EXIT); +} + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c b/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c index fa96f3b..9d41d96 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_soft_reset PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_printer_soft_reset(UX_DEVICE_CLASS_PRINTER *printer) @@ -76,11 +79,17 @@ UX_SLAVE_ENDPOINT *endpoint; /* Stop OUT. */ endpoint = printer -> ux_device_class_printer_endpoint_out; _ux_device_stack_transfer_all_request_abort(endpoint, UX_ENDPOINT_RESET); +#if defined(UX_DEVICE_STANDALONE) + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; +#endif /* Stop IN (optional). */ endpoint = printer -> ux_device_class_printer_endpoint_in; if (endpoint != UX_NULL) { _ux_device_stack_transfer_all_request_abort(endpoint, UX_ENDPOINT_RESET); +#if defined(UX_DEVICE_STANDALONE) + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; +#endif } } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c index 1ff77aa..6a4e956 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_uninitialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_printer_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -89,13 +92,13 @@ UX_SLAVE_CLASS *class_ptr; /* Sanity check. */ if (printer != UX_NULL) { - +#if !defined(UX_DEVICE_STANDALONE) /* Delete the IN endpoint mutex. */ _ux_device_mutex_delete(&printer -> ux_device_class_printer_endpoint_in_mutex); /* Out Mutex. */ _ux_device_mutex_delete(&printer -> ux_device_class_printer_endpoint_out_mutex); - +#endif /* Free the resources. */ _ux_utility_memory_free(printer); } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_write_run.c b/common/usbx_device_classes/src/ux_device_class_printer_write_run.c new file mode 100644 index 0000000..d078cd4 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_write_run.c @@ -0,0 +1,258 @@ +/**************************************************************************/ +/* */ +/* 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 Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_printer.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_write_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the Printer class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write, */ +/* set to 0 to issue ZLP */ +/* actual_length Pointer to save number of */ +/* bytes written */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_NEXT Transfer done, to next state */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* (others) Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run Transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_write_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT zlp = UX_FALSE; +UINT status = 0; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_WRITE, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* Locate the endpoints. */ + endpoint = printer -> ux_device_class_printer_endpoint_in; + + /* Check if it's available. */ + if (endpoint == UX_NULL) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_ENDPOINT_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(printer -> ux_device_class_printer_write_state) + { + case UX_STATE_RESET: + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_START; + printer -> ux_device_class_printer_write_status = UX_TRANSFER_NO_ANSWER; + printer -> ux_device_class_printer_write_buffer = buffer; + printer -> ux_device_class_printer_write_requested_length = requested_length; + printer -> ux_device_class_printer_write_actual_length = 0; + printer -> ux_device_class_printer_write_host_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + if (requested_length == 0) + zlp = UX_TRUE; + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_WRITE_START: + + /* Get remaining requested length. */ + requested_length = printer -> ux_device_class_printer_write_requested_length - + printer -> ux_device_class_printer_write_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0 && !zlp) + { + *actual_length = printer -> ux_device_class_printer_write_actual_length; + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_SUCCESS; + return(UX_STATE_NEXT); + } + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + printer -> ux_device_class_printer_write_transfer_length = + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + { + + /* We can proceed with the demanded length. */ + printer -> ux_device_class_printer_write_transfer_length = requested_length; + +#if !defined(UX_DEVICE_CLASS_PRINTER_WRITE_AUTO_ZLP) + + /* Assume expected length and transfer length match. */ + printer -> ux_device_class_printer_write_host_length = requested_length; +#else + + /* Assume expected more than transfer to let stack append ZLP if needed. */ + printer -> ux_device_class_printer_write_host_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1; +#endif + } + + + /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API + easier. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + printer -> ux_device_class_printer_write_buffer, + printer -> ux_device_class_printer_write_transfer_length); /* Use case of memcpy is verified. */ + + /* Next state. */ + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_WRITE_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + printer -> ux_device_class_printer_write_transfer_length, + printer -> ux_device_class_printer_write_host_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_ERROR); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next buffer address. */ + printer -> ux_device_class_printer_write_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + printer -> ux_device_class_printer_write_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + printer -> ux_device_class_printer_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual done length. */ + *actual_length = printer -> ux_device_class_printer_write_actual_length; + + /* Check ZLP case. */ + if (printer -> ux_device_class_printer_write_requested_length == 0) + { + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c index be900a9..92c1115 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkin_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkin_thread(ULONG rndis_class) @@ -97,8 +100,8 @@ UX_SLAVE_TRANSFER *transfer_request; UINT status; ULONG actual_flags; NX_PACKET *current_packet; -UCHAR *packet_header; ULONG transfer_length; +ULONG copied; /* Cast properly the rndis instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, rndis_class) @@ -150,9 +153,6 @@ ULONG transfer_length; if (rndis -> ux_slave_class_rndis_link_state == UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP) { - /* Load the address of the current packet header at the physical header. */ - packet_header = current_packet -> nx_packet_prepend_ptr; - /* Calculate the transfer length. */ transfer_length = current_packet -> nx_packet_length + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH; @@ -161,21 +161,27 @@ ULONG transfer_length; { /* Copy the packet in the transfer descriptor buffer. */ - _ux_utility_memory_copy (transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, packet_header, current_packet -> nx_packet_length); /* Use case of memcpy is verified. */ - - /* Add the RNDIS header to this packet. */ - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH, transfer_length); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET, - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH, current_packet -> nx_packet_length); - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + status = nx_packet_data_extract_offset(current_packet, 0, + transfer_request -> ux_slave_transfer_request_data_pointer + + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, + current_packet -> nx_packet_length, &copied); + if (status == NX_SUCCESS) + { + + /* Add the RNDIS header to this packet. */ + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH, transfer_length); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET, + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH, current_packet -> nx_packet_length); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE + 1); + } - /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE); - /* Check for error. */ if (status != UX_SUCCESS) diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c index a569e5f..1fcc35a 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkout_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -84,6 +84,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* used linked NX IP pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkout_thread(ULONG rndis_class) @@ -95,8 +99,8 @@ UX_SLAVE_DEVICE *device; UX_SLAVE_TRANSFER *transfer_request; UINT status; NX_PACKET *packet; -ULONG ip_given_length; ULONG packet_payload; +USB_NETWORK_DEVICE_TYPE *ux_nx_device; /* Cast properly the rndis instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, rndis_class) @@ -117,16 +121,39 @@ ULONG packet_payload; /* As long as the device is in the CONFIGURED state. */ while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) { - + + /* Check if packet pool is ready. */ + if (rndis -> ux_slave_class_rndis_packet_pool == UX_NULL) + { + + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(rndis -> ux_slave_class_rndis_network_handle); + + /* Get packet pool from IP instance (if available). */ + if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL) + { + rndis -> ux_slave_class_rndis_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool; + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR); + + _ux_utility_delay_ms(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT); + continue; + } + } + /* We can accept new reception. Get a NX Packet. */ - status = nx_packet_allocate(&rndis -> ux_slave_class_rndis_packet_pool, &packet, + status = nx_packet_allocate(rndis -> ux_slave_class_rndis_packet_pool, &packet, NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT)); if (status == NX_SUCCESS) { /* And length. */ - transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH; + transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH; transfer_request -> ux_slave_transfer_request_actual_length = 0; /* Memorize this packet at the beginning of the queue. */ @@ -136,8 +163,8 @@ ULONG packet_payload; packet -> nx_packet_queue_next = UX_NULL; /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, - UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH); + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH, + UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH); /* Check the completion code. */ if (status == UX_SUCCESS) @@ -147,63 +174,71 @@ ULONG packet_payload; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_RECEIVE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - /* Check the state of the transfer. If there is an error, we do not proceed with this report. Also ensure the header has a valid ID of 1. */ - if (_ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE) == UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG) + /* Check the state of the transfer. If there is an error, we do not proceed with this report. + Ensure this packet is at least larger than the header. + Also ensure the header has a valid ID of 1. */ + if (transfer_request -> ux_slave_transfer_request_actual_length > UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH && + _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE) == UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG) { - /* Ensure this packet is at least larger than the header. */ - if (transfer_request -> ux_slave_transfer_request_actual_length > UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) - { - - /* Get the size of the payload. */ - packet_payload = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH); - - /* Ensure the length reported in the RNDIS header is not larger than it actually is. - The reason we can't check to see if the length reported in the header and the - actual length are exactly equal is because there might other data after the payload - (padding, or even a message). */ - if (packet_payload <= transfer_request -> ux_slave_transfer_request_actual_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) - { + /* Get the size of the payload. */ + packet_payload = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH); - /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ - packet -> nx_packet_prepend_ptr += sizeof(USHORT); - - /* Adjust the prepend, length, and append fields. */ - packet -> nx_packet_length = packet_payload; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + packet_payload; - + /* Ensure the length reported in the RNDIS header is not larger than it actually is. + The reason we can't check to see if the length reported in the header and the + actual length are exactly equal is because there might other data after the payload + (padding, or even a message). */ + if (packet_payload <= transfer_request -> ux_slave_transfer_request_actual_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) + { - /* Copy the received packet in the IP packet data area. */ - _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER, packet_payload); /* Use case of memcpy is verified. */ - - /* Calculate the accurate packet length from ip header */ - if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && - (*(packet -> nx_packet_prepend_ptr + 13) == 0)) - { + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + packet -> nx_packet_append_ptr += sizeof(USHORT); - ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; - packet -> nx_packet_length = ip_given_length ; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; - } + /* Copy the received packet in the IP packet data area. */ + status = nx_packet_data_append(packet, + transfer_request -> ux_slave_transfer_request_data_pointer + + UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER, + packet_payload, + rndis -> ux_slave_class_rndis_packet_pool, + UX_MS_TO_TICK(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT)); + if (status == UX_SUCCESS) + { /* Send that packet to the NetX USB broker. */ _ux_network_driver_packet_received(rndis -> ux_slave_class_rndis_network_handle, packet); } else + { - /* We received a malformed packet. Report to application. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + /* Error. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_ERROR); + nx_packet_release(packet); + } } else + { /* We received a malformed packet. Report to application. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); + } + } + else + { + + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); } } else + { /* Free the packet that was not successfully received. */ nx_packet_release(packet); + } + } else { diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c index 8af7732..18604e8 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c @@ -78,7 +78,7 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -136,6 +136,9 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_rndis_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -294,31 +297,6 @@ UINT status; status = UX_EVENT_ERROR; } - /* Allocate some packet pool for reception. */ - if (status == UX_SUCCESS) - { - - /* UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - rndis -> ux_slave_class_rndis_pool_memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check the completion status. */ - if (rndis -> ux_slave_class_rndis_pool_memory == UX_NULL) - status = UX_MEMORY_INSUFFICIENT; - } - - /* Create a packet pool. */ - if (status == UX_SUCCESS) - { - status = nx_packet_pool_create(&rndis -> ux_slave_class_rndis_packet_pool, "Rndis Device Packet Pool", - UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE, rndis -> ux_slave_class_rndis_pool_memory, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check for pool creation error. */ - if (status != UX_SUCCESS) - status = UX_MEMORY_INSUFFICIENT; - } - /* Create a semaphore for protecting the driver entry. */ if (status == UX_SUCCESS) { @@ -338,14 +316,6 @@ UINT status; if (rndis -> ux_slave_class_rndis_semaphore.tx_semaphore_id != 0) _ux_device_semaphore_delete(&rndis -> ux_slave_class_rndis_semaphore); - /* Delete the packet pool. */ - if (rndis -> ux_slave_class_rndis_packet_pool.nx_packet_pool_id != 0) - nx_packet_pool_delete(&rndis -> ux_slave_class_rndis_packet_pool); - - /* Free rndis -> ux_slave_class_rndis_pool_memory. */ - if (rndis -> ux_slave_class_rndis_pool_memory) - _ux_utility_memory_free(rndis -> ux_slave_class_rndis_pool_memory); - /* Delete rndis -> ux_slave_class_rndis_event_flags_group. */ if (rndis -> ux_slave_class_rndis_event_flags_group.tx_event_flags_group_id != 0) _ux_utility_event_flags_delete(&rndis -> ux_slave_class_rndis_event_flags_group); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c index 2acafd4..a3652f6 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c @@ -65,7 +65,7 @@ static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *s /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_tasks_run PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -125,6 +125,9 @@ static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *s /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_tasks_run(VOID *instance) @@ -148,13 +151,14 @@ static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *sto UX_SLAVE_DEVICE *device; UCHAR state; UINT status; +INT immediate_state = UX_TRUE; /* Get pointer to the device. */ device = &_ux_system_slave -> ux_system_slave_device; /* Run states once. */ - while(1) + while(immediate_state) { /* General check for MSC ready. */ @@ -301,9 +305,12 @@ UINT status; break; } - /* Unhandled, just do again by app call. */ - return(UX_STATE_EXIT); + /* Unhandled, just break the loop and do again by app call. */ + immediate_state = UX_FALSE; } + + /* Unhandled state. */ + return(UX_STATE_EXIT); } static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage) @@ -979,9 +986,10 @@ static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *st { UCHAR state = storage -> ux_device_class_storage_disk_state; UINT status; +INT immediate_state = UX_TRUE; /* Run states once. */ - while(1) + while(immediate_state) { /* Update state. */ @@ -1035,8 +1043,8 @@ UINT status; break; } - /* Task run once. */ - return; + /* Task run once, break the loop. */ + immediate_state = UX_FALSE; } } static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage) @@ -1058,6 +1066,8 @@ ULONG max_n_blocks; /* Max blocks for one buffer. */ block_size = storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. ux_slave_class_storage_media_block_length; + if (block_size == 0) + UX_ASSERT(UX_FALSE); max_n_blocks = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE / block_size; /* Prepare next disk read. */ diff --git a/common/usbx_device_classes/src/ux_device_class_video_activate.c b/common/usbx_device_classes/src/ux_device_class_video_activate.c index 80e71f6..7d78048 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_video_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -154,6 +157,14 @@ ULONG stream_index; /* Store the class instance into the interface. */ stream_interface -> ux_slave_interface_class_instance = (VOID *)video; + +#if defined(UX_DEVICE_STANDALONE) + + /* Reset stream task state. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = UX_SUCCESS; +#endif + } /* If there is a activate function call it. */ diff --git a/common/usbx_device_classes/src/ux_device_class_video_change.c b/common/usbx_device_classes/src/ux_device_class_video_change.c index 199fcc6..9bf5e01 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_change.c +++ b/common/usbx_device_classes/src/ux_device_class_video_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_change PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_change(UX_SLAVE_CLASS_COMMAND *command) @@ -160,6 +163,15 @@ ULONG stream_index; return(UX_DESCRIPTOR_CORRUPTED); } +#if defined(UX_DEVICE_STANDALONE) + + /* Reset background transfer state. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; +#endif + + /* Now reset payload buffer error count. */ + stream -> ux_device_class_video_stream_buffer_error_count = 0; + /* Now reset payload buffers. */ payload_buffer = stream -> ux_device_class_video_stream_buffer; while(payload_buffer < stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) diff --git a/common/usbx_device_classes/src/ux_device_class_video_initialize.c b/common/usbx_device_classes/src/ux_device_class_video_initialize.c index 8ffb9fe..625bc4f 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_video_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_initialize PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,14 +67,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UINT status = UX_SUCCESS; UX_DEVICE_CLASS_VIDEO *video; @@ -163,6 +162,9 @@ ULONG i; stream -> ux_device_class_video_stream_transfer_pos = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)stream -> ux_device_class_video_stream_buffer; stream -> ux_device_class_video_stream_access_pos = stream -> ux_device_class_video_stream_transfer_pos; + +#if !defined(UX_DEVICE_STANDALONE) + /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_video_stream_parameter_thread_stack_size == 0) memory_size = UX_DEVICE_CLASS_VIDEO_THREAD_STACK_SIZE; @@ -189,6 +191,11 @@ ULONG i; break; UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_video_stream_thread), stream) +#else + + /* Save task function for streaming. */ + stream -> ux_device_class_video_stream_task_function = stream_parameter -> ux_device_class_video_stream_parameter_task_function; +#endif /* Save callbacks. */ _ux_utility_memory_copy(&stream -> ux_device_class_video_stream_callbacks, @@ -217,6 +224,12 @@ ULONG i; &video_parameter -> ux_device_class_video_parameter_callbacks, sizeof(UX_DEVICE_CLASS_VIDEO_CALLBACKS)); /* Use case of memcpy is verified. */ +#if defined(UX_DEVICE_STANDALONE) + + /* Link task function. */ + class_inst -> ux_slave_class_task_function = _ux_device_class_video_tasks_run; +#endif + /* Return completion status. */ return(UX_SUCCESS); } @@ -228,10 +241,14 @@ ULONG i; stream = video -> ux_device_class_video_streams; for (i = 0; i < video -> ux_device_class_video_streams_nb; i ++) { + +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_video_stream_thread.tx_thread_id) _ux_utility_thread_delete(&stream -> ux_device_class_video_stream_thread); if (stream -> ux_device_class_video_stream_thread_stack) _ux_utility_memory_free(stream -> ux_device_class_video_stream_thread_stack); +#endif + if (stream -> ux_device_class_video_stream_buffer) _ux_utility_memory_free(stream -> ux_device_class_video_stream_buffer); stream ++; @@ -239,5 +256,4 @@ ULONG i; _ux_utility_memory_free(video); return(status); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c b/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c new file mode 100644 index 0000000..a7422cc --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* 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 Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_read_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video stream read. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to video stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_read_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_VIDEO_PAYLOAD *next_payload; +ULONG max_packet_size; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_video_stream_video -> ux_device_class_video_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_video_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_video_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, reset transfer and start polling. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT; + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Run transfer state machine. */ + max_packet_size = endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_transfer_length; + status = _ux_device_stack_transfer_run(transfer, max_packet_size, max_packet_size); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Frame received, log it. */ + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length = actual_length; + _ux_utility_memory_copy(stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_data, + transfer -> ux_slave_transfer_request_data_pointer, + actual_length); /* Use case of memcpy is verified. */ + + /* For simple, do not advance the transfer position if there is overflow. */ + next_pos = (UCHAR *)stream -> ux_device_class_video_stream_transfer_pos; + next_pos += stream -> ux_device_class_video_stream_payload_buffer_size; + if (next_pos >= stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) + next_pos = stream -> ux_device_class_video_stream_buffer; + next_payload = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)next_pos; + + /* Check overflow! */ + if (next_payload -> ux_device_class_video_payload_length > 0) + { + + /* Error notification! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + else + + /* Update transfer position. */ + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + + /* Invoke notification callback. */ + if (stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done != UX_NULL) + stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c index e9cd669..060723d 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_read_thread_entry PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added error statistics, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_video_read_thread_entry(ULONG video_stream) @@ -145,6 +148,7 @@ ULONG actual_length; { /* Error notification! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); } else diff --git a/common/usbx_device_classes/src/ux_device_class_video_reception_start.c b/common/usbx_device_classes/src/ux_device_class_video_reception_start.c index 84be153..342b00e 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_reception_start.c +++ b/common/usbx_device_classes/src/ux_device_class_video_reception_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_reception_start PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,14 +65,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_reception_start(UX_DEVICE_CLASS_VIDEO_STREAM *stream) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(stream); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_ENDPOINT *endpoint; UX_SLAVE_DEVICE *device; @@ -102,8 +101,16 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length > 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start read task. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + +#else /* Start read thread. */ _ux_utility_thread_resume(&stream -> ux_device_class_video_stream_thread); - return(UX_SUCCESS); #endif + + return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c new file mode 100644 index 0000000..24ca2ed --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* 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 Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_tasks_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_video_stream_task_function) */ +/* Run stream task */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_tasks_run(VOID *instance) +{ +UX_SLAVE_DEVICE *device; +UX_DEVICE_CLASS_VIDEO *video; +UX_DEVICE_CLASS_VIDEO_STREAM *stream; +ULONG stream_index; +UINT status; +ULONG running_count; + + + /* Get Video instance. */ + video = (UX_DEVICE_CLASS_VIDEO *) instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return(UX_STATE_EXIT); + + /* Run video streaming tasks. */ + running_count = 0; + for (stream_index = 0; + stream_index < video -> ux_device_class_video_streams_nb; + stream_index ++) + { + stream = &video -> ux_device_class_video_streams[stream_index]; + status = stream -> ux_device_class_video_stream_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + running_count ++; + } + + /* Return state running. */ + return (running_count > 0) ? (UX_STATE_WAIT) : (UX_STATE_IDLE); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c b/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c index 63a6c30..c01f117 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c +++ b/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_transmission_start PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,14 +65,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_transmission_start(UX_DEVICE_CLASS_VIDEO_STREAM *stream) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(stream); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_ENDPOINT *endpoint; UX_SLAVE_DEVICE *device; @@ -102,8 +101,17 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length == 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start write task. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + +#else + /* Start write thread. */ - _ux_utility_thread_resume(&stream -> ux_device_class_video_stream_thread); - return(UX_SUCCESS); + _ux_device_thread_resume(&stream -> ux_device_class_video_stream_thread); #endif + + return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c b/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c new file mode 100644 index 0000000..55dba42 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* 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 Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_write_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video stream write. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* video_class Address of video class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_write_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_VIDEO_PAYLOAD *next_payload; +ULONG transfer_length; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_video_stream_video -> ux_device_class_video_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_video_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_video_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, prepare data, reset transfer and start polling. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT; + + /* Start payload transfer anyway (even ZLP). */ + transfer_length = stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length; + if (transfer_length) + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_data, transfer_length); /* Use case of memcpy is verified. */ + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Get current transfer length. */ + transfer_length = stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length; + + /* Run transfer states. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Frame sent, free it. */ + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length = 0; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Calculate next position. */ + next_pos = (UCHAR *)stream -> ux_device_class_video_stream_transfer_pos; + next_pos += stream -> ux_device_class_video_stream_payload_buffer_size; + if (next_pos >= stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) + next_pos = stream -> ux_device_class_video_stream_buffer; + next_payload = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)next_pos; + + /* Underflow check! */ + if (transfer_length) + { + + /* Advance position. */ + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + + /* Error trap! */ + if (next_payload -> ux_device_class_video_payload_length == 0) + { + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + } + else + { + + /* Advance position if next payload available. */ + if (next_payload -> ux_device_class_video_payload_length) + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + else + { + + /* Error trap! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + } + + /* Invoke notification callback. */ + if (stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done != UX_NULL) + stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c index 43006d6..3dce636 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_write_thread_entry PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added error statistics, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_video_write_thread_entry(ULONG video_stream) @@ -147,7 +150,10 @@ ULONG actual_length; /* Error trap! */ if (next_payload -> ux_device_class_video_payload_length == 0) + { + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } else { @@ -156,9 +162,12 @@ ULONG actual_length; if (next_payload -> ux_device_class_video_payload_length) stream -> ux_device_class_video_stream_transfer_pos = next_payload; else + { /* Error trap! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } /* Invoke notification callback. */ |
