diff --git a/common/core/CMakeLists.txt b/common/core/CMakeLists.txt index 8b1796f9..1cbb4d56 100644 --- a/common/core/CMakeLists.txt +++ b/common/core/CMakeLists.txt @@ -13,14 +13,17 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_state_change.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_abort.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_change.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_deactivate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_read_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_write_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_set.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_class_register.c @@ -41,9 +44,11 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_microsoft_extension_register.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_set_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_abort.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_all_request_abort.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_queue_process.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_schedule.c @@ -77,6 +82,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_timer_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transaction_schedule.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transfer_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_configure.c @@ -144,11 +150,14 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_extraction.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_insertion.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_role_swap.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_error_handler.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_insert.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_update.c diff --git a/common/core/inc/ux_api.h b/common/core/inc/ux_api.h index bc8b40cc..9f12ac2a 100755 --- a/common/core/inc/ux_api.h +++ b/common/core/inc/ux_api.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* ux_api.h PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -101,6 +101,15 @@ /* added transfer size field, */ /* improved traceX support, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added too many ports error, */ +/* moved tx_api.h include and */ +/* typedefs to ux_port.h, */ +/* added standalone support, */ +/* added device HID trace IDs, */ +/* added some general errors, */ +/* added printer trace IDs, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -117,16 +126,44 @@ extern "C" { #endif - -/* Include ThreadX API include file. */ - -#include "tx_api.h" - - /* Include USBX port specific file. */ #include "ux_port.h" +/* Process compile options: + * + * - UX_HOST_SIDE_ONLY/UX_HOST_STANDALONE: + * Must not be defined at the same time, + * When defined, only host/device side APIs are available. + * + * - UX_STANDALONE: + * Defined, whole RTOS dependencies are removed from USBX. + * + * - UX_DEVICE_STANDALONE/UX_HOST_STANDALONE + * Internal definitions for different parts, + * _DEVICE_STANDALONE removes RTOS dependencies of DCD, device stack and classes, + * _HOST_STANDALONE removes RTOS dependencies of HCD, host stack and classes, + * if UX_STANDALONE is not defined, RTOS is always enabled in system and utilities. + */ +#if defined(UX_STANDALONE) +#if !defined(UX_DEVICE_STANDALONE) +#define UX_DEVICE_STANDALONE +#endif +#if !defined(UX_HOST_STANDALONE) +#define UX_HOST_STANDALONE +#endif +#if !defined(UX_OTG_STANDALONE) +#define UX_OTG_STANDALONE +#endif +#else +#if defined(UX_DEVICE_STANDALONE) && defined(UX_HOST_STANDALONE) && defined(UX_OTG_STANDALONE) ||\ + defined(UX_DEVICE_STANDALONE) && defined(UX_DEVICE_SIDE_ONLY) ||\ + defined(UX_HOST_STANDALONE) && defined(UX_HOST_SIDE_ONLY) +#define UX_STANDALONE +#endif +#endif + + /* Define the maximum length for class names (exclude string null-terminator). */ #define UX_MAX_CLASS_NAME_LENGTH 63 @@ -168,6 +205,7 @@ typedef signed char SCHAR; /* Convert from millisecond to ThreadX Tick value. */ #define UX_MS_TO_TICK(ms) ((ms) * (UX_PERIODIC_RATE) / 1000) +#define UX_MS_TO_TICK_NON_ZERO(ms) UX_MAX(1, UX_MS_TO_TICK(ms)) /* Deprecated, left to be compatible with apps already using MS_TO_TICK. */ #define MS_TO_TICK(ms) UX_MS_TO_TICK(ms) @@ -239,7 +277,7 @@ typedef signed char SCHAR; #define AZURE_RTOS_USBX #define USBX_MAJOR_VERSION 6 #define USBX_MINOR_VERSION 1 -#define USBX_PATCH_VERSION 9 +#define USBX_PATCH_VERSION 10 /* Macros for concatenating tokens, where UX_CONCATn concatenates n tokens. */ @@ -347,7 +385,11 @@ VOID _ux_utility_debug_log(UCHAR *debug_location, UCHAR *debug_message, ULONG de /* Determine if tracing is enabled. */ -#ifdef TX_ENABLE_EVENT_TRACE +#if defined(TX_ENABLE_EVENT_TRACE) && !defined(UX_STANDALONE) +#define UX_ENABLE_EVENT_TRACE +#endif + +#ifdef UX_ENABLE_EVENT_TRACE /* Trace is enabled. Remap calls so that interrupts can be disabled around the actual event logging. */ @@ -643,6 +685,9 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_TRACE_DEVICE_CLASS_HID_REPORT_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 24) /* I1 = class instance , I2 = descriptor type , I3 = request index */ #define UX_TRACE_DEVICE_CLASS_HID_REPORT_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 25) /* I1 = class instance , I2 = descriptor type , I3 = request index */ #define UX_TRACE_DEVICE_CLASS_HID_DESCRIPTOR_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 26) /* I1 = class instance , I2 = descriptor type , I3 = request index */ +#define UX_TRACE_DEVICE_CLASS_HID_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 27) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_HID_RECEIVER_EVENT_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 28) /* I1 = class instance , I2 = receiver event , I3 = wait_option */ +#define UX_TRACE_DEVICE_CLASS_HID_RECEIVER_EVENT_FREE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 29) /* I1 = class instance , I2 = receiver event */ #define UX_TRACE_DEVICE_CLASS_PIMA_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 30) /* I1 = class instance */ #define UX_TRACE_DEVICE_CLASS_PIMA_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 31) /* I1 = class instance */ @@ -714,6 +759,11 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_TRACE_DEVICE_CLASS_DFU_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 97) /* I1 = class instance */ #define UX_TRACE_DEVICE_CLASS_DFU_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 98) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PRINTER_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 100) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PRINTER_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 101) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PRINTER_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 102) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_PRINTER_WRITE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 103) /* I1 = class instance , I2 = buffer , I3 = requested_length */ + /* Define the USBX Error Event. */ #define UX_TRACE_ERROR 999 @@ -741,6 +791,7 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_SYSTEM_CONTEXT_CLASS 7 #define UX_SYSTEM_CONTEXT_UTILITY 8 #define UX_SYSTEM_CONTEXT_DEVICE_STACK 9 +#define UX_SYSTEM_CONTEXT_HOST_STACK 10 /* Defines the number of ThreadX timer ticks per seconds. By default, the ThreadX timer tick is 10ms, @@ -760,46 +811,92 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL under ISR in the device stack. */ #ifndef UX_INTERRUPT_SAVE_AREA +#ifdef TX_INTERRUPT_SAVE_AREA #define UX_INTERRUPT_SAVE_AREA TX_INTERRUPT_SAVE_AREA +#else +#define UX_INTERRUPT_SAVE_AREA ALIGN_TYPE saved_flags; +#endif #endif #ifndef UX_DISABLE +#ifdef TX_DISABLE #define UX_DISABLE TX_DISABLE +#else +#define UX_DISABLE saved_flags = _ux_utility_interrupt_disable(); +#endif #endif #ifndef UX_RESTORE +#ifdef TX_RESTORE #define UX_RESTORE TX_RESTORE +#else +#define UX_RESTORE _ux_utility_interrupt_restore(saved_flags); +#endif +#endif + +#ifndef UX_INT_SAVE_AREA /* Backword compatible. */ +#define UX_INT_SAVE_AREA UX_INTERRUPT_SAVE_AREA +#endif +#ifndef UX_DISABLE_INTS /* Backword compatible. */ +#define UX_DISABLE_INTS UX_DISABLE +#endif +#ifndef UX_RESTORE_INTS /* Backword compatible. */ +#define UX_RESTORE_INTS UX_RESTORE #endif /* Define thread/timer related things. */ #ifndef UX_EMPTY +#ifdef TX_EMPTY #define UX_EMPTY TX_EMPTY +#else +#define UX_EMPTY (0) +#endif #endif #ifndef UX_TIMER +#ifdef TX_API_H #define UX_TIMER TX_TIMER #endif +#endif #ifndef UX_THREAD +#ifdef TX_API_H #define UX_THREAD TX_THREAD #endif +#endif #ifndef UX_AUTO_START +#ifdef TX_AUTO_START #define UX_AUTO_START TX_AUTO_START +#else +#define UX_AUTO_START (1ul) +#endif #endif #ifndef UX_DONT_START +#ifdef TX_DONT_START #define UX_DONT_START TX_DONT_START +#else +#define UX_DONT_START (0ul) +#endif #endif #ifndef UX_AUTO_ACTIVATE +#ifdef TX_AUTO_ACTIVATE #define UX_AUTO_ACTIVATE TX_AUTO_ACTIVATE +#else +#define UX_AUTO_ACTIVATE (1ul) +#endif #endif #ifndef UX_NO_ACTIVATE +#ifdef TX_NO_ACTIVATE #define UX_NO_ACTIVATE TX_NO_ACTIVATE +#else +#define UX_NO_ACTIVATE (0ul) +#endif #endif #ifndef UX_THREAD_GET_SYSTEM_STATE @@ -807,62 +904,101 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #endif #ifndef UX_WAIT_FOREVER +#ifdef TX_WAIT_FOREVER #define UX_WAIT_FOREVER TX_WAIT_FOREVER +#else +#define UX_WAIT_FOREVER (0xFFFFFFFFul) +#endif #endif #ifndef UX_NO_WAIT +#ifdef TX_NO_WAIT #define UX_NO_WAIT TX_NO_WAIT +#else +#define UX_NO_WAIT (0ul) +#endif #endif #ifndef UX_NO_TIME_SLICE +#ifdef TX_NO_TIME_SLICE #define UX_NO_TIME_SLICE TX_NO_TIME_SLICE +#else +#define UX_NO_TIME_SLICE (0ul) +#endif #endif /* Define semaphore related things. */ #ifndef UX_SEMAPHORE +#ifdef TX_API_H #define UX_SEMAPHORE TX_SEMAPHORE #endif +#endif /* Define mutex related things. */ #ifndef UX_MUTEX +#ifdef TX_API_H #define UX_MUTEX TX_MUTEX #endif +#endif /* Define event flags group related things. */ #ifndef UX_EVENT_FLAGS_GROUP +#ifdef TX_API_H #define UX_EVENT_FLAGS_GROUP TX_EVENT_FLAGS_GROUP #endif +#endif #ifndef UX_OR_CLEAR +#ifdef TX_OR_CLEAR #define UX_OR_CLEAR TX_OR_CLEAR +#else +#define UX_OR_CLEAR (1u) +#endif #endif #ifndef UX_OR +#ifdef TX_OR #define UX_OR TX_OR +#else +#define UX_OR (0u) +#endif #endif #ifndef UX_AND_CLEAR +#ifdef TX_AND_CLEAR #define UX_AND_CLEAR TX_AND_CLEAR +#else +#define UX_AND_CLEAR (3u) +#endif #endif #ifndef UX_AND +#ifdef TX_AND #define UX_AND TX_AND +#else +#define UX_AND (2u) +#endif #endif #ifndef UX_NO_EVENTS +#ifdef TX_NO_EVENTS #define UX_NO_EVENTS TX_NO_EVENTS +#else +#define UX_NO_EVENTS (7u) +#endif #endif /* Define basic USBX constants. */ #define UX_NULL ((void*)0) +#define UX_INVALID_PTR ((void*)(~((ALIGN_TYPE)0))) #define UX_TRUE 1u #define UX_FALSE 0u #define UX_TT_MASK 0x1FFu @@ -1085,7 +1221,11 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_DEVICE_CONNECTION 0x81u #define UX_DEVICE_DISCONNECTION 0x82u +/* Host change callback events : _callback(event, NULL, NULL) */ +#define UX_STANDALONE_WAIT_BACKGROUND_TASK 0x00u + + /* Define USBX transfer request status constants. */ #define UX_TRANSFER_STATUS_NOT_PENDING 0 @@ -1167,9 +1307,34 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_PS_DS 6u +/* Define USBX generic state machine constants. */ + +#define UX_STATE_RESET 0u +#define UX_STATE_EXIT 1u +#define UX_STATE_IDLE 2u +#define UX_STATE_ERROR 3u +#define UX_STATE_NEXT 4u +#define UX_STATE_WAIT 5u +#define UX_STATE_LOCK 6u +#define UX_STATE_BUSY 6u +#define UX_STATE_STEP 0x20u +#define UX_STATE_STACK_STEP 0x20u +#define UX_STATE_DRIVER_STEP 0x40u +#define UX_STATE_CLASS_STEP 0x60u +#define UX_STATE_APP_STEP 0x80u + +#define UX_STATE_IS_RESET(s) (!(s)) /* Reset state */ +#define UX_STATE_IS_FATAL(s) ((s) && (s) < UX_STATE_ERROR) /* Fatal, break all pending loops. */ +#define UX_STATE_IS_ERROR(s) ((s) == UX_STATE_ERROR) /* General error */ +#define UX_STATE_IS_BUSY(s) ((s) >= UX_STATE_WAIT) /* Locked or pending */ +#define UX_STATE_IS_LOCKED(s) ((s) >= UX_STATE_LOCK) /* Locked but not pendint */ + + /* Define USBX Error Code constants. The following format describes their meaning: + 0x00 : Success + 0x0x : State machine return codes 0x1x : Configuration errors 0x2x : USB transport errors 0x3x : USB controller errors @@ -1179,10 +1344,20 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL 0x7x : USB HID Class errors 0x8x : USB Audio Class errors 0x9x : USB CDC-ECM Class errors + ... + 0xfx : General errors */ #define UX_SUCCESS 0 + #define UX_ERROR 0xff +#define UX_BUSY 0xfe +#define UX_TIMEOUT 0xfd +#define UX_REENTRY 0xfc +#define UX_INVALID_STATE 0xfb +#define UX_INVALID_PARAMETER 0xfa +#define UX_ABORTED 0xf9 + #define UX_TOO_MANY_DEVICES 0x11 #define UX_MEMORY_INSUFFICIENT 0x12 #define UX_NO_TD_AVAILABLE 0x13 @@ -1214,6 +1389,7 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_DESCRIPTOR_CORRUPTED 0x42 #define UX_OVER_CURRENT_CONDITION 0x43 #define UX_DEVICE_ENUMERATION_FAILURE 0x44 +#define UX_TOO_MANY_HUB_PORTS 0x45 #define UX_DEVICE_HANDLE_UNKNOWN 0x50 #define UX_CONFIGURATION_HANDLE_UNKNOWN 0x51 @@ -1270,11 +1446,13 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_HCD_GET_FRAME_NUMBER 10 #define UX_HCD_SET_FRAME_NUMBER 11 #define UX_HCD_TRANSFER_REQUEST 12 +#define UX_HCD_TRANSFER_RUN 12 #define UX_HCD_TRANSFER_ABORT 13 #define UX_HCD_CREATE_ENDPOINT 14 #define UX_HCD_DESTROY_ENDPOINT 15 #define UX_HCD_RESET_ENDPOINT 16 #define UX_HCD_PROCESS_DONE_QUEUE 17 +#define UX_HCD_TASKS_RUN 17 #define UX_HCD_UNINITIALIZE 18 /* Define USBX DCD API function constants. */ @@ -1291,12 +1469,14 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_DCD_GET_FRAME_NUMBER 10 #define UX_DCD_SET_FRAME_NUMBER 11 #define UX_DCD_TRANSFER_REQUEST 12 +#define UX_DCD_TRANSFER_RUN 12 #define UX_DCD_TRANSFER_ABORT 13 #define UX_DCD_CREATE_ENDPOINT 14 #define UX_DCD_DESTROY_ENDPOINT 15 #define UX_DCD_RESET_ENDPOINT 16 #define UX_DCD_SET_DEVICE_ADDRESS 17 #define UX_DCD_ISR_PENDING 18 +#define UX_DCD_TASKS_RUN 18 #define UX_DCD_CHANGE_STATE 19 #define UX_DCD_STALL_ENDPOINT 20 #define UX_DCD_ENDPOINT_STATUS 21 @@ -1326,6 +1506,8 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_HOST_CLASS_COMMAND_ACTIVATE 2 #define UX_HOST_CLASS_COMMAND_DEACTIVATE 3 #define UX_HOST_CLASS_COMMAND_DESTROY 4 +#define UX_HOST_CLASS_COMMAND_ACTIVATE_START UX_HOST_CLASS_COMMAND_ACTIVATE +#define UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT 5 #define UX_SLAVE_CLASS_COMMAND_QUERY 1 #define UX_SLAVE_CLASS_COMMAND_ACTIVATE 2 @@ -1465,12 +1647,17 @@ typedef struct UX_HOST_CLASS_STRUCT UCHAR ux_host_class_name[UX_MAX_CLASS_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ #endif +#if defined(UX_HOST_STANDALONE) + UINT (*ux_host_class_task_function)(struct UX_HOST_CLASS_STRUCT *); +#endif + UINT ux_host_class_status; UINT (*ux_host_class_entry_function) (struct UX_HOST_CLASS_COMMAND_STRUCT *); VOID *ux_host_class_first_instance; VOID *ux_host_class_client; VOID *ux_host_class_media; VOID *ux_host_class_ext; + } UX_HOST_CLASS; @@ -1490,7 +1677,6 @@ typedef struct UX_TRANSFER_STRUCT UINT ux_transfer_request_value; UINT ux_transfer_request_index; VOID (*ux_transfer_request_completion_function) (struct UX_TRANSFER_STRUCT *); - UX_SEMAPHORE ux_transfer_request_semaphore; VOID *ux_transfer_request_class_instance; ULONG ux_transfer_request_maximum_length; ULONG ux_transfer_request_timeout_value; @@ -1499,9 +1685,30 @@ typedef struct UX_TRANSFER_STRUCT struct UX_TRANSFER_STRUCT *ux_transfer_request_next_transfer_request; VOID *ux_transfer_request_user_specific; +#if !defined(UX_HOST_STANDALONE) + UX_SEMAPHORE ux_transfer_request_semaphore; UX_THREAD *ux_transfer_request_thread_pending; +#else + UINT ux_transfer_request_state; + ULONG ux_transfer_request_time_start; + ULONG ux_transfer_request_flags; + struct UX_TRANSFER_STRUCT + *ux_transfer_request_next_pending; +#endif } UX_TRANSFER; +#if defined(UX_HOST_STANDALONE) +#define UX_TRANSFER_STATE_RESET(tr) ((tr)->ux_transfer_request_state = UX_STATE_RESET) +#define UX_TRANSFER_STATE_IDLE(tr) ((tr)->ux_transfer_request_state = UX_STATE_IDLE) +#define UX_TRANSFER_STATE_IS_BUSY(tr) UX_STATE_IS_BUSY((tr)->ux_transfer_request_state) +#define UX_TRANSFER_STATE_IS_IDLE(tr) ((tr)->ux_transfer_request_state == UX_STATE_IDLE) + +#define UX_TRANSFER_FLAGS_RESET(tr) ((tr)->ux_transfer_request_flags = 0) +#define UX_TRANSFER_FLAG_LOCK (0x1u << 0) +#define UX_TRANSFER_FLAG_AUTO_WAIT (0x1u << 1) /* Wait until transfer done. */ +#define UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK (0x1u << 2) /* In wait case, unlock device after transfer done. */ +#endif + /* Define USBX Endpoint Descriptor structure. */ @@ -1650,7 +1857,9 @@ typedef struct UX_DEVICE_STRUCT ULONG ux_device_power_source; struct UX_CONFIGURATION_STRUCT *ux_device_current_configuration; +#if !defined(UX_HOST_STANDALONE) UX_SEMAPHORE ux_device_protection_semaphore; +#endif struct UX_HOST_CLASS_STRUCT *ux_device_class; VOID *ux_device_class_instance; @@ -1672,8 +1881,45 @@ typedef struct UX_DEVICE_STRUCT struct UX_HUB_TT_STRUCT ux_device_hub_tt[UX_MAX_TT]; #endif + +#if defined(UX_HOST_STANDALONE) + ULONG ux_device_flags; + + struct UX_DEVICE_STRUCT + *ux_device_enum_next; + struct UX_TRANSFER_STRUCT + *ux_device_enum_trans; + union { + struct UX_DEVICE_STRUCT + *device; + struct UX_CONFIGURATION_STRUCT + *configuration; + struct UX_INTERFACE_STRUCT + *interface; + VOID *ptr; + } ux_device_enum_inst; + + ULONG ux_device_enum_wait_start; + ULONG ux_device_enum_wait_ms; + + UCHAR ux_device_enum_state; + UCHAR ux_device_dbg_state; + UCHAR ux_device_enum_next_state; + UCHAR ux_device_enum_retry; + UCHAR ux_device_enum_port_status; + UCHAR ux_device_enum_index; + UCHAR reserved[2]; + ULONG ux_device_dbg_state_count; +#endif + } UX_DEVICE; +#if defined(UX_HOST_STANDALONE) +#define UX_DEVICE_FLAG_LOCK 0x01u +#define UX_DEVICE_FLAG_RESET 0x02u +#define UX_DEVICE_FLAG_ENUM 0x04u +#define UX_DEVICE_FLAG_PROTECT 0x08u +#endif #if UX_MAX_HCD > 1 #define UX_DEVICE_HCD_GET(d) ((d)->ux_device_hcd) @@ -1901,6 +2147,10 @@ typedef struct UX_HCD_STRUCT ULONG ux_hcd_available_bandwidth; ULONG ux_hcd_version; #endif + +#if defined(UX_HOST_STANDALONE) + ULONG ux_hcd_flags; +#endif } UX_HCD; @@ -1922,13 +2172,21 @@ typedef struct UX_SLAVE_TRANSFER_STRUCT ULONG ux_slave_transfer_request_completion_code; ULONG ux_slave_transfer_request_phase; VOID (*ux_slave_transfer_request_completion_function) (struct UX_SLAVE_TRANSFER_STRUCT *); +#if defined(UX_DEVICE_STANDALONE) + ULONG ux_slave_transfer_request_state; +#else UX_SEMAPHORE ux_slave_transfer_request_semaphore; +#endif ULONG ux_slave_transfer_request_timeout; ULONG ux_slave_transfer_request_force_zlp; UCHAR ux_slave_transfer_request_setup[UX_SETUP_SIZE]; ULONG ux_slave_transfer_request_status_phase_ignore; } UX_SLAVE_TRANSFER; +#if defined(UX_DEVICE_STANDALONE) +#define UX_SLAVE_TRANSFER_STATE_RESET(tr) ((tr)->ux_slave_transfer_request_state = UX_STATE_RESET) +#endif + /* Define USBX Device Controller Endpoint structure. */ @@ -2008,6 +2266,11 @@ typedef struct UX_SLAVE_DCD_STRUCT ULONG ux_slave_dcd_device_address; UINT (*ux_slave_dcd_function) (struct UX_SLAVE_DCD_STRUCT *,UINT, VOID *); void *ux_slave_dcd_controller_hardware; + +#if defined(UX_DEVICE_STANDALONE) + UINT (*ux_device_dcd_task_function)(struct UX_SLAVE_DCD_STRUCT *); +#endif + } UX_SLAVE_DCD; /* Define USBX Device Class Command container structure. */ @@ -2046,8 +2309,12 @@ typedef struct UX_SLAVE_CLASS_STRUCT UINT (*ux_slave_class_entry_function) (struct UX_SLAVE_CLASS_COMMAND_STRUCT *); VOID *ux_slave_class_instance; VOID *ux_slave_class_client; +#if !defined(UX_DEVICE_STANDALONE) UX_THREAD ux_slave_class_thread; VOID *ux_slave_class_thread_stack; +#else + UINT (*ux_slave_class_task_function)(VOID *class_instance); +#endif VOID *ux_slave_class_interface_parameter; ULONG ux_slave_class_interface_number; ULONG ux_slave_class_configuration_number; @@ -2097,7 +2364,9 @@ typedef struct UX_SYSTEM_STRUCT #endif UINT ux_system_thread_lowest_priority; +#if !defined(UX_STANDALONE) UX_MUTEX ux_system_mutex; +#endif #ifndef UX_DISABLE_ERROR_HANDLER UINT ux_system_last_error; @@ -2142,23 +2411,40 @@ typedef struct UX_SYSTEM_HOST_STRUCT ULONG ux_system_host_max_td; ULONG ux_system_host_max_iso_td; +#if !defined(UX_HOST_STANDALONE) UCHAR *ux_system_host_enum_thread_stack; UX_THREAD ux_system_host_enum_thread; UX_SEMAPHORE ux_system_host_enum_semaphore; +#endif #if UX_MAX_DEVICES > 1 VOID (*ux_system_host_enum_hub_function) (VOID); #endif +#if !defined(UX_HOST_STANDALONE) UCHAR *ux_system_host_hcd_thread_stack; UX_THREAD ux_system_host_hcd_thread; UX_SEMAPHORE ux_system_host_hcd_semaphore; +#endif -#if defined(UX_OTG_SUPPORT) +#if defined(UX_OTG_SUPPORT) && !defined(UX_OTG_STANDALONE) UCHAR *ux_system_host_hnp_polling_thread_stack; UX_THREAD ux_system_host_hnp_polling_thread; #endif +#if defined(UX_HOST_STANDALONE) + struct UX_DEVICE_STRUCT + *ux_system_host_enum_device; + struct UX_DEVICE_STRUCT + *ux_system_host_enum_lock; + struct UX_TRANSFER_STRUCT + *ux_system_host_pending_transfers; +#if UX_MAX_DEVICES > 1 + struct UX_HOST_CLASS_HUB_STRUCT + *ux_system_host_hub_list; +#endif +#endif + UINT (*ux_system_host_change_function) (ULONG, UX_HOST_CLASS *, VOID *); } UX_SYSTEM_HOST; @@ -2235,9 +2521,11 @@ typedef struct UX_SYSTEM_SLAVE_STRUCT typedef struct UX_SYSTEM_OTG_STRUCT { +#if !defined(UX_OTG_STANDALONE) UX_THREAD ux_system_otg_thread; UCHAR *ux_system_otg_thread_stack; UX_SEMAPHORE ux_system_otg_semaphore; +#endif UINT (*ux_system_otg_function) (ULONG); ULONG ux_system_otg_mode; ULONG ux_system_otg_io; @@ -2266,7 +2554,11 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT UX_ENDPOINT *ux_host_class_dpump_bulk_in_endpoint; UX_ENDPOINT *ux_host_class_dpump_interrupt_endpoint; UINT ux_host_class_dpump_state; +#if !defined(UX_HOST_STANDALONE) UX_SEMAPHORE ux_host_class_dpump_semaphore; +#else + ULONG ux_host_class_dpump_flags; +#endif } UX_HOST_CLASS_DPUMP; @@ -2282,6 +2574,7 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT #define ux_system_initialize _ux_system_initialize #define ux_system_uninitialize _ux_system_uninitialize +#define ux_system_tasks_run _ux_system_tasks_run #define ux_host_class_hub_entry _ux_host_class_hub_entry @@ -2313,6 +2606,9 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT #define ux_host_stack_role_swap _ux_host_stack_role_swap #define ux_host_stack_device_configuration_reset _ux_host_stack_device_configuration_reset +#define ux_host_stack_tasks_run _ux_host_stack_tasks_run +#define ux_host_stack_transfer_run _ux_host_stack_transfer_run + #define ux_utility_pci_class_scan _ux_utility_pci_class_scan #define ux_utility_pci_read _ux_utility_pci_read #define ux_utility_pci_write _ux_utility_pci_write @@ -2337,6 +2633,9 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT #define ux_device_stack_transfer_request _ux_device_stack_transfer_request #define ux_device_stack_transfer_abort _ux_device_stack_transfer_abort +#define ux_device_stack_tasks_run _ux_device_stack_tasks_run +#define ux_device_stack_transfer_run _ux_device_stack_transfer_run + #define ux_hcd_ehci_initialize _ux_hcd_ehci_initialize #define ux_hcd_isp1161_initialize _ux_hcd_isp1161_initialize #define ux_hcd_ohci_initialize _ux_hcd_ohci_initialize @@ -2344,6 +2643,7 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT #define ux_dcd_sim_slave_initialize _ux_dcd_sim_slave_initialize #define ux_network_driver_init _ux_network_driver_init + #endif @@ -2352,6 +2652,7 @@ typedef struct UX_HOST_CLASS_DPUMP_STRUCT UINT ux_system_initialize(VOID *non_cached_memory_pool_start, ULONG non_cached_memory_size, VOID *cached_memory_pool_start, ULONG cached_memory_size); UINT ux_system_uninitialize(VOID); +UINT ux_system_tasks_run(VOID); /* Define USBX Host API prototypes. */ @@ -2387,6 +2688,8 @@ VOID ux_host_stack_hnp_polling_thread_entry(ULONG id); UINT ux_host_stack_role_swap(UX_DEVICE *device); UINT ux_host_stack_device_configuration_reset(UX_DEVICE *device); +UINT ux_host_stack_tasks_run(VOID); +UINT ux_host_stack_transfer_run(UX_TRANSFER *transfer_request); /* Define USBX Device API prototypes. */ @@ -2426,6 +2729,9 @@ UINT ux_device_stack_interface_start(UX_SLAVE_INTERFACE *interface); UINT ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length); UINT ux_device_stack_transfer_request_abort(UX_SLAVE_TRANSFER *transfer_request, ULONG completion_code); +UINT ux_device_stack_tasks_run(VOID); +UINT ux_device_stack_transfer_run(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length); + /* Include USBX utility and system file. */ #include "ux_utility.h" diff --git a/common/core/inc/ux_dcd_sim_slave.h b/common/core/inc/ux_dcd_sim_slave.h index 5c70cdfc..dd2e8894 100644 --- a/common/core/inc/ux_dcd_sim_slave.h +++ b/common/core/inc/ux_dcd_sim_slave.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_dcd_sim_slave.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -77,32 +80,33 @@ extern "C" { /* Define USB slave simulator error code register bits. */ -#define UX_DCD_SIM_SLAVE_ERROR_TRANSMISSION_OK 0x00000001 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_MASK 0x0000000e -#define UX_DCD_SIM_SLAVE_ERROR_CODE_SHIFT 0x00000001 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_ERROR 0x00000001 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_UNKNOWN 0x00000002 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_PACKET 0x00000003 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_TOKEN_CRC 0x00000004 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_CRC 0x00000005 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_TIME_OUT 0x00000006 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_BABBLE 0x00000007 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_EOP 0x00000008 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_NAK 0x00000009 -#define UX_DCD_SIM_SLAVE_ERROR_CODE_STALLED 0x0000000a -#define UX_DCD_SIM_SLAVE_ERROR_CODE_OVERFLOW 0x0000000b -#define UX_DCD_SIM_SLAVE_ERROR_CODE_EMPTY_PACKET 0x0000000c -#define UX_DCD_SIM_SLAVE_ERROR_CODE_BIT_STUFFING 0x0000000d -#define UX_DCD_SIM_SLAVE_ERROR_CODE_SYNC_ERROR 0x0000000e -#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_TOGGLE 0x0000000f +#define UX_DCD_SIM_SLAVE_ERROR_TRANSMISSION_OK 0x00000001u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_MASK 0x0000000eu +#define UX_DCD_SIM_SLAVE_ERROR_CODE_SHIFT 0x00000001u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_ERROR 0x00000001u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_UNKNOWN 0x00000002u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_PACKET 0x00000003u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_TOKEN_CRC 0x00000004u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_CRC 0x00000005u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_TIME_OUT 0x00000006u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_BABBLE 0x00000007u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_EOP 0x00000008u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_NAK 0x00000009u +#define UX_DCD_SIM_SLAVE_ERROR_CODE_STALLED 0x0000000au +#define UX_DCD_SIM_SLAVE_ERROR_CODE_OVERFLOW 0x0000000bu +#define UX_DCD_SIM_SLAVE_ERROR_CODE_EMPTY_PACKET 0x0000000cu +#define UX_DCD_SIM_SLAVE_ERROR_CODE_BIT_STUFFING 0x0000000du +#define UX_DCD_SIM_SLAVE_ERROR_CODE_SYNC_ERROR 0x0000000eu +#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_TOGGLE 0x0000000fu /* Define USB slave simulator physical endpoint status definition. */ -#define UX_DCD_SIM_SLAVE_ED_STATUS_UNUSED 0 -#define UX_DCD_SIM_SLAVE_ED_STATUS_USED 1 -#define UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER 2 -#define UX_DCD_SIM_SLAVE_ED_STATUS_STALLED 4 +#define UX_DCD_SIM_SLAVE_ED_STATUS_UNUSED 0u +#define UX_DCD_SIM_SLAVE_ED_STATUS_USED 1u +#define UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER 2u +#define UX_DCD_SIM_SLAVE_ED_STATUS_STALLED 4u +#define UX_DCD_SIM_SLAVE_ED_STATUS_DONE 8u /* Define USB slave simulator physical endpoint structure. */ @@ -153,11 +157,13 @@ UINT _ux_dcd_sim_slave_initialize(VOID); UINT _ux_dcd_sim_slave_initialize_complete(VOID); UINT _ux_dcd_sim_slave_state_change(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG state); UINT _ux_dcd_sim_slave_transfer_request(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_dcd_sim_slave_transfer_run(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request); UINT _ux_dcd_sim_slave_transfer_abort(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request); /* Define Device Simulator Class API prototypes. */ #define ux_dcd_sim_slave_initialize _ux_dcd_sim_slave_initialize + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/common/core/inc/ux_device_class_dpump.h b/common/core/inc/ux_device_class_dpump.h index ec54284b..659bdbaf 100644 --- a/common/core/inc/ux_device_class_dpump.h +++ b/common/core/inc/ux_device_class_dpump.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_dpump.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -47,6 +47,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -92,8 +95,20 @@ typedef struct UX_SLAVE_CLASS_DPUMP_STRUCT UX_SLAVE_ENDPOINT *ux_slave_class_dpump_bulkin_endpoint; UX_SLAVE_ENDPOINT *ux_slave_class_dpump_bulkout_endpoint; ULONG ux_slave_class_dpump_alternate_setting; - - +#if defined(UX_DEVICE_STANDALONE) + UCHAR *ux_device_class_dpump_write_buffer; + ULONG ux_device_class_dpump_write_requested_length; + ULONG ux_device_class_dpump_write_transfer_length; + ULONG ux_device_class_dpump_write_actual_length; + UINT ux_device_class_dpump_write_state; + UINT ux_device_class_dpump_write_status; + UCHAR *ux_device_class_dpump_read_buffer; + ULONG ux_device_class_dpump_read_requested_length; + ULONG ux_device_class_dpump_read_transfer_length; + ULONG ux_device_class_dpump_read_actual_length; + UINT ux_device_class_dpump_read_state; + UINT ux_device_class_dpump_read_status; +#endif } UX_SLAVE_CLASS_DPUMP; /* Define Device Data Pump Class prototypes. */ @@ -104,15 +119,21 @@ UINT _ux_device_class_dpump_deactivate(UX_SLAVE_CLASS_COMMAND *command); UINT _ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command); UINT _ux_device_class_dpump_read(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_dpump_read_run(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); UINT _ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_dpump_write_run(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); UINT _ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND *command); /* Define Device DPUMP Class API prototypes. */ #define ux_device_class_dpump_entry _ux_device_class_dpump_entry #define ux_device_class_dpump_read _ux_device_class_dpump_read +#define ux_device_class_dpump_read_run _ux_device_class_dpump_read_run #define ux_device_class_dpump_write _ux_device_class_dpump_write +#define ux_device_class_dpump_write_run _ux_device_class_dpump_write_run /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/core/inc/ux_device_stack.h b/common/core/inc/ux_device_stack.h index 85c37f01..2b514dd2 100644 --- a/common/core/inc/ux_device_stack.h +++ b/common/core/inc/ux_device_stack.h @@ -25,7 +25,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_stack.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -99,6 +102,9 @@ UINT _ux_device_stack_class_unregister(UCHAR *class_name, UINT (*class_entry_ UINT _ux_device_stack_microsoft_extension_register(ULONG vendor_request, UINT (*vendor_request_function)(ULONG, ULONG, ULONG, ULONG, UCHAR *, ULONG *)); UINT _ux_device_stack_uninitialize(VOID); +UINT _ux_device_stack_tasks_run(VOID); +UINT _ux_device_stack_transfer_run(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length); + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/common/core/inc/ux_hcd_sim_host.h b/common/core/inc/ux_hcd_sim_host.h index dafa2256..4b43bdd7 100644 --- a/common/core/inc/ux_hcd_sim_host.h +++ b/common/core/inc/ux_hcd_sim_host.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_hcd_sim_host.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,6 +58,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -132,7 +135,9 @@ typedef struct UX_HCD_SIM_HOST_STRUCT UINT ux_hcd_sim_host_periodic_scheduler_active; UINT ux_hcd_sim_host_interruptible; ULONG ux_hcd_sim_host_interrupt_count; +#if !defined(UX_HOST_STANDALONE) UX_TIMER ux_hcd_sim_host_timer; +#endif } UX_HCD_SIM_HOST; @@ -159,8 +164,9 @@ typedef struct UX_HCD_SIM_HOST_ED_STRUCT /* Define simulator host ED bitmap. */ -#define UX_HCD_SIM_HOST_ED_STATIC 0x80000000 -#define UX_HCD_SIM_HOST_ED_SKIP 0x40000000 +#define UX_HCD_SIM_HOST_ED_STATIC 0x80000000u +#define UX_HCD_SIM_HOST_ED_SKIP 0x40000000u +#define UX_HCD_SIM_HOST_ED_TRANSFER 0x00100000u /* Define simulator host TD structure. */ @@ -257,6 +263,7 @@ UINT _ux_hcd_sim_host_transaction_schedule(UX_HCD_SIM_HOST *hcd_sim_host, UX_ UINT _ux_hcd_sim_host_transfer_abort(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); UINT _ux_hcd_sim_host_port_reset(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index); +UINT _ux_hcd_sim_host_transfer_run(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); /* Define Device Simulator Class API prototypes. */ diff --git a/common/core/inc/ux_host_class_dpump.h b/common/core/inc/ux_host_class_dpump.h index 879f9b80..df5de875 100644 --- a/common/core/inc/ux_host_class_dpump.h +++ b/common/core/inc/ux_host_class_dpump.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_dpump.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -47,6 +47,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -81,6 +84,10 @@ extern "C" { #define UX_HOST_CLASS_DPUMP_GENERIC_NAME "USB DPUMP" +/* Define R/W lock bits for standalone mode. */ + +#define UX_HOST_CLASS_DPUMP_READ_LOCK (1u<<0) +#define UX_HOST_CLASS_DPUMP_WRITE_LOCK (1u<<1) /* Define Printer Class function prototypes. */ diff --git a/common/core/inc/ux_host_stack.h b/common/core/inc/ux_host_stack.h index 41a52072..06066325 100644 --- a/common/core/inc/ux_host_stack.h +++ b/common/core/inc/ux_host_stack.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_stack.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,6 +57,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -74,6 +77,32 @@ extern "C" { #endif +/* Define Host Stack enumeration state machine states. */ + +#define UX_HOST_STACK_ENUM_PORT_ENABLE (UX_STATE_STEP + 0) +#define UX_HOST_STACK_ENUM_PORT_RESET (UX_STATE_STEP + 1) +#define UX_HOST_STACK_ENUM_PORT_RESET_WAIT (UX_STATE_STEP + 2) +#define UX_HOST_STACK_ENUM_DEVICE_ADDR_SET (UX_STATE_STEP + 3) +#define UX_HOST_STACK_ENUM_DEVICE_ADDR_SENT (UX_STATE_STEP + 4) +#define UX_HOST_STACK_ENUM_DEVICE_DESCR_READ (UX_STATE_STEP + 5) +#define UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE (UX_STATE_STEP + 6) +#define UX_HOST_STACK_ENUM_CONFIG_DESCR_READ (UX_STATE_STEP + 7) +#define UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE (UX_STATE_STEP + 8) +#define UX_HOST_STACK_ENUM_CONFIG_DESCR_NEXT (UX_STATE_STEP + 9) +#define UX_HOST_STACK_ENUM_CONFIG_SET (UX_STATE_STEP + 10) +#define UX_HOST_STACK_ENUM_CONFIG_ACTIVATE (UX_STATE_STEP + 11) +#define UX_HOST_STACK_ENUM_ACTIVATE (UX_STATE_STEP + 12) +#define UX_HOST_STACK_ENUM_ACTIVATE_WAIT (UX_STATE_STEP + 13) +#define UX_HOST_STACK_ENUM_RETRY (UX_STATE_STEP + 14) +#define UX_HOST_STACK_ENUM_NEXT (UX_STATE_STEP + 15) +#define UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT (UX_STATE_STEP + 16) +#define UX_HOST_STACK_ENUM_TRANS_WAIT (UX_STATE_STEP + 17) +#define UX_HOST_STACK_ENUM_WAIT (UX_STATE_STEP + 18) +#define UX_HOST_STACK_ENUM_FAIL (UX_STATE_STEP + 19) +#define UX_HOST_STACK_ENUM_DONE (UX_STATE_STEP + 20) +#define UX_HOST_STACK_ENUM_IDLE (UX_STATE_STEP + 21) + + /* Define Host Stack component function prototypes. */ #if UX_MAX_DEVICES > 1 @@ -156,6 +185,8 @@ UINT _ux_host_stack_role_swap(UX_DEVICE *device); VOID _ux_host_stack_hnp_polling_thread_entry(ULONG id); #endif +UINT _ux_host_stack_tasks_run(VOID); +UINT _ux_host_stack_transfer_run(UX_TRANSFER *transfer_request); /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/core/inc/ux_system.h b/common/core/inc/ux_system.h index 5c64ab2d..e0e20873 100644 --- a/common/core/inc/ux_system.h +++ b/common/core/inc/ux_system.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_system.h PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,10 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* added BOS support, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added device printer name, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -62,6 +66,7 @@ UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size, VOID *cache_safe_memory_pool_start, ULONG cache_safe_memory_size); UINT _ux_system_uninitialize(VOID); +UINT _ux_system_tasks_run(VOID); #endif /* Define System component external data references. */ @@ -139,7 +144,19 @@ extern UCHAR _ux_system_slave_class_rndis_name[]; extern UCHAR _ux_system_slave_class_cdc_ecm_name[]; extern UCHAR _ux_system_slave_class_dfu_name[]; +extern UCHAR _ux_system_device_class_printer_name[]; +#if defined(UX_HOST_SIDE_ONLY) +#define _ux_system_host_tasks_run _ux_host_stack_tasks_run +#else +#define _ux_system_host_tasks_run _ux_system_tasks_run +#endif + +#if defined(UX_DEVICE_SIDE_ONLY) +#define _ux_system_device_tasks_run _ux_device_stack_tasks_run +#else +#define _ux_system_device_tasks_run _ux_system_tasks_run +#endif #endif diff --git a/common/core/inc/ux_user_sample.h b/common/core/inc/ux_user_sample.h index d144b0df..9005d351 100644 --- a/common/core/inc/ux_user_sample.h +++ b/common/core/inc/ux_user_sample.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_user.h PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -68,6 +68,16 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* added option for assert, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added option for device */ +/* audio feedback endpoint, */ +/* added option for MTP, */ +/* added options for HID */ +/* interrupt OUT support, */ +/* added option to validate */ +/* class code in enumeration, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -359,10 +369,39 @@ /* #define UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE */ +/* defined, this macro enables device audio feedback endpoint support. */ + +/* #define UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT */ + +/* Defined, device HID interrupt OUT transfer is supported. */ + +/* #define UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT */ + /* Defined, this macro enables device bi-directional-endpoint support. */ /* #define UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT */ +/* Defined, this macro enables device/host PIMA MTP support. */ + +/* #define UX_PIMA_WITH_MTP_SUPPORT */ + +/* Defined, this macro enables host device class code validation. + Only following USB-IF allowed device class code is allowed: + 0x00, 0x02 (CDC Control), 0x09 (Hub), 0x11 (Billboard), 0xDC (Diagnostic), 0xEF (MISC), 0xFF (Vendor) + Refer to https://www.usb.org/defined-class-codes for more details. + */ + +/* #define UX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE */ + +/* Defined, host HID interrupt OUT transfer is supported. */ + +/* #define UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT */ + +/* Define HID report transfer timeout value in millisecond. + The default is 10000 milliseconds. */ + +/* #define UX_HOST_CLASS_HID_REPORT_TRANSFER_TIMEOUT 10000 */ + /* Defined, this value will only enable the host side of usbx. */ /* #define UX_HOST_SIDE_ONLY */ @@ -380,7 +419,23 @@ #endif #endif -/* Defined, this value represents the maximum size of single tansfers for the SCSI data phase. +/* Defined, this macro will enable the standalone mode of usbx. */ +/* #define UX_STANDALONE */ + +/* Defined, this macro will remove the FileX dependency of host storage. + In this mode, sector access is offered instead of directly FileX FX_MEDIA support. + Use following APIs for media obtain and access: + - ux_host_class_storage_media_get : get instance of UX_HOST_CLASS_STORAGE_MEDIA + - ux_host_class_storage_media_lock : lock specific media for further read/write + - ux_host_class_storage_media_read : read sectors on locked media + - ux_host_class_storage_media_write : write sectors on locked media + - ux_host_class_storage_media_unlock : unlock media + Note it's forced defined/enabled in standalone mode of usbx. +*/ +/* #define UX_HOST_CLASS_STORAGE_NO_FILEX */ + +/* Defined, this value represents the maximum size of single transfers for the SCSI data phase. + By default it's 1024. */ #define UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE (1024 * 1) @@ -389,6 +444,29 @@ */ #define UX_DEBUG_LOG_SIZE (1024 * 16) +/* Defined, this macro represents the non-blocking function to return time tick. + This macro is used only in standalone mode. + The tick rate is defined by UX_PERIODIC_RATE. + If it's not defined, or TX is not included, a external function must be + implement in application: + extern ULONG _ux_utility_time_get(VOID); +*/ +/* #define _ux_utility_time_get() tx_time_get() */ + +/* Defined, this macro represents the non-blocking function to disable interrupts + and return old interrupt setting flags. + If it's not defined, or TX is not included, a external function must be + implement in application: + extern ALIGN_TYPE _ux_utility_interrupt_disable(VOID); +*/ +/* #define _ux_utility_interrupt_disable() _tx_thread_interrupt_disable() */ + +/* Defined, this macro represents the non-blocking function to restore interrupts. + If it's not defined, or TX is not included, a external function must be + implement in application: + extern VOID _ux_utility_interrupt_restore(ALIGN_TYPE); +*/ +/* #define _ux_utility_interrupt_restore(flags) _tx_thread_interrupt_restore(flags) */ /* Defined, this enables the assert checks inside usbx. */ #define UX_ENABLE_ASSERT diff --git a/common/core/inc/ux_utility.h b/common/core/inc/ux_utility.h index ae74c90e..fcd7e4fe 100644 --- a/common/core/inc/ux_utility.h +++ b/common/core/inc/ux_utility.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_utility.h PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -47,6 +47,9 @@ /* symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -72,10 +75,6 @@ ULONG _ux_utility_string_length_get(UCHAR *string); UINT _ux_utility_string_length_check(UCHAR *input_string, UINT *string_length_ptr, UINT max_string_length); UX_MEMORY_BLOCK *_ux_utility_memory_free_block_best_get(ULONG memory_cache_flag, ULONG memory_size_requested); VOID _ux_utility_memory_set(VOID *destination, UCHAR value, ULONG length); -UINT _ux_utility_mutex_create(UX_MUTEX *mutex, CHAR *mutex_name); -UINT _ux_utility_mutex_delete(UX_MUTEX *mutex); -VOID _ux_utility_mutex_off(UX_MUTEX *mutex); -VOID _ux_utility_mutex_on(UX_MUTEX *mutex); ULONG _ux_utility_pci_class_scan(ULONG pci_class, ULONG bus_number, ULONG device_number, ULONG function_number, ULONG *current_bus_number, ULONG *current_device_number, ULONG *current_function_number); @@ -84,15 +83,26 @@ ULONG _ux_utility_pci_read(ULONG bus_number, ULONG device_number, ULO VOID _ux_utility_pci_write(ULONG bus_number, ULONG device_number, ULONG function_number, ULONG offset, ULONG value, UINT write_size); VOID *_ux_utility_physical_address(VOID *virtual_address); -UINT _ux_utility_semaphore_create(UX_SEMAPHORE *semaphore, CHAR *semaphore_name, UINT initial_count); -UINT _ux_utility_semaphore_delete(UX_SEMAPHORE *semaphore); -UINT _ux_utility_semaphore_get(UX_SEMAPHORE *semaphore, ULONG semaphore_signal); -UINT _ux_utility_semaphore_put(UX_SEMAPHORE *semaphore); VOID _ux_utility_set_interrupt_handler(UINT irq, VOID (*interrupt_handler)(VOID)); ULONG _ux_utility_short_get(UCHAR * address); ULONG _ux_utility_short_get_big_endian(UCHAR * address); VOID _ux_utility_short_put(UCHAR * address, USHORT value); VOID _ux_utility_short_put_big_endian(UCHAR * address, USHORT value); +VOID *_ux_utility_virtual_address(VOID *physical_address); +VOID _ux_utility_unicode_to_string(UCHAR *source, UCHAR *destination); +VOID _ux_utility_string_to_unicode(UCHAR *source, UCHAR *destination); +VOID _ux_utility_debug_callback_register(VOID (*debug_callback)(UCHAR *, ULONG)); +VOID _ux_utility_delay_ms(ULONG ms_wait); + +#if !defined(UX_STANDALONE) +UINT _ux_utility_mutex_create(UX_MUTEX *mutex, CHAR *mutex_name); +UINT _ux_utility_mutex_delete(UX_MUTEX *mutex); +VOID _ux_utility_mutex_off(UX_MUTEX *mutex); +VOID _ux_utility_mutex_on(UX_MUTEX *mutex); +UINT _ux_utility_semaphore_create(UX_SEMAPHORE *semaphore, CHAR *semaphore_name, UINT initial_count); +UINT _ux_utility_semaphore_delete(UX_SEMAPHORE *semaphore); +UINT _ux_utility_semaphore_get(UX_SEMAPHORE *semaphore, ULONG semaphore_signal); +UINT _ux_utility_semaphore_put(UX_SEMAPHORE *semaphore); UINT _ux_utility_thread_create(UX_THREAD *thread_ptr, CHAR *name, VOID (*entry_function)(ULONG), ULONG entry_input, VOID *stack_start, ULONG stack_size, @@ -109,17 +119,165 @@ UINT _ux_utility_timer_create(UX_TIMER *timer, CHAR *timer_name, VOI ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT activation_flag); UINT _ux_utility_timer_delete(UX_TIMER *timer); -VOID *_ux_utility_virtual_address(VOID *physical_address); UINT _ux_utility_event_flags_create(UX_EVENT_FLAGS_GROUP*group_ptr, CHAR *name); UINT _ux_utility_event_flags_delete(UX_EVENT_FLAGS_GROUP*group_ptr); UINT _ux_utility_event_flags_get(UX_EVENT_FLAGS_GROUP*group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); UINT _ux_utility_event_flags_set(UX_EVENT_FLAGS_GROUP*group_ptr, ULONG flags_to_set, UINT set_option); -VOID _ux_utility_unicode_to_string(UCHAR *source, UCHAR *destination); -VOID _ux_utility_string_to_unicode(UCHAR *source, UCHAR *destination); -VOID _ux_utility_debug_callback_register(VOID (*debug_callback)(UCHAR *, ULONG)); -VOID _ux_utility_delay_ms(ULONG ms_wait); +#endif + +#ifndef _ux_utility_interrupt_disable +#ifdef TX_API_H +#define _ux_utility_interrupt_disable() _tx_thread_interrupt_disable() +#else +extern ALIGN_TYPE _ux_utility_interrupt_disable(VOID); +#endif +#else +extern ALIGN_TYPE _ux_utility_interrupt_disable(VOID); +#endif + +#ifndef _ux_utility_interrupt_restore +#ifdef TX_API_H +#define _ux_utility_interrupt_restore(flags) _tx_thread_interrupt_restore(flags) +#else +extern VOID _ux_utility_interrupt_restore(ALIGN_TYPE); +#endif +#else +extern VOID _ux_utility_interrupt_restore(ALIGN_TYPE); +#endif + +#ifndef _ux_utility_time_get +#ifdef TX_API_H +#define _ux_utility_time_get() tx_time_get() +#else +extern ULONG _ux_utility_time_get(VOID); +#endif +#else +extern ULONG _ux_utility_time_get(VOID); +#endif + +#ifndef _ux_utility_time_elapsed +#define _ux_utility_time_elapsed(a,b) (((b)>=(a)) ? ((b)-(a)) : (0xFFFFFFFFul-(b)+(a)+1)) +#else +extern ALIGN_TYPE _ux_utility_time_elapsed(ALIGN_TYPE, ALIGN_TYPE); +#endif + +#if !defined(UX_STANDALONE) +#define _ux_system_semaphore_create _ux_utility_semaphore_create +#define _ux_system_semaphore_create_rc _ux_utility_semaphore_create +#define _ux_system_semaphore_delete _ux_utility_semaphore_delete +#define _ux_system_thread_create_rc _ux_utility_thread_create +#define _ux_system_mutex_create _ux_utility_mutex_create +#define _ux_system_mutex_delete _ux_utility_mutex_delete +#define _ux_system_mutex_off _ux_utility_mutex_off +#define _ux_system_mutex_on _ux_utility_mutex_on +#else +#define _ux_system_semaphore_create(sem,name,cnt) do{}while(0) +#define _ux_system_semaphore_create_rc(sem,name,cnt) (UX_SUCCESS) +#define _ux_system_semaphore_delete _ux_utility_semaphore_delete +#define _ux_system_thread_create_rc(t,name,entry,entry_param,stack,stack_size,priority,preempt_threshold,time_slice,auto_start) (UX_SUCCESS) +#define _ux_system_mutex_create(mutex,name) do{}while(0) +#define _ux_system_mutex_delete(mutex) do{}while(0) +#define _ux_system_mutex_off(mutex) do{}while(0) +#define _ux_system_mutex_on(mutex) do{}while(0) +#endif + +#if !defined(UX_DEVICE_STANDALONE) +#define _ux_device_thread_create _ux_utility_thread_create +#define _ux_device_thread_delete _ux_utility_thread_delete +#define _ux_device_thread_suspend _ux_utility_thread_suspend +#define _ux_device_thread_resume _ux_utility_thread_resume +#define _ux_device_thread_relinquish _ux_utility_thread_relinquish +#define _ux_device_semaphore_create _ux_utility_semaphore_create +#define _ux_device_semaphore_created(sem) ((sem)->tx_semaphore_id != 0) +#define _ux_device_semaphore_waiting(sem) ((sem)->tx_semaphore_count != 0) +#define _ux_device_semaphore_delete _ux_utility_semaphore_delete +#define _ux_device_semaphore_get _ux_utility_semaphore_get +#define _ux_device_semaphore_put _ux_utility_semaphore_put +#define _ux_device_mutex_create _ux_utility_mutex_create +#define _ux_device_mutex_delete _ux_utility_mutex_delete +#define _ux_device_mutex_off _ux_utility_mutex_off +#define _ux_device_mutex_on _ux_utility_mutex_on +#define _ux_device_event_flags_create _ux_utility_event_flags_create +#define _ux_device_event_flags_delete _ux_utility_event_flags_delete +#define _ux_device_event_flags_get _ux_utility_event_flags_get +#define _ux_device_event_flags_set _ux_utility_event_flags_set +#else +#define _ux_device_thread_create(t,name,entry,entry_param,stack,stack_size,priority,preempt_threshold,time_slice,auto_start) (UX_SUCCESS) +#define _ux_device_thread_delete(t) do{}while(0) +#define _ux_device_thread_suspend(t) do{}while(0) +#define _ux_device_thread_resume(t) do{}while(0) +#define _ux_device_thread_relinquish(t) do{}while(0) +#define _ux_device_semaphore_create(sem,name,cnt) (UX_SUCCESS) +#define _ux_device_semaphore_created(sem) (UX_FALSE) +#define _ux_device_semaphore_waiting(sem) (UX_FALSE) +#define _ux_device_semaphore_delete(sem) do{}while(0) +#define _ux_device_semaphore_get(sem,t) (UX_SUCCESS) +#define _ux_device_semaphore_put(sem) do{}while(0) +#define _ux_device_mutex_create(mutex,name) do{}while(0) +#define _ux_device_mutex_delete(mutex) do{}while(0) +#define _ux_device_mutex_off(mutex) do{}while(0) +#define _ux_device_mutex_on(mutex) do{}while(0) +#define _ux_device_event_flags_create(g,name) do{}while(0) +#define _ux_device_event_flags_delete(g) do{}while(0) +#define _ux_device_event_flags_get(g,req,gopt,actual,wopt) do{}while(0) +#define _ux_device_event_flags_set(g,flags,option) do{}while(0) +#endif + + +#if !defined(UX_HOST_STANDALONE) +#define _ux_host_thread_create _ux_utility_thread_create +#define _ux_host_thread_created(thr) ((thr)->tx_thread_id != 0) +#define _ux_host_thread_delete _ux_utility_thread_delete +#define _ux_host_thread_resume _ux_utility_thread_resume +#define _ux_host_thread_sleep _ux_utility_thread_sleep +#define _ux_host_thread_schedule_other _ux_utility_thread_schedule_other +#define _ux_host_semaphore_create _ux_utility_semaphore_create +#define _ux_host_semaphore_created(sem) ((sem)->tx_semaphore_id != 0) +#define _ux_host_semaphore_waiting(sem) ((sem)->tx_semaphore_count != 0) +#define _ux_host_semaphore_delete _ux_utility_semaphore_delete +#define _ux_host_semaphore_get _ux_utility_semaphore_get +#define _ux_host_semaphore_get_norc _ux_utility_semaphore_get +#define _ux_host_semaphore_put _ux_utility_semaphore_put +#define _ux_host_semaphore_put_rc _ux_utility_semaphore_put +#define _ux_host_mutex_create _ux_utility_mutex_create +#define _ux_host_mutex_delete _ux_utility_mutex_delete +#define _ux_host_mutex_off _ux_utility_mutex_off +#define _ux_host_mutex_on _ux_utility_mutex_on +#define _ux_host_event_flags_create _ux_utility_event_flags_create +#define _ux_host_event_flags_delete _ux_utility_event_flags_delete +#define _ux_host_event_flags_get _ux_utility_event_flags_get +#define _ux_host_event_flags_set _ux_utility_event_flags_set +#define _ux_host_timer_create _ux_utility_timer_create +#define _ux_host_timer_delete _ux_utility_timer_delete +#else +#define _ux_host_thread_create(t,name,entry,entry_param,stack,stack_size,priority,preempt_threshold,time_slice,auto_start) (UX_SUCCESS) +#define _ux_host_thread_created(t) (UX_FALSE) +#define _ux_host_thread_delete(t) do{}while(0) +#define _ux_host_thread_resume(t) do{}while(0) +#define _ux_host_thread_sleep(t) do{}while(0) +#define _ux_host_thread_schedule_other(t) do{}while(0) +#define _ux_host_semaphore_create(sem,name,cnt) (UX_SUCCESS) +#define _ux_host_semaphore_created(sem) (UX_FALSE) +#define _ux_host_semaphore_waiting(sem) (UX_FALSE) +#define _ux_host_semaphore_delete(sem) do{}while(0) +#define _ux_host_semaphore_get(sem,t) (UX_SUCCESS) +#define _ux_host_semaphore_get_norc(sem,t) do{}while(0) +#define _ux_host_semaphore_put(sem) do{}while(0) +#define _ux_host_semaphore_put_rc(sem) (UX_SUCCESS) +#define _ux_host_mutex_create(mutex,name) do{}while(0) +#define _ux_host_mutex_delete(mutex) do{}while(0) +#define _ux_host_mutex_off(mutex) do{}while(0) +#define _ux_host_mutex_on(mutex) do{}while(0) +#define _ux_host_event_flags_create(g,name) do{}while(0) +#define _ux_host_event_flags_delete(g) do{}while(0) +#define _ux_host_event_flags_get(g,req,gopt,actual,wopt) do{}while(0) +#define _ux_host_event_flags_set(g,flags,option) do{}while(0) +#define _ux_host_timer_create(t,name,func,arg,tick0,tick1,flag) (UX_SUCCESS) +#define _ux_host_timer_delete(t) do{}while(0) +#endif + #ifdef UX_DISABLE_ERROR_HANDLER #define _ux_system_error_handler(system_level, system_context, error_code) do {} while(0) @@ -250,6 +408,9 @@ VOID* _ux_utility_memory_allocate_add_safe(ULONG align,ULONG cache,UL #define ux_utility_delay_ms _ux_utility_delay_ms #define ux_utility_error_callback_register _ux_utility_error_callback_register #define ux_system_error_handler _ux_system_error_handler + +#define ux_utility_time_get _ux_utility_time_get +#define ux_utility_time_elapsed _ux_utility_time_elapsed #endif #endif diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_reset.c b/common/core/src/ux_dcd_sim_slave_endpoint_reset.c index e4d7e741..4132843a 100644 --- a/common/core/src/ux_dcd_sim_slave_endpoint_reset.c +++ b/common/core/src/ux_dcd_sim_slave_endpoint_reset.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_dcd_sim_slave_endpoint_reset PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* cleared transfer flag and */ /* waked up suspended thread, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_dcd_sim_slave_endpoint_reset(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint) @@ -78,13 +81,21 @@ UINT _ux_dcd_sim_slave_endpoint_reset(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE UX_DCD_SIM_SLAVE_ED *ed; ULONG transfer_waiting; +#if !defined(UX_DEVICE_STANDALONE) UX_SLAVE_TRANSFER *transfer; +#endif UX_PARAMETER_NOT_USED(dcd_sim_slave); /* Get the physical endpoint address in the endpoint container. */ ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; +#if defined(UX_DEVICE_STANDALONE) + + /* Transfer pending always considered. */ + transfer_waiting = UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; +#else + /* Save waiting status for non-zero endpoints. */ if (ed -> ux_sim_slave_ed_index) { @@ -93,18 +104,23 @@ UX_SLAVE_TRANSFER *transfer; } else transfer_waiting = 0; +#endif + + /* Clear pending transfer and stall status. */ + ed -> ux_sim_slave_ed_status &= ~(ULONG)(transfer_waiting | + UX_DCD_SIM_SLAVE_ED_STATUS_STALLED | + UX_DCD_SIM_SLAVE_ED_STATUS_DONE); - /* Set the state of the endpoint to not stalled. */ - ed -> ux_sim_slave_ed_status &= ~(ULONG)(UX_DCD_SIM_SLAVE_ED_STATUS_STALLED | - transfer_waiting); +#if !defined(UX_DEVICE_STANDALONE) /* If some thread is pending, signal wakeup. */ if (transfer_waiting) { transfer = &endpoint -> ux_slave_endpoint_transfer_request; transfer -> ux_slave_transfer_request_completion_code = UX_TRANSFER_BUS_RESET; - _ux_utility_semaphore_put(&transfer -> ux_slave_transfer_request_semaphore); + _ux_device_semaphore_put(&transfer -> ux_slave_transfer_request_semaphore); } +#endif /* This function never fails. */ return(UX_SUCCESS); diff --git a/common/core/src/ux_dcd_sim_slave_function.c b/common/core/src/ux_dcd_sim_slave_function.c index f3e332b4..ee1ed62a 100644 --- a/common/core/src/ux_dcd_sim_slave_function.c +++ b/common/core/src/ux_dcd_sim_slave_function.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_dcd_sim_slave_function PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter) @@ -112,10 +115,17 @@ UX_DCD_SIM_SLAVE *dcd_sim_slave; status = _ux_dcd_sim_slave_frame_number_get(dcd_sim_slave, (ULONG *) parameter); break; +#if defined(UX_DEVICE_STANDALONE) + case UX_DCD_TRANSFER_RUN: + + status = _ux_dcd_sim_slave_transfer_run(dcd_sim_slave, (UX_SLAVE_TRANSFER *) parameter); + break; +#else case UX_DCD_TRANSFER_REQUEST: status = _ux_dcd_sim_slave_transfer_request(dcd_sim_slave, (UX_SLAVE_TRANSFER *) parameter); break; +#endif case UX_DCD_TRANSFER_ABORT: @@ -157,6 +167,11 @@ UX_DCD_SIM_SLAVE *dcd_sim_slave; status = _ux_dcd_sim_slave_endpoint_status(dcd_sim_slave, (ULONG) (ALIGN_TYPE) parameter); break; + case UX_DCD_ISR_PENDING: + + status = UX_SUCCESS; + break; + default: /* Error trap. */ diff --git a/common/core/src/ux_dcd_sim_slave_state_change.c b/common/core/src/ux_dcd_sim_slave_state_change.c index 0b0bf152..7ba52a68 100644 --- a/common/core/src/ux_dcd_sim_slave_state_change.c +++ b/common/core/src/ux_dcd_sim_slave_state_change.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_dcd_sim_slave_state_change PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ /* simulate force disconnect, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_dcd_sim_slave_state_change(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG state) @@ -94,7 +97,7 @@ UX_HCD *hcd; if (hcd) { hcd -> ux_hcd_root_hub_signal[0] = 2; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); } } diff --git a/common/core/src/ux_dcd_sim_slave_transfer_abort.c b/common/core/src/ux_dcd_sim_slave_transfer_abort.c index 9648aab2..3f67623f 100644 --- a/common/core/src/ux_dcd_sim_slave_transfer_abort.c +++ b/common/core/src/ux_dcd_sim_slave_transfer_abort.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_dcd_sim_slave_transfer_abort PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_dcd_sim_slave_transfer_abort(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request) @@ -84,7 +87,8 @@ UX_SLAVE_ENDPOINT *endpoint; ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; /* Turn off the transfer bit. */ - ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + ed -> ux_sim_slave_ed_status &= ~(ULONG) + (UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER | UX_DCD_SIM_SLAVE_ED_STATUS_DONE); /* This function never fails. */ return(UX_SUCCESS); diff --git a/common/core/src/ux_dcd_sim_slave_transfer_request.c b/common/core/src/ux_dcd_sim_slave_transfer_request.c index 41c84856..018c8f1b 100644 --- a/common/core/src/ux_dcd_sim_slave_transfer_request.c +++ b/common/core/src/ux_dcd_sim_slave_transfer_request.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_dcd_sim_slave_transfer_request PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,12 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* cleared transfer status */ +/* before semaphore wakeup to */ +/* avoid a race condition, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_dcd_sim_slave_transfer_request(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request) @@ -99,12 +105,9 @@ UINT status; ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; /* We should wait for the semaphore to wake us up. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_slave_transfer_request_semaphore, + status = _ux_device_semaphore_get(&transfer_request -> ux_slave_transfer_request_semaphore, transfer_request -> ux_slave_transfer_request_timeout); - /* Reset the ED to TRANSFER status. */ - ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; - /* Check the completion code. */ if (status != UX_SUCCESS) { @@ -112,7 +115,9 @@ UINT status; transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_COMPLETED; return(status); } - + + /* ED TRANSFER has been cleared before semaphore wakeup. */ + /* Check the transfer request completion code. We may have had a BUS reset or a device disconnection. */ if (transfer_request -> ux_slave_transfer_request_completion_code != UX_SUCCESS) diff --git a/common/core/src/ux_dcd_sim_slave_transfer_run.c b/common/core/src/ux_dcd_sim_slave_transfer_run.c new file mode 100644 index 00000000..aed81d2b --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_transfer_run.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_transfer_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will initiate a transfer to a specific endpoint. */ +/* If the endpoint is IN, the endpoint register will be set to accept */ +/* the request. */ +/* */ +/* If the endpoint is IN, the endpoint FIFO will be filled with the */ +/* buffer and the endpoint register set. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* 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_utility_semaphore_get Get semaphore */ +/* _ux_dcd_sim_slave_transfer_abort Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_transfer_run(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request) +{ + +UX_INTERRUPT_SAVE_AREA + +UX_SLAVE_ENDPOINT *endpoint; +UX_DCD_SIM_SLAVE_ED *ed; +ULONG ed_status; + + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* Get the pointer to the logical endpoint from the transfer request. */ + endpoint = transfer_request -> ux_slave_transfer_request_endpoint; + + /* Get the slave endpoint. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + UX_DISABLE + + /* Get current status. */ + ed_status = ed -> ux_sim_slave_ed_status; + + /* ED freed, must disconnected. */ + if (ed_status == UX_DCD_SIM_SLAVE_ED_STATUS_UNUSED) + { + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_BUS_RESET; + UX_RESTORE + return(UX_STATE_EXIT); + } + + /* For control endpoint, always go to next state. */ + if(ed -> ux_sim_slave_ed_index == 0) + { + UX_RESTORE + return(UX_STATE_NEXT); + } + + /* ED stalled. */ + if (ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_STALLED) + { + ed -> ux_sim_slave_ed_status = UX_DCD_SIM_SLAVE_ED_STATUS_USED; + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STALLED; + UX_RESTORE + return(UX_STATE_NEXT); + } + + /* Transfer started. */ + if (ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER) + { + if (ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_DONE) + { + ed -> ux_sim_slave_ed_status = UX_DCD_SIM_SLAVE_ED_STATUS_USED; + UX_RESTORE + return(UX_STATE_NEXT); + } + UX_RESTORE + return(UX_STATE_WAIT); + } + + /* Start transfer. */ + ed->ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + UX_RESTORE + return(UX_STATE_WAIT); + +} +#endif diff --git a/common/core/src/ux_device_class_dpump_activate.c b/common/core/src/ux_device_class_dpump_activate.c index e2f401d3..e1987d93 100644 --- a/common/core/src/ux_device_class_dpump_activate.c +++ b/common/core/src/ux_device_class_dpump_activate.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dpump_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_dpump_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -122,6 +125,12 @@ UX_SLAVE_ENDPOINT *endpoint; endpoint = endpoint -> ux_slave_endpoint_next_endpoint; } +#if defined(UX_DEVICE_STANDALONE) + + /* Reset read/write states. */ + dpump -> ux_device_class_dpump_read_state = 0; + dpump -> ux_device_class_dpump_write_state = 0; +#endif /* If there is a activate function call it. */ if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate != UX_NULL) diff --git a/common/core/src/ux_device_class_dpump_change.c b/common/core/src/ux_device_class_dpump_change.c index 6c6b90e2..eb3a4345 100644 --- a/common/core/src/ux_device_class_dpump_change.c +++ b/common/core/src/ux_device_class_dpump_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dpump_change PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND *command) @@ -144,6 +147,13 @@ UX_SLAVE_ENDPOINT *endpoint; /* Keep the alternate setting in the dpump structure. */ dpump -> ux_slave_class_dpump_alternate_setting = interface -> ux_slave_interface_descriptor.bAlternateSetting; +#if defined(UX_DEVICE_STANDALONE) + + /* Reset read/write states. */ + dpump -> ux_device_class_dpump_read_state = 0; + dpump -> ux_device_class_dpump_write_state = 0; +#endif + /* If there is an activate function call it. */ if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate != UX_NULL) diff --git a/common/core/src/ux_device_class_dpump_read_run.c b/common/core/src/ux_device_class_dpump_read_run.c new file mode 100644 index 00000000..73fad411 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_read_run.c @@ -0,0 +1,242 @@ +/**************************************************************************/ +/* */ +/* 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 DPUMP Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + +#define UX_DEVICE_CLASS_DPUMP_READ_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_DPUMP_READ_WAIT (UX_STATE_STEP + 2) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_read_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the DPUMP class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* dpump DPUMP class instance */ +/* buffer Buffer to hold data read */ +/* requested_length Bytes to read */ +/* actual_length 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_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_read_run(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +UINT read_state; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_READ, dpump, 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. */ + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* Locate the OUT endpoint. */ + endpoint = dpump -> ux_slave_class_dpump_bulkout_endpoint; + + /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */ + if (endpoint == UX_NULL) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_read_status = UX_ENDPOINT_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* All DPUMP reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + read_state = dpump -> ux_device_class_dpump_read_state; + switch(read_state) + { + case UX_STATE_RESET: + dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_START; + dpump -> ux_device_class_dpump_read_status = UX_TRANSFER_NO_ANSWER; + dpump -> ux_device_class_dpump_read_buffer = buffer; + dpump -> ux_device_class_dpump_read_requested_length = requested_length; + dpump -> ux_device_class_dpump_read_actual_length = 0; + + /* Fall through. */ + case UX_DEVICE_CLASS_DPUMP_READ_START: + + /* Get remaining requested length. */ + requested_length = dpump -> ux_device_class_dpump_read_requested_length - + dpump -> ux_device_class_dpump_read_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0) + { + *actual_length = dpump -> ux_device_class_dpump_read_actual_length; + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_read_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. */ + dpump -> ux_device_class_dpump_read_transfer_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + dpump -> ux_device_class_dpump_read_transfer_length = requested_length; + + /* Next state. */ + dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_DPUMP_READ_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + dpump -> ux_device_class_dpump_read_transfer_length, + dpump -> ux_device_class_dpump_read_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(dpump -> ux_device_class_dpump_read_buffer, + transfer_request -> ux_slave_transfer_request_data_pointer, + dpump -> ux_device_class_dpump_read_transfer_length); /* Use case of memcpy is verified. */ + + /* Next buffer address. */ + dpump -> ux_device_class_dpump_read_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + dpump -> ux_device_class_dpump_read_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + dpump -> ux_device_class_dpump_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual length. */ + *actual_length = dpump -> ux_device_class_dpump_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. */ + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/core/src/ux_device_class_dpump_thread.c b/common/core/src/ux_device_class_dpump_thread.c index 598f6e7f..a73496ef 100644 --- a/common/core/src/ux_device_class_dpump_thread.c +++ b/common/core/src/ux_device_class_dpump_thread.c @@ -37,7 +37,7 @@ VOID _ux_device_class_dpump_thread(ULONG dpump_class); /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dpump_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -45,6 +45,8 @@ VOID _ux_device_class_dpump_thread(ULONG dpump_class); /* DESCRIPTION */ /* */ /* This function is the thread of the dpump class. */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -74,6 +76,9 @@ VOID _ux_device_class_dpump_thread(ULONG dpump_class); /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_dpump_thread(ULONG dpump_class) @@ -163,7 +168,7 @@ ULONG length; /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + _ux_device_thread_suspend(&class -> ux_slave_class_thread); } } diff --git a/common/core/src/ux_device_class_dpump_write_run.c b/common/core/src/ux_device_class_dpump_write_run.c new file mode 100644 index 00000000..437ce072 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_write_run.c @@ -0,0 +1,243 @@ +/**************************************************************************/ +/* */ +/* 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 DPUMP Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + +#define UX_DEVICE_CLASS_DPUMP_WRITE_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_DPUMP_WRITE_WAIT (UX_STATE_STEP + 2) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_write_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the DPUMP class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* dpump DPUMP class instance */ +/* buffer Buffer data to write */ +/* requested_length Bytes to write */ +/* actual_length 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_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_write_run(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +UINT zlp = UX_FALSE; +UINT read_state; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_WRITE, dpump, 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. */ + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_write_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* Locate the OUT endpoint. */ + endpoint = dpump -> ux_slave_class_dpump_bulkin_endpoint; + + /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */ + if (endpoint == UX_NULL) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_write_status = UX_ENDPOINT_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* All DPUMP reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + read_state = dpump -> ux_device_class_dpump_write_state; + switch(read_state) + { + case UX_STATE_RESET: + dpump -> ux_device_class_dpump_write_state = UX_DEVICE_CLASS_DPUMP_WRITE_START; + dpump -> ux_device_class_dpump_write_status = UX_TRANSFER_NO_ANSWER; + dpump -> ux_device_class_dpump_write_buffer = buffer; + dpump -> ux_device_class_dpump_write_requested_length = requested_length; + dpump -> ux_device_class_dpump_write_actual_length = 0; + if (requested_length == 0) + zlp = UX_TRUE; + + /* Fall through. */ + case UX_DEVICE_CLASS_DPUMP_WRITE_START: + + /* Get remaining requested length. */ + requested_length = dpump -> ux_device_class_dpump_write_requested_length - + dpump -> ux_device_class_dpump_write_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0 && !zlp) + { + *actual_length = dpump -> ux_device_class_dpump_write_actual_length; + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_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. */ + dpump -> ux_device_class_dpump_write_transfer_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + dpump -> ux_device_class_dpump_write_transfer_length = requested_length; + + /* 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, + dpump -> ux_device_class_dpump_write_buffer, + dpump -> ux_device_class_dpump_write_transfer_length); /* Use case of memcpy is verified. */ + + /* Next state. */ + dpump -> ux_device_class_dpump_write_state = UX_DEVICE_CLASS_DPUMP_WRITE_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_DPUMP_WRITE_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + dpump -> ux_device_class_dpump_write_transfer_length, + dpump -> ux_device_class_dpump_write_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + dpump -> ux_device_class_dpump_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next buffer address. */ + dpump -> ux_device_class_dpump_write_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + dpump -> ux_device_class_dpump_write_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + dpump -> ux_device_class_dpump_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual length. */ + *actual_length = dpump -> ux_device_class_dpump_write_actual_length; + + /* Check ZLP case. */ + if (dpump -> ux_device_class_dpump_write_requested_length == 0) + { + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + dpump -> ux_device_class_dpump_write_state = UX_DEVICE_CLASS_DPUMP_WRITE_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + dpump -> ux_device_class_dpump_write_state = UX_STATE_RESET; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/core/src/ux_device_stack_control_request_process.c b/common/core/src/ux_device_stack_control_request_process.c index 2ae50bef..8b9e9a28 100644 --- a/common/core/src/ux_device_stack_control_request_process.c +++ b/common/core/src/ux_device_stack_control_request_process.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_control_request_process PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -84,6 +84,9 @@ /* fixed possible buffer issue */ /* for control vendor request, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added printer support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_control_request_process(UX_SLAVE_TRANSFER *transfer_request) @@ -192,6 +195,13 @@ ULONG application_data_length; for (class_index = 0; class_index < UX_MAX_SLAVE_INTERFACES; class_index ++) { + /* Get the class for the interface. */ + class = _ux_system_slave -> ux_system_slave_interface_class_array[class_index]; + + /* If class is not ready, try next. */ + if (class == UX_NULL) + continue; + /* Is the request target to an interface? */ if ((request_type & UX_REQUEST_TARGET) == UX_REQUEST_TARGET_INTERFACE) { @@ -199,17 +209,16 @@ ULONG application_data_length; /* Yes, so the request index contains the index of the interface the request is for. So if the current index does not match the request index, we should go to the next one. */ - if ((request_index & 0xFF) != class_index) - continue; + /* For printer class (0x07) GET_DEVICE_ID (0x00) the high byte of + wIndex is interface index (for recommended index sequence the interface + number is same as interface index inside configuration). */ + if (((request_index & 0xFF) != class_index) || + ((class -> ux_slave_class_interface -> ux_slave_interface_descriptor.bInterfaceClass == 0x07) && + (request == 0x00) && + *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX + 1) != class_index)) + continue; } - /* Get the class for the interface. */ - class = _ux_system_slave -> ux_system_slave_interface_class_array[class_index]; - - /* If class is not ready, try next. */ - if (class == UX_NULL) - continue; - /* Memorize the class in the command. */ class_command.ux_slave_class_command_class_ptr = class; diff --git a/common/core/src/ux_device_stack_endpoint_stall.c b/common/core/src/ux_device_stack_endpoint_stall.c index 6b7ad504..cea5f15f 100644 --- a/common/core/src/ux_device_stack_endpoint_stall.c +++ b/common/core/src/ux_device_stack_endpoint_stall.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_endpoint_stall PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT *endpoint) @@ -96,14 +99,17 @@ UINT status; /* Check if the device is in a valid state; as soon as the device is out of the RESET state, transfers occur and thus endpoints may be stalled. */ - if (_ux_system_slave -> ux_system_slave_device.ux_slave_device_state != UX_DEVICE_RESET) + if (_ux_system_slave -> ux_system_slave_device.ux_slave_device_state != UX_DEVICE_RESET && + endpoint -> ux_slave_endpoint_state != UX_ENDPOINT_HALTED) { /* Stall the endpoint. */ status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); - + /* Mark the endpoint state. */ - endpoint -> ux_slave_endpoint_state = UX_ENDPOINT_HALTED; + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != + UX_CONTROL_ENDPOINT) + endpoint -> ux_slave_endpoint_state = UX_ENDPOINT_HALTED; } /* Restore interrupts. */ diff --git a/common/core/src/ux_device_stack_initialize.c b/common/core/src/ux_device_stack_initialize.c index 15e3eb3f..c06ed617 100644 --- a/common/core/src/ux_device_stack_initialize.c +++ b/common/core/src/ux_device_stack_initialize.c @@ -42,6 +42,8 @@ UCHAR _ux_system_slave_class_cdc_ecm_name[] = "ux_ UCHAR _ux_system_slave_class_dfu_name[] = "ux_slave_class_dfu"; UCHAR _ux_system_slave_class_audio_name[] = "ux_slave_class_audio"; +UCHAR _ux_system_device_class_printer_name[] = "ux_device_class_printer"; + /* Define USBX Host variable. */ UX_SYSTEM_SLAVE *_ux_system_slave; @@ -50,7 +52,7 @@ UX_SYSTEM_SLAVE *_ux_system_slave; /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -97,6 +99,10 @@ UX_SYSTEM_SLAVE *_ux_system_slave; /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added printer support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed, @@ -383,7 +389,7 @@ UCHAR *memory; } /* Create the semaphore for the endpoint. */ - status = _ux_utility_semaphore_create(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore, + status = _ux_device_semaphore_create(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore, "ux_transfer_request_semaphore", 0); /* Check completion status. */ @@ -417,8 +423,8 @@ UCHAR *memory; { /* Delete ux_slave_transfer_request_semaphore. */ - if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); + if (_ux_device_semaphore_created(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore)) + _ux_device_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); /* Free ux_slave_transfer_request_data_pointer buffer. */ if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer) diff --git a/common/core/src/ux_device_stack_tasks_run.c b/common/core/src/ux_device_stack_tasks_run.c new file mode 100644 index 00000000..0f43d3b7 --- /dev/null +++ b/common/core/src/ux_device_stack_tasks_run.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* 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 Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs device stack and registered classes tasks. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* UX_STATE_RESET Tasks suspended */ +/* UX_STATE_IDLE Activated but no task ran */ +/* (others > UX_STATE_IDLE) Tasks running */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) run DCD function */ +/* (ux_slave_class_task_function) run Class tasks function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_tasks_run(VOID) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_CLASS *class_instance; +ULONG class_index; +UINT status; + + + status = UX_STATE_RESET; + + /* Run all DCD tasks (pending ISR handle). */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + dcd -> ux_slave_dcd_function(dcd, UX_DCD_TASKS_RUN, UX_NULL); + + /* Run all Class instance tasks. */ + class_instance = _ux_system_slave -> ux_system_slave_class_array; + for (class_index = 0; class_index < UX_SYSTEM_DEVICE_MAX_CLASS_GET(); class_index++) + { + + /* Skip classes not used. */ + if (class_instance -> ux_slave_class_status == UX_UNUSED) + continue; + + /* Skip classes has no task function. */ + if (class_instance -> ux_slave_class_task_function == UX_NULL) + continue; + + /* Invoke task function. */ + status |= class_instance -> ux_slave_class_task_function(class_instance -> ux_slave_class_instance); + + /* Move to the next class. */ + class_instance ++; + } + + /* Return overall status. */ + return(status); +} +#endif diff --git a/common/core/src/ux_device_stack_transfer_abort.c b/common/core/src/ux_device_stack_transfer_abort.c index 9b17b5ac..1e8fce36 100644 --- a/common/core/src/ux_device_stack_transfer_abort.c +++ b/common/core/src/ux_device_stack_transfer_abort.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_transfer_abort PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,10 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* assigned aborting code, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_transfer_abort(UX_SLAVE_TRANSFER *transfer_request, ULONG completion_code) @@ -94,7 +98,7 @@ UX_SLAVE_DCD *dcd; dcd = &_ux_system_slave -> ux_system_slave_dcd; /* Sets the completion code due to bus reset. */ - transfer_request -> ux_slave_transfer_request_completion_code = UX_TRANSFER_BUS_RESET; + transfer_request -> ux_slave_transfer_request_completion_code = completion_code; /* Ensure we're not preempted by the transfer completion ISR. */ UX_DISABLE @@ -116,7 +120,7 @@ UX_SLAVE_DCD *dcd; transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_ABORT; /* Wake up the device driver who is waiting on the semaphore. */ - _ux_utility_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore); + _ux_device_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore); } else { diff --git a/common/core/src/ux_device_stack_transfer_request.c b/common/core/src/ux_device_stack_transfer_request.c index 08e2353d..1d2d3c0d 100644 --- a/common/core/src/ux_device_stack_transfer_request.c +++ b/common/core/src/ux_device_stack_transfer_request.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_transfer_request PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,13 +76,29 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length) { - +#if defined(UX_DEVICE_STANDALONE) +UINT status; + + /* Start a transfer request without waiting it end. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + status = _ux_device_stack_transfer_run(transfer_request, slave_length, host_length); + if (status == UX_STATE_LOCK) + return(UX_BUSY); + if (status < UX_STATE_NEXT) + return(transfer_request -> ux_slave_transfer_request_completion_code); + + /* Started/done, things will be done in BG */ + return(UX_SUCCESS); +#else UX_INTERRUPT_SAVE_AREA UX_SLAVE_DCD *dcd; @@ -184,5 +200,6 @@ ULONG device_state; /* And return the status. */ return(status); +#endif } diff --git a/common/core/src/ux_device_stack_transfer_run.c b/common/core/src/ux_device_stack_transfer_run.c new file mode 100644 index 00000000..25798dd5 --- /dev/null +++ b/common/core/src/ux_device_stack_transfer_run.c @@ -0,0 +1,220 @@ +/**************************************************************************/ +/* */ +/* 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 Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + +#define UX_DEVICE_STACK_TRANSFER_STATE_HALT_WAIT (UX_STATE_STACK_STEP + 0) +#define UX_DEVICE_STACK_TRANSFER_STATE_TRAN_WAIT (UX_STATE_STACK_STEP + 1) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_transfer_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a USB transaction. On entry the */ +/* transfer request gives the endpoint pipe selected for this */ +/* transaction and the parameters associated with the transfer */ +/* (data payload, length of transaction). */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* slave_length Length returned by host */ +/* host_length Length asked by host */ +/* */ +/* 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_slave_dcd_function) Slave DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_transfer_run(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length) +{ + +UX_SLAVE_DCD *dcd; +UINT status; +UINT state; +UX_SLAVE_ENDPOINT *endpoint; +ULONG device_state; + + + /* Do we have to skip this transfer? */ + if (transfer_request -> ux_slave_transfer_request_status_phase_ignore == UX_TRUE) + { + transfer_request -> ux_slave_transfer_request_completion_code = UX_SUCCESS; + transfer_request -> ux_slave_transfer_request_state = UX_STATE_NEXT; + return(UX_STATE_NEXT); + } + + /* Get the device state. */ + device_state = _ux_system_slave -> ux_system_slave_device.ux_slave_device_state; + + /* We can only transfer when the device is ATTACHED, ADDRESSED OR CONFIGURED. */ + if (!(device_state == UX_DEVICE_ATTACHED) && + !(device_state == UX_DEVICE_ADDRESSED) && + !(device_state == UX_DEVICE_CONFIGURED)) + { + transfer_request -> ux_slave_transfer_request_completion_code = UX_TRANSFER_NOT_READY; + transfer_request -> ux_slave_transfer_request_state = UX_STATE_RESET; + return(UX_STATE_EXIT); + } + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the endpoint associated with this transaction. */ + endpoint = transfer_request -> ux_slave_transfer_request_endpoint; + + /* Process states. */ + state = transfer_request -> ux_slave_transfer_request_state; + switch(state) + { + case UX_STATE_RESET: + + /* Prepare transfer parameters. */ + + /* If the endpoint is non Control, check the endpoint direction and set the data phase direction. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_CONTROL_ENDPOINT) + { + + /* Isolate the direction from the endpoint address. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + else + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_IN; + } + + /* See if we need to force a zero length packet at the end of the transfer. + This happens on a DATA IN and when the host requested length is not met + and the last packet is on a boundary. If slave_length is zero, then it is + a explicit ZLP request, no need to force ZLP. */ + if ((transfer_request -> ux_slave_transfer_request_phase == UX_TRANSFER_PHASE_DATA_OUT) && + (slave_length != 0) && (host_length != slave_length) && + (slave_length % endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) == 0) + { + + /* If so force Zero Length Packet. */ + transfer_request -> ux_slave_transfer_request_force_zlp = UX_TRUE; + } + else + { + + /* Condition is not met, do not force a Zero Length Packet. */ + transfer_request -> ux_slave_transfer_request_force_zlp = UX_FALSE; + } + + /* Reset the number of bytes sent/received. */ + transfer_request -> ux_slave_transfer_request_actual_length = 0; + + /* Determine how many bytes to send in this transaction. We keep track of the original + length and have a working length. */ + transfer_request -> ux_slave_transfer_request_requested_length = slave_length; + transfer_request -> ux_slave_transfer_request_in_transfer_length = slave_length; + + /* Save the buffer pointer. */ + transfer_request -> ux_slave_transfer_request_current_data_pointer = + transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Set the transfer to pending. */ + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_PENDING; + + /* Next state. */ + transfer_request -> ux_slave_transfer_request_state = UX_DEVICE_STACK_TRANSFER_STATE_HALT_WAIT; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_TRANSFER_REQUEST, transfer_request, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Fall through. */ + case UX_DEVICE_STACK_TRANSFER_STATE_HALT_WAIT: + + /* If the endpoint is non Control, check the endpoint direction and set the data phase direction. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_CONTROL_ENDPOINT) + { + + /* Return WAIT until halt cleared. */ + if (endpoint -> ux_slave_endpoint_state == UX_ENDPOINT_HALTED) + return(UX_STATE_WAIT); + + } + + /* Next state. */ + transfer_request -> ux_slave_transfer_request_state = UX_DEVICE_STACK_TRANSFER_STATE_TRAN_WAIT; + + /* Start background transfer immediately. */ + /* Fall through. */ + case UX_DEVICE_STACK_TRANSFER_STATE_TRAN_WAIT: + + /* Call the DCD driver transfer function. */ + /* Transfer state is adjusted inside DCD driver. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_TRANSFER_RUN, transfer_request); + + /* Any error case or normal end: reset state for next transfer. */ + if (status < UX_STATE_WAIT) + { + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + } + break; + + default: /* Error case, return EXIT. */ + transfer_request -> ux_slave_transfer_request_state = UX_STATE_RESET; + return(UX_STATE_EXIT); + } + + /* And return the status. */ + return(status); +} +#endif diff --git a/common/core/src/ux_device_stack_uninitialize.c b/common/core/src/ux_device_stack_uninitialize.c index 6d163e26..18d5a5f2 100644 --- a/common/core/src/ux_device_stack_uninitialize.c +++ b/common/core/src/ux_device_stack_uninitialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_stack_uninitialize PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* fixed uninitialize in case */ /* there is no EP except EP0, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_stack_uninitialize(VOID) @@ -107,7 +110,7 @@ ULONG endpoints_found; _ux_utility_memory_free(endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer); /* Remove the TX semaphore for the endpoint. */ - _ux_utility_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); + _ux_device_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); /* Next endpoint. */ endpoints_pool++; diff --git a/common/core/src/ux_hcd_sim_host_endpoint_reset.c b/common/core/src/ux_hcd_sim_host_endpoint_reset.c index 20e1ec8f..fef3c354 100644 --- a/common/core/src/ux_hcd_sim_host_endpoint_reset.c +++ b/common/core/src/ux_hcd_sim_host_endpoint_reset.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_endpoint_reset PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_endpoint_reset(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) @@ -82,6 +85,11 @@ UX_HCD_SIM_HOST_ED *ed; /* Reset the data0/data1 toggle bit in the Head TD. */ ed -> ux_sim_host_ed_toggle = 0; +#if defined(UX_HOST_STANDALONE) + /* Reset transfer status. */ + ed -> ux_sim_host_ed_status &= ~UX_HCD_SIM_HOST_ED_TRANSFER; +#endif + /* This operation never fails. */ return(UX_SUCCESS); } diff --git a/common/core/src/ux_hcd_sim_host_entry.c b/common/core/src/ux_hcd_sim_host_entry.c index e4dec964..b02e0809 100644 --- a/common/core/src/ux_hcd_sim_host_entry.c +++ b/common/core/src/ux_hcd_sim_host_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_entry PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -88,6 +88,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* added HCD uninitialize, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter) @@ -190,7 +193,11 @@ UX_HCD_SIM_HOST *hcd_sim_host; case UX_HCD_TRANSFER_REQUEST: +#if defined(UX_HOST_STANDALONE) + status = _ux_hcd_sim_host_transfer_run(hcd_sim_host, (UX_TRANSFER *) parameter); +#else status = _ux_hcd_sim_host_request_transfer(hcd_sim_host, (UX_TRANSFER *) parameter); +#endif break; diff --git a/common/core/src/ux_hcd_sim_host_initialize.c b/common/core/src/ux_hcd_sim_host_initialize.c index ed1cf88f..65a3947c 100644 --- a/common/core/src/ux_hcd_sim_host_initialize.c +++ b/common/core/src/ux_hcd_sim_host_initialize.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_initialize PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ /* added link with DCD, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_initialize(UX_HCD *hcd) @@ -155,7 +158,7 @@ UINT status; hcd_sim_host -> ux_hcd_sim_host_periodic_scheduler_active = 0; /* We start a timer that will invoke the simulator every timer tick. */ - status = _ux_utility_timer_create(&hcd_sim_host -> ux_hcd_sim_host_timer, "USBX Simulation Timer", + status = _ux_host_timer_create(&hcd_sim_host -> ux_hcd_sim_host_timer, "USBX Simulation Timer", _ux_hcd_sim_host_timer_function, (ULONG) (ALIGN_TYPE) hcd_sim_host, 1, 1, UX_AUTO_ACTIVATE); } @@ -206,7 +209,7 @@ UINT status; /* We need to simulate a Root HUB Status Change for the USB stack since the simulator has not root HUB per se. */ - status = _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + status = _ux_host_semaphore_put_rc(&_ux_system_host -> ux_system_host_enum_semaphore); if (status != UX_SUCCESS) /* Resources are still ready but diff --git a/common/core/src/ux_hcd_sim_host_port_reset.c b/common/core/src/ux_hcd_sim_host_port_reset.c index 98077973..1a5a30d3 100644 --- a/common/core/src/ux_hcd_sim_host_port_reset.c +++ b/common/core/src/ux_hcd_sim_host_port_reset.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_port_reset PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 08-02-2021 Wen Wang Modified comment(s), */ /* fixed spelling error, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_port_reset(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index) @@ -80,6 +83,10 @@ UINT _ux_hcd_sim_host_port_reset(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_inde UX_SLAVE_DEVICE *device; +#if defined(UX_HOST_STANDALONE) + /* No port reset wait simulated, return _STATE_NEXT later to move state. */ +#endif + UX_PARAMETER_NOT_USED(hcd_sim_host); UX_PARAMETER_NOT_USED(port_index); @@ -108,6 +115,10 @@ UX_SLAVE_DEVICE *device; device -> ux_slave_device_state = UX_DEVICE_ATTACHED; /* This function should never fail. */ +#if defined(UX_HOST_STANDALONE) + return(UX_STATE_NEXT); +#else return(UX_SUCCESS); +#endif } diff --git a/common/core/src/ux_hcd_sim_host_regular_td_obtain.c b/common/core/src/ux_hcd_sim_host_regular_td_obtain.c index f3973ef6..f460bb73 100644 --- a/common/core/src/ux_hcd_sim_host_regular_td_obtain.c +++ b/common/core/src/ux_hcd_sim_host_regular_td_obtain.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_regular_td_obtain PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UX_HCD_SIM_HOST_TD *_ux_hcd_sim_host_regular_td_obtain(UX_HCD_SIM_HOST *hcd_sim_host) @@ -80,7 +83,7 @@ ULONG td_index; /* Get the mutex as this is a critical section. */ - _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + _ux_host_mutex_on(&_ux_system -> ux_system_mutex); /* Start the search from the beginning of the list. */ td = hcd_sim_host -> ux_hcd_sim_host_td_list; @@ -99,7 +102,7 @@ ULONG td_index; td -> ux_sim_host_td_status = UX_USED; /* Release the mutex protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_host_mutex_off(&_ux_system -> ux_system_mutex); /* Return the TD pointer. */ return(td); @@ -112,7 +115,7 @@ ULONG td_index; /* There is no available TD in the TD list. */ /* Release the mutex protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_host_mutex_off(&_ux_system -> ux_system_mutex); /* Return a NULL pointer. */ return(UX_NULL); diff --git a/common/core/src/ux_hcd_sim_host_request_control_transfer.c b/common/core/src/ux_hcd_sim_host_request_control_transfer.c index f1d8de1e..1701422e 100644 --- a/common/core/src/ux_hcd_sim_host_request_control_transfer.c +++ b/common/core/src/ux_hcd_sim_host_request_control_transfer.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_request_control_transfer PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_request_control_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) @@ -92,11 +95,13 @@ UX_HCD_SIM_HOST_TD *tail_td; UX_HCD_SIM_HOST_TD *status_td; UX_HCD_SIM_HOST_TD *start_data_td; UX_HCD_SIM_HOST_TD *next_data_td; -UINT status; ULONG transfer_request_payload_length; ULONG control_packet_payload_length; UCHAR *data_pointer; - +#if !defined(UX_HOST_STANDALONE) +UINT status; +#endif + /* Get the pointer to the endpoint. */ endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; @@ -294,8 +299,12 @@ UCHAR *data_pointer; /* Now we can tell the scheduler to wake up. */ hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_FALSE; - /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); +#if defined(UX_HOST_STANDALONE) + /* Transfer started in background, fine. */ + return(UX_SUCCESS); +#else + /* Wait for the completion of the transfer request. */ + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -320,5 +329,5 @@ UCHAR *data_pointer; /* Return completion to caller. */ return(transfer_request -> ux_transfer_request_completion_code); +#endif } - diff --git a/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c b/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c index 0c961f1f..86fd6dc9 100644 --- a/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c +++ b/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_request_isochronous_transfer PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed payload calculation, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_request_isochronous_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) @@ -157,6 +160,9 @@ ULONG n_trans, packet_size; data_td -> ux_sim_host_iso_td_direction = UX_HCD_SIM_HOST_TD_OUT; + /* Mark the TD with the DATA phase. */ + data_td -> ux_sim_host_iso_td_status |= UX_HCD_SIM_HOST_TD_DATA_PHASE; + /* Set the frame number. */ ed -> ux_sim_host_ed_frame = current_frame_number; diff --git a/common/core/src/ux_hcd_sim_host_request_transfer.c b/common/core/src/ux_hcd_sim_host_request_transfer.c index b422e2d5..a7720a77 100644 --- a/common/core/src/ux_hcd_sim_host_request_transfer.c +++ b/common/core/src/ux_hcd_sim_host_request_transfer.c @@ -29,12 +29,13 @@ #include "ux_hcd_sim_host.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_request_transfer PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +78,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_request_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) @@ -123,4 +127,4 @@ UINT status = 0; so no error checking. */ return(status); } - +#endif diff --git a/common/core/src/ux_hcd_sim_host_timer_function.c b/common/core/src/ux_hcd_sim_host_timer_function.c index 673fbe05..37c98843 100644 --- a/common/core/src/ux_hcd_sim_host_timer_function.c +++ b/common/core/src/ux_hcd_sim_host_timer_function.c @@ -27,6 +27,8 @@ #include "ux_api.h" #include "ux_hcd_sim_host.h" + +#if !defined(UX_HOST_STANDALONE) #include "tx_timer.h" @@ -35,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_timer_function PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +46,8 @@ /* */ /* This function is the timer function of the simulator. It is */ /* invoked on a timer every tick. */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -68,6 +72,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used macros to configure */ +/* for RTOS mode compile, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_sim_host_timer_function(ULONG hcd_sim_host_addr) @@ -92,8 +100,7 @@ UX_HCD *hcd; /* Wake up the thread for the controller transaction processing. */ hcd -> ux_hcd_thread_signal++; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); } } - - +#endif diff --git a/common/core/src/ux_hcd_sim_host_transaction_schedule.c b/common/core/src/ux_hcd_sim_host_transaction_schedule.c index 0a4562fa..4fb6f5aa 100644 --- a/common/core/src/ux_hcd_sim_host_transaction_schedule.c +++ b/common/core/src/ux_hcd_sim_host_transaction_schedule.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_transaction_schedule PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,12 @@ /* improved check for tests, */ /* added error trap case, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* cleared transfer status */ +/* before semaphore wakeup to */ +/* avoid a race condition, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_transaction_schedule(UX_HCD_SIM_HOST *hcd_sim_host, UX_HCD_SIM_HOST_ED *ed) @@ -176,6 +182,13 @@ UX_SLAVE_DCD *dcd; td -> ux_sim_host_td_buffer, td -> ux_sim_host_td_length); /* Use case of memcpy is verified. */ +#if defined(UX_HOST_STANDALONE) + + /* The setup buffer is allocated, release it since it's used. */ + _ux_utility_memory_free(td -> ux_sim_host_td_buffer); + td -> ux_sim_host_td_buffer = UX_NULL; +#endif + /* The setup phase never fails. We acknowledge the transfer code here by taking the TD out of the endpoint. */ ed -> ux_sim_host_ed_head_td = td -> ux_sim_host_td_next_td; @@ -334,7 +347,7 @@ UX_SLAVE_DCD *dcd; td -> ux_sim_host_td_status = UX_UNUSED; /* Then, we wake up the host. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } } else @@ -356,7 +369,7 @@ UX_SLAVE_DCD *dcd; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_STALLED, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Wake up the host side. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* Clean up this ED. */ head_td = ed -> ux_sim_host_ed_head_td; @@ -475,11 +488,14 @@ UX_SLAVE_DCD *dcd; if (slave_ed -> ux_sim_slave_ed_index != 0) { - /* Reset the ED to NO TRANSFER status. */ + /* Clear pending flag. */ slave_ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + /* Set done flag. */ + slave_ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_DONE; + /* Wake up the slave side. */ - _ux_utility_semaphore_put(&slave_transfer_request -> ux_slave_transfer_request_semaphore); + _ux_device_semaphore_put(&slave_transfer_request -> ux_slave_transfer_request_semaphore); } } @@ -525,7 +541,7 @@ UX_SLAVE_DCD *dcd; transfer_request -> ux_transfer_request_completion_function(transfer_request); /* Wake up the host side. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } } } diff --git a/common/core/src/ux_hcd_sim_host_transfer_abort.c b/common/core/src/ux_hcd_sim_host_transfer_abort.c index c7dfbd23..dc2125d3 100644 --- a/common/core/src/ux_hcd_sim_host_transfer_abort.c +++ b/common/core/src/ux_hcd_sim_host_transfer_abort.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_transfer_abort PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_transfer_abort(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) @@ -100,11 +103,15 @@ UX_HCD_SIM_HOST_TD *tail_td; return(UX_ENDPOINT_HANDLE_UNKNOWN); } +#if defined(UX_HOST_STANDALONE) + ed -> ux_sim_host_ed_status |= UX_HCD_SIM_HOST_ED_SKIP; +#else /* The endpoint may be active. If so, set the skip bit. */ ed -> ux_sim_host_ed_status |= UX_HCD_SIM_HOST_ED_SKIP; /* Wait for the controller to finish the current frame processing. */ _ux_utility_delay_ms(1); +#endif /* Remove all the TDs from this ED and leave the head and tail pointing to the dummy TD. */ head_td = ed -> ux_sim_host_ed_head_td; @@ -124,8 +131,13 @@ UX_HCD_SIM_HOST_TD *tail_td; head_td = ed -> ux_sim_host_ed_head_td; } +#if defined(UX_HOST_STANDALONE) + /* Remove the skip and transfer bits in the ED. */ + ed -> ux_sim_host_ed_status &= ~(UX_HCD_SIM_HOST_ED_SKIP|UX_HCD_SIM_HOST_ED_TRANSFER); +#else /* Remove the reset bit in the ED. */ - ed -> ux_sim_host_ed_status = (ULONG)~UX_HCD_SIM_HOST_ED_SKIP; + ed -> ux_sim_host_ed_status &= (ULONG)~UX_HCD_SIM_HOST_ED_SKIP; +#endif /* Return successful completion. */ return(UX_SUCCESS); diff --git a/common/core/src/ux_hcd_sim_host_transfer_run.c b/common/core/src/ux_hcd_sim_host_transfer_run.c new file mode 100644 index 00000000..38c46b69 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_transfer_run.c @@ -0,0 +1,166 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_transfer_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the handler for all the transactions on the USB. */ +/* The transfer request passed as parameter contains the endpoint and */ +/* the device descriptors in addition to the type of transaction de */ +/* be executed. This function routes the transfer request to */ +/* according to the type of transfer to be executed. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_request_bulk_transfer Request bulk transfer */ +/* _ux_hcd_sim_host_request_control_transfer Request control */ +/* transfer */ +/* _ux_hcd_sim_host_request_interrupt_transfer Request interrupt */ +/* transfer */ +/* _ux_hcd_sim_host_request_isochronous_transfer Request isochronous */ +/* transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_transfer_run(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_INTERRUPT_SAVE_AREA +UX_ENDPOINT *endpoint; +UX_HCD_SIM_HOST_ED *ed; +UINT status = 0; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Sanity check. */ + if (endpoint == UX_NULL) + return(UX_STATE_EXIT); + + /* Get ED. */ + ed = (UX_HCD_SIM_HOST_ED *)endpoint -> ux_endpoint_ed; + + /* Sanity check. */ + if (ed == UX_NULL) + return(UX_STATE_EXIT); + + UX_DISABLE + + /* If transfer started, check status. */ + if (ed -> ux_sim_host_ed_status & UX_HCD_SIM_HOST_ED_TRANSFER) + { + if (ed -> ux_sim_host_ed_head_td != ed -> ux_sim_host_ed_tail_td) + { + UX_RESTORE + return(UX_STATE_WAIT); + } + + /* Check if it's transfer waiting state. */ + if (transfer_request -> ux_transfer_request_status != UX_TRANSFER_STATUS_NOT_PENDING) + { + + /* Yes, polling pending status, report and transfer done. */ + ed -> ux_sim_host_ed_status &= ~UX_HCD_SIM_HOST_ED_TRANSFER; + UX_RESTORE + return(UX_STATE_NEXT); + } + + /* Maybe transfer completed but state not reported yet. */ + } + ed -> ux_sim_host_ed_status |= UX_HCD_SIM_HOST_ED_TRANSFER; + transfer_request -> ux_transfer_request_status = UX_TRANSFER_STATUS_PENDING; + + UX_RESTORE + + /* We reset the actual length field of the transfer request as a safety measure. */ + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Isolate the endpoint type and route the transfer request. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + status = _ux_hcd_sim_host_request_control_transfer(hcd_sim_host, transfer_request); + break; + + + case UX_BULK_ENDPOINT: + + status = _ux_hcd_sim_host_request_bulk_transfer(hcd_sim_host, transfer_request); + break; + + case UX_INTERRUPT_ENDPOINT: + + status = _ux_hcd_sim_host_request_interrupt_transfer(hcd_sim_host, transfer_request); + break; + + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_sim_host_request_isochronous_transfer(hcd_sim_host, transfer_request); + break; + + } + + return (status == UX_SUCCESS) ? (UX_STATE_WAIT) : (UX_STATE_ERROR); +} +#endif diff --git a/common/core/src/ux_hcd_sim_host_uninitialize.c b/common/core/src/ux_hcd_sim_host_uninitialize.c index 5cbe0811..bfd8a480 100644 --- a/common/core/src/ux_hcd_sim_host_uninitialize.c +++ b/common/core/src/ux_hcd_sim_host_uninitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_sim_host_uninitialize PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,13 +67,19 @@ /* DATE NAME DESCRIPTION */ /* */ /* 11-09-2020 Chaoqiong Xiao Initial Version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_sim_host_uninitialize(UX_HCD_SIM_HOST *hcd_sim_host) { -UX_HCD *hcd = hcd_sim_host -> ux_hcd_sim_host_hcd_owner; - +UX_HCD *hcd = hcd_sim_host -> ux_hcd_sim_host_hcd_owner; +#if defined(UX_HOST_STANDALONE) +UX_HCD_SIM_HOST_TD *td; +UINT td_index; +#endif /* Set the state of the controller to HALTED first. */ hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; @@ -82,7 +88,31 @@ UX_HCD *hcd = hcd_sim_host -> ux_hcd_sim_host_hcd_owner; hcd_sim_host = (UX_HCD_SIM_HOST *)hcd -> ux_hcd_controller_hardware; /* Delete timer. */ - _ux_utility_timer_delete(&hcd_sim_host -> ux_hcd_sim_host_timer); + _ux_host_timer_delete(&hcd_sim_host -> ux_hcd_sim_host_timer); + +#if defined(UX_HOST_STANDALONE) + + /* Check if there is pending SETUP TD, free buffers of them. */ + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_td; td_index++) + { + td = &hcd_sim_host -> ux_hcd_sim_host_td_list[td_index]; + + /* Skip free TDs. */ + if (td -> ux_sim_host_td_status == UX_UNUSED) + continue; + + /* Skip TDs not for setup. */ + if ((td -> ux_sim_host_td_status & UX_HCD_SIM_HOST_TD_SETUP_PHASE) == 0) + continue; + + /* Skip TDs already freed. */ + if (td -> ux_sim_host_td_buffer == UX_NULL) + continue; + + /* Free the TD buffer. */ + _ux_utility_memory_free(td -> ux_sim_host_td_buffer); + } +#endif /* Free TD/ED memories. */ _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_iso_td_list); diff --git a/common/core/src/ux_host_class_dpump_activate.c b/common/core/src/ux_host_class_dpump_activate.c index c9b48637..14edf6c7 100644 --- a/common/core/src/ux_host_class_dpump_activate.c +++ b/common/core/src/ux_host_class_dpump_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_activate(UX_HOST_CLASS_COMMAND *command) @@ -120,7 +123,7 @@ UINT status; status = _ux_host_class_dpump_endpoints_get(dpump); /* Create the semaphore to protect 2 threads from accessing the same dpump instance. */ - status = _ux_utility_semaphore_create(&dpump -> ux_host_class_dpump_semaphore, "ux_dpump_semaphore", 1); + status = _ux_host_semaphore_create(&dpump -> ux_host_class_dpump_semaphore, "ux_dpump_semaphore", 1); if (status != UX_SUCCESS) return(UX_SEMAPHORE_ERROR); diff --git a/common/core/src/ux_host_class_dpump_deactivate.c b/common/core/src/ux_host_class_dpump_deactivate.c index 23426c32..b640a6f4 100644 --- a/common/core/src/ux_host_class_dpump_deactivate.c +++ b/common/core/src/ux_host_class_dpump_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -90,7 +93,7 @@ UINT status; dpump -> ux_host_class_dpump_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) { @@ -107,13 +110,13 @@ UINT status; _ux_host_stack_endpoint_transfer_abort(dpump -> ux_host_class_dpump_bulk_in_endpoint); /* If the class instance was busy, let it finish properly and not return. */ - _ux_utility_thread_sleep(UX_ENUMERATION_THREAD_WAIT); + _ux_host_thread_sleep(UX_ENUMERATION_THREAD_WAIT); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(dpump -> ux_host_class_dpump_class, (VOID *) dpump); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&dpump -> ux_host_class_dpump_semaphore); + _ux_host_semaphore_delete(&dpump -> ux_host_class_dpump_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/core/src/ux_host_class_dpump_endpoints_get.c b/common/core/src/ux_host_class_dpump_endpoints_get.c index 453e4813..d57e13da 100644 --- a/common/core/src/ux_host_class_dpump_endpoints_get.c +++ b/common/core/src/ux_host_class_dpump_endpoints_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_endpoints_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_endpoints_get(UX_HOST_CLASS_DPUMP *dpump) @@ -98,6 +101,10 @@ UX_ENDPOINT *endpoint; /* This transfer_request always have the OUT direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + /* Setup default timeout value. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT; + /* We have found the bulk endpoint, save it. */ dpump -> ux_host_class_dpump_bulk_out_endpoint = endpoint; break; @@ -139,6 +146,10 @@ UX_ENDPOINT *endpoint; /* This transfer_request always have the IN direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + /* Setup default timeout value. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT; + /* We have found the bulk endpoint, save it. */ dpump -> ux_host_class_dpump_bulk_in_endpoint = endpoint; break; diff --git a/common/core/src/ux_host_class_dpump_entry.c b/common/core/src/ux_host_class_dpump_entry.c index 58bfaf16..14b83ce2 100644 --- a/common/core/src/ux_host_class_dpump_entry.c +++ b/common/core/src/ux_host_class_dpump_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command) @@ -102,6 +105,9 @@ UINT status; status = _ux_host_class_dpump_activate(command); return(status); + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + return(UX_STATE_NEXT); + case UX_HOST_CLASS_COMMAND_DEACTIVATE: /* The deactivate command is used when the device has been extracted either diff --git a/common/core/src/ux_host_class_dpump_read.c b/common/core/src/ux_host_class_dpump_read.c index 806b8012..c6515902 100644 --- a/common/core/src/ux_host_class_dpump_read.c +++ b/common/core/src/ux_host_class_dpump_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,12 +76,18 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_read(UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer, ULONG requested_length, ULONG *actual_length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; @@ -103,16 +109,33 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (dpump -> ux_host_class_dpump_flags & UX_HOST_CLASS_DPUMP_READ_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + dpump -> ux_host_class_dpump_flags |= UX_HOST_CLASS_DPUMP_READ_LOCK; + UX_RESTORE +#else + status = _ux_host_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); +#endif /* Start by resetting the actual length of the transfer to zero. */ *actual_length = 0; /* Get the pointer to the bulk in endpoint in the transfer_request. */ transfer_request = &dpump -> ux_host_class_dpump_bulk_in_endpoint -> ux_endpoint_transfer_request; - + +#if defined(UX_HOST_STANDALONE) + + /* Here wait blocking mode is used. */ + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk in endpoint until either the transfer is completed or until there is an error. */ while (requested_length) @@ -131,12 +154,22 @@ ULONG transfer_request_length; /* Perform the transfer. */ status = _ux_host_stack_transfer_request(transfer_request); +#if defined(UX_HOST_STANDALONE) + + /* If the transfer is not success, return error. */ + if (status != UX_SUCCESS) + { + dpump -> ux_host_class_dpump_flags &= ~UX_HOST_CLASS_DPUMP_READ_LOCK; + return(status); + } +#else + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ if (status == UX_SUCCESS) { /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -150,7 +183,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + _ux_host_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -169,11 +202,12 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + status = _ux_host_semaphore_put_rc(&dpump -> ux_host_class_dpump_semaphore); /* There was a non transfer error, no partial transfer to be checked. */ return(status); } +#endif /* Update the length of the transfer. Normally all the data has to be received. */ *actual_length += transfer_request -> ux_transfer_request_actual_length; @@ -185,7 +219,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + _ux_host_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); /* Return success to caller. */ return(UX_SUCCESS); @@ -199,7 +233,11 @@ ULONG transfer_request_length; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); +#if defined(UX_HOST_STANDALONE) + dpump -> ux_host_class_dpump_flags &= ~UX_HOST_CLASS_DPUMP_READ_LOCK; +#else + _ux_host_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); +#endif /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/core/src/ux_host_class_dpump_write.c b/common/core/src/ux_host_class_dpump_write.c index d1a714b5..3d398571 100644 --- a/common/core/src/ux_host_class_dpump_write.c +++ b/common/core/src/ux_host_class_dpump_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_dpump_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,12 +76,18 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer, ULONG requested_length, ULONG *actual_length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; @@ -103,16 +109,33 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (dpump -> ux_host_class_dpump_flags & UX_HOST_CLASS_DPUMP_WRITE_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + dpump -> ux_host_class_dpump_flags |= UX_HOST_CLASS_DPUMP_WRITE_LOCK; + UX_RESTORE +#else + status = _ux_host_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); +#endif /* Start by resetting the actual length of the transfer. */ *actual_length = 0; /* Get the pointer to the bulk out endpoint transfer request. */ transfer_request = &dpump -> ux_host_class_dpump_bulk_out_endpoint -> ux_endpoint_transfer_request; - + +#if defined(UX_HOST_STANDALONE) + + /* Here wait blocking mode is used. */ + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk out endpoint until either the transfer is completed or when there is an error. */ while (requested_length) @@ -131,12 +154,21 @@ ULONG transfer_request_length; /* Perform the transfer. */ status = _ux_host_stack_transfer_request(transfer_request); +#if defined(UX_HOST_STANDALONE) + + /* If the transfer is not success, return error. */ + if (status != UX_SUCCESS) + { + dpump -> ux_host_class_dpump_flags &= ~UX_HOST_CLASS_DPUMP_WRITE_LOCK; + return(status); + } +#else /* If the transfer is successful, we need to wait for the transfer request to be completed. */ if (status == UX_SUCCESS) { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -150,7 +182,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + _ux_host_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -169,11 +201,12 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + status = _ux_host_semaphore_put_rc(&dpump -> ux_host_class_dpump_semaphore); /* There was a non transfer error, no partial transfer to be checked */ return(status); } +#endif /* Update the length of the transfer. Normally all the data has to be sent. */ *actual_length += transfer_request -> ux_transfer_request_actual_length; @@ -185,7 +218,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + status = _ux_host_semaphore_put_rc(&dpump -> ux_host_class_dpump_semaphore); /* Return success. */ return(UX_SUCCESS); @@ -199,7 +232,11 @@ ULONG transfer_request_length; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); +#if defined(UX_HOST_STANDALONE) + dpump -> ux_host_class_dpump_flags &= ~UX_HOST_CLASS_DPUMP_WRITE_LOCK; +#else + _ux_host_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); +#endif /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/core/src/ux_host_stack_class_device_scan.c b/common/core/src/ux_host_stack_class_device_scan.c index 41d796c1..8a160cc9 100644 --- a/common/core/src/ux_host_stack_class_device_scan.c +++ b/common/core/src/ux_host_stack_class_device_scan.c @@ -41,7 +41,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_class_device_scan PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* removed duplicate line, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_class_device_scan(UX_DEVICE *device) @@ -126,12 +129,20 @@ UX_HOST_CLASS_COMMAND class_command; { device -> ux_device_class = class_inst; + +#if defined(UX_HOST_STANDALONE) + + /* Activation may take time, run as state machine. */ + status = UX_SUCCESS; + return(status); +#else class_command.ux_host_class_command_class_ptr = class_inst; class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE; status = device -> ux_device_class -> ux_host_class_entry_function(&class_command); /* Return result of activation. */ return(status); +#endif } #endif diff --git a/common/core/src/ux_host_stack_configuration_interface_scan.c b/common/core/src/ux_host_stack_configuration_interface_scan.c index 6f83f3e2..d8195968 100644 --- a/common/core/src/ux_host_stack_configuration_interface_scan.c +++ b/common/core/src/ux_host_stack_configuration_interface_scan.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_configuration_interface_scan PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 02-02-2021 Chaoqiong Xiao Initial Version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_configuration_interface_scan(UX_CONFIGURATION *configuration) @@ -124,6 +127,13 @@ UINT status; interface = interface -> ux_interface_next_interface; } +#if defined(UX_HOST_STANDALONE) + + /* Activated later in state machine. */ + status = (nb_class_owners > 0) ? UX_SUCCESS : UX_NO_CLASS_MATCH; + return(status); +#else + /* Assume no classes. */ status = UX_NO_CLASS_MATCH; @@ -175,5 +185,6 @@ UINT status; /* Return operation result. */ return(status); +#endif } diff --git a/common/core/src/ux_host_stack_configuration_set.c b/common/core/src/ux_host_stack_configuration_set.c index 4ffba3ec..e7b5279e 100644 --- a/common/core/src/ux_host_stack_configuration_set.c +++ b/common/core/src/ux_host_stack_configuration_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_configuration_set PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -42,9 +42,16 @@ /* DESCRIPTION */ /* */ /* This function performs a setting of a device configuration. */ +/* */ +/* In RTOS mode, this function is blocking. */ /* If the host is OTG capable and the device has an OTG descriptor */ /* that supports HNP we perform a SET_FEATURE with b_hnp_support. */ /* */ +/* In standalone mode, when device enumeration is in progress, this */ +/* function is non-blocking, it prepares transfer for enum step of */ +/* SET_CONFIGURE request. Otherwise it blocks until transfer request */ +/* done. */ +/* */ /* INPUT */ /* */ /* configuration Pointer to configuration */ @@ -74,6 +81,10 @@ /* used pointer for current */ /* selected configuration, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* set device power source, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_configuration_set(UX_CONFIGURATION *configuration) @@ -143,6 +154,19 @@ UX_HCD *hcd; transfer_request -> ux_transfer_request_value = (USHORT) configuration -> ux_configuration_descriptor.bConfigurationValue; transfer_request -> ux_transfer_request_index = 0; +#if defined(UX_HOST_STANDALONE) + if (device -> ux_device_flags &= UX_DEVICE_FLAG_ENUM) + { + + /* Special case for enumeration process, non-blocking. */ + device -> ux_device_enum_trans = transfer_request; + status = UX_SUCCESS; + return(status); + } + + /* Tend to be blocking after enumeration done. */ +#endif + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -155,9 +179,14 @@ UX_HCD *hcd; /* Store the new configuration value in the device container. */ device -> ux_device_current_configuration = configuration; + + /* Save current device power source. */ + device -> ux_device_power_source = (configuration -> + ux_configuration_descriptor.bmAttributes & + UX_CONFIGURATION_DEVICE_SELF_POWERED) ? + UX_DEVICE_SELF_POWERED : UX_DEVICE_BUS_POWERED; } /* Return status to caller. */ return(status); } - diff --git a/common/core/src/ux_host_stack_device_address_set.c b/common/core/src/ux_host_stack_device_address_set.c index 9734d0ed..1d93c345 100644 --- a/common/core/src/ux_host_stack_device_address_set.c +++ b/common/core/src/ux_host_stack_device_address_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_address_set(UX_DEVICE *device) @@ -152,6 +155,12 @@ UCHAR device_address_byte; transfer_request -> ux_transfer_request_value = device_address; transfer_request -> ux_transfer_request_index = 0; +#if defined(UX_HOST_STANDALONE) + device -> ux_device_enum_trans = transfer_request; + status = UX_SUCCESS; + return(status); +#else + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -163,6 +172,9 @@ UCHAR device_address_byte; if (status == UX_SUCCESS) { + /* Mark the device as ADDRESSED now. */ + device -> ux_device_state = UX_DEVICE_ADDRESSED; + /* Some devices need some time to accept this address. */ _ux_utility_delay_ms(UX_DEVICE_ADDRESS_SET_WAIT); @@ -177,4 +189,5 @@ UCHAR device_address_byte; we will try again either at the root hub or regular hub. */ return(status); } +#endif } diff --git a/common/core/src/ux_host_stack_device_configuration_activate.c b/common/core/src/ux_host_stack_device_configuration_activate.c index 864bae87..fc7b8eef 100644 --- a/common/core/src/ux_host_stack_device_configuration_activate.c +++ b/common/core/src/ux_host_stack_device_configuration_activate.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_configuration_activate PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,11 +74,16 @@ /* 06-02-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed trace enabled error, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_configuration_activate(UX_CONFIGURATION *configuration) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_DEVICE *device; UINT status; @@ -102,9 +107,22 @@ UINT status; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_ACTIVATE, device, configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) +#if defined(UX_HOST_STANDALONE) + + /* Check device lock. */ + UX_DISABLE + if (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + UX_RESTORE +#else + /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -118,6 +136,7 @@ UINT status; return(UX_SEMAPHORE_ERROR); } +#endif /* Check for the state of the device . If the device is already configured, we need to cancel the existing configuration before enabling this one. */ @@ -128,13 +147,40 @@ UINT status; otherwise report error. */ status = (device -> ux_device_current_configuration == configuration) ? UX_SUCCESS : UX_ALREADY_ACTIVATED; - _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); +#if defined(UX_HOST_STANDALONE) + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; +#else + _ux_host_semaphore_put(&device -> ux_device_protection_semaphore); +#endif return(status); } /* Scan and activate the interfaces. */ status = _ux_host_stack_configuration_interface_scan(configuration); +#if defined(UX_HOST_STANDALONE) + + if (status == UX_SUCCESS) + { + + /* Place device enum state: LOCK -> SET_CONFIGURE. */ + device -> ux_device_enum_trans = + &device -> ux_device_control_endpoint.ux_endpoint_transfer_request; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT; + device -> ux_device_enum_inst.configuration = configuration; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_SET; + + /* Set enumeration flag to process enumeration sequence. */ + device -> ux_device_flags |= UX_DEVICE_FLAG_ENUM; + + /* Wait until enumeration done and device removed. */ + while(device -> ux_device_enum_state != UX_STATE_IDLE) + { + _ux_system_host_tasks_run(); + } + } +#endif + /* Return completion status. */ return(status); } diff --git a/common/core/src/ux_host_stack_device_configuration_deactivate.c b/common/core/src/ux_host_stack_device_configuration_deactivate.c index 7012dce7..88071a60 100644 --- a/common/core/src/ux_host_stack_device_configuration_deactivate.c +++ b/common/core/src/ux_host_stack_device_configuration_deactivate.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_configuration_deactivate PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,11 +71,17 @@ /* 06-02-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed trace enabled error, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_configuration_deactivate(UX_DEVICE *device) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_HOST_CLASS_COMMAND command; UX_CONFIGURATION *configuration; UX_INTERFACE *interface; @@ -101,9 +107,22 @@ UINT status; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_DEACTIVATE, device, configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) +#if defined(UX_HOST_STANDALONE) + + /* Check device lock. */ + UX_DISABLE + if (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + UX_RESTORE +#else + /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -117,11 +136,16 @@ UINT status; return(UX_SEMAPHORE_ERROR); } +#endif /* Check for the state of the device, if not configured, we are done. */ if (device -> ux_device_state != UX_DEVICE_CONFIGURED) { - _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); +#if defined(UX_HOST_STANDALONE) + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; +#else + _ux_host_semaphore_put(&device -> ux_device_protection_semaphore); +#endif return(UX_SUCCESS); } @@ -158,6 +182,10 @@ UINT status; /* The device can now be un-configured. */ status = _ux_host_stack_device_configuration_reset(device); +#if defined(UX_HOST_STANDALONE) + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; +#endif + /* Return completion status. */ return(status); } diff --git a/common/core/src/ux_host_stack_device_configuration_reset.c b/common/core/src/ux_host_stack_device_configuration_reset.c index 20aa20dd..2db43548 100644 --- a/common/core/src/ux_host_stack_device_configuration_reset.c +++ b/common/core/src/ux_host_stack_device_configuration_reset.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_configuration_reset PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,10 @@ /* used pointer for current */ /* selected configuration, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed device state support, */ +/* reset device power source, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_configuration_reset(UX_DEVICE *device) @@ -105,8 +109,11 @@ UINT status; /* No configuration is selected now. */ device -> ux_device_current_configuration = UX_NULL; - /* Set state of device to ATTACHED. */ - device -> ux_device_state = UX_DEVICE_ATTACHED; + /* Set state of device to ADDRESSED. */ + device -> ux_device_state = UX_DEVICE_ADDRESSED; + + /* Reset power source. */ + device -> ux_device_power_source = UX_DEVICE_BUS_POWERED; /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */ transfer_request -> ux_transfer_request_requested_length = 0; diff --git a/common/core/src/ux_host_stack_device_configuration_select.c b/common/core/src/ux_host_stack_device_configuration_select.c index 80597dcc..e6270f86 100644 --- a/common/core/src/ux_host_stack_device_configuration_select.c +++ b/common/core/src/ux_host_stack_device_configuration_select.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_configuration_select PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* used pointer for current */ /* selected configuration, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refine power usage check, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_configuration_select(UX_CONFIGURATION *configuration) @@ -110,6 +113,22 @@ UINT status; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_SELECT, device, configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + /* We need to check the amount of power the bus powered device is consuming + before switch configuration. Otherwise we may run the risk of + an over current fault. */ + if (((configuration -> ux_configuration_descriptor.bmAttributes & UX_CONFIGURATION_DEVICE_SELF_POWERED) == 0) && + (configuration -> ux_configuration_descriptor.MaxPower > UX_DEVICE_MAX_POWER_GET(device))) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_OVER_CURRENT_CONDITION); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_OVER_CURRENT_CONDITION, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_OVER_CURRENT_CONDITION); + } + /* Check for the state of the device . If the device is already configured, we need to cancel the existing configuration before enabling this one. */ if (device -> ux_device_state == UX_DEVICE_CONFIGURED) @@ -122,22 +141,6 @@ UINT status; _ux_host_stack_configuration_instance_delete(current_configuration); } - /* The device is now in the unconfigured state. We need to deal - with the amount of power the device is consuming before allowing - it to be configured. Otherwise we may run the risk of an over - current fault. */ - if (configuration -> ux_configuration_descriptor.MaxPower > UX_DEVICE_MAX_POWER_GET(device)) - { - - /* Error trap. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_OVER_CURRENT_CONDITION); - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_OVER_CURRENT_CONDITION, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) - - return(UX_OVER_CURRENT_CONDITION); - } - /* The device can now be configured. */ status = _ux_host_stack_configuration_set(configuration); if (status != UX_SUCCESS) diff --git a/common/core/src/ux_host_stack_device_descriptor_read.c b/common/core/src/ux_host_stack_device_descriptor_read.c index 7cadf7c0..97e039ba 100644 --- a/common/core/src/ux_host_stack_device_descriptor_read.c +++ b/common/core/src/ux_host_stack_device_descriptor_read.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_descriptor_read PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,10 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* added bMaxPacketSize0 check,*/ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added class code checking, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_descriptor_read(UX_DEVICE *device) @@ -104,6 +108,12 @@ UX_ENDPOINT *control_endpoint; transfer_request -> ux_transfer_request_value = UX_DEVICE_DESCRIPTOR_ITEM << 8; transfer_request -> ux_transfer_request_index = 0; +#if defined(UX_HOST_STANDALONE) + device -> ux_device_enum_trans = transfer_request; + status = UX_SUCCESS; + return(status); +#else + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -135,6 +145,27 @@ UX_ENDPOINT *control_endpoint; return(UX_DESCRIPTOR_CORRUPTED); } +#if defined(UX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE) + + /* Validate the USB-IF bDeviceClass class code. */ + switch(device -> ux_device_descriptor.bDeviceClass) + { + case 0x00: /* Fall through. */ + case 0x02: /* Fall through. */ + case 0x09: /* Fall through. */ + case 0x11: /* Fall through. */ + case 0xDC: /* Fall through. */ + case 0xEF: /* Fall through. */ + case 0xFF: + break; + default: + + /* Invalid device class code. */ + _ux_utility_memory_free(descriptor); + return(UX_DESCRIPTOR_CORRUPTED); + } +#endif + /* Update the max packet size value for the endpoint. */ control_endpoint -> ux_endpoint_descriptor.wMaxPacketSize = device -> ux_device_descriptor.bMaxPacketSize0; @@ -176,5 +207,6 @@ UX_ENDPOINT *control_endpoint; /* Return completion status. */ return(status); +#endif } diff --git a/common/core/src/ux_host_stack_device_remove.c b/common/core/src/ux_host_stack_device_remove.c index 1a466588..510111e0 100644 --- a/common/core/src/ux_host_stack_device_remove.c +++ b/common/core/src/ux_host_stack_device_remove.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_remove PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* added notification for */ /* device disconnection, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_remove(UX_HCD *hcd, UX_DEVICE *parent, UINT port_index) @@ -94,12 +97,6 @@ UX_HOST_CLASS_COMMAND command; with the parent device and the port it was attached to. Start with the first device. */ device = _ux_system_host -> ux_system_host_device_array; - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_REMOVE, hcd, parent, port_index, device, UX_TRACE_HOST_STACK_EVENTS, 0, 0) - - /* If trace is enabled, unregister this object. */ - UX_TRACE_OBJECT_UNREGISTER(device); - #if UX_MAX_DEVICES > 1 /* Start at the beginning of the list. */ container_index = 0; @@ -145,6 +142,12 @@ UX_HOST_CLASS_COMMAND command; return(UX_DEVICE_HANDLE_UNKNOWN); } + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_REMOVE, hcd, parent, port_index, device, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* If trace is enabled, unregister this object. */ + UX_TRACE_OBJECT_UNREGISTER(device); + /* We have found the device to be removed. */ device -> ux_device_state = UX_DEVICE_REMOVED; diff --git a/common/core/src/ux_host_stack_device_resources_free.c b/common/core/src/ux_host_stack_device_resources_free.c index f77b3fd5..0be0fc72 100644 --- a/common/core/src/ux_host_stack_device_resources_free.c +++ b/common/core/src/ux_host_stack_device_resources_free.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_resources_free PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* definitions, verified */ /* memset and memcpy cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_resources_free(UX_DEVICE *device) @@ -98,6 +101,39 @@ UCHAR device_address_byte; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_RESOURCE_FREE, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) +#if defined(UX_HOST_STANDALONE) + + /* Free possible allocated enumeration resources. */ + if (device -> ux_device_flags & UX_DEVICE_FLAG_ENUM) + { + + /* If transfer buffer is not freed, free it. */ + if (device -> ux_device_enum_trans && + device -> ux_device_enum_trans -> ux_transfer_request_data_pointer) + { + _ux_utility_memory_free(device -> ux_device_enum_trans -> + ux_transfer_request_data_pointer); + } + + /* If configuration is not attached, free it. */ + if ((device -> ux_device_enum_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE) || + ((device -> ux_device_enum_state == UX_HOST_STACK_ENUM_TRANS_WAIT) && + (device -> ux_device_enum_next_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE))) + { + if (device -> ux_device_enum_inst.configuration && + device -> ux_device_enum_inst.configuration -> + ux_configuration_device == UX_NULL) + { + _ux_utility_memory_free(device -> ux_device_enum_inst.ptr); + } + } + } + + /* Reset device flags. */ + device -> ux_device_flags = 0; + +#endif + /* Set the alternate setting to zero. */ current_alternate_setting = 0; @@ -179,14 +215,14 @@ UCHAR device_address_byte; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using the control endpoint to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* The control endpoint should be destroyed at the HCD level. */ hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *) &device -> ux_device_control_endpoint); } /* The semaphore attached to the control endpoint must be destroyed. */ - _ux_utility_semaphore_delete(&device -> ux_device_control_endpoint.ux_endpoint_transfer_request.ux_transfer_request_semaphore); + _ux_host_semaphore_delete(&device -> ux_device_control_endpoint.ux_endpoint_transfer_request.ux_transfer_request_semaphore); #if UX_MAX_DEVICES > 1 /* Check if the device had an assigned address. */ @@ -211,7 +247,7 @@ UCHAR device_address_byte; #endif /* The semaphore for endpoint 0 protection must be destroyed. */ - _ux_utility_semaphore_delete(&device -> ux_device_protection_semaphore); + _ux_host_semaphore_delete(&device -> ux_device_protection_semaphore); /* Now this device can be free and its container return to the pool. */ _ux_utility_memory_set(device, 0, sizeof(UX_DEVICE)); /* Use case of memset is verified. */ diff --git a/common/core/src/ux_host_stack_device_string_get.c b/common/core/src/ux_host_stack_device_string_get.c index 4df274b6..6389cb20 100644 --- a/common/core/src/ux_host_stack_device_string_get.c +++ b/common/core/src/ux_host_stack_device_string_get.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_device_string_get PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,10 +75,16 @@ /* 06-02-2021 Chaoqiong Xiao Modified comment(s), and */ /* removed unnecessary header, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_device_string_get(UX_DEVICE *device, UCHAR *descriptor_buffer, ULONG length, ULONG language_id, ULONG string_index) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UINT status; @@ -100,17 +106,32 @@ UINT status; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_STRING_GET, device, descriptor_buffer, length, (language_id << 16) | string_index, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if ((device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) || + (transfer_request -> ux_transfer_request_flags & UX_TRANSFER_FLAG_LOCK)) + { + UX_RESTORE + return(UX_BUSY); + } + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + transfer_request -> ux_transfer_request_flags |= + (UX_TRANSFER_FLAG_LOCK | UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK); + UX_RESTORE +#else + /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) return(UX_SEMAPHORE_ERROR); - - /* We need to get the default control endpoint transfer request pointer. */ - control_endpoint = &device -> ux_device_control_endpoint; - transfer_request = &control_endpoint -> ux_endpoint_transfer_request; +#endif /* Create a transfer request for the GET_DEVICE_ID request. */ transfer_request -> ux_transfer_request_data_pointer = descriptor_buffer; diff --git a/common/core/src/ux_host_stack_endpoint_instance_create.c b/common/core/src/ux_host_stack_endpoint_instance_create.c index 10409efa..2a76e0f2 100644 --- a/common/core/src/ux_host_stack_endpoint_instance_create.c +++ b/common/core/src/ux_host_stack_endpoint_instance_create.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_endpoint_instance_create PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* filled default endpoint */ /* request endpoint pointer, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_endpoint_instance_create(UX_ENDPOINT *endpoint) @@ -141,7 +144,7 @@ UCHAR endpoint_type; } /* Create a semaphore for this endpoint to be attached to its transfer request. */ - status = _ux_utility_semaphore_create(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, + status = _ux_host_semaphore_create(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, "ux_transfer_request_semaphore", 0); /* Check status. */ diff --git a/common/core/src/ux_host_stack_endpoint_instance_delete.c b/common/core/src/ux_host_stack_endpoint_instance_delete.c index 60ada600..387a1773 100644 --- a/common/core/src/ux_host_stack_endpoint_instance_delete.c +++ b/common/core/src/ux_host_stack_endpoint_instance_delete.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_endpoint_instance_delete PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 06-02-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed trace enabled error, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_stack_endpoint_instance_delete(UX_ENDPOINT *endpoint) @@ -97,7 +100,7 @@ UX_HCD *hcd; hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *) endpoint); /* Free the semaphore previously attached to the transfer_request of this endpoint. */ - _ux_utility_semaphore_delete(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore); + _ux_host_semaphore_delete(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore); } /* If the endpoint requested guaranteed bandwidth, free it now. */ diff --git a/common/core/src/ux_host_stack_enum_thread_entry.c b/common/core/src/ux_host_stack_enum_thread_entry.c index 93b6a23d..65ea3e9f 100644 --- a/common/core/src/ux_host_stack_enum_thread_entry.c +++ b/common/core/src/ux_host_stack_enum_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_enum_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,6 +54,8 @@ /* there has been a change in the USB topology which could be either */ /* a insertion or extraction or eventually a hub downstream port */ /* signal. */ +/* */ +/* This is for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -82,6 +84,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_stack_enum_thread_entry(ULONG input) @@ -94,7 +99,7 @@ VOID _ux_host_stack_enum_thread_entry(ULONG input) { /* Wait for the semaphore to be put by the root hub or a regular hub. */ - _ux_utility_semaphore_get(&_ux_system_host -> ux_system_host_enum_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get_norc(&_ux_system_host -> ux_system_host_enum_semaphore, UX_WAIT_FOREVER); #if UX_MAX_DEVICES > 1 /* We try the hub first. For this we look into the USBX project diff --git a/common/core/src/ux_host_stack_hcd_thread_entry.c b/common/core/src/ux_host_stack_hcd_thread_entry.c index bc0042e0..2ae43a18 100755 --- a/common/core/src/ux_host_stack_hcd_thread_entry.c +++ b/common/core/src/ux_host_stack_hcd_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_hcd_thread_entry PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,8 @@ /* entry routine is invoked right away. This thread suspends until */ /* one of the HCD resumes it due to HCD activities. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* input Not used input */ @@ -75,6 +77,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed registered HCD scan, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_stack_hcd_thread_entry(ULONG input) @@ -93,7 +98,7 @@ UX_INTERRUPT_SAVE_AREA /* Get the semaphore that signals something is available for this thread to process. */ - _ux_utility_semaphore_get(&_ux_system_host -> ux_system_host_hcd_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get_norc(&_ux_system_host -> ux_system_host_hcd_semaphore, UX_WAIT_FOREVER); #if UX_MAX_HCD > 1 /* This thread was awaken by one or more HCD controllers. Check each of the HCDs diff --git a/common/core/src/ux_host_stack_hnp_polling_thread_entry.c b/common/core/src/ux_host_stack_hnp_polling_thread_entry.c index e57bca64..2f72fa77 100644 --- a/common/core/src/ux_host_stack_hnp_polling_thread_entry.c +++ b/common/core/src/ux_host_stack_hnp_polling_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_hnp_polling_thread_entry PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* used pointer for current */ /* selected configuration, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_stack_hnp_polling_thread_entry(ULONG argument) @@ -176,7 +179,7 @@ UINT status; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Perform a GET_STATUS on this device to see if it wants to become the host. */ /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */ diff --git a/common/core/src/ux_host_stack_initialize.c b/common/core/src/ux_host_stack_initialize.c index 33638724..59b21c1c 100644 --- a/common/core/src/ux_host_stack_initialize.c +++ b/common/core/src/ux_host_stack_initialize.c @@ -87,7 +87,7 @@ UCHAR _ux_system_host_hcd_simulator_name[] = "ux_ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -131,6 +131,9 @@ UCHAR _ux_system_host_hcd_simulator_name[] = "ux_ /* instead of using them */ /* directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *)) @@ -138,6 +141,10 @@ UINT _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX UINT status; UCHAR *memory; +#if defined(UX_HOST_STANDALONE) +UINT i; +UX_DEVICE *device; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) @@ -196,8 +203,33 @@ UCHAR *memory; /* Store memory in system structure. */ _ux_system_host -> ux_system_host_device_array = (UX_DEVICE *) memory; + +#if defined(UX_HOST_STANDALONE) + + /* Add devices to the enumeration list, with ENUM flags cleared. */ + if (status == UX_SUCCESS) + { + + /* Start from the last device instance. */ + device = &_ux_system_host -> ux_system_host_device_array[UX_MAX_DEVICES - 1]; + + /* Insert all devices to enumeration list head. */ + for (i = 0; i < UX_MAX_DEVICES; i ++) + { + + /* Insert to head. */ + device -> ux_device_enum_next = _ux_system_host -> ux_system_host_enum_device; + _ux_system_host -> ux_system_host_enum_device = device; + + /* Next device. */ + device --; + } + } +#endif + } +#if !defined(UX_HOST_STANDALONE) /* Obtain enough stack for the two USBX host threads. */ if (status == UX_SUCCESS) { @@ -261,8 +293,9 @@ UCHAR *memory; if(status != UX_SUCCESS) status = UX_THREAD_ERROR; } +#endif -#ifdef UX_OTG_SUPPORT +#if defined(UX_OTG_SUPPORT) && !defined(UX_OTG_STANDALONE) /* Allocate another stack area for the HNP polling thread. */ if (status == UX_SUCCESS) { @@ -315,6 +348,7 @@ UCHAR *memory; * no need to delete it. */ #endif +#if !defined(UX_HOST_STANDALONE) /* Delete _ux_system_host -> ux_system_host_enum_thread. */ if (_ux_system_host -> ux_system_host_enum_thread.tx_thread_id != 0) _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_enum_thread); @@ -334,7 +368,8 @@ UCHAR *memory; /* Free _ux_system_host -> ux_system_host_enum_thread_stack. */ if (_ux_system_host -> ux_system_host_enum_thread_stack) _ux_utility_memory_free(_ux_system_host -> ux_system_host_enum_thread_stack); - +#endif + /* Free _ux_system_host -> ux_system_host_device_array. */ if (_ux_system_host -> ux_system_host_device_array) _ux_utility_memory_free(_ux_system_host -> ux_system_host_device_array); diff --git a/common/core/src/ux_host_stack_interface_set.c b/common/core/src/ux_host_stack_interface_set.c index a75eec5f..d87da200 100644 --- a/common/core/src/ux_host_stack_interface_set.c +++ b/common/core/src/ux_host_stack_interface_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_interface_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_interface_set(UX_INTERFACE *interface) @@ -96,8 +99,8 @@ UX_ENDPOINT *control_endpoint; transfer_request -> ux_transfer_request_index = (USHORT) interface -> ux_interface_descriptor.bInterfaceNumber; transfer_request -> ux_transfer_request_value = (USHORT) interface -> ux_interface_descriptor.bAlternateSetting; - /* Send request to HCD layer. */ - status = _ux_host_stack_hcd_transfer_request(transfer_request); + /* Send request. */ + status = _ux_host_stack_transfer_request(transfer_request); /* Return status completion. */ return(status); diff --git a/common/core/src/ux_host_stack_new_device_create.c b/common/core/src/ux_host_stack_new_device_create.c index e9ee5496..2fd5ebec 100644 --- a/common/core/src/ux_host_stack_new_device_create.c +++ b/common/core/src/ux_host_stack_new_device_create.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_new_device_create PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -102,6 +102,10 @@ /* added a new parameter to */ /* return created device, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* reset device power source, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_new_device_create(UX_HCD *hcd, UX_DEVICE *device_owner, @@ -159,15 +163,17 @@ UX_ENDPOINT *control_endpoint; Initialize the device structure. */ device -> ux_device_handle = (ULONG) (ALIGN_TYPE) device; device -> ux_device_state = UX_DEVICE_ATTACHED; + device -> ux_device_address = 0; device -> ux_device_speed = device_speed; UX_DEVICE_MAX_POWER_SET(device, port_max_power); UX_DEVICE_PARENT_SET(device, device_owner); UX_DEVICE_HCD_SET(device, hcd); UX_DEVICE_PORT_LOCATION_SET(device, port_index); + device -> ux_device_power_source = UX_DEVICE_BUS_POWERED; /* Create a semaphore for the device. This is to protect endpoint 0 mostly for OTG HNP polling. The initial count is 1 as a mutex mechanism. */ - status = _ux_utility_semaphore_create(&device -> ux_device_protection_semaphore, "ux_host_endpoint0_semaphore", 1); + status = _ux_host_semaphore_create(&device -> ux_device_protection_semaphore, "ux_host_endpoint0_semaphore", 1); /* Check semaphore creation. */ if (status != UX_SUCCESS) @@ -188,7 +194,7 @@ UX_ENDPOINT *control_endpoint; control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_endpoint = control_endpoint; /* Create a semaphore for this endpoint to be attached to its transfer request. */ - status = _ux_utility_semaphore_create(&control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, "ux_host_transfer_request_semaphore", 0); + status = _ux_host_semaphore_create(&control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, "ux_host_transfer_request_semaphore", 0); /* Check semaphore creation. */ if (status != UX_SUCCESS) @@ -208,6 +214,28 @@ UX_ENDPOINT *control_endpoint; /* Create the default control endpoint at the HCD level. */ status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_CREATE_ENDPOINT, (VOID *) control_endpoint); + +#if defined(UX_HOST_STANDALONE) + if (status == UX_SUCCESS) + { + + /* Now control endpoint is ready, set state to running. */ + control_endpoint -> ux_endpoint_state = UX_ENDPOINT_RUNNING; + + /* Setup default control request timeout. */ + control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_MS_TO_TICK_NON_ZERO(UX_CONTROL_TRANSFER_TIMEOUT); + + /* Set default control request mode to wait. */ + control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_flags |= + UX_TRANSFER_FLAG_AUTO_WAIT; + } + + /* Enumeration steps will be done in task state machine. */ + +#else + + /* Going on to do enumeration (requests). */ if (status == UX_SUCCESS) { @@ -253,6 +281,7 @@ UX_ENDPOINT *control_endpoint; /* If trace is enabled, register this object. */ UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_DEVICE, hcd, device_owner, port_index, 0); } +#endif /* Return status. If there's an error, device resources that have been allocated until this point should be freed by the caller via _ux_host_stack_device_resources_free. */ diff --git a/common/core/src/ux_host_stack_rh_device_insertion.c b/common/core/src/ux_host_stack_rh_device_insertion.c index 6e33f472..c7d9477f 100644 --- a/common/core/src/ux_host_stack_rh_device_insertion.c +++ b/common/core/src/ux_host_stack_rh_device_insertion.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_rh_device_insertion PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,11 +81,41 @@ /* added disconnection check */ /* in enumeration retries, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_rh_device_insertion(UX_HCD *hcd, UINT port_index) { +#if defined(UX_HOST_STANDALONE) +UX_DEVICE *device; +UINT status; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_DEVICE_INSERTION, hcd, port_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Anyway there is device connected. */ + hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index); + /* Create a new device slot for enumeration. */ + status = _ux_host_stack_new_device_create(hcd, UX_NULL, port_index, + UX_FULL_SPEED_DEVICE, UX_MAX_SELF_POWER, + &device); + + /* Link the device in enumeration list. */ + if (status == UX_SUCCESS) + { + + /* Set enumeration flag to process enumeration sequence. */ + device -> ux_device_flags |= UX_DEVICE_FLAG_ENUM; + + /* Done success. */ + return(UX_SUCCESS); + } + +#else UX_DEVICE *device; UINT index_loop; UINT device_speed; @@ -195,6 +225,7 @@ UINT status; so we try again ! */ _ux_utility_delay_ms(UX_RH_ENUMERATION_RETRY_DELAY); } +#endif /* defined(UX_HOST_STANDALONE) */ /* If we get here, the device did not enumerate completely. The device is still attached to the root hub and therefore @@ -218,4 +249,3 @@ UINT status; /* Return a failed enumeration. */ return(UX_DEVICE_ENUMERATION_FAILURE); } - diff --git a/common/core/src/ux_host_stack_role_swap.c b/common/core/src/ux_host_stack_role_swap.c index 46aee96e..65c6b2a8 100644 --- a/common/core/src/ux_host_stack_role_swap.c +++ b/common/core/src/ux_host_stack_role_swap.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_role_swap PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_role_swap(UX_DEVICE *device) @@ -93,7 +96,7 @@ UINT status; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Perform a SET_FEATURE on this device to inform the it we are ready to change role. */ transfer_request -> ux_transfer_request_requested_length = 0; diff --git a/common/core/src/ux_host_stack_tasks_run.c b/common/core/src/ux_host_stack_tasks_run.c new file mode 100644 index 00000000..8e592618 --- /dev/null +++ b/common/core/src/ux_host_stack_tasks_run.c @@ -0,0 +1,1085 @@ +/**************************************************************************/ +/* */ +/* 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 Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_host_stack.h" + +#if defined(UX_HOST_STANDALONE) + + +#define UX_HOST_STACK_ENUM_TRANS_ERROR(t) ( \ + (t)->ux_transfer_request_completion_code != UX_SUCCESS || \ + (t)->ux_transfer_request_actual_length != \ + (t)->ux_transfer_request_requested_length) + +static inline VOID _ux_host_stack_port_check_run(VOID); +static inline VOID _ux_host_stack_enum_run(VOID); +static inline VOID _ux_host_stack_pending_transfers_run(VOID); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs host stack and registered classes tasks. */ +/* */ +/* It's valid only in standalone mode. */ +/* It's non-blocking. */ +/* */ +/* INPUT */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion State Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_hcd_entry_function) HCD function */ +/* (ux_host_class_task_function) Host class task function */ +/* (ux_system_host_change_function) Host change callback function */ +/* (ux_system_host_enum_hub_function) Host hub enumeration function */ +/* _ux_host_stack_rh_change_process Host Root Hub process */ +/* _ux_host_stack_device_address_set Start process to set address */ +/* _ux_host_stack_configuration_set Start process to set config */ +/* _ux_host_stack_device_descriptor_read Start process to read device */ +/* descriptor */ +/* _ux_host_stack_new_configuration_create */ +/* Link a new configuration to */ +/* a device */ +/* _ux_host_stack_configuration_instance_create */ +/* Create configuration instance */ +/* _ux_host_stack_transfer_run Runs transfer state machine */ +/* _ux_host_stack_class_device_scan Query device class driver */ +/* _ux_host_stack_class_interface_scan Query interface class driver */ +/* _ux_host_stack_interfaces_scan Parse interfaces in a */ +/* configuration */ +/* _ux_host_stack_device_remove Remove a device */ +/* _ux_utility_descriptor_parse Parse a descriptor */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_time_get Get current time tick */ +/* _ux_system_error_handler Error trap */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_tasks_run(VOID) +{ + +UX_HCD *hcd_inst; +ULONG hcd_index; +UX_HOST_CLASS *class_inst; +ULONG class_index; + + /* =========== Run all HCD tasks. */ + for (hcd_index = 0; hcd_index < UX_SYSTEM_HOST_MAX_HCD_GET(); hcd_index++) + { + hcd_inst = &_ux_system_host->ux_system_host_hcd_array[hcd_index]; + if (hcd_inst -> ux_hcd_status != UX_HCD_STATUS_OPERATIONAL || + hcd_inst -> ux_hcd_entry_function == UX_NULL) + continue; + hcd_inst -> ux_hcd_entry_function(hcd_inst, UX_HCD_TASKS_RUN, UX_NULL); + } + + /* =========== Run port check process. */ + _ux_host_stack_port_check_run(); + + /* =========== Run enumeration process. */ + _ux_host_stack_enum_run(); + + /* =========== Run classes tasks. */ + for (class_index = 0; class_index < UX_SYSTEM_HOST_MAX_CLASS_GET(); class_index++) + { + class_inst = &_ux_system_host->ux_system_host_class_array[class_index]; + if ((class_inst -> ux_host_class_status == UX_UNUSED) || + (class_inst -> ux_host_class_task_function == UX_NULL)) + continue; + class_inst -> ux_host_class_task_function(class_inst); + } + + /* =========== Run pending transfer tasks. */ + _ux_host_stack_pending_transfers_run(); + + /* =========== Run background tasks. */ + if (_ux_system_host -> ux_system_host_change_function) + { + _ux_system_host -> ux_system_host_change_function( + UX_STANDALONE_WAIT_BACKGROUND_TASK, UX_NULL, UX_NULL); + } + + /* No idle report support now. */ + return (UX_STATE_WAIT); +} + +static inline VOID _ux_host_stack_port_check_run(VOID) +{ +#if UX_MAX_DEVICES > 1 + + /* We try the hub first. For this we look into the USBX project + structure to see if there is at least one hub. */ + if (_ux_system_host->ux_system_host_enum_hub_function != UX_NULL) + { + + /* Yes, there is a HUB function, call it! */ + _ux_system_host->ux_system_host_enum_hub_function(); + } +#endif + + /* Check root hub changes. */ + _ux_host_stack_rh_change_process(); +} + +static inline UINT _ux_host_stack_rh_port_enable(UX_DEVICE *device) +{ +UX_HCD *hcd = UX_DEVICE_HCD_GET(device); +ALIGN_TYPE port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device); + return hcd -> ux_hcd_entry_function(hcd, UX_HCD_ENABLE_PORT, (VOID *)port_index); +} +static inline UINT _ux_host_stack_rh_port_reset(UX_DEVICE *device) +{ +UX_HCD *hcd = UX_DEVICE_HCD_GET(device); +ALIGN_TYPE port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device); + return hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_PORT, (VOID *)port_index); +} +static inline UINT _ux_host_stack_rh_port_status_get(UX_DEVICE *device) +{ +UX_HCD *hcd = UX_DEVICE_HCD_GET(device); +ALIGN_TYPE port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device); + return hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)port_index); +} +static inline VOID _ux_host_stack_enum_address_sent(UX_DEVICE *device) +{ + + /* Address (request wValue) applied to device. */ + device -> ux_device_address = + device -> ux_device_enum_trans -> ux_transfer_request_value; + device -> ux_device_state = UX_DEVICE_ADDRESSED; + + /* Unlock enumeration. */ + _ux_system_host -> ux_system_host_enum_lock = UX_NULL; +} +static inline VOID _ux_host_stack_enum_device_descriptor_parse0( + UX_DEVICE *device, UCHAR *descriptor) +{ + + /* Endpoint descriptor updated. */ + device -> ux_device_descriptor.bMaxPacketSize0 = descriptor[7]; + + /* Update EP0 wMaxPacketSize. */ + device -> ux_device_control_endpoint. + ux_endpoint_descriptor.wMaxPacketSize = descriptor[7]; +} +static inline VOID _ux_host_stack_enum_configuration_descriptor_parse0( + UX_DEVICE *device, UX_CONFIGURATION *configuration, UCHAR *descriptor) +{ + /* This configuration must be linked to the device. */ + _ux_host_stack_new_configuration_create(device, configuration); + + /* The descriptor is in a packed format, parse it locally. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &configuration -> ux_configuration_descriptor); +} +static inline UINT _ux_host_stack_enum_configuration_read(UX_DEVICE *device) +{ + +UX_CONFIGURATION *configuration; +UCHAR *descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; + + /* Allocate configuration containter for the descriptor. */ + configuration = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + sizeof(UX_CONFIGURATION)); + if (configuration == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Need to allocate memory for the configuration descriptor the first time we read + only the configuration descriptor when we have the configuration descriptor, we have + the length of the entire configuration\interface\endpoint descriptors. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, + UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + { + _ux_utility_memory_free(configuration); + return(UX_MEMORY_INSUFFICIENT); + } + + /* Save allocated configuration container. */ + device -> ux_device_enum_inst.configuration = configuration; + + /* Retrieve the pointer to the control endpoint and its transfer_request. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | + UX_REQUEST_TYPE_STANDARD | + UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UINT)device -> ux_device_enum_index | + (UINT)(UX_CONFIGURATION_DESCRIPTOR_ITEM << 8); + transfer_request -> ux_transfer_request_index = 0; + + /* Transfer for wait. */ + UX_TRANSFER_STATE_RESET(transfer_request); + device -> ux_device_enum_trans = transfer_request; + + return(UX_SUCCESS); +} +static inline VOID _ux_host_stack_configuration_parsed(UX_DEVICE *device) +{ +UINT status; + + /* By default (error) configuration not activated. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + + /* Query device class driver. */ + status = _ux_host_stack_class_device_scan(device); + if (status == UX_SUCCESS) + { + + /* Prepare device activation. */ + device -> ux_device_enum_index = 0xFF; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE; + device -> ux_device_enum_inst.device = device; + } + else if (status == UX_NO_CLASS_MATCH) + { + + /* Query interface class driver. */ + status = _ux_host_stack_class_interface_scan(device); + if (status == UX_SUCCESS) + { + + /* Prepare interfaces activation. */ + device -> ux_device_enum_index = 0; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_SET; + device -> ux_device_enum_inst.configuration = + device -> ux_device_first_configuration; + } + } +} + +static inline VOID _ux_host_stack_device_enumerated(UX_DEVICE *device) +{ + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_DEVICE, + UX_DEVICE_HCD_GET(device), UX_DEVICE_PARENT_GET(device), + UX_DEVICE_PORT_LOCATION_GET(device), 0); + + /* Reset enumeration state. */ + device -> ux_device_enum_state = UX_STATE_IDLE; + + /* Unlock device EP0. */ + device -> ux_device_control_endpoint.ux_endpoint_transfer_request. + ux_transfer_request_flags &= ~UX_TRANSFER_FLAG_LOCK; + + /* Disconnect from enumeration list. */ + + /* Clear enumeration flag to stop enumeration sequence. */ + device -> ux_device_flags &= ~UX_DEVICE_FLAG_ENUM; + + /* If HCD is dead or device disconnected, free device. */ + if (UX_DEVICE_HCD_GET(device) -> ux_hcd_status != UX_HCD_STATUS_OPERATIONAL || + (device -> ux_device_enum_port_status & UX_PS_CCS) == 0) + { + _ux_host_stack_device_remove(UX_DEVICE_HCD_GET(device), + UX_DEVICE_PARENT_GET(device), + UX_DEVICE_PORT_LOCATION_GET(device)); + + /* Done without notification. */ + return; + } + + /* Device connected and enumerated success/fail. */ + + /* For root hub, set root hub connection status. */ + if (UX_DEVICE_PARENT_IS_ROOTHUB(device)) + { + UX_DEVICE_HCD_GET(device) -> ux_hcd_rh_device_connection |= + (ULONG)(1 << UX_DEVICE_PORT_LOCATION_GET(device)); + } + + /* If change function available, notify device connection. */ + if (_ux_system_host -> ux_system_host_change_function) + { + _ux_system_host -> ux_system_host_change_function( + UX_DEVICE_CONNECTION, UX_NULL, (VOID*)device); + } +} + +static inline UINT _ux_host_stack_interface_activate_wait(UX_DEVICE *device, + UX_HOST_CLASS_COMMAND *command) +{ +UINT status; +UX_INTERFACE *interface_inst; + + command -> ux_host_class_command_container = device -> ux_device_enum_inst.ptr; + command -> ux_host_class_command_class_ptr = (device -> ux_device_enum_index == 0xFF) ? + device -> ux_device_class : + device -> ux_device_enum_inst.interface -> ux_interface_class; + command -> ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT; + status = command -> ux_host_class_command_class_ptr -> ux_host_class_entry_function(command); + + /* No wait command or ready for next state. */ + if (status == UX_FUNCTION_NOT_SUPPORTED || + status == UX_STATE_NEXT) + { + + /* Activate for device class driver. */ + if (device -> ux_device_enum_index == 0xFF) + { + + /* Enumeration done (class driver controls device configuration). */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE; + return(UX_STATE_NEXT); + } + else + { + + /* Activate next interface (default setting). */ + interface_inst = device -> ux_device_enum_inst.interface -> ux_interface_next_interface; + while(interface_inst != UX_NULL && + interface_inst -> ux_interface_descriptor.bAlternateSetting != 0) + { + interface_inst = interface_inst -> ux_interface_next_interface; + } + if (interface_inst != UX_NULL) + { + device -> ux_device_enum_inst.interface = interface_inst; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE; + return(UX_STATE_NEXT); + } + + /* Enumeration is done. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE; + return(UX_STATE_NEXT); + } + } + + /* Error cases. */ + if (status < UX_STATE_NEXT) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + return(UX_STATE_NEXT); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} + + +static inline VOID _ux_host_stack_device_enum_run(UX_DEVICE *device) +{ +UX_INTERRUPT_SAVE_AREA +UINT status; +ULONG current_ms, elapsed_ms; +UX_TRANSFER *trans; +UX_CONFIGURATION *configuration; +UX_HOST_CLASS_COMMAND class_command; +UCHAR *buffer; + + /* Check if the device enumeration should be processed. */ + if ((device -> ux_device_flags & UX_DEVICE_FLAG_ENUM) == 0) + return; + + /* Enumeration lock check, devices not addressed should wait. */ + UX_DISABLE + if (_ux_system_host -> ux_system_host_enum_lock && + device -> ux_device_address == 0) + { + + /* Check if the device is the one locks, others should wait. */ + if (device != _ux_system_host -> ux_system_host_enum_lock) + { + + /* Wait, return. */ + UX_RESTORE + return; + } + } + UX_RESTORE + + while (1) + { + switch (device -> ux_device_enum_state) + { + case UX_STATE_RESET: + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_PORT_ENABLE; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_ENABLE; + device -> ux_device_enum_retry = UX_RH_ENUMERATION_RETRY; + device -> ux_device_enum_port_status = UX_PS_CCS; + + /* Fall through. */ + case UX_HOST_STACK_ENUM_PORT_ENABLE: + + /* Lock enumeration any way. */ + _ux_system_host -> ux_system_host_enum_lock = device; + + /* For device connected to roohub, we may need port enable (OHCI). */ +#if UX_MAX_DEVICES > 1 + if (UX_DEVICE_PARENT_IS_HUB(device)) +#endif + { + status = _ux_host_stack_rh_port_enable(device); + if (status == UX_PORT_INDEX_UNKNOWN) + { + + /* No retry, enumeration fail. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + } + + /* Wait a while after port connection. */ + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_RESET; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT; + device -> ux_device_enum_wait_start = _ux_utility_time_get(); + device -> ux_device_enum_wait_ms = + UX_MS_TO_TICK_NON_ZERO(UX_RH_ENUMERATION_RETRY_DELAY); + continue; + + case UX_HOST_STACK_ENUM_PORT_RESET: + +#if UX_MAX_DEVICES > 1 + if (UX_DEVICE_PARENT_IS_HUB(device)) + { + /* NOTE: need hub support. */ + } +#endif + + /* Reset may blocking, wait the reset done. */ + /* Fall through. */ + case UX_HOST_STACK_ENUM_PORT_RESET_WAIT: + + /* Run states for reset. */ + status = _ux_host_stack_rh_port_reset(device); + + /* Check fatal error (exit enumeration). */ + if (status < UX_STATE_ERROR) + { + + /* Fail no retry. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + + /* Check error. */ + if (status == UX_STATE_ERROR) + { + + /* Fail retry. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Ready for next state. */ + if (status == UX_STATE_NEXT) + { + + /* Return device address to 0. */ +#if UX_MAX_DEVICES > 1 + if (device -> ux_device_address) + { + + /* Free the address. */ + UX_DEVICE_HCD_GET(device) -> + ux_hcd_address[(device -> ux_device_address-1) >> 3] &= + (UCHAR)(1u << ((device -> ux_device_address-1) & 7u)); + } +#endif +#if UX_MAX_DEVICES > 1 + if (UX_DEVICE_PARENT_IS_HUB(device)) + { + /* NOTE: need hub support. */ + } +#endif + + /* Get port status. */ + status = _ux_host_stack_rh_port_status_get(device); + if (status == UX_PORT_INDEX_UNKNOWN) + { + + /* Fail no retry: No connection. */ + device -> ux_device_enum_port_status = 0; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + + /* Save port status, next : SetAddress. */ + device -> ux_device_enum_port_status = (UCHAR)status; + device -> ux_device_enum_trans = &device -> + ux_device_control_endpoint.ux_endpoint_transfer_request; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_ADDR_SET; + continue; + } + + /* Keep waiting. */ + return; + + case UX_HOST_STACK_ENUM_DEVICE_ADDR_SET: + + /* Check port connection status. */ + if ((device -> ux_device_enum_port_status & UX_PS_CCS) == 0) + { + + /* Port disconnected, no retry, just fail. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + + /* Set device speed. */ + device -> ux_device_speed = device -> ux_device_enum_port_status >> UX_PS_DS; + + /* Reset bMaxPacketSize0. */ + device -> ux_device_descriptor.bMaxPacketSize0 = 0; + + /* Start SetAddress(). */ + status = _ux_host_stack_device_address_set(device); + if (status != UX_SUCCESS) + { + + /* Request fail, retry. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Wait request progress done. */ + UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_ADDR_SENT; + continue; + + case UX_HOST_STACK_ENUM_DEVICE_ADDR_SENT: + + /* Transfer error check. */ + trans = device -> ux_device_enum_trans; + if (trans -> ux_transfer_request_completion_code != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Address is already sent to device. */ + _ux_host_stack_enum_address_sent(device); + + /* Wait at least 2ms after address is sent. */ + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_READ; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT; + device -> ux_device_enum_wait_start = _ux_utility_time_get(); + device -> ux_device_enum_wait_ms = UX_MS_TO_TICK_NON_ZERO(2); + continue; + + case UX_HOST_STACK_ENUM_DEVICE_DESCR_READ: + + /* Start GetDescriptor(Device). */ + status = _ux_host_stack_device_descriptor_read(device); + if (status != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE; + continue; + + case UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE: + + /* Transfer error check. */ + trans = device -> ux_device_enum_trans; + buffer = trans -> ux_transfer_request_data_pointer; + if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans)) + { + _ux_utility_memory_free(buffer); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Device bMaxPacketSize0 not available, update it. */ + if(device -> ux_device_descriptor.bMaxPacketSize0 == 0) + { + /* Validate the bMaxPacketSize0. */ + if (buffer[7] != 8 && buffer[7] != 16 && buffer[7] != 32 && buffer[7] != 64) + { + + _ux_utility_memory_free(buffer); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Validate the USB-IF bDeviceClass class code. */ +#if defined(UX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE) + switch(buffer[4]) + { + case 0x00: /* Fall through. */ + case 0x02: /* Fall through. */ + case 0x09: /* Fall through. */ + case 0x11: /* Fall through. */ + case 0xDC: /* Fall through. */ + case 0xEF: /* Fall through. */ + case 0xFF: + break; + default: + + /* Invalid device class code. */ + _ux_utility_memory_free(buffer); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } +#endif + + _ux_host_stack_enum_device_descriptor_parse0(device, buffer); + + /* Update SETUP wLength. */ + trans -> ux_transfer_request_requested_length = UX_DEVICE_DESCRIPTOR_LENGTH; + + /* Issue GetDescriptor(Device) again and parse it. */ + UX_TRANSFER_STATE_RESET(trans); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE; + continue; + } + + /* Parse the device descriptor. */ + _ux_utility_descriptor_parse(buffer, + _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES, + (UCHAR *) &device -> ux_device_descriptor); + _ux_utility_memory_free(buffer); + trans -> ux_transfer_request_data_pointer = UX_NULL; + + /* Start configuration enumeration, from index 0. */ + device -> ux_device_enum_index = 0; + + /* Fall through. */ + case UX_HOST_STACK_ENUM_CONFIG_DESCR_READ: + + /* Start GetDescriptor(Configuration, 9). */ + status = _ux_host_stack_enum_configuration_read(device); + if (status != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE; + + /* In this case, there are two memory blocks allocated floating: + - UX_CONFIGURATION + - configuration descriptor RX buffer. */ + continue; + + case UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE: + + /* Transfer error check. */ + trans = device -> ux_device_enum_trans; + buffer = trans -> ux_transfer_request_data_pointer; + if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans)) + { + _ux_utility_memory_free(buffer); + _ux_utility_memory_free(device -> ux_device_enum_inst.ptr); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Load current parsing configuration. */ + configuration = device -> ux_device_enum_inst.configuration; + + /* Get configuration descriptor only. */ + if (trans -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH) + { + + /* Parse the configuration descriptor and free descriptor buffer. */ + _ux_host_stack_enum_configuration_descriptor_parse0(device, configuration, buffer); + + /* Release descriptor buffer. */ + _ux_utility_memory_free(buffer); + trans -> ux_transfer_request_data_pointer = UX_NULL; + + /* If there is no interface for the configuration, check next. */ + if (configuration -> ux_configuration_descriptor.wTotalLength == + UX_CONFIGURATION_DESCRIPTOR_LENGTH) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_NEXT; + continue; + } + + /* Allocate new buffer for total configuration. */ + buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, + UX_CACHE_SAFE_MEMORY, + configuration -> ux_configuration_descriptor.wTotalLength); + if (buffer == UX_NULL) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + trans -> ux_transfer_request_data_pointer = buffer; + + /* Modify transfer length for total configuration */ + trans -> ux_transfer_request_requested_length = + configuration -> ux_configuration_descriptor.wTotalLength; + + /* Start transfer again. */ + UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans); + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE; + + /* In this case, there is one memory blocks allocated floating: + - configuration descriptor RX buffer. */ + continue; + } + + /* Parse configuration and it's interfaces. */ + status = _ux_host_stack_interfaces_scan(configuration, buffer); + + /* Release descriptor memory. */ + _ux_utility_memory_free(buffer); + trans -> ux_transfer_request_data_pointer = UX_NULL; + + /* Check operation status. */ + if (status != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Enumerate next configuration. */ + /* Fall through. */ + case UX_HOST_STACK_ENUM_CONFIG_DESCR_NEXT: + device -> ux_device_enum_index ++; + if (device -> ux_device_enum_index < + device -> ux_device_descriptor.bNumConfigurations) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_READ; + continue; + } + + /* All configurations are enumerated. */ + _ux_host_stack_configuration_parsed(device); + + /* Roll back to next state. */ + continue; + + case UX_HOST_STACK_ENUM_CONFIG_SET: + + /* The device is now in the unconfigured state. We need to deal + with the amount of power the device is consuming before allowing + it to be configured. Otherwise we may run the risk of an over + current fault. */ + configuration = device -> ux_device_enum_inst.configuration; + if (((configuration -> ux_configuration_descriptor.bmAttributes & + UX_CONFIGURATION_DEVICE_SELF_POWERED) == 0) && + (configuration -> ux_configuration_descriptor.MaxPower > + UX_DEVICE_MAX_POWER_GET(device))) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_OVER_CURRENT_CONDITION); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_OVER_CURRENT_CONDITION, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Enumeration fail without retry. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + + /* Prepare transfer request SetConfiguration(). */ + _ux_host_stack_configuration_set(configuration); + + /* Roll back to start transfer wait. */ + UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans); + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_ACTIVATE; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT; + continue; + + case UX_HOST_STACK_ENUM_CONFIG_ACTIVATE: + trans = device -> ux_device_enum_trans; + if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans)) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Set device state to configured. */ + configuration = device -> ux_device_enum_inst.configuration; + device -> ux_device_state = UX_DEVICE_CONFIGURED; + device -> ux_device_current_configuration = configuration; + + /* Create the configuration instance. */ + status = _ux_host_stack_configuration_instance_create(configuration); + if (status != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + if (configuration -> ux_configuration_first_interface) + { + + /* Activate classes. */ + device -> ux_device_enum_index = 0; + device -> ux_device_enum_inst.interface = + configuration -> ux_configuration_first_interface; + } + else + { + + /* No activation, done */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE; + continue; + } + + /* Fall through. */ + case UX_HOST_STACK_ENUM_ACTIVATE: + + /* Class activate. */ + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE_START; + if (device -> ux_device_enum_index == 0xFF) + { + + /* Device class driver. */ + class_command.ux_host_class_command_container = device; + class_command.ux_host_class_command_class_ptr = device -> ux_device_class; + } + else + { + + /* Interface class driver. */ + class_command.ux_host_class_command_container = device -> ux_device_enum_inst.ptr; + class_command.ux_host_class_command_class_ptr = + device -> ux_device_enum_inst.interface -> ux_interface_class; + } + status = class_command.ux_host_class_command_class_ptr -> + ux_host_class_entry_function(&class_command); + if (status != UX_SUCCESS) + { + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Class activate execute wait. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE_WAIT; + + /* Fall through. */ + case UX_HOST_STACK_ENUM_ACTIVATE_WAIT: + + /* Class activate execution wait. */ + status = _ux_host_stack_interface_activate_wait(device, &class_command); + + /* Next state. */ + if (status != UX_STATE_WAIT) + continue; + + /* Keep waiting. */ + return; + + case UX_HOST_STACK_ENUM_TRANS_WAIT: + + /* Poll transfer task. */ + status = _ux_host_stack_transfer_run(device -> ux_device_enum_trans); + + /* Transfer done - next state. */ + if (status == UX_STATE_NEXT || status == UX_STATE_IDLE) + { + device -> ux_device_enum_state = device -> ux_device_enum_next_state; + continue; + } + + /* Check error. */ + if (status < UX_STATE_ERROR) + { + + /* No retry, fail. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL; + continue; + } + if (status < UX_STATE_NEXT) + { + + /* Error, retry. */ + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; + continue; + } + + /* Transfer in progress, wait. */ + return; + + case UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT: + trans = device -> ux_device_enum_trans; + UX_DISABLE + if (trans -> ux_transfer_request_flags & UX_TRANSFER_FLAG_LOCK) + { + + /* Keep waiting. */ + UX_RESTORE; + return; + } + + /* Lock it. */ + trans -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_LOCK; + UX_RESTORE + + /* Apply next expected state. */ + device -> ux_device_enum_state = device -> ux_device_enum_next_state; + continue; + + case UX_HOST_STACK_ENUM_WAIT: + current_ms = _ux_utility_time_get(); + elapsed_ms = _ux_utility_time_elapsed(current_ms, + device -> ux_device_enum_wait_start); + if (elapsed_ms < device -> ux_device_enum_wait_ms) + + /* Keep waiting. */ + return; + + /* Next pre-defined state. */ + device -> ux_device_enum_state = device -> ux_device_enum_next_state; + continue; + + case UX_HOST_STACK_ENUM_RETRY: + + /* Check remaining retry count. */ + if (device -> ux_device_enum_retry > 0) + { + device -> ux_device_enum_retry --; + + /* Start from port enable delay. */ + device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_RESET; + device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT; + device -> ux_device_enum_wait_start = _ux_utility_time_get(); + device -> ux_device_enum_wait_ms = + UX_MS_TO_TICK_NON_ZERO(UX_RH_ENUMERATION_RETRY_DELAY); + continue; + } + + /* Tried several times, fail case. */ + /* Fall through. */ + case UX_HOST_STACK_ENUM_FAIL: + + /* Clear lock anyway. */ + if (device == _ux_system_host -> ux_system_host_enum_lock) + _ux_system_host -> ux_system_host_enum_lock = UX_NULL; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, + UX_DEVICE_PARENT_IS_HUB(device) ? UX_SYSTEM_CONTEXT_HUB : + UX_SYSTEM_CONTEXT_ROOT_HUB, + UX_DEVICE_ENUMERATION_FAILURE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, + UX_DEVICE_PORT_LOCATION_GET(device), 0, 0, UX_TRACE_ERRORS, 0, 0); + + /* Fall through. */ + case UX_HOST_STACK_ENUM_DONE: + _ux_host_stack_device_enumerated(device); + + /* We are done now. */ + /* Fall through. */ + case UX_HOST_STACK_ENUM_IDLE: + + /* Nothing to run. */ + return; + + default: + + /* Invalid state, reset. */ + device -> ux_device_enum_state = UX_STATE_RESET; + } + + /* Run once anyway. */ + break; + } +} + +static inline VOID _ux_host_stack_enum_run(VOID) +{ + +UX_DEVICE *enum_device; + + /* Check if there is device pending enumeration. */ + enum_device = _ux_system_host -> ux_system_host_enum_device; + + /* Run enumeration task for each device. */ + while(enum_device != UX_NULL) + { + + /* Run enumeration task on the device. */ + if ((enum_device -> ux_device_flags & UX_DEVICE_FLAG_PROTECT) == 0) + { + enum_device -> ux_device_flags |= UX_DEVICE_FLAG_PROTECT; + _ux_host_stack_device_enum_run(enum_device); + enum_device -> ux_device_flags &= ~UX_DEVICE_FLAG_PROTECT; + } + + /* Check device lock. */ + if (enum_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + break; + } + + /* Check next enumerating device. */ + enum_device = enum_device -> ux_device_enum_next; + } +} + +static inline VOID _ux_host_stack_pending_transfers_run(VOID) +{ +UX_TRANSFER *transfer, *next; + transfer = _ux_system_host -> ux_system_host_pending_transfers; + while(transfer) + { + next = transfer -> ux_transfer_request_next_pending; + _ux_host_stack_transfer_run(transfer); + if (transfer == next || _ux_system_host -> ux_system_host_pending_transfers == next) + break; + transfer = next; + } +} +#endif diff --git a/common/core/src/ux_host_stack_transfer_request.c b/common/core/src/ux_host_stack_transfer_request.c index 8f7740ff..a93f532e 100644 --- a/common/core/src/ux_host_stack_transfer_request.c +++ b/common/core/src/ux_host_stack_transfer_request.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_transfer_request PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,11 +85,44 @@ /* instead of using them */ /* directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_transfer_request(UX_TRANSFER *transfer_request) { +#if defined(UX_HOST_STANDALONE) +UINT status; + UX_TRANSFER_STATE_RESET(transfer_request); + _ux_host_stack_transfer_run(transfer_request); + if ((transfer_request -> ux_transfer_request_flags & UX_TRANSFER_FLAG_AUTO_WAIT)) + { + while(1) + { + + /* Allow tasks running during waiting. */ + _ux_system_host_tasks_run(); + + if (transfer_request -> ux_transfer_request_state <= UX_STATE_NEXT) + break; + } + status = transfer_request -> ux_transfer_request_completion_code; + } + else + { + + /* In this mode, transfer pending is a success started case. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + status = UX_SUCCESS; + else + status = transfer_request -> ux_transfer_request_completion_code; + } + + /* Return transfer completion status. */ + return(status); +#else UX_INTERRUPT_SAVE_AREA UX_ENDPOINT *endpoint; @@ -115,10 +148,11 @@ UINT status; /* Set the transfer to pending. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STATUS_PENDING; - +#if !defined(UX_HOST_STANDALONE) /* Save the thread making this transfer. If we're under interrupt, this will be null. */ transfer_request -> ux_transfer_request_thread_pending = _ux_utility_thread_identify(); +#endif } else { @@ -131,11 +165,11 @@ UINT status; { /* Check if the class has already protected it. */ - if (device -> ux_device_protection_semaphore.tx_semaphore_count == 0) + if (!_ux_host_semaphore_waiting(&device -> ux_device_protection_semaphore)) { /* Class is using endpoint 0. Unprotect semaphore. */ - _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); + _ux_host_semaphore_put(&device -> ux_device_protection_semaphore); } } @@ -156,11 +190,11 @@ UINT status; { /* Check if the class has already protected it. */ - if (device -> ux_device_protection_semaphore.tx_semaphore_count != 0) + if (_ux_host_semaphore_waiting(&device -> ux_device_protection_semaphore)) { /* We are using endpoint 0. Protect with semaphore. */ - status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -177,8 +211,9 @@ UINT status; if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0) /* We are using endpoint 0. Unprotect with semaphore. */ - _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); + _ux_host_semaphore_put(&device -> ux_device_protection_semaphore); /* And return the status. */ return(status); +#endif } diff --git a/common/core/src/ux_host_stack_transfer_request_abort.c b/common/core/src/ux_host_stack_transfer_request_abort.c index c0b2820d..58591e96 100644 --- a/common/core/src/ux_host_stack_transfer_request_abort.c +++ b/common/core/src/ux_host_stack_transfer_request_abort.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_transfer_request_abort PORTABLE C */ -/* 6.1.7 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 06-02-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed trace enabled error, */ /* resulting in version 6.1.7 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_transfer_request_abort(UX_TRANSFER *transfer_request) @@ -124,13 +127,15 @@ ULONG completion_code; /* Is a thread waiting on the semaphore? */ if (/* Is the transfer pending? */ completion_code == UX_TRANSFER_STATUS_PENDING && +#if !defined(UX_HOST_STANDALONE) /* Is the thread waiting not this one? (clearly we're not waiting!) */ transfer_request -> ux_transfer_request_thread_pending != _ux_utility_thread_identify() && +#endif /* Does the transfer request not have a completion function? */ transfer_request -> ux_transfer_request_completion_function == UX_NULL) /* Wake up the semaphore for this request. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } /* This function never fails! */ diff --git a/common/core/src/ux_host_stack_transfer_run.c b/common/core/src/ux_host_stack_transfer_run.c new file mode 100644 index 00000000..0acf14a8 --- /dev/null +++ b/common/core/src/ux_host_stack_transfer_run.c @@ -0,0 +1,296 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) + +#define UX_HOST_STACK_TRANSFER_LIST_IS_NULL 0 +#define UX_HOST_STACK_TRANSFER_NOT_IN_LIST 1 +#define UX_HOST_STACK_TRANSFER_AT_LIST_HEAD 2 +#define UX_HOST_STACK_TRANSFER_IN_LIST 3 +static inline UINT _ux_host_stack_transfer_locate(UX_TRANSFER *transfer, UX_TRANSFER **previous); +static inline void _ux_host_stack_transfer_retire(UX_TRANSFER *transfer); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_transfer_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a USB transaction. On entry the transfer */ +/* request gives the endpoint pipe selected for this transaction and */ +/* the parameters associated with the transfer (data payload, length */ +/* of transaction) */ +/* */ +/* Note after transfer is done, it's in error or idle state. To ensure */ +/* transfer is ready for next round, use UX_TRANSFER_STATE_RESET(). */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Transfer request structure */ +/* */ +/* 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 */ +/* */ +/* HCD Entry Function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_transfer_run(UX_TRANSFER *transfer_request) +{ + +UX_INTERRUPT_SAVE_AREA + +UX_ENDPOINT *endpoint; +UX_DEVICE *device; +UX_HCD *hcd; +ULONG endpoint_type; +UINT status; + + + /* Get the endpoint container from the transfer_request */ + endpoint = transfer_request -> ux_transfer_request_endpoint; + + /* Sanity check. */ + if (endpoint == UX_NULL) + return(UX_STATE_EXIT); + + /* Get the endpoint type. */ + endpoint_type = endpoint -> ux_endpoint_descriptor.bmAttributes; + endpoint_type &= UX_MASK_ENDPOINT_TYPE; + + /* Get the device container from the endpoint. */ + device = endpoint -> ux_endpoint_device; + + /* Sanity check. */ + if (device == UX_NULL) + return(UX_STATE_EXIT); + + /* Ensure we are not preempted by the enum thread while we check the device + state and set the transfer status. */ + UX_DISABLE + + /* Check if it's default endpoint 0. */ + if (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION) + { + + /* It's not endpoint 0, check device state. */ + if (device -> ux_device_state != UX_DEVICE_ATTACHED && + device -> ux_device_state != UX_DEVICE_ADDRESSED && + device -> ux_device_state != UX_DEVICE_CONFIGURED) + { + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NOT_READY; + transfer_request -> ux_transfer_request_state = UX_STATE_EXIT; + _ux_host_stack_transfer_retire(transfer_request); + + /* Restore interrupts. */ + UX_RESTORE + return(UX_STATE_EXIT); + } + } + + /* With the device we have the pointer to the HCD. */ + hcd = UX_DEVICE_HCD_GET(device); + + /* Process states. */ + switch(transfer_request -> ux_transfer_request_state) + { + case UX_STATE_RESET: + + /* Initialize request fields. */ + transfer_request -> ux_transfer_request_actual_length = 0; + transfer_request -> ux_transfer_request_status = UX_TRANSFER_STATUS_NOT_PENDING; + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STATUS_PENDING; + transfer_request -> ux_transfer_request_state = UX_STATE_WAIT; + transfer_request -> ux_transfer_request_time_start = _ux_utility_time_get(); + + /* Add request to system pending request list. Note request may be kept + if transfer callback is used. */ + if (_ux_host_stack_transfer_locate(transfer_request, UX_NULL) < + UX_HOST_STACK_TRANSFER_AT_LIST_HEAD) + { + transfer_request -> ux_transfer_request_next_pending = + _ux_system_host -> ux_system_host_pending_transfers; + _ux_system_host -> ux_system_host_pending_transfers = transfer_request; + } + + /* Do immediate HCD call to start transfer in background. */ + /* Fall through. */ + case UX_STATE_WAIT: + UX_RESTORE + + { + + /* Send the command to the controller. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_RUN, transfer_request); + } + + /* Any error or end: simplify to idle. */ + if (status < UX_STATE_WAIT) + { + UX_DISABLE + UX_TRANSFER_STATE_IDLE(transfer_request); + _ux_host_stack_transfer_retire(transfer_request); + UX_RESTORE + return(status); + } + + /* Timeout check. */ + if (transfer_request -> ux_transfer_request_timeout_value != UX_WAIT_FOREVER) + { + if (transfer_request -> ux_transfer_request_timeout_value < + _ux_utility_time_elapsed(transfer_request -> ux_transfer_request_time_start, + _ux_utility_time_get())) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* There was an error: simplify to idle. */ + UX_DISABLE + UX_TRANSFER_STATE_IDLE(transfer_request); + _ux_host_stack_transfer_retire(transfer_request); + UX_RESTORE + return(UX_STATE_ERROR); + } + } + + /* And return the status. */ + return(status); + + case UX_STATE_EXIT: + UX_RESTORE + return(UX_STATE_EXIT); + case UX_STATE_IDLE: + UX_RESTORE + return(UX_STATE_IDLE); + + default: /* Error case, return EXIT. */ + break; + } + + /* Error case, return EXIT. */ + transfer_request -> ux_transfer_request_state = UX_STATE_RESET; + _ux_host_stack_transfer_retire(transfer_request); + UX_RESTORE + return(UX_STATE_EXIT); +} +static inline UINT _ux_host_stack_transfer_locate(UX_TRANSFER *transfer, UX_TRANSFER **previous) +{ +UX_TRANSFER *prev; + + /* Case 0: pending list is NULL. */ + if (_ux_system_host -> ux_system_host_pending_transfers == UX_NULL) + return(UX_HOST_STACK_TRANSFER_LIST_IS_NULL); + + /* Case 1: it's list head. */ + if (_ux_system_host -> ux_system_host_pending_transfers == transfer) + return(UX_HOST_STACK_TRANSFER_AT_LIST_HEAD); + + /* Case 2: scan list. */ + prev = _ux_system_host -> ux_system_host_pending_transfers; + do + { + if (prev -> ux_transfer_request_next_pending == transfer) + { + if (previous) + *previous = prev; + return(UX_HOST_STACK_TRANSFER_IN_LIST); + } + prev = prev -> ux_transfer_request_next_pending; + } while (prev); + + /* Case 3: not found. */ + return(UX_HOST_STACK_TRANSFER_NOT_IN_LIST); +} +static inline void _ux_host_stack_transfer_retire(UX_TRANSFER *transfer) +{ +ULONG flags; +UX_TRANSFER *previous; + + /* Locate the request in pending list. */ + switch(_ux_host_stack_transfer_locate(transfer, &previous)) + { + case UX_HOST_STACK_TRANSFER_AT_LIST_HEAD: + + /* Unlink from pending transfer list head. */ + _ux_system_host -> ux_system_host_pending_transfers = + transfer -> ux_transfer_request_next_pending; + break; + case UX_HOST_STACK_TRANSFER_IN_LIST: + + /* Unlink from pending transfer list. */ + previous -> ux_transfer_request_next_pending = + transfer -> ux_transfer_request_next_pending; + break; + + default: + break; + } + + /* Process transfer flags. */ + flags = transfer -> ux_transfer_request_flags; + transfer -> ux_transfer_request_flags &= + ~(UX_TRANSFER_FLAG_LOCK | UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK); + if (flags & UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK) + { + transfer -> ux_transfer_request_endpoint -> + ux_endpoint_device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + } +} +#endif diff --git a/common/core/src/ux_host_stack_uninitialize.c b/common/core/src/ux_host_stack_uninitialize.c index 047482bf..b49dde54 100644 --- a/common/core/src/ux_host_stack_uninitialize.c +++ b/common/core/src/ux_host_stack_uninitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_uninitialize PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 08-02-2021 Xiuwen Cai Modified comment(s), */ /* fixed compile issue, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_stack_uninitialize(VOID) @@ -83,6 +86,7 @@ UINT _ux_host_stack_uninitialize(VOID) /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_UNINITIALIZE, 0, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) +#if !defined(UX_HOST_STANDALONE) /* Delete enumeration thread. */ _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_enum_thread); @@ -100,8 +104,9 @@ UINT _ux_host_stack_uninitialize(VOID) /* Free HCD thread stack. */ _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_thread_stack); +#endif -#if defined(UX_OTG_SUPPORT) +#if defined(UX_OTG_SUPPORT) && !defined(UX_OTG_STANDALONE) /* Delete HNP thread. */ _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_hnp_polling_thread); diff --git a/common/core/src/ux_system_initialize.c b/common/core/src/ux_system_initialize.c index 214701ec..7d862901 100644 --- a/common/core/src/ux_system_initialize.c +++ b/common/core/src/ux_system_initialize.c @@ -69,7 +69,7 @@ UCHAR _ux_system_container_id_descriptor_structure[] = {1,1 /* FUNCTION RELEASE */ /* */ /* _ux_system_initialize PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -112,6 +112,9 @@ UCHAR _ux_system_container_id_descriptor_structure[] = {1,1 /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* added BOS support, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size, @@ -121,8 +124,11 @@ UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memor UX_MEMORY_BLOCK *memory_block; ALIGN_TYPE int_memory_pool_start; VOID *regular_memory_pool_end; -UINT status; ULONG memory_pool_offset; +#if !defined(UX_STANDALONE) +UINT status; +#endif + /* Reset memory block */ _ux_utility_memory_set(regular_memory_pool_start, 0, regular_memory_size); /* Use case of memset is verified. */ @@ -251,10 +257,13 @@ ULONG memory_pool_offset; #endif +#if !defined(UX_STANDALONE) + /* Create the Mutex object used by USBX to control critical sections. */ - status = _ux_utility_mutex_create(&_ux_system -> ux_system_mutex, "ux_system_mutex"); + status = _ux_system_mutex_create(&_ux_system -> ux_system_mutex, "ux_system_mutex"); if(status != UX_SUCCESS) return(UX_MUTEX_ERROR); +#endif return(UX_SUCCESS); } diff --git a/common/core/src/ux_system_tasks_run.c b/common/core/src/ux_system_tasks_run.c new file mode 100644 index 00000000..d8abcf84 --- /dev/null +++ b/common/core/src/ux_system_tasks_run.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** System */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_system.h" +#include "ux_host_stack.h" +#include "ux_device_stack.h" + + +#if defined(UX_STANDALONE) || defined(UX_HOST_STANDALONE) || defined(UX_DEVICE_STANDALONE) || defined(UX_OTG_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_system_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs USB system tasks, including possible tasks for */ +/* host, device and OTG. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_tasks_run Run device tasks */ +/* _ux_host_stack_tasks_run Run host tasks */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_system_tasks_run(VOID) +{ +#if defined(UX_DEVICE_STANDALONE) && !defined(UX_HOST_SIDE_ONLY) + _ux_device_stack_tasks_run(); +#endif +#if defined(UX_HOST_STANDALONE) && !defined(UX_DEVICE_SIDE_ONLY) + _ux_host_stack_tasks_run(); +#endif +#if defined(UX_OTG_STANDALONE) && defined(UX_OTG_SUPPORT) + _ux_otg_tasks_run(); +#endif + + /* Return code not used now. */ + return(0); +} +#endif diff --git a/common/core/src/ux_system_uninitialize.c b/common/core/src/ux_system_uninitialize.c index 5b20e041..4f9235d4 100644 --- a/common/core/src/ux_system_uninitialize.c +++ b/common/core/src/ux_system_uninitialize.c @@ -27,6 +27,7 @@ #include "ux_api.h" #include "ux_system.h" +#include "ux_utility.h" /**************************************************************************/ @@ -34,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_system_uninitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,13 +66,16 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_system_uninitialize(VOID) { /* Delete the Mutex object used by USBX to control critical sections. */ - _ux_utility_mutex_delete(&_ux_system -> ux_system_mutex); + _ux_system_mutex_delete(&_ux_system -> ux_system_mutex); return(UX_SUCCESS); } diff --git a/common/core/src/ux_trace_event_insert.c b/common/core/src/ux_trace_event_insert.c index 305d477c..e47381ff 100644 --- a/common/core/src/ux_trace_event_insert.c +++ b/common/core/src/ux_trace_event_insert.c @@ -83,7 +83,7 @@ /* resulting in version 6.1.9 */ /* */ /**************************************************************************/ -#ifdef TX_ENABLE_EVENT_TRACE +#ifdef UX_ENABLE_EVENT_TRACE VOID _ux_trace_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, TX_TRACE_BUFFER_ENTRY **current_event, ULONG *current_timestamp) { diff --git a/common/core/src/ux_trace_event_update.c b/common/core/src/ux_trace_event_update.c index 76ce1f54..f6ae710f 100644 --- a/common/core/src/ux_trace_event_update.c +++ b/common/core/src/ux_trace_event_update.c @@ -81,7 +81,7 @@ /* resulting in version 6.1.9 */ /* */ /**************************************************************************/ -#ifdef TX_ENABLE_EVENT_TRACE +#ifdef UX_ENABLE_EVENT_TRACE VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4) { diff --git a/common/core/src/ux_trace_object_register.c b/common/core/src/ux_trace_object_register.c index 473b1ae8..26a1206e 100644 --- a/common/core/src/ux_trace_object_register.c +++ b/common/core/src/ux_trace_object_register.c @@ -29,7 +29,7 @@ #include "ux_api.h" -#ifdef TX_ENABLE_EVENT_TRACE +#ifdef UX_ENABLE_EVENT_TRACE extern VOID _tx_trace_object_register(UCHAR , VOID *, CHAR *, ULONG , ULONG ); /**************************************************************************/ /* */ diff --git a/common/core/src/ux_trace_object_unregister.c b/common/core/src/ux_trace_object_unregister.c index a5085cc9..deac88fd 100644 --- a/common/core/src/ux_trace_object_unregister.c +++ b/common/core/src/ux_trace_object_unregister.c @@ -29,7 +29,7 @@ #include "ux_api.h" -#ifdef TX_ENABLE_EVENT_TRACE +#ifdef UX_ENABLE_EVENT_TRACE extern VOID _tx_trace_object_unregister(VOID *); /**************************************************************************/ /* */ diff --git a/common/core/src/ux_utility_delay_ms.c b/common/core/src/ux_utility_delay_ms.c index e996b047..64a3add1 100755 --- a/common/core/src/ux_utility_delay_ms.c +++ b/common/core/src/ux_utility_delay_ms.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_utility_delay_ms PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed compile warnings 64b, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_utility_delay_ms(ULONG ms_wait) @@ -77,6 +80,16 @@ VOID _ux_utility_delay_ms(ULONG ms_wait) ULONG ticks; +#if defined(UX_STANDALONE) + + /* Get current time. */ + ticks = _ux_utility_time_get(); + + /* Wait until timeout. */ + while(_ux_utility_time_elapsed(ticks, _ux_utility_time_get()) < + UX_MS_TO_TICK_NON_ZERO(ms_wait)); +#else + /* translate ms into ticks. */ ticks = (ULONG)(ms_wait * UX_PERIODIC_RATE) / 1000; @@ -85,8 +98,8 @@ ULONG ticks; /* Call ThreadX sleep function. */ tx_thread_sleep(ticks); +#endif /* Return completion status. */ return; } - diff --git a/common/core/src/ux_utility_memory_allocate.c b/common/core/src/ux_utility_memory_allocate.c index 3b550437..f4423ee4 100644 --- a/common/core/src/ux_utility_memory_allocate.c +++ b/common/core/src/ux_utility_memory_allocate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_utility_memory_allocate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID *_ux_utility_memory_allocate(ULONG memory_alignment, ULONG memory_cache_flag, @@ -88,7 +91,7 @@ ALIGN_TYPE int_memory_buffer; /* Get the mutex as this is a critical section. */ - _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + _ux_system_mutex_on(&_ux_system -> ux_system_mutex); #ifdef UX_ENFORCE_SAFE_ALIGNMENT @@ -232,7 +235,7 @@ ALIGN_TYPE int_memory_buffer; { /* Release the protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_system_mutex_off(&_ux_system -> ux_system_mutex); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, memory_size_requested, 0, 0, UX_TRACE_ERRORS, 0, 0) @@ -391,7 +394,7 @@ ALIGN_TYPE int_memory_buffer; #endif /* Release the protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_system_mutex_off(&_ux_system -> ux_system_mutex); /* The memory block pointer contains a memory area properly aligned. */ diff --git a/common/core/src/ux_utility_memory_free.c b/common/core/src/ux_utility_memory_free.c index 54fed00f..bbab0e93 100644 --- a/common/core/src/ux_utility_memory_free.c +++ b/common/core/src/ux_utility_memory_free.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_utility_memory_free PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_utility_memory_free(VOID *memory) @@ -75,9 +78,39 @@ UX_MEMORY_BLOCK *memory_block; UX_MEMORY_BLOCK *next_block; ULONG memory_size_returned; UCHAR *memory_address; +#ifdef UX_ENABLE_MEMORY_POOL_SANITY_CHECK +UCHAR *regular_start, *regular_end; +UCHAR *cache_safe_start, *cache_safe_end; +#endif /* Get the mutex as this is a critical section. */ - _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + _ux_system_mutex_on(&_ux_system -> ux_system_mutex); + +#ifdef UX_ENABLE_MEMORY_POOL_SANITY_CHECK + + /* Sanity check, check if the memory is in memory pool. */ + regular_start = (UCHAR *)_ux_system -> ux_system_regular_memory_pool_start; + regular_end = regular_start + _ux_system -> ux_system_regular_memory_pool_size; + regular_start += sizeof(UX_MEMORY_BLOCK); + cache_safe_start = (UCHAR *)_ux_system -> ux_system_cache_safe_memory_pool_start; + cache_safe_end = cache_safe_start + _ux_system -> ux_system_cache_safe_memory_pool_size; + cache_safe_start += sizeof(UX_MEMORY_BLOCK); + memory_address = (UCHAR *)memory; + if (!((memory_address >= regular_start && memory_address < regular_end) || + (memory_address >= cache_safe_start && memory_address < cache_safe_end))) + { + + /* Not valid. Release the protection. */ + _ux_system_mutex_off(&_ux_system -> ux_system_mutex); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, + UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_CORRUPTED); + + /* No action taken. */ + return; + } +#endif /* The memory block for this memory pointer is located right before the memory. */ @@ -92,7 +125,7 @@ UCHAR *memory_address; { /* Not valid. Release the protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_system_mutex_off(&_ux_system -> ux_system_mutex); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_CORRUPTED); @@ -192,7 +225,7 @@ UCHAR *memory_address; } /* Release the protection. */ - _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + _ux_system_mutex_off(&_ux_system -> ux_system_mutex); /* Return to caller. */ return; diff --git a/common/usbx_device_classes/CMakeLists.txt b/common/usbx_device_classes/CMakeLists.txt index 0cf623a6..f7e3cc68 100644 --- a/common/usbx_device_classes/CMakeLists.txt +++ b/common/usbx_device_classes/CMakeLists.txt @@ -7,6 +7,9 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_control_request.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_deactivate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_entry.c + ${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_frame_write.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_ioctl.c @@ -18,6 +21,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read24.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read32.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read8.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_speed_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_stream_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_transmission_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_unitialize.c @@ -33,8 +37,11 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_read_run.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_unitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write_with_callback.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_bulkin_thread.c @@ -54,6 +61,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_state_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_state_sync.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_control_request.c @@ -64,8 +72,15 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_event_set.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_receiver_event_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_receiver_event_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_receiver_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_receiver_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_receiver_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_control_request.c @@ -101,6 +116,16 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_id_send.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_info_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_entry.c + ${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_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_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 @@ -139,6 +164,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_request_sense.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_start_stop.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_synchronize_cache.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_test_ready.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_uninitialize.c 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 402a1718..30675844 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.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -50,21 +50,29 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added feedback support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ #ifndef UX_DEVICE_CLASS_AUDIO_H -#define UX_DEVICE_CLASS_AUDIO_H - -/* Determine if a C++ compiler is being used. If so, ensure that standard - C is used to process the API information. */ +#define UX_DEVICE_CLASS_AUDIO_H -#ifdef __cplusplus +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ -/* Yes, C++ compiler is present. Use standard C. */ -extern "C" { +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + + +/* Compile option: if defined, audio feedback endpoint is supported. */ +/* #define UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT */ -#endif /* Define Audio Class function (AF) constants. */ @@ -124,6 +132,7 @@ extern "C" { #define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_MASK (0x3u<<4) #define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_DATA (0x0u<<4) +#define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_FEEDBACK (0x1u<<4) #define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_IMPLICIT_FEEDBACK (0x2u<<4) @@ -316,6 +325,10 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER_STRUCT { ULONG ux_device_class_audio_stream_parameter_thread_stack_size; VOID (*ux_device_class_audio_stream_parameter_thread_entry)(ULONG id); +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + ULONG ux_device_class_audio_stream_parameter_feedback_thread_stack_size; + VOID (*ux_device_class_audio_stream_parameter_feedback_thread_entry)(ULONG id); +#endif UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_parameter_callbacks; ULONG ux_device_class_audio_stream_parameter_max_frame_buffer_size; @@ -349,6 +362,13 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT UX_SLAVE_INTERFACE *ux_device_class_audio_stream_interface; UX_SLAVE_ENDPOINT *ux_device_class_audio_stream_endpoint; +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + UX_SLAVE_ENDPOINT *ux_device_class_audio_stream_feedback; + + UCHAR *ux_device_class_audio_stream_feedback_thread_stack; + UX_THREAD ux_device_class_audio_stream_feedback_thread; +#endif + UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_callbacks; UCHAR *ux_device_class_audio_stream_thread_stack; @@ -410,6 +430,11 @@ UINT _ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UINT _ux_device_class_audio_write_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR **buffer, ULONG *max_length); 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_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); + /* Define Device Class Audio API prototypes. */ @@ -427,7 +452,7 @@ UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM * #define ux_device_class_audio_sample_read32 _ux_device_class_audio_sample_read32 #define ux_device_class_audio_read_frame_get _ux_device_class_audio_read_frame_get -#define ux_device_class_audio_read_frame_free _ux_device_class_audio_read_frame_free +#define ux_device_class_audio_read_frame_free _ux_device_class_audio_read_frame_free #define ux_device_class_audio_transmission_start _ux_device_class_audio_transmission_start #define ux_device_class_audio_frame_write _ux_device_class_audio_frame_write @@ -437,10 +462,15 @@ UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM * #define ux_device_class_audio_ioctl _ux_device_class_audio_ioctl -/* Determine if a C++ compiler is being used. If so, complete the standard - C conditional started above. */ +#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_get _ux_device_class_audio_feedback_get +#define ux_device_class_audio_feedback_set _ux_device_class_audio_feedback_set + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ #ifdef __cplusplus -} -#endif +} +#endif #endif /* ifndef UX_DEVICE_CLASS_AUDIO_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h index 93deb6d2..c71165a5 100644 --- a/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_cdc_acm.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -144,6 +147,16 @@ extern "C" { /* Define event group flag. */ #define UX_DEVICE_CLASS_CDC_ACM_WRITE_EVENT 1 + +/* CDC ACM read state machine states. */ +#define UX_DEVICE_CLASS_CDC_ACM_READ_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_CDC_ACM_READ_WAIT (UX_STATE_STEP + 2) + +/* CDC ACM write state machine states. */ +#define UX_DEVICE_CLASS_CDC_ACM_WRITE_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_CDC_ACM_WRITE_WAIT (UX_STATE_STEP + 2) + + /* Define Slave CDC Class Calling Parameter structure */ typedef struct UX_SLAVE_CLASS_CDC_ACM_PARAMETER_STRUCT @@ -160,28 +173,52 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT { UX_SLAVE_INTERFACE *ux_slave_class_cdc_acm_interface; UX_SLAVE_CLASS_CDC_ACM_PARAMETER ux_slave_class_cdc_acm_parameter; + +#if !defined(UX_DEVICE_STANDALONE) UX_MUTEX ux_slave_class_cdc_acm_endpoint_in_mutex; UX_MUTEX ux_slave_class_cdc_acm_endpoint_out_mutex; +#else + UCHAR *ux_device_class_cdc_acm_read_buffer; + ULONG ux_device_class_cdc_acm_read_requested_length; + ULONG ux_device_class_cdc_acm_read_transfer_length; + ULONG ux_device_class_cdc_acm_read_actual_length; + UINT ux_device_class_cdc_acm_read_status; + UINT ux_device_class_cdc_acm_read_state; + + UCHAR *ux_device_class_cdc_acm_write_buffer; + ULONG ux_device_class_cdc_acm_write_transfer_length; + ULONG ux_device_class_cdc_acm_write_requested_length; + ULONG ux_device_class_cdc_acm_write_actual_length; + UINT ux_device_class_cdc_acm_write_status; + UINT ux_device_class_cdc_acm_write_state; +#endif + ULONG ux_slave_class_cdc_acm_baudrate; UCHAR ux_slave_class_cdc_acm_stop_bit; UCHAR ux_slave_class_cdc_acm_parity; UCHAR ux_slave_class_cdc_acm_data_bit; UCHAR ux_slave_class_cdc_acm_data_dtr_state; UCHAR ux_slave_class_cdc_acm_data_rts_state; + UCHAR reserved[3]; + #ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +#if !defined(UX_DEVICE_STANDALONE) UX_THREAD ux_slave_class_cdc_acm_bulkin_thread; UX_THREAD ux_slave_class_cdc_acm_bulkout_thread; + UX_EVENT_FLAGS_GROUP ux_slave_class_cdc_acm_event_flags_group; UCHAR *ux_slave_class_cdc_acm_bulkin_thread_stack; UCHAR *ux_slave_class_cdc_acm_bulkout_thread_stack; +#endif UINT (*ux_device_class_cdc_acm_write_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, ULONG length); UINT (*ux_device_class_cdc_acm_read_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, UCHAR *data_pointer, ULONG length); - UX_EVENT_FLAGS_GROUP ux_slave_class_cdc_acm_event_flags_group; ULONG ux_slave_class_cdc_acm_transmission_status; ULONG ux_slave_class_cdc_acm_scheduled_write; +#if !defined(UX_DEVICE_STANDALONE) ULONG ux_slave_class_cdc_acm_callback_total_length; UCHAR *ux_slave_class_cdc_acm_callback_data_pointer; UCHAR *ux_slave_class_cdc_acm_callback_current_data_pointer; #endif +#endif } UX_SLAVE_CLASS_CDC_ACM; /* Define some CDC Class structures */ @@ -271,6 +308,12 @@ VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG class_pointer); UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, ULONG requested_length); +UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); + +UINT _ux_device_class_cdc_acm_tasks_run(VOID *instance); /* Define Device CDC Class API prototypes. */ @@ -280,6 +323,9 @@ UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_a #define ux_device_class_cdc_acm_ioctl _ux_device_class_cdc_acm_ioctl #define ux_device_class_cdc_acm_write_with_callback _ux_device_class_cdc_acm_write_with_callback +#define ux_device_class_cdc_acm_read_run _ux_device_class_cdc_acm_read_run +#define ux_device_class_cdc_acm_write_run _ux_device_class_cdc_acm_write_run + /* 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_dfu.h b/common/usbx_device_classes/inc/ux_device_class_dfu.h index da31b1f5..f6cf1a61 100644 --- a/common/usbx_device_classes/inc/ux_device_class_dfu.h +++ b/common/usbx_device_classes/inc/ux_device_class_dfu.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_dfu.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,6 +54,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -173,8 +176,8 @@ extern "C" { #define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR 2 /* Define DFU thread event signals. */ -#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT 1 -#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET 2 +#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT 0x1u +#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET 0x2u /* Define Slave DFU Class Calling Parameter structure */ @@ -212,12 +215,26 @@ typedef struct UX_SLAVE_CLASS_DFU_STRUCT #ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE UINT (*ux_device_class_dfu_custom_request)(VOID *dfu, UX_SLAVE_TRANSFER *transfer); #endif + +#if !defined(UX_DEVICE_STANDALONE) UX_THREAD ux_slave_class_dfu_thread; UCHAR *ux_slave_class_dfu_thread_stack; UX_EVENT_FLAGS_GROUP ux_slave_class_dfu_event_flags_group; - +#else + ULONG ux_device_class_dfu_flags; +#endif } UX_SLAVE_CLASS_DFU; +#if !defined(UX_DEVICE_STANDALONE) +#define _ux_device_class_dfu_event_flags_set(dfu, flags) do { \ + _ux_utility_event_flags_set(&(dfu) -> ux_slave_class_dfu_event_flags_group, flags, UX_OR); \ + } while(0) +#else +#define _ux_device_class_dfu_event_flags_set(dfu, flags) do { \ + (dfu) -> ux_device_class_dfu_flags |= flags; \ + } while(0) +#endif + /* Define Device DFU Class prototypes. */ UINT _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command); @@ -230,6 +247,8 @@ VOID _ux_device_class_dfu_thread(ULONG dfu_class); UCHAR _ux_device_class_dfu_state_get(UX_SLAVE_CLASS_DFU *dfu); VOID _ux_device_class_dfu_state_sync(UX_SLAVE_CLASS_DFU *dfu); +UINT _ux_device_class_dfu_tasks_run(VOID *class_instance); + /* Define Device DFU Class API prototypes. */ #define ux_device_class_dfu_entry _ux_device_class_dfu_entry diff --git a/common/usbx_device_classes/inc/ux_device_class_hid.h b/common/usbx_device_classes/inc/ux_device_class_hid.h index 48eac985..0d53f79c 100644 --- a/common/usbx_device_classes/inc/ux_device_class_hid.h +++ b/common/usbx_device_classes/inc/ux_device_class_hid.h @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** HID Class */ /** */ @@ -21,25 +21,25 @@ /**************************************************************************/ -/**************************************************************************/ -/* */ -/* COMPONENT DEFINITION RELEASE */ -/* */ -/* ux_device_class_hid.h PORTABLE C */ -/* 6.1.8 */ +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_hid.h PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ +/* */ /* This file contains all the header and extern functions used by the */ -/* USBX HID class. */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* USBX HID class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* used UX prefix to refer to */ @@ -54,21 +54,37 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added interrupt OUT support,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ #ifndef UX_DEVICE_CLASS_HID_H #define UX_DEVICE_CLASS_HID_H -/* Determine if a C++ compiler is being used. If so, ensure that standard - C is used to process the API information. */ +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ -#ifdef __cplusplus +#ifdef __cplusplus -/* Yes, C++ compiler is present. Use standard C. */ -extern "C" { +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + +/* Device HID Compile Options. */ + +/* If defined, interrupt OUT transfer is supported. */ +/* #define UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT */ + +/* Use UX general thread stack size for receiver thread. */ +#define UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE + +/* Use UX general thread stack size for HID class thread. */ +#define UX_DEVICE_CLASS_HID_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE -#endif /* Define HID Class constants. */ @@ -122,9 +138,13 @@ extern "C" { #define UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE 16 #endif -#define UX_DEVICE_CLASS_HID_NEW_EVENT 1 -#define UX_DEVICE_CLASS_HID_NEW_IDLE_RATE 2 -#define UX_DEVICE_CLASS_HID_EVENTS_MASK 3 +#define UX_DEVICE_CLASS_HID_NEW_EVENT 1u +#define UX_DEVICE_CLASS_HID_NEW_IDLE_RATE 2u +#define UX_DEVICE_CLASS_HID_EVENTS_MASK 3u /* Mask _NEW_EVENT and _NEW_IDLE_RATE */ + +#define UX_DEVICE_CLASS_HID_RECEIVER_RESTART 4u + +#define UX_DEVICE_CLASS_HID_EVENTS_ALL_MASK 7u /* Mask all event flags. */ typedef struct UX_SLAVE_CLASS_HID_EVENT_STRUCT { @@ -132,7 +152,7 @@ typedef struct UX_SLAVE_CLASS_HID_EVENT_STRUCT ULONG ux_device_class_hid_event_report_type; UCHAR ux_device_class_hid_event_buffer[UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH]; ULONG ux_device_class_hid_event_length; - + } UX_SLAVE_CLASS_HID_EVENT; /* Define HID structure. */ @@ -150,7 +170,13 @@ typedef struct UX_SLAVE_CLASS_HID_STRUCT UCHAR *ux_device_class_hid_report_address; ULONG ux_device_class_hid_report_id; ULONG ux_device_class_hid_report_length; +#if !defined(UX_DEVICE_STANDALONE) UX_EVENT_FLAGS_GROUP ux_device_class_hid_event_flags_group; +#else + UINT ux_device_class_hid_event_state; + ULONG ux_device_class_hid_event_wait_start; + UX_SLAVE_CLASS_HID_EVENT ux_device_class_hid_event; +#endif ULONG ux_device_class_hid_event_idle_rate; ULONG ux_device_class_hid_event_wait_timeout; ULONG ux_device_class_hid_protocol; @@ -158,9 +184,56 @@ typedef struct UX_SLAVE_CLASS_HID_STRUCT UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_head; UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_tail; UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_end; - + +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_SLAVE_ENDPOINT *ux_device_class_hid_read_endpoint; + struct UX_DEVICE_CLASS_HID_RECEIVER_STRUCT + *ux_device_class_hid_receiver; +#if !defined(UX_DEVICE_STANDALONE) + UX_MUTEX ux_device_class_hid_read_mutex; +#else + UCHAR *ux_device_class_hid_read_buffer; + UCHAR ux_device_class_hid_read_requested_length; + UCHAR ux_device_class_hid_read_actual_length; + UCHAR ux_device_class_hid_read_transfer_length; + UINT ux_device_class_hid_read_state; +#endif +#endif + } UX_SLAVE_CLASS_HID; + +/* HID interrupt OUT support extensions. */ + +typedef struct UX_DEVICE_CLASS_HID_RECEIVED_EVENT_STRUCT +{ + ULONG ux_device_class_hid_received_event_length; + UCHAR *ux_device_class_hid_received_event_data; +} UX_DEVICE_CLASS_HID_RECEIVED_EVENT; + +typedef struct UX_DEVICE_CLASS_HID_RECEIVER_STRUCT +{ + + VOID (*ux_device_class_hid_receiver_uninitialize)(struct UX_DEVICE_CLASS_HID_RECEIVER_STRUCT *receiver); + + ULONG ux_device_class_hid_receiver_event_buffer_size; + UX_DEVICE_CLASS_HID_RECEIVED_EVENT + *ux_device_class_hid_receiver_events; + UX_DEVICE_CLASS_HID_RECEIVED_EVENT + *ux_device_class_hid_receiver_events_end; + UX_DEVICE_CLASS_HID_RECEIVED_EVENT + *ux_device_class_hid_receiver_event_read_pos; + UX_DEVICE_CLASS_HID_RECEIVED_EVENT + *ux_device_class_hid_receiver_event_save_pos; + +#if !defined(UX_DEVICE_STANDALONE) + UX_THREAD ux_device_class_hid_receiver_thread; +#else + VOID (*ux_device_class_hid_receiver_tasks_run)(struct UX_SLAVE_CLASS_HID_STRUCT *hid); +#endif +} UX_DEVICE_CLASS_HID_RECEIVER; + + /* Define HID initialization command structure. */ typedef struct UX_SLAVE_CLASS_HID_PARAMETER_STRUCT @@ -173,12 +246,17 @@ typedef struct UX_SLAVE_CLASS_HID_PARAMETER_STRUCT ULONG ux_device_class_hid_parameter_report_length; UINT (*ux_device_class_hid_parameter_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); UINT (*ux_device_class_hid_parameter_get_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UINT (*ux_device_class_hid_parameter_receiver_initialize)(UX_SLAVE_CLASS_HID *hid, struct UX_SLAVE_CLASS_HID_PARAMETER_STRUCT *parameter, UX_DEVICE_CLASS_HID_RECEIVER **receiver); + ULONG ux_device_class_hid_parameter_receiver_event_max_number; + ULONG ux_device_class_hid_parameter_receiver_event_max_length; +#endif } UX_SLAVE_CLASS_HID_PARAMETER; /* Define HID Class function prototypes. */ -UINT _ux_device_class_hid_descriptor_send(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, +UINT _ux_device_class_hid_descriptor_send(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, ULONG request_index, ULONG host_length); UINT _ux_device_class_hid_activate(UX_SLAVE_CLASS_COMMAND *command); UINT _ux_device_class_hid_deactivate(UX_SLAVE_CLASS_COMMAND *command); @@ -187,30 +265,51 @@ UINT _ux_device_class_hid_entry(UX_SLAVE_CLASS_COMMAND *command); VOID _ux_device_class_hid_interrupt_thread(ULONG hid_class); UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command); UINT _ux_device_class_hid_uninitialize(UX_SLAVE_CLASS_COMMAND *command); -UINT _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid, +UINT _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid, UX_SLAVE_CLASS_HID_EVENT *hid_event); -UINT _ux_device_class_hid_event_get(UX_SLAVE_CLASS_HID *hid, +UINT _ux_device_class_hid_event_get(UX_SLAVE_CLASS_HID *hid, UX_SLAVE_CLASS_HID_EVENT *hid_event); -UINT _ux_device_class_hid_report_set(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, +UINT _ux_device_class_hid_report_set(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, ULONG request_index, ULONG host_length); -UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, +UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, ULONG request_index, ULONG host_length); +UINT _ux_device_class_hid_tasks_run(VOID *class_instance); + +UINT _ux_device_class_hid_read(UX_SLAVE_CLASS_HID *hid, + UCHAR *buffer, ULONG requested_length, + ULONG *actual_length); + +VOID _ux_device_class_hid_receiver_thread(ULONG hid_class); +UINT _ux_device_class_hid_receiver_initialize(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_PARAMETER *parameter, + UX_DEVICE_CLASS_HID_RECEIVER **receiver); +VOID _ux_device_class_hid_receiver_uninitialize(UX_DEVICE_CLASS_HID_RECEIVER *receiver); +UINT _ux_device_class_hid_receiver_event_get(UX_SLAVE_CLASS_HID *hid, + UX_DEVICE_CLASS_HID_RECEIVED_EVENT *event); +UINT _ux_device_class_hid_receiver_event_free(UX_SLAVE_CLASS_HID *hid); + + /* Define Device HID Class API prototypes. */ -#define ux_device_class_hid_entry _ux_device_class_hid_entry +#define ux_device_class_hid_entry _ux_device_class_hid_entry #define ux_device_class_hid_event_set _ux_device_class_hid_event_set #define ux_device_class_hid_event_get _ux_device_class_hid_event_get #define ux_device_class_hid_report_set _ux_device_class_hid_report_set #define ux_device_class_hid_report_get _ux_device_class_hid_report_get -#define ux_device_class_hid_protocol_get(hid) (hid -> ux_device_class_hid_protocol) +#define ux_device_class_hid_protocol_get(hid) (hid -> ux_device_class_hid_protocol) +#define ux_device_class_hid_read _ux_device_class_hid_read -/* Determine if a C++ compiler is being used. If so, complete the standard - C conditional started above. */ +#define ux_device_class_hid_receiver_initialize _ux_device_class_hid_receiver_initialize +#define ux_device_class_hid_receiver_event_get _ux_device_class_hid_receiver_event_get +#define ux_device_class_hid_receiver_event_free _ux_device_class_hid_receiver_event_free + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ #ifdef __cplusplus -} -#endif +} +#endif #endif diff --git a/common/usbx_device_classes/inc/ux_device_class_pima.h b/common/usbx_device_classes/inc/ux_device_class_pima.h index 93dbfab7..00242b18 100644 --- a/common/usbx_device_classes/inc/ux_device_class_pima.h +++ b/common/usbx_device_classes/inc/ux_device_class_pima.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_pima.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -50,6 +50,11 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated definitions, */ +/* improved internal function, */ +/* added cancel callback, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -68,6 +73,15 @@ extern "C" { /* Define PIMA Class constants. */ +#define UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#define UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD (UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) +#define UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) +#define UX_DEVICE_CLASS_PIMA_STORAGE_INFO_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) +#define UX_DEVICE_CLASS_PIMA_ARRAY_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) +#define UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE (UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) + #define UX_DEVICE_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT 300000 #define UX_DEVICE_CLASS_PIMA_CLASS 0x06 #define UX_DEVICE_CLASS_PIMA_SUBCLASS 0X01 @@ -75,20 +89,11 @@ extern "C" { #define UX_DEVICE_CLASS_PIMA_MAGIC_NUMBER 0x50494D41 #define UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH 256 #define UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH 64 -#define UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD 1024 -#define UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE 1024 -#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_BUFFER_SIZE 1024 -#define UX_DEVICE_CLASS_PIMA_STORAGE_INFO_BUFFER_SIZE 1024 -#define UX_DEVICE_CLASS_PIMA_ARRAY_BUFFER_SIZE 1024 #define UX_DEVICE_CLASS_PIMA_MAX_EVENTS_QUEUE 16 #define UX_DEVICE_CLASS_PIMA_MAX_STORAGE_IDS 1 -#define UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH 256 #define UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH 256 -#define UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH 64 #define UX_DEVICE_CLASS_PIMA_DEVICE_PROPERTIES_ARRAY_MAX_ITEMS 32 #define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTIES_ARRAY_MAX_ITEMS 128 -#define UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE 1024 -#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE 1024 #define UX_DEVICE_CLASS_PIMA_PROP_VALUE_SIZE 256 #define UX_DEVICE_CLASS_PIMA_MICROSOFT_VENDOR_COMMAND_CODE 0x54 @@ -98,6 +103,15 @@ extern "C" { #define UX_DEVICE_CLASS_PIMA_EXTENSION_VERSION 100 #define UX_DEVICE_CLASS_PIMA_STANDARD_MODE 0 + +/* Define PIMA phases. */ + +#define UX_DEVICE_CLASS_PIMA_PHASE_IDLE 0 +#define UX_DEVICE_CLASS_PIMA_PHASE_COMMAND 1 +#define UX_DEVICE_CLASS_PIMA_PHASE_RESPONSE 2 +#define UX_DEVICE_CLASS_PIMA_PHASE_DATA_IN 3 +#define UX_DEVICE_CLASS_PIMA_PHASE_DATA_OUT 4 + /* Define PIMA data phases. */ #define UX_DEVICE_CLASS_PIMA_DATA_PHASE_NONE 0 @@ -786,6 +800,7 @@ typedef struct UX_SLAVE_CLASS_PIMA_STRUCT UX_SLAVE_ENDPOINT *ux_device_class_pima_bulk_out_endpoint; UX_SLAVE_ENDPOINT *ux_device_class_pima_interrupt_endpoint; UINT ux_device_class_pima_state; + USHORT ux_device_class_pima_device_status; ULONG ux_device_class_pima_session_id; ULONG ux_device_class_pima_current_object_handle; ULONG ux_device_class_pima_transaction_id; @@ -820,6 +835,7 @@ typedef struct UX_SLAVE_CLASS_PIMA_STRUCT USHORT *ux_device_class_pima_supported_capture_formats_list; USHORT *ux_device_class_pima_supported_image_formats_list; USHORT *ux_device_class_pima_object_properties_list; + UINT (*ux_device_class_pima_cancel)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); UINT (*ux_device_class_pima_device_reset)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); UINT (*ux_device_class_pima_device_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_dataset, ULONG *device_prop_dataset_length); @@ -878,6 +894,9 @@ typedef struct UX_SLAVE_CLASS_PIMA_PARAMETER_STRUCT USHORT *ux_device_class_pima_parameter_supported_capture_formats_list; USHORT *ux_device_class_pima_parameter_supported_image_formats_list; USHORT *ux_device_class_pima_parameter_object_properties_list; + + /* PIMA callbacks, return UX success, or PIMA RC code. */ + UINT (*ux_device_class_pima_parameter_cancel)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); UINT (*ux_device_class_pima_parameter_device_reset)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); UINT (*ux_device_class_pima_parameter_device_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_dataset, ULONG *device_prop_dataset_length); UINT (*ux_device_class_pima_parameter_device_prop_value_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_value, ULONG *device_prop_value_length); @@ -959,7 +978,7 @@ UINT _ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG obj UINT _ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id, ULONG parent_object_handle); UINT _ux_device_class_pima_object_data_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); UINT _ux_device_class_pima_object_data_send(UX_SLAVE_CLASS_PIMA *pima); -UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); +UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle, ULONG object_format); UINT _ux_device_class_pima_object_add(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); UINT _ux_device_class_pima_partial_object_data_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle, diff --git a/common/usbx_device_classes/inc/ux_device_class_printer.h b/common/usbx_device_classes/inc/ux_device_class_printer.h new file mode 100644 index 00000000..d434bcea --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_printer.h @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_printer.h PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Class */ +/* Printer component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_PRINTER_H +#define UX_DEVICE_CLASS_PRINTER_H + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + + +/* Define Printer Class USB Class constants. */ +#define UX_DEVICE_CLASS_PRINTER_CLASS 7 + +#define UX_DEVICE_CLASS_PRINTER_SUBCLASS 1 + +#define UX_DEVICE_CLASS_PRINTER_PROTOCOL_UNIDIRECTIONAL 1 +#define UX_DEVICE_CLASS_PRINTER_PROTOCOL_BIDIRECTIONAL 2 +#define UX_DEVICE_CLASS_PRINTER_PROTOCOL_1284_4_COMPATIBLE_BIDIR 3 + + +/* Device Printer Requests */ +#define UX_DEVICE_CLASS_PRINTER_GET_DEVICE_ID 0x00 +#define UX_DEVICE_CLASS_PRINTER_GET_PORT_STATUS 0x01 +#define UX_DEVICE_CLASS_PRINTER_SOFT_RESET 0x02 + + +/* Printer Port Status. */ +#define UX_DEVICE_CLASS_PRINTER_PAPER_EMPTY (1u << 5) +#define UX_DEVICE_CLASS_PRINTER_SELECT (1u << 4) +#define UX_DEVICE_CLASS_PRINTER_NOT_ERROR (1u << 3) + + +/* Printer IOCTL code. */ +#define UX_DEVICE_CLASS_PRINTER_IOCTL_PORT_STATUS_SET 1 +#define UX_DEVICE_CLASS_PRINTER_IOCTL_READ_TIMEOUT_SET 2 +#define UX_DEVICE_CLASS_PRINTER_IOCTL_WRITE_TIMEOUT_SET 3 + + +/* Define Device Printer Class Calling Parameter structure */ + +typedef struct UX_DEVICE_CLASS_PRINTER_PARAMETER_STRUCT +{ + UCHAR *ux_device_class_printer_device_id; /* IEEE 1284 string, first 2 big endian length. */ + VOID (*ux_device_class_printer_instance_activate)(VOID *); + VOID (*ux_device_class_printer_instance_deactivate)(VOID *); + VOID (*ux_device_class_printer_soft_reset)(VOID *); +} UX_DEVICE_CLASS_PRINTER_PARAMETER; + + +/* Define Printer Class structure. */ + +typedef struct UX_DEVICE_CLASS_PRINTER_STRUCT +{ + UX_SLAVE_INTERFACE *ux_device_class_printer_interface; + UX_SLAVE_ENDPOINT *ux_device_class_printer_endpoint_out; + UX_SLAVE_ENDPOINT *ux_device_class_printer_endpoint_in; + ULONG ux_device_class_printer_port_status; + UX_DEVICE_CLASS_PRINTER_PARAMETER + ux_device_class_printer_parameter; + UX_MUTEX ux_device_class_printer_endpoint_out_mutex; + UX_MUTEX ux_device_class_printer_endpoint_in_mutex; +} UX_DEVICE_CLASS_PRINTER; + + +/* Define Device Printer Class prototypes. */ + +UINT _ux_device_class_printer_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_printer_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_printer_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_printer_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_printer_uninitialize(UX_SLAVE_CLASS_COMMAND *command); + +VOID _ux_device_class_printer_soft_reset(UX_DEVICE_CLASS_PRINTER *printer); + +UINT _ux_device_class_printer_write(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_printer_read(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); + +UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioctl_function, + VOID *parameter); + + +/* Define Device Printer Class API prototypes. */ + +#define ux_device_class_printer_entry _ux_device_class_printer_entry +#define ux_device_class_printer_read _ux_device_class_printer_read +#define ux_device_class_printer_write _ux_device_class_printer_write +#define ux_device_class_printer_ioctl _ux_device_class_printer_ioctl + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus +} +#endif + +#endif /* UX_DEVICE_CLASS_PRINTER_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_storage.h b/common/usbx_device_classes/inc/ux_device_class_storage.h index db366199..a1d34e1f 100644 --- a/common/usbx_device_classes/inc/ux_device_class_storage.h +++ b/common/usbx_device_classes/inc/ux_device_class_storage.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_storage.h PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,6 +54,9 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* improved TAG management, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -76,6 +79,7 @@ extern "C" { #define UX_MAX_SLAVE_LUN 2 #endif + /* Define Storage Class USB Class constants. */ #define UX_SLAVE_CLASS_STORAGE_CLASS 8 @@ -135,6 +139,12 @@ extern "C" { #define UX_SLAVE_CLASS_STORAGE_CBW_CB 15 #define UX_SLAVE_CLASS_STORAGE_CBW_LENGTH 31 +#define UX_DEVICE_CLASS_STORAGE_CBW_FLAG_DIR (1u<<7) +#define UX_DEVICE_CLASS_STORAGE_CBW_FLAG_IN (1u<<7) +#define UX_DEVICE_CLASS_STORAGE_CBW_FLAG_D2H (1u<<7) +#define UX_DEVICE_CLASS_STORAGE_CBW_FLAG_OUT (0u) +#define UX_DEVICE_CLASS_STORAGE_CBW_FLAG_H2D (0u) + /* Define Storage Class SCSI response status wrapper constants. */ @@ -433,6 +443,39 @@ extern "C" { #define UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC 0x1C #define UX_SLAVE_CLASS_STORAGE_PAGE_CODE_ALL 0x3F +#if defined(UX_DEVICE_STANDALONE) + +/* Define Device Storage Class states. */ + +#define UX_DEVICE_CLASS_STORAGE_STATE_IDLE (UX_STATE_STEP + 0) +#define UX_DEVICE_CLASS_STORAGE_STATE_RESET (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_STORAGE_STATE_RESET_WAIT (UX_STATE_STEP + 2) +#define UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START (UX_STATE_STEP + 3) +#define UX_DEVICE_CLASS_STORAGE_STATE_TRANS_WAIT (UX_STATE_STEP + 4) +#define UX_DEVICE_CLASS_STORAGE_STATE_TRANS_NEXT (UX_STATE_STEP + 5) +#define UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT (UX_STATE_STEP + 6) +#define UX_DEVICE_CLASS_STORAGE_STATE_DISK_ERROR (UX_STATE_STEP + 7) + +#define UX_DEVICE_CLASS_STORAGE_DISK_IDLE (0) +#define UX_DEVICE_CLASS_STORAGE_DISK_OP_START (1) +#define UX_DEVICE_CLASS_STORAGE_DISK_OP_WAIT (2) +#define UX_DEVICE_CLASS_STORAGE_DISK_OP_NEXT (3) +#define UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT (4) +#define UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR (5) + +#define UX_DEVICE_CLASS_STORAGE_BUFFER_IDLE (0) +#define UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY (1) +#define UX_DEVICE_CLASS_STORAGE_BUFFER_FULL (2) + +#define UX_DEVICE_CLASS_STORAGE_CMD_IDLE (0) +#define UX_DEVICE_CLASS_STORAGE_CMD_CBW (1) +#define UX_DEVICE_CLASS_STORAGE_CMD_ERR (2) +#define UX_DEVICE_CLASS_STORAGE_CMD_CSW (3) +#define UX_DEVICE_CLASS_STORAGE_CMD_WRITE (4) +#define UX_DEVICE_CLASS_STORAGE_CMD_READ (5) +#define UX_DEVICE_CLASS_STORAGE_CMD_DISK_OP (6) + +#endif /* Define Slave Storage Class LUN structure. */ @@ -447,6 +490,7 @@ typedef struct UX_SLAVE_CLASS_STORAGE_LUN_STRUCT ULONG ux_slave_class_storage_request_sense_status; ULONG ux_slave_class_storage_disk_status; ULONG ux_slave_class_storage_last_session_state; + UINT (*ux_slave_class_storage_media_read)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status); UINT (*ux_slave_class_storage_media_write)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status); UINT (*ux_slave_class_storage_media_flush)(VOID *storage, ULONG lun, ULONG number_blocks, ULONG lba, ULONG *media_status); @@ -483,6 +527,34 @@ typedef struct UX_SLAVE_CLASS_STORAGE_STRUCT UCHAR *ux_slave_class_storage_product_rev; UCHAR *ux_slave_class_storage_product_serial; +#if defined(UX_DEVICE_STANDALONE) + UCHAR *ux_device_class_storage_buffer[2]; + UCHAR ux_device_class_storage_buffer_state[2]; + UCHAR ux_device_class_storage_buffer_usb; + UCHAR ux_device_class_storage_buffer_disk; + + UCHAR ux_device_class_storage_cmd; + UCHAR ux_device_class_storage_cmd_state; + UCHAR ux_device_class_storage_disk_state; + UCHAR ux_device_class_storage_state; + + UX_SLAVE_ENDPOINT *ux_device_class_storage_ep_out; + UX_SLAVE_ENDPOINT *ux_device_class_storage_ep_in; + UX_SLAVE_TRANSFER *ux_device_class_storage_transfer; + + ULONG ux_device_class_storage_device_length; + UCHAR *ux_device_class_storage_data_buffer; + ULONG ux_device_class_storage_data_length; + ULONG ux_device_class_storage_data_count; + ULONG ux_device_class_storage_trans_host_length; + ULONG ux_device_class_storage_trans_device_length; + + ULONG ux_device_class_storage_cmd_lba; + ULONG ux_device_class_storage_cmd_n_lb; + ULONG ux_device_class_storage_disk_n_lb; + ULONG ux_device_class_storage_media_status; +#endif + } UX_SLAVE_CLASS_STORAGE; #define UX_DEVICE_CLASS_STORAGE_CSW_STATUS(p) (((UCHAR*)(p))[0]) @@ -568,6 +640,8 @@ UINT _ux_device_class_storage_read_dvd_structure(UX_SLAVE_CLASS_STORAGE *stor UX_SLAVE_ENDPOINT *endpoint_in, UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_tasks_run(VOID *instance); + /* Define Device Storage Class API prototypes. */ #define ux_device_class_storage_entry _ux_device_class_storage_entry diff --git a/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c index 20fb743c..78f7629d 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c +++ b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio20_control_process PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -79,6 +79,10 @@ /* 04-02-2021 Chaoqiong Xiao Modified comment(s), */ /* added volume RES support, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* allowed answer length only */ +/* when requesting range, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio20_control_process(UX_DEVICE_CLASS_AUDIO *audio, @@ -162,7 +166,7 @@ ULONG i; _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 2, control -> ux_device_class_audio20_control_sampling_frequency); _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 6, control -> ux_device_class_audio20_control_sampling_frequency); _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 10, 0); - _ux_device_stack_transfer_request(transfer, 14, request_length); + _ux_device_stack_transfer_request(transfer, UX_MIN(14, request_length), request_length); return(UX_SUCCESS); default: 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 8b5e6b9f..aff9cdcf 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.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* replaced wMaxPacketSize by */ /* calculated payload size, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added feedback support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_change(UX_SLAVE_CLASS_COMMAND *command) @@ -81,6 +84,7 @@ UX_SLAVE_INTERFACE *interface; UX_SLAVE_ENDPOINT *endpoint; UCHAR *frame_buffer; ULONG stream_index; +ULONG endpoint_dir; /* Get the class container. */ @@ -118,35 +122,79 @@ ULONG stream_index; if (interface -> ux_slave_interface_descriptor.bAlternateSetting != 0) { - /* Locate the endpoints. ISO IN/OUT for Streaming Interface. */ + /* Locate the endpoints. ISO IN(write)/OUT(read) for Streaming Interface. */ endpoint = interface -> ux_slave_interface_first_endpoint; /* Parse all endpoints. */ + endpoint_dir = (stream -> ux_device_class_audio_stream_thread.tx_thread_entry == + _ux_device_class_audio_read_thread_entry) ? + UX_ENDPOINT_OUT : UX_ENDPOINT_IN; stream -> ux_device_class_audio_stream_endpoint = UX_NULL; - while (endpoint != UX_NULL) + +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + stream -> ux_device_class_audio_stream_feedback = UX_NULL; +#endif + while(endpoint != UX_NULL) { - /* Check the endpoint. */ - if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & - (UX_DEVICE_CLASS_AUDIO_EP_TRANSFER_TYPE_MASK | UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_MASK)) == UX_ISOCHRONOUS_ENDPOINT) + /* Check the endpoint attributes. */ + if((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & + UX_DEVICE_CLASS_AUDIO_EP_TRANSFER_TYPE_MASK) == UX_ISOCHRONOUS_ENDPOINT) { - /* We found the endpoint, check its size. */ - if (endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length > stream -> ux_device_class_audio_stream_frame_buffer_size - 8) + /* Check the endpoint direction. */ + if ((endpoint->ux_slave_endpoint_descriptor.bEndpointAddress & + UX_ENDPOINT_DIRECTION) == endpoint_dir) { - /* Error trap! */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + /* We found the data endpoint, check its size. */ + if (endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length > stream -> ux_device_class_audio_stream_frame_buffer_size - 8) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); - /* Frame buffer too small for endpoints. */ - return(UX_MEMORY_INSUFFICIENT); + /* Frame buffer too small for endpoints. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Save it. */ + stream -> ux_device_class_audio_stream_endpoint = endpoint; } +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + else + { - /* Save it. */ - stream -> ux_device_class_audio_stream_endpoint = endpoint; - break; + /* We found the feedback endpoint, check its size. */ + if (endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length < + (_ux_system_slave->ux_system_slave_speed == UX_HIGH_SPEED_DEVICE ? 4 : 3)) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Frame buffer too small for endpoints. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Set request length. */ + endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_requested_length = + (_ux_system_slave -> ux_system_slave_speed == UX_HIGH_SPEED_DEVICE) ? 4 : 3; + + /* Save it. */ + stream -> ux_device_class_audio_stream_feedback = endpoint; + } +#endif } + /* Check if done. */ + if (stream -> ux_device_class_audio_stream_endpoint +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + && stream -> ux_device_class_audio_stream_feedback +#endif + ) + break; + /* Next endpoint. */ endpoint = endpoint -> ux_slave_endpoint_next_endpoint; } @@ -175,12 +223,22 @@ ULONG stream_index; frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; } 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 feedback supported, resume the thread. */ + if (stream -> ux_device_class_audio_stream_feedback_thread_stack) + _ux_utility_thread_resume(&stream -> ux_device_class_audio_stream_feedback_thread); +#endif } else { /* There is no data endpoint. */ stream -> ux_device_class_audio_stream_endpoint = UX_NULL; +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + stream -> ux_device_class_audio_stream_feedback = UX_NULL; +#endif /* In this case, we are reverting to the Alternate Setting 0. We need to terminate the pending transactions. */ /* Endpoints actually aborted and destroyed before change command. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_get.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_get.c new file mode 100644 index 00000000..eede8543 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_get.c @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_feedback_get PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtain encoded feedback from the Audio Stream. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* encoded_feedback Feedback data (3 or 4 bytes) */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_feedback_get(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + UCHAR *encoded_feedback) +{ +#if !defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + UX_PARAMETER_NOT_USED(stream); + UX_PARAMETER_NOT_USED(encoded_feedback); + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *buffer; + + + /* 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) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_feedback; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Get transfer buffer. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + buffer = transfer -> ux_slave_transfer_request_data_pointer; + + /* Get packed data. */ + *encoded_feedback ++ = *buffer ++; + *encoded_feedback ++ = *buffer ++; + *encoded_feedback ++ = *buffer ++; + if (_ux_system_slave -> ux_system_slave_speed == UX_HIGH_SPEED_DEVICE) + *encoded_feedback = *buffer; + return(UX_SUCCESS); +#endif +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_set.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_set.c new file mode 100644 index 00000000..898eeea5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_set.c @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_feedback_set PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function set encoded feedback of the Audio Stream. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* encoded_feedback Feedback data (3 or 4 bytes) */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_feedback_set(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + UCHAR *encoded_feedback) +{ +#if !defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + UX_PARAMETER_NOT_USED(stream); + UX_PARAMETER_NOT_USED(encoded_feedback); + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *buffer; + + + /* 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) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_feedback; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + return(UX_ERROR); + + /* Transfer buffer. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + buffer = transfer -> ux_slave_transfer_request_data_pointer; + + /* Save data. */ + *buffer++ = *encoded_feedback ++; + *buffer++ = *encoded_feedback ++; + *buffer++ = *encoded_feedback ++; + if (_ux_system_slave -> ux_system_slave_speed == UX_HIGH_SPEED_DEVICE) + *buffer = *encoded_feedback; + return(UX_SUCCESS); +#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 new file mode 100644 index 00000000..88525f1b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* 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) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_feedback_thread_entry PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is thread of ISO OUT/IN (feedback of IN/OUT) */ +/* for the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* audio_stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_utility_thread_suspend Suspend thread used */ +/* _ux_device_stack_transfer_request Issue transfer request */ +/* _ux_utility_memory_copy Copy data */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_audio_feedback_thread_entry(ULONG audio_stream) +{ + +UINT status; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +ULONG transfer_length; + + + /* Get Audio class stream instance. */ + UX_THREAD_EXTENSION_PTR_GET(stream, UX_DEVICE_CLASS_AUDIO_STREAM, audio_stream) + + /* Get stack device instance. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* This thread runs forever but can be suspended or resumed. */ + while (1) + { + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Get endpoint instance. */ + endpoint = stream -> ux_device_class_audio_stream_feedback; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + break; + + /* 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; + + /* Issue transfer request, thread blocked until transfer done. */ + status = _ux_device_stack_transfer_request(transfer, transfer_length, transfer_length); + + /* Check error. */ + if (status == UX_TRANSFER_BUS_RESET) + continue; + if (status != UX_SUCCESS) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + break; + } + + /* Transfer done, keep data in transfer buffer. */ + } + + /* 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 diff --git a/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c b/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c index 18406704..20538c60 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_frame_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed frame length check, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *stream, UCHAR *frame, ULONG length) @@ -105,7 +108,7 @@ ULONG frame_buffer_size; /* Check frame length. */ frame_buffer_size = stream -> ux_device_class_audio_stream_frame_buffer_size; - if (frame_buffer_size < length) + if ((frame_buffer_size - 8) < length) return(UX_ERROR); /* Check overflow!! */ 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 904fb6ab..97e9df50 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,8 +55,8 @@ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_copy Copy memory */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_thread_create Create thread to use */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_create Create thread to use */ +/* _ux_device_thread_delete Delete thread */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,10 @@ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added feedback support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -180,7 +184,7 @@ ULONG i; } /* Create streaming thread. */ - status = _ux_utility_thread_create(&stream -> ux_device_class_audio_stream_thread , "ux_device_class_audio_stream_thread", + status = _ux_device_thread_create(&stream -> ux_device_class_audio_stream_thread , "ux_device_class_audio_stream_thread", stream_parameter -> ux_device_class_audio_stream_parameter_thread_entry, (ULONG)(ALIGN_TYPE)stream, (VOID *) stream -> ux_device_class_audio_stream_thread_stack, memory_size, UX_THREAD_PRIORITY_CLASS, @@ -192,6 +196,41 @@ ULONG i; UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_thread), stream) +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + + /* 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; + else + memory_size = stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_stack_size; + stream -> ux_device_class_audio_stream_feedback_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (stream -> ux_device_class_audio_stream_feedback_thread_stack == UX_NULL) + { + status = UX_MEMORY_INSUFFICIENT; + break; + } + + /* Create streaming thread. */ + status = _ux_utility_thread_create(&stream -> ux_device_class_audio_stream_feedback_thread , "ux_device_class_audio_stream_feedback_thread", + stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_entry, + (ULONG)(ALIGN_TYPE)stream, (VOID *) stream -> ux_device_class_audio_stream_feedback_thread_stack, + memory_size, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); + + /* Check for successful allocation. */ + if (status != UX_SUCCESS) + break; + + UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_feedback_thread), stream) + } +#endif + /* Save callbacks. */ _ux_utility_memory_copy(&stream -> ux_device_class_audio_stream_callbacks, &stream_parameter -> ux_device_class_audio_stream_parameter_callbacks, @@ -230,8 +269,14 @@ ULONG i; stream = audio -> ux_device_class_audio_streams; for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) { +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + if (stream -> ux_device_class_audio_stream_feedback_thread.tx_thread_id) + _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_feedback_thread); + if (stream -> ux_device_class_audio_stream_feedback_thread_stack) + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack); +#endif if (stream -> ux_device_class_audio_stream_thread.tx_thread_id) - _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_thread); + _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_thread); if (stream -> ux_device_class_audio_stream_thread_stack) _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); if (stream -> ux_device_class_audio_stream_buffer) 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 72702856..60460511 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.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +43,8 @@ /* */ /* This function is thread of ISO OUT from the Audio class. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* audio_stream Address of audio stream */ @@ -55,7 +57,7 @@ /* CALLS */ /* */ /* _ux_system_error_handler System error trap */ -/* _ux_utility_thread_suspend Suspend thread used */ +/* _ux_device_thread_suspend Suspend thread used */ /* _ux_device_stack_transfer_request Issue transfer request */ /* _ux_utility_memory_copy Copy data */ /* */ @@ -76,6 +78,9 @@ /* replaced wMaxPacketSize by */ /* calculated payload size, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream) @@ -166,7 +171,7 @@ ULONG actual_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_thread); + _ux_device_thread_suspend(&stream -> ux_device_class_audio_stream_thread); } } 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 6be79e5a..120eb1ea 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,7 +54,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_resume Resume thread used */ +/* _ux_device_thread_resume Resume thread used */ /* */ /* CALLED BY */ /* */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -101,6 +104,6 @@ UX_SLAVE_DEVICE *device; return(UX_BUFFER_OVERFLOW); /* Start read thread. */ - _ux_utility_thread_resume(&stream -> ux_device_class_audio_stream_thread); + _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_speed_get.c b/common/usbx_device_classes/src/ux_device_class_audio_speed_get.c new file mode 100644 index 00000000..13c8f250 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_speed_get.c @@ -0,0 +1,73 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_speed_get PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtain transfer speed from the Audio stream. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* Device Working Speed */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +ULONG _ux_device_class_audio_speed_get(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + UX_PARAMETER_NOT_USED(stream); + return(_ux_system_slave -> ux_system_slave_speed); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c b/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c index 06bf94f4..1abb5afc 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_stream_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,6 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_delete Delete thread used */ -/* _ux_utility_memory_free Free used local memory */ /* */ /* CALLED BY */ /* */ @@ -71,6 +69,8 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_stream_get(UX_DEVICE_CLASS_AUDIO *audio, 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 7b52f6bf..050390c9 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,7 +54,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_resume Resume thread used */ +/* _ux_device_thread_resume Resume thread used */ /* */ /* CALLED BY */ /* */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_transmission_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -101,6 +104,6 @@ UX_SLAVE_DEVICE *device; return(UX_BUFFER_OVERFLOW); /* Start write thread. */ - _ux_utility_thread_resume(&stream -> ux_device_class_audio_stream_thread); + _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c b/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c index 1cac54ea..c9df828a 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_uninitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -53,7 +53,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_delete Delete thread used */ +/* _ux_device_thread_delete Delete thread used */ /* _ux_utility_memory_free Free used local memory */ /* */ /* CALLED BY */ @@ -67,6 +67,11 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added feedback support, */ +/* fixed stream uninitialize, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -92,9 +97,19 @@ ULONG i; stream = (UX_DEVICE_CLASS_AUDIO_STREAM *)((UCHAR *)audio + sizeof(UX_DEVICE_CLASS_AUDIO)); for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) { - _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_thread); + _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_thread); +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + if (stream -> ux_device_class_audio_stream_feedback_thread_stack) + { + _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_feedback_thread); + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack); + } +#endif _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer); + + /* Next stream instance. */ + stream++; } /* Free the audio instance with controls and streams. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c index 655bd616..90ff1ff0 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_write_frame_commit PORTABLE C */ -/* 6.1 */ +/* 6.X */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed frame length check, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM *stream, ULONG length) @@ -108,7 +111,7 @@ UCHAR *next_pos; return(UX_BUFFER_OVERFLOW); /* Check frame length. */ - if (stream -> ux_device_class_audio_stream_frame_buffer_size < length) + if ((stream -> ux_device_class_audio_stream_frame_buffer_size - 8) < length) return(UX_ERROR); /* Calculate next frame buffer. */ 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 7b204d6a..f6c1cf0e 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,7 +55,7 @@ /* CALLS */ /* */ /* _ux_system_error_handler System error trap */ -/* _ux_utility_thread_suspend Suspend thread used */ +/* _ux_device_thread_suspend Suspend thread used */ /* _ux_device_stack_transfer_request Issue transfer request */ /* _ux_utility_memory_copy Copy data */ /* */ @@ -72,6 +72,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream) @@ -170,7 +173,7 @@ ULONG actual_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_thread); + _ux_device_thread_suspend(&stream -> ux_device_class_audio_stream_thread); } } diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c index 4583a205..0f27eed9 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c @@ -29,13 +29,13 @@ #include "ux_device_stack.h" -#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +#if !defined(UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE) && !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_bulkin_thread PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,8 @@ /* IN endpoint is used when the device wants to write data to be sent */ /* to the host. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* cdc_acm_class Address of cdc_acm class */ @@ -78,6 +80,9 @@ /* added macro to disable */ /* transmission support, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_acm_bulkin_thread(ULONG cdc_acm_class) @@ -216,7 +221,7 @@ ULONG sent_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(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); } } #endif diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c index 301f368a..d904a7b6 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c @@ -29,13 +29,13 @@ #include "ux_device_stack.h" -#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +#if !defined(UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE) && !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_bulkout_thread PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,8 @@ /* is waiting for the host to send data on the bulk out endpoint to */ /* the device. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* cdc_acm_class Address of cdc_acm class */ @@ -74,6 +76,9 @@ /* added macro to disable */ /* transmission support, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG cdc_acm_class) @@ -151,7 +156,7 @@ UINT status; } /* We need to suspend ourselves. We will be resumed by the application if needed. */ - _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + _ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); } } #endif diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c index 1612759b..a2bd1098 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_initialize PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* moved transmission resource */ /* allocate to here (init), */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -86,7 +89,9 @@ UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command) UX_SLAVE_CLASS_CDC_ACM *cdc_acm; UX_SLAVE_CLASS_CDC_ACM_PARAMETER *cdc_acm_parameter; UX_SLAVE_CLASS *class; +#if !defined(UX_DEVICE_STANDALONE) UINT status; +#endif /* Get the class container. */ class = command -> ux_slave_class_command_class_ptr; @@ -109,6 +114,8 @@ UINT status; cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_deactivate; cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change = cdc_acm_parameter -> ux_slave_class_cdc_acm_parameter_change; +#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(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex, "ux_slave_class_cdc_acm_in_mutex"); @@ -140,6 +147,8 @@ UINT status; return(UX_MUTEX_ERROR); } +#endif + /* Update the line coding fields with default values. */ cdc_acm -> ux_slave_class_cdc_acm_baudrate = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE; cdc_acm -> ux_slave_class_cdc_acm_stop_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT; @@ -148,6 +157,12 @@ UINT status; #ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +#if defined(UX_DEVICE_STANDALONE) + + /* Set task function. */ + class -> ux_slave_class_task_function = _ux_device_class_cdc_acm_tasks_run; +#else + /* We need to prepare the 2 threads for sending and receiving. */ /* Allocate some memory for the bulk out and in thread stack. */ cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack = @@ -252,6 +267,7 @@ UINT status; return(status); } +#endif #endif /* Return completion status. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c index 3e447340..4ac932cc 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_ioctl PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,8 +59,8 @@ /* _ux_utility_memory_free Free memory */ /* _ux_utility_event_flags_create Create event flags */ /* _ux_utility_event_flags_delete Delete event flags */ -/* _ux_utility_thread_create Create thread */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_create Create thread */ +/* _ux_device_thread_delete Delete thread */ /* */ /* CALLED BY */ /* */ @@ -88,6 +88,10 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed compile issue, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* fixed aborting return code, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_ioctl(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, @@ -205,15 +209,25 @@ UX_SLAVE_TRANSFER *transfer_request; /* Get the transfer request associated with the endpoint. */ transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; +#if defined(UX_DEVICE_STANDALONE) + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + if ((ULONG) (ALIGN_TYPE) parameter == UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT) + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + else + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; +#else + /* Check the status of the transfer. */ if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) { /* Abort the transfer. */ - _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - - } + _ux_device_stack_transfer_abort(transfer_request, UX_ABORTED); + } +#endif break; case UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_READ_TIMEOUT: @@ -262,9 +276,12 @@ UX_SLAVE_TRANSFER *transfer_request; /* Save the callback function for read. */ cdc_acm -> ux_device_class_cdc_acm_read_callback = callback -> ux_device_class_cdc_acm_parameter_read_callback; +#if !defined(UX_DEVICE_STANDALONE) + /* Start transmission threads. */ _ux_utility_thread_resume(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); _ux_utility_thread_resume(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); +#endif /* Declare the transmission with callback on. */ cdc_acm -> ux_slave_class_cdc_acm_transmission_status = UX_TRUE; @@ -284,24 +301,27 @@ UX_SLAVE_TRANSFER *transfer_request; /* Locate the endpoints. */ endpoint = interface -> ux_slave_interface_first_endpoint; - /* Get the transfer request associated with the endpoint. */ - transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; - - /* Abort the transfer. */ - _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_ABORTED); /* Next endpoint. */ endpoint = endpoint -> ux_slave_endpoint_next_endpoint; - /* Get the transfer request associated with the endpoint. */ - transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; - - /* Abort the transfer. */ - _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_ABORTED); + +#if !defined(UX_DEVICE_STANDALONE) + /* Suspend threads. */ - _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); - _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + _ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); +#endif /* Clear scheduled write flag. */ cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c index 7efb7496..65050d5a 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c @@ -29,12 +29,13 @@ #include "ux_device_stack.h" +#if !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_read PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +44,8 @@ /* */ /* This function reads from the CDC class. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* cdc_acm Address of cdc_acm class */ @@ -79,6 +82,8 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed compile issue, */ /* resulting in version 6.1.9 */ +/* 01-31-2022x Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, @@ -227,4 +232,4 @@ ULONG local_requested_length; /* Simply return the last transaction result. */ return(status); } - +#endif 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 new file mode 100644 index 00000000..4086b03c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c @@ -0,0 +1,256 @@ +/**************************************************************************/ +/* */ +/* 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 CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_read_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the CDC class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm 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 Run Transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, + UCHAR *buffer, ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *class_interface; +UX_SLAVE_TRANSFER *transfer_request; +ULONG max_transfer_length; +UINT status = UX_SUCCESS; + + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + + /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + + /* Not allowed. */ + return(UX_ERROR); +#endif + + /* 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. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* This is the first time we are activated. We need the interface to the class. */ + class_interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = class_interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if OUT we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + { + + /* So the next endpoint has to be the OUT endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* All CDC reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(cdc_acm -> ux_device_class_cdc_acm_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_CDC_ACM_READ, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_DEVICE_CLASS_CDC_ACM_READ_START; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_TRANSFER_NO_ANSWER; + cdc_acm -> ux_device_class_cdc_acm_read_buffer = buffer; + cdc_acm -> ux_device_class_cdc_acm_read_requested_length = requested_length; + cdc_acm -> ux_device_class_cdc_acm_read_actual_length = 0; + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_READ_START: + + /* Get remaining transfer length. */ + requested_length = cdc_acm -> ux_device_class_cdc_acm_read_requested_length - + cdc_acm -> ux_device_class_cdc_acm_read_actual_length; + + /* There is nothing remaining, it's done. */ + if (requested_length == 0) + { + *actual_length = cdc_acm -> ux_device_class_cdc_acm_read_actual_length; + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_SUCCESS; + return(UX_STATE_NEXT); + } + + /* Check if we have enough in the local buffer. */ + /* Use wMaxPacketSize for faster action, UX_SLAVE_REQUEST_DATA_MAX_LENGTH for better performance. */ + max_transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + if (requested_length > max_transfer_length) + { + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length = max_transfer_length; + } + else + { + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length = requested_length; + } + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_DEVICE_CLASS_CDC_ACM_READ_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_READ_WAIT: + + /* Run the transfer state machine. */ + status = _ux_device_stack_transfer_run(transfer_request, + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length, + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + 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); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(cdc_acm -> ux_device_class_cdc_acm_read_buffer, + transfer_request -> ux_slave_transfer_request_data_pointer, + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length); /* Use case of memcpy is verified. */ + + /* Next buffer address. */ + cdc_acm -> ux_device_class_cdc_acm_read_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + cdc_acm -> ux_device_class_cdc_acm_read_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + cdc_acm -> ux_device_class_cdc_acm_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual length. */ + *actual_length = cdc_acm -> ux_device_class_cdc_acm_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. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_DEVICE_CLASS_CDC_ACM_READ_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_INVALID_STATE; + break; + } + + /* Error cases. */ + return(UX_STATE_EXIT); +} +#endif 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 new file mode 100644 index 00000000..0c156de5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c @@ -0,0 +1,357 @@ +/**************************************************************************/ +/* */ +/* 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 CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + +#if defined(UX_DEVICE_STANDALONE) + +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); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs tasks of the CDC ACM class. */ +/* E.g., Transmission state machine. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Address of CDC ACM instance */ +/* */ +/* OUTPUT */ +/* */ +/* UX_STATE_RESET Tasks suspended */ +/* UX_STATE_IDLE Activated but no task ran */ +/* (others > UX_STATE_IDLE) Tasks running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +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; + + + /* 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); + + /* Check if device state is good. */ + device = &_ux_system_slave -> ux_system_slave_device; + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + cdc_acm -> ux_slave_class_cdc_acm_transmission_status = UX_FALSE; + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + 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(status); + } + + /* Run state machine for read. */ + _ux_device_class_cdc_acm_transmission_read_run(cdc_acm); + + /* Run state machine for write. */ + _ux_device_class_cdc_acm_transmission_write_run(cdc_acm); + + /* There must be something running. */ + status = UX_STATE_WAIT; +#endif + + return(status); +} + +#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) +{ + +UINT status; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +ULONG max_transfer_length; + + + /* Get the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if OUT we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + { + + /* So the next endpoint has to be the OUT endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* All CDC reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(cdc_acm -> ux_device_class_cdc_acm_read_state) + { + case UX_STATE_RESET: + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_DEVICE_CLASS_CDC_ACM_READ_WAIT; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_TRANSFER_NO_ANSWER; + + /* Use wMaxPacketSize for faster action, UX_SLAVE_REQUEST_DATA_MAX_LENGTH for better performance. */ + max_transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length = max_transfer_length; + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_DEVICE_CLASS_CDC_ACM_READ_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_READ_WAIT: + + /* Run the transfer state machine. */ + status = _ux_device_stack_transfer_run(transfer_request, + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length, + cdc_acm -> ux_device_class_cdc_acm_read_transfer_length); + + /* Error case. */ + if (status <= UX_STATE_NEXT) + { + + /* Do it again. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + + /* Last transfer status. */ + cdc_acm -> ux_device_class_cdc_acm_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + if (cdc_acm -> ux_device_class_cdc_acm_read_callback) + { + cdc_acm -> ux_device_class_cdc_acm_read_callback(cdc_acm, + transfer_request -> ux_slave_transfer_request_completion_code, + transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length); + } + return; + } + + /* Keep waiting. */ + return; + + default: /* Error. */ + cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_read_status = UX_INVALID_STATE; + break; + } +} +static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm) +{ + +UINT status; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +UINT zlp = UX_FALSE; +ULONG requested_length; + + + /* If write not started, return. */ + if (!cdc_acm -> ux_slave_class_cdc_acm_scheduled_write) + return; + + /* We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* So the next endpoint has to be the IN endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(cdc_acm -> ux_device_class_cdc_acm_write_state) + { + case UX_STATE_RESET: + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_START; + cdc_acm -> ux_device_class_cdc_acm_write_status = UX_TRANSFER_NO_ANSWER; + cdc_acm -> ux_device_class_cdc_acm_write_actual_length = 0; + if (cdc_acm -> ux_device_class_cdc_acm_write_requested_length == 0) + zlp = UX_TRUE; + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_WRITE_START: + + /* Get remaining requested length. */ + requested_length = cdc_acm -> ux_device_class_cdc_acm_write_requested_length - + cdc_acm -> ux_device_class_cdc_acm_write_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0 && !zlp) + { + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_write_status = UX_SUCCESS; + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; + if (cdc_acm -> ux_device_class_cdc_acm_write_callback) + { + cdc_acm -> ux_device_class_cdc_acm_write_callback(cdc_acm, + UX_SUCCESS, 0); + } + return; + } + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length = + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length = requested_length; + + /* 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, + cdc_acm -> ux_device_class_cdc_acm_write_buffer, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length); /* Use case of memcpy is verified. */ + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_WRITE_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + 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; + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; + if (cdc_acm -> ux_device_class_cdc_acm_write_callback) + { + cdc_acm -> ux_device_class_cdc_acm_write_callback(cdc_acm, + cdc_acm -> ux_device_class_cdc_acm_write_status, + cdc_acm -> ux_device_class_cdc_acm_write_actual_length); + } + return; + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next buffer address. */ + cdc_acm -> ux_device_class_cdc_acm_write_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + cdc_acm -> ux_device_class_cdc_acm_write_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + cdc_acm -> ux_device_class_cdc_acm_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Check ZLP case. */ + if (cdc_acm -> ux_device_class_cdc_acm_write_requested_length == 0) + { + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; + if (cdc_acm -> ux_device_class_cdc_acm_write_callback) + { + cdc_acm -> ux_device_class_cdc_acm_write_callback(cdc_acm, + cdc_acm -> ux_device_class_cdc_acm_write_status, + cdc_acm -> ux_device_class_cdc_acm_write_actual_length); + } + return; + } + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_START; + } + + /* Keep waiting. */ + return; + + default: /* Error. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + break; + } +} + +#endif /* !defined(UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE) */ + +#endif /* defined(UX_DEVICE_STANDALONE) */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c index 3df8ba98..5b83da62 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_uninitialize PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* moved transmission resource */ /* free to here (uninit), */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -91,6 +94,8 @@ UX_SLAVE_CLASS *class; if (cdc_acm != UX_NULL) { +#if !defined(UX_DEVICE_STANDALONE) + /* Delete the IN endpoint mutex. */ _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); @@ -104,6 +109,7 @@ UX_SLAVE_CLASS *class; _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack); +#endif #endif /* Free the resources. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c index a14927c7..996b2665 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c @@ -29,12 +29,13 @@ #include "ux_device_stack.h" +#if !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_write PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +44,8 @@ /* */ /* This function writes to the CDC class. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* cdc_acm Address of cdc_acm class */ @@ -79,6 +82,8 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed compile issue, */ /* resulting in version 6.1.9 */ +/* 01-31-2022x Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_write(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, @@ -96,6 +101,7 @@ UINT status = 0; UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_WRITE, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) #ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on. */ if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) @@ -233,4 +239,4 @@ UINT status = 0; return(status); } - +#endif 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 new file mode 100644 index 00000000..30baac5b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* */ +/* 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 CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_write_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the CDC class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write */ +/* 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_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, + UCHAR *buffer, ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +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_CDC_ACM_WRITE, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE + + /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + + /* Not allowed. */ + return(UX_ERROR); +#endif + + /* 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. */ + 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); + } + + /* We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* So the next endpoint has to be the IN endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(cdc_acm -> ux_device_class_cdc_acm_write_state) + { + case UX_STATE_RESET: + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_START; + cdc_acm -> ux_device_class_cdc_acm_write_status = UX_TRANSFER_NO_ANSWER; + cdc_acm -> ux_device_class_cdc_acm_write_buffer = buffer; + cdc_acm -> ux_device_class_cdc_acm_write_requested_length = requested_length; + cdc_acm -> ux_device_class_cdc_acm_write_actual_length = 0; + if (requested_length == 0) + zlp = UX_TRUE; + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_WRITE_START: + + /* Get remaining requested length. */ + requested_length = cdc_acm -> ux_device_class_cdc_acm_write_requested_length - + cdc_acm -> ux_device_class_cdc_acm_write_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0 && !zlp) + { + *actual_length = cdc_acm -> ux_device_class_cdc_acm_write_actual_length; + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + cdc_acm -> ux_device_class_cdc_acm_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. */ + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length = + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length = requested_length; + + /* 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, + cdc_acm -> ux_device_class_cdc_acm_write_buffer, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length); /* Use case of memcpy is verified. */ + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_CDC_ACM_WRITE_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length, + cdc_acm -> ux_device_class_cdc_acm_write_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + 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); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next buffer address. */ + cdc_acm -> ux_device_class_cdc_acm_write_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + cdc_acm -> ux_device_class_cdc_acm_write_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + cdc_acm -> ux_device_class_cdc_acm_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual done length. */ + *actual_length = cdc_acm -> ux_device_class_cdc_acm_write_actual_length; + + /* Check ZLP case. */ + if (cdc_acm -> ux_device_class_cdc_acm_write_requested_length == 0) + { + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_DEVICE_CLASS_CDC_ACM_WRITE_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c index 1915a6ac..1d00fdbe 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_write_with_callback PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* added macro to disable */ /* transmission support, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, @@ -127,6 +130,21 @@ UINT status; return(UX_ERROR); } +#if defined(UX_DEVICE_STANDALONE) + + /* Save the length to be sent. */ + cdc_acm -> ux_device_class_cdc_acm_write_requested_length = requested_length; + + /* And the buffer pointer. */ + cdc_acm -> ux_device_class_cdc_acm_write_buffer = buffer; + + /* Schedule a transmission. */ + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_TRUE; + + /* Status success. */ + status = (UX_SUCCESS); +#else + /* Save the length to be sent. */ cdc_acm -> ux_slave_class_cdc_acm_callback_total_length = requested_length; @@ -138,6 +156,7 @@ UINT status; /* Invoke the bulkin thread by sending a flag . */ status = _ux_utility_event_flags_set(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, UX_DEVICE_CLASS_CDC_ACM_WRITE_EVENT, UX_OR); +#endif /* Simply return the last function result. When we leave this function, the deferred writing has been scheduled. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c index 343818b1..5ed7d814 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_activate PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* 08-02-2021 Wen Wang Modified comment(s), */ /* fixed spelling error, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -126,7 +129,7 @@ ULONG physical_address_lsw; ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */ /* Resume the interrupt endpoint threads. */ - _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); } @@ -210,8 +213,8 @@ ULONG physical_address_lsw; ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */ /* Resume the endpoint threads. */ - _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); - _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); } 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 107ad534..9c8d39c6 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 @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkin_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkin_thread(ULONG cdc_ecm_class) @@ -230,6 +233,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(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + _ux_device_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); } } 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 3a70402c..40ee6e72 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 @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkout_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,7 +59,7 @@ /* _ux_utility_memory_copy Copy memory */ /* nx_packet_allocate Allocate NetX packet */ /* nx_packet_release Free NetX packet */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -75,6 +75,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class) @@ -177,7 +180,7 @@ ULONG ip_given_length; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_device_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); } } diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c index a8f59bb0..e895e747 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_change PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,7 +55,7 @@ /* _ux_network_driver_link_up Link status up */ /* _ux_network_driver_link_down Link status down */ /* _ux_utility_memory_set Set memory */ -/* _ux_utility_thread_resume Resume thread */ +/* _ux_device_thread_resume Resume thread */ /* _ux_utility_event_flags_set Set event flags */ /* _ux_device_stack_transfer_all_request_abort */ /* Abort transfer */ @@ -75,6 +75,9 @@ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND *command) @@ -150,8 +153,8 @@ UX_SLAVE_ENDPOINT *endpoint; ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */ /* Resume the endpoint threads. */ - _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); - _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); /* Wake up the Interrupt thread and send a network notification to the host. */ _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, UX_OR); 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 af9ed7d5..94408cda 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 @@ -34,7 +34,7 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,8 +59,8 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* _ux_utility_mutex_delete Delete Mutex */ /* _ux_utility_event_flags_create Create Flag group */ /* _ux_utility_event_flags_delete Delete Flag group */ -/* _ux_utility_thread_create Create Thread */ -/* _ux_utility_thread_delete Delete Thread */ +/* _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 */ /* */ @@ -79,6 +79,9 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -166,7 +169,7 @@ UINT status; does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread , "ux_slave_class_cdc_ecm_interrupt_thread", + status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread , "ux_slave_class_cdc_ecm_interrupt_thread", _ux_device_class_cdc_ecm_interrupt_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -184,7 +187,7 @@ UINT status; /* Bulk 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. */ - status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread , "ux_slave_class_cdc_ecm_bulkout_thread", + status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread , "ux_slave_class_cdc_ecm_bulkout_thread", _ux_device_class_cdc_ecm_bulkout_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -199,7 +202,7 @@ UINT status; /* Bulk 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. */ - status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread , "ux_slave_class_cdc_ecm_bulkin_thread", + status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread , "ux_slave_class_cdc_ecm_bulkin_thread", _ux_device_class_cdc_ecm_bulkin_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -242,13 +245,13 @@ UINT status; return(UX_SUCCESS); } - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); } - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); } - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); } /* Free allocated resources. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c index 2d804921..bc0bc26c 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_interrupt_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,7 +57,7 @@ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_utility_event_flags_get Get event flags */ /* _ux_utility_short_put Put 16-bit value to buffer */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_interrupt_thread(ULONG cdc_ecm_class) @@ -151,7 +154,7 @@ UCHAR *notification_buffer; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + _ux_device_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); } } 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 a7e8b456..857dc637 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,10 +56,10 @@ /* CALLS */ /* */ /* _ux_utility_mutex_delete Delete mutex */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_delete Delete thread */ /* _ux_utility_memory_free Free memory */ /* _ux_utility_event_flags_delete Delete event flags */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_device_semaphore_delete Delete semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -99,19 +102,19 @@ UX_SLAVE_CLASS *class; _ux_utility_mutex_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); /* Delete bulk out thread . */ - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); /* Free bulk out thread stack. */ _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack); /* Delete interrupt thread. */ - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); /* Free interrupt thread stack. */ _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack); /* Delete bulk in thread. */ - _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); /* Free bulk in thread stack. */ _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack); diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_activate.c b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c index db088755..efe5bab9 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_activate PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,7 +58,6 @@ /* CALLS */ /* */ /* _ux_utility_memory_allocate Allocate memory */ -/* _ux_utility_thread_resume Resume thread */ /* */ /* CALLED BY */ /* */ @@ -75,6 +74,8 @@ /* removed block count (it's */ /* from host request wValue), */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command) diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c index 3daa42c8..2b1cab23 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c @@ -40,7 +40,7 @@ static inline VOID _ux_device_class_dfu_status_get(UX_SLAVE_CLASS_DFU *, /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_control_request PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,10 @@ static inline VOID _ux_device_class_dfu_status_get(UX_SLAVE_CLASS_DFU *, /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed compile warning, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added UPLOAD length check, */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_control_request(UX_SLAVE_CLASS_COMMAND *command) @@ -162,15 +166,13 @@ ULONG media_status; { /* Wake up the DFU thread and send a detach request.. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); - + _ux_device_class_dfu_event_flags_set(dfu, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT); } else { /* We expect the host to issue a reset. Arm a timer in the DFU thread. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET, UX_OR); - + _ux_device_class_dfu_event_flags_set(dfu, UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET); } /* We can switch dfu state machine. */ @@ -375,9 +377,10 @@ ULONG media_status; #ifndef UX_DEVICE_CLASS_DFU_UPLOAD_DISABLE case UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD: - /* bitCanUpload != 1, or length = 0. */ + /* bitCanUpload != 1, or length = 0, or length > wTransferSize (we can support max of control buffer size). */ if (!(_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD) || - request_length == 0) + (request_length == 0) || + (request_length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)) { _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); @@ -624,9 +627,7 @@ ULONG media_status; { /* Wake up the DFU thread and send a detach request.. */ - _ux_utility_event_flags_set( - &dfu -> ux_slave_class_dfu_event_flags_group, - UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); + _ux_device_class_dfu_event_flags_set(dfu, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT); } #else @@ -648,7 +649,7 @@ ULONG media_status; { /* Wake up the DFU thread and send a detach request.. */ - _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, UX_OR); + _ux_device_class_dfu_event_flags_set(dfu, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT); } diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c index a7571e0b..52b33763 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_initialize PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,7 +57,7 @@ /* _ux_utility_descriptor_parse Parse a descriptor */ /* _ux_utility_event_flags_create Create event flags */ /* _ux_utility_event_flags_delete Delete event flags */ -/* _ux_utility_thread_create Create thread */ +/* _ux_device_thread_create Create thread */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* fixed max transfer size, */ /* added max size limit check, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -183,6 +186,8 @@ ULONG descriptor_length; } +#if !defined(UX_DEVICE_STANDALONE) + /* Create a event flag group for the dfu class to synchronize with the event interrupt thread. */ status = _ux_utility_event_flags_create(&dfu -> ux_slave_class_dfu_event_flags_group, "ux_device_class_dfu_event_flag"); @@ -204,7 +209,7 @@ ULONG descriptor_length; /* dfu needs a thread to watch for disconnect and timer event for the DFU_DETACH sequence. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&dfu -> ux_slave_class_dfu_thread , "ux_slave_class_dfu_thread", + status = _ux_device_thread_create(&dfu -> ux_slave_class_dfu_thread , "ux_slave_class_dfu_thread", _ux_device_class_dfu_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) dfu -> ux_slave_class_dfu_thread_stack, UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -216,18 +221,26 @@ ULONG descriptor_length; } UX_THREAD_EXTENSION_PTR_SET(&(dfu -> ux_slave_class_dfu_thread), class) +#else + + /* Set task function. */ + class -> ux_slave_class_task_function = _ux_device_class_dfu_tasks_run; +#endif /* Return completion status. */ if (status == UX_SUCCESS) return(UX_SUCCESS); /* There is error, free resources. */ - /* The last resource, thread is not created or created error, no need to free. */ +#if !defined(UX_DEVICE_STANDALONE) + + /* The last resource, thread is not created or created error, no need to free. */ if (dfu -> ux_slave_class_dfu_thread_stack) _ux_utility_memory_free(dfu -> ux_slave_class_dfu_thread_stack); if (dfu -> ux_slave_class_dfu_event_flags_group.tx_event_flags_group_id != 0) _ux_utility_event_flags_delete(&dfu -> ux_slave_class_dfu_event_flags_group); +#endif /* Detach from container and free instance memory. */ class -> ux_slave_class_instance = UX_NULL; diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_dfu_tasks_run.c new file mode 100644 index 00000000..5d06156d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_tasks_run.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device dfu Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the dfu class. It waits for */ +/* the dfu command to signal a DFU_DETACH stage and either force a */ +/* disconnect from the device or wait for the host to detach. */ +/* */ +/* INPUT */ +/* */ +/* class_instance DFU class instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Delay for some time */ +/* */ +/* CALLED BY */ +/* */ +/* USBX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_tasks_run(VOID *class_instance) +{ + +UX_SLAVE_CLASS_DFU *dfu; +UX_SLAVE_DCD *dcd; +ULONG actual_flags; + + /* Get the dfu instance from this class container. */ + dfu = (UX_SLAVE_CLASS_DFU *) class_instance; + + /* Process when there is flags. */ + if (dfu -> ux_device_class_dfu_flags == 0) + return(UX_STATE_IDLE); + actual_flags = dfu -> ux_device_class_dfu_flags; + + /* Check the source of event. */ + if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT) + { + dfu -> ux_device_class_dfu_flags &= ~UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT; + + /* We need to disconnect. The control command for DETACH is still being processed, wait 2-3 ms. */ + _ux_utility_delay_ms(2); + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Issue a Soft Disconnect. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_FORCE_DISCONNECT); + + } + + /* Check the source of event. */ + if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET) + { + dfu -> ux_device_class_dfu_flags &= ~UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET; + + /* We need to wait for reset. Arm a timer. The timeout value is indicated in ms from + the device framework. */ + _ux_utility_delay_ms(_ux_system_slave -> ux_system_slave_device_dfu_detach_timeout); + + /* Check the mode. */ + if (_ux_system_slave -> ux_system_slave_device_dfu_mode == UX_DEVICE_CLASS_DFU_MODE_RUNTIME) + + /* We are still in RunTime mode. The host never reset. Revert to AppIdle state. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE; + + } + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_thread.c b/common/usbx_device_classes/src/ux_device_class_dfu_thread.c index f18b524d..69bb2cbd 100644 --- a/common/usbx_device_classes/src/ux_device_class_dfu_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_dfu_thread.c @@ -28,12 +28,14 @@ #include "ux_device_class_dfu.h" #include "ux_device_stack.h" + +#if !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_dfu_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +45,8 @@ /* This function is the thread of the dfu class. It waits for the */ /* dfu command to signal a DFU_DETACH stage and either force a */ /* disconnect from the device or wait for the host to detach. */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -72,6 +76,8 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_dfu_thread(ULONG dfu_class) @@ -136,4 +142,4 @@ ULONG actual_flags; } } } - +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_activate.c b/common/usbx_device_classes/src/ux_device_class_hid_activate.c index c4682930..29317a13 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_activate.c @@ -10,8 +10,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device HID Class */ /** */ @@ -28,40 +28,40 @@ #include "ux_device_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_hid_activate PORTABLE C */ -/* 6.1.9 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_activate PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function activates an instance of a HID device. */ -/* */ -/* INPUT */ -/* */ -/* command Pointer to hid command */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_utility_thread_resume Resume thread */ -/* */ -/* CALLED BY */ -/* */ -/* USBX Source Code */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* This function activates an instance of a HID device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to hid command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ @@ -72,44 +72,70 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* added packet size assert, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added interrupt OUT support,*/ +/* added packet size assert, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_activate(UX_SLAVE_CLASS_COMMAND *command) { - + UX_SLAVE_INTERFACE *interface; UX_SLAVE_CLASS_HID *hid; -UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS *class_inst; UX_SLAVE_ENDPOINT *endpoint_interrupt; +UX_SLAVE_ENDPOINT *endpoint_in = UX_NULL; +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) +UX_SLAVE_ENDPOINT *endpoint_out = UX_NULL; +#endif /* Get the class container. */ - class = command -> ux_slave_class_command_class_ptr; + class_inst = command -> ux_slave_class_command_class_ptr; /* Get the class instance in the container. */ - hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + hid = (UX_SLAVE_CLASS_HID *) class_inst -> ux_slave_class_instance; /* Get the interface that owns this instance. */ interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; - + /* Store the class instance into the interface. */ interface -> ux_slave_interface_class_instance = (VOID *)hid; - + /* Now the opposite, store the interface in the class instance. */ hid -> ux_slave_class_hid_interface = interface; - + /* Locate the endpoints. */ endpoint_interrupt = interface -> ux_slave_interface_first_endpoint; /* Check if interrupt IN endpoint exists. */ while (endpoint_interrupt != UX_NULL) { - - if ((endpoint_interrupt -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN && - (endpoint_interrupt -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT) + if ((endpoint_interrupt -> ux_slave_endpoint_descriptor.bmAttributes & + UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT) { - - /* It's right endpoint we need. */ - break; + if ((endpoint_interrupt -> ux_slave_endpoint_descriptor.bEndpointAddress & + UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* It's interrupt IN endpoint we need. */ + endpoint_in = endpoint_interrupt; +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + if (endpoint_out != UX_NULL) +#endif + break; + } +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + else + { + + /* It's optional interrupt OUT endpoint. */ + endpoint_out = endpoint_interrupt; + if (endpoint_in != UX_NULL) + break; + } +#endif } /* Try next endpoint. */ @@ -117,26 +143,67 @@ UX_SLAVE_ENDPOINT *endpoint_interrupt; } /* Check if we found right endpoint. */ - if (endpoint_interrupt == UX_NULL) + if (endpoint_in == UX_NULL) return (UX_ERROR); /* Validate event buffer size (fits largest transfer payload size). */ UX_ASSERT(UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH >= - endpoint_interrupt -> ux_slave_endpoint_transfer_request. + endpoint_in -> ux_slave_endpoint_transfer_request. ux_slave_transfer_request_transfer_length); /* Default HID protocol is report protocol. */ hid -> ux_device_class_hid_protocol = UX_DEVICE_CLASS_HID_PROTOCOL_REPORT; - /* Save the endpoint in the hid instance. */ - hid -> ux_device_class_hid_interrupt_endpoint = endpoint_interrupt; + /* Save the endpoints in the hid instance. */ + hid -> ux_device_class_hid_interrupt_endpoint = endpoint_in; + +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* Save endpoint OUT. */ + hid -> ux_device_class_hid_read_endpoint = endpoint_out; + + /* Resume receiver thread/task (if present). */ + if (hid -> ux_device_class_hid_receiver && endpoint_out) + { + + /* Reset events. */ + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_event_save_pos = + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_events; + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_event_read_pos = + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_events; + _ux_utility_memory_set( + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_events, 0x00, + (ALIGN_TYPE)hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_events_end - + (ALIGN_TYPE)hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_events); /* Use case of memset is verified. */ + +#if !defined(UX_DEVICE_STANDALONE) + + /* Resume thread. */ + _ux_utility_thread_resume(&hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_thread); +#endif + } +#endif + +#if !defined(UX_DEVICE_STANDALONE) /* Resume thread. */ - _ux_utility_thread_resume(&class -> ux_slave_class_thread); - + _ux_device_thread_resume(&class_inst -> ux_slave_class_thread); +#else + + /* Reset event buffered for background transfer. */ + _ux_utility_memory_set((VOID *)&hid -> ux_device_class_hid_event, 0, + sizeof(UX_SLAVE_CLASS_HID_EVENT)); /* Use case of memset is verified. */ + hid -> ux_device_class_hid_event.ux_device_class_hid_event_length = + endpoint_interrupt -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + /* Reset event sending state. */ + hid -> ux_device_class_hid_event_state = UX_STATE_RESET; +#endif + + /* If there is a activate function call it. */ if (hid -> ux_slave_class_hid_instance_activate != UX_NULL) - { + { /* Invoke the application. */ hid -> ux_slave_class_hid_instance_activate(hid); @@ -151,4 +218,3 @@ UX_SLAVE_ENDPOINT *endpoint_interrupt; /* Return completion status. */ return(UX_SUCCESS); } - 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 f5c9d10e..108556d8 100755 --- 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 @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_control_request PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* added Get/Set Protocol */ /* request support, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND *command) @@ -179,8 +182,16 @@ UX_SLAVE_CLASS_HID *hid; if (hid -> ux_device_class_hid_event_wait_timeout == 0) hid -> ux_device_class_hid_event_wait_timeout ++; +#if defined(UX_DEVICE_STANDALONE) + + /* Restart event checking if no transfer in progress. */ + if (hid -> ux_device_class_hid_event_state != UX_STATE_WAIT) + hid -> ux_device_class_hid_event_state = UX_STATE_RESET; +#else + /* Set an event to wake up the interrupt thread. */ _ux_utility_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_IDLE_RATE, UX_OR); +#endif } } } diff --git a/common/usbx_device_classes/src/ux_device_class_hid_event_set.c b/common/usbx_device_classes/src/ux_device_class_hid_event_set.c index 988a0742..24abfa99 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_event_set.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_event_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_event_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,11 +68,15 @@ /* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ /* verified memset and memcpy */ /* cases, used UX prefix to */ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid, @@ -153,9 +157,18 @@ UX_SLAVE_CLASS_HID_EVENT *next_hid_event; /* fill in the event structure from the user. */ current_hid_event -> ux_device_class_hid_event_length = hid_event -> ux_device_class_hid_event_length; } - + +#if defined(UX_DEVICE_STANDALONE) + + /* Set state machine to start sending if no transfer on going. */ + if (hid -> ux_device_class_hid_event_state != UX_STATE_WAIT && + hid -> ux_device_class_hid_event_state != UX_STATE_EXIT) + hid -> ux_device_class_hid_event_state = UX_STATE_RESET; +#else + /* Set an event to wake up the interrupt thread. */ - _ux_utility_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_EVENT, UX_OR); + _ux_device_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_EVENT, UX_OR); +#endif /* Return event status to the user. */ return(UX_SUCCESS); 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 72962777..fbb41a09 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,8 +56,8 @@ /* */ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_thread_create Create thread */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_create Create thread */ +/* _ux_device_thread_delete Delete thread */ /* _ux_utility_event_flags_create Create event flags group */ /* */ /* CALLED BY */ @@ -74,6 +74,10 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added interrupt OUT support,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -98,9 +102,11 @@ UINT status = UX_SUCCESS; /* Save the address of the HID instance inside the HID container. */ class -> ux_slave_class_instance = (VOID *) hid; +#if !defined(UX_DEVICE_STANDALONE) + /* Allocate some memory for the thread stack. */ class -> ux_slave_class_thread_stack = - _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_DEVICE_CLASS_HID_THREAD_STACK_SIZE); /* Check for successful allocation. */ if (class -> ux_slave_class_thread_stack == UX_NULL) @@ -110,17 +116,24 @@ UINT status = UX_SUCCESS; a new thread. We pass a pointer to the class to the new thread. This thread does not start until we have a instance of the class. */ if (status == UX_SUCCESS) - status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_hid_thread", + status = _ux_device_thread_create(&class -> ux_slave_class_thread, "ux_slave_hid_thread", _ux_device_class_hid_interrupt_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, - UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_DEVICE_CLASS_HID_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); +#else + + /* Set task function. */ + class -> ux_slave_class_task_function = _ux_device_class_hid_tasks_run; +#endif /* Check the creation of this thread. */ if (status == UX_SUCCESS) { +#if !defined(UX_DEVICE_STANDALONE) UX_THREAD_EXTENSION_PTR_SET(&(class -> ux_slave_class_thread), class) +#endif /* Get the pointer to the application parameters for the hid class. */ hid_parameter = command -> ux_slave_class_command_parameter; @@ -154,28 +167,85 @@ UINT status = UX_SUCCESS; /* By default no event wait timeout. */ hid -> ux_device_class_hid_event_wait_timeout = UX_WAIT_FOREVER; +#if defined(UX_DEVICE_STANDALONE) + + return(UX_SUCCESS); +#else + /* Create a event flag group for the hid class to synchronize with the event interrupt thread. */ status = _ux_utility_event_flags_create(&hid -> ux_device_class_hid_event_flags_group, "ux_device_class_hid_event_flag"); /* Check status. */ if (status == UX_SUCCESS) + { +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) + + /* Create a mutex for reading reentry check. */ + status = _ux_utility_mutex_create(&hid -> ux_device_class_hid_read_mutex, + "ux_device_class_hid_read_mutex"); + if (status == UX_SUCCESS) + { +#endif + + /* If receiver is enabled by parameter, initialize it. */ + if (hid_parameter -> ux_device_class_hid_parameter_receiver_initialize) + { + + /* Allocate buffer for receiver and receiver events. */ + status = hid_parameter -> + ux_device_class_hid_parameter_receiver_initialize(hid, + hid_parameter, + &hid -> ux_device_class_hid_receiver); + } + + /* Done success, return. */ + if (status == UX_SUCCESS) + return(status); + +#if !defined(UX_DEVICE_STANDALONE) + + /* There is error, delete mutex. */ + _ux_utility_mutex_delete(&hid -> ux_device_class_hid_read_mutex); + } + else + status = UX_MUTEX_ERROR; + + /* There is error, delete event flags. */ + _ux_utility_event_flags_delete(&hid -> ux_device_class_hid_event_flags_group); +#endif +#else return(status); +#endif - /* It's event error. */ - status = UX_EVENT_ERROR; + } + else + + /* It's event error. */ + status = UX_EVENT_ERROR; + + /* Free allocated event array memory. */ + _ux_utility_memory_free(hid -> ux_device_class_hid_event_array); +#endif } else status = UX_MEMORY_INSUFFICIENT; +#if !defined(UX_DEVICE_STANDALONE) + /* Delete thread. */ - _ux_utility_thread_delete(&class -> ux_slave_class_thread); + _ux_device_thread_delete(&class -> ux_slave_class_thread); +#endif } else status = (UX_THREAD_ERROR); +#if !defined(UX_DEVICE_STANDALONE) + /* Free stack. */ if (class -> ux_slave_class_thread_stack) _ux_utility_memory_free(class -> ux_slave_class_thread_stack); +#endif /* Unmount instance. */ class -> ux_slave_class_instance = UX_NULL; diff --git a/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c index 813c4afb..9d684546 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c @@ -29,19 +29,22 @@ #include "ux_device_stack.h" +#if !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_interrupt_thread PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function is the thread of the hid interrupt endpoint */ +/* This function is the thread of the hid interrupt (IN) endpoint */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -58,7 +61,7 @@ /* _ux_device_class_hid_event_get Get HID event */ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_utility_memory_copy Copy memory */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -77,7 +80,10 @@ /* resulting in version 6.1 */ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* improved idle generation, */ -/* resulting in version 6.1 */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* off for standalone compile, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_hid_interrupt_thread(ULONG hid_class) @@ -191,6 +197,7 @@ ULONG actual_flags; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + _ux_device_thread_suspend(&class -> ux_slave_class_thread); } } +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_read.c b/common/usbx_device_classes/src/ux_device_class_hid_read.c new file mode 100644 index 00000000..95026c9e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_read.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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +#if !defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_read PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the HID class. */ +/* This function must not be used with receiver related functions. */ +/* */ +/* INPUT */ +/* */ +/* hid Address of hid 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 */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_mutex_off Release mutex */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_read(UX_SLAVE_CLASS_HID *hid, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ +#if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_PARAMETER_NOT_USED(hid); + UX_PARAMETER_NOT_USED(buffer); + UX_PARAMETER_NOT_USED(requested_length); + UX_PARAMETER_NOT_USED(actual_length); + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status= UX_SUCCESS; +ULONG local_requested_length; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_READ, hid, 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. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Protect this thread. */ + _ux_utility_mutex_on(&hid -> ux_device_class_hid_read_mutex); + + /* Locate the endpoint. */ + endpoint = hid -> ux_device_class_hid_read_endpoint; + + /* All HID reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > transfer_request -> ux_slave_transfer_request_transfer_length) + + /* We have too much to transfer. */ + local_requested_length = transfer_request -> ux_slave_transfer_request_transfer_length; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(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. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + /* Is this a short packet or a ZLP indicating we are done with this transfer ? */ + if (transfer_request -> ux_slave_transfer_request_actual_length < endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + { + + /* We are done. */ + /* Free Mutex resource. */ + _ux_utility_mutex_off(&hid -> ux_device_class_hid_read_mutex); + + /* Return with success. */ + return(UX_SUCCESS); + } + } + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&hid -> ux_device_class_hid_read_mutex); + + /* We got an error. */ + return(status); + } + } + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&hid -> ux_device_class_hid_read_mutex); + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); +#endif +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_free.c b/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_free.c new file mode 100644 index 00000000..3965d7ef --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_free.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_receiver_event_free PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function free event buffer for new incoming interrupt OUT */ +/* and advance the current reading position. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer of the HID instance */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS if freed */ +/* UX_ERROR if nothing to free */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_receiver_event_free(UX_SLAVE_CLASS_HID *hid) +{ +#if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_PARAMETER_NOT_USED(hid); + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_DEVICE_CLASS_HID_RECEIVER *receiver; +UX_DEVICE_CLASS_HID_RECEIVED_EVENT *pos; +UCHAR *next_pos; + + /* Get receiver. */ + receiver = hid -> ux_device_class_hid_receiver; + + /* Get current event. */ + pos = receiver -> ux_device_class_hid_receiver_event_read_pos; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_RECEIVER_EVENT_FREE, hid, pos, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If event is not valid, return error. */ + if (pos -> ux_device_class_hid_received_event_length == 0) + return(UX_ERROR); + + /* Invalidate the event and advance position. */ + next_pos = (UCHAR *)pos + receiver -> ux_device_class_hid_receiver_event_buffer_size + sizeof(ULONG); + if (next_pos >= (UCHAR *)receiver -> ux_device_class_hid_receiver_events_end) + next_pos = (UCHAR *)receiver -> ux_device_class_hid_receiver_events; + receiver -> ux_device_class_hid_receiver_event_read_pos = (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)next_pos; + pos -> ux_device_class_hid_received_event_length = 0; + + /* Inform receiver thread to (re)start. */ + _ux_utility_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, + UX_DEVICE_CLASS_HID_RECEIVER_RESTART, UX_OR); + + /* Return event status to the user. */ + return(UX_SUCCESS); +#endif +} diff --git a/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_get.c b/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_get.c new file mode 100644 index 00000000..d701267a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_receiver_event_get.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_receiver_event_get PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if there was an event from the interrupt OUT, */ +/* if so return first received event length and it's buffer entry */ +/* pointer. */ +/* */ +/* INPUT */ +/* */ +/* hid Address of hid class */ +/* event Pointer of the event */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS with event */ +/* UX_ERROR without event */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_receiver_event_get(UX_SLAVE_CLASS_HID *hid, + UX_DEVICE_CLASS_HID_RECEIVED_EVENT *event) +{ +#if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_PARAMETER_NOT_USED(hid); + UX_PARAMETER_NOT_USED(event); + return(UX_FUNCTION_NOT_SUPPORTED); +#else + + +UX_DEVICE_CLASS_HID_RECEIVER *receiver; +UX_DEVICE_CLASS_HID_RECEIVED_EVENT *pos; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_RECEIVER_EVENT_GET, hid, event, wait_option, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get receiver. */ + receiver = hid -> ux_device_class_hid_receiver; + + /* Get current reading position. */ + pos = receiver -> ux_device_class_hid_receiver_event_read_pos; + + /* Check if it's available. */ + if (pos -> ux_device_class_hid_received_event_length != 0) + { + + /* Fill event structure to return. */ + event -> ux_device_class_hid_received_event_length = pos -> ux_device_class_hid_received_event_length; + event -> ux_device_class_hid_received_event_data = (UCHAR *)&pos -> ux_device_class_hid_received_event_data; + return(UX_SUCCESS); + } + + return(UX_ERROR); +#endif +} diff --git a/common/usbx_device_classes/src/ux_device_class_hid_receiver_initialize.c b/common/usbx_device_classes/src/ux_device_class_hid_receiver_initialize.c new file mode 100644 index 00000000..ef7bd6ec --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_receiver_initialize.c @@ -0,0 +1,180 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_receiver_initialize PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB HID device receiver. */ +/* This function is called by the class register function. It is only */ +/* done once. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to hid instance */ +/* parameter Pointer to hid parameter */ +/* receiver Pointer to fill pointer to */ +/* allocated receiver instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_receiver_initialize(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_PARAMETER *parameter, + UX_DEVICE_CLASS_HID_RECEIVER **receiver) +{ +#if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_PARAMETER_NOT_USED(hid); + UX_PARAMETER_NOT_USED(parameter); + UX_PARAMETER_NOT_USED(receiver); + return(UX_FUNCTION_NOT_SUPPORTED); +#else +ULONG memory_size; +ULONG events_size; +UCHAR *memory_receiver; +UCHAR *memory_events; +UCHAR *memory_stack; +UINT status = UX_SUCCESS; + + + /* Validate parameters. */ + UX_ASSERT(parameter -> ux_device_class_hid_parameter_receiver_event_max_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Allocate memory for receiver and receiver events. */ + + /* Memory of thread stack and receiver instance. */ +#if !defined(UX_DEVICE_STANDALONE) + UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE, sizeof(UX_DEVICE_CLASS_HID_RECEIVER))); + memory_size = UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE + + sizeof(UX_DEVICE_CLASS_HID_RECEIVER); +#else + memory_size = sizeof(UX_DEVICE_CLASS_HID_RECEIVER); +#endif + UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(parameter -> ux_device_class_hid_parameter_receiver_event_max_length, sizeof(ULONG))); + + /* Memory of events. */ + events_size = parameter -> ux_device_class_hid_parameter_receiver_event_max_length + sizeof(ULONG); + UX_ASSERT(!UX_OVERFLOW_CHECK_MULV_ULONG(events_size, parameter -> ux_device_class_hid_parameter_receiver_event_max_number)); + events_size *= parameter -> ux_device_class_hid_parameter_receiver_event_max_number; + UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(memory_size, events_size)); + memory_size += events_size; + + /* Allocate memory. */ + memory_receiver = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + if (memory_receiver == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + memory_stack = memory_receiver + sizeof(UX_DEVICE_CLASS_HID_RECEIVER); + memory_events = memory_stack + UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE; + + /* Store receiver instance pointer. */ + (*receiver) = (UX_DEVICE_CLASS_HID_RECEIVER *)memory_receiver; + +#if !defined(UX_DEVICE_STANDALONE) + + /* This instance needs to be running in a different thread. So start + a new thread. We pass a pointer to the class to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + status = _ux_utility_thread_create(&(*receiver) -> ux_device_class_hid_receiver_thread, + "ux_device_class_hid_receiver_thread", + _ux_device_class_hid_receiver_thread, + (ULONG) (ALIGN_TYPE) hid, (VOID *) memory_stack, + UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); +#endif + + /* Check the creation of this thread. */ + if (status == UX_SUCCESS) + { + +#if !defined(UX_DEVICE_STANDALONE) + UX_THREAD_EXTENSION_PTR_SET(&((*receiver) -> ux_device_class_hid_receiver_thread), hid) +#else + /* TODO: initialize read state for receiver. */ +#endif + + /* Initialize event buffer size. */ + (*receiver) -> ux_device_class_hid_receiver_event_buffer_size = + parameter -> ux_device_class_hid_parameter_receiver_event_max_length; + + /* Initialize events. */ + (*receiver) -> ux_device_class_hid_receiver_events = + (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)(memory_events); + (*receiver) -> ux_device_class_hid_receiver_events_end = + (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)(memory_receiver + memory_size); + (*receiver) -> ux_device_class_hid_receiver_event_read_pos = + (*receiver) -> ux_device_class_hid_receiver_events; + (*receiver) -> ux_device_class_hid_receiver_event_save_pos = + (*receiver) -> ux_device_class_hid_receiver_events; + + /* Initialize uninitialize function. */ + (*receiver) -> ux_device_class_hid_receiver_uninitialize = _ux_device_class_hid_receiver_uninitialize; + + /* Done success. */ + return(UX_SUCCESS); + } + else + status = (UX_THREAD_ERROR); + + /* Free allocated memory. */ + _ux_utility_memory_free(*receiver); + (*receiver) = UX_NULL; + + /* Return completion status. */ + return(status); +#endif +} diff --git a/common/usbx_device_classes/src/ux_device_class_hid_receiver_thread.c b/common/usbx_device_classes/src/ux_device_class_hid_receiver_thread.c new file mode 100644 index 00000000..0854e884 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_receiver_thread.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) && !defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_receiver_thread PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the hid interrupt OUT endpoint */ +/* */ +/* INPUT */ +/* */ +/* hid_class Address of hid class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_device_class_hid_event_get Get HID event */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_hid_receiver_thread(ULONG hid_instance) +{ + +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_DEVICE *device; +UX_DEVICE_CLASS_HID_RECEIVER *receiver; +UX_DEVICE_CLASS_HID_RECEIVED_EVENT *pos; +UCHAR *next_pos; +UX_SLAVE_TRANSFER *transfer; +UINT status; +UCHAR *buffer; +ULONG temp; + + + /* Cast properly the hid instance. */ + UX_THREAD_EXTENSION_PTR_GET(hid, UX_SLAVE_CLASS_HID, hid_instance) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get receiver instance. */ + receiver = hid -> ux_device_class_hid_receiver; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Check device state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&receiver -> ux_device_class_hid_receiver_thread); + continue; + } + + /* Check if there is buffer available. */ + pos = receiver -> ux_device_class_hid_receiver_event_save_pos; + if (pos -> ux_device_class_hid_received_event_length != 0) + { + + /* Wait before check again. */ + status = _ux_utility_event_flags_get( + &hid -> ux_device_class_hid_event_flags_group, + UX_DEVICE_CLASS_HID_RECEIVER_RESTART, + UX_OR_CLEAR, &temp, 100); + if (status != UX_SUCCESS) + { + + /* Keep checking before a good state. */ + continue; + } + } + + /* Event buffer available, issue request to get data. */ + transfer = &hid -> ux_device_class_hid_read_endpoint -> ux_slave_endpoint_transfer_request; + + /* Protect read. */ + _ux_utility_mutex_on(&hid -> ux_device_class_hid_read_mutex); + + /* Issue the transfer request. */ + status = _ux_device_stack_transfer_request(transfer, + receiver -> ux_device_class_hid_receiver_event_buffer_size, + receiver -> ux_device_class_hid_receiver_event_buffer_size); + + /* Check status and ignore ZLPs. */ + if (status != UX_SUCCESS || + transfer -> ux_slave_transfer_request_actual_length == 0) + { + _ux_utility_mutex_off(&hid -> ux_device_class_hid_read_mutex); + continue; + } + + /* Save received event data and length. */ + buffer = (UCHAR *)&pos -> ux_device_class_hid_received_event_data; + temp = transfer -> ux_slave_transfer_request_actual_length; + _ux_utility_memory_copy(buffer, + transfer -> ux_slave_transfer_request_data_pointer, + temp); /* Use case of memcpy is verified. */ + + /* Unprotect read. */ + _ux_utility_mutex_off(&hid -> ux_device_class_hid_read_mutex); + + /* Advance the save position. */ + next_pos = (UCHAR *)pos + receiver -> ux_device_class_hid_receiver_event_buffer_size + sizeof(ULONG); + if (next_pos >= (UCHAR *)receiver -> ux_device_class_hid_receiver_events_end) + next_pos = (UCHAR *)receiver -> ux_device_class_hid_receiver_events; + receiver -> ux_device_class_hid_receiver_event_save_pos = (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)next_pos; + + /* Save received data length (it's valid now). */ + pos -> ux_device_class_hid_received_event_length = temp; + } +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_receiver_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_hid_receiver_uninitialize.c new file mode 100644 index 00000000..c45157d4 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_receiver_uninitialize.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_receiver_uninitialize PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitialize the USB HID device receiver. It's only */ +/* done once. */ +/* */ +/* INPUT */ +/* */ +/* receiver Pointer to receiver instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_hid_receiver_uninitialize(UX_DEVICE_CLASS_HID_RECEIVER *receiver) +{ + +#if !defined(UX_DEVICE_STANDALONE) + + /* Delete receiver thread. */ + _ux_utility_thread_delete(&receiver -> ux_device_class_hid_receiver_thread); +#endif + + /* Free receiver and events memory. */ + _ux_utility_memory_free(receiver); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_hid_tasks_run.c new file mode 100644 index 00000000..1bcaf391 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_tasks_run.c @@ -0,0 +1,194 @@ +/**************************************************************************/ +/* */ +/* 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 HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the hid. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* hid_class Address of hid class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No interrupt transfer running */ +/* UX_STATE_WAIT Interrupt IN transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_hid_event_get Get HID event */ +/* _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 */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_tasks_run(VOID *instance) +{ + +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS_HID_EVENT *hid_event; +UX_SLAVE_TRANSFER *trans; +ULONG tick, elapsed; +UINT status; + + + /* Get HID instance. */ + hid = (UX_SLAVE_CLASS_HID *) 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) + { + hid -> ux_device_class_hid_event_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + if (hid -> ux_device_class_hid_receiver) + hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_tasks_run(hid); +#endif + + /* Run HID state machine. */ + switch(hid -> ux_device_class_hid_event_state) + { + case UX_STATE_EXIT: + + /* There is nothing to do in this state. */ + return (UX_STATE_EXIT); + + case UX_STATE_RESET: + + /* Start timeout waiting. */ + hid -> ux_device_class_hid_event_wait_start = _ux_utility_time_get(); + hid -> ux_device_class_hid_event_state = UX_STATE_IDLE; + + /* Fall through. */ + case UX_STATE_IDLE: + + /* Check if there is event ready. */ + hid_event = &hid -> ux_device_class_hid_event; + status = _ux_device_class_hid_event_get(hid, hid_event); + + /* If there is no event, check idle rate. */ + if (status != UX_SUCCESS) + { + + /* Check idle rate setting. */ + if (hid -> ux_device_class_hid_event_wait_timeout == UX_WAIT_FOREVER) + { + + /* There is no background idle report, keep waiting. */ + return(UX_STATE_IDLE); + } + + /* Check wait timeout. */ + tick = _ux_utility_time_get(); + elapsed = _ux_utility_time_elapsed(hid -> ux_device_class_hid_event_wait_start, tick); + if (elapsed < hid -> ux_device_class_hid_event_wait_timeout) + { + + /* Keep waiting. */ + return(UX_STATE_IDLE); + } + + /* Send the last event in buffer. */ + } + + /* Prepare the request to send event. */ + trans = &hid -> ux_device_class_hid_interrupt_endpoint -> + ux_slave_endpoint_transfer_request; + _ux_utility_memory_copy(trans -> ux_slave_transfer_request_data_pointer, + hid_event -> ux_device_class_hid_event_buffer, + hid_event -> ux_device_class_hid_event_length); /* Use case of memcpy is verified. */ + trans -> ux_slave_transfer_request_requested_length = + hid_event -> ux_device_class_hid_event_length; + UX_SLAVE_TRANSFER_STATE_RESET(trans); + hid -> ux_device_class_hid_event_state = UX_STATE_WAIT; + + /* Fall through. */ + case UX_STATE_WAIT: + + /* Run transfer state machine. */ + trans = &hid -> ux_device_class_hid_interrupt_endpoint -> + ux_slave_endpoint_transfer_request; + hid_event = &hid -> ux_device_class_hid_event; + status = _ux_device_stack_transfer_run(trans, + hid_event -> ux_device_class_hid_event_length, + hid_event -> ux_device_class_hid_event_length); + + /* Any error or success case. */ + if (status <= UX_STATE_NEXT) + { + + /* Next round. */ + hid -> ux_device_class_hid_event_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } + + /* Wait. */ + return(UX_STATE_WAIT); + + default: + + /* Just go back to normal state. */ + hid -> ux_device_class_hid_event_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c index 3086331f..7fb839e2 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_uninitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,7 +52,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_delete Remove storage thread. */ +/* _ux_device_thread_delete Remove storage thread. */ /* _ux_utility_memory_free Free memory used by storage */ /* _ux_utility_event_flags_delete Remove flag event structure */ /* */ @@ -68,6 +68,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added interrupt OUT support,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -83,18 +87,35 @@ UX_SLAVE_CLASS *class; /* Get the class instance in the container. */ hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; +#if !defined(UX_DEVICE_STANDALONE) + /* Remove HID thread. */ - _ux_utility_thread_delete(&class -> ux_slave_class_thread); + _ux_device_thread_delete(&class -> ux_slave_class_thread); /* Remove the thread used by HID. */ _ux_utility_memory_free(class -> ux_slave_class_thread_stack); /* Delete the event flag group for the hid class. */ - _ux_utility_event_flags_delete(&hid -> ux_device_class_hid_event_flags_group); + _ux_device_event_flags_delete(&hid -> ux_device_class_hid_event_flags_group); +#endif /* Free memory for the array. */ _ux_utility_memory_free(hid -> ux_device_class_hid_event_array); +#if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + +#if !defined(UX_DEVICE_STANDALONE) + + /* Free read mutex. */ + _ux_utility_mutex_delete(&hid -> ux_device_class_hid_read_mutex); +#endif + + /* Uninitialize receiver. */ + if (hid -> ux_device_class_hid_receiver) + hid -> ux_device_class_hid_receiver -> + ux_device_class_hid_receiver_uninitialize(hid -> ux_device_class_hid_receiver); +#endif + /* Free the resources. */ _ux_utility_memory_free(hid); diff --git a/common/usbx_device_classes/src/ux_device_class_pima_activate.c b/common/usbx_device_classes/src/ux_device_class_pima_activate.c index e24938f7..16a28035 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,7 +52,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_resume Resume thread */ +/* _ux_device_thread_resume Resume thread */ /* */ /* CALLED BY */ /* */ @@ -65,6 +65,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added variables initialize, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -126,8 +130,13 @@ UX_SLAVE_ENDPOINT *endpoint_interrupt; pima -> ux_device_class_pima_bulk_out_endpoint = endpoint_out; pima -> ux_device_class_pima_interrupt_endpoint = endpoint_interrupt; + /* Initialize status code. */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_IDLE; + pima -> ux_device_class_pima_session_id = 0; + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + /* Resume thread. */ - status = _ux_utility_thread_resume(&class -> ux_slave_class_thread); + status = _ux_device_thread_resume(&class -> ux_slave_class_thread); /* If there is a activate function call it. */ if (pima -> ux_device_class_pima_instance_activate != UX_NULL) diff --git a/common/usbx_device_classes/src/ux_device_class_pima_control_request.c b/common/usbx_device_classes/src/ux_device_class_pima_control_request.c index b6cc24fc..26e29b90 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_control_request.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_control_request.c @@ -11,8 +11,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device PIMA Class */ /** */ @@ -29,58 +29,69 @@ #include "ux_device_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_control_request PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_control_request PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function manages the based sent by the host on the control */ -/* endpoints with a CLASS or VENDOR SPECIFIC type. */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ /* _ux_device_stack_transfer_abort Transfer abort */ /* _ux_device_class_pima_event_set Put PIMA event into queue */ /* _ux_utility_short_put Put 16-bit value into buffer */ -/* */ -/* CALLED BY */ -/* */ +/* */ +/* CALLED BY */ +/* */ /* PIMA Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved request handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_control_request(UX_SLAVE_CLASS_COMMAND *command) { +UX_SLAVE_DCD *dcd; +UX_SLAVE_ENDPOINT *endpoint; UX_SLAVE_TRANSFER *transfer_request; UX_SLAVE_DEVICE *device; UX_SLAVE_CLASS *class; -UX_SLAVE_CLASS_PIMA_EVENT pima_event; ULONG request; +ULONG request_length; +ULONG length; +UCHAR *request_data; UX_SLAVE_CLASS_PIMA *pima; +ULONG transaction_id; + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; /* Get the pointer to the device. */ device = &_ux_system_slave -> ux_system_slave_device; @@ -90,10 +101,12 @@ UX_SLAVE_CLASS_PIMA *pima; /* Extract all necessary fields of the request. */ request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); - + request_data = transfer_request -> ux_slave_transfer_request_data_pointer; + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + /* Get the class container. */ class = command -> ux_slave_class_command_class_ptr; - + /* Get the storage instance from this class container. */ pima = (UX_SLAVE_CLASS_PIMA *) class -> ux_slave_class_instance; @@ -103,52 +116,92 @@ UX_SLAVE_CLASS_PIMA *pima; case UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_COMMAND: - /* We need to cancel the request that is currently pending. It could be either - on the bulk in or bulk out endpoint. Load the bulk in transfer request first. */ - transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; - - /* And check if we have something waiting on this one. */ - if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) - - /* Yes, abort it. */ - _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - - /* Maybe the bulk out is busy too. */ - transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; - - /* And check if we have something waiting on this one. */ - if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) - - /* Yes, abort it. */ - _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); - - /* The host is now waiting for an event of transfer cancelled to proceed. - Prepare an event command and set the event code to transaction cancelled*/ - pima_event.ux_device_class_pima_event_code = UX_DEVICE_CLASS_PIMA_EC_CANCEL_TRANSACTION; - - /* Set all parameters to a 0 value. */ - pima_event.ux_device_class_pima_event_parameter_1 = 0; - pima_event.ux_device_class_pima_event_parameter_2 = 0; - pima_event.ux_device_class_pima_event_parameter_3 = 0; - - /* Send the pima event into the queue. This will be processed by an asynchronous thread. */ - _ux_device_class_pima_event_set(pima, &pima_event); + /* Validate length. */ + if (request_length != 6) + return(UX_ERROR); + + /* Validate Cancellation code (0x4001). */ + if (request_data[0] != 0x01 || request_data[1] != 0x40) + return(UX_ERROR); + + /* Obtain TransactionID. */ + transaction_id = _ux_utility_long_get(request_data + 2); + if (transaction_id != pima -> ux_device_class_pima_transaction_id) + return(UX_ERROR); + + /* Cancel data phase only. */ + if (pima -> ux_device_class_pima_state > UX_DEVICE_CLASS_PIMA_PHASE_RESPONSE) + { + + /* Abort, device is busy until data thread end. */ + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_DEVICE_BUSY; + + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_DATA_IN) + _ux_device_stack_transfer_abort(&pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request, UX_ABORTED); + else + _ux_device_stack_transfer_abort(&pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request, UX_ABORTED); + + /* Invoke callback if available, let application cancel/close related objects. */ + if (pima -> ux_device_class_pima_cancel) + pima -> ux_device_class_pima_cancel(pima); + /* Set state to idle, time consuming threads detect it to break the loop. */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_IDLE; + } break ; case UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_COMMAND: - - /* Fill the status data payload. First with length. */ - _ux_utility_short_put(transfer_request -> ux_slave_transfer_request_data_pointer, 4); - /* Then the status. */ - _ux_utility_short_put(transfer_request -> ux_slave_transfer_request_data_pointer + 2, UX_DEVICE_CLASS_PIMA_RC_OK); + /* Validate length. */ + if (request_length < 2) + return(UX_ERROR); - /* We have a request to obtain the status of the MTP. */ - _ux_device_stack_transfer_request(transfer_request, 4, 4); + /* Fill the status data payload. Initialize length to 4. */ + length = 4; + + /* Fill status. */ + _ux_utility_short_put(request_data + 2, + pima -> ux_device_class_pima_device_status); + + /* Fill device status actual length. */ + _ux_utility_short_put(request_data, (USHORT)length); + length = UX_MIN(request_length, length); + + /* Change status, error is reported only once. */ + pima->ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + /* We have a request to obtain the status of the MTP. */ + _ux_device_stack_transfer_request(transfer_request, length, request_length); break ; - + + case UX_DEVICE_CLASS_PIMA_REQUEST_RESET_DEVICE: + + /* Clear stall. */ + endpoint = pima -> ux_device_class_pima_bulk_in_endpoint; + if (endpoint->ux_slave_endpoint_state == UX_ENDPOINT_HALTED) + { + dcd -> ux_slave_dcd_function(dcd, UX_DCD_RESET_ENDPOINT, endpoint); + endpoint -> ux_slave_endpoint_state = UX_ENDPOINT_RESET; + } + else + _ux_device_stack_transfer_abort(&endpoint->ux_slave_endpoint_transfer_request, UX_ABORTED); + endpoint = pima -> ux_device_class_pima_bulk_out_endpoint; + if (endpoint->ux_slave_endpoint_state == UX_ENDPOINT_HALTED) + { + dcd -> ux_slave_dcd_function(dcd, UX_DCD_RESET_ENDPOINT, endpoint); + endpoint -> ux_slave_endpoint_state = UX_ENDPOINT_RESET; + } + else + _ux_device_stack_transfer_abort(&endpoint->ux_slave_endpoint_transfer_request, UX_ABORTED); + + /* Reset session. */ + pima -> ux_device_class_pima_device_reset(pima); + + /* Reset status. */ + pima -> ux_device_class_pima_session_id = 0; + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + break; + default: /* Unknown function. It's not handled. */ @@ -158,4 +211,3 @@ UX_SLAVE_CLASS_PIMA *pima; /* It's handled. */ return(UX_SUCCESS); } - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c b/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c index 7794f28c..67a06eb3 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device Pima Class */ /** */ @@ -29,49 +29,56 @@ #include "ux_device_class_pima.h" #include "ux_device_stack.h" +/* Basic buffer length check: larger than DeviceInfo with all string and array 0. */ +#if UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH < 35 +#error UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH too small +#endif -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_device_info_send PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_info_send PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function returns the device info structure to the host. */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_transfer_request Transfer request */ -/* _ux_utility_long_put Put 32-bit value */ -/* _ux_utility_short_put Put 16-bit value */ -/* _ux_utility_memory_set Set memory */ +/* */ +/* This function returns the device info structure to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_memory_set Set memory */ /* _ux_utility_string_to_unicode Ascii string to unicode */ /* _ux_device_class_pima_response_send Send PIMA response */ -/* */ -/* CALLED BY */ -/* */ -/* Device Storage Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_device_info_send(UX_SLAVE_CLASS_PIMA *pima) @@ -90,39 +97,45 @@ USHORT *array_pointer; /* Obtain the pointer to the transfer request. */ transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; - + /* Obtain memory for this object info. We use the transfer request pre-allocated buffer. */ device_info = transfer_request -> ux_slave_transfer_request_data_pointer; /* Fill in the data container type. */ _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); - + /* Fill in the data code. */ _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_INFO); - + /* Fill in the Transaction ID. */ - _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, pima -> ux_device_class_pima_transaction_id); - + /* Allocate the device info pointer to the beginning of the dynamic device info field. */ device_info_pointer = device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC; /* Fill in the standard version field. */ - _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_STANDARD_VERSION, + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_STANDARD_VERSION, UX_DEVICE_CLASS_PIMA_STANDARD_VERSION); - + /* Fill in the vendor extension ID field. */ - _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_ID, + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_ID, UX_DEVICE_CLASS_PIMA_VENDOR_EXTENSION_ID); - + /* Fill in the vendor extension version. */ - _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_VERSION, + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_VERSION, UX_DEVICE_CLASS_PIMA_EXTENSION_VERSION); - + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + + _ux_utility_string_length_get(_ux_device_class_pima_vendor_extension_descriptor) * 2 + 1)); + /* Fill in the vendor extension description. */ - _ux_utility_string_to_unicode(_ux_device_class_pima_vendor_extension_descriptor, device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC); + _ux_utility_string_to_unicode(_ux_device_class_pima_vendor_extension_descriptor, + device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC); /* Calculate the address of the dynamic area of the device info. */ device_info_pointer = device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC; @@ -130,28 +143,36 @@ USHORT *array_pointer; /* Update the device info pointer after the Unicode string. */ device_info_pointer += (ULONG) *(device_info_pointer) * 2 + 1; + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(USHORT))); + /* Add the functional mode which is set to standard. */ _ux_utility_short_put(device_info_pointer, UX_DEVICE_CLASS_PIMA_STANDARD_MODE); - + /* Update the device info pointer. */ device_info_pointer += sizeof(USHORT); - + /* Fill in the supported operations. This table is defined locally. */ array_field_counter = 0; while (_ux_device_class_pima_supported_operations[array_field_counter] != 0) { + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter))); + /* Add one element. */ _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), _ux_device_class_pima_supported_operations[array_field_counter]); - + /* Next element. */ array_field_counter++; - } - + /* Put the length of this variable array at the beginning of the field. */ _ux_utility_long_put(device_info_pointer, array_field_counter); - + /* Update the device info pointer. */ device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); @@ -159,153 +180,187 @@ USHORT *array_pointer; array_field_counter = 0; while (_ux_device_class_pima_supported_events[array_field_counter] != 0) { + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter))); + /* Add one element. */ _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), _ux_device_class_pima_supported_events[array_field_counter]); - + /* Next element. */ array_field_counter++; - } - + /* Put the length of this variable array at the beginning of the field. */ _ux_utility_long_put(device_info_pointer, array_field_counter); - + /* Update the device info pointer. */ device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); /* Fill in the supported properties. This table can be configured by the user. If it is declared NULL, use the local default one. */ array_pointer = pima -> ux_device_class_pima_device_properties_list; - + /* Check if array defined. */ if (array_pointer == UX_NULL) - + /* Use local array. */ array_pointer = _ux_device_class_pima_device_prop_supported; - + /* Reset counter. */ array_field_counter = 0; /* Parse the table. */ while (*(array_pointer + array_field_counter) != 0) { + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter))); + /* Add one element. */ _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), *(array_pointer + array_field_counter)); - + /* Next element. */ array_field_counter++; - } - + /* Put the length of this variable array at the beginning of the field. */ _ux_utility_long_put(device_info_pointer, array_field_counter); - + /* Update the device info pointer. */ device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); /* Fill in the supported capture formats. This table can be configured by the user. If it is declared NULL, use the local default one. */ array_pointer = pima -> ux_device_class_pima_supported_capture_formats_list; - + /* Check if array defined. */ if (array_pointer == UX_NULL) - + /* Use local array. */ array_pointer = _ux_device_class_pima_supported_capture_formats; - + /* Reset counter. */ array_field_counter = 0; /* Parse the table. */ while (*(array_pointer + array_field_counter) != 0) { + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter))); + /* Add one element. */ _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), *(array_pointer + array_field_counter)); - + /* Next element. */ array_field_counter++; - } /* Put the length of this variable array at the beginning of the field. */ _ux_utility_long_put(device_info_pointer, array_field_counter); - + /* Update the device info pointer. */ device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); /* Fill in the supported image formats. This table can be configured by the user. If it is declared NULL, use the local default one. */ array_pointer = pima -> ux_device_class_pima_supported_image_formats_list; - + /* Check if array defined. */ if (array_pointer == UX_NULL) - + /* Use local array. */ array_pointer = _ux_device_class_pima_supported_image_formats; - + /* Reset counter. */ array_field_counter = 0; /* Parse the table. */ while (*(array_pointer + array_field_counter) != 0) { + + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter))); + /* Add one element. */ _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), *(array_pointer + array_field_counter)); - + /* Next element. */ array_field_counter++; - } - + /* Put the length of this variable array at the beginning of the field. */ _ux_utility_long_put(device_info_pointer, array_field_counter); - + /* Update the device info pointer. */ device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + + _ux_utility_string_length_get(pima -> ux_device_class_pima_manufacturer) * 2 + 1)); + /* Fill in the manufacturer string. */ _ux_utility_string_to_unicode(pima -> ux_device_class_pima_manufacturer, device_info_pointer); /* Update the device info pointer. */ device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + + _ux_utility_string_length_get(pima -> ux_device_class_pima_model) * 2 + 1)); + /* Fill in the model string. */ _ux_utility_string_to_unicode(pima -> ux_device_class_pima_model, device_info_pointer); /* Update the device info pointer. */ device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + + _ux_utility_string_length_get(pima -> ux_device_class_pima_device_version) * 2 + 1)); + /* Fill in the device version string. */ _ux_utility_string_to_unicode(pima -> ux_device_class_pima_device_version, device_info_pointer); /* Update the device info pointer. */ device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + /* Validate buffer space available. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH > + ((ULONG)(device_info_pointer - device_info) + + _ux_utility_string_length_get(pima -> ux_device_class_pima_serial_number) * 2 + 1)); + /* Fill in the device serial number. */ _ux_utility_string_to_unicode(pima -> ux_device_class_pima_serial_number, device_info_pointer); - + /* Update the device info pointer. */ device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; /* Compute the overall length of the device info structure. */ device_info_length = (ULONG) ((ALIGN_TYPE) device_info_pointer - (ALIGN_TYPE) device_info); - + /* Set the transfer data pointer. */ transfer_request -> ux_slave_transfer_request_data_pointer = device_info; - + /* Fill in the size of the response header. */ - _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, device_info_length); - + /* Send a data payload with the device info data set. */ status = _ux_device_stack_transfer_request(transfer_request, device_info_length, 0); - + /* Now we return a response with success. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c index c6d770d0..8a12fab4 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device Pima Class */ /** */ @@ -30,52 +30,56 @@ #include "ux_device_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_device_prop_desc_get PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_desc_get PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* Return an Device Property Description dataset. */ -/* */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* device_property_code Device Property code for */ -/* which the dataset is obtained */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* Return an Device Property Description dataset. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* device_property_code Device Property code for */ +/* which the dataset is obtained */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ /* _ux_utility_short_put Put 16-bit value */ /* _ux_utility_long_put Put 32-bit value */ /* _ux_utility_memory_copy Copy memory */ /* _ux_device_class_pima_response_send Send PIMA response */ -/* */ -/* CALLED BY */ -/* */ -/* Device Pima Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_device_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, @@ -93,36 +97,39 @@ UCHAR *device_property_desc_dataset; /* Obtain the pointer to the transfer request. */ transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; - + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; /* Fill in the data container type. */ _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); - + /* Fill in the data code. */ _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_DESC); - + /* Fill in the Transaction ID. */ - _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, pima -> ux_device_class_pima_transaction_id); /* Ask the application to retrieve for us the device prop description. */ - status = pima -> ux_device_class_pima_device_prop_desc_get(pima, device_property_code, &device_property_desc_dataset, &device_property_desc_dataset_length); - + device_property_desc_dataset_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD; + status = pima -> ux_device_class_pima_device_prop_desc_get(pima, device_property_code, + &device_property_desc_dataset, &device_property_desc_dataset_length); + /* Result should always be OK, but to be sure .... */ if (status != UX_SUCCESS) + { - /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_DEVICE_PROP_NOT_SUPPORTED, 0, 0, 0, 0); - + /* We response returned error. */ + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + } else { /* Ensure the application's data can fit in the endpoint's data buffer. */ - if (device_property_desc_dataset_length + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + if (device_property_desc_dataset_length > UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) { /* If trace is enabled, insert this event into the trace buffer. */ @@ -134,27 +141,25 @@ UCHAR *device_property_desc_dataset; /* Return overflow error. */ return(UX_MEMORY_INSUFFICIENT); } - + /* Copy the property dataset into the local buffer. */ - _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, device_property_desc_dataset, device_property_desc_dataset_length); /* Use case of memcpy is verified. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + device_property_desc_dataset, device_property_desc_dataset_length); /* Use case of memcpy is verified. */ /* Add the header size to the payload. */ device_property_desc_dataset_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - + /* Fill in the size of the response header. */ - _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, device_property_desc_dataset_length); - + /* Send a data payload with the device prop description dataset. */ status = _ux_device_stack_transfer_request(transfer_request, device_property_desc_dataset_length, 0); - + /* Now we return a response with success. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); - } - + /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c index 9590e2bb..bc8bae04 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device Pima Class */ /** */ @@ -30,56 +30,60 @@ #include "ux_device_stack.h" -#if UX_SLAVE_REQUEST_DATA_MAX_LENGTH < UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE -#error UX_SLAVE_REQUEST_DATA_MAX_LENGTH too small, please check +#if UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH < UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE +#error UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH too small, please check #endif -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_device_prop_value_get PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_value_get PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* Return an Device Property Value. */ -/* */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* device_property_code Device Property code for */ -/* which the value is obtained. */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* Return an Device Property Value. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* device_property_code Device Property code for */ +/* which the value is obtained. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ /* _ux_utility_short_put Put 16-bit value */ /* _ux_utility_long_put Put 32-bit value */ /* _ux_utility_memory_copy Copy memory */ /* _ux_device_class_pima_response_send Send PIMA response */ -/* */ -/* CALLED BY */ -/* */ -/* Device Pima Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_device_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, @@ -97,36 +101,39 @@ UCHAR *device_property_value; /* Obtain the pointer to the transfer request. */ transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; - + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; /* Fill in the data container type. */ _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); - + /* Fill in the data code. */ _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_VALUE); - + /* Fill in the Transaction ID. */ - _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, pima -> ux_device_class_pima_transaction_id); /* Ask the application to retrieve for us the device prop value. */ - status = pima -> ux_device_class_pima_device_prop_value_get(pima, device_property_code, &device_property_value, &device_property_value_length); - + device_property_value_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD; + status = pima -> ux_device_class_pima_device_prop_value_get(pima, device_property_code, + &device_property_value, &device_property_value_length); + /* Result should always be OK, but to be sure .... */ if (status != UX_SUCCESS) + { /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); - + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + } else { /* Ensure the application's data can fit in the endpoint's data buffer. */ - if (device_property_value_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) + if (device_property_value_length > UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD) { /* If trace is enabled, insert this event into the trace buffer. */ @@ -140,25 +147,23 @@ UCHAR *device_property_value; } /* Copy the property dataset into the local buffer. */ - _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, device_property_value, device_property_value_length); /* Use case of memcpy is verified. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + device_property_value, device_property_value_length); /* Use case of memcpy is verified. */ /* Add the header size to the payload. */ device_property_value_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - + /* Fill in the size of the response header. */ - _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, device_property_value_length); - + /* Send a data payload with the device prop value. */ status = _ux_device_stack_transfer_request(transfer_request, device_property_value_length, 0); - + /* Now we return a response with success. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); - } - + /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c index 5391204d..9b2eb294 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device Pima Class */ /** */ @@ -30,45 +30,49 @@ #include "ux_device_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_device_prop_value_set PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_value_set PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function receives an device object value from the host. */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_endpoint_stall Stall endpoint */ -/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* This function receives an device object value from the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_stack_transfer_request Transfer request */ /* _ux_device_class_pima_response_send Send PIMA response */ -/* */ -/* CALLED BY */ -/* */ -/* Device Storage Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_device_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, ULONG device_property_code) @@ -85,26 +89,26 @@ UCHAR *device_property_value_pointer; /* Obtain the pointer to the transfer request. */ transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; - + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ device_property_value = transfer_request -> ux_slave_transfer_request_data_pointer; /* Get the data payload. */ - status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE, - UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE); + status = _ux_device_stack_transfer_request(transfer_request, + UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH, + UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); /* Check if there was an error. If so, stall the endpoint. */ if (status != UX_SUCCESS) { - + /* Stall the endpoint. */ _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); - + /* Return the status. */ return(status); - } - + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ device_property_value_pointer = device_property_value + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; @@ -117,25 +121,25 @@ UCHAR *device_property_value_pointer; /* Take out the header. */ device_property_value_length -= UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - + /* Send the object to the application. */ - status = pima -> ux_device_class_pima_device_prop_value_set(pima, device_property_code, device_property_value_pointer, device_property_value_length); - - /* Now we return a response with success. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + status = pima -> ux_device_class_pima_device_prop_value_set(pima, device_property_code, + device_property_value_pointer, device_property_value_length); + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, (status == UX_SUCCESS) ? + UX_DEVICE_CLASS_PIMA_RC_OK : status, 0, 0, 0, 0); } else - { + { + /* We return an error. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); /* Status error. */ status = UX_ERROR; - } + /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_event_set.c b/common/usbx_device_classes/src/ux_device_class_pima_event_set.c index 015c13e6..570a477a 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_event_set.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_event_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_event_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,7 +55,7 @@ /* event */ /* CALLS */ /* */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_device_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -68,6 +68,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added transaction ID, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_event_set(UX_SLAVE_CLASS_PIMA *pima, @@ -123,13 +127,14 @@ UX_SLAVE_DEVICE *device; current_pima_event = pima -> ux_device_class_pima_event_array_tail; /* fill in the event structure from the user. */ - current_pima_event -> ux_device_class_pima_event_code = pima_event -> ux_device_class_pima_event_code; - current_pima_event -> ux_device_class_pima_event_parameter_1 = pima_event -> ux_device_class_pima_event_parameter_1; - current_pima_event -> ux_device_class_pima_event_parameter_2 = pima_event -> ux_device_class_pima_event_parameter_2; - current_pima_event -> ux_device_class_pima_event_parameter_3 = pima_event -> ux_device_class_pima_event_parameter_3; + current_pima_event -> ux_device_class_pima_event_code = pima_event -> ux_device_class_pima_event_code; + current_pima_event -> ux_device_class_pima_event_transaction_id = pima_event -> ux_device_class_pima_event_transaction_id; + current_pima_event -> ux_device_class_pima_event_parameter_1 = pima_event -> ux_device_class_pima_event_parameter_1; + current_pima_event -> ux_device_class_pima_event_parameter_2 = pima_event -> ux_device_class_pima_event_parameter_2; + current_pima_event -> ux_device_class_pima_event_parameter_3 = pima_event -> ux_device_class_pima_event_parameter_3; /* Set a semaphore to wake up the interrupt thread. */ - _ux_utility_semaphore_put(&pima -> ux_device_class_pima_interrupt_thread_semaphore); + _ux_device_semaphore_put(&pima -> ux_device_class_pima_interrupt_thread_semaphore); /* Return event status to the user. */ return(UX_SUCCESS); diff --git a/common/usbx_device_classes/src/ux_device_class_pima_initialize.c b/common/usbx_device_classes/src/ux_device_class_pima_initialize.c index b1e2f519..b324dfc6 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,7 +54,7 @@ /* */ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_thread_create Create thread */ +/* _ux_device_thread_create Create thread */ /* */ /* CALLED BY */ /* */ @@ -70,6 +70,10 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added cancel callback, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -108,7 +112,7 @@ UX_SLAVE_CLASS *class; does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_class_thread", + status = _ux_device_thread_create(&class -> ux_slave_class_thread, "ux_slave_class_thread", _ux_device_class_pima_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -178,6 +182,9 @@ UX_SLAVE_CLASS *class; #endif + /* Store the callback functions for request. */ + pima -> ux_device_class_pima_cancel = pima_parameter -> ux_device_class_pima_parameter_cancel; + /* Store the callback functions for device. */ pima -> ux_device_class_pima_device_reset = pima_parameter -> ux_device_class_pima_parameter_device_reset; pima -> ux_device_class_pima_device_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get; diff --git a/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c index cc5bc590..79b392e3 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_interrupt_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,11 +56,11 @@ /* */ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_utility_memory_allocate Allocate memory */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_device_semaphore_get Get semaphore */ /* _ux_device_class_pima_event_get Get PIMA event */ /* _ux_utility_long_put Put 32-bit value */ /* _ux_utility_short_put Put 16-bit value */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* added transaction ID, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_pima_interrupt_thread(ULONG pima_class) @@ -119,7 +123,7 @@ UCHAR *buffer; { /* Wait until something has awaken us. */ - status = _ux_utility_semaphore_get(&pima -> ux_device_class_pima_interrupt_thread_semaphore, UX_WAIT_FOREVER); + status = _ux_device_semaphore_get(&pima -> ux_device_class_pima_interrupt_thread_semaphore, UX_WAIT_FOREVER); /* Check the completion code. */ if (status != UX_SUCCESS) @@ -147,7 +151,7 @@ UCHAR *buffer; _ux_utility_short_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_EVENT_CODE, (USHORT)pima_event.ux_device_class_pima_event_code); /* Put the transaction ID. */ - _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_TRANSACTION_ID, 0xFFFFFFFF); + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_TRANSACTION_ID, pima_event.ux_device_class_pima_event_transaction_id); /* Put the value of parameter 1. */ _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_1, pima_event.ux_device_class_pima_event_parameter_1); @@ -171,7 +175,7 @@ UCHAR *buffer; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&pima -> ux_device_class_pima_interrupt_thread); + _ux_device_thread_suspend(&pima -> ux_device_class_pima_interrupt_thread); } } diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c index 20b0d82a..c54ae350 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Device Pima Class */ /** */ @@ -29,48 +29,52 @@ #include "ux_device_class_pima.h" #include "ux_device_stack.h" - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_device_class_pima_object_data_get PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_data_get PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function returns the object data to the host. */ -/* */ -/* INPUT */ -/* */ -/* pima Pointer to pima class */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_device_stack_transfer_request Transfer request */ -/* _ux_utility_long_put Put 32-bit value */ -/* _ux_utility_short_put Put 32-bit value */ +/* */ +/* This function returns the object data to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ /* _ux_device_class_pima_response_send Send PIMA response */ /* _ux_device_stack_endpoint_stall Stall endpoint */ -/* */ -/* CALLED BY */ -/* */ -/* Device Storage Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* improved sanity checks, */ +/* improved cancel flow, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_data_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) @@ -83,7 +87,7 @@ UCHAR *object_data; ULONG object_offset; ULONG object_length; ULONG total_length; -ULONG object_length_demanded; +ULONG object_length_demanded; ULONG object_length_received; /* If trace is enabled, insert this event into the trace buffer. */ @@ -91,199 +95,203 @@ ULONG object_length_received; /* Obtain the object info from the application. */ status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object); - + /* Check for error. */ if (status == UX_SUCCESS) - { + { + + /* Data phase (Bulk IN). */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_DATA_IN; /* Set the object length. */ - object_length = object -> ux_device_class_pima_object_compressed_size; + object_length = object -> ux_device_class_pima_object_compressed_size; + /* Set the total length to be sent. */ total_length = object_length + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - + /* Reset the offset. */ - object_offset = 0; + object_offset = 0; /* Obtain the pointer to the transfer request of the bulk in endpoint. */ transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; - + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ object_data = transfer_request -> ux_slave_transfer_request_data_pointer; /* Fill in the total length to be sent (header + payload. */ - _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, total_length); /* Fill in the data container type. */ _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); - + /* Fill in the data code. */ _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT); - + /* Fill in the Transaction ID. */ - _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, pima -> ux_device_class_pima_transaction_id); - + /* Assuming the host will ask for the entire object. */ while (object_length != 0) { - + /* If this is the first packet, we have to take into account the header. */ if (object_offset == 0) { - + /* Calculate the maximum length for the first packet. */ - object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE - - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - + object_length_demanded = UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH - + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + /* Can we get that much from the application ? */ if (object_length_demanded > object_length) - + /* We ask too much. */ object_length_demanded = object_length; - + /* Obtain some data from the application. */ - status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, - object_offset, - object_length_demanded, - &object_length_received); - + status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, + object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + object_offset, + object_length_demanded, + &object_length_received); + /* Check status, if we have a problem, we abort. */ if (status != UX_SUCCESS) { - + /* We need to inform the host of an error. */ - status = UX_ERROR; break; } else - { + { + + /* Do some sanity check. */ + if (object_length < object_length_received) + { + + /* We have an overflow. Do not proceed. */ + status = UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR; + break; + } + /* Adjust the length of the object. */ object_length -= object_length_received; - + /* Adjust the offset within the object data. */ object_offset += object_length_received; - + /* Adjust the length to be sent. */ object_length_received += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - - } - + } } else - { + { /* Calculate the maximum length for the first packet. */ - object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE; - + object_length_demanded = UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH; + /* Can we get that much from the application ? */ if (object_length_demanded > object_length) - + /* We ask too much. */ object_length_demanded = object_length; - + /* Obtain some data from the application. */ status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data, object_offset, object_length_demanded, &object_length_received); - - - + /* Check status, if we have a problem, we abort. */ if (status != UX_SUCCESS) { - + /* We need to inform the host of an error. */ - status = UX_ERROR; break; - } - else { - + + /* Do some sanity check. */ + if (object_length < object_length_received) + { + + /* We have an overflow. Do not proceed. */ + status = UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR; + break; + } + /* Adjust the length of the object. */ object_length -= object_length_received; + /* Adjust the offset within the object data. */ object_offset += object_length_received; - } - } - - /* Check if it is the last transfer. */ - if (object_length > 0) - /* Not the last transfer, just send the object data to the host. */ - status = _ux_device_stack_transfer_request(transfer_request, object_length_received, object_length_received); + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } - else + /* Not do transfer, just send the object data to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, + object_length_received, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); - /* It's the last transfer, we need to send a ZLP if the last packet is a full packet. */ - status = _ux_device_stack_transfer_request(transfer_request, object_length_received, 0); + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } /* Check for the status. We may have had a request to cancel the transaction from the host. */ if (status != UX_SUCCESS) { - + /* Check the completion code for transfer abort from the host. */ if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_ABORT) { - + /* Do not proceed. */ return(UX_ERROR); - - } - + } else - { - + /* We need to inform the host of an error. */ - status = UX_ERROR; + status = UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR; break; - } } - else - { - /* Do some sanity check. */ - if (total_length < object_length_received) - { - /* We have an overflow. Do not proceed. */ - status = UX_ERROR; - break; - - } - - - /* Update the total length to be sent. */ total_length -= object_length_received; - } } - /* Now we return a response with success. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); - + /* Now we return a response. */ + if (status == UX_SUCCESS) + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); } /* Check if status is OK. */ if (status != UX_SUCCESS) - - /* We need to stall the bulk in pipe. This is the method used by Pima devices to + { + + /* We need to stall the bulk in pipe. This is the method used by Pima devices to cancel a transaction. */ _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_in_endpoint); - + } + /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c index 1411b0bc..c30ad157 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_data_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* improved cancel flow, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_data_send(UX_SLAVE_CLASS_PIMA *pima) @@ -96,6 +100,9 @@ ULONG total_length; if (status == UX_SUCCESS) { + /* Data phase (Bulk OUT). */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_DATA_OUT; + /* Set the object length. */ object_length = object -> ux_device_class_pima_object_compressed_size; @@ -116,7 +123,14 @@ ULONG total_length; { /* Get a data payload. */ - status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE); + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); + + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } /* Check for the status. We may have had a request to cancel the transaction from the host. */ if (status != UX_SUCCESS) @@ -188,8 +202,9 @@ ULONG total_length; { /* Do some sanity check. */ - if (object_length < (transfer_length - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE)) + if (object_length < transfer_length) { + /* We have an overflow. Do not proceed. */ status = UX_ERROR; break; @@ -222,6 +237,13 @@ ULONG total_length; } } + + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } } } diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c b/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c index e70f838a..34514a3c 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_delete PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,9 +69,12 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ -UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) +UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle, ULONG object_format) { UINT status; @@ -79,22 +82,19 @@ UINT status; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DELETE, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - /* Invoke the application callback function. */ - status = pima -> ux_device_class_pima_object_delete(pima, object_handle); - - /* Check for error. */ - if (status != UX_SUCCESS) + if (object_format == 0) - /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE, 0, 0, 0, 0); - + /* Invoke the application callback function. */ + status = pima -> ux_device_class_pima_object_delete(pima, object_handle); else - /* We return a response with success. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + /* Not supported. */ + status = UX_DEVICE_CLASS_PIMA_RC_FORMAT_UNSUPPORTED; + + /* Response status. */ + status = _ux_device_class_pima_response_send(pima, (status == UX_SUCCESS) ? + UX_DEVICE_CLASS_PIMA_RC_OK : status, 0, 0, 0, 0); /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c index d4a707b8..76a997cc 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_handles_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_handles_send(UX_SLAVE_CLASS_PIMA *pima, @@ -119,7 +122,7 @@ UCHAR *object_handles_array; if (status != UX_SUCCESS) /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_FORMAT_CODE, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); else { diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c index df22e7b4..11331d4b 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_info_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) @@ -101,7 +104,7 @@ ULONG keywords_length; if (status != UX_SUCCESS) /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); else { @@ -200,5 +203,3 @@ ULONG keywords_length; /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c index 25a7de6c..1d10e74e 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_info_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id, ULONG parent_object_handle) @@ -101,8 +104,8 @@ ULONG object_handle; object_info = transfer_request -> ux_slave_transfer_request_data_pointer; /* Get the data payload. */ - status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE, - UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE); + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH, + UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); /* Check if there was an error. If so, stall the endpoint. */ if (status != UX_SUCCESS) @@ -222,8 +225,9 @@ ULONG object_handle; status = pima -> ux_device_class_pima_object_info_send(pima, object, storage_id, parent_object_handle, &object_handle); /* Now we return a response with success. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 3, pima -> ux_device_class_pima_storage_id, - parent_object_handle, object_handle); + status = (status == UX_SUCCESS) ? UX_DEVICE_CLASS_PIMA_RC_OK : status; + _ux_device_class_pima_response_send(pima, status, 3, pima -> ux_device_class_pima_storage_id, + object -> ux_device_class_pima_object_parent_object, object_handle); /* Store the object handle. It will be used for the OBJECT_SEND command. */ pima -> ux_device_class_pima_current_object_handle = object_handle; diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c index f5d84467..20075e91 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_prop_desc_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,10 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* passed max length to app, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, @@ -116,6 +120,7 @@ UCHAR *object_props_desc_end; pima -> ux_device_class_pima_transaction_id); /* Call the application to retrieve the property description dataset. */ + object_prop_dataset_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD; status = pima -> ux_device_class_pima_object_prop_desc_get(pima, object_property, object_format_code, &object_prop_dataset, &object_prop_dataset_length); /* See if we have the right format code and object property. */ @@ -157,14 +162,14 @@ UCHAR *object_props_desc_end; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); /* Report the error. */ - status = UX_MEMORY_INSUFFICIENT; + status = UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR; } } /* We get here when we did not find the object format code or the dataset was too large. */ /* Now we return a response with error code. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OBJECT_PROP_NOT_SUPPORTED, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); /* Return completion status. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c index 081d2ac3..917de74f 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_prop_value_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,6 +80,10 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* passed max length to app, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, @@ -119,13 +123,14 @@ ULONG object_property_value_length; pima -> ux_device_class_pima_transaction_id); /* Ask the application to retrieve for us the object prop value. */ + object_property_value_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD; status = pima -> ux_device_class_pima_object_prop_value_get(pima, object_handle, object_property_code, &object_property_value, &object_property_value_length); /* Result should always be OK, but to be sure .... */ if (status != UX_SUCCESS) /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); else { diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c index f0410213..8920932f 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_props_supported_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_props_supported_get(UX_SLAVE_CLASS_PIMA *pima, @@ -128,6 +131,9 @@ USHORT *object_props_list_pointer; /* Add the header size. */ object_props_list_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + /* Sanity check of buffer length. */ + UX_ASSERT(object_props_list_length <= UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); + /* Fill in the size of the response header. */ _ux_utility_long_put(object_props_list + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, object_props_list_length); diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c index 3162dca0..a3cf39cd 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_references_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,10 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* passed max length to app, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_references_get(UX_SLAVE_CLASS_PIMA *pima, @@ -115,13 +119,14 @@ ULONG object_references_length; pima -> ux_device_class_pima_transaction_id); /* Ask the application to retrieve for us the object references. */ + object_references_length = UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD; status = pima -> ux_device_class_pima_object_references_get(pima, object_handle, &object_references, &object_references_length); /* Result should always be OK, but to be sure .... */ if (status != UX_SUCCESS) /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); else { diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c b/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c index b2c8761d..b3c835f3 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_object_references_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_object_references_set(UX_SLAVE_CLASS_PIMA *pima, @@ -128,7 +131,8 @@ ULONG object_references_length; status = pima -> ux_device_class_pima_object_references_set(pima, object_handle, object_references, object_references_length); /* Now we return a response with success. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + status = (status == UX_SUCCESS) ? UX_DEVICE_CLASS_PIMA_RC_OK : status; + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); } else diff --git a/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c b/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c index f0449cac..95ef1d27 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_objects_number_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated status handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_objects_number_send(UX_SLAVE_CLASS_PIMA *pima, @@ -90,7 +93,7 @@ ULONG object_number; if (status != UX_SUCCESS) /* We return an error. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); else diff --git a/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c b/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c index 3a59fd6c..400fc9fd 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_partial_object_data_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,11 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved cancel flow, */ +/* updated status handling, */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_partial_object_data_get(UX_SLAVE_CLASS_PIMA *pima, @@ -180,26 +185,23 @@ ULONG object_bytes_sent; if (status != UX_SUCCESS) { - /* We need to inform the host of an error. */ - status = UX_ERROR; break; } else { + /* Adjust the length of the object. */ object_length -= object_length_received; /* Adjust the length to be sent. */ object_length_transfer = object_length_received + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; - } - } else { /* Calculate the maximum length for the first packet. */ - object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE; + object_length_demanded = UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH; /* Can we get that much from the application ? */ if (object_length_demanded > total_length) @@ -217,32 +219,35 @@ ULONG object_bytes_sent; { /* We need to inform the host of an error. */ - status = UX_ERROR; break; - } - else { + /* Adjust the length of the object. */ object_length -= object_length_received; /* Adjust the length to be sent. */ object_length_transfer = object_length_received; } - } - - /* Check if it is the last transfer. */ - if (object_length_transfer != total_length) - /* Not the last transfer, just send the object data to the host. */ - status = _ux_device_stack_transfer_request(transfer_request, object_length_transfer, object_length_transfer); + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } - else + /* Send the object data to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, object_length_transfer, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH); - /* It's the last transfer, we need to send a ZLP if the last packet is a full packet. */ - status = _ux_device_stack_transfer_request(transfer_request, object_length_transfer, 0); + /* It's canceled, do not proceed. */ + if (pima -> ux_device_class_pima_state == UX_DEVICE_CLASS_PIMA_PHASE_IDLE) + { + pima -> ux_device_class_pima_device_status = UX_DEVICE_CLASS_PIMA_RC_OK; + return(UX_ERROR); + } /* Check for the status. We may have had a request to cancel the transaction from the host. */ if (status != UX_SUCCESS) @@ -254,31 +259,25 @@ ULONG object_bytes_sent; /* Do not proceed. */ return(UX_ERROR); - } - else - { /* We need to inform the host of an error. */ - status = UX_ERROR; + status = UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR; break; - } } - else - { /* Do some sanity check. */ if (total_length < object_length_received) { + /* We have an overflow. Do not proceed. */ status = UX_ERROR; break; - } /* Adjust the offset within the object data. */ @@ -286,13 +285,11 @@ ULONG object_bytes_sent; /* Update the total length to be sent. */ total_length -= object_length_transfer; - } - } + /* Now we return a response with success. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 1, object_bytes_sent, 0, 0); - } /* Check if status is OK. */ @@ -305,5 +302,3 @@ ULONG object_bytes_sent; /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_response_send.c b/common/usbx_device_classes/src/ux_device_class_pima_response_send.c index d4855d50..1e3a0118 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_response_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_response_send.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_response_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* updated command phase, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_response_send(UX_SLAVE_CLASS_PIMA *pima, ULONG response_code, @@ -134,6 +137,9 @@ ULONG header_size; } + /* Set phase to response. */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_RESPONSE; + /* Send the response block. */ status = _ux_device_stack_transfer_request(transfer_request, header_size, 0); diff --git a/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c b/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c index 635c99e6..adef1c1b 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c @@ -30,12 +30,18 @@ #include "ux_device_stack.h" +#if UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH < UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + \ + 4 + \ + (4 * UX_DEVICE_CLASS_PIMA_MAX_STORAGE_IDS) +#error UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH too small +#endif + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_storage_id_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_storage_id_send(UX_SLAVE_CLASS_PIMA *pima) @@ -123,5 +132,3 @@ UCHAR *storage_id; /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c b/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c index 60799e96..ebf6ce0f 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_storage_info_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved sanity checks, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_storage_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id) @@ -149,7 +152,12 @@ UCHAR *storage_info_pointer; /* Fill in the free space in image. */ _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_IMAGE, pima -> ux_device_class_pima_storage_free_space_image); - + + /* Sanity check for buffer length. */ + UX_ASSERT(UX_DEVICE_CLASS_PIMA_STORAGE_FREE_STORAGE_DESCRIPTION + 2 + + _ux_utility_string_length_get(pima -> ux_device_class_pima_storage_description) * 2 + + _ux_utility_string_length_get(pima -> ux_device_class_pima_storage_volume_label) * 2); + /* Fill in the storage description string. */ _ux_utility_string_to_unicode(pima -> ux_device_class_pima_storage_description, storage_info_pointer); @@ -179,5 +187,3 @@ UCHAR *storage_info_pointer; /* Return completion status. */ return(status); } - - diff --git a/common/usbx_device_classes/src/ux_device_class_pima_thread.c b/common/usbx_device_classes/src/ux_device_class_pima_thread.c index ed507057..a54b1682 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,9 +57,9 @@ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_device_stack_endpoint_stall Stall endpoint */ /* _ux_utility_memory_allocate Allocate memory */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_thread_create Create thread */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_semaphore_create Create semaphore */ +/* _ux_device_thread_create Create thread */ +/* _ux_device_thread_suspend Suspend thread */ /* _ux_utility_short_get Get 16-bit value */ /* _ux_utility_long_get Get 32-bit value */ /* _ux_device_class_pima_device_info_send */ @@ -115,6 +115,11 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* updated phase states, */ +/* refined internal function, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_pima_thread(ULONG pima_class) @@ -151,7 +156,7 @@ UINT status; } /* Allocate a semaphore to this thread. */ - status = _ux_utility_semaphore_create(&pima -> ux_device_class_pima_interrupt_thread_semaphore, + status = _ux_device_semaphore_create(&pima -> ux_device_class_pima_interrupt_thread_semaphore, "ux_device_class_interrupt_thread_semaphore", 0); /* Check completion status. */ @@ -164,7 +169,7 @@ UINT status; /* The Pima device class needs 2 threads, one is activated by default for the command\response and one needs to be created here for the interrupt pipe event. */ - status = _ux_utility_thread_create(&pima -> ux_device_class_pima_interrupt_thread, "ux_slave_class_thread_pima_interrupt", + status = _ux_device_thread_create(&pima -> ux_device_class_pima_interrupt_thread, "ux_slave_class_thread_pima_interrupt", _ux_device_class_pima_interrupt_thread, (ULONG) (ALIGN_TYPE) pima, (VOID *) pima -> ux_device_class_pima_interrupt_thread_stack, UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -195,6 +200,9 @@ UINT status; while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) { + /* Phase idle. */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_IDLE; + /* Send the request to the device controller. */ status = _ux_device_stack_transfer_request(transfer_request, 64, 64); @@ -205,7 +213,6 @@ UINT status; /* Obtain the buffer address containing the PIMA command. */ pima_command = transfer_request -> ux_slave_transfer_request_data_pointer; - /* Check to make sure we have a command block. */ if (_ux_utility_short_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_TYPE) == UX_DEVICE_CLASS_PIMA_CT_COMMAND_BLOCK) { @@ -226,6 +233,9 @@ UINT status; /* Retrieve the parameter 3. */ pima_parameter_3 = _ux_utility_long_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_3); + /* Phase command. */ + pima -> ux_device_class_pima_state = UX_DEVICE_CLASS_PIMA_PHASE_COMMAND; + /* We check first if this is a GET_DEVICE_INFO as this is the only command which does not require a session to be opened. */ @@ -238,34 +248,48 @@ UINT status; status = _ux_device_class_pima_device_info_send(pima); break; - case UX_DEVICE_CLASS_PIMA_OC_OPEN_SESSION : + /* If the first parameter is 0x00000000, + the operation should fail with a response of Invalid_Parameter. + If a session is already open, and the device does not support multiple sessions, + the response Session_Already_Open should be returned, + with the SessionID of the already open session as the first response parameter. + The response Session_Already_Open should also be used if the device supports multiple sessions, + but a session with that ID is already open. + If the device supports multiple sessions, and the maximum number of sessions are open, + the device should respond with Device_Busy */ + if (pima_parameter_1 == 0) + { + _ux_device_class_pima_response_send(pima, + UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + break; + } /* Check if session is already opened. */ - if (pima -> ux_device_class_pima_session_id == 0) + if (pima -> ux_device_class_pima_session_id != 0) { + _ux_device_class_pima_response_send(pima, + UX_DEVICE_CLASS_PIMA_RC_SESSION_ALREADY_OPENED, + pima -> ux_device_class_pima_session_id, 0, 0, 0); + break; + } /* Session can be opened. */ - _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); - - /* Store the session number. */ pima -> ux_device_class_pima_session_id = pima_parameter_1; - + pima -> ux_device_class_pima_transaction_id = 0; + _ux_device_class_pima_response_send(pima, + UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); break; - default : - /* Check if a session is opened. */ if (pima -> ux_device_class_pima_session_id == 0) { /* We cannot proceed since the session is not opened. */ _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_SESSION_NOT_OPEN, 0, 0, 0, 0); - } - else { @@ -280,8 +304,8 @@ UINT status; /* Session is now closed. */ pima -> ux_device_class_pima_session_id = 0; + break; - break; case UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_IDS : /* Return the array of storage IDs to the host. In this version, we support @@ -325,7 +349,7 @@ UINT status; case UX_DEVICE_CLASS_PIMA_OC_DELETE_OBJECT : /* Delete one or more objects. */ - status = _ux_device_class_pima_object_delete(pima, pima_parameter_1); + status = _ux_device_class_pima_object_delete(pima, pima_parameter_1, pima_parameter_2); break; case UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT_INFO : @@ -448,7 +472,6 @@ UINT status; } } - } /* Check error code. */ if (status != UX_SUCCESS) @@ -464,7 +487,7 @@ UINT status; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + _ux_device_thread_suspend(&class -> ux_slave_class_thread); } } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_activate.c b/common/usbx_device_classes/src/ux_device_class_printer_activate.c new file mode 100644 index 00000000..dcc90752 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_activate.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_activate PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB Printer device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to printer command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_printer_instance_deactivate) */ +/* Notify activation */ +/* */ +/* CALLED BY */ +/* */ +/* Device Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_DEVICE_CLASS_PRINTER *printer; +UX_SLAVE_CLASS *printer_class; +UX_SLAVE_ENDPOINT *endpoint; + + /* Get the class container. */ + printer_class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + printer = (UX_DEVICE_CLASS_PRINTER *) printer_class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)printer; + + /* Now the opposite, store the interface in the class instance. */ + printer -> ux_device_class_printer_interface = interface; + + /* Save endpoints for future use. */ + printer -> ux_device_class_printer_endpoint_in = UX_NULL; + printer -> ux_device_class_printer_endpoint_out = UX_NULL; + endpoint = interface -> ux_slave_interface_first_endpoint; + while(endpoint) + { + if (endpoint -> ux_slave_endpoint_descriptor.bmAttributes == UX_BULK_ENDPOINT) + { + if (endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_IN) + { + printer -> ux_device_class_printer_endpoint_in = endpoint; + if (printer -> ux_device_class_printer_endpoint_out) + break; + } + else + { + printer -> ux_device_class_printer_endpoint_out = endpoint; + if (printer -> ux_device_class_printer_endpoint_in) + break; + } + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Check error, there must be Bulk OUT. */ + if (printer -> ux_device_class_printer_endpoint_out == UX_NULL) + return(UX_DESCRIPTOR_CORRUPTED); + + /* Initialize port status. + Benign status of "Paper Not Empty", "Selected", and "No Error". */ + printer -> ux_device_class_printer_port_status = UX_DEVICE_CLASS_PRINTER_SELECT | + UX_DEVICE_CLASS_PRINTER_NOT_ERROR; + + /* If there is a activate function call it. */ + if (printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_activate != UX_NULL) + { + /* Invoke the application. */ + printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_activate(printer); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_ACTIVATE, printer, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, printer, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_printer_control_request.c b/common/usbx_device_classes/src/ux_device_class_printer_control_request.c new file mode 100644 index 00000000..3a424f19 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_control_request.c @@ -0,0 +1,264 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_control_request PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the requests sent by the host on the control */ +/* endpoint with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_printer_soft_reset) Notify a software reset */ +/* _ux_device_class_printer_soft_reset Performs software reset */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_short_get Get short value from buffer */ +/* _ux_utility_short_get_big_endian Get big endian short value */ +/* */ +/* CALLED BY */ +/* */ +/* Device Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ +UX_DEVICE_CLASS_PRINTER *printer; +UX_SLAVE_CLASS *printer_class; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +ULONG request; +ULONG value; +ULONG request_length; +ULONG length; +UCHAR *buffer; +UCHAR index_low; +UCHAR *descriptor; +ULONG descriptor_length; +ULONG index; +UCHAR found; + + /* Get the class container. */ + printer_class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + printer = (UX_DEVICE_CLASS_PRINTER *) printer_class -> ux_slave_class_instance; + + /* Get the interface. */ + interface = printer_class -> ux_slave_class_interface; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + + /* Extract all necessary fields of the value. */ + value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + index_low = transfer_request -> ux_slave_transfer_request_setup[UX_SETUP_INDEX]; + + /* Pickup the request length. */ + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* Get buffer to fill. */ + buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + case UX_DEVICE_CLASS_PRINTER_GET_DEVICE_ID: + + /* Sanity check + - wValue == config index + - wIndex_high == interface (already checked before entry, index of + interface should equal to interface number) + - wIndex_low == alternate */ + if (index_low != (UCHAR)interface -> ux_slave_interface_descriptor.bAlternateSetting) + return(UX_ERROR); + + /* Check config index. */ + descriptor = _ux_system_slave -> ux_system_slave_device_framework; + length = _ux_system_slave->ux_system_slave_device_framework_length; + index = 0; + found = 0; + while(length) + { + + /* By default use bLength @ 0. */ + descriptor_length = descriptor[0]; + + /* Check bDescriptorType @ 1. */ + switch(descriptor[1]) + { + case UX_CONFIGURATION_DESCRIPTOR_ITEM: + + /* It's configuration requested? */ + if (index == value) + { + + /* Check if bConfigurationValue @ 5 is as expected. */ + if ((UCHAR)printer_class -> ux_slave_class_configuration_number != descriptor[5]) + return(UX_ERROR); + + /* Find the configuration. */ + found = 1; + break; + } + + /* Target to next configuration index. */ + index ++; + + /* Use wTotalLength @ 2. */ + descriptor_length = _ux_utility_short_get(descriptor + 2); + break; + + default: + break; + } + + /* Break if found. */ + if (found) + break; + + /* Descriptor broken check. */ + if (descriptor_length < 2 || + descriptor_length > length) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Next descriptor. */ + descriptor += descriptor_length; + length -= descriptor_length; + } + + /* Request parameter not expected if not found. */ + if (!found) + return(UX_ERROR); + + /* Length of data (first two bytes in big endian). */ + length = _ux_utility_short_get_big_endian(printer -> + ux_device_class_printer_parameter.ux_device_class_printer_device_id); + + /* Prepare device ID to send. */ + if (length) + { + + /* Sanity check. */ + if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + return(UX_BUFFER_OVERFLOW); + } + + /* Copy data. */ + _ux_utility_memory_copy(buffer, printer -> + ux_device_class_printer_parameter.ux_device_class_printer_device_id, + length); /* Use case of memcpy is verified. */ + } + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Transfer. */ + _ux_device_stack_transfer_request(transfer_request, length, request_length); + break ; + + case UX_DEVICE_CLASS_PRINTER_GET_PORT_STATUS: + + /* Sanity check. */ + if (request_length < 1) + return(UX_ERROR); + + /* Fill status byte. */ + *buffer = (UCHAR)printer -> ux_device_class_printer_port_status; + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Perform the data transfer. */ + _ux_device_stack_transfer_request(transfer_request, 1, request_length); + break; + + case UX_DEVICE_CLASS_PRINTER_SOFT_RESET: + _ux_device_class_printer_soft_reset(printer); + + /* If there is a soft reset function call it. */ + if (printer -> ux_device_class_printer_parameter. + ux_device_class_printer_soft_reset != UX_NULL) + { + + /* Invoke the application callback. */ + printer -> ux_device_class_printer_parameter. + ux_device_class_printer_soft_reset(printer); + } + break; + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_printer_deactivate.c b/common/usbx_device_classes/src/ux_device_class_printer_deactivate.c new file mode 100644 index 00000000..0bdbef7e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_deactivate.c @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_deactivate PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the printer class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_printer_instance_deactivate) */ +/* Notify deactivation */ +/* _ux_device_class_printer_soft_reset Performs software reset */ +/* */ +/* CALLED BY */ +/* */ +/* Device Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_PRINTER *printer; +UX_SLAVE_CLASS *printer_class; + + /* Get the class container. */ + printer_class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + printer = (UX_DEVICE_CLASS_PRINTER *) printer_class -> ux_slave_class_instance; + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_class_printer_soft_reset(printer); + + /* Endpoints not ready. */ + printer -> ux_device_class_printer_endpoint_in = UX_NULL; + printer -> ux_device_class_printer_endpoint_out = UX_NULL; + + /* Reset port status. */ + printer -> ux_device_class_printer_port_status = 0; + + /* If there is a deactivate function call it. */ + if (printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_deactivate != UX_NULL) + { + + /* Invoke the application. */ + printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_deactivate(printer); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_DEACTIVATE, printer, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(printer); + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_printer_entry.c b/common/usbx_device_classes/src/ux_device_class_printer_entry.c new file mode 100644 index 00000000..b4d00a2c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_entry.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_entry PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the printer class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the printer interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_printer_initialize Initialize printer class */ +/* _ux_device_class_printer_uninitialize Uninitialize printer class */ +/* _ux_device_class_printer_activate Activate printer class */ +/* _ux_device_class_printer_deactivate Deactivate printer class */ +/* _ux_device_class_printer_control_request */ +/* Request control */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the Printer class. */ + status = _ux_device_class_printer_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the Printer class. */ + status = _ux_device_class_printer_uninitialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_PRINTER_CLASS && + command -> ux_slave_class_command_subclass == UX_DEVICE_CLASS_PRINTER_SUBCLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the printer thread needs to be activated. */ + status = _ux_device_class_printer_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the printer thread canceled. */ + status = _ux_device_class_printer_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_printer_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} 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 new file mode 100644 index 00000000..db3579f3 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_initialize.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_initialize PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB Printer device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to printer command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_mutex_create Create mutex */ +/* _ux_utility_mutex_delete Delete mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_PRINTER *printer; +UX_DEVICE_CLASS_PRINTER_PARAMETER *printer_parameter; +UX_SLAVE_CLASS *printer_class; +UINT status; + + /* Get the class container. */ + printer_class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device printer class. */ + printer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DEVICE_CLASS_PRINTER)); + + /* Check for successful allocation. */ + if (printer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the Printer instance inside the Printer container. */ + printer_class -> ux_slave_class_instance = (VOID *) printer; + + /* Get the pointer to the application parameters for the printer class. */ + printer_parameter = command -> ux_slave_class_command_parameter; + + /* Store the start and stop signals if needed by the application. */ + printer -> ux_device_class_printer_parameter.ux_device_class_printer_device_id = printer_parameter -> ux_device_class_printer_device_id; + printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_activate = printer_parameter -> ux_device_class_printer_instance_activate; + 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; + + /* 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"); + + /* Check Mutex creation error. */ + if(status != UX_SUCCESS) + { + + /* Free the resources. */ + _ux_utility_memory_free(printer); + + /* Return fatal error. */ + return(UX_MUTEX_ERROR); + } + + /* Out Mutex. */ + status = _ux_utility_mutex_create(&printer -> ux_device_class_printer_endpoint_out_mutex, "ux_device_class_printer_out_mutex"); + + /* Check Mutex creation error. */ + if(status != UX_SUCCESS) + { + + /* Delete the endpoint IN mutex. */ + _ux_utility_mutex_delete(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* Free the resources. */ + _ux_utility_memory_free(printer); + + /* Return fatal error. */ + return(UX_MUTEX_ERROR); + } + + /* Reset port status. */ + printer -> ux_device_class_printer_port_status = 0; + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_printer_ioctl.c b/common/usbx_device_classes/src/ux_device_class_printer_ioctl.c new file mode 100644 index 00000000..c8599304 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_ioctl.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_ioctl PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs certain functions on the printer instance */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; + + + /* Default to success. */ + status = UX_SUCCESS; + + /* The command request will tell us what we need to do here. */ + switch (ioctl_function) + { + case UX_DEVICE_CLASS_PRINTER_IOCTL_PORT_STATUS_SET: + + /* Set port status. */ + printer -> ux_device_class_printer_port_status = (ULONG)(UCHAR)(ALIGN_TYPE)parameter; + break; + + case UX_DEVICE_CLASS_PRINTER_IOCTL_READ_TIMEOUT_SET: + + /* Set endpoint transfer timeout. */ + endpoint = printer -> ux_device_class_printer_endpoint_out; + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + transfer -> ux_slave_transfer_request_timeout = (ULONG)(ALIGN_TYPE)parameter; + break; + + case UX_DEVICE_CLASS_PRINTER_IOCTL_WRITE_TIMEOUT_SET: + + /* Set endpoint transfer timeout (if exist). */ + endpoint = printer -> ux_device_class_printer_endpoint_in; + if (endpoint != UX_NULL) + { + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + transfer -> ux_slave_transfer_request_timeout = (ULONG)(ALIGN_TYPE)parameter; + } + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + break; + } + + /* Return status to caller. */ + return(status); + +} diff --git a/common/usbx_device_classes/src/ux_device_class_printer_read.c b/common/usbx_device_classes/src/ux_device_class_printer_read.c new file mode 100644 index 00000000..cf8cf0f5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_read.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_read PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the Printer class. */ +/* */ +/* 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 */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_mutex_off Release mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_read(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 status= UX_SUCCESS; +ULONG local_requested_length; + + /* 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. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Locate the endpoint. */ + endpoint = printer -> ux_device_class_printer_endpoint_out; + + /* Protect this thread. */ + _ux_utility_mutex_on(&printer -> ux_device_class_printer_endpoint_out_mutex); + + /* All Printer reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + + /* We have too much to transfer. */ + local_requested_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, + local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(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. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + /* Is this a short packet or a ZLP indicating we are done with this transfer ? */ + if (transfer_request -> ux_slave_transfer_request_actual_length < + endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + { + + /* We are done. */ + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex); + + /* Return with success. */ + return(UX_SUCCESS); + } + } + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex); + + /* We got an error. */ + return(status); + } + } + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex); + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); +} 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 new file mode 100644 index 00000000..fa96f3b7 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_soft_reset PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function Perform Soft Reset on the Printer class. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort transfers on endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Device Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_printer_soft_reset(UX_DEVICE_CLASS_PRINTER *printer) +{ + +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); + + /* 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); + } +} 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 new file mode 100644 index 00000000..9c9483af --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_uninitialize PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitialize the printer class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_delete Delete Mutex */ +/* _ux_utility_memory_free Free used local memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_PRINTER *printer; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + printer = (UX_DEVICE_CLASS_PRINTER *) class -> ux_slave_class_instance; + + /* Sanity check. */ + if (printer != UX_NULL) + { + + /* Delete the IN endpoint mutex. */ + _ux_utility_mutex_delete(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* Out Mutex. */ + _ux_utility_mutex_delete(&printer -> ux_device_class_printer_endpoint_out_mutex); + + /* Free the resources. */ + _ux_utility_memory_free(printer); + } + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_printer_write.c b/common/usbx_device_classes/src/ux_device_class_printer_write.c new file mode 100644 index 00000000..b553bd0a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_write.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* 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" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_write PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the Printer class. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write */ +/* actual_length Pointer to save number of */ +/* bytes written */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_mutex_on Take Mutex */ +/* _ux_utility_mutex_off Release Mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_write(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 local_requested_length; +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. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Locate the endpoints. */ + endpoint = printer -> ux_device_class_printer_endpoint_in; + + /* Check if it's available. */ + if (endpoint == UX_NULL) + return(UX_FUNCTION_NOT_SUPPORTED); + + /* Protect this thread. */ + _ux_utility_mutex_on(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Check if the application forces a 0 length packet. */ + if (requested_length == 0) + { + + /* Send the request for 0 byte packet to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, 0, 0); + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* Return the status. */ + return(status); + } + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && + requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + local_requested_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* 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, + buffer, local_requested_length); /* Use case of memcpy is verified. */ + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, + local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* Next buffer address. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + } + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* We had an error, abort. */ + return(status); + } + } + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&printer -> ux_device_class_printer_endpoint_in_mutex); + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); +} diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_activate.c b/common/usbx_device_classes/src/ux_device_class_rndis_activate.c index 5f226831..7cf32009 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,7 +54,7 @@ /* */ /* _ux_network_driver_activate Activate NetX USB interface */ /* _ux_utility_memory_set Set memory */ -/* _ux_utility_thread_resume Resume thread */ +/* _ux_device_thread_resume Resume thread */ /* */ /* CALLED BY */ /* */ @@ -69,6 +69,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_rndis_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -182,9 +185,9 @@ ULONG physical_address_lsw; ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */ /* Resume the endpoint threads. */ - _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_interrupt_thread); - _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_bulkout_thread); - _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_bulkin_thread); + _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_interrupt_thread); + _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_bulkout_thread); + _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_bulkin_thread); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) 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 eb960a01..096c99fc 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 @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkin_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkin_thread(ULONG rndis_class) @@ -223,7 +226,7 @@ ULONG transfer_length; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_bulkin_thread); + _ux_device_thread_suspend(&rndis -> ux_slave_class_rndis_bulkin_thread); } } 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 0dde156e..8148c80c 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 @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkout_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,7 +58,7 @@ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_network_driver_packet_received Process received packet */ /* _ux_utility_long_get Get 32-bit value */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* nx_packet_allocate Allocate NetX packet */ /* nx_packet_release Release NetX packet */ /* */ @@ -76,6 +76,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkout_thread(ULONG rndis_class) @@ -209,7 +212,7 @@ ULONG packet_payload; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_bulkout_thread); + _ux_device_thread_suspend(&rndis -> ux_slave_class_rndis_bulkout_thread); } } 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 54aec46a..42bbed80 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 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -104,10 +104,10 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* _ux_utility_event_flags_delete Delete Flag group */ /* _ux_utility_mutex_create Create mutex */ /* _ux_utility_mutex_delete Delete mutex */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ -/* _ux_utility_thread_create Create thread */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_semaphore_create Create semaphore */ +/* _ux_device_semaphore_delete Delete semaphore */ +/* _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 */ /* */ @@ -126,6 +126,9 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* refer to TX symbols instead */ /* of using them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_rndis_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -199,7 +202,7 @@ UINT status; does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_interrupt_thread , "ux_slave_class_rndis_interrupt_thread", + status = _ux_device_thread_create(&rndis -> ux_slave_class_rndis_interrupt_thread , "ux_slave_class_rndis_interrupt_thread", _ux_device_class_rndis_interrupt_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_interrupt_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -228,7 +231,7 @@ UINT status; does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_bulkout_thread , "ux_slave_class_rndis_bulkout_thread", + status = _ux_device_thread_create(&rndis -> ux_slave_class_rndis_bulkout_thread , "ux_slave_class_rndis_bulkout_thread", _ux_device_class_rndis_bulkout_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_bulkout_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -257,7 +260,7 @@ UINT status; does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { - status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_bulkin_thread , "ux_slave_class_rndis_bulkin_thread", + status = _ux_device_thread_create(&rndis -> ux_slave_class_rndis_bulkin_thread , "ux_slave_class_rndis_bulkin_thread", _ux_device_class_rndis_bulkin_thread, (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_bulkin_thread_stack , UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, @@ -308,7 +311,7 @@ UINT status; /* Create a semaphore for protecting the driver entry. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&rndis -> ux_slave_class_rndis_semaphore, "ux_device_class_rndis_semaphore", 1); + status = _ux_device_semaphore_create(&rndis -> ux_slave_class_rndis_semaphore, "ux_device_class_rndis_semaphore", 1); if (status == UX_SUCCESS) /* Return success. */ @@ -322,7 +325,7 @@ UINT status; /* Delete semaphore for protecting the driver entry. */ if (rndis -> ux_slave_class_rndis_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&rndis -> ux_slave_class_rndis_semaphore); + _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) @@ -338,7 +341,7 @@ UINT status; /* Delete rndis -> ux_slave_class_rndis_bulkin_thread. */ if (rndis -> ux_slave_class_rndis_bulkin_thread.tx_thread_id != 0) - _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_bulkin_thread); + _ux_device_thread_delete(&rndis -> ux_slave_class_rndis_bulkin_thread); /* Free rndis -> ux_slave_class_rndis_bulkin_thread_stack. */ if (rndis -> ux_slave_class_rndis_bulkin_thread_stack) @@ -346,7 +349,7 @@ UINT status; /* Delete rndis -> ux_slave_class_rndis_bulkout_thread. */ if (rndis -> ux_slave_class_rndis_bulkout_thread.tx_thread_id != 0) - _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_bulkout_thread); + _ux_device_thread_delete(&rndis -> ux_slave_class_rndis_bulkout_thread); /* Free rndis -> ux_slave_class_rndis_bulkout_thread_stack. */ if (rndis -> ux_slave_class_rndis_bulkout_thread_stack) @@ -354,7 +357,7 @@ UINT status; /* Delete rndis -> ux_slave_class_rndis_interrupt_thread. */ if (rndis -> ux_slave_class_rndis_interrupt_thread.tx_thread_id != 0) - _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_interrupt_thread); + _ux_device_thread_delete(&rndis -> ux_slave_class_rndis_interrupt_thread); /* Free rndis -> ux_slave_class_rndis_interrupt_thread_stack. */ if (rndis -> ux_slave_class_rndis_interrupt_thread_stack) diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c index ad552426..11dc1a97 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_interrupt_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,7 +56,7 @@ /* */ /* _ux_device_stack_transfer_request Request transfer */ /* _ux_utility_event_flags_get Get event flags */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_interrupt_thread(ULONG rndis_class) @@ -130,7 +133,7 @@ ULONG actual_flags; } /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_interrupt_thread); + _ux_device_thread_suspend(&rndis -> ux_slave_class_rndis_interrupt_thread); } } diff --git a/common/usbx_device_classes/src/ux_device_class_storage_activate.c b/common/usbx_device_classes/src/ux_device_class_storage_activate.c index 2a45a2c6..fcb732c6 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,7 +54,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_thread_resume Resume thread */ +/* _ux_device_thread_resume Resume thread */ /* */ /* CALLED BY */ /* */ @@ -67,21 +67,28 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_activate(UX_SLAVE_CLASS_COMMAND *command) { -UINT status; +UINT status = UX_SUCCESS; UX_SLAVE_INTERFACE *interface; UX_SLAVE_CLASS_STORAGE *storage; -UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS *class_inst; +#if defined(UX_DEVICE_STANDALONE) +UX_SLAVE_ENDPOINT *endpoint; +#endif + /* Get the class container. */ - class = command -> ux_slave_class_command_class_ptr; + class_inst = command -> ux_slave_class_command_class_ptr; /* Get the class instance in the container. */ - storage = (UX_SLAVE_CLASS_STORAGE *)class -> ux_slave_class_instance; + storage = (UX_SLAVE_CLASS_STORAGE *)class_inst -> ux_slave_class_instance; /* Get the interface that owns this instance. */ interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; @@ -92,8 +99,52 @@ UX_SLAVE_CLASS *class; /* Now the opposite, store the interface in the class instance. */ storage -> ux_slave_class_storage_interface = interface; +#if !defined(UX_DEVICE_STANDALONE) + /* Resume thread. */ - status = _ux_utility_thread_resume(&class -> ux_slave_class_thread); + _ux_device_thread_resume(&class_inst -> ux_slave_class_thread); + +#else + + /* Locate the endpoints. */ + /* Check the first endpoint direction, if IN we have the correct endpoint. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + storage -> ux_device_class_storage_ep_out = endpoint; + + /* So the next endpoint has to be the IN endpoint. */ + storage -> ux_device_class_storage_ep_in = endpoint -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the IN endpoint first. */ + storage -> ux_device_class_storage_ep_in = endpoint; + + /* So the next endpoint has to be the OUT endpoint. */ + storage -> ux_device_class_storage_ep_out = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Reset states. */ + storage -> ux_device_class_storage_buffer[0] = storage -> ux_device_class_storage_ep_out -> + ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer; + storage -> ux_device_class_storage_buffer[1] = storage -> ux_device_class_storage_ep_in -> + ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer; + storage -> ux_device_class_storage_data_buffer = UX_NULL; + storage -> ux_device_class_storage_state = UX_STATE_RESET; + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + storage -> ux_device_class_storage_buffer_state[0] = UX_DEVICE_CLASS_STORAGE_BUFFER_IDLE; + storage -> ux_device_class_storage_buffer_state[1] = UX_DEVICE_CLASS_STORAGE_BUFFER_IDLE; + storage -> ux_device_class_storage_buffer_usb = 0; + storage -> ux_device_class_storage_buffer_disk = 0; + UX_SLAVE_TRANSFER_STATE_RESET(&storage -> ux_device_class_storage_ep_out -> ux_slave_endpoint_transfer_request); + UX_SLAVE_TRANSFER_STATE_RESET(&storage -> ux_device_class_storage_ep_in -> ux_slave_endpoint_transfer_request); + + status = UX_SUCCESS; +#endif /* If there is a activate function call it. */ if (storage -> ux_slave_class_storage_instance_activate != UX_NULL) diff --git a/common/usbx_device_classes/src/ux_device_class_storage_control_request.c b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c index aec76810..7b695d99 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_control_request.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_control_request PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_control_request(UX_SLAVE_CLASS_COMMAND *command) @@ -85,7 +88,9 @@ ULONG request; ULONG request_value; ULONG request_length; UX_SLAVE_CLASS_STORAGE *storage; +#if !defined(UX_DEVICE_STANDALONE) UX_SLAVE_INTERFACE *interface; +#endif UX_SLAVE_ENDPOINT *endpoint_in; UX_SLAVE_ENDPOINT *endpoint_out; @@ -121,6 +126,11 @@ UX_SLAVE_ENDPOINT *endpoint_out; if (request_length != 0) return(UX_ERROR); +#if defined(UX_DEVICE_STANDALONE) + endpoint_in = storage -> ux_device_class_storage_ep_in; + endpoint_out = storage -> ux_device_class_storage_ep_out; +#else + /* We need the interface to the class. */ interface = storage -> ux_slave_class_storage_interface; @@ -143,6 +153,7 @@ UX_SLAVE_ENDPOINT *endpoint_out; /* We found the endpoint IN first, so next endpoint is OUT. */ endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; } +#endif /* First cancel any transfer on the endpoint OUT, from the host. */ transfer_request = &endpoint_out -> ux_slave_endpoint_transfer_request; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c index 2ad7ba34..6e45e1b5 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_csw_send PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -86,13 +86,16 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* improved TAG management, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_csw_send(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, UCHAR csw_status) { -UINT status; +UINT status = UX_SUCCESS; UX_SLAVE_TRANSFER *transfer_request; UCHAR *csw_buffer; @@ -100,6 +103,15 @@ UCHAR *csw_buffer; UX_PARAMETER_NOT_USED(csw_status); UX_PARAMETER_NOT_USED(lun); +#if defined(UX_DEVICE_STANDALONE) + + /* Reset transfer request buffer pointers. */ + storage -> ux_device_class_storage_ep_out -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer = storage -> ux_device_class_storage_buffer[0]; + storage -> ux_device_class_storage_ep_in -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer = storage -> ux_device_class_storage_buffer[1]; +#endif + /* If CSW skipped, just return. */ if (UX_DEVICE_CLASS_STORAGE_CSW_SKIP(&storage -> ux_slave_class_storage_csw_status)) return(UX_SUCCESS); @@ -125,12 +137,26 @@ UCHAR *csw_buffer; /* Store the status of the previous operation. */ csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_STATUS] = (UCHAR)storage -> ux_slave_class_storage_csw_status; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (CSW). */ + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_CSW; + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_transfer = transfer_request; + + storage -> ux_device_class_storage_device_length = UX_SLAVE_CLASS_STORAGE_CSW_LENGTH; + storage -> ux_device_class_storage_data_length = UX_SLAVE_CLASS_STORAGE_CSW_LENGTH; + storage -> ux_device_class_storage_data_count = 0; + +#else + /* We may be in a special state machine condition where the endpoint is stalled waiting for a CLEAR_FEATURE. We will wait until the host clears the endpoint. The transfer_request function does that. */ /* Send the CSW back to the host. */ status = _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_CSW_LENGTH, UX_SLAVE_CLASS_STORAGE_CSW_LENGTH); +#endif /* Return completion status. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c b/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c index 15aa9535..beee747e 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,12 +67,14 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_deactivate(UX_SLAVE_CLASS_COMMAND *command) { -UX_SLAVE_INTERFACE *interface; UX_SLAVE_CLASS_STORAGE *storage; UX_SLAVE_ENDPOINT *endpoint_in; UX_SLAVE_ENDPOINT *endpoint_out; @@ -84,11 +86,20 @@ UX_SLAVE_CLASS *class; /* Get the class instance in the container. */ storage = (UX_SLAVE_CLASS_STORAGE *)class -> ux_slave_class_instance; - /* We need the interface to the class. */ - interface = storage -> ux_slave_class_storage_interface; - +#if defined(UX_DEVICE_STANDALONE) + + endpoint_in = storage -> ux_device_class_storage_ep_in; + endpoint_out = storage -> ux_device_class_storage_ep_out; + _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); + endpoint_out -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer = + storage -> ux_device_class_storage_buffer[0]; + endpoint_in -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer = + storage -> ux_device_class_storage_buffer[1]; +#else + /* Locate the endpoints. */ - endpoint_in = interface -> ux_slave_interface_first_endpoint; + endpoint_in = storage -> ux_slave_class_storage_interface -> ux_slave_interface_first_endpoint; /* Check the endpoint direction, if IN we have the correct endpoint. */ if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) @@ -110,6 +121,7 @@ UX_SLAVE_CLASS *class; /* Terminate the transactions pending on the endpoints. */ _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); +#endif /* If there is a deactivate function call it. */ if (storage -> ux_slave_class_storage_instance_deactivate != UX_NULL) diff --git a/common/usbx_device_classes/src/ux_device_class_storage_format.c b/common/usbx_device_classes/src/ux_device_class_storage_format.c index b972ae7e..f7630fbd 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_format.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_format.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_format PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* optimized command logic, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_format(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, @@ -85,9 +88,15 @@ UINT _ux_device_class_storage_format(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_FORMAT, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) +#if !defined(UX_DEVICE_STANDALONE) + /* This command is not yet supported. So Stall the endpoint. We stall the OUT endpoint because we expect the host to send parameters. */ _ux_device_stack_endpoint_stall(endpoint_out); +#else + + UX_PARAMETER_NOT_USED(endpoint_out); +#endif /* And update the REQUEST_SENSE codes. */ storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c b/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c index 09487427..5593dccd 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c @@ -302,7 +302,7 @@ UCHAR usbx_device_class_storage_configuration_active_profile[] = { /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_get_configuration PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -345,6 +345,9 @@ UCHAR usbx_device_class_storage_configuration_active_profile[] = { /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_get_configuration(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -423,11 +426,6 @@ ULONG feature; } - /* Send a data payload with the configuration profile response buffer. */ - _ux_device_stack_transfer_request(transfer_request, - allocation_length, - allocation_length); - /* Now success. */ status = UX_SUCCESS; } @@ -465,12 +463,7 @@ ULONG feature; _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, profile_pointer, allocation_length); /* Use case of memcpy is verified. */ - - /* Send a data payload with the read_capacity response buffer. */ - _ux_device_stack_transfer_request(transfer_request, - allocation_length, - allocation_length); - + /* Now success. */ status = UX_SUCCESS; @@ -485,7 +478,6 @@ ULONG feature; { /* We are either at the end of the profile or the profile is corrupted. */ - _ux_device_stack_endpoint_stall(endpoint_in); /* And update the REQUEST_SENSE codes. */ storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = @@ -514,6 +506,39 @@ ULONG feature; } } + /* Success, send data. */ + if (status == UX_SUCCESS) + { + +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = allocation_length; + storage -> ux_device_class_storage_data_length = allocation_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); +#else + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + allocation_length, + allocation_length); +#endif + + } + else + { + + /* Error, stall. */ +#if !defined(UX_DEVICE_STANDALONE) + _ux_device_stack_endpoint_stall(endpoint_in); +#endif + } + /* Return completion status. */ return(status); } diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c b/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c index 5da7514e..c4558455 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c @@ -44,7 +44,7 @@ UCHAR usbx_device_class_storage_performance[] = { /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_get_performance PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -86,6 +86,9 @@ UCHAR usbx_device_class_storage_performance[] = { /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_get_performance(UX_SLAVE_CLASS_STORAGE *storage, @@ -98,6 +101,7 @@ UINT _ux_device_class_storage_get_performance(UX_SLAVE_CLASS_STORAGE *storage, UINT status; UX_SLAVE_TRANSFER *transfer_request; ULONG performance_page; +ULONG data_length = 0; UX_PARAMETER_NOT_USED(lun); @@ -129,8 +133,7 @@ ULONG performance_page; _ux_utility_long_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer + 4, UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAYLOAD); - /* Send a data payload with the read_capacity response buffer. */ - _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH, UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH); + data_length = UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH; break; case UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE_0 : @@ -143,11 +146,31 @@ ULONG performance_page; _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer + 8, usbx_device_class_storage_performance, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH); /* Use case of memcpy is verified. */ - /* Send a data payload with the read_capacity response buffer. */ - _ux_device_stack_transfer_request(transfer_request, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8); + data_length = USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8; break; + + default: + data_length = 0; } - + +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = data_length; + storage -> ux_device_class_storage_data_length = data_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, data_length, data_length); +#endif + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; status = UX_SUCCESS; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c b/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c index 27f8eeca..ca7e5b2e 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_get_status_notification PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_get_status_notification(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -102,8 +105,11 @@ ULONG notification_class; if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_notification == UX_NULL) { +#if !defined(UX_DEVICE_STANDALONE) + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ _ux_device_stack_endpoint_stall(endpoint_in); +#endif /* And update the REQUEST_SENSE codes. */ storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = @@ -141,8 +147,11 @@ ULONG notification_class; if (status != UX_SUCCESS) { +#if !defined(UX_DEVICE_STANDALONE) + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ _ux_device_stack_endpoint_stall(endpoint_in); +#endif } else { @@ -161,11 +170,23 @@ ULONG notification_class; /* Update the notification length. */ media_notification_length += (ULONG)sizeof (USHORT); +#if !defined(UX_DEVICE_STANDALONE) /* Send a data payload with the notification buffer. */ _ux_device_stack_transfer_request(transfer_request, media_notification_length, media_notification_length); - +#else + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = media_notification_length; + storage -> ux_device_class_storage_data_length = media_notification_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); +#endif + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; status = UX_SUCCESS; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_initialize.c b/common/usbx_device_classes/src/ux_device_class_storage_initialize.c index 28554985..9e4b7aee 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_initialize.c @@ -41,7 +41,7 @@ UCHAR _ux_system_slave_class_storage_product_serial[] = "123 /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ UCHAR _ux_system_slave_class_storage_product_serial[] = "123 /* */ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_thread_create Create thread */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_create Create thread */ +/* _ux_device_thread_delete Delete thread */ /* */ /* CALLED BY */ /* */ @@ -79,17 +79,21 @@ UCHAR _ux_system_slave_class_storage_product_serial[] = "123 /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command) { -UINT status; +UINT status = UX_SUCCESS; UX_SLAVE_CLASS_STORAGE *storage; UX_SLAVE_CLASS_STORAGE_PARAMETER *storage_parameter; -UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS *class_inst; ULONG lun_index; + /* Get the pointer to the application parameters for the storage class. */ storage_parameter = command -> ux_slave_class_command_parameter; @@ -99,7 +103,7 @@ ULONG lun_index; return UX_ERROR; /* Get the class container. */ - class = command -> ux_slave_class_command_class_ptr; + class_inst = command -> ux_slave_class_command_class_ptr; /* Create an instance of the device storage class. */ storage = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_STORAGE)); @@ -108,28 +112,37 @@ ULONG lun_index; if (storage == UX_NULL) return(UX_MEMORY_INSUFFICIENT); +#if !defined(UX_DEVICE_STANDALONE) + /* Allocate some memory for the thread stack. */ - class -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + class_inst -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); /* If it's OK, create thread. */ - if (class -> ux_slave_class_thread_stack != UX_NULL) + if (class_inst -> ux_slave_class_thread_stack != UX_NULL) /* This instance needs to be running in a different thread. So start a new thread. We pass a pointer to the class to the new thread. This thread does not start until we have a instance of the class. */ - status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_storage_thread", + status = _ux_device_thread_create(&class_inst -> ux_slave_class_thread, "ux_slave_storage_thread", _ux_device_class_storage_thread, - (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, + (ULONG) (ALIGN_TYPE) class_inst, (VOID *) class_inst -> ux_slave_class_thread_stack, UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); else status = UX_MEMORY_INSUFFICIENT; +#else + + /* Save tasks run entry. */ + class_inst -> ux_slave_class_task_function = _ux_device_class_storage_tasks_run; + + status = UX_SUCCESS; +#endif /* If thread resources allocated, go on. */ if (status == UX_SUCCESS) { - UX_THREAD_EXTENSION_PTR_SET(&(class -> ux_slave_class_thread), class) + UX_THREAD_EXTENSION_PTR_SET(&(class_inst -> ux_slave_class_thread), class_inst) /* Store the number of LUN declared. */ storage -> ux_slave_class_storage_number_lun = storage_parameter -> ux_slave_class_storage_parameter_number_lun; @@ -189,17 +202,19 @@ ULONG lun_index; storage -> ux_slave_class_storage_product_serial = _ux_system_slave_class_storage_product_serial; /* Save the address of the STORAGE instance inside the STORAGE container. */ - class -> ux_slave_class_instance = (VOID *) storage; + class_inst -> ux_slave_class_instance = (VOID *) storage; return(UX_SUCCESS); } /* Free thread resources. */ - _ux_utility_thread_delete(&class -> ux_slave_class_thread); + _ux_device_thread_delete(&class_inst -> ux_slave_class_thread); } - if (class -> ux_slave_class_thread_stack != UX_NULL) - _ux_utility_memory_free(&class -> ux_slave_class_thread_stack); +#if !defined(UX_DEVICE_STANDALONE) + if (class_inst -> ux_slave_class_thread_stack != UX_NULL) + _ux_utility_memory_free(&class_inst -> ux_slave_class_thread_stack); +#endif /* Free instance. */ _ux_utility_memory_free(storage); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c index 2c5a0053..71f4e73d 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_inquiry PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_inquiry(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, @@ -102,6 +105,8 @@ UCHAR *inquiry_buffer; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_INQUIRY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) +#if !defined(UX_DEVICE_STANDALONE) + /* Check direction. */ if (storage -> ux_slave_class_storage_host_length && (storage -> ux_slave_class_storage_cbw_flags & 0x80) == 0) @@ -110,6 +115,7 @@ UCHAR *inquiry_buffer; storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; return(UX_ERROR); } +#endif /* From the SCSI Inquiry payload, get the page code. */ inquiry_page_code = *(cbwcb + UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE); @@ -190,8 +196,10 @@ UCHAR *inquiry_buffer; default: +#if !defined(UX_DEVICE_STANDALONE) /* The page code is not supported. */ _ux_device_stack_endpoint_stall(endpoint_in); +#endif /* And update the REQUEST_SENSE codes. */ storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = @@ -210,6 +218,19 @@ UCHAR *inquiry_buffer; if (status != UX_SUCCESS) return(status); +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = inquiry_length; + storage -> ux_device_class_storage_data_length = inquiry_length; + storage -> ux_device_class_storage_data_count = 0; + +#else + /* Send a data payload with the inquiry response buffer. */ if (inquiry_length) _ux_device_stack_transfer_request(transfer_request, inquiry_length, inquiry_length); @@ -219,6 +240,7 @@ UCHAR *inquiry_buffer; { _ux_device_stack_endpoint_stall(endpoint_in); } +#endif /* Return completion status. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c index 6ef4fdd7..daca0403 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_mode_select PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -92,7 +95,13 @@ UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULON /* This command is not yet supported. So Stall the endpoint. */ if (storage -> ux_slave_class_storage_host_length) { + +#if !defined(UX_DEVICE_STANDALONE) _ux_device_stack_endpoint_stall(endpoint_out); +#else + UX_PARAMETER_NOT_USED(endpoint_out); +#endif + storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length; } diff --git a/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c b/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c index cffc6cf6..138ebc36 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c @@ -65,7 +65,7 @@ UCHAR usbx_device_class_storage_mode_sense_page_cdrom[USBX_DEVICE_CLASS_STORAGE_ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_mode_sense PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -109,6 +109,9 @@ UCHAR usbx_device_class_storage_mode_sense_page_cdrom[USBX_DEVICE_CLASS_STORAGE_ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_mode_sense(UX_SLAVE_CLASS_STORAGE *storage, @@ -251,8 +254,22 @@ ULONG page_length; /* Store the write protection flag. */ *(transfer_request -> ux_slave_transfer_request_data_pointer + flags_index) = read_only_flag; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = mode_data_length; + storage -> ux_device_class_storage_data_length = mode_data_length; + storage -> ux_device_class_storage_data_count = 0; + +#else + /* Send a payload with the response buffer. */ _ux_device_stack_transfer_request(transfer_request, mode_sense_reply_length, mode_sense_reply_length); +#endif /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read.c b/common/usbx_device_classes/src/ux_device_class_storage_read.c index 08e7e1ec..0823440b 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -89,14 +92,18 @@ UINT _ux_device_class_storage_read(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, { UINT status; -UX_SLAVE_TRANSFER *transfer_request; ULONG lba; +UX_SLAVE_TRANSFER *transfer_request; ULONG total_number_blocks; -ULONG number_blocks; ULONG media_status; ULONG total_length; + +#if !defined(UX_DEVICE_STANDALONE) +ULONG number_blocks; ULONG transfer_length; ULONG done_length; +#endif + UX_PARAMETER_NOT_USED(endpoint_out); @@ -124,6 +131,48 @@ ULONG done_length; /* Default CSW to failed. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; +#if defined(UX_DEVICE_STANDALONE) + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = media_status; + + /* Update the request to use. */ + storage -> ux_device_class_storage_transfer = transfer_request; + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* Update residue. */ + storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length; + + /* Return an error. */ + return(UX_ERROR); + } + + /* Next: Disk read -> Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + storage -> ux_device_class_storage_buffer_state[0] = UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + storage -> ux_device_class_storage_buffer_state[1] = UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + storage -> ux_device_class_storage_buffer_usb = 1; + storage -> ux_device_class_storage_buffer_disk = 1; + + storage -> ux_device_class_storage_device_length = total_length; + storage -> ux_device_class_storage_data_length = + UX_MIN(total_length , storage -> ux_slave_class_storage_host_length); + storage -> ux_device_class_storage_data_count = 0; + + storage -> ux_device_class_storage_cmd_lba = lba; + storage -> ux_device_class_storage_cmd_n_lb = total_number_blocks; + +#else + /* Check transfer length. */ /* Case (7). Host length < device length. */ @@ -254,6 +303,8 @@ ULONG done_length; storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length; } +#endif /* else defined(UX_DEVICE_STANDALONE) */ + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c b/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c index 62d4cf65..916b64e2 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read_capacity PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -110,9 +113,12 @@ UCHAR *read_capacity_buffer; /* Check the status for error. */ if (status != UX_SUCCESS) { - + +#if !defined(UX_DEVICE_STANDALONE) + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ _ux_device_stack_endpoint_stall(endpoint_in); +#endif /* Now we set the CSW with Error. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; @@ -138,11 +144,28 @@ UCHAR *read_capacity_buffer; _ux_utility_long_put_big_endian(&read_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_BLOCK_SIZE], storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length); +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = + UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH; + storage -> ux_device_class_storage_data_length = + UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + /* Send a data payload with the read_capacity response buffer. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH, UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH); - +#endif + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; status = UX_SUCCESS; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c b/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c index 213f7111..a34d22ea 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c @@ -64,7 +64,7 @@ UCHAR usbx_device_class_storage_disk_information[] = { /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read_disk_information PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -105,6 +105,9 @@ UCHAR usbx_device_class_storage_disk_information[] = { /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read_disk_information(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -153,10 +156,25 @@ ULONG allocation_length; usbx_device_class_storage_disk_information, allocation_length); /* Use case of memcpy is verified. */ +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = allocation_length; + storage -> ux_device_class_storage_data_length = allocation_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + /* Send a data payload with the read_capacity response buffer. */ _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); +#endif /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c b/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c index 46151eaf..a55fdf33 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c @@ -162,7 +162,7 @@ UCHAR usbx_device_class_storage_dvd_structure[] = { /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read_dvd_structure PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -203,6 +203,9 @@ UCHAR usbx_device_class_storage_dvd_structure[] = { /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read_dvd_structure(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -213,9 +216,13 @@ UINT _ux_device_class_storage_read_dvd_structure(UX_SLAVE_CLASS_STORAGE *storag UINT status; UX_SLAVE_TRANSFER *transfer_request; ULONG allocation_length; -ULONG transfer_length = 0; UCHAR *dvd_structure_pointer; +#if !defined(UX_DEVICE_STANDALONE) +ULONG transfer_length = 0; +#endif + + UX_PARAMETER_NOT_USED(endpoint_out); /* If trace is enabled, insert this event into the trace buffer. */ @@ -236,6 +243,21 @@ UCHAR *dvd_structure_pointer; /* Set dvd structure pointer. */ dvd_structure_pointer = usbx_device_class_storage_dvd_structure; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = allocation_length; + storage -> ux_device_class_storage_data_buffer = dvd_structure_pointer; + storage -> ux_device_class_storage_data_length = allocation_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + /* Send back everything in chunks. */ while (allocation_length) { @@ -271,7 +293,8 @@ UCHAR *dvd_structure_pointer; /* Subtract what is left to send out. */ allocation_length -= transfer_length; } - +#endif + /* Now we set the CSW with success. */ UX_PARAMETER_NOT_USED(lun); storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c b/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c index 18b08718..5a0d2838 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read_format_capacity PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read_format_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -121,10 +124,27 @@ UCHAR *read_format_capacity_buffer; /* Insert the response code : always 2. */ read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_DESC_CODE] = 2; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = + UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH; + storage -> ux_device_class_storage_data_length = + UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + /* Send a data payload with the read_capacity response buffer. */ _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH, UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH); +#endif /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c b/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c index 8a6486d7..85c7a702 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_read_toc PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -186,9 +189,23 @@ UCHAR *toc_buffer; /* We return less than demanded. */ allocation_length = toc_length; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = allocation_length; + storage -> ux_device_class_storage_data_length = allocation_length; + storage -> ux_device_class_storage_data_count = 0; + +#else + /* Send a data payload with the TOC response buffer. */ _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); - +#endif + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; status = UX_SUCCESS; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_report_key.c b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c index 003ae941..65b93c66 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_report_key.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_report_key PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed compile warning, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_report_key(UX_SLAVE_CLASS_STORAGE *storage, @@ -141,19 +144,32 @@ ULONG key_format; /* Adjust the reply. */ allocation_length = UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_LENGTH; - /* Send a data payload with the read_capacity response buffer. */ - _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); /* Use case of memset is verified. */ - break; default : - - /* Send a data payload with the read_capacity response buffer. */ - status = _ux_device_stack_transfer_request(transfer_request, 0, 0); + allocation_length = 0; break; } +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = allocation_length; + storage -> ux_device_class_storage_data_length = allocation_length; + storage -> ux_device_class_storage_data_count = 0; + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); + +#else + + /* Send a data payload with the read_capacity response buffer. */ + status = _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); /* Use case of memset is verified. */ +#endif + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c index 15c20158..54114288 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_request_sense PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_request_sense(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, @@ -141,6 +144,19 @@ ULONG sense_length; /* Initialize the response buffer with the additional length. */ sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH] = 10; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = sense_length; + storage -> ux_device_class_storage_data_length = sense_length; + storage -> ux_device_class_storage_data_count = 0; + +#else + /* Send a data payload with the sense codes. */ if (sense_length) _ux_device_stack_transfer_request(transfer_request, sense_length, sense_length); @@ -151,6 +167,7 @@ ULONG sense_length; _ux_device_stack_endpoint_stall(endpoint_in); storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; } +#endif /* Return completion status. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c b/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c index 5428a915..b73b069e 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_synchronize_cache PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* optimized command logic, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_synchronize_cache(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -89,7 +92,10 @@ UINT status; ULONG lba; USHORT number_blocks; ULONG media_status; + +#if !defined(UX_DEVICE_STANDALONE) UCHAR flags; +#endif UX_PARAMETER_NOT_USED(endpoint_out); @@ -108,8 +114,6 @@ UCHAR flags; return(UX_SUCCESS); } - flags = *(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS); - /* Get the LBA and number of blocks from the CBWCB in 16 bits. */ lba = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_LBA); number_blocks = (USHORT)_ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_NUMBER_OF_BLOCKS); @@ -130,7 +134,12 @@ UCHAR flags; /* We have a problem, media status error. Return a bad completion and wait for the REQUEST_SENSE command. */ +#if !defined(UX_DEVICE_STANDALONE) _ux_device_stack_endpoint_stall(endpoint_in); +#else + UX_PARAMETER_NOT_USED(endpoint_in); + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_ERR; +#endif storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; @@ -138,8 +147,25 @@ UCHAR flags; return(UX_ERROR); } + /* Now it's OK to perform synchronize cache. */ + +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Disk (SYNC). */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT; + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_DISK_OP; + + storage -> ux_device_class_storage_cmd_lba = lba; + storage -> ux_device_class_storage_cmd_n_lb = number_blocks; + +#else + + /* Get the flags. */ + flags = *(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS); + /* If the immediate bit is set, we return a CSW before flush. */ - else if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0) + if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0) _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); /* Send the flush command to the local media. */ @@ -170,6 +196,7 @@ UCHAR flags; /* Return an error. */ return(UX_ERROR); } +#endif /* Return completion status. */ return(status); 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 new file mode 100644 index 00000000..2acafd4e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c @@ -0,0 +1,1282 @@ +/**************************************************************************/ +/* */ +/* 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 Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#if defined(UX_DEVICE_STANDALONE) + +/* Internal static inline implements. */ + + +static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *storage); + +static inline UINT _ux_device_class_storage_reset_wait(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_cbw_process(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_cmd_process(UX_SLAVE_CLASS_STORAGE *storage, UCHAR *cbw); +static inline VOID _ux_device_class_storage_data_cases_check(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_trans_start(UX_SLAVE_CLASS_STORAGE *storage); +static inline UINT _ux_device_class_storage_trans_wait(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_trans_error(UX_SLAVE_CLASS_STORAGE *storage); +static inline UINT _ux_device_class_storage_data_next(UX_SLAVE_CLASS_STORAGE *storage); + +static inline VOID _ux_device_class_storage_halt_out(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_halt_in(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_halt_trans(UX_SLAVE_CLASS_STORAGE *storage); + +static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *storage); + +static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage); +static inline UINT _ux_device_class_storage_disk_wait(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_disk_next(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_disk_read_next(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_disk_write_next(UX_SLAVE_CLASS_STORAGE *storage); +static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *storage); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs tasks of the storage class. */ +/* E.g., CBW-DATA-CSW state machine. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Address of storage instance */ +/* */ +/* OUTPUT */ +/* */ +/* UX_STATE_RESET Tasks suspended */ +/* UX_STATE_IDLE Activated but no task ran */ +/* (others > UX_STATE_IDLE) Tasks running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_format Storage class format */ +/* _ux_device_class_storage_inquiry Storage class inquiry */ +/* _ux_device_class_storage_mode_select Mode select */ +/* _ux_device_class_storage_mode_sense Mode sense */ +/* _ux_device_class_storage_prevent_allow_media_removal */ +/* Prevent media removal */ +/* _ux_device_class_storage_read Read */ +/* _ux_device_class_storage_read_capacity */ +/* Read capacity */ +/* _ux_device_class_storage_read_format_capacity */ +/* Read format capacity */ +/* _ux_device_class_storage_request_sense */ +/* Sense request */ +/* _ux_device_class_storage_start_stop Start/Stop */ +/* _ux_device_class_storage_synchronize_cache */ +/* Synchronize cache */ +/* _ux_device_class_storage_test_ready Ready test */ +/* _ux_device_class_storage_verify Verify */ +/* _ux_device_class_storage_write Write */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_stack_interface_delete Interface delete */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_tasks_run(VOID *instance) +{ + +UX_SLAVE_CLASS_STORAGE *storage; +UINT status; + + + /* Get storage instance. */ + storage = (UX_SLAVE_CLASS_STORAGE *) instance; + + /* Run USB and disk tasks. */ + status = _ux_device_class_storage_task_usb(storage); + _ux_device_class_storage_task_disk(storage); + return(status); +} + +static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *storage) +{ +UX_SLAVE_DEVICE *device; +UCHAR state; +UINT status; + + + /* Get pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Run states once. */ + while(1) + { + + /* General check for MSC ready. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED || + storage -> ux_device_class_storage_ep_in == UX_NULL || + storage -> ux_device_class_storage_ep_out == UX_NULL) + { + storage -> ux_device_class_storage_state = UX_STATE_RESET; + return(UX_STATE_EXIT); + } + + /* Get current state. */ + state = storage -> ux_device_class_storage_state; + + /* Handle different state. */ + switch(state) + { + + case UX_STATE_RESET: /* Initial, reset. */ + _ux_device_class_storage_cbw_receive(storage); + + /* Roll back to next state directly. */ + continue; + + case UX_DEVICE_CLASS_STORAGE_STATE_RESET: + _ux_device_class_storage_halt_in(storage); + _ux_device_class_storage_halt_out(storage); + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET_WAIT; + + /* Fall through. */ + case UX_DEVICE_CLASS_STORAGE_STATE_RESET_WAIT: /* Wait reset recovery. */ + return _ux_device_class_storage_reset_wait(storage); + + case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START: + _ux_device_class_storage_trans_start(storage); + + /* Fall through. */ + case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_WAIT: + status = _ux_device_class_storage_trans_wait(storage); + + /* Fatal case. */ + if (status < UX_STATE_ERROR) + { + + /* USB idle. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_IDLE; + + /* Disk notified with USB error. */ + if (storage -> ux_device_class_storage_disk_state != + UX_DEVICE_CLASS_STORAGE_DISK_IDLE) + { + storage -> ux_device_class_storage_disk_state = + UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR; + } + return(UX_STATE_WAIT); + } + + /* Error case. */ + if (status == UX_STATE_ERROR) + { + + /* Stall. */ + _ux_device_class_storage_halt_trans(storage); + + /* Disk notified with USB error. */ + if (storage -> ux_device_class_storage_disk_state != + UX_DEVICE_CLASS_STORAGE_DISK_IDLE) + { + storage -> ux_device_class_storage_disk_state = + UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR; + } + + /* Update residue. */ + storage -> ux_slave_class_storage_csw_residue = + storage -> ux_slave_class_storage_host_length - + storage -> ux_device_class_storage_data_count; + + /* Update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[ + storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_request_sense_status = + UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00); + + /* Issue CSW. */ + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, 0); + + return(UX_STATE_WAIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Update data count. */ + storage -> ux_device_class_storage_data_count += + storage -> ux_device_class_storage_transfer -> + ux_slave_transfer_request_actual_length; + + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_NEXT; + } + + /* Other cases, keep waiting. */ + return(UX_STATE_WAIT); + + case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_NEXT: + + /* CBW received: -> CBW handle. */ + if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CBW) + { + _ux_device_class_storage_cbw_process(storage); + + /* Apply command in next call anyway. */ + return(UX_STATE_WAIT); + } + + /* CSW sent: -> CSW done - CBW start. */ + if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CSW) + { + if (storage -> ux_slave_class_storage_csw_status == UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR) + { + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET; + } + else + { + _ux_device_class_storage_cbw_receive(storage); + } + continue; + } + + /* DATA done: -> process data. */ + return _ux_device_class_storage_data_next(storage); + + case UX_DEVICE_CLASS_STORAGE_STATE_DISK_ERROR: + _ux_device_class_storage_trans_error(storage); + continue; + + case UX_DEVICE_CLASS_STORAGE_STATE_IDLE: /* Nothing to do, fall through. */ + + case UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT: /* Nothing to do, fall through. */ + + default: /* Do nothing. */ + break; + } + + /* Unhandled, just do again by app call. */ + return(UX_STATE_EXIT); + } +} + +static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage) +{ +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +ULONG max_packet_size; + + + /* Command state: CBW. */ + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_CBW; + storage -> ux_device_class_storage_data_buffer = UX_NULL; + + /* Transfer state: START: OUT 31. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + + endpoint = storage -> ux_device_class_storage_ep_out; + max_packet_size = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + storage -> ux_device_class_storage_transfer = transfer; + storage -> ux_device_class_storage_data_length = max_packet_size; + storage -> ux_device_class_storage_data_count = 0; +} + +static inline VOID _ux_device_class_storage_cbw_process(UX_SLAVE_CLASS_STORAGE *storage) +{ +UX_SLAVE_TRANSFER *cbw_trans; +ULONG cbw_length; +UCHAR *cbw; + + + /* Get transfer. */ + cbw_trans = storage -> ux_device_class_storage_transfer; + + /* If CBW is stalled, just retry. */ + if (cbw_trans -> ux_slave_transfer_request_completion_code == UX_TRANSFER_STALLED) + { + _ux_device_class_storage_cbw_receive(storage); + return; + } + + /* Get CBW and length. */ + cbw_length = cbw_trans -> ux_slave_transfer_request_actual_length; + cbw = cbw_trans -> ux_slave_transfer_request_data_pointer; + if (cbw_length != UX_SLAVE_CLASS_STORAGE_CBW_LENGTH) + { + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + } + else + { + _ux_device_class_storage_cmd_process(storage, cbw); + } + + /* If still in CBW phase, there must be CBW structure error, wait reset. */ + if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CBW) + { + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET; + return; + } + + /* If no error, error cases need check. */ + if (storage -> ux_slave_class_storage_csw_status == UX_SLAVE_CLASS_STORAGE_CSW_PASSED) + { + _ux_device_class_storage_data_cases_check(storage); + } + + /* Error, stall and send CSW. */ + if (storage -> ux_slave_class_storage_csw_status) + { + + /* There will not be any disk operation in this case. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + + if (storage -> ux_slave_class_storage_host_length && + (storage -> ux_slave_class_storage_cbw_flags & + UX_DEVICE_CLASS_STORAGE_CBW_FLAG_DIR) == 0) + { + _ux_device_class_storage_halt_out(storage); + } + else + { + _ux_device_class_storage_halt_in(storage); + } + + /* Still need CSW phase. */ + if (storage -> ux_device_class_storage_cmd_state != UX_DEVICE_CLASS_STORAGE_CMD_CBW) + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_ERR; + } + + /* No error, state not changed. */ + + /* Start CSW if there is no data. */ + if (storage -> ux_device_class_storage_cmd_state < UX_DEVICE_CLASS_STORAGE_CMD_WRITE) + { + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, 0); + } +} +static inline VOID _ux_device_class_storage_cmd_process(UX_SLAVE_CLASS_STORAGE *storage, UCHAR *cbw) +{ + +UX_SLAVE_ENDPOINT *endpoint_in, *endpoint_out; +ULONG cbwcb_length; +UCHAR *cbwcb; +UCHAR lun; + + + /* Get bCBWLUN. */ + lun = *(cbw + UX_SLAVE_CLASS_STORAGE_CBW_LUN); + storage -> ux_slave_class_storage_cbw_lun = lun; + + /* Get bmCBWFlags. */ + storage -> ux_slave_class_storage_cbw_flags = *(cbw + UX_SLAVE_CLASS_STORAGE_CBW_FLAGS); + + /* Get dCBWTag. */ + storage -> ux_slave_class_storage_scsi_tag = + _ux_utility_long_get(cbw + UX_SLAVE_CLASS_STORAGE_CBW_TAG); + + /* Get dCBWDataTransferLength: number of bytes to transfer. */ + storage -> ux_slave_class_storage_host_length = _ux_utility_long_get(cbw + UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Reset CSW status. */ + storage -> ux_slave_class_storage_csw_residue = 0; + storage -> ux_slave_class_storage_csw_status = 0; + + /* Check LUN error. */ + if (lun >= storage -> ux_slave_class_storage_number_lun) + { + + /* Phase error! */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + return; + } + + /* Check Signature error. */ + if (_ux_utility_long_get(cbw) != UX_SLAVE_CLASS_STORAGE_CBW_SIGNATURE_MASK) + { + + /* Phase error! */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + return; + } + + /* Get CBWCB length. */ + cbwcb_length = (ULONG)*(cbw + UX_SLAVE_CLASS_STORAGE_CBW_CB_LENGTH); + + /* Check CBWCB length. */ + if (cbwcb_length == 0) + { + + /* Phase error! */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + return; + } + + /* Get endpoints. */ + endpoint_in = storage -> ux_device_class_storage_ep_in; + endpoint_out = storage -> ux_device_class_storage_ep_out; + + /* By default set next command state to CSW (no DATA). */ + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_CSW; + storage -> ux_device_class_storage_device_length = 0; + storage -> ux_device_class_storage_data_length = 0; + storage -> ux_device_class_storage_data_count = 0; + + /* Reset disk access state. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + + /* Analyze the CBWCB command. */ + cbwcb = cbw + UX_SLAVE_CLASS_STORAGE_CBW_CB; + storage -> ux_device_class_storage_cmd = *cbwcb; + switch(storage -> ux_device_class_storage_cmd) + { + + case UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY: + + _ux_device_class_storage_test_ready(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE: + + _ux_device_class_storage_request_sense(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT: + + _ux_device_class_storage_format(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_INQUIRY: + + _ux_device_class_storage_inquiry(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP: + + _ux_device_class_storage_start_stop(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL: + + _ux_device_class_storage_prevent_allow_media_removal(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY: + + _ux_device_class_storage_read_format_capacity(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_CAPACITY: + + _ux_device_class_storage_read_capacity(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY: + + _ux_device_class_storage_verify(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT: + + _ux_device_class_storage_mode_select(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT: + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE: + + _ux_device_class_storage_mode_sense(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + + _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbwcb, + UX_SLAVE_CLASS_STORAGE_SCSI_READ32); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + + _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbwcb, + UX_SLAVE_CLASS_STORAGE_SCSI_READ16); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + + _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbwcb, + UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + + _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbwcb, + UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE: + + _ux_device_class_storage_synchronize_cache(storage, lun, endpoint_in, endpoint_out, cbwcb, *(cbwcb)); + break; + +#ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_STATUS_NOTIFICATION: + + _ux_device_class_storage_get_status_notification(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_CONFIGURATION: + + _ux_device_class_storage_get_configuration(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DISK_INFORMATION: + + _ux_device_class_storage_read_disk_information(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_REPORT_KEY: + + _ux_device_class_storage_report_key(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_PERFORMANCE: + + _ux_device_class_storage_get_performance(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DVD_STRUCTURE: + + _ux_device_class_storage_read_dvd_structure(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_TOC: + + _ux_device_class_storage_read_toc(storage, lun, endpoint_in, endpoint_out, cbwcb); + break; + +#endif + + default: + + /* The command is unknown or unsupported, fail. */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; + + /* Initialize the request sense keys. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = + UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST, + UX_SLAVE_CLASS_STORAGE_ASC_KEY_INVALID_COMMAND,0); + } +} +static inline VOID _ux_device_class_storage_data_cases_check(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* ============ 13 cases check. */ + /* (1)Hn=Dn, (2)HnDn, (5)Hi>Di, (6)Hi=Di, (7)HiDo : DATA */ + /* (9)Ho>Dn, (10)Ho<>Di, (11)Ho>Do, (12)Ho=Do, (13)Ho ux_slave_class_storage_cbw_flags & UX_DEVICE_CLASS_STORAGE_CBW_FLAG_DIR) + { + + /* Hi. */ + /* Case (2), (8). */ + if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_WRITE || + storage -> ux_slave_class_storage_host_length == 0) + { + + /* Phase error. */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + return; + } + + /* Case (7). */ + if (storage -> ux_slave_class_storage_host_length < + storage -> ux_device_class_storage_data_length) + { + + /* Part of data will be sent. */ + storage -> ux_device_class_storage_data_length = + storage -> ux_slave_class_storage_host_length; + } + + /* Case (4), (5), (6), (7). */ + /* No touch for prepared transfer. */ + } + else + { + + /* Ho. */ + /* Case (3), (10), (13). */ + if (storage -> ux_slave_class_storage_host_length < + storage -> ux_device_class_storage_device_length || + storage -> ux_device_class_storage_cmd_state == + UX_DEVICE_CLASS_STORAGE_CMD_READ) + { + + /* Phase error. */ + storage -> ux_slave_class_storage_csw_status = + UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR; + return; + } + + /* Case (9), (11). */ + if (storage -> ux_slave_class_storage_host_length != + storage -> ux_device_class_storage_device_length) + { + + /* Update dCSWDataResidue. */ + storage -> ux_slave_class_storage_csw_residue = + storage -> ux_slave_class_storage_host_length - + storage -> ux_device_class_storage_device_length; + + /* Failed. */ + storage -> ux_slave_class_storage_csw_status = + UX_SLAVE_CLASS_STORAGE_CSW_FAILED; + return; + } + } +} +static inline UINT _ux_device_class_storage_reset_wait(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* Check PhaseError. */ + if ((UCHAR)storage -> ux_slave_class_storage_csw_status != + UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR) + { + + /* Reset states. */ + storage -> ux_device_class_storage_state = UX_STATE_RESET; + } + else + { + + /* Keep CBW endpoints halted until status is reset. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET; + } + + return(UX_STATE_WAIT); +} +static inline UINT _ux_device_class_storage_data_next(UX_SLAVE_CLASS_STORAGE *storage) +{ + switch(storage -> ux_device_class_storage_cmd) + { + + /* Disk read. */ + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + /* Fall through. */ + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + + /* Check if all data is done. */ + if (storage -> ux_device_class_storage_data_count >= + storage -> ux_device_class_storage_data_length) + { + + /* Stall if host expects more data. */ + if (storage -> ux_slave_class_storage_host_length > + storage -> ux_device_class_storage_data_length) + { + _ux_device_class_storage_halt_in(storage); + + /* Update dCSWDataResidue. */ + storage -> ux_slave_class_storage_csw_residue = + storage -> ux_slave_class_storage_host_length - + storage -> ux_device_class_storage_data_length; + } + + /* Set to fail if device expects more data. */ + if (storage -> ux_device_class_storage_device_length > + storage -> ux_device_class_storage_data_count) + { + + /* Update bCSWStatus. */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; + } + + /* Issue CSW. */ + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, + 0 /* Not used. */); + } + else + { + + /* Buffer sent, update buffer states. */ + storage -> ux_device_class_storage_buffer_state[storage -> ux_device_class_storage_buffer_usb] = + UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + storage -> ux_device_class_storage_buffer_usb = !storage -> ux_device_class_storage_buffer_usb; + storage -> ux_device_class_storage_transfer -> ux_slave_transfer_request_data_pointer = + storage -> ux_device_class_storage_buffer[storage -> ux_device_class_storage_buffer_usb]; + + /* If disk read not started (waiting free buffer), start it. */ + if (storage -> ux_device_class_storage_disk_state == UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT) + { + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + } + + /* If there is buffer ready, send next. */ + if (storage -> ux_device_class_storage_buffer_state[storage->ux_device_class_storage_buffer_usb] == + UX_DEVICE_CLASS_STORAGE_BUFFER_FULL) + { + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + } + else + { + + /* Wait disk operation to fill buffer. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT; + } + } + break; + + /* Disk write. */ + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + /* Fall through. */ + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + + /* Buffer received, update buffer state. */ + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_usb] = + UX_DEVICE_CLASS_STORAGE_BUFFER_FULL; + + /* If disk waiting data, Start disk write. */ + if (storage -> ux_device_class_storage_disk_state == + UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT) + { + storage -> ux_device_class_storage_disk_state = + UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + } + + /* Check if all data is done. */ + if (storage -> ux_device_class_storage_data_count >= + storage -> ux_device_class_storage_data_length) + { + + /* Wait disk operation done. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT; + } + else + { + + /* Buffer received, update buffer states. */ + storage -> ux_device_class_storage_buffer_usb = + !storage -> ux_device_class_storage_buffer_usb; + storage -> ux_device_class_storage_transfer -> + ux_slave_transfer_request_data_pointer = + storage -> ux_device_class_storage_buffer[ + storage -> ux_device_class_storage_buffer_usb]; + + /* If there is buffer empty, start it. */ + if (storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_usb] == + UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY) + { + storage -> ux_device_class_storage_state = + UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + } + else + { + + /* No buffer available, wait disk operation done. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT; + } + } + break; + + /* No further data to send. */ + default: + + /* Stall if host expects more data. */ + if (storage -> ux_slave_class_storage_host_length > + storage -> ux_device_class_storage_data_count) + { + _ux_device_class_storage_halt_trans(storage); + + /* Update dCSWDataResidue. */ + storage -> ux_slave_class_storage_csw_residue = + storage -> ux_slave_class_storage_host_length - + storage -> ux_device_class_storage_data_length; + } + + /* Set to fail if device expects more data. */ + if (storage -> ux_device_class_storage_device_length > + storage -> ux_device_class_storage_data_count) + { + + /* Update bCSWStatus. */ + storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED; + } + + /* Issue CSW. */ + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, + 0 /* Not used. */); + } + + /* Next task state. */ + return(UX_STATE_NEXT); +} +static inline VOID _ux_device_class_storage_trans_start(UX_SLAVE_CLASS_STORAGE *storage) +{ +ULONG remaining, host_length, device_length; + + + /* Get remaining transfer length. */ + remaining = storage -> ux_device_class_storage_data_length - storage -> ux_device_class_storage_data_count; + + /* Check if data exceeds buffer length. */ + if (remaining > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + { + + /* Send full packets, without ZLP. */ + host_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + device_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + } + else + { + + /* Send packets sliced based on host length and device length. */ + device_length = remaining; + + /* USB CV test expecting stall but not ZLP, so host length is same, but not remaining. */ + host_length = remaining; + } + + /* Prepare data if necessary. */ + if (storage -> ux_device_class_storage_data_buffer && device_length && + storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_READ) + { + _ux_utility_memory_copy(storage -> ux_device_class_storage_transfer -> + ux_slave_transfer_request_data_pointer, + storage -> ux_device_class_storage_data_buffer + + storage -> ux_device_class_storage_data_count, + device_length); /* Use case of memcpy is verified. */ + } + + /* Save host length and device length for task states. */ + storage -> ux_device_class_storage_trans_device_length = device_length; + storage -> ux_device_class_storage_trans_host_length = host_length; + + /* To TRANS_WAIT. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_WAIT; + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer); +} +static inline UINT _ux_device_class_storage_trans_wait(UX_SLAVE_CLASS_STORAGE *storage) +{ + return _ux_device_stack_transfer_run(storage -> ux_device_class_storage_transfer, + storage -> ux_device_class_storage_trans_device_length, + storage -> ux_device_class_storage_trans_host_length); +} +static inline VOID _ux_device_class_storage_trans_error(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* Abort USB operation if transfer not done. */ + if (storage -> ux_device_class_storage_data_count < storage -> ux_device_class_storage_data_length) + { + if (storage -> ux_slave_class_storage_cbw_flags & UX_DEVICE_CLASS_STORAGE_CBW_FLAG_IN) + { + _ux_device_class_storage_halt_in(storage); + } + else + { + _ux_device_class_storage_halt_out(storage); + } + + /* Update dCSWDataResidue. */ + storage -> ux_slave_class_storage_csw_residue = + storage -> ux_slave_class_storage_host_length - + storage -> ux_device_class_storage_data_count; + } + else + { + _ux_device_class_storage_halt_in(storage); + } + + /* Issue CSW. */ + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, + 0 /* Not used. */); +} +static inline VOID _ux_device_class_storage_halt_out(UX_SLAVE_CLASS_STORAGE *storage) +{ + _ux_device_stack_endpoint_stall(storage -> ux_device_class_storage_ep_out); +} +static inline VOID _ux_device_class_storage_halt_in(UX_SLAVE_CLASS_STORAGE *storage) +{ + _ux_device_stack_endpoint_stall(storage -> ux_device_class_storage_ep_in); +} +static inline VOID _ux_device_class_storage_halt_trans(UX_SLAVE_CLASS_STORAGE *storage) +{ +UX_SLAVE_TRANSFER *trans = storage -> ux_device_class_storage_transfer; +UX_SLAVE_ENDPOINT *endp = trans -> ux_slave_transfer_request_endpoint; + _ux_device_stack_endpoint_stall(endp); +} + + +static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *storage) +{ +UCHAR state = storage -> ux_device_class_storage_disk_state; +UINT status; + + /* Run states once. */ + while(1) + { + + /* Update state. */ + state = storage -> ux_device_class_storage_disk_state; + switch(state) + { + + case UX_DEVICE_CLASS_STORAGE_DISK_OP_START: + _ux_device_class_storage_disk_start(storage); + storage -> ux_device_class_storage_disk_state = + UX_DEVICE_CLASS_STORAGE_DISK_OP_WAIT; + + /* Fall through. */ + case UX_DEVICE_CLASS_STORAGE_DISK_OP_WAIT: + status = _ux_device_class_storage_disk_wait(storage); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Disk idle. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + + /* USB notified with disk error. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_ERROR; + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_NEXT; + } + + /* Other cases, keep waiting. */ + return; + + case UX_DEVICE_CLASS_STORAGE_DISK_OP_NEXT: + _ux_device_class_storage_disk_next(storage); + return; + + case UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR: + _ux_device_class_storage_disk_error(storage); + break; + + case UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT: /* Nothing to do, fall through. */ + + case UX_DEVICE_CLASS_STORAGE_DISK_IDLE: /* Nothing to do, fall through. */ + + default: /* Nothing to do. */ + break; + } + + /* Task run once. */ + return; + } +} +static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage) +{ +ULONG block_size; +ULONG max_n_blocks; + + + if (storage -> ux_device_class_storage_cmd == UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE) + { + + /* All things sync in one call. */ + storage -> ux_device_class_storage_disk_n_lb = storage -> ux_device_class_storage_cmd_n_lb; + return; + } + + /* Read/write, split the operation by buffer sizes. */ + + /* 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; + max_n_blocks = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE / block_size; + + /* Prepare next disk read. */ + if (storage -> ux_device_class_storage_cmd_n_lb > max_n_blocks) + { + storage -> ux_device_class_storage_disk_n_lb = max_n_blocks; + } + else + { + storage -> ux_device_class_storage_disk_n_lb = storage -> ux_device_class_storage_cmd_n_lb; + } +} +static inline UINT _ux_device_class_storage_disk_wait(UX_SLAVE_CLASS_STORAGE *storage) +{ + switch (storage -> ux_device_class_storage_cmd) + { + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_media_read(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_buffer[ + storage -> ux_device_class_storage_buffer_disk], + storage -> ux_device_class_storage_disk_n_lb, + storage -> ux_device_class_storage_cmd_lba, + &storage -> ux_device_class_storage_media_status); + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_media_write(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_buffer[ + storage -> ux_device_class_storage_buffer_disk], + storage -> ux_device_class_storage_disk_n_lb, + storage -> ux_device_class_storage_cmd_lba, + &storage -> ux_device_class_storage_media_status); + + case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE: + return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_media_flush(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_disk_n_lb, + storage -> ux_device_class_storage_cmd_lba, + &storage -> ux_device_class_storage_media_status); + + case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY: /* No nothing for now. */ + default: + break; + } + return(UX_STATE_NEXT); +} +static inline VOID _ux_device_class_storage_disk_next(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* Update disk operation status. */ + storage -> ux_device_class_storage_cmd_lba += storage -> ux_device_class_storage_disk_n_lb; + storage -> ux_device_class_storage_cmd_n_lb -= storage -> ux_device_class_storage_disk_n_lb; + + /* Next check is different for read/write. */ + switch (storage -> ux_device_class_storage_cmd) + { + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + _ux_device_class_storage_disk_read_next(storage); + return; + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + _ux_device_class_storage_disk_write_next(storage); + return; + + case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE: + + /* Disk is idle now. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + + /* Send CSW if not sent yet. */ + if (storage -> ux_device_class_storage_state == UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT) + { + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, + 0 /* Not used. */); + } + return; + + default: + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + break; + } +} +static inline VOID _ux_device_class_storage_disk_read_next(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* Update buffer state : full. */ + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_disk] = + UX_DEVICE_CLASS_STORAGE_BUFFER_FULL; + + /* Check if all disk operation is done. */ + if (storage -> ux_device_class_storage_cmd_n_lb == 0) + { + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + } + else + { + + /* Update buffer index. */ + storage -> ux_device_class_storage_buffer_disk = + !storage -> ux_device_class_storage_buffer_disk; + + /* If buffer is free, start next read. */ + if (UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY == + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_disk]) + { + + /* Start next read. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + } + else + { + + /* Wait until buffer sent by USB. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT; + } + } + + /* Start USB transfer. */ + if (storage -> ux_device_class_storage_state == + UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT && + UX_DEVICE_CLASS_STORAGE_BUFFER_FULL == + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_usb]) + { + storage -> ux_device_class_storage_state = + UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + } +} +static inline VOID _ux_device_class_storage_disk_write_next(UX_SLAVE_CLASS_STORAGE *storage) +{ + + /* Update buffer state : empty. */ + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_disk] = + UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + + /* Check if all disk operation is done. */ + if (storage -> ux_device_class_storage_cmd_n_lb == 0) + { + + /* Disk is idle now. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; + + /* Issue CSW. */ + _ux_device_class_storage_csw_send(storage, + storage -> ux_slave_class_storage_cbw_lun, + storage -> ux_device_class_storage_ep_in, + 0 /* Not used. */); + } + else + { + + /* Update buffer index. */ + storage -> ux_device_class_storage_buffer_disk = + !storage -> ux_device_class_storage_buffer_disk; + + /* If buffer is full, start next write. */ + if (UX_DEVICE_CLASS_STORAGE_BUFFER_FULL == + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_disk]) + { + + /* Start next write. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START; + } + else + { + + /* Wait until buffer filled by USB. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT; + } + + /* Start USB transfer. */ + if (storage -> ux_device_class_storage_state == + UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT && + UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY == + storage -> ux_device_class_storage_buffer_state[ + storage -> ux_device_class_storage_buffer_usb]) + { + storage -> ux_device_class_storage_state = + UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + } + } +} +static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *storage) +{ + /* Abort disk operation: read or write with NULL! */ + switch (storage -> ux_device_class_storage_cmd) + { + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_media_read(storage, + storage -> ux_slave_class_storage_cbw_lun, UX_NULL, 0, 0, UX_NULL); + break; + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. + ux_slave_class_storage_media_write(storage, + storage -> ux_slave_class_storage_cbw_lun, UX_NULL, 0, 0, UX_NULL); + break; + default: + break; + } + + /* Change disk state to IDLE. */ + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE; +} + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c index ac627f90..2793af0a 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_test_ready PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -78,6 +78,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_test_ready(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, @@ -107,12 +110,15 @@ ULONG media_status; UX_SLAVE_CLASS_STORAGE_CSW_PASSED : UX_SLAVE_CLASS_STORAGE_CSW_FAILED; status = UX_SUCCESS; +#if !defined(UX_DEVICE_STANDALONE) + /* Case (9) Ho > Dn. */ if (storage -> ux_slave_class_storage_host_length) { _ux_device_stack_endpoint_stall(endpoint_out); storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length; } +#endif /* Return completion status. */ return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_thread.c b/common/usbx_device_classes/src/ux_device_class_storage_thread.c index f275b056..c7d3026f 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_thread.c @@ -30,12 +30,13 @@ #include "ux_device_stack.h" +#if !defined(UX_DEVICE_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_thread PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -43,6 +44,8 @@ /* DESCRIPTION */ /* */ /* This function is the thread of the storage class. */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -79,9 +82,9 @@ /* _ux_device_stack_transfer_request Transfer request */ /* _ux_utility_long_get Get 32-bit value */ /* _ux_utility_memory_allocate Allocate memory */ -/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_device_semaphore_create Create semaphore */ /* _ux_utility_delay_ms Sleep thread for several ms */ -/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_device_thread_suspend Suspend thread */ /* */ /* CALLED BY */ /* */ @@ -114,6 +117,9 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* improved TAG management, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_device_class_storage_thread(ULONG storage_class) @@ -154,9 +160,12 @@ UCHAR *cbw_cb; /* We assume the worst situation. */ status = UX_ERROR; - /* This is the first time we are activated. We need the interface to the class. */ + /* We are activated. We need the interface to the class. */ interface = storage -> ux_slave_class_storage_interface; + /* We assume the worst situation. */ + status = UX_ERROR; + /* Locate the endpoints. */ endpoint_in = interface -> ux_slave_interface_first_endpoint; @@ -401,7 +410,7 @@ UCHAR *cbw_cb; else /* We must therefore wait a while. */ - _ux_utility_thread_relinquish(); + _ux_device_thread_relinquish(); } break; } @@ -449,7 +458,7 @@ UCHAR *cbw_cb; /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ - _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + _ux_device_thread_suspend(&class -> ux_slave_class_thread); } } - +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c index 1785008c..61cb4d7d 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_uninitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,7 +55,7 @@ /* CALLS */ /* */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_thread_delete Delete thread */ +/* _ux_device_thread_delete Delete thread */ /* */ /* CALLED BY */ /* */ @@ -68,6 +68,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -87,11 +90,13 @@ UX_SLAVE_CLASS *class; { /* Remove STORAGE thread. */ - _ux_utility_thread_delete(&class -> ux_slave_class_thread); - + _ux_device_thread_delete(&class -> ux_slave_class_thread); + +#if !(defined(UX_DEVICE_STANDALONE) || defined(UX_STANDALONE)) /* Remove the thread used by STORAGE. */ _ux_utility_memory_free(class -> ux_slave_class_thread_stack); - +#endif + /* Free the resources. */ _ux_utility_memory_free(storage); } diff --git a/common/usbx_device_classes/src/ux_device_class_storage_write.c b/common/usbx_device_classes/src/ux_device_class_storage_write.c index 47560f0f..50edd817 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_write.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_write.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_write PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed USB CV test issues, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_write(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, @@ -94,11 +97,15 @@ UINT status; UX_SLAVE_TRANSFER *transfer_request; ULONG lba; ULONG total_number_blocks; -ULONG number_blocks; ULONG media_status; ULONG total_length; + +#if !defined(UX_DEVICE_STANDALONE) +ULONG number_blocks; ULONG transfer_length; ULONG done_length; +#endif + UX_PARAMETER_NOT_USED(endpoint_in); @@ -139,7 +146,9 @@ ULONG done_length; /* We have a problem, media status error. Return a bad completion and wait for the REQUEST_SENSE command. */ +#if !defined(UX_DEVICE_STANDALONE) _ux_device_stack_endpoint_stall(endpoint_out); +#endif /* We are done here. */ return(UX_ERROR); @@ -156,7 +165,9 @@ ULONG done_length; /* We have a problem, cannot write to RO drive. Return a bad completion and wait for the REQUEST_SENSE command. */ +#if !defined(UX_DEVICE_STANDALONE) _ux_device_stack_endpoint_stall(endpoint_out); +#endif /* We are done here. */ return(UX_ERROR); @@ -165,6 +176,27 @@ ULONG done_length; /* Compute the total length to transfer and how much remains. */ total_length = total_number_blocks * storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length; +#if defined(UX_DEVICE_STANDALONE) + + /* Next: Transfer (DATA) -> Disk write. */ + storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START; + storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_WRITE; + storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT; + storage -> ux_device_class_storage_buffer_state[0] = UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + storage -> ux_device_class_storage_buffer_state[1] = UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY; + storage -> ux_device_class_storage_buffer_usb = 0; + storage -> ux_device_class_storage_buffer_disk = 0; + + storage -> ux_device_class_storage_transfer = transfer_request; + storage -> ux_device_class_storage_device_length = total_length; + storage -> ux_device_class_storage_data_length = total_length; + storage -> ux_device_class_storage_data_count = 0; + + storage -> ux_device_class_storage_cmd_lba = lba; + storage -> ux_device_class_storage_cmd_n_lb = total_number_blocks; + +#else + /* Check transfer length. */ /* Case (3) Hn < Do. */ @@ -258,6 +290,8 @@ ULONG done_length; if (storage -> ux_slave_class_storage_csw_residue) _ux_device_stack_endpoint_stall(endpoint_out); +#endif /* else defined(UX_DEVICE_STANDALONE) */ + /* Now we set the CSW with success. */ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED; diff --git a/common/usbx_host_classes/CMakeLists.txt b/common/usbx_host_classes/CMakeLists.txt index 40880195..48ac6b1a 100644 --- a/common/usbx_host_classes/CMakeLists.txt +++ b/common/usbx_host_classes/CMakeLists.txt @@ -44,7 +44,9 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_stop.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_transmission_callback.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_write_with_callback.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_deactivate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_endpoints_get.c @@ -78,6 +80,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_global_item_parse.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_instance_clean.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_interrupt_endpoint_search.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_item_data_get.c @@ -87,6 +90,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_key_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_local_item_parse.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_main_item_parse.c @@ -113,7 +117,9 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_id_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_item_analyse.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_set_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_resources_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_transfer_request_completed.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_change_detect.c @@ -191,6 +197,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_write.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_cbw_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_check_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_configure.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_deactivate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_initialize.c @@ -199,9 +206,11 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_driver_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_endpoints_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_lock.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_max_lun_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_capacity_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_characteristics_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_check.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_format_capacity_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_lock.c @@ -212,14 +221,17 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_recovery_sense_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_write.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_partition_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_read_write_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_request_sense.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_sense_code_translate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_start_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_thread_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_bo.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cb.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cbi.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_unit_ready_test.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_configure.c diff --git a/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h b/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h index 52275410..da5389c2 100644 --- a/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h +++ b/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_cdc_acm.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -50,6 +50,11 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* used defined line coding */ +/* instead of magic number, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -93,6 +98,9 @@ extern "C" { #define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DCM 0x01 #define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DCI 0x02 +/* Define CDC ACM Class union interface functional descriptors. */ +#define UX_HOST_CLASS_CDC_ACM_UNION_FUNCTIONAL_MASTER 0x03 + /* Define CDC ACM command request values. */ #define UX_HOST_CLASS_CDC_ACM_REQ_SEND_ENCAPSULATED_COMMAND 0x00 @@ -140,6 +148,8 @@ extern "C" { /* Define CDC ACM default values. */ #define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE 9600 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT 0 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY 0 #define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT 8 /* Define CDC ACM line coding definitions. */ @@ -175,6 +185,8 @@ extern "C" { #define UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE 6 #define UX_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK 7 #define UX_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS 8 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_WRITE_CALLBACK 9 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_GET_WRITE_STATUS 10 /* Define CDC ACM Reception States. */ @@ -213,15 +225,33 @@ typedef struct UX_HOST_CLASS_CDC_ACM_STRUCT UX_INTERFACE *ux_host_class_cdc_acm_interface; UINT ux_host_class_cdc_acm_instance_status; UINT ux_host_class_cdc_acm_state; - UX_SEMAPHORE ux_host_class_cdc_acm_semaphore; ULONG ux_host_class_cdc_acm_notification_count; - UCHAR ux_host_class_cdc_acm_capabilities; + ULONG ux_host_class_cdc_acm_capabilities; ULONG ux_host_class_cdc_acm_device_state; struct UX_HOST_CLASS_CDC_ACM_RECEPTION_STRUCT *ux_host_class_cdc_acm_reception; VOID (*ux_host_class_cdc_acm_device_status_change_callback)(struct UX_HOST_CLASS_CDC_ACM_STRUCT *cdc_acm, ULONG notification_type, ULONG notification_value); +#if !defined(UX_HOST_STANDALONE) + UX_SEMAPHORE ux_host_class_cdc_acm_semaphore; +#else + UINT ux_host_class_cdc_acm_status; + VOID *ux_host_class_cdc_acm_allocated; + ULONG ux_host_class_cdc_acm_interfaces_bitmap; + ULONG ux_host_class_cdc_acm_tick; + struct UX_HOST_CLASS_CDC_ACM_STRUCT + *ux_host_class_cdc_acm_control; + ULONG ux_host_class_cdc_acm_write_length; + ULONG ux_host_class_cdc_acm_write_count; + VOID (*ux_host_class_cdc_acm_write_callback)( + struct UX_HOST_CLASS_CDC_ACM_STRUCT *cdc_acm, + UINT status, ULONG length); + UCHAR ux_host_class_cdc_acm_cmd_state; + UCHAR ux_host_class_cdc_acm_read_state; + UCHAR ux_host_class_cdc_acm_write_state; + UCHAR ux_host_class_cdc_acm_next_state; +#endif } UX_HOST_CLASS_CDC_ACM; /* Define CDC DLC Class instance structure. */ @@ -239,12 +269,26 @@ typedef struct UX_HOST_CLASS_CDC_DLC_STRUCT UX_INTERFACE *ux_host_class_cdc_dlc_interface; UINT ux_host_class_cdc_dlc_instance_status; UINT ux_host_class_cdc_dlc_state; - UX_SEMAPHORE ux_host_class_cdc_dlc_semaphore; ULONG ux_host_class_cdc_dlc_notification_count; - UCHAR ux_host_class_cdc_dlc_capabilities; + ULONG ux_host_class_cdc_dlc_capabilities; struct UX_HOST_CLASS_CDC_DLC_RECEPTION_STRUCT *ux_host_class_cdc_dlc_reception; - +#if !defined(UX_HOST_STANDALONE) + UX_SEMAPHORE ux_host_class_cdc_dlc_semaphore; +#else + ULONG ux_host_class_cdc_dlc_interfaces_bitmap; + struct UX_HOST_CLASS_CDC_ACM_STRUCT + *ux_host_class_cdc_dlc_control; + ULONG ux_host_class_cdc_dlc_write_length; + ULONG ux_host_class_cdc_dlc_write_count; + VOID (*ux_host_class_cdc_dlc_write_callback)( + struct UX_HOST_CLASS_CDC_ACM_STRUCT *cdc_acm, + UINT status, ULONG length); + UCHAR ux_host_class_cdc_dlc_cmd_state; + UCHAR ux_host_class_cdc_dlc_read_state; + UCHAR ux_host_class_cdc_dlc_write_state; + UCHAR ux_host_class_cdc_dlc_next_state; +#endif } UX_HOST_CLASS_CDC_DLC; /* Define CDC ACM reception structure. */ @@ -320,6 +364,9 @@ UINT _ux_host_class_cdc_acm_reception_start (UX_HOST_CLASS_CDC_ACM *cdc_acm, VOID _ux_host_class_cdc_acm_reception_callback (UX_TRANSFER *transfer_request); +UINT _ux_host_class_cdc_acm_write_with_callback(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, + ULONG requested_length); +VOID _ux_host_class_cdc_acm_transmission_callback(UX_TRANSFER *transfer_request); /* Define CDC ACM Class API prototypes. */ @@ -330,6 +377,7 @@ VOID _ux_host_class_cdc_acm_reception_callback (UX_TRANSFER *transfer_request); #define ux_host_class_cdc_acm_reception_start _ux_host_class_cdc_acm_reception_start #define ux_host_class_cdc_acm_reception_stop _ux_host_class_cdc_acm_reception_stop +#define ux_host_class_cdc_acm_write_with_callback _ux_host_class_cdc_acm_write_with_callback /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/usbx_host_classes/inc/ux_host_class_hid.h b/common/usbx_host_classes/inc/ux_host_class_hid.h index 253b7892..7770b37a 100644 --- a/common/usbx_host_classes/inc/ux_host_class_hid.h +++ b/common/usbx_host_classes/inc/ux_host_class_hid.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_hid.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -51,6 +51,10 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Xiuwen Cai, CQ Xiao Modified comment(s), */ +/* added interrupt OUT support,*/ +/* added standalone mode, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -765,6 +769,14 @@ extern "C" { #define UX_HOST_CLASS_HID_MAX_GLOBAL 4 #define UX_HOST_CLASS_HID_MAX_COLLECTION 4 +/* Define HID flags. */ +#define UX_HOST_CLASS_HID_FLAG_LOCK 1ul +#define UX_HOST_CLASS_HID_FLAG_PROTECT 2ul + +#ifndef UX_HOST_CLASS_HID_REPORT_TRANSFER_TIMEOUT +#define UX_HOST_CLASS_HID_REPORT_TRANSFER_TIMEOUT 10000 +#endif + /* Define HID Class descriptor. */ typedef struct UX_HID_DESCRIPTOR_STRUCT @@ -943,6 +955,9 @@ typedef struct UX_HOST_CLASS_HID_STRUCT UX_HOST_CLASS *ux_host_class_hid_class; UX_DEVICE *ux_host_class_hid_device; UX_ENDPOINT *ux_host_class_hid_interrupt_endpoint; +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) + UX_ENDPOINT *ux_host_class_hid_interrupt_out_endpoint; +#endif UINT ux_host_class_hid_interrupt_endpoint_status; UX_INTERFACE *ux_host_class_hid_interface; ULONG ux_host_class_hid_state; @@ -952,9 +967,43 @@ typedef struct UX_HOST_CLASS_HID_STRUCT ux_host_class_hid_parser; struct UX_HOST_CLASS_HID_CLIENT_STRUCT *ux_host_class_hid_client; +#if !defined(UX_HOST_STANDALONE) UX_SEMAPHORE ux_host_class_hid_semaphore; +#else + ULONG ux_host_class_hid_flags; + UCHAR *ux_host_class_hid_allocated; + UINT ux_host_class_hid_status; + UCHAR ux_host_class_hid_enum_state; + UCHAR ux_host_class_hid_next_state; + UCHAR ux_host_class_hid_cmd_state; + UCHAR reserved[1]; +#endif } UX_HOST_CLASS_HID; +#if defined(UX_HOST_STANDALONE) +#define _ux_host_class_hid_lock_fail_return(hid) \ + UX_DISABLE \ + if (hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) \ + { \ + UX_RESTORE \ + status = UX_BUSY; \ + return(status); \ + } \ + hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_LOCK; \ + UX_RESTORE +#define _ux_host_class_hid_unlock(hid) do { \ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; \ + } while(0) +#else +#define _ux_host_class_hid_lock_fail_return(hid) \ + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, \ + UX_WAIT_FOREVER); \ + if (status != UX_SUCCESS) \ + return(status); +#define _ux_host_class_hid_unlock(hid) \ + _ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore); +#endif + /* Define HID Class client command format structure. */ @@ -989,9 +1038,16 @@ typedef struct UX_HOST_CLASS_HID_CLIENT_STRUCT { ULONG ux_host_class_hid_client_status; +#if defined(UX_NAME_REFERENCED_BY_POINTER) + UCHAR *ux_host_class_hid_client_name; +#else UCHAR ux_host_class_hid_client_name[UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ +#endif UINT (*ux_host_class_hid_client_handler) (struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT *); VOID *ux_host_class_hid_client_local_instance; +#if defined(UX_HOST_STANDALONE) + VOID (*ux_host_class_hid_client_function)(struct UX_HOST_CLASS_HID_CLIENT_STRUCT *); +#endif } UX_HOST_CLASS_HID_CLIENT; /* Define HID Class function prototypes. */ @@ -1029,6 +1085,10 @@ UINT _ux_host_class_hid_report_set(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ UINT _ux_host_class_hid_resources_free(UX_HOST_CLASS_HID *hid); VOID _ux_host_class_hid_transfer_request_completed(UX_TRANSFER *transfer_request); +UINT _ux_host_class_hid_tasks_run(UX_HOST_CLASS *hid_class); +UINT _ux_host_class_hid_idle_set_run(UX_HOST_CLASS_HID *hid, USHORT idle_time, USHORT report_id); +UINT _ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report); + /* Define HID Class API prototypes. */ #define ux_host_class_hid_client_register _ux_host_class_hid_client_register diff --git a/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h b/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h index df42c23b..ba87ee84 100644 --- a/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h +++ b/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_hid_keyboard.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -50,6 +50,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -204,11 +207,19 @@ typedef struct UX_HOST_CLASS_HID_KEYBOARD_STRUCT ULONG ux_host_class_hid_keyboard_key_count; UX_HOST_CLASS_HID *ux_host_class_hid_keyboard_hid; USHORT ux_host_class_hid_keyboard_id; +#if !defined(UX_HOST_STANDALONE) + VOID *ux_host_class_hid_keyboard_thread_stack; UX_THREAD ux_host_class_hid_keyboard_thread; UX_SEMAPHORE ux_host_class_hid_keyboard_semaphore; +#else + UINT ux_host_class_hid_keyboard_status; + UCHAR ux_host_class_hid_keyboard_enum_state; + UCHAR ux_host_class_hid_keyboard_next_state; + UCHAR ux_host_class_hid_keyboard_out_state; + UCHAR reserved; +#endif ULONG ux_host_class_hid_keyboard_alternate_key_state; ULONG ux_host_class_hid_keyboard_led_mask; - VOID *ux_host_class_hid_keyboard_thread_stack; ULONG *ux_host_class_hid_keyboard_usage_array; ULONG *ux_host_class_hid_keyboard_usage_array_head; ULONG *ux_host_class_hid_keyboard_usage_array_tail; @@ -228,6 +239,8 @@ UINT _ux_host_class_hid_keyboard_key_get(UX_HOST_CLASS_HID_KEYBOARD *keyboard UINT _ux_host_class_hid_keyboard_ioctl(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance, ULONG ioctl_function, VOID *parameter); +VOID _ux_host_class_hid_keyboard_tasks_run(UX_HOST_CLASS_HID_CLIENT *client); + /* Define HID Keyboard Class API prototypes. */ #define ux_host_class_hid_keyboard_entry _ux_host_class_hid_keyboard_entry diff --git a/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h b/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h index 9df9526f..9e01f269 100644 --- a/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h +++ b/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_hid_mouse.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -47,6 +47,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -95,7 +98,10 @@ typedef struct UX_HOST_CLASS_HID_MOUSE_STRUCT SLONG ux_host_class_hid_mouse_y_position; ULONG ux_host_class_hid_mouse_buttons; SLONG ux_host_class_hid_mouse_wheel; - +#if defined(UX_HOST_STANDALONE) + UINT ux_host_class_hid_mouse_enum_state; + UINT ux_host_class_hid_mouse_status; +#endif } UX_HOST_CLASS_HID_MOUSE; diff --git a/common/usbx_host_classes/inc/ux_host_class_printer.h b/common/usbx_host_classes/inc/ux_host_class_printer.h index 4f080114..ccdd0c34 100644 --- a/common/usbx_host_classes/inc/ux_host_class_printer.h +++ b/common/usbx_host_classes/inc/ux_host_class_printer.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_printer.h PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -53,6 +53,10 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* added entry public define, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* added a new protocol const, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -76,6 +80,7 @@ extern "C" { #define UX_HOST_CLASS_PRINTER_CLASS 7 #define UX_HOST_CLASS_PRINTER_SUBCLASS 1 #define UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL 2 +#define UX_HOST_CLASS_PRINTER_PROTOCOL_IEEE_1284_4_BI_DIR 3 #define UX_HOST_CLASS_PRINTER_GET_STATUS 1 #define UX_HOST_CLASS_PRINTER_SOFT_RESET 2 #define UX_HOST_CLASS_PRINTER_STATUS_LENGTH 4 @@ -94,6 +99,12 @@ extern "C" { #define UX_HOST_CLASS_PRINTER_GENERIC_NAME "USB PRINTER" + +/* Define Printer flag constants. */ + +#define UX_HOST_CLASS_PRINTER_FLAG_LOCK 0x1u + + /* Define Printer Class structure. */ typedef struct UX_HOST_CLASS_PRINTER_STRUCT @@ -108,10 +119,27 @@ typedef struct UX_HOST_CLASS_PRINTER_STRUCT UX_ENDPOINT *ux_host_class_printer_bulk_in_endpoint; UINT ux_host_class_printer_state; UCHAR ux_host_class_printer_name[UX_HOST_CLASS_PRINTER_NAME_LENGTH]; +#if !defined(UX_HOST_STANDALONE) UX_SEMAPHORE ux_host_class_printer_semaphore; +#else + UCHAR *ux_host_class_printer_allocated; + ULONG ux_host_class_printer_flags; + UINT ux_host_class_printer_status; + UCHAR ux_host_class_printer_enum_state; + UCHAR ux_host_class_printer_read_state; + UCHAR ux_host_class_printer_write_state; + UCHAR ux_host_class_printer_next_state; +#endif } UX_HOST_CLASS_PRINTER; +#if !defined(UX_HOST_STANDALONE) +#define _ux_host_class_printer_unlock(printer) _ux_host_semaphore_put(&(printer) -> ux_host_class_printer_semaphore) +#else +#define _ux_host_class_printer_unlock(printer) do { (printer)->ux_host_class_printer_flags &= ~UX_HOST_CLASS_PRINTER_FLAG_LOCK; } while(0) +#endif + + /* Define Printer Class function prototypes. */ UINT _ux_host_class_printer_activate(UX_HOST_CLASS_COMMAND *command); diff --git a/common/usbx_host_classes/inc/ux_host_class_storage.h b/common/usbx_host_classes/inc/ux_host_class_storage.h index ea4b678c..e961f722 100755 --- a/common/usbx_host_classes/inc/ux_host_class_storage.h +++ b/common/usbx_host_classes/inc/ux_host_class_storage.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_storage.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,6 +61,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -78,7 +81,7 @@ extern "C" { #endif -#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) +#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) && !defined(UX_HOST_STANDALONE) /* Include the FileX API. */ #include "fx_api.h" @@ -143,6 +146,11 @@ extern "C" { #define UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE #endif +#if defined(UX_HOST_STANDALONE) && !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) +#define UX_HOST_CLASS_STORAGE_NO_FILEX +#endif + + /* Define Storage Class constants. */ #define UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY (200) @@ -376,6 +384,21 @@ extern "C" { #define UX_HOST_CLASS_STORAGE_SENSE_KEY_VOLUME_OVERFLOW 0x0d #define UX_HOST_CLASS_STORAGE_SENSE_KEY_MISCOMPARE 0x0e +#define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_READY 0x04 +#define UX_HOST_CLASS_STORAGE_SENSE_CODE_WRITE_PROTECTED 0x27 +#define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_READY_TO_READY 0x28 +#define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_PRESENT 0x3A + +/* Convertion between sense status and sense key, ASC, ASCQ. */ + +#define UX_HOST_CLASS_STORAGE_SENSE_STATUS(key,ascode,ascqualifier) (((key) << 16) | ((ascode) << 8) | (ascqualifier)) +#define UX_HOST_CLASS_STORAGE_SENSE_QUALIFIER(status) ((status) & 0xFF) +#define UX_HOST_CLASS_STORAGE_SENSE_CODE(status) (((status) >> 8) & 0xFF) +#define UX_HOST_CLASS_STORAGE_SENSE_KEY(status) (((status) >> 16) & 0xFF) +#define UX_HOST_CLASS_STORAGE_SENSE_ASCQ(status) UX_HOST_CLASS_STORAGE_SENSE_QUALIFIER(status) +#define UX_HOST_CLASS_STORAGE_SENSE_ASC(status) UX_HOST_CLASS_STORAGE_SENSE_CODE(status) + + /* Define Mode Sense page codes. */ #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RWER_PAGE 0x01 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_FD_PAGE 0x05 @@ -457,17 +480,106 @@ typedef struct UX_HOST_CLASS_STORAGE_STRUCT #endif ULONG ux_host_class_storage_sector_size; ULONG ux_host_class_storage_data_phase_length; - UINT (*ux_host_class_storage_transport) (struct UX_HOST_CLASS_STORAGE_STRUCT *storage, UCHAR * data_pointer); ULONG ux_host_class_storage_sense_code; UCHAR *ux_host_class_storage_memory; +#if !defined(UX_HOST_STANDALONE) + UINT (*ux_host_class_storage_transport) (struct UX_HOST_CLASS_STORAGE_STRUCT *storage, UCHAR * data_pointer); UX_SEMAPHORE ux_host_class_storage_semaphore; +#else + ULONG ux_host_class_storage_flags; + UINT ux_host_class_storage_status; + UCHAR *ux_host_class_storage_sense_memory; + + /* State info for transport state machine. */ + UX_TRANSFER *ux_host_class_storage_trans; + UCHAR *ux_host_class_storage_trans_data; + UCHAR *ux_host_class_storage_trans_data_bak; + UCHAR ux_host_class_storage_trans_state; + UCHAR ux_host_class_storage_trans_stage; + UCHAR ux_host_class_storage_trans_retry; + UCHAR ux_host_class_storage_trans_status; + + /* State info for media main state machine. */ + ULONG ux_host_class_storage_delay_start; + ULONG ux_host_class_storage_delay_ms; + UCHAR ux_host_class_storage_state_state; + UCHAR ux_host_class_storage_state_next; + UCHAR ux_host_class_storage_check_lun; + UCHAR ux_host_class_storage_op_state; + UCHAR ux_host_class_storage_dbg_state; + UCHAR ux_host_class_storage_dbg_rw_state; + UCHAR ux_host_class_storage_dbg_trans_state; + UCHAR ux_host_class_storage_dbg_trans_stage; + ULONG ux_host_class_storage_dbg_state_count; + ULONG ux_host_class_storage_dbg_rw_state_count; + ULONG ux_host_class_storage_dbg_trans_state_count; + +#endif } UX_HOST_CLASS_STORAGE; +#define UX_HOST_CLASS_STORAGE_FLAG_PROTECT (1ul << 0) +#define UX_HOST_CLASS_STORAGE_FLAG_LOCK (1ul << 1) +#define UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT (1ul << 2) + +/* Read/write states. */ + +#define UX_HOST_CLASS_STORAGE_RW_STATE_RESET(s) ((s) -> ux_host_class_storage_op_state = UX_STATE_RESET) +#define UX_HOST_CLASS_STORAGE_RW_STATE_IS_IDLE(s) ((s) -> ux_host_class_storage_op_state == UX_STATE_IDLE) +#define UX_HOST_CLASS_STORAGE_RW_STATE_IS_RESET(s) ((s) -> ux_host_class_storage_op_state == UX_STATE_RESET) +#define UX_HOST_CLASS_STORAGE_RW_IS_IDLE(s) (UX_HOST_CLASS_STORAGE_RW_STATE_IS_IDLE(s) || UX_HOST_CLASS_STORAGE_RW_STATE_IS_RESET(s)) + +/* Main states. */ + +#define UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET (UX_STATE_CLASS_STEP + 0) +#define UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE (UX_STATE_CLASS_STEP + 1) +#define UX_HOST_CLASS_STORAGE_STATE_CHECK_START (UX_STATE_CLASS_STEP + 2) +#define UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT (UX_STATE_CLASS_STEP + 3) +#define UX_HOST_CLASS_STORAGE_STATE_TEST_READY (UX_STATE_CLASS_STEP + 4) +#define UX_HOST_CLASS_STORAGE_STATE_TEST_CHECK (UX_STATE_CLASS_STEP + 5) +#define UX_HOST_CLASS_STORAGE_STATE_INQUIRY (UX_STATE_CLASS_STEP + 6) +#define UX_HOST_CLASS_STORAGE_STATE_INQUIRY_SAVE (UX_STATE_CLASS_STEP + 7) +#define UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET (UX_STATE_CLASS_STEP + 8) +#define UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_SAVE (UX_STATE_CLASS_STEP + 9) +#define UX_HOST_CLASS_STORAGE_STATE_CAP_GET (UX_STATE_CLASS_STEP + 10) +#define UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE (UX_STATE_CLASS_STEP + 11) +#define UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN (UX_STATE_CLASS_STEP + 12) +#define UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT (UX_STATE_CLASS_STEP + 13) +#define UX_HOST_CLASS_STORAGE_STATE_TRANSPORT (UX_STATE_CLASS_STEP + 14) +#define UX_HOST_CLASS_STORAGE_STATE_TRANSFER (UX_STATE_CLASS_STEP + 15) +#define UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE (UX_STATE_CLASS_STEP + 16) + +/* Transport states. */ + +#define UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(s) do { \ + (s) -> ux_host_class_storage_trans_state = UX_STATE_RESET; \ + (s) -> ux_host_class_storage_trans_data = UX_NULL; \ + } while(0) \ + +#define UX_HOST_CLASS_STORAGE_TRANS_CBW (UX_STATE_CLASS_STEP + 0) +#define UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT (UX_STATE_CLASS_STEP + 1) +#define UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT (UX_STATE_CLASS_STEP + 2) +#define UX_HOST_CLASS_STORAGE_TRANS_CSW (UX_STATE_CLASS_STEP + 3) +#define UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE (UX_STATE_CLASS_STEP + 4) +#define UX_HOST_CLASS_STORAGE_TRANS_WAIT (UX_STATE_CLASS_STEP + 5) +#define UX_HOST_CLASS_STORAGE_TRANS_STATUS (UX_STATE_CLASS_STEP + 6) +#define UX_HOST_CLASS_STORAGE_TRANS_MS_RESET (UX_STATE_CLASS_STEP + 7) +#define UX_HOST_CLASS_STORAGE_TRANS_EP_RESET (UX_STATE_CLASS_STEP + 8) +#define UX_HOST_CLASS_STORAGE_TRANS_RESET_NEXT (UX_STATE_CLASS_STEP + 9) + +#define UX_HOST_CLASS_STORAGE_STAGE_CBW (0x00u) +#define UX_HOST_CLASS_STORAGE_STAGE_DATA (0x01u) +#define UX_HOST_CLASS_STORAGE_STAGE_CSW (0x02u) +#define UX_HOST_CLASS_STORAGE_STAGE_MS_RESET (0x04u) +#define UX_HOST_CLASS_STORAGE_STAGE_EP_RESET (0x08u) typedef struct UX_HOST_CLASS_STORAGE_EXT_STRUCT { +#if !defined(UX_HOST_STANDALONE) UX_THREAD ux_host_class_thread; CHAR ux_host_class_thread_stack[UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE]; +#else + ALIGN_TYPE reserved; +#endif } UX_HOST_CLASS_STORAGE_EXT; @@ -489,7 +601,7 @@ typedef struct UX_HOST_CLASS_STORAGE_MEDIA_STRUCT ULONG ux_host_class_storage_media_number_sectors; USHORT ux_host_class_storage_media_sector_size; UCHAR ux_host_class_storage_media_lun; - UCHAR reserved; + UCHAR ux_host_class_storage_media_status; #endif } UX_HOST_CLASS_STORAGE_MEDIA; @@ -505,15 +617,11 @@ UINT _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command); UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage); UINT _ux_host_class_storage_device_reset(UX_HOST_CLASS_STORAGE *storage); UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage); + #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) VOID _ux_host_class_storage_driver_entry(UX_MEDIA *media); -#else -#define _ux_host_class_storage_lock(s,w) _ux_utility_semaphore_get(&(s) -> ux_host_class_storage_semaphore, (w)) -#define _ux_host_class_storage_unlock(s) _ux_utility_semaphore_put(&(s) -> ux_host_class_storage_semaphore) -UINT _ux_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, ULONG media_index, UX_HOST_CLASS_STORAGE_MEDIA **storage_media); -UINT _ux_host_class_storage_media_lock(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG wait); -#define _ux_host_class_storage_media_unlock(m) _ux_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) #endif + UINT _ux_host_class_storage_endpoints_get(UX_HOST_CLASS_STORAGE *storage); UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command); UINT _ux_host_class_storage_max_lun_get(UX_HOST_CLASS_STORAGE *storage); @@ -540,17 +648,49 @@ UINT _ux_host_class_storage_transport_cb(UX_HOST_CLASS_STORAGE *storage, UCHA UINT _ux_host_class_storage_transport_cbi(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); UINT _ux_host_class_storage_unit_ready_test(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, ULONG media_lun, UX_HOST_CLASS_STORAGE_MEDIA **storage_media); +UINT _ux_host_class_storage_media_lock(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG wait); + +#if defined(UX_HOST_STANDALONE) +UINT _ux_host_class_storage_lock(UX_HOST_CLASS_STORAGE *storage, ULONG wait); +#define _ux_host_class_storage_unlock(s) do { (s) -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK; } while(0) +#define _ux_host_class_storage_media_unlock(m) _ux_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) +#else +#define _ux_host_class_storage_lock(s,w) _ux_host_semaphore_get(&(s) -> ux_host_class_storage_semaphore, (w)) +#define _ux_host_class_storage_unlock(s) _ux_host_semaphore_put(&(s) -> ux_host_class_storage_semaphore) +#define _ux_host_class_storage_media_unlock(m) _ux_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) +#endif +#define _ux_host_class_storage_max_lun(s) ((s) -> ux_host_class_storage_max_lun) +#define _ux_host_class_storage_lun(s) ((s) -> ux_host_class_storage_lun) +#define _ux_host_class_storage_lun_select(s,l) do { (s) -> ux_host_class_storage_lun = (l); } while(0) +#define _ux_host_class_storage_sense_status(s) ((s) -> ux_host_class_storage_sense_code) + +UINT _ux_host_class_storage_media_check(UX_HOST_CLASS_STORAGE *storage); + +UINT _ux_host_class_storage_tasks_run(UX_HOST_CLASS *storage_class); +UINT _ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_check_run(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE *storage, + ULONG read_write, ULONG sector_start, ULONG sector_count, UCHAR *data_pointer); + /* Define Storage Class API prototypes. */ #define ux_host_class_storage_entry _ux_host_class_storage_entry + +#define ux_host_class_storage_lock _ux_host_class_storage_lock +#define ux_host_class_storage_unlock _ux_host_class_storage_unlock +#define ux_host_class_storage_lun_select _ux_host_class_storage_lun_select + #define ux_host_class_storage_media_read _ux_host_class_storage_media_read #define ux_host_class_storage_media_write _ux_host_class_storage_media_write -#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX) #define ux_host_class_storage_media_get _ux_host_class_storage_media_get #define ux_host_class_storage_media_lock _ux_host_class_storage_media_lock #define ux_host_class_storage_media_unlock _ux_host_class_storage_media_unlock -#endif + +#define ux_host_class_storage_media_check _ux_host_class_storage_media_check + +#define ux_host_class_storage_sense_status _ux_host_class_storage_sense_status /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/usbx_host_classes/src/ux_host_class_asix_activate.c b/common/usbx_host_classes/src/ux_host_class_asix_activate.c index d39e31e2..a243a072 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_activate.c @@ -36,7 +36,7 @@ UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,8 +64,8 @@ UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* _ux_host_stack_transfer_request Transfer request */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_create Create semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_thread_create Create thread */ /* _ux_utility_thread_delete Delete thread */ /* nx_packet_pool_create Create NetX packet pool */ @@ -84,6 +84,9 @@ UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND *command) @@ -137,7 +140,7 @@ UX_TRANSFER *transfer_request; /* Create the semaphore to protect 2 threads from accessing the same asix instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&asix -> ux_host_class_asix_semaphore, "ux_host_class_asix_semaphore", 1); + status = _ux_host_semaphore_create(&asix -> ux_host_class_asix_semaphore, "ux_host_class_asix_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -145,7 +148,7 @@ UX_TRANSFER *transfer_request; /* Create the semaphore to wake up the Asix thread. */ if(status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&asix -> ux_host_class_asix_interrupt_notification_semaphore, "ux_host_class_asix_interrupt_notification_semaphore", 0); + status = _ux_host_semaphore_create(&asix -> ux_host_class_asix_interrupt_notification_semaphore, "ux_host_class_asix_interrupt_notification_semaphore", 0); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -264,11 +267,11 @@ UX_TRANSFER *transfer_request; /* Free asix -> ux_host_class_asix_interrupt_notification_semaphore. */ if (asix -> ux_host_class_asix_interrupt_notification_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + _ux_host_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); /* Free asix -> ux_host_class_asix_semaphore. */ if (asix -> ux_host_class_asix_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_delete(&asix -> ux_host_class_asix_semaphore); /* Destroy class instance. */ _ux_host_stack_class_instance_destroy(asix -> ux_host_class_asix_class, (VOID *) asix); diff --git a/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c b/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c index de08299f..324848a6 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_delete Delete thread */ /* _ux_network_driver_deactivate Deactivate NetX USB interface */ /* nx_packet_transmit_release Release NetX packet */ @@ -77,6 +77,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -92,7 +95,7 @@ UINT status; asix = (UX_HOST_CLASS_ASIX *) command -> ux_host_class_command_instance; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -173,14 +176,14 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(asix -> ux_host_class_asix_class, (VOID *) asix); /* Destroy the semaphores. */ - _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_semaphore); - _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + _ux_host_semaphore_delete(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); /* Destroy the link monitoring thread. */ _ux_utility_thread_delete(&asix -> ux_host_class_asix_thread); diff --git a/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c b/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c index 13e8d97c..2a4437a6 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_interrupt_notification PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -55,7 +55,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_host_stack_transfer_request Transfer request */ /* */ /* CALLED BY */ @@ -73,6 +73,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_interrupt_notification(UX_TRANSFER *transfer_request) @@ -122,7 +125,7 @@ UX_HOST_CLASS_ASIX *asix; asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP; /* We need to inform the asix thread of this change. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); } } @@ -152,7 +155,7 @@ UX_HOST_CLASS_ASIX *asix; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Wake up the semaphore on which the transaction is waiting. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } @@ -171,13 +174,13 @@ UX_HOST_CLASS_ASIX *asix; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Wake up the semaphore on which the transaction is waiting. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } /* We need to inform the asix thread of this change. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); } } } diff --git a/common/usbx_host_classes/src/ux_host_class_asix_read.c b/common/usbx_host_classes/src/ux_host_class_asix_read.c index 68bea046..0aa05e2b 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_read.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -75,6 +75,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_read (UX_HOST_CLASS_ASIX *asix, UCHAR *data_pointer, @@ -130,7 +133,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_ASIX_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_ASIX_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_asix_thread.c b/common/usbx_host_classes/src/ux_host_class_asix_thread.c index 791458fe..053a0f59 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_thread.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -54,8 +54,8 @@ /* CALLS */ /* */ /* _ux_host_stack_transfer_request Transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ /* _ux_utility_memory_set Set memory */ @@ -78,6 +78,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_thread(ULONG parameter) @@ -102,7 +105,7 @@ ULONG physical_address_lsw; { /* Wait for the semaphore to be put by the asix interrupt event. */ - status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_interrupt_notification_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&asix -> ux_host_class_asix_interrupt_notification_semaphore, UX_WAIT_FOREVER); /* Check for successful completion. */ if (status != UX_SUCCESS) @@ -110,7 +113,7 @@ ULONG physical_address_lsw; return; /* Protect Thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); /* Check for successful completion. */ if (status != UX_SUCCESS) @@ -131,7 +134,7 @@ ULONG physical_address_lsw; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); return; } @@ -155,7 +158,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -182,7 +185,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -208,7 +211,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -241,7 +244,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -268,7 +271,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -299,7 +302,7 @@ ULONG physical_address_lsw; _ux_utility_memory_free(setup_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); /* Return completion status. */ return; @@ -369,7 +372,7 @@ ULONG physical_address_lsw; } /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); return; } @@ -414,7 +417,7 @@ ULONG physical_address_lsw; _ux_network_driver_link_down(asix -> ux_host_class_asix_network_handle); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); return; diff --git a/common/usbx_host_classes/src/ux_host_class_audio_activate.c b/common/usbx_host_classes/src/ux_host_class_audio_activate.c index 33e553b3..82a2800e 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,7 +64,7 @@ /* _ux_host_stack_class_instance_create Create class instance */ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_allocate Allocate a memory block */ -/* _ux_utility_semaphore_create Create protection semaphore */ +/* _ux_host_semaphore_create Create protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_activate(UX_HOST_CLASS_COMMAND *command) @@ -183,7 +186,7 @@ UINT status; /* Create the semaphore to protect multiple threads from accessing the same audio instance. */ - status = _ux_utility_semaphore_create(&audio -> ux_host_class_audio_semaphore, "ux_hot_class_audio_semaphore", 1); + status = _ux_host_semaphore_create(&audio -> ux_host_class_audio_semaphore, "ux_hot_class_audio_semaphore", 1); if (status != UX_SUCCESS) return(UX_SEMAPHORE_ERROR); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_get.c b/common/usbx_host_classes/src/ux_host_class_audio_control_get.c index 926555d9..71332f9d 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_control_get.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_control_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_get Read 16-bit value */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_control_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) @@ -101,7 +104,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -115,7 +118,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -123,7 +126,7 @@ UCHAR * control_buffer; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -156,7 +159,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -182,7 +185,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -206,7 +209,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c b/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c index d77e6df3..1096e53a 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_control_value_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_get Read 16-bit value */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_control_value_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) @@ -102,7 +105,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &audio -> ux_host_class_audio_device -> ux_device_control_endpoint; @@ -114,7 +117,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return error. */ return(UX_MEMORY_INSUFFICIENT); @@ -143,7 +146,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c b/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c index e1d1017c..250b3bc8 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_control_value_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_put Write 16-bit value */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_control_value_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) @@ -100,7 +103,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -114,7 +117,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -125,7 +128,7 @@ UCHAR * control_buffer; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -148,7 +151,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c b/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c index d81cc00a..85513026 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort outstanding transfer */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_memory_free Release memory block */ /* */ /* CALLED BY */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -88,7 +91,7 @@ UINT status; audio -> ux_host_class_audio_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -99,13 +102,13 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&audio -> ux_host_class_audio_semaphore); + _ux_host_semaphore_delete(&audio -> ux_host_class_audio_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_audio_read.c b/common/usbx_host_classes/src/ux_host_class_audio_read.c index 783edef9..868c9cb3 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_read.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_read PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_class_audio_transfer_request Audio transfer request */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +76,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_read(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request) @@ -101,7 +104,7 @@ UINT status; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -113,7 +116,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); @@ -140,7 +143,7 @@ UINT status; status = _ux_host_class_audio_transfer_request(audio, audio_transfer_request); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c index 411e0d1f..5777c478 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_streaming_sampling_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_utility_descriptor_parse Parse the descriptor */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_streaming_sampling_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING_CHARACTERISTICS *audio_sampling) @@ -109,7 +112,7 @@ UINT previous_match_found; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -143,7 +146,7 @@ UINT previous_match_found; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); return(UX_DESCRIPTOR_CORRUPTED); } @@ -225,7 +228,7 @@ UINT previous_match_found; audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* We have found the first streaming characteristics. */ return(UX_SUCCESS); @@ -293,7 +296,7 @@ UINT previous_match_found; audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = lower_frequency; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -331,7 +334,7 @@ UINT previous_match_found; audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = higher_frequency; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -347,7 +350,7 @@ UINT previous_match_found; audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = lower_frequency; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -369,7 +372,7 @@ UINT previous_match_found; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); return(UX_DESCRIPTOR_CORRUPTED); } @@ -382,7 +385,7 @@ UINT previous_match_found; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_NO_ALTERNATE_SETTING); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c index 447ffab2..763a8a64 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_streaming_sampling_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_interface_endpoint_get Get interface endpoint */ /* _ux_host_stack_interface_setting_select Select interface */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_streaming_sampling_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling) @@ -98,7 +101,7 @@ UINT streaming_interface; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(UX_HOST_CLASS_INSTANCE_UNKNOWN); @@ -110,7 +113,7 @@ UINT streaming_interface; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); return(status); } @@ -160,7 +163,7 @@ UINT streaming_interface; audio -> ux_host_class_audio_isochronous_endpoint = endpoint; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -175,7 +178,7 @@ UINT streaming_interface; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_NO_ALTERNATE_SETTING); diff --git a/common/usbx_host_classes/src/ux_host_class_audio_write.c b/common/usbx_host_classes/src/ux_host_class_audio_write.c index 481a741b..400d0bd8 100644 --- a/common/usbx_host_classes/src/ux_host_class_audio_write.c +++ b/common/usbx_host_classes/src/ux_host_class_audio_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_audio_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_class_audio_transfer_request Start audio transfer request */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_audio_write(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request) @@ -97,7 +100,7 @@ UINT status; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -109,7 +112,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); @@ -131,7 +134,7 @@ UINT status; status = _ux_host_class_audio_transfer_request(audio, audio_transfer_request); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + status = _ux_host_semaphore_put(&audio -> ux_host_class_audio_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c index 26bd13e0..d0c27362 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* _ux_host_stack_endpoint_transfer_abort Abort transfer */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_semaphore_create Create cdc_acm semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_create Create cdc_acm semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_delay_ms Delay */ /* */ /* CALLED BY */ @@ -77,6 +77,11 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* used defined line coding */ +/* instead of magic number, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_activate(UX_HOST_CLASS_COMMAND *command) @@ -84,9 +89,17 @@ UINT _ux_host_class_cdc_acm_activate(UX_HOST_CLASS_COMMAND *command) UX_INTERFACE *interface; UX_HOST_CLASS_CDC_ACM *cdc_acm; +UINT status; +#if defined(UX_HOST_STANDALONE) +UX_HOST_CLASS *cdc_acm_class; +UX_HOST_CLASS_CDC_ACM *cdc_acm_inst; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +ULONG descriptors_length; +#else UX_HOST_CLASS_CDC_ACM_LINE_CODING line_coding; UX_HOST_CLASS_CDC_ACM_LINE_STATE line_state; -UINT status; +#endif /* The CDC ACM class is always activated by the interface descriptor and not the device descriptor. */ @@ -101,8 +114,10 @@ UINT status; /* Memory allocation fail. */ return(UX_MEMORY_INSUFFICIENT); +#if !defined(UX_HOST_STANDALONE) + /* Create the semaphore to protect 2 threads from accessing the same acm instance. */ - status = _ux_utility_semaphore_create(&cdc_acm -> ux_host_class_cdc_acm_semaphore, "ux_host_class_cdc_acm_semaphore", 1); + status = _ux_host_semaphore_create(&cdc_acm -> ux_host_class_cdc_acm_semaphore, "ux_host_class_cdc_acm_semaphore", 1); if (status != UX_SUCCESS) { @@ -112,6 +127,7 @@ UINT status; /* Semaphore creation error. */ return(UX_SEMAPHORE_ERROR); } +#endif /* Store the class container into this instance. */ cdc_acm -> ux_host_class_cdc_acm_class = command -> ux_host_class_command_class_ptr; @@ -128,6 +144,107 @@ UINT status; /* Create this class instance. */ _ux_host_stack_class_instance_create(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); +#if defined(UX_HOST_STANDALONE) + + /* Get the cdc_acm endpoint(s). Depending on the interface type, we will need to search for + Bulk Out and Bulk In endpoints and the optional interrupt endpoint. */ + status = _ux_host_class_cdc_acm_endpoints_get(cdc_acm); + + /* Mark the cdc_acm as mounting. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* If we have the Control Class, we process default setup command sequence. */ + if (interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) + { + + /* Get descriptors to see capabilities. */ + + /* Get default control transfer. */ + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Allocate memory for the descriptors. */ + descriptors_length = interface -> ux_interface_configuration -> + ux_configuration_descriptor.wTotalLength; + cdc_acm -> ux_host_class_cdc_acm_allocated = + _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + descriptors_length); + if (cdc_acm -> ux_host_class_cdc_acm_allocated != UX_NULL) + { + + transfer_request -> ux_transfer_request_data_pointer = + cdc_acm -> ux_host_class_cdc_acm_allocated; + + /* Create transfer for GET_DESCRIPTOR. */ + transfer_request -> ux_transfer_request_requested_length = descriptors_length; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Set state to wait and next is "next". */ + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_STATE_WAIT; + cdc_acm -> ux_host_class_cdc_acm_next_state = UX_STATE_NEXT; + + /* ACTIVATE_WAIT will be processed to finish next steps. */ + return(UX_SUCCESS); + } + else + status = UX_MEMORY_INSUFFICIENT; + } + else + { + + /* We scan CDC ACM instances to find the master instance. */ + /* Get class. */ + cdc_acm_class = cdc_acm -> ux_host_class_cdc_acm_class; + + /* Get first instance linked to the class. */ + cdc_acm_inst = (UX_HOST_CLASS_CDC_ACM *)cdc_acm_class -> ux_host_class_first_instance; + + /* Scan all instances. */ + while(cdc_acm_inst) + { + + /* If this data interface is inside the associate list, link it. */ + if (cdc_acm_inst -> ux_host_class_cdc_acm_interfaces_bitmap & + (1ul << interface -> ux_interface_descriptor.bInterfaceNumber)) + { + + /* Save control instance and we are done. */ + cdc_acm -> ux_host_class_cdc_acm_control = cdc_acm_inst; + break; + } + + /* Next instance. */ + cdc_acm_inst = cdc_acm_inst -> ux_host_class_cdc_acm_next_instance; + } + + /* Mark the cdc_acm as live now. Both interfaces need to be live. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_ACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_acm, 0, 0, 0) + + /* We are done success. */ + return(UX_SUCCESS); + } + +#else + /* Configure the cdc_acm. */ status = _ux_host_class_cdc_acm_configure(cdc_acm); @@ -163,8 +280,8 @@ UINT status; /* Set the default values to the device, first line coding. */ line_coding.ux_host_class_cdc_acm_line_coding_dter = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE; - line_coding.ux_host_class_cdc_acm_line_coding_stop_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_0; - line_coding.ux_host_class_cdc_acm_line_coding_parity = UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_NONE; + line_coding.ux_host_class_cdc_acm_line_coding_stop_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT; + line_coding.ux_host_class_cdc_acm_line_coding_parity = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY; line_coding.ux_host_class_cdc_acm_line_coding_data_bits = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT; status = _ux_host_class_cdc_acm_ioctl(cdc_acm, UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING, (VOID *) &line_coding); } @@ -214,6 +331,7 @@ UINT status; return(UX_SUCCESS); } } +#endif /* On error case, it's possible data buffer allocated for interrupt endpoint and transfer started, stop and free it. */ if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint && @@ -230,8 +348,11 @@ UINT status; /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); +#if !defined(UX_HOST_STANDALONE) + /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); + _ux_host_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); +#endif /* Unmount instance. */ interface -> ux_interface_class_instance = UX_NULL; diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c index 5a5ddb64..dfa80289 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** CDC ACM Class */ /** */ @@ -30,67 +30,75 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_cdc_acm_command PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_command PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function will send a command to the ACM device. The command */ -/* can be one of the following : */ -/* SET_CONTROL */ -/* SET_LINE */ -/* SEND_BREAK */ -/* */ -/* */ -/* INPUT */ -/* */ -/* acm Pointer to acm class */ -/* command command value */ -/* value value to be sent in the */ -/* command request */ -/* data_buffer buffer to be sent */ -/* data_length length of the buffer to send */ -/* */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* */ -/* CALLED BY */ -/* */ -/* Storage Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* This function will send a command to the ACM device. The command */ +/* can be one of the following : */ +/* SET_CONTROL */ +/* SET_LINE */ +/* SEND_BREAK */ +/* */ +/* */ +/* INPUT */ +/* */ +/* acm Pointer to acm class */ +/* command command value */ +/* value value to be sent in the */ +/* command request */ +/* data_buffer buffer to be sent */ +/* data_length length of the buffer to send */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_command(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG command, ULONG value, UCHAR *data_buffer, ULONG data_length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +UX_DEVICE *device; +#endif + UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UINT status; ULONG request_direction; - + /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; transfer_request = &control_endpoint -> ux_endpoint_transfer_request; @@ -98,56 +106,95 @@ ULONG request_direction; /* Check the direction of the command. */ switch (command) { - - case UX_HOST_CLASS_CDC_ACM_REQ_SEND_ENCAPSULATED_COMMAND : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_COMM_FEATURE : - case UX_HOST_CLASS_CDC_ACM_REQ_CLEAR_COMM_FEATURE : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_AUX_LINE_STATE : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_HOOK_STATE : - case UX_HOST_CLASS_CDC_ACM_REQ_PULSE_SETUP : - case UX_HOST_CLASS_CDC_ACM_REQ_SEND_PULSE : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_PUSLE_TIME : - case UX_HOST_CLASS_CDC_ACM_REQ_RING_AUX_JACK : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE : - case UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_RINGER_PARMS : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_OPERATION_PARMS : - case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_PARMS : - - /* Direction is out */ - request_direction = UX_REQUEST_OUT; - break; - - - case UX_HOST_CLASS_CDC_ACM_REQ_GET_ENCAPSULATED_COMMAND : - case UX_HOST_CLASS_CDC_ACM_REQ_GET_COMM_FEATURE : - case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING : - case UX_HOST_CLASS_CDC_ACM_REQ_GET_RINGER_PARMS : - case UX_HOST_CLASS_CDC_ACM_REQ_GET_OPERATION_PARMS : - case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_PARMS : - - /* Direction is in */ - request_direction = UX_REQUEST_IN; - break; - - - default : - - return(UX_ERROR); + + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_ENCAPSULATED_COMMAND : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_COMM_FEATURE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_CLEAR_COMM_FEATURE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_AUX_LINE_STATE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_HOOK_STATE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_PULSE_SETUP : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_PULSE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_PUSLE_TIME : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_RING_AUX_JACK : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_RINGER_PARMS : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_OPERATION_PARMS : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_PARMS : + + /* Direction is out */ + request_direction = UX_REQUEST_OUT; + break; + + + case UX_HOST_CLASS_CDC_ACM_REQ_GET_ENCAPSULATED_COMMAND : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_GET_COMM_FEATURE : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_GET_RINGER_PARMS : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_GET_OPERATION_PARMS : + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_PARMS : + + /* Direction is in */ + request_direction = UX_REQUEST_IN; + break; + + + default : + + return(UX_ERROR); } - /* Protect the control endpoint semaphore here. It will be unprotected in the +#if defined(UX_HOST_STANDALONE) + + /* Get device instance. */ + device = cdc_acm -> ux_host_class_cdc_acm_device; + + /* Check device EP0 transfer lock flag. */ + UX_DISABLE + if (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + UX_RESTORE + return(UX_STATE_LOCK); + } + + /* Lock the device for EP0 transfer. */ + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; + UX_RESTORE +#else + + /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) - + /* Something went wrong. */ return(status); - +#endif + /* Create a transfer_request for the request. */ transfer_request -> ux_transfer_request_data_pointer = data_buffer; transfer_request -> ux_transfer_request_requested_length = data_length; @@ -162,4 +209,3 @@ ULONG request_direction; /* Return completion status. */ return(status); } - diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c index 97d59178..86635479 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -82,7 +85,9 @@ UINT _ux_host_class_cdc_acm_deactivate(UX_HOST_CLASS_COMMAND *command) UX_HOST_CLASS_CDC_ACM *cdc_acm; UX_TRANSFER *transfer_request; +#if !defined(UX_HOST_STANDALONE) UINT status; +#endif /* Get the instance for this class. */ cdc_acm = (UX_HOST_CLASS_CDC_ACM *) command -> ux_host_class_command_instance; @@ -90,12 +95,15 @@ UINT status; /* The cdc_acm is being shut down. */ cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; +#if !defined(UX_HOST_STANDALONE) + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ return(status); +#endif /* If we have the Control Class, we only unmount the interrupt endpoint if it is active. */ if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) @@ -138,15 +146,28 @@ UINT status; } +#if !defined(UX_HOST_STANDALONE) + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); +#else + + /* If there is allocated resource, free it. */ + if (cdc_acm -> ux_host_class_cdc_acm_allocated) + { + _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated); + } +#endif /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); +#if !defined(UX_HOST_STANDALONE) + /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); + _ux_host_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); +#endif /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c index f252320a..ea2bb628 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_endpoints_get PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* initialized timeout value, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_endpoints_get(UX_HOST_CLASS_CDC_ACM *cdc_acm) @@ -104,6 +107,9 @@ UX_TRANSFER *transfer_request; /* This transfer_request always have the OUT direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + /* Set default timeout for transfer. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT; + /* We have found the bulk endpoint, save it. */ cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint = endpoint; @@ -120,6 +126,9 @@ UX_TRANSFER *transfer_request; /* This transfer_request always have the IN direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + /* Set default timeout for transfer. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT; + /* We have found the bulk endpoint, save it. */ cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint = endpoint; diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c index 8a39be34..1f7cf015 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c @@ -30,12 +30,29 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) +#define UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT (UX_STATE_WAIT) +#define UX_HOST_CLASS_CDC_ACM_INIT_DESCRIPTORS_PARSE (UX_STATE_NEXT) + +#define UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT (UX_STATE_CLASS_STEP + 0) +#define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET (UX_STATE_CLASS_STEP + 1) +#define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET (UX_STATE_CLASS_STEP + 2) +#define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK (UX_STATE_CLASS_STEP + 3) +#define UX_HOST_CLASS_CDC_ACM_INIT_LINE_STATE_SET (UX_STATE_CLASS_STEP + 4) +#define UX_HOST_CLASS_CDC_ACM_INIT_ERROR (UX_STATE_CLASS_STEP + 5) +#define UX_HOST_CLASS_CDC_ACM_INIT_DONE (UX_STATE_CLASS_STEP + 6) + + +static inline UINT _ux_host_class_cdc_acm_activate_wait(UX_HOST_CLASS_COMMAND *command); +#endif + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +92,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND *command) @@ -133,6 +153,12 @@ UINT status; status = _ux_host_class_cdc_acm_activate(command); return(status); +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + status = _ux_host_class_cdc_acm_activate_wait(command); + return(status); +#endif + case UX_HOST_CLASS_COMMAND_DEACTIVATE: /* The deactivate command is used when the device has been extracted either @@ -152,3 +178,431 @@ UINT status; } } +#if defined(UX_HOST_STANDALONE) +static inline VOID _ux_host_class_cdc_acm_descriptors_parse(UX_HOST_CLASS_CDC_ACM *cdc_acm) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_INTERFACE *interface; +UCHAR *descriptor; +ULONG total_descriptor_length; +UCHAR descriptor_length; +UCHAR descriptor_type; +UCHAR descriptor_byte2; +ULONG interface_found; +ULONG interface_parsed; +UCHAR offset; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Check if transfer is done success. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != + transfer_request -> ux_transfer_request_requested_length) + { + cdc_acm -> ux_host_class_cdc_acm_status = UX_DESCRIPTOR_CORRUPTED; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + return; + } + + /* Get the interface. */ + interface = cdc_acm -> ux_host_class_cdc_acm_interface; + + /* Parse the descriptor. */ + total_descriptor_length = transfer_request -> ux_transfer_request_actual_length; + descriptor = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated; + interface_found = UX_FALSE; + interface_parsed = UX_FALSE; + + while(total_descriptor_length) + { + + /* Get descriptor length, type, subtype. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_byte2 = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3 || descriptor_length > total_descriptor_length) + { + /* Descriptor is corrupted. */ + break; + } + + /* Process related descriptors. */ + switch(descriptor_type) + { + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Check if interface is what we expected. */ + if (interface -> ux_interface_descriptor.bInterfaceNumber == descriptor_byte2) + { + + /* Mark found. */ + interface_found = UX_TRUE; + } + else + { + + /* Run out of expected interface. */ + if (interface_found) + { + + interface_parsed = UX_TRUE; + } + } + break; + + case UX_HOST_CLASS_CDC_ACM_CS_INTERFACE: + + /* Check if we are in correct interface. */ + if (interface_found) + { + + /* Check bDescriptorSubType. */ + switch(descriptor_byte2) + { + case UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DESCRIPTOR: + + /* Store capabilities. */ + cdc_acm -> ux_host_class_cdc_acm_capabilities = + *(descriptor + UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_CAPABILITIES); + break; + + case UX_HOST_CLASS_CDC_ACM_UNION_DESCRIPTOR: + + /* Check related interfaces. */ + for (offset = UX_HOST_CLASS_CDC_ACM_UNION_FUNCTIONAL_MASTER; + offset < descriptor_length; + offset ++) + { + + /* Save the interface in interface bitmap. */ + cdc_acm -> ux_host_class_cdc_acm_interfaces_bitmap |= + 1u << *(descriptor + offset); + } + break; + + default: + break; + } + } + break; + + default: + break; + } + + /* Next descriptor. */ + descriptor += descriptor_length; + total_descriptor_length -= descriptor_length; + } + + /* We can free the resource now. */ + _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated); + cdc_acm -> ux_host_class_cdc_acm_allocated = UX_NULL; + + /* Descriptor fail. */ + if (interface_parsed == UX_FALSE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Descriptor is corrupted. */ + cdc_acm -> ux_host_class_cdc_acm_status = UX_DESCRIPTOR_CORRUPTED; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + return; + } + + /* Descriptor is parsed. */ + cdc_acm -> ux_host_class_cdc_acm_tick = _ux_utility_time_get(); + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT; +} + +static inline UINT _ux_host_class_cdc_acm_activate_wait(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS *cdc_acm_class; +UX_HOST_CLASS_CDC_ACM *cdc_acm_inst; +UX_INTERFACE *interface; +UX_HOST_CLASS_CDC_ACM *cdc_acm; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer; +UCHAR *buffer; +ULONG rate, stop_bit, parity, data_bit; +UINT status; +ULONG tick, diff; + + /* Get the instance for this class. */ + interface = (UX_INTERFACE *)command -> ux_host_class_command_container; + cdc_acm = (UX_HOST_CLASS_CDC_ACM *) interface -> ux_interface_class_instance; + + /* Run initialize state machine. */ + switch(cdc_acm -> ux_host_class_cdc_acm_cmd_state) + { + case UX_HOST_CLASS_CDC_ACM_INIT_DESCRIPTORS_PARSE: + _ux_host_class_cdc_acm_descriptors_parse(cdc_acm); + break; + + case UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT: + tick = _ux_utility_time_get(); + diff = _ux_utility_time_elapsed(cdc_acm -> ux_host_class_cdc_acm_tick, tick); + if (diff > UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ACM_DEVICE_INIT_DELAY)) + { + /* Allocate some buffer for commands. */ + cdc_acm -> ux_host_class_cdc_acm_allocated = + _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + 8); + + if (cdc_acm -> ux_host_class_cdc_acm_allocated == UX_NULL) + { + cdc_acm -> ux_host_class_cdc_acm_status = UX_MEMORY_INSUFFICIENT; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + break; + } + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> + ux_device_control_endpoint; + transfer = &control_endpoint -> ux_endpoint_transfer_request; + + /* Initialize transfer buffer. */ + transfer -> ux_transfer_request_data_pointer = (UCHAR *) + cdc_acm -> ux_host_class_cdc_acm_allocated; + + /* Initialize transfer flags. */ + transfer -> ux_transfer_request_flags = 0; + + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET; + } + break; + + case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET: + + /* Put line coding things in buffer. */ + buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated; + rate = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE; + stop_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT; + parity = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY; + data_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT; + _ux_utility_long_put(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE, rate); + *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT) = (UCHAR)stop_bit; + *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY) = (UCHAR)parity; + *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT) = (UCHAR)data_bit; + + status = _ux_host_class_cdc_acm_command(cdc_acm, + UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING, 0, + buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + if (status != UX_SUCCESS) + { + cdc_acm -> ux_host_class_cdc_acm_status = status; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + break; + } + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT; + cdc_acm -> ux_host_class_cdc_acm_next_state = + UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET; + break; + + case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET: + + /* Get line coding things from device. */ + buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated; + status = _ux_host_class_cdc_acm_command(cdc_acm, + UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING, 0, + buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + if (status != UX_SUCCESS) + { + cdc_acm -> ux_host_class_cdc_acm_status = status; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + break; + } + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT; + cdc_acm -> ux_host_class_cdc_acm_next_state = + UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK; + break; + + case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK: + + /* Check line coding things in buffer. */ + buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated; + rate = _ux_utility_long_get(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE); + stop_bit = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT); + parity = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY); + data_bit = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT); + if (rate != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE || + stop_bit != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT || + parity != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY || + data_bit != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT) + { + cdc_acm -> ux_host_class_cdc_acm_status = UX_DEVICE_ENUMERATION_FAILURE; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + break; + } + + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_INIT_LINE_STATE_SET: + + /* Put line state things. */ + buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated; + *(buffer) = UX_HOST_CLASS_CDC_ACM_CTRL_DTR | UX_HOST_CLASS_CDC_ACM_CTRL_RTS; + status = _ux_host_class_cdc_acm_command(cdc_acm, + UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE, + *(buffer), UX_NULL, 0); + if (status != UX_SUCCESS) + { + cdc_acm -> ux_host_class_cdc_acm_status = status; + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_ERROR; + break; + } + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT; + cdc_acm -> ux_host_class_cdc_acm_next_state = + UX_HOST_CLASS_CDC_ACM_INIT_DONE; + break; + + case UX_HOST_CLASS_CDC_ACM_INIT_ERROR: + /* Fall through. */ + case UX_HOST_CLASS_CDC_ACM_INIT_DONE: + + /* Free allocated buffer. */ + if (cdc_acm -> ux_host_class_cdc_acm_allocated) + { + _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated); + cdc_acm -> ux_host_class_cdc_acm_allocated = UX_NULL; + } + + /* Check status. */ + if (cdc_acm -> ux_host_class_cdc_acm_status == UX_SUCCESS) + { + + /* We scan CDC ACM instances to find the DATA instance. */ + /* Get class. */ + cdc_acm_class = cdc_acm -> ux_host_class_cdc_acm_class; + + /* Get first instance linked to the class. */ + cdc_acm_inst = (UX_HOST_CLASS_CDC_ACM *)cdc_acm_class -> ux_host_class_first_instance; + + /* Scan all instances. */ + while(cdc_acm_inst) + { + + /* Get interface of the instance. */ + interface = cdc_acm_inst -> ux_host_class_cdc_acm_interface; + + /* If this data interface is inside the associate list, link it. */ + if (cdc_acm -> ux_host_class_cdc_acm_interfaces_bitmap & + (1ul << interface -> ux_interface_descriptor.bInterfaceNumber)) + { + + /* Save control instance and we are done. */ + cdc_acm_inst -> ux_host_class_cdc_acm_control = cdc_acm; + break; + } + + /* Next instance. */ + cdc_acm_inst = cdc_acm_inst -> ux_host_class_cdc_acm_next_instance; + } + + /* Mark the cdc_acm as live now. Both interfaces need to be live. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_ACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_acm, 0, 0, 0) + + /* Reset CMD state. */ + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_STATE_RESET; + } + else + { + + /* On error case, it's possible data buffer allocated for interrupt endpoint and transfer started, stop and free it. */ + if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint && + cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer) + { + + /* The first transfer request has already been initiated. Abort it. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint); + + /* Free the memory for the data pointer. */ + _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + } + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + + /* Unmount instance. */ + interface = cdc_acm -> ux_host_class_cdc_acm_interface; + interface -> ux_interface_class_instance = UX_NULL; + + /* Free instance. */ + _ux_utility_memory_free(cdc_acm); + } + + /* Done, OK to go on. */ + return(UX_STATE_NEXT); + + case UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT: + + /* Get transfer. */ + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; + transfer = &control_endpoint -> ux_endpoint_transfer_request; + + /* Transfer state machine. */ + status = _ux_host_stack_transfer_run(transfer); + + /* Is it done? */ + if (status <= UX_STATE_NEXT) + { + + /* Is there error? */ + if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS) + { + cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_STATE_EXIT; + break; + } + + /* No error, next state. */ + cdc_acm -> ux_host_class_cdc_acm_cmd_state = + cdc_acm -> ux_host_class_cdc_acm_next_state; + break; + } + + /* Keep waiting. */ + break; + + /* UX_STATE_RESET, UX_STATE_EXIT, UX_STATE_IDLE, ... */ + default: + + /* Do nothing. */ + return(UX_STATE_NEXT); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c index c05d2d62..eed20562 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_ioctl PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, @@ -88,6 +91,10 @@ UX_HOST_CLASS_CDC_ACM_LINE_CODING *line_coding; UX_HOST_CLASS_CDC_ACM_LINE_STATE *line_state; VOID (*callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG ); ULONG value; +#if defined(UX_HOST_STANDALONE) +VOID (*write_callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG ); +UX_TRANSFER *transfer; +#endif /* Ensure the instance is valid. */ if ((cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) && @@ -235,7 +242,7 @@ ULONG value; /* We need to abort transactions on the bulk In pipe. */ _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint); - + /* Status is successful. */ status = UX_SUCCESS; break; @@ -248,6 +255,12 @@ ULONG value; /* We need to abort transactions on the bulk Out pipe. */ _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint); +#if defined(UX_HOST_STANDALONE) + + /* Reset write state. */ + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET; +#endif + /* Status is successful. */ status = UX_SUCCESS; break; @@ -277,6 +290,39 @@ ULONG value; status = UX_SUCCESS; break; +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_CDC_ACM_IOCTL_WRITE_CALLBACK: + + /* Register a callback when write is done. */ + write_callback_function = ((VOID (*) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG )) (ALIGN_TYPE)parameter); + cdc_acm -> ux_host_class_cdc_acm_write_callback = write_callback_function; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_WRITE_STATUS: + + /* Check write state. */ + if (cdc_acm -> ux_host_class_cdc_acm_write_state == UX_STATE_WAIT) + { + status = UX_BUSY; + } + else + { + + /* Get transfer for write. */ + transfer = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> + ux_endpoint_transfer_request; + + /* Status is from transfer completion code. */ + status = transfer -> ux_transfer_request_completion_code; + + /* Actual length is from latest write count. */ + *(ULONG *)parameter = cdc_acm -> ux_host_class_cdc_acm_write_count; + } + break; +#endif default: diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c index 5fc8deff..ad3093ea 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_read (UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, @@ -83,6 +86,9 @@ UINT _ux_host_class_cdc_acm_read (UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_p UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; +#if defined(UX_HOST_STANDALONE) +ULONG transfer_flags; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_READ, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) @@ -119,7 +125,14 @@ ULONG transfer_request_length; /* Get the pointer to the bulk in endpoint in the transfer_request. */ transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request; - + +#if defined(UX_HOST_STANDALONE) + + /* Enable auto wait. */ + transfer_flags = transfer_request -> ux_transfer_request_flags; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk in endpoint until either the transfer is completed or until there is an error. */ while (requested_length) @@ -141,9 +154,11 @@ ULONG transfer_request_length; /* If the transfer is successful, we need to wait for the transfer request to be completed. */ if (status == UX_SUCCESS) { - +#if !defined(UX_HOST_STANDALONE) + /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, + transfer_request -> ux_transfer_request_timeout_value); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -167,11 +182,22 @@ ULONG transfer_request_length; /* There was an error, return to the caller */ return(UX_TRANSFER_TIMEOUT); - } + } +#endif } else { +#if defined(UX_HOST_STANDALONE) + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Restore previous setting. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif + /* There was a non transfer error, no partial transfer to be checked. */ return(status); } @@ -196,6 +222,12 @@ ULONG transfer_request_length; requested_length -= transfer_request_length; } +#if defined(UX_HOST_STANDALONE) + + /* Restore previous setting. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif + /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); } diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c index 27a2b2c0..99f60632 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_reception_stop PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,7 +58,7 @@ /* */ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort transfer */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -71,6 +71,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_reception_stop(UX_HOST_CLASS_CDC_ACM *cdc_acm, @@ -125,10 +128,13 @@ UX_TRANSFER *transfer_request; /* Reset the completion callback function. */ transfer_request -> ux_transfer_request_completion_function = UX_NULL; +#if !defined(UX_HOST_STANDALONE) + /* Clear semaphore counts that were (incorrectly) increased during each transfer completion. */ while (transfer_request -> ux_transfer_request_semaphore.tx_semaphore_count) - _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, 0); + _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, 0); +#endif /* This function never really fails. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_transmission_callback.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_transmission_callback.c new file mode 100644 index 00000000..d370b924 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_transmission_callback.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** ACM CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_transmission_callback PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_run Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_acm_transmission_callback(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_CDC_ACM *cdc_acm; +ULONG request_length; +VOID (*write_callback)(struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG); + + /* Get the class instance for this transfer request. */ + cdc_acm = (UX_HOST_CLASS_CDC_ACM *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + { + + /* Update write information. */ + cdc_acm -> ux_host_class_cdc_acm_write_count += + transfer_request -> ux_transfer_request_actual_length; + + /* Check if there is remaining. */ + request_length = cdc_acm -> ux_host_class_cdc_acm_write_length - + cdc_acm -> ux_host_class_cdc_acm_write_count; + if (request_length > 0) + { + + /* Program the maximum authorized length for this transfer_request. */ + if (request_length > transfer_request -> ux_transfer_request_maximum_length) + request_length = transfer_request -> ux_transfer_request_maximum_length; + + /* Update buffer pointer and request length. */ + transfer_request -> ux_transfer_request_data_pointer += + transfer_request -> ux_transfer_request_actual_length; + transfer_request -> ux_transfer_request_requested_length = request_length; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Arm another transfer. */ + _ux_host_stack_transfer_run(transfer_request); + + /* There is no status to be reported back to the stack. */ + return; + } + } + + /* There is error, or total things done, set state to idle. */ + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET; + + /* Clear callback for blocking mode. */ + write_callback = cdc_acm -> ux_host_class_cdc_acm_write_callback; + cdc_acm -> ux_host_class_cdc_acm_write_callback = UX_NULL; + + /* We need to report this transfer to the application. */ + if (write_callback) + { + write_callback(cdc_acm, + transfer_request -> ux_transfer_request_completion_code, + cdc_acm -> ux_host_class_cdc_acm_write_count); + } + + /* There is no status to be reported back to the stack. */ + return; +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c index 91ef76fa..8e0a7869 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_acm_write PORTABLE C */ -/* 6.1.3 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed ZLP sending, */ /* resulting in version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, @@ -86,6 +89,9 @@ UINT _ux_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_p UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; +#if defined(UX_HOST_STANDALONE) +ULONG transfer_flags; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_WRITE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) @@ -117,12 +123,25 @@ ULONG transfer_request_length; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } +#if defined(UX_HOST_STANDALONE) + if (cdc_acm -> ux_host_class_cdc_acm_write_state == UX_STATE_WAIT) + return(UX_BUSY); + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_WAIT; +#endif + /* Start by resetting the actual length of the transfer. */ *actual_length = 0; /* Get the pointer to the bulk out endpoint transfer request. */ transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request; +#if defined(UX_HOST_STANDALONE) + + /* Enable auto wait. */ + transfer_flags = transfer_request -> ux_transfer_request_flags; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk out endpoint until either the transfer is completed or when there is an error. */ do @@ -145,8 +164,10 @@ ULONG transfer_request_length; if (status == UX_SUCCESS) { +#if !defined(UX_HOST_STANDALONE) /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, + transfer_request -> ux_transfer_request_timeout_value); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -171,10 +192,24 @@ ULONG transfer_request_length; /* There was an error, return to the caller. */ return(UX_TRANSFER_TIMEOUT); } +#endif } else { +#if defined(UX_HOST_STANDALONE) + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Restore previous setting. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; + + /* Not busy any more. */ + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET; +#endif + /* There was a non transfer error, no partial transfer to be checked */ return(status); } @@ -200,6 +235,15 @@ ULONG transfer_request_length; } while (requested_length); +#if defined(UX_HOST_STANDALONE) + + /* Restore previous setting. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; + + /* Not busy any more. */ + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET; +#endif + /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); } diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_write_with_callback.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write_with_callback.c new file mode 100644 index 00000000..596a51f7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write_with_callback.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_write_with_callback PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the cdc_acm interface. The call starts */ +/* background transmission and returns immediately. */ +/* A callback is invoked when background transmission is done or there */ +/* is error during transmission. */ +/* */ +/* Following IOCTL functions can be used with this function: */ +/* - _WRITE_CALLBACK Set the callback function */ +/* - _GET_WRITE_STATUS Return UX_BUSY if transfer is */ +/* pending, otherwise report */ +/* actual length of bytes done, */ +/* a pointer to ULONG must be */ +/* passed to fill the actual */ +/* length value, as parameter */ +/* */ +/* It's for standalone mode. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_run Run transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_write_with_callback(UX_HOST_CLASS_CDC_ACM *cdc_acm, + UCHAR *data_pointer, ULONG requested_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_WRITE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* As further protection, we must ensure this instance of the interface is the data interface and not + the control interface ! */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check write state. */ + if (cdc_acm -> ux_host_class_cdc_acm_write_state != UX_STATE_RESET) + return(UX_BUSY); + + /* Set state to busy. */ + cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_WAIT; + + /* Reset write status. */ + cdc_acm -> ux_host_class_cdc_acm_write_length = requested_length; + cdc_acm -> ux_host_class_cdc_acm_write_count = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Initialize request for callback mode. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) cdc_acm; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_cdc_acm_transmission_callback; + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Start the transfer. */ + status = _ux_host_stack_transfer_run(transfer_request); + + /* We get here when all the transfers went through without errors. */ + return((status == UX_STATE_WAIT) ? + UX_SUCCESS : transfer_request -> ux_transfer_request_completion_code); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c index cdc9b39a..faa99e0f 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c @@ -36,7 +36,7 @@ UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_activate PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_create Create semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_thread_create Create thread */ /* _ux_utility_thread_delete Delete thread */ /* _ux_utility_thread_resume Resume thread */ @@ -89,6 +89,9 @@ UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* compile option for using */ /* packet pool from NetX, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_activate(UX_HOST_CLASS_COMMAND *command) @@ -214,19 +217,19 @@ UX_INTERFACE *cur_interface; { /* Create the semaphore for aborting bulk in transfers. */ - status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, + status = _ux_host_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, "host CDC-ECM bulk in wait semaphore", 0); if (status == UX_SUCCESS) { /* Create the semaphore for aborting bulk out transfers. */ - status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, + status = _ux_host_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, "host CDC-ECM bulk out wait semaphore", 0); if (status == UX_SUCCESS) { /* Create the semaphore to wake up the CDC ECM thread. */ - status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, "host CDC-ECM interrupt notification semaphore", 0); + status = _ux_host_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, "host CDC-ECM interrupt notification semaphore", 0); if (status == UX_SUCCESS) { #ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX @@ -350,15 +353,15 @@ UX_INTERFACE *cur_interface; } #endif /* Delete interrupt notification semaphore. */ - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); } /* Delete class-level bulk out semaphore. */ - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); } /* Delete class-level bulk in semaphore. */ - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); } } diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c index 6fc0e850..6adf7d2c 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_deactivate PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -81,6 +81,9 @@ /* compile option for using */ /* packet pool from NetX, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -142,7 +145,7 @@ UX_TRANSFER *transfer_request; UX_RESTORE /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up. */ - _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); /* We're no longer waiting. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; @@ -164,7 +167,7 @@ UX_TRANSFER *transfer_request; _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); /* Now wait for all threads to leave the instance before freeing the resources. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Free the memory used by the interrupt endpoint. */ if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) @@ -178,11 +181,11 @@ UX_TRANSFER *transfer_request; _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_thread_stack); /* Destroy the bulk semaphores. */ - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); /* Destroy the notification semaphore. */ - _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); #ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX /* Delete the packet pool. */ nx_packet_pool_delete(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool); diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c index 870c13ab..3575a8ba 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_interrupt_notification PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER *transfer_request) @@ -119,7 +122,7 @@ ULONG notification_value; cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP; /* We need to inform the cdc_ecm thread of this change. */ - _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); } } else @@ -149,7 +152,7 @@ ULONG notification_value; cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE; /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up. */ - _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); /* We're no longer waiting. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; @@ -159,7 +162,7 @@ ULONG notification_value; _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request); /* We need to inform the CDC-ECM thread of this change. */ - _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); } } } diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c index 6911d598..42d8ed74 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_thread PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* _ux_host_class_cdc_ecm_transmit_queue_clean */ /* Clean transmit queue */ /* _ux_host_stack_transfer_request Transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_short_get_big_endian Get 16-bit big endian */ /* _ux_network_driver_link_up Set state link up */ /* _ux_network_driver_link_down Set state link down */ @@ -86,6 +86,9 @@ /* compile option for using */ /* packet pool from NetX, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_cdc_ecm_thread(ULONG parameter) @@ -108,7 +111,7 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; { /* Wait for the semaphore to be put by the cdc_ecm interrupt event. */ - _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, UX_WAIT_FOREVER); /* Check the link state. It is either pending up or down. */ if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP) @@ -194,14 +197,14 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; /* Signal that we are done arming and resume waiting thread if necessary. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_FALSE; if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) - _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); /* Check if the transaction was armed successfully. */ if (status == UX_SUCCESS) { /* Wait for the completion of the transfer request. */ - _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_WAIT_FOREVER); /* Check the transfer status. If there is a transport error, we ignore the packet and restart it. */ @@ -252,7 +255,7 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; /* Signal that we are done arming and resume waiting thread if necessary. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_FALSE; if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) - _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); /* Release packet. */ nx_packet_release(packet); diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c index 308be1d7..1ccb3d7f 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_transmit_queue_clean PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -53,7 +53,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_semaphore_get Get bulk out semaphore */ +/* _ux_host_semaphore_get Get bulk out semaphore */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* nx_packet_transmit_release Release NetX packet */ /* */ @@ -71,6 +71,9 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_cdc_ecm_transmit_queue_clean(UX_HOST_CLASS_CDC_ECM *cdc_ecm) @@ -99,7 +102,7 @@ NX_PACKET *next_packet; UX_RESTORE /* Wait for write function to resume us. */ - _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); /* We're done waiting. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c index 4c52d60c..fd41ba26 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,7 +57,7 @@ /* CALLS */ /* */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* nx_packet_transmit_release Release NetX packet */ /* */ /* CALLED BY */ @@ -74,6 +74,9 @@ /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet) @@ -214,7 +217,7 @@ UX_HOST_CLASS_CDC_ECM *cdc_ecm; /* Signal that we are done arming and resume waiting thread if necessary. */ cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_check_and_arm_in_process = UX_FALSE; if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) - _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); /* We are done here. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_gser_command.c b/common/usbx_host_classes/src/ux_host_class_gser_command.c index 25848750..cf9e0c81 100644 --- a/common/usbx_host_classes/src/ux_host_class_gser_command.c +++ b/common/usbx_host_classes/src/ux_host_class_gser_command.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_gser_command PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,7 +66,7 @@ /* CALLS */ /* */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,6 +79,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_gser_command(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG command, @@ -140,7 +143,7 @@ ULONG request_direction; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&gser -> ux_host_class_gser_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_gser_configure.c b/common/usbx_host_classes/src/ux_host_class_gser_configure.c index 3c2e901e..1455e596 100644 --- a/common/usbx_host_classes/src/ux_host_class_gser_configure.c +++ b/common/usbx_host_classes/src/ux_host_class_gser_configure.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_gser_configure PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,7 +59,7 @@ /* _ux_host_stack_configuration_interface_get Get interface */ /* _ux_host_stack_device_configuration_get Get configuration */ /* _ux_host_stack_device_configuration_select Select configuration */ -/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_host_semaphore_create Create semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,6 +74,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_gser_configure(UX_HOST_CLASS_GSER *gser) @@ -158,7 +161,7 @@ UX_DEVICE *parent_device; gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface -> ux_interface_class = gser -> ux_host_class_gser_device -> ux_device_class ; /* Create the semaphore to protect 2 threads from accessing the same gser instance. */ - status = _ux_utility_semaphore_create(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, "ux_host_class_gser_semaphore", 1); + status = _ux_host_semaphore_create(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, "ux_host_class_gser_semaphore", 1); /* Check status. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c b/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c index 921b9ff1..345728b9 100644 --- a/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_gser_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +60,7 @@ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_gser_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -99,10 +102,10 @@ ULONG interface_index; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + _ux_host_semaphore_delete(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); } diff --git a/common/usbx_host_classes/src/ux_host_class_gser_read.c b/common/usbx_host_classes/src/ux_host_class_gser_read.c index e3146d54..a5bb43d8 100644 --- a/common/usbx_host_classes/src/ux_host_class_gser_read.c +++ b/common/usbx_host_classes/src/ux_host_class_gser_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_gser_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +76,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_gser_read(UX_HOST_CLASS_GSER *gser, @@ -106,7 +109,7 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -142,7 +145,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -156,7 +159,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -175,7 +178,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* There was a non transfer error, no partial transfer to be checked. */ return(status); @@ -191,7 +194,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* Return success to caller. */ return(UX_SUCCESS); @@ -205,7 +208,7 @@ ULONG transfer_request_length; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_gser_write.c b/common/usbx_host_classes/src/ux_host_class_gser_write.c index df45c95d..10afc090 100644 --- a/common/usbx_host_classes/src/ux_host_class_gser_write.c +++ b/common/usbx_host_classes/src/ux_host_class_gser_write.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_gser_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -75,6 +75,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_gser_write(UX_HOST_CLASS_GSER *gser, @@ -101,7 +104,7 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -137,7 +140,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -151,7 +154,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -167,7 +170,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* There was a non transfer error, no partial transfer to be checked */ return(status); @@ -183,7 +186,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* Return success. */ return(UX_SUCCESS); @@ -199,7 +202,7 @@ ULONG transfer_request_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + status = _ux_host_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_activate.c index edcf715b..481abd28 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -63,7 +63,7 @@ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory */ -/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_host_semaphore_create Create semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND *command) @@ -110,6 +113,18 @@ UINT status; /* Create this class instance. */ _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) hid); +#if defined(UX_HOST_STANDALONE) + + /* Set class tasks function. */ + hid -> ux_host_class_hid_class -> ux_host_class_task_function = _ux_host_class_hid_tasks_run; + + /* Set activate state to first step. */ + hid -> ux_host_class_hid_enum_state = UX_STATE_WAIT; + + status = UX_SUCCESS; + return(status); +#else + /* Configure the HID. */ status = _ux_host_class_hid_configure(hid); @@ -135,7 +150,7 @@ UINT status; /* Create the semaphore to protect multiple threads from accessing the same storage instance. */ - status = _ux_utility_semaphore_create(&hid -> ux_host_class_hid_semaphore, "ux_host_class_hid_semaphore", 1); + status = _ux_host_semaphore_create(&hid -> ux_host_class_hid_semaphore, "ux_host_class_hid_semaphore", 1); if (status == UX_SUCCESS) { @@ -188,5 +203,7 @@ UINT status; /* Return error code. */ return(status); + +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c index cc661384..4e8fc33a 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort transfer */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_delete Delete semaphore */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -77,6 +77,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -85,7 +88,9 @@ UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command) UX_HOST_CLASS_HID *hid; UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; UX_TRANSFER *transfer_request; +#if !defined(UX_HOST_STANDALONE) UINT status; +#endif /* Get the instance for this class. */ @@ -94,15 +99,36 @@ UINT status; /* The HID is being shut down. */ hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; +#if !defined(UX_HOST_STANDALONE) + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ return(status); +#endif + +#if defined(UX_HOST_STANDALONE) + if (hid -> ux_host_class_hid_interrupt_endpoint) +#endif + { - /* We need to abort transactions on the interrupt pipe. */ - _ux_host_stack_endpoint_transfer_abort(hid -> ux_host_class_hid_interrupt_endpoint); + /* We need to abort transactions on the interrupt pipe. */ + _ux_host_stack_endpoint_transfer_abort(hid -> ux_host_class_hid_interrupt_endpoint); + + /* If the Hid class instance has a interrupt pipe with a data payload associated with it + it must be freed. */ + transfer_request = &hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* Then de allocate the memory. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + } + +#if defined(UX_HOST_STANDALONE) + if (hid -> ux_host_class_hid_allocated) + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); +#endif /* We need to inform the HID client, if any, of the deactivation. */ hid_client_command.ux_host_class_hid_client_command_instance = (VOID *) hid; @@ -116,22 +142,15 @@ UINT status; /* Clean all the HID memory fields. */ _ux_host_class_hid_instance_clean(hid); - /* If the Hid class instance has a interrupt pipe with a data payload associated with it - it must be freed. */ - transfer_request = &hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request; - - /* Then de allocate the memory. */ - _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); - /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&hid -> ux_host_class_hid_semaphore); + _ux_host_semaphore_delete(&hid -> ux_host_class_hid_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_hid_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_entry.c index a0bbfc24..01c23a31 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_entry.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** HID Class */ /** */ @@ -30,49 +30,68 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_hid_entry PORTABLE C */ -/* 6.1 */ +#if defined(UX_HOST_STANDALONE) +#define UX_HOST_CLASS_HID_ENUM_HID_DESC_READ (UX_STATE_WAIT) +#define UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE (UX_STATE_CLASS_STEP + 1) +#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ (UX_STATE_CLASS_STEP + 2) +#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE (UX_STATE_CLASS_STEP + 3) +#define UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH (UX_STATE_CLASS_STEP + 4) +#define UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT (UX_STATE_CLASS_STEP + 6) +#define UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT (UX_STATE_CLASS_STEP + 7) +#define UX_HOST_CLASS_HID_ENUM_ERROR (UX_STATE_CLASS_STEP + 8) +#define UX_HOST_CLASS_HID_ENUM_DONE (UX_STATE_CLASS_STEP + 9) + + +static inline UINT _ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND *command); +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_entry PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function is the entry point of the HID class. It will be */ -/* called by the USB stack enumeration module when there is a new */ -/* device on the bus or when there is a device extraction. */ -/* */ -/* INPUT */ -/* */ -/* command Pointer to command */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_host_class_hid_activate Activate HID class */ -/* _ux_host_class_hid_deactivate Deactivate HID class */ +/* */ +/* This function is the entry point of the HID class. It will be */ +/* called by the USB stack enumeration module when there is a new */ +/* device on the bus or when there is a device extraction. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_activate Activate HID class */ +/* _ux_host_class_hid_deactivate Deactivate HID class */ /* _ux_utility_memory_free Free memory */ -/* */ -/* CALLED BY */ -/* */ -/* Application */ -/* HID Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* added destroy command, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND *command) @@ -95,8 +114,8 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND client_command; this device or not. */ if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && (command -> ux_host_class_command_class == UX_HOST_CLASS_HID_CLASS)) - return(UX_SUCCESS); - else + return(UX_SUCCESS); + else return(UX_NO_CLASS_MATCH); @@ -109,9 +128,16 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND client_command; return(status); +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + status = _ux_host_class_hid_activate_wait(command); + return(status); +#endif + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: - /* The deactivate command is used when the device has been extracted either + /* The deactivate command is used when the device has been extracted either directly or when its parents has been extracted. */ status = _ux_host_class_hid_deactivate(command); @@ -144,7 +170,7 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND client_command; } return(UX_SUCCESS); - default: + default: /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); @@ -154,6 +180,449 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND client_command; /* Return error status. */ return(UX_FUNCTION_NOT_SUPPORTED); - } + } +} + +#if defined(UX_HOST_STANDALONE) +static inline VOID _ux_host_class_hid_descriptor_read(UX_HOST_CLASS_HID *hid) +{ +UX_INTERFACE *interface; +UX_CONFIGURATION *configuration; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + interface = hid -> ux_host_class_hid_interface; + configuration = interface -> ux_interface_configuration; + hid -> ux_host_class_hid_allocated = _ux_utility_memory_allocate( + UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + configuration -> ux_configuration_descriptor.wTotalLength); + if (hid -> ux_host_class_hid_allocated == UX_NULL) + { + + /* Next: error. */ + hid -> ux_host_class_hid_status = UX_MEMORY_INSUFFICIENT; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; + return; + } + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = hid -> ux_host_class_hid_allocated; + transfer_request -> ux_transfer_request_requested_length = configuration -> ux_configuration_descriptor.wTotalLength; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Next: transfer and parse. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT; + hid -> ux_host_class_hid_next_state = UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE; +} +static inline VOID _ux_host_class_hid_report_descriptor_read(UX_HOST_CLASS_HID *hid) +{ +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + hid -> ux_host_class_hid_allocated = _ux_utility_memory_allocate( + UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + hid -> ux_host_class_hid_descriptor.wItemLength); + if (hid -> ux_host_class_hid_allocated == UX_NULL) + { + + /* Next: error. */ + hid -> ux_host_class_hid_status = UX_MEMORY_INSUFFICIENT; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; + return; + } + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = hid -> ux_host_class_hid_allocated; + transfer_request -> ux_transfer_request_requested_length = hid -> ux_host_class_hid_descriptor.wItemLength; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_HID_REPORT_DESCRIPTOR << 8; + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Next: transfer and parse. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT; + hid -> ux_host_class_hid_next_state = UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE; +} +static inline VOID _ux_host_class_hid_hid_descriptor_parse(UX_HOST_CLASS_HID *hid) +{ +UX_DEVICE *device; +UX_TRANSFER *transfer; +UCHAR *descriptor; +UINT descriptor_length; +UINT descriptor_type; +UINT descriptor_2; +ULONG total_length; +ULONG interface_number; +UINT interface_found = UX_FALSE; + + /* Get transfer. */ + device = hid -> ux_host_class_hid_device; + transfer = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request; + + /* Get current interface number. */ + interface_number = hid -> ux_host_class_hid_interface -> + ux_interface_descriptor.bInterfaceNumber; + + /* Get received descriptor. */ + descriptor = transfer -> ux_transfer_request_data_pointer; + total_length = transfer -> ux_transfer_request_actual_length; + + /* The HID descriptor is embedded within the configuration descriptor. + We parse the entire descriptor to locate the HID portion. */ + while(total_length) + { + + /* Get length and type of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_2 = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + break; + + switch(descriptor_type) + { + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Check if interface is what we expected. */ + interface_found = (interface_number == descriptor_2) ? UX_TRUE : UX_FALSE; + break; + + case UX_HOST_CLASS_HID_DESCRIPTOR: + + /* Check if we are in expected interface. */ + if (!interface_found) + break; + + /* Save HID descriptor for later usage. + Note only first 7 entries are saved, since we only support first + 9 bytes, no optional descriptors are supported for now. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_hid_descriptor_structure, UX_HID_DESCRIPTOR_ENTRIES, + (UCHAR *) &hid -> ux_host_class_hid_descriptor); + + /* Free allocated bytes. */ + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + hid -> ux_host_class_hid_allocated = UX_NULL; + + /* Next: HID report descriptor read. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ; + return; + + default: + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_length) + break; + + /* Next descriptor. */ + descriptor += descriptor_length; + total_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + hid -> ux_host_class_hid_status = UX_DESCRIPTOR_CORRUPTED; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; +} +static inline VOID _ux_host_class_hid_report_descriptor_parse(UX_HOST_CLASS_HID *hid) +{ +UX_DEVICE *device; +UX_TRANSFER *transfer; +UCHAR *descriptor; +ULONG length; +UX_HOST_CLASS_HID_ITEM item; +UINT status; + + /* Get transfer. */ + device = hid -> ux_host_class_hid_device; + transfer = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request; + + /* Get buffer and length. */ + descriptor = hid -> ux_host_class_hid_allocated; + length = transfer -> ux_transfer_request_actual_length; + + /* Parse the report descriptor and build the report items. */ + while (length) + { + + /* Get one item from the report and analyze it. */ + _ux_host_class_hid_report_item_analyse(descriptor, &item); + + /* Point the descriptor right after the item identifier. */ + descriptor += item.ux_host_class_hid_item_report_format; + + /* Process relative to the item type. */ + switch (item.ux_host_class_hid_item_report_type) + { + + case UX_HOST_CLASS_HID_TYPE_GLOBAL: + + /* This is a global item. */ + status = _ux_host_class_hid_global_item_parse(hid, &item, descriptor); + break; + + + case UX_HOST_CLASS_HID_TYPE_MAIN: + + /* This is a main item. */ + status = _ux_host_class_hid_main_item_parse(hid, &item, descriptor); + break; + + + case UX_HOST_CLASS_HID_TYPE_LOCAL: + + /* This is a local item. */ + status = _ux_host_class_hid_local_item_parse(hid, &item, descriptor); + break; + + default: + + /* This is a reserved item, meaning it shouldn't be used! */ + + /* Set status to error. The check after this switch statement + will handle the rest. */ + status = UX_DESCRIPTOR_CORRUPTED; + break; + } + + /* Recheck the status code. */ + if (status != UX_SUCCESS) + { + break; + } + + /* Jump to the next item. */ + descriptor += item.ux_host_class_hid_item_report_length; + + /* Verify that the report descriptor is not corrupted. */ + if (length < item.ux_host_class_hid_item_report_length) + { + + /* Return error status. */ + status = (UX_DESCRIPTOR_CORRUPTED); + break; + } + + /* Adjust the length. */ + length -= (ULONG)(item.ux_host_class_hid_item_report_length + item.ux_host_class_hid_item_report_format); + } + + if (status != UX_SUCCESS) + { + hid -> ux_host_class_hid_status = status; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; + return; + } + + /* Search the HID interrupt endpoint. */ + status = _ux_host_class_hid_interrupt_endpoint_search(hid); + if (status != UX_SUCCESS) + { + hid -> ux_host_class_hid_status = status; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; + return; + } + + /* Allocated memory is no use now, free. */ + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + hid -> ux_host_class_hid_allocated = UX_NULL; + + /* Next: search & activate client. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH; } +static inline VOID _ux_host_class_hid_client_activate_wait(UX_HOST_CLASS_HID *hid) +{ +UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; +UINT status; + + hid_client_command.ux_host_class_hid_client_command_instance = hid; + hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT; + + /* Call the HID client with an activate command. */ + status = hid -> ux_host_class_hid_client -> ux_host_class_hid_client_handler(&hid_client_command); + + /* Error. */ + if (status < UX_STATE_NEXT) + { + hid -> ux_host_class_hid_client = UX_NULL; + hid -> ux_host_class_hid_status = UX_DEVICE_ENUMERATION_FAILURE; + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR; + return; + } + + /* Success. */ + if (status == UX_STATE_NEXT) + { + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_DONE; + return; + } + + /* Wait. */ + return; +} +static inline UINT _ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer; +UX_HOST_CLASS_HID *hid; +UINT status; + + /* Get the instance for this class. */ + interface = (UX_INTERFACE *)command -> ux_host_class_command_container; + hid = (UX_HOST_CLASS_HID *) interface -> ux_interface_class_instance; + + /* Run initialize state machine. */ + switch(hid -> ux_host_class_hid_enum_state) + { + case UX_HOST_CLASS_HID_ENUM_HID_DESC_READ : + _ux_host_class_hid_descriptor_read(hid); + break; + + case UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE : + _ux_host_class_hid_hid_descriptor_parse(hid); + break; + + case UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ : + _ux_host_class_hid_report_descriptor_read(hid); + break; + + case UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE : + _ux_host_class_hid_report_descriptor_parse(hid); + break; + + case UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH : + + /* Search and activate client. */ + status = _ux_host_class_hid_client_search(hid); + if (status != UX_SUCCESS) + { + + /* There is no client, but HID can still be used. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_DONE; + break; + } + /* Activate wait in case there is still steps for client. */ + hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT; + + /* Fall through. */ + case UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT : + _ux_host_class_hid_client_activate_wait(hid); + break; + + case UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT : + + /* Get transfer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer = &control_endpoint -> ux_endpoint_transfer_request; + + /* Transfer state machine. */ + status = _ux_host_stack_transfer_run(transfer); + + /* Is it done? */ + if (status <= UX_STATE_NEXT) + { + + /* Is there error? */ + if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS) + { + hid -> ux_host_class_hid_status = transfer -> ux_transfer_request_completion_code; + hid -> ux_host_class_hid_enum_state = UX_STATE_EXIT; + break; + } + + /* No error, next state. */ + hid -> ux_host_class_hid_enum_state = hid -> ux_host_class_hid_next_state; + break; + } + + /* Keep waiting. */ + break; + + case UX_HOST_CLASS_HID_ENUM_ERROR : + + /* Clean interrupt endpoint. */ + if (hid -> ux_host_class_hid_interrupt_endpoint && + hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer) + _ux_utility_memory_free(hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + + /* Clean instance. */ + _ux_host_class_hid_instance_clean(hid); + + /* Error, destroy the class instance and return error code. */ + _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid); + + /* Unmount instance. */ + interface -> ux_interface_class_instance = UX_NULL; + + /* Free memory. */ + if (hid -> ux_host_class_hid_allocated) + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + + /* Free instance. */ + _ux_utility_memory_free(hid); + return(UX_STATE_NEXT); + + case UX_HOST_CLASS_HID_ENUM_DONE : + + /* Free temperary memory. */ + if (hid -> ux_host_class_hid_allocated) + { + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + hid -> ux_host_class_hid_allocated = UX_NULL; + } + + /* Mark the HID class as live now. */ + hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* We may need to inform the application if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0) + + hid -> ux_host_class_hid_enum_state = UX_STATE_IDLE; + return(UX_STATE_NEXT); + + default: /* IDLE, Other states. */ + return(UX_STATE_NEXT); + } + + /* By default, keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c b/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c index c7d906c8..f751d406 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_idle_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,11 +74,16 @@ /* protected default control */ /* endpoint before using it, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_idle_get(UX_HOST_CLASS_HID *hid, USHORT *idle_time, USHORT report_id) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UCHAR *idle_byte; @@ -97,16 +102,28 @@ UINT status; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + UX_RESTORE +#else + + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ return(status); - - /* We need to get the default control endpoint transfer request pointer. */ - control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; - transfer_request = &control_endpoint -> ux_endpoint_transfer_request; +#endif /* Need to allocate memory for the idle byte. */ idle_byte = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 1); @@ -114,7 +131,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Return error status. */ return(UX_MEMORY_INSUFFICIENT); @@ -122,7 +139,23 @@ UINT status; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (hid -> ux_host_class_hid_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + + /* Free allocated return busy. */ + _ux_utility_memory_free(idle_byte); + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + UX_RESTORE + return(UX_BUSY); + } + hid -> ux_host_class_hid_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; + UX_TRANSFER_STATE_RESET(transfer_request); + UX_RESTORE +#else + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -134,10 +167,11 @@ UINT status; _ux_utility_memory_free(idle_byte); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore); return(status); } +#endif /* Create a transfer request for the GET_IDLE request. */ transfer_request -> ux_transfer_request_data_pointer = idle_byte; @@ -149,7 +183,15 @@ UINT status; /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); - + +#if defined(UX_HOST_STANDALONE) + if (!(transfer_request -> ux_transfer_request_flags & UX_TRANSFER_FLAG_AUTO_WAIT)) + { + hid -> ux_host_class_hid_allocated = idle_byte; + return(status); + } +#endif + /* Check for correct transfer and for the entire descriptor returned. */ if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 1)) *idle_time = (USHORT) *idle_byte; @@ -158,9 +200,12 @@ UINT status; _ux_utility_memory_free(idle_byte); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); +#if defined(UX_HOST_STANDALONE) + _ux_host_class_hid_unlock(hid); +#else + status = _ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore); +#endif /* Return the completion status. */ return(status); } - diff --git a/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c b/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c index eb7602f0..c407bbdf 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_idle_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,10 +74,21 @@ /* protected default control */ /* endpoint before using it, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_idle_set(UX_HOST_CLASS_HID *hid, USHORT idle_time, USHORT report_id) { +#if defined(UX_HOST_STANDALONE) +UINT status; + do + { + status = _ux_host_class_hid_idle_set_run(hid, idle_time, report_id); + } while(status == UX_STATE_WAIT || status == UX_STATE_LOCK); + return(hid -> ux_host_class_hid_status); +#else UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; @@ -96,14 +107,18 @@ UINT status; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -111,15 +126,11 @@ UINT status; /* Something went wrong. */ /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore); return(status); } - /* We need to get the default control endpoint transfer request pointer. */ - control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; - transfer_request = &control_endpoint -> ux_endpoint_transfer_request; - /* Create a transfer request for the SET_IDLE request. */ transfer_request -> ux_transfer_request_data_pointer = UX_NULL; transfer_request -> ux_transfer_request_requested_length = 0; @@ -132,9 +143,9 @@ UINT status; status = _ux_host_stack_transfer_request(transfer_request); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore); /* Return the function status. */ return(status); +#endif } - diff --git a/common/usbx_host_classes/src/ux_host_class_hid_idle_set_run.c b/common/usbx_host_classes/src/ux_host_class_hid_idle_set_run.c new file mode 100644 index 00000000..fa8d87d7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_idle_set_run.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_idle_set_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a SET_IDLE to the HID device. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* idle_time Idle time */ +/* report_id Report ID */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_run Process transfer states */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_idle_set_run(UX_HOST_CLASS_HID *hid, USHORT idle_time, USHORT report_id) +{ + +UX_INTERRUPT_SAVE_AREA +UX_DEVICE *device; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_IDLE_SET, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* Get device. */ + device = hid -> ux_host_class_hid_device; + + /* Sanity check. */ + if (device == UX_NULL || + device -> ux_device_handle != (ULONG)(ALIGN_TYPE)device) + { + hid -> ux_host_class_hid_status = UX_DEVICE_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Waiting transfer done. */ + if (hid -> ux_host_class_hid_cmd_state == UX_STATE_WAIT) + { + + /* Process background tasks. */ + _ux_system_tasks_run(); + + /* Check if transfer is done. */ + if (transfer_request -> ux_transfer_request_state < UX_STATE_WAIT) + { + + /* Unlock. */ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + + /* We are done. */ + hid -> ux_host_class_hid_cmd_state = UX_STATE_IDLE; + hid -> ux_host_class_hid_status = + transfer_request -> ux_transfer_request_completion_code; + return(UX_STATE_NEXT); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + } + + /* Check state or protection status. */ + UX_DISABLE + if ((hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) || + (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)) + { + + /* Locked. */ + UX_RESTORE + return(UX_STATE_LOCK); + } + hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + hid -> ux_host_class_hid_cmd_state = UX_STATE_WAIT; + UX_RESTORE + + /* Create a transfer request for the SET_IDLE request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_IDLE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (UINT)((idle_time << 8) | report_id); + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_run(transfer_request); + if (status != UX_STATE_WAIT) + { + hid -> ux_host_class_hid_status = + transfer_request -> ux_transfer_request_completion_code; + + /* Unlock. */ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + + hid -> ux_host_class_hid_cmd_state = (UCHAR)status; + } + + /* Return the function status. */ + return(status); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c b/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c index 34f807d8..96770dad 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_interrupt_endpoint_search PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,12 +71,16 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Xiuwen Cai, CQ Xiao Modified comment(s), */ +/* added interrupt OUT support,*/ +/* added timeout initialize, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_interrupt_endpoint_search(UX_HOST_CLASS_HID *hid) { -UINT status; +UINT status = UX_ENDPOINT_HANDLE_UNKNOWN; UX_INTERFACE *interface; UX_ENDPOINT *endpoint; UX_TRANSFER *transfer_request; @@ -88,7 +92,7 @@ UX_TRANSFER *transfer_request; while(endpoint != UX_NULL) { - /* Found interrupt IN endpoint. */ + /* Find interrupt IN endpoint. */ if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) { @@ -110,6 +114,9 @@ UX_TRANSFER *transfer_request; /* Interrupt transactions have a completion routine. */ transfer_request -> ux_transfer_request_completion_function = _ux_host_class_hid_transfer_request_completed; + /* Transfer timeout : wait forever. */ + transfer_request -> ux_transfer_request_timeout_value = UX_WAIT_FOREVER; + /* Obtain a buffer for this transaction. The buffer will always be reused. */ transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, transfer_request -> ux_transfer_request_requested_length); @@ -119,19 +126,33 @@ UX_TRANSFER *transfer_request; { hid -> ux_host_class_hid_interrupt_endpoint_status = UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY; status = UX_SUCCESS; +#if !defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* We have found the interrupt IN endpoint, just stop searching. */ + break; +#endif } else + { status = UX_MEMORY_INSUFFICIENT; + break; + } + } +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) + else if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { - /* Return completion status. */ - return(status); + /* Found the interrupt OUT endpoint, save it. */ + hid -> ux_host_class_hid_interrupt_out_endpoint = endpoint; } +#endif /* Check next endpoint. */ endpoint = endpoint -> ux_endpoint_next_endpoint; } - /* Return error completion. */ - return(UX_ENDPOINT_HANDLE_UNKNOWN); + /* Return completion status. */ + return(status); } diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c index fbdfced9..eedfe1d3 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c @@ -98,7 +98,7 @@ UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout = /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -126,8 +126,8 @@ UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout = /* _ux_host_class_hid_report_set Do SET_REPORT */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_create Create semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_thread_create Create thread */ /* _ux_utility_thread_delete Delete thread */ /* */ @@ -145,13 +145,18 @@ UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout = /* TX symbols instead of using */ /* them directly, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_keyboard_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) { UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; +#if !defined(UX_HOST_STANDALONE) UX_HOST_CLASS_HID_CLIENT_REPORT client_report; +#endif UX_HOST_CLASS_HID_REPORT_GET_ID report_id; UX_HOST_CLASS_HID *hid; UX_HOST_CLASS_HID_CLIENT *hid_client; @@ -182,8 +187,18 @@ UX_HOST_CLASS_HID_FIELD *field; /* Save the HID instance in the client instance. */ keyboard_instance -> ux_host_class_hid_keyboard_hid = hid; +#if defined(UX_HOST_STANDALONE) + + /* Set client task function. */ + hid_client -> ux_host_class_hid_client_function = _ux_host_class_hid_keyboard_tasks_run; + + /* The instance is mounting now. */ + keyboard_instance -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_MOUNTING; +#else + /* The instance is live now. */ keyboard_instance -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_LIVE; +#endif /* Allocate the round-robin buffer that the remote control instance will use * to store the usages as they come in. @@ -207,23 +222,15 @@ UX_HOST_CLASS_HID_FIELD *field; report_id.ux_host_class_hid_report_get_report = UX_NULL; report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; status = _ux_host_class_hid_report_id_get(hid, &report_id); - - /* If we are OK, go on. */ - if (status == UX_SUCCESS) - { - - /* Save the keyboard report ID. */ - keyboard_instance -> ux_host_class_hid_keyboard_id = (USHORT)(report_id.ux_host_class_hid_report_get_id); - - /* Set the idle rate of the keyboard to 0. This way a report is generated only when there is an activity. */ - status = _ux_host_class_hid_idle_set(hid, 0, keyboard_instance -> ux_host_class_hid_keyboard_id); - } } /* If we are OK, go on. */ if (status == UX_SUCCESS) { + /* Save the keyboard report ID. */ + keyboard_instance -> ux_host_class_hid_keyboard_id = (USHORT)(report_id.ux_host_class_hid_report_get_id); + #ifdef UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE /* Summarize number of usages to allocate state buffer for keyboard report. @@ -281,12 +288,14 @@ UX_HOST_CLASS_HID_FIELD *field; status = _ux_host_class_hid_report_callback_register(hid, &call_back); } +#if !defined(UX_HOST_STANDALONE) + /* If we are OK, go on. */ if (status == UX_SUCCESS) { /* We need a semaphore now. This will be used to synchronize the HID report with the keyboard thread. */ - status = _ux_utility_semaphore_create(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, "ux_host_class_hid_keyboard_semaphore", 0); + status = _ux_host_semaphore_create(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, "ux_host_class_hid_keyboard_semaphore", 0); if(status != UX_SUCCESS) status = (UX_SEMAPHORE_ERROR); } @@ -314,11 +323,15 @@ UX_HOST_CLASS_HID_FIELD *field; UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_KEYBOARD, UX_THREAD_PRIORITY_KEYBOARD, UX_NO_TIME_SLICE, UX_AUTO_START); +#endif + /* If we are OK, go on. */ if (status == UX_SUCCESS) { +#if !defined(UX_HOST_STANDALONE) UX_THREAD_EXTENSION_PTR_SET(&(keyboard_instance -> ux_host_class_hid_keyboard_thread), keyboard_instance) +#endif /* Default state of keyboard is with NumLock on. */ keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_NUM_LOCK; @@ -326,7 +339,21 @@ UX_HOST_CLASS_HID_FIELD *field; /* We need to build the field for the LEDs. */ keyboard_instance -> ux_host_class_hid_keyboard_led_mask = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_MASK_LOCK; - + +#if defined(UX_HOST_STANDALONE) + + /* Initialize the keyboard layout and use it to decode keys. */ + keyboard_instance -> ux_host_class_hid_keyboard_layout = &ux_host_class_hid_keyboard_layout; + keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_FALSE; + + /* Remaining things will be done in ACTIVATE_WAIT. + - SET_REPORT(LEDs) + - SET_IDLE(KEYs, 0) + - _periodic_report_start() */ + keyboard_instance -> ux_host_class_hid_keyboard_enum_state = UX_STATE_WAIT; + return(status); +#else + /* We need to find the OUTPUT report for the keyboard LEDs. */ report_id.ux_host_class_hid_report_get_report = UX_NULL; report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; @@ -353,6 +380,14 @@ UX_HOST_CLASS_HID_FIELD *field; status = _ux_host_class_hid_report_set(hid, &client_report); } + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Set the idle rate of the keyboard to 0. This way a report is generated only when there is an activity. */ + status = _ux_host_class_hid_idle_set(hid, 0, keyboard_instance -> ux_host_class_hid_keyboard_id); + } + /* If we are OK, go on. */ if (status == UX_SUCCESS) { @@ -387,6 +422,7 @@ UX_HOST_CLASS_HID_FIELD *field; /* There is error, delete thread. */ _ux_utility_thread_delete(&keyboard_instance -> ux_host_class_hid_keyboard_thread); +#endif } /* We are here if there is error. */ @@ -398,14 +434,18 @@ UX_HOST_CLASS_HID_FIELD *field; if (keyboard_instance -> ux_host_class_hid_keyboard_key_state) _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); +#if !defined(UX_HOST_STANDALONE) + /* Free stack. */ if (keyboard_instance -> ux_host_class_hid_keyboard_thread_stack) _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_thread_stack); /* Delete semaphore. */ if (keyboard_instance -> ux_host_class_hid_keyboard_semaphore.tx_semaphore_id != UX_EMPTY) - _ux_utility_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); - + _ux_host_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); + +#endif + /* Free usage array. */ if (keyboard_instance -> ux_host_class_hid_keyboard_usage_array) _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_usage_array); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c index d690a1f7..f52f649e 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_callback PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_hid_keyboard_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback) @@ -486,8 +489,15 @@ UCHAR *state_action; else keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[key_state]; +#if defined(UX_HOST_STANDALONE) + + /* Let background task to set LED status. */ + keyboard_instance -> ux_host_class_hid_keyboard_out_state = UX_STATE_WAIT; +#else + /* Wake up the keyboard thread semaphore. */ - _ux_utility_semaphore_put(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); + _ux_host_semaphore_put(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); +#endif } #if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) && defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS) diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c index a78d34c3..63ef15bb 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,7 +58,7 @@ /* _ux_host_class_hid_periodic_report_stop */ /* Stop periodic report */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_thread_delete Delete thread */ /* */ /* CALLED BY */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_keyboard_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) @@ -95,17 +98,20 @@ UINT status; /* Get the remote control local instance. */ keyboard_instance = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance; - /* Stop the semaphore. */ - status = _ux_utility_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); +#if !defined(UX_HOST_STANDALONE) - /* Free memory for key states. */ - _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); + /* Stop the semaphore. */ + status = _ux_host_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); /* Terminate the thread. */ _ux_utility_thread_delete(&keyboard_instance -> ux_host_class_hid_keyboard_thread); /* Return to the pool the thread stack. */ _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_thread_stack); +#endif + + /* Free memory for key states. */ + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_DEACTIVATE, hid, keyboard_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c index df8bd095..7ddf8b63 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c @@ -31,12 +31,26 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) + +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_START (UX_STATE_WAIT) +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT (UX_STATE_STACK_STEP + 0) +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE (UX_STATE_STACK_STEP + 1) +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT (UX_STATE_STACK_STEP + 2) +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START (UX_STATE_STACK_STEP + 3) +#define UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE (UX_STATE_STACK_STEP + 4) + + +static inline UINT _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +#endif + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +87,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) @@ -107,6 +124,13 @@ UINT status; return(status); +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + + return(_ux_host_class_hid_keyboard_activate_wait(command)); +#endif + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: /* The deactivate command is used by the HID class when it received a deactivate @@ -121,3 +145,125 @@ UINT status; return(UX_ERROR); } +#if defined(UX_HOST_STANDALONE) +static inline UINT _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_KEYBOARD *keyboard; +UINT status; + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* And of the HID client. */ + hid_client = hid -> ux_host_class_hid_client; + + /* And of the keyboard instance. */ + keyboard = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Run states. */ + switch(keyboard -> ux_host_class_hid_keyboard_enum_state) + { + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_START: + /* Fall through. */ + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT: + + /* Update LED in task. */ + keyboard -> ux_host_class_hid_keyboard_out_state = UX_STATE_WAIT; + keyboard -> ux_host_class_hid_keyboard_enum_state = + UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT; + keyboard -> ux_host_class_hid_keyboard_next_state = + UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE; + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT: + + /* LEDs processed in background task. */ + if (keyboard -> ux_host_class_hid_keyboard_out_state != UX_STATE_WAIT) + { + if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS) + keyboard -> ux_host_class_hid_keyboard_enum_state = + UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE; + else + keyboard -> ux_host_class_hid_keyboard_enum_state = + keyboard -> ux_host_class_hid_keyboard_next_state; + } + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE: + + /* Run SET_IDLE states. */ + status = _ux_host_class_hid_idle_set_run(hid, 0, + keyboard -> ux_host_class_hid_keyboard_id); + if (status < UX_STATE_WAIT) + { + keyboard -> ux_host_class_hid_keyboard_status = + hid -> ux_host_class_hid_status; + + /* Set_Idle is mandatory, if there is error enum fail. */ + if (keyboard -> ux_host_class_hid_keyboard_status == UX_SUCCESS) + keyboard -> ux_host_class_hid_keyboard_enum_state = + UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START; + else + keyboard -> ux_host_class_hid_keyboard_enum_state = + UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE; + + } + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START: + + /* Start the periodic report. */ + status = _ux_host_class_hid_periodic_report_start(hid); + keyboard -> ux_host_class_hid_keyboard_status = status; + + /* Fall through. */ + case UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE: + + /* Anything failed, Free resources. */ + if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS) + { + + /* Detach instance. */ + hid_client -> ux_host_class_hid_client_local_instance = UX_NULL; + + /* Free usage state. */ + if (keyboard -> ux_host_class_hid_keyboard_key_state) + _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_key_state); + + /* Free usage array. */ + if (keyboard -> ux_host_class_hid_keyboard_usage_array) + _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_usage_array); + + /* Free instance. */ + _ux_utility_memory_free(keyboard); + + return(UX_STATE_ERROR); + } + + /* Now keyboard instance is live. */ + keyboard -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE, hid, keyboard, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Enumeration idle. */ + keyboard -> ux_host_class_hid_keyboard_enum_state = UX_STATE_IDLE; + return(UX_STATE_NEXT); + + default: /* IDLE, Other states. */ + return(UX_STATE_NEXT); + } +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_tasks_run.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_tasks_run.c new file mode 100644 index 00000000..37aa1e7f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_tasks_run.c @@ -0,0 +1,133 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains the keyboard tasks used to process the changes */ +/* in the keyboard LEDs. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* client The keyboard client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_report_id_get Get report ID */ +/* _ux_host_class_hid_report_set Do SET_REPORT */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Host HID */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_keyboard_tasks_run(UX_HOST_CLASS_HID_CLIENT *client) +{ + +UX_HOST_CLASS_HID_KEYBOARD *keyboard; +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT_REPORT client_report; +UX_HOST_CLASS_HID_REPORT_GET_ID report_id; +UINT status; + + + /* Sanity check. */ + if (client == UX_NULL) + return; + + /* Get keyboard instance. */ + keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)client -> ux_host_class_hid_client_local_instance; + if (keyboard == UX_NULL) + return; + + /* Get HID instance. */ + hid = keyboard -> ux_host_class_hid_keyboard_hid; + if (hid == UX_NULL) + return; + + /* Check if there is pending chnages. */ + if (keyboard -> ux_host_class_hid_keyboard_out_state != UX_STATE_WAIT) + return; + + /* We got awaken by the keyboard callback which indicates a change on + the LEDs has to happen. We need to build the field for the LEDs. */ + keyboard -> ux_host_class_hid_keyboard_led_mask = + keyboard -> ux_host_class_hid_keyboard_alternate_key_state & + UX_HID_KEYBOARD_STATE_MASK_LOCK; + + /* We need to find the OUTPUT report for the keyboard LEDs. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* Build a RAW client report. */ + client_report.ux_host_class_hid_client_report = report_id.ux_host_class_hid_report_get_report; + client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW; + client_report.ux_host_class_hid_client_report_length = 1; + client_report.ux_host_class_hid_client_report_buffer = &keyboard -> ux_host_class_hid_keyboard_led_mask; + + /* The HID class will perform the SET_REPORT command. */ + status = _ux_host_class_hid_report_set_run(hid, &client_report); + if (status < UX_STATE_WAIT) + { + + /* Update status. */ + keyboard -> ux_host_class_hid_keyboard_status = hid -> ux_host_class_hid_status; + + /* The change is processed. */ + keyboard -> ux_host_class_hid_keyboard_out_state = UX_STATE_IDLE; + } +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c index 23baf1f3..1816d6df 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_thread PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -45,6 +45,8 @@ /* */ /* This file contains the keyboard thread used to process the changes */ /* in the keyboard LEDs. */ +/* */ +/* It's for RTOS mode. */ /* */ /* INPUT */ /* */ @@ -57,7 +59,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_semaphore_get Get signal semaphore */ +/* _ux_host_semaphore_get Get signal semaphore */ /* _ux_host_class_hid_report_id_get Get report ID */ /* _ux_host_class_hid_report_set Do SET_REPORT */ /* */ @@ -72,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_hid_keyboard_thread(ULONG thread_input) @@ -90,7 +95,7 @@ UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; { /* Wait for the semaphore to be put by the root hub or a regular hub. */ - status = _ux_utility_semaphore_get(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, UX_WAIT_FOREVER); /* The semaphore could be awaken because the semaphore was destroyed by the HID client when the keyboard is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c index 96b0ac4d..d68bd4ef 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_mouse_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,12 +75,17 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_mouse_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) { +#if !defined(UX_HOST_STANDALONE) UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; +#endif UX_HOST_CLASS_HID_REPORT_GET_ID report_id; UX_HOST_CLASS_HID *hid; UX_HOST_CLASS_HID_CLIENT *hid_client; @@ -107,6 +112,31 @@ UINT status; /* Save the HID instance in the client instance. */ mouse_instance -> ux_host_class_hid_mouse_hid = hid; +#if defined(UX_HOST_STANDALONE) + + /* The instance is mounting now. */ + mouse_instance -> ux_host_class_hid_mouse_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* Get the report ID for the mouse. The mouse is a INPUT report. + This should be 0 but in case. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* The report ID should exist. */ + if (status == UX_SUCCESS) + { + + /* Save the mouse report ID. */ + mouse_instance -> ux_host_class_hid_mouse_id = (USHORT)report_id.ux_host_class_hid_report_get_id; + + /* Set state for activate wait steps. */ + mouse_instance -> ux_host_class_hid_mouse_enum_state = UX_STATE_WAIT; + + } + return(status); +#else + /* The instance is live now. */ mouse_instance -> ux_host_class_hid_mouse_state = UX_HOST_CLASS_INSTANCE_LIVE; @@ -183,5 +213,6 @@ UINT status; /* Return completion status. */ return(status); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c index 322b332e..b29ce6cf 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c @@ -31,12 +31,23 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) + +#define UX_HOST_CLASS_HID_MOUSE_ENUM_START (UX_STATE_WAIT) +#define UX_HOST_CLASS_HID_MOUSE_ENUM_SET_IDLE (UX_STATE_STACK_STEP + 1) +#define UX_HOST_CLASS_HID_MOUSE_ENUM_PERIODIC_START (UX_STATE_STACK_STEP + 3) +#define UX_HOST_CLASS_HID_MOUSE_ENUM_DONE (UX_STATE_STACK_STEP + 4) + +static inline UINT _ux_host_class_hid_mouse_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +#endif + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_mouse_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +82,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_mouse_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) @@ -104,6 +118,12 @@ UINT status; /* Return completion status. */ return(status); +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + status = _ux_host_class_hid_mouse_activate_wait(command); + return(status); +#endif + case UX_HOST_CLASS_COMMAND_DEACTIVATE: @@ -119,3 +139,114 @@ UINT status; return(UX_ERROR); } +#if defined(UX_HOST_STANDALONE) +static inline UINT _ux_host_class_hid_mouse_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_MOUSE *mouse; +UINT status; +UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* And of the HID client. */ + hid_client = hid -> ux_host_class_hid_client; + + /* And of the mouse instance. */ + mouse = (UX_HOST_CLASS_HID_MOUSE *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Run states. */ + switch(mouse -> ux_host_class_hid_mouse_enum_state) + { + case UX_HOST_CLASS_HID_MOUSE_ENUM_START: + mouse -> ux_host_class_hid_mouse_enum_state = UX_HOST_CLASS_HID_MOUSE_ENUM_SET_IDLE; + /* Fall through. */ + case UX_HOST_CLASS_HID_MOUSE_ENUM_SET_IDLE: + + /* Run SET_IDLE states. */ + status = _ux_host_class_hid_idle_set_run(hid, 0, + mouse -> ux_host_class_hid_mouse_id); + if (status < UX_STATE_WAIT) + { + mouse -> ux_host_class_hid_mouse_status = + hid -> ux_host_class_hid_status; + + /* Set_Idle is optional, stall is accepted. */ + if (mouse -> ux_host_class_hid_mouse_status == UX_TRANSFER_STALLED) + mouse -> ux_host_class_hid_mouse_status = UX_SUCCESS; + + if (mouse -> ux_host_class_hid_mouse_status == UX_SUCCESS) + mouse -> ux_host_class_hid_mouse_enum_state = + UX_HOST_CLASS_HID_MOUSE_ENUM_PERIODIC_START; + else + mouse -> ux_host_class_hid_mouse_enum_state = + UX_HOST_CLASS_HID_MOUSE_ENUM_DONE; + } + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_HID_MOUSE_ENUM_PERIODIC_START: + + /* Set callback. */ + call_back.ux_host_class_hid_report_callback_id = mouse -> ux_host_class_hid_mouse_id; + call_back.ux_host_class_hid_report_callback_function = _ux_host_class_hid_mouse_callback; + call_back.ux_host_class_hid_report_callback_buffer = UX_NULL; + call_back.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_INDIVIDUAL_USAGE; + call_back.ux_host_class_hid_report_callback_length = 0; + status = _ux_host_class_hid_report_callback_register(hid, &call_back); + if (status != UX_SUCCESS) + { + mouse -> ux_host_class_hid_mouse_status = status; + mouse -> ux_host_class_hid_mouse_enum_state = + UX_HOST_CLASS_HID_MOUSE_ENUM_DONE; + break; + } + + /* Start the periodic report. */ + status = _ux_host_class_hid_periodic_report_start(hid); + mouse -> ux_host_class_hid_mouse_status = status; + + /* Fall through. */ + case UX_HOST_CLASS_HID_MOUSE_ENUM_DONE: + + /* Anything failed, Free resources. */ + if (mouse -> ux_host_class_hid_mouse_status != UX_SUCCESS) + { + + /* Detach instance. */ + hid_client -> ux_host_class_hid_client_local_instance = UX_NULL; + + /* Free instance. */ + _ux_utility_memory_free(mouse); + + return(UX_STATE_ERROR); + } + + /* The instance is live now. */ + mouse -> ux_host_class_hid_mouse_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_MOUSE_ACTIVATE, hid, mouse, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return completion status. */ + return(UX_STATE_NEXT); + + default: /* IDLE, Other states. */ + return(UX_STATE_NEXT); + } + + /* By default, wait. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c index aacb26e5..73323c60 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_periodic_report_start PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,11 +72,16 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_periodic_report_start(UX_HOST_CLASS_HID *hid) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UINT status; UX_TRANSFER *transfer_request; @@ -95,18 +100,14 @@ UX_TRANSFER *transfer_request; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); - if (status != UX_SUCCESS) - - /* Return error. */ - return(status); + _ux_host_class_hid_lock_fail_return(hid); /* Check the status of the interrupt endpoint. */ if (hid -> ux_host_class_hid_interrupt_endpoint_status != UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY) { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR); @@ -130,7 +131,7 @@ UX_TRANSFER *transfer_request; hid -> ux_host_class_hid_interrupt_endpoint_status = UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_ACTIVE; /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Return the function status */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c index a2ee3cda..e0032484 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_periodic_report_stop PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_endpoint_transfer_abort Abort transfer on endpoint */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_periodic_report_stop(UX_HOST_CLASS_HID *hid) diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c index 02336ddd..f5850f5b 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_remote_control_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_remote_control_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) @@ -115,6 +118,17 @@ UINT status; /* Return completion status. */ return(status); + +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + + /* Nothing to do, just next state. */ + return(UX_STATE_NEXT); +#endif + + + default: + break; } /* Return error status. */ diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c b/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c index 1451e3a4..cfe67d46 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_report_callback_register PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* CALLS */ /* */ /* _ux_host_stack_class_instance_verify Verify class instance is valid*/ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,11 +76,16 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_report_callback_register(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_CALLBACK *call_back) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UINT status; UX_HOST_CLASS_HID_REPORT *hid_report; @@ -99,11 +104,7 @@ UX_HOST_CLASS_HID_REPORT *hid_report; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); - if (status!=UX_SUCCESS) - - /* Return error. */ - return(status); + _ux_host_class_hid_lock_fail_return(hid); /* Search for the report ID. Note that this can only be an Input report! */ hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report; @@ -123,7 +124,7 @@ UX_HOST_CLASS_HID_REPORT *hid_report; hid_report -> ux_host_class_hid_report_callback_length = call_back -> ux_host_class_hid_report_callback_length; /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Tell the user the report was OK and the call back was registered. */ return(UX_SUCCESS); @@ -134,7 +135,7 @@ UX_HOST_CLASS_HID_REPORT *hid_report; } /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_get.c b/common/usbx_host_classes/src/ux_host_class_hid_report_get.c index f1c8179f..4f584138 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_report_get.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_report_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_copy Copy memory block */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -80,11 +80,16 @@ /* cases, accepted both INPUT */ /* and FEATURE reports, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_report_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UCHAR *report_buffer; @@ -108,11 +113,7 @@ UINT status; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); - if (status != UX_SUCCESS) - - /* Return error. */ - return(status); + _ux_host_class_hid_lock_fail_return(hid); /* Get the report pointer from the caller. */ hid_report = client_report -> ux_host_class_hid_client_report; @@ -123,7 +124,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) @@ -137,7 +138,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); @@ -155,7 +156,7 @@ UINT status; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Return error code. */ return(UX_MEMORY_INSUFFICIENT); @@ -167,7 +168,21 @@ UINT status; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (hid -> ux_host_class_hid_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) + { + _ux_utility_memory_free(report_buffer); + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + UX_RESTORE + return(UX_BUSY); + } + hid -> ux_host_class_hid_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; + UX_TRANSFER_STATE_RESET(transfer_request); + UX_RESTORE +#else + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -179,10 +194,11 @@ UINT status; _ux_utility_memory_free(report_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); return(status); } +#endif /* Create a transfer request for the GET_REPORT request. */ transfer_request -> ux_transfer_request_data_pointer = report_buffer; @@ -250,7 +266,7 @@ UINT status; _ux_utility_memory_free(report_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Return the completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c b/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c index d5ca2e4b..28774bda 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_report_id_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,8 +59,8 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* _ux_host_stack_class_instance_verify Verify class instance is valid*/ /* */ /* CALLED BY */ @@ -75,11 +75,16 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_report_id_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_GET_ID *report_id) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UINT status; UX_HOST_CLASS_HID_REPORT *next_hid_report; @@ -98,9 +103,7 @@ UX_HOST_CLASS_HID_REPORT *next_hid_report; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); - if (status != UX_SUCCESS) - return(status); + _ux_host_class_hid_lock_fail_return(hid); /* Check if this is the first report to get. */ if (report_id -> ux_host_class_hid_report_get_report == UX_NULL) @@ -172,7 +175,7 @@ UX_HOST_CLASS_HID_REPORT *next_hid_report; } /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* The status variable has been set correctly. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_set.c b/common/usbx_host_classes/src/ux_host_class_hid_report_set.c index 63d8c420..1731a586 100644 --- a/common/usbx_host_classes/src/ux_host_class_hid_report_set.c +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_set.c @@ -30,12 +30,96 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) + +/* Inline the function to let compiler optimize. */ +static inline +#else + +/* Prototype the function to remove warnings. */ +UINT ux_host_class_hid_report_set_buffer_allocate( + UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR **allocated); +#endif +UINT ux_host_class_hid_report_set_buffer_allocate( + UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR **allocated) +{ + +UX_HOST_CLASS_HID_REPORT *hid_report; +UCHAR *report_buffer; +UCHAR *current_report_buffer; + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Ensure this is NOT an INPUT report. */ + if (hid_report -> ux_host_class_hid_report_type == UX_HOST_CLASS_HID_REPORT_TYPE_INPUT) + { + + /* Return error code. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* Get some memory for sending the report. */ + if (hid_report -> ux_host_class_hid_report_id == 0) + report_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length); + else + report_buffer = _ux_utility_memory_allocate_add_safe(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length, 1); + if (report_buffer == UX_NULL) + { + + /* Return error code. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Memorize the start of the real report buffer. */ + current_report_buffer = report_buffer; + + /* Check if there is a report ID to be inserted in front of the buffer. */ + if (hid_report -> ux_host_class_hid_report_id != 0) + *current_report_buffer++ = (UCHAR)(hid_report -> ux_host_class_hid_report_id); + + /* The report is in the client's buffer. It may be raw or or decompressed. If decompressed, + we need to create the report. */ + if (client_report -> ux_host_class_hid_client_report_flags & UX_HOST_CLASS_HID_REPORT_RAW) + { + + /* Ensure the user is not trying to overflow the report buffer. */ + if (hid_report -> ux_host_class_hid_report_byte_length >= client_report -> ux_host_class_hid_client_report_length) + { + + /* We have enough memory to store the raw buffer. */ + _ux_utility_memory_copy(current_report_buffer, client_report -> ux_host_class_hid_client_report_buffer, hid_report -> ux_host_class_hid_report_byte_length); /* Use case of memcpy is verified. */ + } + else + { + + /* Free allocated buffer. */ + _ux_utility_memory_free(report_buffer); + + /* Return error code. */ + return(UX_HOST_CLASS_HID_REPORT_OVERFLOW); + } + } + else + { + + /* The report buffer has to be compressed. */ + _ux_host_class_hid_report_compress(hid, client_report, current_report_buffer, client_report -> ux_host_class_hid_client_report_length); + } + + /* Buffer is allocated and report data copied. */ + *allocated = report_buffer; + return(UX_SUCCESS); +} + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_report_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +146,8 @@ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_copy Copy memory block */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,15 +163,27 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Xiuwen Cai, CQ Xiao Modified comment(s), */ +/* added interrupt OUT support,*/ +/* added standalone support, */ +/* refined code sequence, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_report_set(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) { +#if defined(UX_HOST_STANDALONE) +UINT status; + do + { + status = _ux_host_class_hid_report_set_run(hid, client_report); + } while(status == UX_STATE_WAIT || status == UX_STATE_LOCK); + return(hid -> ux_host_class_hid_status); +#else UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UCHAR *report_buffer; -UCHAR *current_report_buffer; UX_HOST_CLASS_HID_REPORT *hid_report; UINT status; @@ -108,114 +204,62 @@ UINT status; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); - if (status != UX_SUCCESS) - return(status); + _ux_host_class_hid_lock_fail_return(hid); /* Get the report pointer from the caller. */ hid_report = client_report -> ux_host_class_hid_client_report; +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) - /* Ensure this is NOT an INPUT report. */ - if (hid_report -> ux_host_class_hid_report_type == UX_HOST_CLASS_HID_REPORT_TYPE_INPUT) + /* Check if there is an interrupt OUT endpoint. */ + if (hid -> ux_host_class_hid_interrupt_out_endpoint != UX_NULL) { - /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); - - /* Error trap. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) - - /* Return error code. */ - return(UX_HOST_CLASS_HID_REPORT_ERROR); + /* Transfer the report by using the interrupt OUT endpoint. */ + transfer_request = &hid -> ux_host_class_hid_interrupt_out_endpoint -> ux_endpoint_transfer_request; } - - /* Get some memory for sending the report. */ - if (hid_report -> ux_host_class_hid_report_id == 0) - report_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length); else - report_buffer = _ux_utility_memory_allocate_add_safe(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length, 1); - - if (report_buffer == UX_NULL) { - - /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); - - /* Return error code. */ - return(UX_MEMORY_INSUFFICIENT); - } - - /* Memorize the start of the real report buffer. */ - current_report_buffer = report_buffer; +#endif + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; - /* Check if there is a report ID to be inserted in front of the buffer. */ - if (hid_report -> ux_host_class_hid_report_id != 0) - *current_report_buffer++ = (UCHAR)(hid_report -> ux_host_class_hid_report_id); - - /* The report is in the client's buffer. It may be raw or or decompressed. If decompressed, - we need to create the report. */ - if (client_report -> ux_host_class_hid_client_report_flags & UX_HOST_CLASS_HID_REPORT_RAW) - { - - /* Ensure the user is not trying to overflow the report buffer. */ - if (hid_report -> ux_host_class_hid_report_byte_length >= client_report -> ux_host_class_hid_client_report_length) - { - - /* We have enough memory to store the raw buffer. */ - _ux_utility_memory_copy(current_report_buffer, client_report -> ux_host_class_hid_client_report_buffer, hid_report -> ux_host_class_hid_report_byte_length); /* Use case of memcpy is verified. */ - } - else + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) { - - /* Free allocated buffer. */ - _ux_utility_memory_free(report_buffer); - + + /* Something went wrong. */ /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); - - /* Error trap. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_OVERFLOW); - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) - - /* Return error code. */ - return(UX_HOST_CLASS_HID_REPORT_OVERFLOW); + _ux_host_class_hid_unlock(hid); + return(status); } - } - else - { - - /* The report buffer has to be compressed. */ - _ux_host_class_hid_report_compress(hid, client_report, current_report_buffer, client_report -> ux_host_class_hid_client_report_length); +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) } - - /* We need to get the default control endpoint transfer request pointer. */ - control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; - transfer_request = &control_endpoint -> ux_endpoint_transfer_request; - - /* Protect the control endpoint semaphore here. It will be unprotected in the - transfer request function. */ - status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); - - /* Check for status. */ +#endif + /* Build the report buffer for SET_REPORT request. */ + status = ux_host_class_hid_report_set_buffer_allocate(hid, client_report, &report_buffer); if (status != UX_SUCCESS) { - /* Something went wrong. */ - - /* Free all resources. */ - _ux_utility_memory_free(report_buffer); + /* Unlock device control endpoint. */ + _ux_host_semaphore_put(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) return(status); } - + /* Create a transfer request for the SET_REPORT request. */ transfer_request -> ux_transfer_request_data_pointer = report_buffer; transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length; @@ -226,10 +270,30 @@ UINT status; /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* Check if interrupt OUT endpoint is used. */ + if ((hid -> ux_host_class_hid_interrupt_out_endpoint != UX_NULL) && (status == UX_SUCCESS)) + { + + /* We need to wait for the completion of the transfer request. */ + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_HID_REPORT_TRANSFER_TIMEOUT)); + } +#endif - /* Check for correct transfer and entire descriptor returned. */ + /* Check for correct transfer and the actual transfer length. */ if ((status != UX_SUCCESS) || (transfer_request -> ux_transfer_request_actual_length != hid_report -> ux_host_class_hid_report_byte_length)) { +#if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* Check if interrupt OUT endpoint is used. */ + if ((hid -> ux_host_class_hid_interrupt_out_endpoint != UX_NULL) && (status != UX_SUCCESS)) + { + + /* We need to abort the transfer request. */ + _ux_host_stack_transfer_request_abort(transfer_request); + } +#endif /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); @@ -244,9 +308,10 @@ UINT status; _ux_utility_memory_free(report_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + _ux_host_class_hid_unlock(hid); /* Return the function status */ return(status); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_set_run.c b/common/usbx_host_classes/src/ux_host_class_hid_report_set_run.c new file mode 100644 index 00000000..a89fbf91 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_set_run.c @@ -0,0 +1,232 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) + +extern UINT ux_host_class_hid_report_set_buffer_allocate( + UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR **allocated); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_set_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets a report (input/output/feature) to the device. */ +/* The report can be either decompressed by the stack or raw. */ +/* */ +/* This function is for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* client_report Pointer to client report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_report_compress Compress HID report */ +/* _ux_host_stack_class_instance_verify Verify the instance is valid */ +/* _ux_host_stack_transfer_run Process transfer states */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) +{ + +UX_INTERRUPT_SAVE_AREA +UX_DEVICE *device; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UCHAR *report_buffer; +UX_HOST_CLASS_HID_REPORT *hid_report; +UINT status; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_SET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* Get device. */ + device = hid -> ux_host_class_hid_device; + + /* Sanity check. */ + if (device == UX_NULL || + device -> ux_device_handle != (ULONG)(ALIGN_TYPE)device) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, + device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + hid -> ux_host_class_hid_status = UX_DEVICE_HANDLE_UNKNOWN; + return(UX_STATE_EXIT); + } + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Waiting transfer done. */ + if (hid -> ux_host_class_hid_cmd_state == UX_STATE_WAIT) + { + + /* Process background tasks. */ + _ux_system_tasks_run(); + + /* Check if transfer is done. */ + if (transfer_request -> ux_transfer_request_state < UX_STATE_WAIT) + { + + /* Free allocated resource. */ + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + hid -> ux_host_class_hid_allocated = UX_NULL; + + /* Unlock. */ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + + /* We are done. */ + hid -> ux_host_class_hid_cmd_state = UX_STATE_IDLE; + hid -> ux_host_class_hid_status = + transfer_request -> ux_transfer_request_completion_code; + return(UX_STATE_NEXT); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + } + + /* Check state or protection status. */ + UX_DISABLE + if ((hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) || + (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)) + { + + /* Locked. */ + UX_RESTORE + return(UX_STATE_LOCK); + } + hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + hid -> ux_host_class_hid_cmd_state = UX_STATE_WAIT; + UX_RESTORE + + /* Build the report buffer for SET_REPORT request. */ + status = ux_host_class_hid_report_set_buffer_allocate(hid, client_report, &report_buffer); + if (status != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status, + hid, client_report, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error code. */ + hid -> ux_host_class_hid_status = status; + + /* Unlock. */ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + + /* State error. */ + hid -> ux_host_class_hid_cmd_state = UX_STATE_ERROR; + return(UX_STATE_ERROR); + } + hid -> ux_host_class_hid_allocated = report_buffer; + + /* Create a transfer request for the SET_REPORT request. */ + transfer_request -> ux_transfer_request_data_pointer = report_buffer; + transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_REPORT; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (UINT)((USHORT) hid_report -> ux_host_class_hid_report_id | (USHORT) hid_report -> ux_host_class_hid_report_type << 8); + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + UX_TRANSFER_STATE_RESET(transfer_request); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_run(transfer_request); + if (status != UX_STATE_WAIT) + { + _ux_utility_memory_free(hid -> ux_host_class_hid_allocated); + hid -> ux_host_class_hid_allocated = UX_NULL; + + hid -> ux_host_class_hid_status = + transfer_request -> ux_transfer_request_completion_code; + + /* Unlock. */ + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK; + device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK; + + hid -> ux_host_class_hid_cmd_state = (UCHAR)status; + } + + /* Return the function status */ + return(status); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hid_tasks_run.c b/common/usbx_host_classes/src/ux_host_class_hid_tasks_run.c new file mode 100644 index 00000000..4d95cc8d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_tasks_run.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) + + +static inline VOID _ux_host_class_hid_inst_tasks_run(UX_HOST_CLASS_HID *hid); + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs HID background tasks. */ +/* */ +/* This function is for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to hid instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_client_function) Client task function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_tasks_run(UX_HOST_CLASS *hid_class) +{ +UX_HOST_CLASS_HID *hid; + + /* Validate class entry. */ + if (hid_class -> ux_host_class_status != UX_USED || + hid_class -> ux_host_class_entry_function != _ux_host_class_hid_entry) + return(UX_STATE_IDLE); + + /* Run for class instances. */ + hid = (UX_HOST_CLASS_HID *)hid_class -> ux_host_class_first_instance; + while(hid) + { + + /* Run tasks for each hid instance. */ + if ((hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_PROTECT) == 0) + { + hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_PROTECT; + _ux_host_class_hid_inst_tasks_run(hid); + hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_PROTECT; + } + hid = hid -> ux_host_class_hid_next_instance; + } + return(UX_STATE_WAIT); +} + +static inline VOID _ux_host_class_hid_inst_tasks_run(UX_HOST_CLASS_HID *hid) +{ +UX_HOST_CLASS_HID_CLIENT *client = hid -> ux_host_class_hid_client; + if (client && client -> ux_host_class_hid_client_function) + { + client -> ux_host_class_hid_client_function(client); + } +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_hub_activate.c b/common/usbx_host_classes/src/ux_host_class_hub_activate.c index 404c2dd2..4707578a 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,7 +66,7 @@ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_host_semaphore_create Create semaphore */ /* */ /* CALLED BY */ /* */ @@ -81,6 +81,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hub_activate(UX_HOST_CLASS_COMMAND *command) diff --git a/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c index d3d46fc6..68a45b07 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort transfer */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -78,6 +78,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hub_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -123,7 +126,7 @@ UINT port_index; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Then de allocate the memory. */ _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); diff --git a/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c b/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c index 2001386b..115bc6c6 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_descriptor_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved protocol handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_hub_descriptor_get(UX_HOST_CLASS_HUB *hub) @@ -84,6 +87,7 @@ UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; UINT status; #if UX_MAX_DEVICES > 1 +ULONG tt_protocols; /* (bDeviceProtocol << 8) | bInterfaceProtocol */ ULONG port_index; #endif @@ -122,31 +126,74 @@ ULONG port_index; (UCHAR *) &hub -> ux_host_class_hub_descriptor); /* Check the protocol used by the HUB. This will indicate if the HUB supports multiple TTs in high speed mode. */ - switch (hub -> ux_host_class_hub_device -> ux_device_descriptor.bDeviceProtocol) + tt_protocols = (hub -> ux_host_class_hub_device -> ux_device_descriptor.bDeviceProtocol << 8) | + hub -> ux_host_class_hub_interface -> ux_interface_descriptor.bInterfaceProtocol; + switch(tt_protocols) { - case UX_HOST_CLASS_HUB_PROTOCOL_FS: + /* 1. A hub operating at full-/low-speed has a device descriptor with a bDeviceProtocol field set to zero(0) + * and an interface descriptor with a bInterfaceProtocol field set to zero(0). + */ + case (UX_HOST_CLASS_HUB_PROTOCOL_FS << 8): /* In the case of full speed hub, there are no TTs to declare */ break; - - - case UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT: - + + /* 2. A hub that has a single TT must set the bDeviceProtocol field of the device descriptor to one(1) and + * the interface descriptor bInterfaceProtocol field set to 0. + * 3. A multiple TT hub must set the bDeviceProtocol field of the device descriptor to two (2). + * The first interface descriptor has the bInterfaceProtocol field set to one(1). + */ + case (UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT << 8): /* Fall through. */ + case (UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT << 8) | UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT: + + /* Single TT hub or single TT interface. */ + /* Check if current setting supports this Hub. */ + if (hub -> ux_host_class_hub_descriptor.bNbPorts > UX_MAX_TT) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_TOO_MANY_HUB_PORTS); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TOO_MANY_HUB_PORTS, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_TOO_MANY_HUB_PORTS; + break; + } + /* In a single TT state, all the downstream ports report to the same - TT and share the 1.1 USB segment bandwidth. This is a very crude - but working method, we simply set all the ports bits to the first - TT. */ + TT and share the 1.1 USB segment bandwidth. This is a very crude + but working method, we simply set all the ports bits to the first + TT. */ hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_port_mapping = UX_TT_MASK; hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_max_bandwidth = UX_TT_BANDWIDTH; - break; + break; + + /* 3. A multiple TT hub must set the bDeviceProtocol field of the device descriptor to two (2). + * The first interface descriptor has the bInterfaceProtocol field set to one(1). + * Such a hub also has a second interface descriptor where the bInterfaceProtocol is set to two(2). + */ + case (UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT << 8) | UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT: + + /* Multiple TTs. */ + /* Check if current setting supports this Hub. */ + if (hub -> ux_host_class_hub_descriptor.bNbPorts > UX_MAX_TT) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_TOO_MANY_HUB_PORTS); - case UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT: + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TOO_MANY_HUB_PORTS, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_TOO_MANY_HUB_PORTS; + break; + } /* In the case of multiple TTs, each downstream port can sustain the USB 1.1 - max bandwidth and therefore we allocate one TT per port with that bandwidth. */ - for (port_index = 0; port_index < hub -> ux_host_class_hub_descriptor.bNbPorts;port_index++) + max bandwidth and therefore we allocate one TT per port with that bandwidth. */ + for (port_index = 0; port_index < hub -> ux_host_class_hub_descriptor.bNbPorts; port_index++) { hub -> ux_host_class_hub_device -> ux_device_hub_tt[port_index].ux_hub_tt_port_mapping = (ULONG)(1 << port_index); @@ -154,8 +201,7 @@ ULONG port_index; } break; - - default: + default: /* Invalid bDeviceProtocol and bInterfaceProtocol pair. */ /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_DESCRIPTOR_CORRUPTED); @@ -188,4 +234,3 @@ ULONG port_index; /* Return completion status. */ return(status); } - diff --git a/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c index ccdb2e5c..79eb1fb7 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_transfer_request_completed PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,7 +65,7 @@ /* */ /* CALLS */ /* */ -/* _ux_utility_semaphore_put Put the signaling semaphore */ +/* _ux_host_semaphore_put Put the signaling semaphore */ /* */ /* CALLED BY */ /* */ @@ -78,6 +78,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_hub_transfer_request_completed(UX_TRANSFER *transfer_request) @@ -119,7 +122,7 @@ UX_HOST_CLASS_HUB *hub; /* Now we can set the semaphore, the enum thread will wake up and will call the HUB instance which has a status change. */ - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); /* Return to caller. */ return; diff --git a/common/usbx_host_classes/src/ux_host_class_pima_command.c b/common/usbx_host_classes/src/ux_host_class_pima_command.c index 7f8bd65a..6c749878 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_command.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_command.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_command PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_command(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_COMMAND *command, @@ -139,7 +142,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -233,7 +236,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c b/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c index 7fd22aaf..917ec9fd 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,8 +59,8 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -91,7 +94,7 @@ UINT status; pima -> ux_host_class_pima_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&pima -> ux_host_class_pima_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&pima -> ux_host_class_pima_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -127,7 +130,7 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Free the header container buffer. */ if (pima -> ux_host_class_pima_container != UX_NULL) @@ -162,7 +165,7 @@ UINT status; _ux_host_stack_class_instance_destroy(pima -> ux_host_class_pima_class, (VOID *) pima); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&pima -> ux_host_class_pima_semaphore); + _ux_host_semaphore_delete(&pima -> ux_host_class_pima_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_close.c b/common/usbx_host_classes/src/ux_host_class_pima_object_close.c index 17dc49bc..14d8d7dd 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_object_close.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_close.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_object_close PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,7 +59,7 @@ /* _ux_host_stack_transfer_request Transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer */ /* _ux_host_stack_endpoint_reset Reset endpoint */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_object_close(UX_HOST_CLASS_PIMA *pima, @@ -143,7 +146,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -185,7 +188,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_get.c b/common/usbx_host_classes/src/ux_host_class_pima_object_get.c index c86686ca..31df74c2 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_object_get.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_object_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,7 +62,7 @@ /* _ux_host_stack_transfer_request Transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer */ /* _ux_host_stack_endpoint_reset Reset endpoint */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* _ux_utility_memory_copy Copy memory */ /* _ux_utility_long_get Get 32-bit value */ /* _ux_utility_long_put Put 32-bit value */ @@ -82,6 +82,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_object_get(UX_HOST_CLASS_PIMA *pima, @@ -179,7 +182,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) @@ -239,7 +242,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) @@ -362,7 +365,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_send.c b/common/usbx_host_classes/src/ux_host_class_pima_object_send.c index de8b8e06..f5d25f74 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_object_send.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_send.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_object_send PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,7 +65,7 @@ /* _ux_host_stack_transfer_request Transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer */ /* _ux_host_stack_endpoint_reset Reset endpoint */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* _ux_utility_long_put Put 32-bit value */ /* _ux_utility_short_put Put 16-bit value */ /* */ @@ -83,6 +83,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_object_send(UX_HOST_CLASS_PIMA *pima, @@ -168,7 +171,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -261,7 +264,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -329,7 +332,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_read.c b/common/usbx_host_classes/src/ux_host_class_pima_read.c index ee272a3d..79b00b48 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_read.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_read.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,7 +68,7 @@ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_host_stack_endpoint_reset Reset endpoint */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* _ux_utility_long_get Get a long 32 bit value */ /* _ux_utility_short_get Get a short 16 bit value */ /* _ux_utility_memory_copy Copy memory */ @@ -87,6 +87,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_read(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, @@ -126,7 +129,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -211,7 +214,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -266,7 +269,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c b/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c index dbdbc267..72163c45 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_thumb_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -63,7 +63,7 @@ /* _ux_host_stack_transfer_request Transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_host_stack_endpoint_reset Reset endpoint */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* _ux_utility_short_put Put 16-bit value */ /* _ux_utility_long_put Put 32-bit value */ /* */ @@ -81,6 +81,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_thumb_get(UX_HOST_CLASS_PIMA *pima, @@ -177,7 +180,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -233,7 +236,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -324,7 +327,7 @@ UINT status; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_pima_write.c b/common/usbx_host_classes/src/ux_host_class_pima_write.c index 60129e6a..cf7f71f0 100644 --- a/common/usbx_host_classes/src/ux_host_class_pima_write.c +++ b/common/usbx_host_classes/src/ux_host_class_pima_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_pima_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,7 +64,7 @@ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_host_stack_endpoint_reset Reset endpoint */ /* _ux_utility_memory_copy Copy memory */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* _ux_utility_long_put Put a long 32 bit value */ /* _ux_utility_short_put Put a short 16 bit value */ /* */ @@ -82,6 +82,9 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_pima_write(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, @@ -158,7 +161,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -217,7 +220,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -272,7 +275,7 @@ ULONG payload_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_printer_activate.c b/common/usbx_host_classes/src/ux_host_class_printer_activate.c index c23eefcc..4a82ec76 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_activate.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Printer Class */ /** */ @@ -30,50 +30,53 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_printer_activate PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_activate PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function calls the USBX stack to activate the class. */ -/* */ -/* INPUT */ -/* */ -/* command Printer class command pointer */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_host_class_printer_configure Configure printer class */ -/* _ux_host_class_printer_endpoints_get Get endpoints of printer */ -/* _ux_host_class_printer_name_get Get printer name */ -/* _ux_host_stack_class_instance_create Create class instance */ -/* _ux_host_stack_class_instance_destroy Destroy the class instance */ -/* _ux_utility_memory_allocate Allocate memory block */ -/* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create printer semaphore */ -/* */ -/* CALLED BY */ -/* */ -/* _ux_host_class_printer_entry Entry of printer class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* This function calls the USBX stack to activate the class. */ +/* */ +/* INPUT */ +/* */ +/* command Printer class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_printer_configure Configure printer class */ +/* _ux_host_class_printer_endpoints_get Get endpoints of printer */ +/* _ux_host_class_printer_name_get Get printer name */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_host_semaphore_create Create printer semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_entry Entry of printer class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_activate(UX_HOST_CLASS_COMMAND *command) @@ -81,8 +84,10 @@ UINT _ux_host_class_printer_activate(UX_HOST_CLASS_COMMAND *command) UX_INTERFACE *interface; UX_HOST_CLASS_PRINTER *printer; +#if !defined(UX_HOST_STANDALONE) UINT status; - +#endif + /* The printer is always activated by the interface descriptor and not the device descriptor. */ @@ -108,21 +113,29 @@ UINT status; /* Create this class instance. */ _ux_host_stack_class_instance_create(printer -> ux_host_class_printer_class, (VOID *) printer); +#if defined(UX_HOST_STANDALONE) + + /* Do activate steps. */ + printer -> ux_host_class_printer_enum_state = UX_STATE_WAIT; + printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + return(UX_SUCCESS); +#else + /* Configure the printer. */ status = _ux_host_class_printer_configure(printer); - /* Get the name of the printer from the 1284 descriptor. */ - if (status == UX_SUCCESS) - status = _ux_host_class_printer_name_get(printer); - /* Get the printer endpoint(s). We may need to search for Bulk Out and Bulk In endpoints. */ if (status == UX_SUCCESS) status = _ux_host_class_printer_endpoints_get(printer); + /* Get the name of the printer from the 1284 descriptor. */ + if (status == UX_SUCCESS) + status = _ux_host_class_printer_name_get(printer); + /* Create the semaphore to protect 2 threads from accessing the same printer instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&printer -> ux_host_class_printer_semaphore, "ux_host_class_printer_semaphore", 1); + status = _ux_host_semaphore_create(&printer -> ux_host_class_printer_semaphore, "ux_host_class_printer_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -138,7 +151,7 @@ UINT status; if a function has been programmed in the system structure. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) { - + /* Call system change function. */ _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, printer -> ux_host_class_printer_class, (VOID *) printer); } @@ -159,6 +172,8 @@ UINT status; _ux_utility_memory_free(printer); /* Return completion status. */ - return(status); + return(status); + +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c b/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c index bfe648b4..8cd3b8c4 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Printer Class */ /** */ @@ -30,58 +30,63 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_printer_deactivate PORTABLE C */ -/* 6.1 */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_deactivate PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ +/* */ /* This function is called when this instance of the printer has been */ -/* removed from the bus either directly or indirectly. The bulk in\out */ -/* pipes will be destroyed and the instanced removed. */ -/* */ -/* INPUT */ -/* */ -/* command Printer class command pointer */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Printer class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort */ -/* Abort endpoint transfer */ -/* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ -/* */ -/* CALLED BY */ -/* */ -/* _ux_host_class_printer_entry Entry of printer class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_entry Entry of printer class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_deactivate(UX_HOST_CLASS_COMMAND *command) { UX_HOST_CLASS_PRINTER *printer; +#if !defined(UX_HOST_STANDALONE) UINT status; +#endif /* Get the instance for this class. */ @@ -90,13 +95,16 @@ UINT status; /* The printer is being shut down. */ printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; +#if !defined(UX_HOST_STANDALONE) + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ return(status); - +#endif + /* We need to abort transactions on the bulk out pipe. */ _ux_host_stack_endpoint_transfer_abort(printer -> ux_host_class_printer_bulk_out_endpoint); @@ -104,21 +112,32 @@ UINT status; if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) _ux_host_stack_endpoint_transfer_abort(printer -> ux_host_class_printer_bulk_in_endpoint); +#if !defined(UX_HOST_STANDALONE) + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); +#else + + /* Free allocated memory. */ + if (printer -> ux_host_class_printer_allocated) + _ux_utility_memory_free(printer -> ux_host_class_printer_allocated); +#endif /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(printer -> ux_host_class_printer_class, (VOID *) printer); +#if !defined(UX_HOST_STANDALONE) + /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&printer -> ux_host_class_printer_semaphore); + _ux_host_semaphore_delete(&printer -> ux_host_class_printer_semaphore); +#endif /* Before we free the device resources, we need to inform the application that the device is removed. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) { - + /* Inform the application the device is removed. */ _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, printer -> ux_host_class_printer_class, (VOID *) printer); } @@ -133,6 +152,6 @@ UINT status; _ux_utility_memory_free(printer); /* Return successful status. */ - return(UX_SUCCESS); + return(UX_SUCCESS); } diff --git a/common/usbx_host_classes/src/ux_host_class_printer_device_id_get.c b/common/usbx_host_classes/src/ux_host_class_printer_device_id_get.c index 5601fad7..b7478417 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_device_id_get.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_device_id_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_device_id_get PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,10 +76,16 @@ /* DATE NAME DESCRIPTION */ /* */ /* 02-02-2021 Chaoqiong Xiao Initial Version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_device_id_get(UX_HOST_CLASS_PRINTER *printer, UCHAR *descriptor_buffer, ULONG length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_INTERFACE *interface; UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; @@ -90,20 +96,34 @@ UINT status; UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_DEVICE_ID_GET, printer, descriptor_buffer, length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if ((printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) || + (printer -> ux_host_class_printer_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)) + { + UX_RESTORE + return(UX_BUSY); + } + printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK; + printer -> ux_host_class_printer_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + UX_RESTORE +#else + + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) { - _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_semaphore_put(&printer -> ux_host_class_printer_semaphore); return(status); } +#endif /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; @@ -121,11 +141,17 @@ UINT status; transfer_request -> ux_transfer_request_index = (interface -> ux_interface_descriptor.bInterfaceNumber << 8) | (interface -> ux_interface_descriptor.bAlternateSetting ); +#if defined(UX_HOST_STANDALONE) + + /* Enable auto unlock device. */ + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; +#endif + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c index ba8114ae..faecb03d 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_endpoints_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* initialized timeout values, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_endpoints_get(UX_HOST_CLASS_PRINTER *printer) @@ -98,6 +101,10 @@ UX_ENDPOINT *endpoint; /* This transfer_request always have the OUT direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + /* By default wait UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT); + /* We have found the bulk endpoint, save it. */ printer -> ux_host_class_printer_bulk_out_endpoint = endpoint; break; @@ -117,8 +124,10 @@ UX_ENDPOINT *endpoint; /* Search the bulk IN endpoint. This endpoint is optional and only valid for bidirectional printers. It is attached to the interface container. */ - if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == - UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + if ((printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == + UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) || + (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == + UX_HOST_CLASS_PRINTER_PROTOCOL_IEEE_1284_4_BI_DIR)) { for (endpoint_index = 0; endpoint_index < printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bNumEndpoints; @@ -140,6 +149,10 @@ UX_ENDPOINT *endpoint; /* This transfer_request always have the IN direction. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + /* By default wait UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT); + /* We have found the bulk endpoint, save it. */ printer -> ux_host_class_printer_bulk_in_endpoint = endpoint; break; @@ -147,9 +160,8 @@ UX_ENDPOINT *endpoint; } } - /* The bulk in endpoint is not mandatory. */ - if ((printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) - && (printer -> ux_host_class_printer_bulk_in_endpoint == UX_NULL)) + /* The bulk in endpoint is mandatory for these protocol. */ + if (printer -> ux_host_class_printer_bulk_in_endpoint == UX_NULL) { /* If trace is enabled, insert this event into the trace buffer. */ diff --git a/common/usbx_host_classes/src/ux_host_class_printer_entry.c b/common/usbx_host_classes/src/ux_host_class_printer_entry.c index 8ee7c020..f6a774d3 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_entry.c @@ -30,12 +30,27 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) +#define UX_HOST_CLASS_PRINTER_ENUM_START (UX_STATE_WAIT) +#define UX_HOST_CLASS_PRINTER_ENUM_IDLE (UX_STATE_IDLE) + +#define UX_HOST_CLASS_PRINTER_ENUM_NAME_GET (UX_STATE_STACK_STEP + 0) +#define UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE (UX_STATE_STACK_STEP + 1) +#define UX_HOST_CLASS_PRINTER_ENUM_TRANSFER (UX_STATE_STACK_STEP + 2) +#define UX_HOST_CLASS_PRINTER_ENUM_DONE (UX_STATE_STACK_STEP + 3) + +extern VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer, + UCHAR *descriptor_buffer, ULONG descriptor_length); + +static inline UINT _ux_host_class_printer_activate_wait(UX_HOST_CLASS_COMMAND *command); +#endif + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +85,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_entry(UX_HOST_CLASS_COMMAND *command) @@ -100,6 +118,12 @@ UINT status; status = _ux_host_class_printer_activate(command); return(status); +#if defined(UX_HOST_STANDALONE) + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + status = _ux_host_class_printer_activate_wait(command); + return(status); +#endif + case UX_HOST_CLASS_COMMAND_DEACTIVATE: /* The deactivate command is used when the device has been extracted either @@ -116,3 +140,149 @@ UINT status; } } +#if defined(UX_HOST_STANDALONE) +static inline UINT _ux_host_class_printer_activate_wait(UX_HOST_CLASS_COMMAND *command) +{ +UX_INTERFACE *interface; +UX_HOST_CLASS_PRINTER *printer; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer; +UINT status; + + /* Get the instance for this class. */ + interface = (UX_INTERFACE *)command -> ux_host_class_command_container; + + /* Sanity check. */ + if (interface == UX_NULL) + return(UX_STATE_EXIT); + + printer = (UX_HOST_CLASS_PRINTER *) interface -> ux_interface_class_instance; + + /* Sanity check. */ + if (printer == UX_NULL) + return(UX_STATE_EXIT); + + switch(printer -> ux_host_class_printer_enum_state) + { + case UX_HOST_CLASS_PRINTER_ENUM_START: + status = _ux_host_class_printer_endpoints_get(printer); + if (status != UX_SUCCESS) + { + printer -> ux_host_class_printer_status = status; + printer -> ux_host_class_printer_enum_state = + UX_HOST_CLASS_PRINTER_ENUM_DONE; + return(UX_STATE_WAIT); + } + + /* Fall through. */ + case UX_HOST_CLASS_PRINTER_ENUM_NAME_GET: + status = _ux_host_class_printer_name_get(printer); + if (status != UX_SUCCESS) + { + printer -> ux_host_class_printer_status = status; + printer -> ux_host_class_printer_enum_state = + UX_HOST_CLASS_PRINTER_ENUM_DONE; + return(UX_STATE_WAIT); + } + + /* Next: transfer -> parse name. */ + printer -> ux_host_class_printer_enum_state = + UX_HOST_CLASS_PRINTER_ENUM_TRANSFER; + printer -> ux_host_class_printer_next_state = + UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE; + + /* Fall through. */ + case UX_HOST_CLASS_PRINTER_ENUM_TRANSFER: + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; + transfer = &control_endpoint -> ux_endpoint_transfer_request; + + status = _ux_host_stack_transfer_run(transfer); + + /* Transfer finished any way. */ + if (status < UX_STATE_WAIT) + { + + /* Error. */ + if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS) + { + printer -> ux_host_class_printer_status = status; + printer -> ux_host_class_printer_enum_state = + UX_HOST_CLASS_PRINTER_ENUM_DONE; + return(UX_STATE_WAIT); + } + + /* Next state. */ + printer -> ux_host_class_printer_enum_state = + printer -> ux_host_class_printer_next_state; + + return(UX_STATE_WAIT); + } + + /* Wait transfer. */ + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE: + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; + transfer = &control_endpoint -> ux_endpoint_transfer_request; + + _ux_host_class_printer_name_parse(printer, + transfer -> ux_transfer_request_data_pointer, + transfer -> ux_transfer_request_actual_length); + + /* Fall through. */ + case UX_HOST_CLASS_PRINTER_ENUM_DONE: + + /* Free allocated resources. */ + if (printer -> ux_host_class_printer_allocated) + { + _ux_utility_memory_free(printer -> ux_host_class_printer_allocated); + printer -> ux_host_class_printer_allocated = UX_NULL; + } + + /* Check status. */ + if (printer -> ux_host_class_printer_status != UX_SUCCESS) + { + + /* On error, free resources. */ + _ux_host_stack_class_instance_destroy( + printer -> ux_host_class_printer_class, (VOID *) printer); + interface -> ux_interface_class_instance = UX_NULL; + _ux_utility_memory_free(printer); + return(UX_STATE_ERROR); + } + + /* Success. */ + + /* Mark the printer as live now. */ + printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, printer -> ux_host_class_printer_class, (VOID *) printer); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_ACTIVATE, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, printer, 0, 0, 0) + + /* Return success. */ + printer -> ux_host_class_printer_enum_state = UX_STATE_IDLE; + return(UX_STATE_NEXT); + + default: /* reset, idle, error ... */ + return(UX_STATE_NEXT); + } + + return(UX_STATE_NEXT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_printer_name_get.c b/common/usbx_host_classes/src/ux_host_class_printer_name_get.c index 7e500e0d..6e74d7f4 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_name_get.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_name_get.c @@ -30,12 +30,102 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) +static inline +#else +VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer, UCHAR *descriptor_buffer, ULONG descriptor_length); +#endif +VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer, UCHAR *descriptor_buffer, ULONG descriptor_length) +{ +ULONG length; +UCHAR * printer_name_buffer; +UCHAR * printer_name; +UINT printer_name_length; + + /* Cannot use descriptor buffer, so copy it to 1284 buffer. */ + printer_name_buffer = descriptor_buffer; + + /* Retrieve the printer name which is a USHORT at the beginning of the returned buffer. */ + length = (USHORT)_ux_utility_short_get_big_endian(printer_name_buffer); + if (length < descriptor_length) + descriptor_length = length; + + /* Point the name buffer after the length. */ + printer_name_buffer += 2; + + /* Parse the name for a tag which is in the form DES: or DESCRIPTOR: */ + while (descriptor_length != 0) + { + + if (descriptor_length > 12) + { + + /* Compare the current pointer position with the DESCRIPTOR: tag. */ + if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DESCRIPTION, 12) == UX_SUCCESS) + { + + printer_name_buffer += 12; + descriptor_length = (USHORT)(descriptor_length - 12); + break; + } + } + + if (descriptor_length > 4) + { + + /* Compare the current pointer position with the DES: tag. */ + if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DES, 4) == UX_SUCCESS) + { + + printer_name_buffer += 4; + descriptor_length = (USHORT)(descriptor_length - 4); + break; + } + } + + /* And reduce the remaining length by 1. */ + descriptor_length--; + + /* Increment the descriptor pointer. */ + printer_name_buffer++; + } + + /* If the length remaining is 0, we have not found the descriptor tag we wanted. */ + if (descriptor_length == 0) + { + + /* Use the generic USB printer name. */ + _ux_utility_memory_copy(printer -> ux_host_class_printer_name, UX_HOST_CLASS_PRINTER_GENERIC_NAME, 11); /* Use case of memcpy is verified. */ + } + else + { + + /* We have found a tag and the name is right after delimited by ; or a 0. */ + printer_name = printer -> ux_host_class_printer_name; + printer_name_length = UX_HOST_CLASS_PRINTER_NAME_LENGTH; + + /* Parse the name and only copy the name until the max length is reached + or the delimiter is reached. */ + while ((descriptor_length--) && (printer_name_length--)) + { + + /* Check for the delimiter. */ + if((*printer_name_buffer == 0) || (*printer_name_buffer == ';')) + break; + else + /* Copy the name of the printer to the printer instance character + by character. */ + *printer_name++ = *printer_name_buffer++; + } + } +} + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_name_get PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -79,20 +169,21 @@ /* supported interface other */ /* than number zero, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_name_get(UX_HOST_CLASS_PRINTER *printer) { UCHAR * descriptor_buffer; -UCHAR * printer_name_buffer; -UCHAR * printer_name; UX_INTERFACE *interface; UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; +#if !defined(UX_HOST_STANDALONE) UINT status; -USHORT descriptor_length; -UINT printer_name_length; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_NAME_GET, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) @@ -118,6 +209,12 @@ UINT printer_name_length; transfer_request -> ux_transfer_request_index = (interface -> ux_interface_descriptor.bInterfaceNumber << 8) | (interface -> ux_interface_descriptor.bAlternateSetting ); +#if defined(UX_HOST_STANDALONE) + printer -> ux_host_class_printer_allocated = descriptor_buffer; + UX_TRANSFER_STATE_RESET(transfer_request); + return(UX_SUCCESS); +#else + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -125,86 +222,16 @@ UINT printer_name_length; if(status == UX_SUCCESS) { - /* Cannot use descriptor buffer, so copy it to 1284 buffer. */ - printer_name_buffer = descriptor_buffer; - - /* Retrieve the printer name which is a USHORT at the beginning of the returned buffer. */ - descriptor_length = (USHORT)_ux_utility_short_get_big_endian(printer_name_buffer); - - /* Point the name buffer after the length. */ - printer_name_buffer += 2; - - /* Parse the name for a tag which is in the form DES: or DESCRIPTOR: */ - while (descriptor_length != 0) - { - - if (descriptor_length > 12) - { - - /* Compare the current pointer position with the DESCRIPTOR: tag. */ - if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DESCRIPTION, 12) == UX_SUCCESS) - { - - printer_name_buffer += 12; - descriptor_length = (USHORT)(descriptor_length - 12); - break; + _ux_host_class_printer_name_parse(printer, descriptor_buffer, + UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH); } - } - - if (descriptor_length > 4) - { - - /* Compare the current pointer position with the DES: tag. */ - if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DES, 4) == UX_SUCCESS) - { - - printer_name_buffer += 4; - descriptor_length = (USHORT)(descriptor_length - 4); - break; - } - } - - /* And reduce the remaining length by 1. */ - descriptor_length--; - - /* Increment the descriptor pointer. */ - printer_name_buffer++; - } - - /* If the length remaining is 0, we have not found the descriptor tag we wanted. */ - if (descriptor_length == 0) - { - - /* Use the generic USB printer name. */ - _ux_utility_memory_copy(printer -> ux_host_class_printer_name, UX_HOST_CLASS_PRINTER_GENERIC_NAME, 11); /* Use case of memcpy is verified. */ - } - else - { - - /* We have found a tag and the name is right after delimited by ; or a 0. */ - printer_name = printer -> ux_host_class_printer_name; - printer_name_length = UX_HOST_CLASS_PRINTER_NAME_LENGTH; - - /* Parse the name and only copy the name until the max length is reached - or the delimiter is reached. */ - while ((descriptor_length--) && (printer_name_length--)) - { - - /* Check for the delimiter. */ - if((*printer_name_buffer == 0) || (*printer_name_buffer == ';')) - break; - else - /* Copy the name of the printer to the printer instance character - by character. */ - *printer_name++ = *printer_name_buffer++; - } - } - } /* Free all used resources. */ _ux_utility_memory_free(descriptor_buffer); /* Return completion status. */ return(status); + +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_printer_read.c b/common/usbx_host_classes/src/ux_host_class_printer_read.c index 122bfb9a..ae64a212 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_read.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,8 +64,8 @@ /* _ux_host_stack_class_instance_verify Verify the class instance */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,12 +79,20 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* adjusted bi-dir check, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_read (UX_HOST_CLASS_PRINTER *printer, UCHAR *data_pointer, ULONG requested_length, ULONG *actual_length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +ULONG transfer_flags; +#endif UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; @@ -105,21 +113,13 @@ ULONG transfer_request_length; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } - /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); - if (status != UX_SUCCESS) - - /* Return error. */ - return(status); - /* Check if the printer is bidirectional. */ - if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol != - UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + if ((printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol != + UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) && + (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol != + UX_HOST_CLASS_PRINTER_PROTOCOL_IEEE_1284_4_BI_DIR)) { - /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); - /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); @@ -130,12 +130,37 @@ ULONG transfer_request_length; return(UX_FUNCTION_NOT_SUPPORTED); } + /* Protect thread reentry to this instance. */ +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK; + UX_RESTORE +#else + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); +#endif + /* Start by resetting the actual length of the transfer to zero. */ *actual_length = 0; /* Get the pointer to the bulk in endpoint in the transfer_request. */ transfer_request = &printer -> ux_host_class_printer_bulk_in_endpoint -> ux_endpoint_transfer_request; - + +#if defined(UX_HOST_STANDALONE) + + /* Enable blocking transfer flags. */ + transfer_flags = transfer_request -> ux_transfer_request_flags; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk in endpoint until either the transfer is completed or until there is an error. */ while (requested_length) @@ -157,9 +182,10 @@ ULONG transfer_request_length; /* If the transfer is successful, we need to wait for the transfer request to be completed. */ if (status == UX_SUCCESS) { - +#if !defined(UX_HOST_STANDALONE) + /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -173,7 +199,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -187,12 +213,18 @@ ULONG transfer_request_length; /* There was an error, return to the caller */ return(UX_TRANSFER_TIMEOUT); } +#endif } else { +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* There was a non transfer error, no partial transfer to be checked. */ return(status); @@ -206,9 +238,14 @@ ULONG transfer_request_length; actually received and determine if a partial transfer is OK. */ if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) { - +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif + /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Return success to caller. */ return(UX_SUCCESS); @@ -221,8 +258,14 @@ ULONG transfer_request_length; requested_length -= transfer_request_length; } +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif + /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c b/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c index 7b81a1d0..5faab001 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_soft_reset PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,8 +56,8 @@ /* CALLS */ /* */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,12 +74,16 @@ /* supported interface other */ /* than number zero, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_soft_reset(UX_HOST_CLASS_PRINTER *printer) { - - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_INTERFACE *interface; UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; @@ -101,8 +105,21 @@ UINT status; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if ((printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) || + (printer -> ux_host_class_printer_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)) + { + UX_RESTORE + return(UX_BUSY); + } + printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK; + printer -> ux_host_class_printer_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + UX_RESTORE +#else + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -118,6 +135,7 @@ UINT status; _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); return(status); } +#endif /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; @@ -134,11 +152,17 @@ UINT status; transfer_request -> ux_transfer_request_value = 0; transfer_request -> ux_transfer_request_index = interface -> ux_interface_descriptor.bInterfaceNumber; +#if defined(UX_HOST_STANDALONE) + + /* Enable auto unlock device. */ + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; +#endif + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_printer_status_get.c b/common/usbx_host_classes/src/ux_host_class_printer_status_get.c index 052a7fee..4d813dd1 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_status_get.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_status_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_status_get PORTABLE C */ -/* 6.1.4 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* _ux_utility_long_get Get 32-bit long word */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,11 +79,16 @@ /* supported interface other */ /* than number zero, */ /* resulting in version 6.1.4 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_status_get(UX_HOST_CLASS_PRINTER *printer, ULONG *printer_status) { - +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +#endif UX_INTERFACE *interface; UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; @@ -100,8 +105,21 @@ UCHAR * printer_status_buffer; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if ((printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) || + (printer -> ux_host_class_printer_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)) + { + UX_RESTORE + return(UX_BUSY); + } + printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK; + printer -> ux_host_class_printer_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK; + UX_RESTORE +#else + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -117,6 +135,7 @@ UCHAR * printer_status_buffer; _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); return(status); } +#endif /* We need to get the default control endpoint transfer_request pointer. */ control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; @@ -128,7 +147,7 @@ UCHAR * printer_status_buffer; { /* Unprotect thread reentry to this instance */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); return(UX_MEMORY_INSUFFICIENT); } @@ -143,6 +162,12 @@ UCHAR * printer_status_buffer; transfer_request -> ux_transfer_request_value = 0; transfer_request -> ux_transfer_request_index = interface -> ux_interface_descriptor.bInterfaceNumber; +#if defined(UX_HOST_STANDALONE) + + /* Enable auto unlock device. */ + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK; +#endif + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -175,9 +200,8 @@ UCHAR * printer_status_buffer; _ux_utility_memory_free(printer_status_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Return completion status. */ return(status); } - diff --git a/common/usbx_host_classes/src/ux_host_class_printer_write.c b/common/usbx_host_classes/src/ux_host_class_printer_write.c index 06cbb056..b3bb58ce 100644 --- a/common/usbx_host_classes/src/ux_host_class_printer_write.c +++ b/common/usbx_host_classes/src/ux_host_class_printer_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_printer_write PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,12 +79,19 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* fixed ZLP sending issue, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_printer_write(UX_HOST_CLASS_PRINTER *printer, UCHAR * data_pointer, ULONG requested_length, ULONG *actual_length) { +#if defined(UX_HOST_STANDALONE) +UX_INTERRUPT_SAVE_AREA +ULONG transfer_flags; +#endif UX_TRANSFER *transfer_request; UINT status; ULONG transfer_request_length; @@ -105,12 +112,24 @@ ULONG transfer_request_length; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } +#if defined(UX_HOST_STANDALONE) + UX_DISABLE + if (printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) + { + UX_RESTORE + return(UX_BUSY); + } + printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK; + UX_RESTORE +#else + /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ return(status); +#endif /* Start by resetting the actual length of the transfer. */ *actual_length = 0; @@ -118,6 +137,13 @@ ULONG transfer_request_length; /* Get the pointer to the bulk out endpoint transfer request. */ transfer_request = &printer -> ux_host_class_printer_bulk_out_endpoint -> ux_endpoint_transfer_request; +#if defined(UX_HOST_STANDALONE) + + /* Enable blocking transfer flags. */ + transfer_flags = transfer_request -> ux_transfer_request_flags; + transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT; +#endif + /* Perform a transfer on the bulk out endpoint until either the transfer is completed or when there is an error. */ do @@ -139,9 +165,10 @@ ULONG transfer_request_length; /* If the transfer is successful, we need to wait for the transfer request to be completed. */ if (status == UX_SUCCESS) { +#if !defined(UX_HOST_STANDALONE) /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -155,7 +182,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -169,12 +196,18 @@ ULONG transfer_request_length; /* There was an error, return to the caller. */ return(UX_TRANSFER_TIMEOUT); } +#endif } else { +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* There was a non transfer error, no partial transfer to be checked */ return(status); @@ -188,9 +221,14 @@ ULONG transfer_request_length; actually sent and determine if a partial transfer is OK. */ if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) { +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* Return success. */ return(UX_SUCCESS); @@ -203,8 +241,14 @@ ULONG transfer_request_length; requested_length -= transfer_request_length; } while (requested_length); +#if defined(UX_HOST_STANDALONE) + + /* Restore transfer options. */ + transfer_request -> ux_transfer_request_flags = transfer_flags; +#endif + /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + _ux_host_class_printer_unlock(printer); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_activate.c b/common/usbx_host_classes/src/ux_host_class_prolific_activate.c index b8d26a67..b9ddba3c 100644 --- a/common/usbx_host_classes/src/ux_host_class_prolific_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_prolific_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_prolific_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create prolific semaphore */ +/* _ux_host_semaphore_create Create prolific semaphore */ /* _ux_host_class_prolific_ioctl IOCTL function for DLC */ /* */ /* CALLED BY */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_prolific_activate(UX_HOST_CLASS_COMMAND *command) @@ -151,7 +154,7 @@ UINT status; /* Create the semaphore to protect 2 threads from accessing the same prolific instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&prolific -> ux_host_class_prolific_semaphore, "ux_host_class_prolific_semaphore", 1); + status = _ux_host_semaphore_create(&prolific -> ux_host_class_prolific_semaphore, "ux_host_class_prolific_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_command.c b/common/usbx_host_classes/src/ux_host_class_prolific_command.c index c6d7f1e7..9044e154 100644 --- a/common/usbx_host_classes/src/ux_host_class_prolific_command.c +++ b/common/usbx_host_classes/src/ux_host_class_prolific_command.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_prolific_command PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,7 +66,7 @@ /* CALLS */ /* */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,6 +79,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_prolific_command(UX_HOST_CLASS_PROLIFIC *prolific, ULONG command, @@ -96,7 +99,7 @@ UINT status; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&prolific -> ux_host_class_prolific_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&prolific -> ux_host_class_prolific_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c b/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c index 1a3e68a0..20e3a45b 100644 --- a/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_prolific_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_prolific_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -92,7 +95,7 @@ UINT status; prolific -> ux_host_class_prolific_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&prolific -> ux_host_class_prolific_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&prolific -> ux_host_class_prolific_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -133,13 +136,13 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(prolific -> ux_host_class_prolific_class, (VOID *) prolific); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&prolific -> ux_host_class_prolific_semaphore); + _ux_host_semaphore_delete(&prolific -> ux_host_class_prolific_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_read.c b/common/usbx_host_classes/src/ux_host_class_prolific_read.c index cde7c274..ca2faa7f 100644 --- a/common/usbx_host_classes/src/ux_host_class_prolific_read.c +++ b/common/usbx_host_classes/src/ux_host_class_prolific_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_prolific_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +76,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_prolific_read (UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, @@ -131,7 +134,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_write.c b/common/usbx_host_classes/src/ux_host_class_prolific_write.c index ce43ca5e..183ae2b5 100644 --- a/common/usbx_host_classes/src/ux_host_class_prolific_write.c +++ b/common/usbx_host_classes/src/ux_host_class_prolific_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_prolific_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -75,6 +75,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_prolific_write(UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, @@ -130,7 +133,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_storage_activate.c b/common/usbx_host_classes/src/ux_host_class_storage_activate.c index 4a6be49b..db824dca 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,7 +61,7 @@ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_host_semaphore_create Create semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,6 +74,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support. */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND *command) @@ -109,13 +112,42 @@ UINT status; /* This instance of the device must also be stored in the interface container. */ interface -> ux_interface_class_instance = (VOID *) storage; +#if defined(UX_HOST_STANDALONE) + + /* Check class,sub class, protocol. */ + status = _ux_host_class_storage_device_support_check(storage); + if (status != UX_SUCCESS) + { + _ux_utility_memory_free(storage); + return(status); + } + + /* Search all the endpoints for the storage interface (Bulk Out, Bulk in, + and optional Interrupt endpoint). */ + status = _ux_host_class_storage_endpoints_get(storage); + if (status != UX_SUCCESS) + { + _ux_utility_memory_free(storage); + return(status); + } + + /* Activate storage class task function. */ + storage -> ux_host_class_storage_class -> ux_host_class_task_function = _ux_host_class_storage_tasks_run; + + /* Mark the storage as live now (media mounts in task). */ + storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* Keep storage locked before it's initialized. */ + storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_LOCK; +#else + /* Configure the USB storage device. */ status = _ux_host_class_storage_configure(storage); /* Create the semaphore to protect multiple threads from accessing the same storage instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&storage -> ux_host_class_storage_semaphore, "ux_host_class_storage_semaphore", 1); + status = _ux_host_semaphore_create(&storage -> ux_host_class_storage_semaphore, "ux_host_class_storage_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -149,6 +181,8 @@ UINT status; /* Mark the storage as live now. */ storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_LIVE; +#endif + /* If all is fine and the device is mounted, we may need to inform the application if a function has been programmed in the system structure. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) diff --git a/common/usbx_host_classes/src/ux_host_class_storage_check_run.c b/common/usbx_host_classes/src/ux_host_class_storage_check_run.c new file mode 100644 index 00000000..be6d5403 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_check_run.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_check_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs state machine to check and mount/unmount storage */ +/* media for current locked logic unit number (LUN). */ +/* */ +/* It's valid only in standalone mode. */ +/* It's non-blocking. */ +/* */ +/* Note it must be used in case following conditions are true: */ +/* - storage insstance is live */ +/* - storage is locked for specific LUN */ +/* - if check is not started yet the main storage state must be idle */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion State Status */ +/* UX_STATE_WAIT States started/in progress */ +/* UX_STATE_NEXT Check is done, next call will */ +/* start check again. */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler The error trap */ +/* _ux_system_tasks_run Run USB system tasks */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_check_run(UX_HOST_CLASS_STORAGE *storage) +{ + +#if defined UX_HOST_CLASS_STORAGE_STATE_CHECK_ENABLE +UX_INTERRUPT_SAVE_AREA + + /* Check states - storage must be live, locked and main state machine idle. */ + UX_DISABLE + if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE || + (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0 || + (storage -> ux_host_class_storage_op_state != UX_STATE_WAIT && + storage -> ux_host_class_storage_state_state != UX_STATE_IDLE)) + { + UX_RESTORE + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NOT_READY); + + /* The state is not ready for check operation. */ + storage -> ux_host_class_storage_status = UX_TRANSFER_NOT_READY; + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + return(UX_STATE_ERROR); + } + UX_RESTORE +#endif + + switch(storage -> ux_host_class_storage_op_state) + { + case UX_STATE_IDLE: + case UX_STATE_ERROR: + case UX_STATE_RESET: + + /* Setup states for immediate LUN check. */ + storage -> ux_host_class_storage_flags |= + UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT; + storage -> ux_host_class_storage_check_lun = + (UCHAR)storage -> ux_host_class_storage_lun; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + + /* Next : wait */ + storage -> ux_host_class_storage_op_state = UX_STATE_WAIT; + + /* Fall through. */ + case UX_STATE_WAIT: + + /* Run tasks, including transport task. */ + _ux_system_host_tasks_run(); + + /* In case state is not idle, check if it changes back. */ + if (storage -> ux_host_class_storage_state_state == UX_STATE_IDLE) + { + storage -> ux_host_class_storage_op_state = UX_STATE_IDLE; + return(UX_STATE_NEXT); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + /* Unexpected states. */ + default: + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + break; + } + + /* We should never be here. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c b/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c index d28c9504..83284f7f 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_deactivate PORTABLE C */ -/* 6.1.6 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_endpoint_transfer_abort Abort transfer request */ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -86,11 +86,16 @@ /* fixed compile issues with */ /* some macro options, */ /* resulting in version 6.1.6 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved media insert/eject */ +/* management without FX, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command) { +UINT status; UX_HOST_CLASS_STORAGE *storage; UX_HOST_CLASS_STORAGE_MEDIA *storage_media; UX_HOST_CLASS *class_inst; @@ -149,7 +154,7 @@ VOID *memory; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Inform UX_MEDIA (default FileX) of the deactivation of all Media attached to this instance. */ @@ -187,9 +192,13 @@ VOID *memory; #else /* Check if the media is for this storage. */ - if (storage_media -> ux_host_class_storage_media_storage == storage) + if (storage_media -> ux_host_class_storage_media_status == UX_USED && + storage_media -> ux_host_class_storage_media_storage == storage) { + /* Free the storage media. */ + storage_media -> ux_host_class_storage_media_status = UX_UNUSED; + /* Invoke callback for media removal. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) { @@ -198,9 +207,6 @@ VOID *memory; _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_REMOVAL, storage -> ux_host_class_storage_class, (VOID *) storage_media); } - - /* Free the storage media. */ - storage_media -> ux_host_class_storage_media_storage = UX_NULL; } #endif @@ -209,13 +215,14 @@ VOID *memory; } /* Protect thread reentry to this instance. */ - _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + UX_PARAMETER_NOT_USED(status); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage); /* Destroy the protection semaphore. */ - _ux_utility_semaphore_delete(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_delete(&storage -> ux_host_class_storage_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c b/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c index 799dfeea..13f8fbdc 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c @@ -30,12 +30,13 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_device_initialize PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +45,8 @@ /* */ /* This function initializes the USB storage device. */ /* */ +/* This function is for RTOS mode. */ +/* */ /* INPUT */ /* */ /* storage Pointer to storage class */ @@ -83,6 +86,10 @@ /* fixed logic of creating */ /* multiple storage media, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved media insert/eject */ +/* management without FX, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage) @@ -193,10 +200,11 @@ UINT inst_index; { /* Find an unused storage media slot. */ - if (storage_media -> ux_host_class_storage_media_storage == UX_NULL) + if (storage_media -> ux_host_class_storage_media_status != UX_USED) { /* Use this free storage media slot. */ + storage_media -> ux_host_class_storage_media_status = UX_USED; storage_media -> ux_host_class_storage_media_storage = storage; /* Save media information. */ @@ -213,6 +221,7 @@ UINT inst_index; storage -> ux_host_class_storage_class, (VOID *) storage_media); } + /* Media inserted in slot, done. */ break; } } @@ -223,4 +232,4 @@ UINT inst_index; return success. The storage thread will try to remount the ones that failed. */ return(UX_SUCCESS); } - +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c b/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c index 678016f8..fd3c406a 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_device_reset PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_device_reset(UX_HOST_CLASS_STORAGE *storage) @@ -90,7 +93,7 @@ UINT status; transfer_request = &control_endpoint -> ux_endpoint_transfer_request; /* We need to prevent other threads from simultaneously using the endpoint. */ - _ux_utility_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Create a transfer_request for the RESET request. */ transfer_request -> ux_transfer_request_data_pointer = UX_NULL; diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c b/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c index e27aef72..ab6639d2 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** Storage Class */ /** */ @@ -30,45 +30,51 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_storage_device_support_check PORTABLE C */ -/* 6.1 */ +#if defined(UX_HOST_STANDALONE) && defined(UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT) +#error Only Mass Storage BulkOnly (BO) is supported in standalone mode right now. +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_device_support_check PORTABLE C */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ -/* This function verifies the support for the subclass and protocol */ -/* of the USB device. If the device is supported it will update the */ -/* storage class instances with the transport layer functions. */ -/* */ -/* INPUT */ -/* */ -/* storage Pointer to storage class */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* Storage Class */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* This function verifies the support for the subclass and protocol */ +/* of the USB device. If the device is supported it will update the */ +/* storage class instances with the transport layer functions. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage) @@ -80,26 +86,34 @@ UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage case UX_HOST_CLASS_STORAGE_PROTOCOL_BO: +#if !defined(UX_HOST_STANDALONE) storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_bo; +#endif break; #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT case UX_HOST_CLASS_STORAGE_PROTOCOL_CB: +#if !defined(UX_HOST_STANDALONE) storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cb; +#endif break; case UX_HOST_CLASS_STORAGE_PROTOCOL_CBI: +#if !defined(UX_HOST_STANDALONE) + /* In case of CBI, the subclass must be UFI, if not, default back to CB transport. */ if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cbi; else storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cb; +#endif break; + #endif - + default: /* Error trap. */ @@ -124,7 +138,7 @@ UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage case UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8070: return(UX_SUCCESS); - + default: /* Error trap. */ @@ -132,8 +146,7 @@ UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_PROTOCOL_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) - + return(UX_HOST_CLASS_PROTOCOL_ERROR); } } - diff --git a/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c index 5db29171..8c2dd17f 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c @@ -30,13 +30,13 @@ #include "ux_host_stack.h" -#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) +#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) && !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_driver_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -45,7 +45,10 @@ /* */ /* This function is the entry point for the FileX file system. All */ /* FileX driver I/O calls are are multiplexed here and rerouted to */ -/* the proper USB storage class functions. */ +/* the proper USB storage class functions. */ +/* */ +/* This entry is for FX support, it's not available if FX media is not */ +/* integrated or standalone mode is used. */ /* */ /* INPUT */ /* */ @@ -61,8 +64,8 @@ /* Translate error status codes */ /* _ux_host_class_storage_media_read Read sector(s) */ /* _ux_host_class_storage_media_write Write sector(s) */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +80,8 @@ /* added option to disable FX */ /* media integration, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_storage_driver_entry(FX_MEDIA *media) @@ -104,7 +109,7 @@ UX_HOST_CLASS_STORAGE_MEDIA *storage_media; } /* Protect Thread reentry to this instance. */ - _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); /* Restore the LUN number from the media instance. */ storage -> ux_host_class_storage_lun = storage_media -> ux_host_class_storage_media_lun; @@ -215,6 +220,6 @@ UX_HOST_CLASS_STORAGE_MEDIA *storage_media; } /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_put(&storage -> ux_host_class_storage_semaphore); } #endif /* !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) */ diff --git a/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c index d0a45482..fe487614 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_endpoints_get PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* initial the timeout value, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_endpoints_get(UX_HOST_CLASS_STORAGE *storage) @@ -154,6 +157,14 @@ UX_ENDPOINT *endpoint; return(UX_ENDPOINT_HANDLE_UNKNOWN); } + /* Set default transfer timeout value. */ + endpoint = storage -> ux_host_class_storage_bulk_in_endpoint; + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_MS_TO_TICK_NON_ZERO(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT); + endpoint = storage -> ux_host_class_storage_bulk_out_endpoint; + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = + UX_MS_TO_TICK_NON_ZERO(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT); + #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT /* Search the Interrupt IN endpoint. This endpoint is optional and only valid for storage devices that use the CBI protocol. */ diff --git a/common/usbx_host_classes/src/ux_host_class_storage_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_entry.c index d8e1c090..68c68a45 100755 --- a/common/usbx_host_classes/src/ux_host_class_storage_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_entry.c @@ -36,7 +36,7 @@ UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS_STORAG /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_entry PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -88,6 +88,9 @@ UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS_STORAG /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed class ext access, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command) @@ -95,7 +98,9 @@ UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command) UINT status; UX_HOST_CLASS *class_inst; +#if !defined(UX_HOST_STANDALONE) UX_HOST_CLASS_STORAGE_EXT *class_ext; +#endif /* The command request will tell us we need to do here, either a enumeration @@ -122,6 +127,8 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; /* Get class. */ class_inst = command -> ux_host_class_command_class_ptr; +#if !defined(UX_HOST_STANDALONE) + /* Allocate UX_HOST_CLASS_STORAGE_EXT. */ if (class_inst -> ux_host_class_ext == UX_NULL) { @@ -136,7 +143,7 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; return(UX_MEMORY_INSUFFICIENT); /* Create the storage class thread. */ - status = _ux_utility_thread_create(&class_ext -> ux_host_class_thread, + status = _ux_host_thread_create(&class_ext -> ux_host_class_thread, "ux_host_storage_thread", _ux_host_class_storage_thread_entry, (ULONG) (ALIGN_TYPE) class_inst, @@ -166,6 +173,7 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; /* Get storage class extension. */ class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext; } +#endif /* Allocate some memory for the media structures used by UX_MEDIA (default FileX). */ if (class_inst -> ux_host_class_media == UX_NULL) @@ -184,7 +192,7 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; } /* Now that the extension pointer has been set, resume the thread. */ - tx_thread_resume(&class_ext -> ux_host_class_thread); + _ux_host_thread_resume(&class_ext -> ux_host_class_thread); /* The activate command is used when the device inserted has found a parent and is ready to complete the enumeration. */ @@ -193,6 +201,9 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; /* Return the completion status. */ return(status); + case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT: + return(UX_STATE_NEXT); + case UX_HOST_CLASS_COMMAND_DEACTIVATE: /* The deactivate command is used when the device has been extracted either @@ -216,6 +227,8 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; class_inst -> ux_host_class_media = UX_NULL; } +#if !defined(UX_HOST_STANDALONE) + /* Free class extension resources. */ if (class_inst -> ux_host_class_ext) { @@ -224,7 +237,7 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext; /* Delete storage thread. */ - _ux_utility_thread_delete(&class_ext -> ux_host_class_thread); + _ux_host_thread_delete(&class_ext -> ux_host_class_thread); /* Free class extension memory. */ _ux_utility_memory_free(class_ext); @@ -232,6 +245,7 @@ UX_HOST_CLASS_STORAGE_EXT *class_ext; /* Set extension pointer to NULL. */ class_inst -> ux_host_class_ext = UX_NULL; } +#endif /* Return success. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_storage_lock.c b/common/usbx_host_classes/src/ux_host_class_storage_lock.c new file mode 100644 index 00000000..25ffd3c1 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_lock.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_lock PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function locks storage for further operations. */ +/* */ +/* It's valid only in standalone mode. */ +/* It's non-blocking if wait is zero, otherwise it blocks. */ +/* */ +/* INPUT */ +/* */ +/* storage_media Pointer to storage to operate */ +/* wait Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* UX_TIMEOUT Time out */ +/* UX_REENTRY Reentry in storage task */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_lock(UX_HOST_CLASS_STORAGE *storage, ULONG wait) +{ +UX_INTERRUPT_SAVE_AREA +ULONG t0, t1; + + t0 = _ux_utility_time_get(); + while(1) + { + UX_DISABLE + + /* Check instance lock. */ + if (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) + { + + /* Check once, just return busy. */ + if (wait == 0) + { + UX_RESTORE + return(UX_TIMEOUT); + } + + /* Check timeout. */ + if (wait != UX_WAIT_FOREVER) + { + t1 = _ux_utility_time_get(); + t1 = _ux_utility_time_elapsed(t0, t1); + if (t1 >= wait) + { + UX_RESTORE + return(UX_TIMEOUT); + } + } + } + else + { + /* It's free, time to lock it. */ + break; + } + + /* Check task reentry. */ + if (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_PROTECT) + { + UX_RESTORE + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_REENTRY); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_REENTRY, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_REENTRY); + } + UX_RESTORE + + /* Run stack tasks. */ + _ux_system_host_tasks_run(); + } + + /* Lock storage. */ + storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_LOCK; + + /* Stop main state machine. */ + storage -> ux_host_class_storage_state_state = UX_STATE_IDLE; + + /* Reset operation state machine. */ + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + + UX_RESTORE + return(UX_SUCCESS); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c b/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c index 5522d065..cf75a2c9 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_max_lun_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,7 +57,7 @@ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -70,6 +70,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_max_lun_get(UX_HOST_CLASS_STORAGE *storage) @@ -96,7 +99,9 @@ UCHAR *storage_data_buffer; transfer_request = &control_endpoint -> ux_endpoint_transfer_request; /* We need to prevent other threads from simultaneously using the control endpoint. */ - _ux_utility_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); /* Need to allocate memory for the descriptor. */ storage_data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 1); @@ -111,6 +116,14 @@ UCHAR *storage_data_buffer; transfer_request -> ux_transfer_request_value = 0; transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber; +#if defined(UX_HOST_STANDALONE) + storage -> ux_host_class_storage_memory = storage_data_buffer; + storage -> ux_host_class_storage_trans = transfer_request; + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSFER; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE; + UX_TRANSFER_STATE_RESET(transfer_request); +#else + /* Send request to HCD layer. */ status = _ux_host_stack_transfer_request(transfer_request); @@ -138,9 +151,17 @@ UCHAR *storage_data_buffer; /* Free all used resources. */ _ux_utility_memory_free(storage_data_buffer); +#endif #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT } +#if defined(UX_HOST_STANDALONE) + else + { + storage -> ux_host_class_storage_trans = UX_NULL; + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE; + } +#endif #endif /* We always succeed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c index e575d998..c02b18c4 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_capacity_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,9 @@ /* added option to disable FX */ /* media integration, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_capacity_get(UX_HOST_CLASS_STORAGE *storage) @@ -85,11 +88,15 @@ UINT status; UCHAR *cbw; UCHAR *capacity_response; UINT command_length; +#if !defined(UX_HOST_STANDALONE) ULONG command_retry; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_CAPACITY_GET, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) +#if !defined(UX_HOST_STANDALONE) + /* Set the default to either 512 or 2048 bytes. */ switch (storage -> ux_host_class_storage_media_type) { @@ -121,6 +128,7 @@ ULONG command_retry; status = _ux_host_class_storage_media_format_capacity_get(storage); if (status != UX_SUCCESS) return(status); +#endif /* Use a pointer for the cbw, easier to manipulate. */ cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; @@ -146,6 +154,17 @@ ULONG command_retry; if (capacity_response == UX_NULL) return(UX_MEMORY_INSUFFICIENT); +#if defined(UX_HOST_STANDALONE) + + /* Initialize state for transport. */ + UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage); + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSPORT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE; + storage -> ux_host_class_storage_trans_data = capacity_response; + status = UX_SUCCESS; + return(status); +#else + /* Send the command to transport layer. */ status = _ux_host_class_storage_transport(storage, capacity_response); @@ -186,4 +205,5 @@ ULONG command_retry; /* We get here when we could not retrieve the sector size through the READ_CAPACITY command. It's OK, we still calculated the default based on the device type. */ return(UX_SUCCESS); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c index 36c8794f..5177ffb0 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_characteristics_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_characteristics_get(UX_HOST_CLASS_STORAGE *storage) @@ -109,7 +112,16 @@ UINT command_length; inquiry_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH); if (inquiry_response == UX_NULL) return(UX_MEMORY_INSUFFICIENT); - + +#if defined(UX_HOST_STANDALONE) + UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage); + storage -> ux_host_class_storage_memory = inquiry_response; + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSPORT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_INQUIRY_SAVE; + storage -> ux_host_class_storage_trans_data = inquiry_response; + status = UX_SUCCESS; + return(status); +#else /* Send the command to transport layer. */ status = _ux_host_class_storage_transport(storage, inquiry_response); @@ -132,5 +144,6 @@ UINT command_length; /* Return completion status. */ return(status); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_check.c b/common/usbx_host_classes/src/ux_host_class_storage_media_check.c new file mode 100644 index 00000000..8763a5ae --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_check.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_check PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs state machine to check and mount/unmount storage */ +/* media for current selected logic unit number (LUN). */ +/* */ +/* It's valid only in standalone mode. */ +/* It's blocking. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* sector_start Starting sector */ +/* sector_count Number of sectors to read */ +/* data_pointer Pointer to data to read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_check_run Runs check state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_check(UX_HOST_CLASS_STORAGE *storage) +{ +UINT status; + do { + status = _ux_host_class_storage_check_run(storage); + } while(status == UX_STATE_WAIT); + return(storage -> ux_host_class_storage_status); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c index 4f1e005e..089cc559 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_format_capacity_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_format_capacity_get(UX_HOST_CLASS_STORAGE *storage) @@ -111,7 +114,18 @@ UINT command_length; read_format_capacity_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH); if (read_format_capacity_response == UX_NULL) return(UX_MEMORY_INSUFFICIENT); - + +#if defined(UX_HOST_STANDALONE) + + /* Initialize main states for GetFormatCapacity(). */ + UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage); + storage -> ux_host_class_storage_memory = read_format_capacity_response; + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSPORT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_SAVE; + storage -> ux_host_class_storage_trans_data = read_format_capacity_response; + return(UX_SUCCESS); +#else + /* Send the command to transport layer. */ _ux_host_class_storage_transport(storage, read_format_capacity_response); @@ -120,5 +134,6 @@ UINT command_length; /* If we have a transport error, there is not much we can do, we do not fail. */ return(UX_SUCCESS); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_get.c index 0e35ebc6..57cbaad3 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_get.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_get.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_get PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -48,7 +48,7 @@ /* INPUT */ /* */ /* storage Pointer to storage class */ -/* media_index Finding media index */ +/* media_lun Media logical unit No. (LUN) */ /* storage_media Holds returned storage media */ /* pointer */ /* */ @@ -71,10 +71,13 @@ /* 08-02-2021 Wen Wang Modified comment(s), */ /* fixed spelling error, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined media to search, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, - ULONG media_index, + ULONG media_lun, UX_HOST_CLASS_STORAGE_MEDIA **storage_media) { #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) @@ -86,9 +89,13 @@ UINT _ux_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, UX_HOST_CLASS_STORAGE_MEDIA *storage_medias; UX_HOST_CLASS *class_inst; -UINT scan_index, found_index; +UINT scan_index; + /* If storage is not live, media is not ready. */ + if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE) + return(UX_ERROR); + /* Get storage class instance. */ class_inst = storage -> ux_host_class_storage_class; @@ -96,26 +103,26 @@ UINT scan_index, found_index; storage_medias = (UX_HOST_CLASS_STORAGE_MEDIA *)class_inst -> ux_host_class_media; /* Search media to find the right one. */ - for(scan_index = 0, found_index = 0; - scan_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; - scan_index ++) + for(scan_index = 0; scan_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; scan_index ++) { + /* Skip storage media not used. */ + if (storage_medias[scan_index].ux_host_class_storage_media_status != UX_USED) + continue; + /* Skip storage media not belong to the storage. */ if (storage_medias[scan_index].ux_host_class_storage_media_storage != storage) continue; - /* Check expected index. */ - if (found_index == media_index) - { + /* Skip storage media with different LUN. */ + if (storage_medias[scan_index].ux_host_class_storage_media_lun != media_lun) + continue; + + /* Store the media instance. */ *storage_media = &storage_medias[scan_index]; return(UX_SUCCESS); } - /* Find next related media. */ - found_index ++; - } - /* Media not found. */ return(UX_ERROR); #endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_lock.c b/common/usbx_host_classes/src/ux_host_class_storage_media_lock.c index afba0ff8..e41e87d2 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_lock.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_lock.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_lock PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_lock(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG wait) @@ -83,9 +86,11 @@ UINT status; /* Get storage instance. */ storage = storage_media -> ux_host_class_storage_media_storage; + if (storage == UX_NULL) + return(UX_ERROR); /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, wait); + status = _ux_host_class_storage_lock(storage, wait); if (status != UX_SUCCESS) return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_read.c b/common/usbx_host_classes/src/ux_host_class_storage_media_read.c index dbc8330b..cdfd0660 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_read.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_read.c @@ -30,12 +30,59 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) +VOID _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count); + +VOID +#else +static inline VOID +#endif +_ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count) +{ +UCHAR *cbw; +UCHAR *cbw_cb; +ULONG command_length; + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *)storage -> ux_host_class_storage_cbw; + cbw_cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; + + /* Get the Read Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == + UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, + UX_HOST_CLASS_STORAGE_DATA_IN, + sector_count * storage -> ux_host_class_storage_sector_size, + command_length); + + /* Prepare the MEDIA READ command block. */ + *(cbw_cb + UX_HOST_CLASS_STORAGE_READ_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_READ16; + + /* Store the sector start (LBA field). */ + _ux_utility_long_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_READ_LBA, sector_start); + + /* Store the number of sectors to read. */ + _ux_utility_short_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH, (USHORT) sector_count); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,15 +120,23 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, ULONG sector_count, UCHAR *data_pointer) { - +#if defined(UX_HOST_STANDALONE) +UINT status; + do { + status = _ux_host_class_storage_read_write_run(storage, UX_TRUE, + sector_start, sector_count, data_pointer); + } while(status == UX_STATE_WAIT); + return(storage -> ux_host_class_storage_status); +#else UINT status; -UCHAR *cbw; -UINT command_length; UINT media_retry; /* If trace is enabled, insert this event into the trace buffer. */ @@ -94,30 +149,8 @@ UINT media_retry; while (media_retry-- != 0) { - /* Use a pointer for the cbw, easier to manipulate. */ - cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; - - /* Get the Read Command Length. */ -#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT - if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) - command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI; - else - command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; -#else - command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; -#endif - - /* Initialize the CBW for this command. */ - _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, sector_count * storage -> ux_host_class_storage_sector_size, command_length); - - /* Prepare the MEDIA READ command block. */ - *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_READ16; - - /* Store the sector start (LBA field). */ - _ux_utility_long_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_LBA, sector_start); - - /* Store the number of sectors to read. */ - _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH, (USHORT) sector_count); + /* Initialize CBW. */ + _ux_host_class_storage_read_initialize(storage, sector_start, sector_count); /* Send the command to transport layer. */ status = _ux_host_class_storage_transport(storage, data_pointer); @@ -153,5 +186,5 @@ UINT media_retry; /* Check if the media in the device has been removed. If so we have to tell UX_MEDIA (default FileX) that the media is closed. */ return(UX_HOST_CLASS_STORAGE_SENSE_ERROR); +#endif } - diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_write.c b/common/usbx_host_classes/src/ux_host_class_storage_media_write.c index 38e74eee..d21d731d 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_write.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_write.c @@ -30,12 +30,58 @@ #include "ux_host_stack.h" +#if defined(UX_HOST_STANDALONE) +VOID _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count); + +VOID +#else +static inline VOID +#endif +_ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count) +{ +UCHAR *cbw; +UCHAR *cbw_cb; +ULONG command_length; + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *)storage -> ux_host_class_storage_cbw; + cbw_cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == + UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_OUT, + sector_count * storage -> ux_host_class_storage_sector_size, + command_length); + + /* Prepare the MEDIA WRITE command block. */ + *(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_WRITE16; + + /* Store the sector start (LBA field). */ + _ux_utility_long_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_LBA, sector_start); + + /* Store the number of sectors to write. */ + _ux_utility_short_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH, (USHORT) sector_count); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -73,45 +119,30 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, ULONG sector_count, UCHAR *data_pointer) { - +#if defined(UX_HOST_STANDALONE) +UINT status; + do { + status = _ux_host_class_storage_read_write_run(storage, UX_FALSE, + sector_start, sector_count, data_pointer); + } while(status == UX_STATE_WAIT); + return(storage -> ux_host_class_storage_status); +#else UINT status; -UCHAR *cbw; UINT media_retry; -UINT command_length; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_WRITE, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) - /* Use a pointer for the cbw, easier to manipulate. */ - cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; - - /* Get the Write Command Length. */ -#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT - if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) - command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI; - else - command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; -#else - command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; -#endif - - /* Initialize the CBW for this command. */ - _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_OUT, sector_count * storage -> ux_host_class_storage_sector_size, - command_length); - - /* Prepare the MEDIA WRITE command block. */ - *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_WRITE16; - - /* Store the sector start (LBA field). */ - _ux_utility_long_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_LBA, sector_start); - - /* Store the number of sectors to write. */ - _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH, (USHORT) sector_count); + /* Initialize CBW. */ + _ux_host_class_storage_write_initialize(storage, sector_start, sector_count); /* Reset the retry count. */ media_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; @@ -132,5 +163,6 @@ UINT command_length; /* Return sense error. */ return(UX_HOST_CLASS_STORAGE_SENSE_ERROR); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_read_write_run.c b/common/usbx_host_classes/src/ux_host_class_storage_read_write_run.c new file mode 100644 index 00000000..ac7c5e86 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_read_write_run.c @@ -0,0 +1,173 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + +#if defined(UX_HOST_STANDALONE) + +extern VOID _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count); + +extern VOID _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage, + ULONG sector_start, ULONG sector_count); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_read_write_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function runs state machine to read or write one or more */ +/* logical sector on a selected media of a storage function. */ +/* */ +/* It's valid only in standalone mode. */ +/* */ +/* Note it must be used in case following conditions are true: */ +/* - storage insstance is live */ +/* - storage is locked for specific LUN */ +/* - the main storage state must be idle */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* read_write Set to UX_TRUE to read */ +/* sector_start Starting sector */ +/* sector_count Number of sectors to read */ +/* data_pointer Pointer to data to read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* UX_STATE_WAIT States started/in progress */ +/* UX_STATE_NEXT Read/write is done, next call */ +/* starts read/write again. */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_read_initialize */ +/* Initialize the CBW */ +/* _ux_host_class_storage_write_initialize */ +/* Initialize the CBW */ +/* _ux_system_error_handler The error trap */ +/* _ux_system_tasks_run Run USB system tasks */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE *storage, + ULONG read_write, + ULONG sector_start, ULONG sector_count, UCHAR *data_pointer) +{ + +#if defined UX_HOST_CLASS_STORAGE_STATE_CHECK_ENABLE +UX_INTERRUPT_SAVE_AREA + + /* Check states - storage must be live, locked and main state machine idle. */ + UX_DISABLE + if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE || + (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0 || + storage -> ux_host_class_storage_state_state != UX_STATE_IDLE) + { + UX_RESTORE + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NOT_READY); + + /* The state is not ready for read. */ + storage -> ux_host_class_storage_status = UX_TRANSFER_NOT_READY; + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + return(UX_STATE_ERROR); + } + UX_RESTORE +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_READ, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + switch(storage -> ux_host_class_storage_op_state) + { + case UX_STATE_IDLE: /* Fall through. */ + case UX_STATE_ERROR: /* Fall through. */ + case UX_STATE_RESET: + + /* Initialize CBW. */ + if (read_write) + _ux_host_class_storage_read_initialize(storage, sector_start, sector_count); + else + _ux_host_class_storage_write_initialize(storage, sector_start, sector_count); + + /* Initialize for transport. */ + UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage); + storage -> ux_host_class_storage_trans_data = data_pointer; + + /* Next : wait */ + storage -> ux_host_class_storage_op_state = UX_STATE_WAIT; + + /* Fall through. */ + case UX_STATE_WAIT: + + /* Run tasks, including transport task. */ + _ux_system_host_tasks_run(); + + /* Fatal error. */ + if (storage -> ux_host_class_storage_op_state < UX_STATE_IDLE) + return(UX_STATE_EXIT); + + /* It's done with/without error. */ + if (storage -> ux_host_class_storage_op_state <= UX_STATE_NEXT) + return(UX_STATE_NEXT); + + /* Wait. */ + return(UX_STATE_WAIT); + + /* Unexpected states. */ + default: + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + break; + } + + /* Return fatal exit state status. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c b/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c index d2e220a8..09efbd95 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_request_sense PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,16 +75,21 @@ /* verified memset and memcpy */ /* cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_request_sense(UX_HOST_CLASS_STORAGE *storage) { +UCHAR *cbw; +UCHAR *request_sense_response; +UINT command_length; +#if !defined(UX_HOST_STANDALONE) UINT status; -UCHAR *cbw; -UCHAR *request_sense_response; ULONG sense_code; -UINT command_length; +#endif /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_REQUEST_SENSE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) @@ -126,7 +131,19 @@ UINT command_length; request_sense_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); if (request_sense_response == UX_NULL) return(UX_MEMORY_INSUFFICIENT); - + +#if defined(UX_HOST_STANDALONE) + + /* Prepare data buffer for request sense. */ + storage -> ux_host_class_storage_trans_data_bak = storage -> ux_host_class_storage_trans_data; + storage -> ux_host_class_storage_trans_data = request_sense_response; + + /* Perform CBW-DATA-CSW transport. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CBW; + + return(UX_SUCCESS); +#else + /* Send the command to transport layer. */ status = _ux_host_class_storage_transport(storage, request_sense_response); @@ -136,9 +153,13 @@ UINT command_length; /* We have a successful transaction, even though the sense code could reflect an error. The sense code will be assembled and store in the device instance. */ - sense_code = (((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY)) & 0x0f) << 16; - sense_code |= ((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE)) << 8; - sense_code |= (ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER); + sense_code = UX_HOST_CLASS_STORAGE_SENSE_STATUS( + (ULONG) *(request_sense_response + + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY), + (ULONG) *(request_sense_response + + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE), + (ULONG) *(request_sense_response + + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER)); /* Store the sense code in the storage instance. */ storage -> ux_host_class_storage_sense_code = sense_code; @@ -152,5 +173,6 @@ UINT command_length; /* Return completion code. */ return(status); +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_tasks_run.c b/common/usbx_host_classes/src/ux_host_class_storage_tasks_run.c new file mode 100644 index 00000000..7a6d021c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_tasks_run.c @@ -0,0 +1,805 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) + + +static inline VOID _ux_host_class_storage_inst_tasks_run(UX_HOST_CLASS_STORAGE *storage); + +static inline UINT _ux_host_class_storage_lun_is_removable(UX_HOST_CLASS_STORAGE *storage); +static inline UINT _ux_host_class_storage_lun_type_is_known(UX_HOST_CLASS_STORAGE *storage); + +static inline VOID _ux_host_class_storage_max_lun_save(UX_HOST_CLASS_STORAGE *storage); +static inline UINT _ux_host_class_storage_inquiry_save(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_format_cap_save(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_capacity_save(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_unit_ready_check(UX_HOST_CLASS_STORAGE *storage); + +static inline VOID _ux_host_class_storage_lun_media_insert(UX_HOST_CLASS_STORAGE *storage); + +static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_STORAGE *storage); + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_tasks_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is awaken every 2 seconds to check if there was a */ +/* device insertion on a specific media. This is the only way we can */ +/* remount a media after the storage instance has opened the media to */ +/* UX_MEDIA (default FileX) and the media is either not present */ +/* or was removed and is being re-inserted. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_device_reset Reset device */ +/* _ux_host_class_storage_media_mount Mount the media */ +/* _ux_host_class_storage_unit_ready_test */ +/* Test for unit ready */ +/* _ux_host_class_storage_media_characteristics_get */ +/* Get media characteristics */ +/* _ux_host_class_storage_media_format_capacity_get */ +/* Get media format capacity */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_tasks_run(UX_HOST_CLASS *storage_class) +{ +UX_HOST_CLASS_STORAGE *storage; + + /* Validate class entry. */ + if (storage_class -> ux_host_class_status != UX_USED || + storage_class -> ux_host_class_entry_function != _ux_host_class_storage_entry) + return(UX_STATE_IDLE); + + /* Run for class instances. */ + storage = (UX_HOST_CLASS_STORAGE *)storage_class -> ux_host_class_first_instance; + while(storage) + { + + /* Run tasks for each storage instance. */ + storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_PROTECT; + _ux_host_class_storage_inst_tasks_run(storage); + storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_PROTECT; + storage = storage -> ux_host_class_storage_next_instance; + } + return(UX_STATE_WAIT); +} + +static inline VOID _ux_host_class_storage_inst_tasks_run(UX_HOST_CLASS_STORAGE *storage) +{ +UX_INTERRUPT_SAVE_AREA +UCHAR state; +ULONG tick_now, tick_elapsed; +UINT status; +UX_TRANSFER *trans; +UX_INTERFACE *interface; + + /* If storage not live, start initialize. */ + if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_MOUNTING) + { + if (storage -> ux_host_class_storage_state_state == UX_STATE_RESET) + { + + /* Start initialize sequence Delay() - GetMaxLUN() - Inquiry() - GetFormatCapacity(). */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET; + storage -> ux_host_class_storage_delay_start = _ux_utility_time_get(); + storage -> ux_host_class_storage_delay_ms = + UX_MS_TO_TICK_NON_ZERO(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY); + return; + } + + /* OK to process states. */ + } + else if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* No need to process states. */ + storage -> ux_host_class_storage_state_state = UX_STATE_RESET; + return; + } + + /* Handle read/write states. */ + if ((storage -> ux_host_class_storage_op_state == UX_STATE_WAIT) && + (storage -> ux_host_class_storage_flags & + UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT) == 0) + { + + /* Run transport. */ + status = _ux_host_class_storage_transport_run(storage); + + /* Fatal error. */ + if (status < UX_STATE_IDLE) + { + storage -> ux_host_class_storage_op_state = UX_STATE_RESET; + return; + } + + /* Done with/without error. */ + if (status <= UX_STATE_NEXT) + { + storage -> ux_host_class_storage_op_state = UX_STATE_IDLE; + return; + } + + /* Keep waiting. */ + /* Main states are frozen in this case. */ + return; + } + + /* Handle main states. */ + while(1) + { + + /* Get current state. */ + /* Initial check: delay()-GetMaxLUN()-Inquiry()-GetFormatCap() + process break on any error. */ + /* Regular check: delay()-TestReady()-Inquiry()-GetFormatCap() + process break on any error. */ + state = storage -> ux_host_class_storage_state_state; + switch(state) + { + case UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET: + + /* Issue GetMaxLun(). */ + status = _ux_host_class_storage_max_lun_get(storage); + if (UX_SUCCESS != status) + { + + /* This fails storage activation. */ + interface = storage -> ux_host_class_storage_interface; + _ux_host_stack_class_instance_destroy( + storage -> ux_host_class_storage_class, (VOID *) storage); + interface -> ux_interface_class_instance = (VOID *) UX_NULL; + _ux_utility_memory_free(storage); + return; + } + + /* Roll back to next state. */ + /* By default TRANSFER -> MAX_LUN_SAVE -> TEST_READY. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE: + _ux_host_class_storage_max_lun_save(storage); + + /* Continue to start LUN 0 check from TEST_READY any way. */ + storage -> ux_host_class_storage_check_lun = 0; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + + /* Fall through. */ + case UX_HOST_CLASS_STORAGE_STATE_TEST_READY: + + /* Save the LUN for the follwing sequence to use. */ + storage -> ux_host_class_storage_lun = + storage -> ux_host_class_storage_check_lun; + + /* If storage is not live, skip to do INQUIRY. */ + if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_INQUIRY; + continue; + } + + /* If LUN is not removable nor known, skip it to check next LUN. */ + if (!_ux_host_class_storage_lun_is_removable(storage) || + !_ux_host_class_storage_lun_type_is_known(storage)) + { + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; + continue; + } + + /* Prepare TestUnitReady(). */ + _ux_host_class_storage_unit_ready_test(storage); + + /* Roll back to next - TRANSPORT - TEST_CHECK. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_TEST_CHECK: + _ux_host_class_storage_unit_ready_check(storage); + + /* Roll back to next - possible NEXT_LUN/INQUIRY/TEST_READY. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_INQUIRY: + status = _ux_host_class_storage_media_characteristics_get(storage); + if (status != UX_SUCCESS) + { + + /* There is error, break the regular check round. */ + storage -> ux_host_class_storage_status = status; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE; + } + + /* Roll back to normal next - TRANSPORT - INQUIRY_SAVE. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_INQUIRY_SAVE: + status = _ux_host_class_storage_inquiry_save(storage); + if (status != UX_SUCCESS) + { + + /* Check next LUN. */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; + continue; + } + + /* Next : GetFormatCapacity(). */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET; + + /* Fall through. */ + case UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET: + status = _ux_host_class_storage_media_format_capacity_get(storage); + if (status != UX_SUCCESS) + { + + /* This error breaks regular check round. */ + storage -> ux_host_class_storage_status = status; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE; + } + + /* Roll back to normal next - TRANSPORT - FORMAT_CAP_SAVE. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_SAVE: + _ux_host_class_storage_format_cap_save(storage); + + /* Next : GetCapacity() */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_CAP_GET; + + /* Fall through. */ + case UX_HOST_CLASS_STORAGE_STATE_CAP_GET: + status = _ux_host_class_storage_media_capacity_get(storage); + if (status != UX_SUCCESS) + { + + /* This error breaks the regular check round. */ + storage -> ux_host_class_storage_status = status; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE; + } + + /* Roll back to normal next - TRANSPORT - CAP_SAVE. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE: + _ux_host_class_storage_capacity_save(storage); + + /* Final step for a single LUN check, going to next LUN. */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; + continue; + + case UX_HOST_CLASS_STORAGE_STATE_CHECK_START: + + /* Get lock and start check sequence: ready - inquiry - formatCap - cap. */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + + /* Fall through. */ + case UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT: + UX_DISABLE + if (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) + { + + /* Locked, keep state to wait. */ + UX_RESTORE + return; + } + + /* I'm locking it. */ + storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_LOCK; + UX_RESTORE + + /* Next state. */ + storage -> ux_host_class_storage_state_state = + storage -> ux_host_class_storage_state_next; + continue; + + case UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN: + + /* If it's immediate check for current LUN, we are done. */ + if (storage -> ux_host_class_storage_flags & + UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT) + { + + /* Go back to idle state. */ + storage -> ux_host_class_storage_flags &= + ~UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT; + storage -> ux_host_class_storage_state_state = UX_STATE_IDLE; + continue; + } + + if (storage -> ux_host_class_storage_check_lun < + storage -> ux_host_class_storage_max_lun) + { + + /* Check next LUN. */ + storage -> ux_host_class_storage_check_lun ++; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + } + else + { + + /* All LUN check is done. */ + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE; + } + + /* Roll back to next state. */ + continue; + + case UX_HOST_CLASS_STORAGE_STATE_TRANSPORT: + status = _ux_host_class_storage_transport_run(storage); + + /* Errors. */ + if (status < UX_STATE_NEXT) + { + + /* Normal flow is broken, if there is data buffer, free it. */ + if (storage -> ux_host_class_storage_trans_data) + _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data); + + /* No further operations, reset state machine. */ + storage -> ux_host_class_storage_state_state = UX_STATE_RESET; + storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK; + return; + } + + /* Next. */ + if (status == UX_STATE_NEXT) + { + + /* If there is sense handled, rollback to next state. */ + if (_ux_host_class_storage_transport_sense_check(storage)) + { + + /* Normal flow is broken, if there is data buffer, free it. */ + if (storage -> ux_host_class_storage_trans_data) + _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data); + continue; + } + + storage -> ux_host_class_storage_state_state = + storage -> ux_host_class_storage_state_next; + continue; + } + + /* Wait, state no change. */ + return; + + case UX_HOST_CLASS_STORAGE_STATE_TRANSFER: + trans = storage -> ux_host_class_storage_trans; + status = _ux_host_stack_transfer_run(trans); + + /* Keep waiting if not done. */ + if (status > UX_STATE_NEXT) + return; + + /* Check status in next state. */ + storage -> ux_host_class_storage_state_state = + storage -> ux_host_class_storage_state_next; + continue; + + case UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE: + + /* If it's mounting, do immediate ready check again. */ + if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_MOUNTING) + { + storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_LIVE; + storage -> ux_host_class_storage_check_lun = 0; + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + continue; + } + + /* Release the storage. */ + storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK; + + /* Main state idle. */ + storage -> ux_host_class_storage_state_state = UX_STATE_IDLE; + continue; + + case UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT: + tick_now = _ux_utility_time_get(); + tick_elapsed = _ux_utility_time_elapsed( + storage -> ux_host_class_storage_delay_start, tick_now); + + /* If no timeout, state no change, keep waiting. */ + if (tick_elapsed < storage -> ux_host_class_storage_delay_ms) + return; + + /* Roll back to do next state. */ + storage -> ux_host_class_storage_state_state = + storage -> ux_host_class_storage_state_next; + continue; + + case UX_STATE_IDLE: + + /* If it's not locked, start delay for checking. */ + UX_DISABLE + if ((storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0) + { + + /* Just keep regular checking from LUN 0. */ + storage -> ux_host_class_storage_check_lun = 0; + storage -> ux_host_class_storage_delay_start = _ux_utility_time_get(); + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT; + storage -> ux_host_class_storage_state_next = + UX_HOST_CLASS_STORAGE_STATE_CHECK_START; + storage -> ux_host_class_storage_delay_ms = UX_MS_TO_TICK( + UX_HOST_CLASS_STORAGE_THREAD_SLEEP_TIME); + UX_RESTORE + continue; + } + UX_RESTORE + + case UX_STATE_RESET: + default: + break; + } + break; + } +} + +static inline VOID _ux_host_class_storage_max_lun_save(UX_HOST_CLASS_STORAGE *storage) +{ +UX_TRANSFER *trans = storage -> ux_host_class_storage_trans; + + /* By default max lun is 0. */ + storage -> ux_host_class_storage_max_lun = 0; + + /* MaxLuN can from success request. */ + if (trans) + { + + /* If success, save max LUN. */ + if (trans -> ux_transfer_request_completion_code == UX_SUCCESS && + trans -> ux_transfer_request_actual_length == 1) + { + storage -> ux_host_class_storage_max_lun = + *trans -> ux_transfer_request_data_pointer; + + /* Is the max LUN index greater than our LUN array's? */ + if (storage -> ux_host_class_storage_max_lun > UX_MAX_HOST_LUN - 1) + { + + /* Cap it off. */ + storage -> ux_host_class_storage_max_lun = UX_MAX_HOST_LUN - 1; + + /* Notify application so it knows to increase UX_MAX_HOST_LUN. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEMORY_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + } + } + + /* Allocated buffer for request must be freed here. */ + _ux_utility_memory_free(trans -> ux_transfer_request_data_pointer); + } +} +static inline UINT _ux_host_class_storage_inquiry_save(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *inquiry_response = storage -> ux_host_class_storage_trans_data; +UINT lun_index = storage -> ux_host_class_storage_lun; + storage -> ux_host_class_storage_media_type = *(inquiry_response + + UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE); + storage -> ux_host_class_storage_lun_types[lun_index] = + storage -> ux_host_class_storage_media_type; + storage -> ux_host_class_storage_lun_removable_media_flags[lun_index] = + *(inquiry_response + + UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA); + + /* Free response buffer. */ + _ux_utility_memory_free(inquiry_response); + + /* Set default sector size. */ + switch(storage -> ux_host_class_storage_media_type) + { + case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK: + case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK: + storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT; + break; + + case UX_HOST_CLASS_STORAGE_MEDIA_CDROM: + case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK: + storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER; + break; + + default: + + /* Notify application so it knows to increase UX_MAX_HOST_LUN. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_MEDIA_NOT_SUPPORTED); + } + return(UX_SUCCESS); +} +static inline VOID _ux_host_class_storage_capacity_save(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *capacity_response = storage -> ux_host_class_storage_trans_data; + + /* If capacity response OK, save last LBA and LB size. */ + if (storage -> ux_host_class_storage_sense_code == 0) + { + storage -> ux_host_class_storage_last_sector_number = + _ux_utility_long_get_big_endian(capacity_response + + UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_LBA); + storage -> ux_host_class_storage_sector_size = + _ux_utility_long_get_big_endian(capacity_response + + UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE); + + /* Media inserted to LUN. */ + _ux_host_class_storage_lun_media_insert(storage); + } + + /* Free allocated buffer. */ + _ux_utility_memory_free(capacity_response); +} +static inline VOID _ux_host_class_storage_format_cap_save(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *format_cap_response = storage -> ux_host_class_storage_trans_data; + + /* There is nothing to save. */ + /* Free allocated resource. */ + _ux_utility_memory_free(format_cap_response); +} + +static inline ULONG _ux_host_class_storage_lun_scan(UX_HOST_CLASS_STORAGE *storage, + ULONG do_unmount) +{ +UX_HOST_CLASS *class_inst; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; +ULONG media_index; +ULONG n_found; + + /* We may need to unmount this partition if it was mounted before. + To do so, we need to parse the existing media instance and find out + if this partition was already mounted. */ + class_inst = storage -> ux_host_class_storage_class; + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media; + + /* Scan all instances of media. */ + for (media_index = 0, n_found = 0; + media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; + storage_media++, media_index++) + { + + /* Check storage instance and lun number. */ + if (storage_media -> ux_host_class_storage_media_status != UX_USED) + continue; + if (storage_media -> ux_host_class_storage_media_storage != storage) + continue; + if (storage_media -> ux_host_class_storage_media_lun != + storage -> ux_host_class_storage_lun) + continue; + + /* Found mounted media. */ + n_found ++; + + /* If no unmount, just check next media instance. */ + if (do_unmount == UX_FALSE) + continue; + + /* Free the storage media. */ + storage_media -> ux_host_class_storage_media_status = UX_UNUSED; + + /* Invoke callback for media removal. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_REMOVAL, + storage -> ux_host_class_storage_class, + (VOID *) storage_media); + } + } + + /* Return number of medias found and unmounted. */ + return(n_found); +} + +static inline VOID _ux_host_class_storage_unit_ready_check(UX_HOST_CLASS_STORAGE *storage) +{ +ULONG n; + + /* The LUN is ready. */ + if (storage -> ux_host_class_storage_sense_code == 0) + { + + /* Check if LUN is mounted. */ + n = _ux_host_class_storage_lun_scan(storage, UX_FALSE); + + /* If LUN is already mounted, check next LUN. */ + if (n > 0) + { + + /* LUN is mounted, just check next LUN. */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; + return; + } + + /* Next mounting steps : Inquiry() -> ReadFormatCapacity() -> mount(). */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_INQUIRY; + return; + } + + /* The LUN not ready cases have been done before. */ + + /* Just check next LUN. */ + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; +} + +static inline UINT _ux_host_class_storage_lun_is_removable(UX_HOST_CLASS_STORAGE *storage) +{ +UINT lun_index = storage -> ux_host_class_storage_lun; +UINT removable = storage -> ux_host_class_storage_lun_removable_media_flags[lun_index] & + UX_HOST_CLASS_STORAGE_MEDIA_REMOVABLE; + return(removable); +} +static inline UINT _ux_host_class_storage_lun_type_is_known(UX_HOST_CLASS_STORAGE *storage) +{ +UINT lun_index = storage -> ux_host_class_storage_lun; +UINT lun_type = storage -> ux_host_class_storage_lun_types[lun_index]; + return((lun_type == UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK) || + (lun_type == UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK) || + (lun_type == UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK)); +} + +static inline VOID _ux_host_class_storage_lun_media_insert(UX_HOST_CLASS_STORAGE *storage) +{ +UX_HOST_CLASS *class_inst; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; +INT media_index; + + /* Get class. */ + class_inst = storage -> ux_host_class_storage_class; + + /* Find a free media slot for inserted media. */ + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media; + for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; + storage_media ++, media_index ++) + { + + /* Skip used storage media slots. */ + if (storage_media -> ux_host_class_storage_media_status == UX_USED) + continue; + + /* Use this free storage media slot. */ + storage_media -> ux_host_class_storage_media_status = UX_USED; + storage_media -> ux_host_class_storage_media_storage = storage; + + /* Save media information. */ + storage_media -> ux_host_class_storage_media_lun = (UCHAR)storage -> ux_host_class_storage_lun; + storage_media -> ux_host_class_storage_media_sector_size = (USHORT)storage -> ux_host_class_storage_sector_size; + storage_media -> ux_host_class_storage_media_number_sectors = storage -> ux_host_class_storage_last_sector_number + 1; + + /* Invoke callback for media insertion. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + /* In standalone mode, no state running (read/write) expected in callback. */ + _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_INSERTION, + storage -> ux_host_class_storage_class, (VOID *) storage_media); + } + + /* Media saved OK. */ + return; + } + + /* No free slot. */ + return; +} + +static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_STORAGE *storage) +{ +ULONG sense_key; + + if (storage -> ux_host_class_storage_sense_code == 0) + return(UX_FALSE); + + sense_key = UX_HOST_CLASS_STORAGE_SENSE_KEY(storage -> ux_host_class_storage_sense_code); + switch(sense_key) + { + case UX_HOST_CLASS_STORAGE_SENSE_KEY_NOT_READY: + + /* Remove the mounted LUN media. */ + _ux_host_class_storage_lun_scan(storage, UX_TRUE); + + /* The LUN is not ready, check next any way. */ + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN; + + /* We have changed state. */ + return(UX_TRUE); + + case UX_HOST_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION: + + /* Remove the mounted LUN media. */ + _ux_host_class_storage_lun_scan(storage, UX_TRUE); + + /* Do immediate ready check again. */ + storage -> ux_host_class_storage_state_state = + UX_HOST_CLASS_STORAGE_STATE_TEST_READY; + + /* We have changed state. */ + return(UX_TRUE); + + case UX_HOST_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT: + + /* Fall through. */ + default: + + /* Nothing to do now. */ + break; + } + + /* State manated by others. */ + return(UX_FALSE); +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c index da46678c..50939c6c 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c @@ -30,12 +30,13 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -48,6 +49,8 @@ /* UX_MEDIA (default FileX) and the media is either not present */ /* or was removed and is being re-inserted. */ /* */ +/* It's for RTOS mode. */ +/* */ /* INPUT */ /* */ /* class_address Class address */ @@ -68,8 +71,8 @@ /* _ux_host_class_storage_media_format_capacity_get */ /* Get media format capacity */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get a semaphore */ -/* _ux_utility_semaphore_put Put a semaphore */ +/* _ux_host_semaphore_get Get a semaphore */ +/* _ux_host_semaphore_put Put a semaphore */ /* _ux_utility_delay_ms Thread sleep */ /* */ /* CALLED BY */ @@ -90,6 +93,9 @@ /* class specific structured */ /* data, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_host_class_storage_thread_entry(ULONG class_address) @@ -130,7 +136,7 @@ UCHAR *memory; /* We need to ensure nobody is accessing this storage instance. We use the storage class instance semaphore to protect. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) break; @@ -192,7 +198,7 @@ UCHAR *memory; memory = storage_media -> ux_host_class_storage_media_memory; /* Let UX_MEDIA (default FileX) use this instance. */ - status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_put(&storage -> ux_host_class_storage_semaphore); /* Ask UX_MEDIA (default FileX) to unmount the partition. */ ux_media_close(media); @@ -204,7 +210,7 @@ UCHAR *memory; ux_media_id_set(media, 0); /* Now, we protect the storage instance. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) break; @@ -214,13 +220,18 @@ UCHAR *memory; #else /* Check storage instance and lun number. */ + if (storage_media -> ux_host_class_storage_media_status != UX_USED) + continue; if (storage_media -> ux_host_class_storage_media_storage != storage) continue; if (storage_media -> ux_host_class_storage_media_lun != storage -> ux_host_class_storage_lun) continue; /* Release the instance. */ - status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + status = _ux_host_semaphore_put_rc(&storage -> ux_host_class_storage_semaphore); + + /* Free the storage media. */ + storage_media -> ux_host_class_storage_media_status = UX_UNUSED; /* Invoke callback for media removal. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) @@ -231,11 +242,8 @@ UCHAR *memory; storage -> ux_host_class_storage_class, (VOID *) storage_media); } - /* Free the storage media. */ - storage_media -> ux_host_class_storage_media_storage = UX_NULL; - /* Now, we protect the storage instance. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) break; #endif @@ -267,7 +275,7 @@ UCHAR *memory; memory = storage_media -> ux_host_class_storage_media_memory; /* Let UX_MEDIA (default FileX) use this instance. */ - status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_put(&storage -> ux_host_class_storage_semaphore); /* Ask UX_MEDIA (default FileX) to unmount the partition. */ ux_media_close(media); @@ -279,7 +287,7 @@ UCHAR *memory; ux_media_id_set(media, 0); /* Now, we protect the storage instance. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) break; @@ -289,13 +297,18 @@ UCHAR *memory; #else /* Check storage instance and lun number. */ + if (storage_media -> ux_host_class_storage_media_status != UX_USED) + continue; if (storage_media -> ux_host_class_storage_media_storage != storage) continue; if (storage_media -> ux_host_class_storage_media_lun != storage -> ux_host_class_storage_lun) continue; /* Release the instance. */ - status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + status = _ux_host_semaphore_put_rc(&storage -> ux_host_class_storage_semaphore); + + /* Free the storage media. */ + storage_media -> ux_host_class_storage_media_status = UX_UNUSED; /* Invoke callback for media removal. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) @@ -306,11 +319,8 @@ UCHAR *memory; storage -> ux_host_class_storage_class, (VOID *) storage_media); } - /* Free the storage media. */ - storage_media -> ux_host_class_storage_media_storage = UX_NULL; - /* Now, we protect the storage instance. */ - status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) break; #endif @@ -343,7 +353,7 @@ UCHAR *memory; break; /* Let UX_MEDIA (default FileX) use this instance. */ - _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_put(&storage -> ux_host_class_storage_semaphore); #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) @@ -358,10 +368,11 @@ UCHAR *memory; { /* Skip used storage media slots. */ - if (storage_media -> ux_host_class_storage_media_storage != UX_NULL) + if (storage_media -> ux_host_class_storage_media_status == UX_USED) continue; /* Use this free storage media slot. */ + storage_media -> ux_host_class_storage_media_status = UX_USED; storage_media -> ux_host_class_storage_media_storage = storage; /* Save media information. */ @@ -381,7 +392,7 @@ UCHAR *memory; #endif /* Now, we protect the storage instance. */ - _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); } break; @@ -392,7 +403,7 @@ UCHAR *memory; } /* Other threads are now allowed to access this storage instance. */ - status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + _ux_host_semaphore_put(&storage -> ux_host_class_storage_semaphore); } /* Move to the next entry in the storage instances link. */ @@ -400,3 +411,4 @@ UCHAR *memory; } } } +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport.c b/common/usbx_host_classes/src/ux_host_class_storage_transport.c index 8458dbb4..764e88e8 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_transport.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_transport PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -45,6 +45,8 @@ /* This function is the transport layer for all protocols. It perform */ /* the error recovery and retries if needed. */ /* */ +/* It's for RTOS mode only. */ +/* */ /* INPUT */ /* */ /* storage Pointer to storage class */ @@ -72,10 +74,18 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_transport(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) { +#if defined(UX_HOST_STANDALONE) + UX_PARAMETER_NOT_USED(storage); + UX_PARAMETER_NOT_USED(data_pointer); + return(UX_FUNCTION_NOT_SUPPORTED); +#else UINT status; UINT csw_status; @@ -153,4 +163,5 @@ UINT csw_status; } } #endif +#endif } diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c index 222e535b..5acd40ac 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c @@ -30,12 +30,13 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_transport_bo PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,7 +65,7 @@ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ /* _ux_utility_long_get Get 32-bit word */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -78,6 +79,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_transport_bo(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) @@ -116,7 +120,7 @@ UCHAR *get_status_response; return(status); /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -200,7 +204,7 @@ UCHAR *get_status_response; if (status == UX_SUCCESS) /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we may have a time out or if we had a problem during the preparation of the transaction we should abort the SCSI transaction. */ @@ -272,7 +276,7 @@ UCHAR *get_status_response; return(status); /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); /* Check semaphore status. */ if (status != UX_SUCCESS) @@ -388,3 +392,4 @@ UCHAR *get_status_response; /* Return the error. */ return(transfer_request -> ux_transfer_request_completion_code); } +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c index edb5c72e..e6ec2fb7 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c @@ -30,12 +30,13 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_transport_cb PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +61,7 @@ /* _ux_host_stack_transfer_request Process host stack transfer */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_utility_long_get Get 32-bit word */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -74,6 +75,10 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed CB request index, */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_transport_cb(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) @@ -100,7 +105,7 @@ UX_ENDPOINT *control_endpoint; transfer_request -> ux_transfer_request_function = 0; transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; transfer_request -> ux_transfer_request_value = 0; - transfer_request -> ux_transfer_request_index = 0; + transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber; /* Use a pointer for the ufi portion of the command. */ cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; @@ -145,7 +150,7 @@ UX_ENDPOINT *control_endpoint; return(status); /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); /* Get the actual transfer length and update the cumulated stored value for upper layers. This could be a non complete packet. But we don't test here because it only matters for @@ -176,4 +181,4 @@ UX_ENDPOINT *control_endpoint; /* Return the status code. */ return(transfer_request -> ux_transfer_request_completion_code); } - +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c index 22837b2a..18a22cb8 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c @@ -30,12 +30,13 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_transport_cbi PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,7 +63,7 @@ /* _ux_host_stack_transfer_request Process host stack transfer */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_utility_long_get Get 32-bit word */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +77,10 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed CBI request index, */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_transport_cbi(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) @@ -102,7 +107,7 @@ UX_ENDPOINT *control_endpoint; transfer_request -> ux_transfer_request_function = 0; transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; transfer_request -> ux_transfer_request_value = 0; - transfer_request -> ux_transfer_request_index = 0; + transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber; /* Use a pointer for the ufi portion of the command. */ cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; @@ -147,7 +152,7 @@ UX_ENDPOINT *control_endpoint; return(status); /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); /* Get the actual transfer length and update the cumulated stored value for upper layers. This could be a non complete packet. But we don't test here because it only matters for @@ -190,7 +195,7 @@ UX_ENDPOINT *control_endpoint; /* We must wait for the interrupt endpoint to return the status stage now. This can take a fairly long time. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_CBI_STATUS_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_STORAGE_CBI_STATUS_TIMEOUT)); /* If the status is not successful, we may have a timeout error. */ if (status != UX_SUCCESS) @@ -199,4 +204,4 @@ UX_ENDPOINT *control_endpoint; /* Return the status code. */ return(transfer_request -> ux_transfer_request_completion_code); } - +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_run.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_run.c new file mode 100644 index 00000000..927a0994 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_run.c @@ -0,0 +1,631 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +#if defined(UX_HOST_STANDALONE) + + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT +#error Storage legacy protocols not supported in standlone mode +#endif + +#define UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) \ + ((s) -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol) +#define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_BO(s) \ + (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_BO) +#define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_CB(s) \ + (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_CB) +#define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_CBI(s) \ + (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI) + +static inline VOID _ux_host_class_storage_transport_cbw(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_csw(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_trans_exit(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_trans_error(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_trans_next(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_trans_in_next(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_trans_out_next(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_status(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_ms_reset(UX_HOST_CLASS_STORAGE *storage); +static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORAGE *storage); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_transport_run PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the transport layer for all protocols. It perform */ +/* the error recovery and retries if needed. */ +/* */ +/* It's valid only with standalone mode. */ +/* It's non-blocking. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_storage_transport) Class storage transport */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE *storage) +{ +UINT status; +UCHAR state; + while(1) + { + state = storage -> ux_host_class_storage_trans_state; + switch(state) + { + case UX_STATE_RESET: + storage -> ux_host_class_storage_trans_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; + storage -> ux_host_class_storage_sense_code = 0; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CBW; + + /* Start the command immediately. */ + /* Fall through. */ + case UX_HOST_CLASS_STORAGE_TRANS_CBW: + _ux_host_class_storage_transport_cbw(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_CSW: + _ux_host_class_storage_transport_csw(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE: + status = _ux_host_class_storage_request_sense(storage); + if (status == UX_SUCCESS) + continue; + + /* Failed to issue request sense. */ + storage -> ux_host_class_storage_status = status; + storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE; + return(UX_STATE_ERROR); + + case UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT: + _ux_host_class_storage_transport_trans_in_next(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT: + _ux_host_class_storage_transport_trans_out_next(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_WAIT: + status = _ux_host_stack_transfer_run(storage -> ux_host_class_storage_trans); + + /* Next cases. */ + if (status == UX_STATE_NEXT || status == UX_STATE_IDLE) + { + _ux_host_class_storage_transport_trans_next(storage); + continue; + } + + /* Exit cases. */ + if (status < UX_STATE_IDLE) + { + _ux_host_class_storage_transport_trans_exit(storage); + return(UX_STATE_EXIT); + } + + /* Error cases. */ + if (status < UX_STATE_NEXT) + { + _ux_host_class_storage_transport_trans_error(storage); + continue; + } + + /* Wait. */ + return(UX_STATE_WAIT); + + case UX_HOST_CLASS_STORAGE_TRANS_STATUS: + _ux_host_class_storage_transport_status(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_MS_RESET: + _ux_host_class_storage_transport_ms_reset(storage); + continue; + + case UX_HOST_CLASS_STORAGE_TRANS_EP_RESET: + _ux_host_class_storage_transport_ep_reset(storage); + continue; + + case UX_STATE_IDLE: + return(UX_STATE_NEXT); + case UX_STATE_EXIT: + return(UX_STATE_EXIT); + + default: + break; + } + break; + } + + /* Unexpected state, fatal error. */ + storage -> ux_host_class_storage_status = UX_ERROR; + storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); +} +static inline VOID _ux_host_class_storage_transport_cbw(UX_HOST_CLASS_STORAGE *storage) +{ +UX_ENDPOINT *endpoint; +UX_TRANSFER *trans; + + /* Prepare BulkOUT CBW transfer. */ + endpoint = storage -> ux_host_class_storage_bulk_out_endpoint; + trans = &endpoint -> ux_endpoint_transfer_request; + trans -> ux_transfer_request_data_pointer = storage -> ux_host_class_storage_cbw; + trans -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CBW_LENGTH; + + /* Next : wait transfer done. */ + UX_TRANSFER_STATE_RESET(trans); + storage -> ux_host_class_storage_trans = trans; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; + storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_CBW; +} +static inline VOID _ux_host_class_storage_transport_csw(UX_HOST_CLASS_STORAGE *storage) +{ +UX_ENDPOINT *endpoint; +UX_TRANSFER *trans; + + /* Prepare BulkIN CSW transfer. */ + endpoint = storage -> ux_host_class_storage_bulk_in_endpoint; + trans = &endpoint -> ux_endpoint_transfer_request; + trans -> ux_transfer_request_data_pointer = storage -> ux_host_class_storage_csw; + trans -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CSW_LENGTH; + + UX_TRANSFER_STATE_RESET(trans); + storage -> ux_host_class_storage_trans = trans; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; + storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_CSW; +} +static inline VOID _ux_host_class_storage_transport_trans_exit(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; +UCHAR *cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; + + /* If request sense in progress, response buffer should be freed. */ + if (*(cb + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) == + UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE) + { + + /* Free sense buffer and restore data pointer. */ + _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data); + storage -> ux_host_class_storage_trans_data = + storage -> ux_host_class_storage_trans_data_bak; + + /* Restore CBW. */ + _ux_utility_memory_copy(storage -> ux_host_class_storage_cbw, + storage -> ux_host_class_storage_saved_cbw, + UX_HOST_CLASS_STORAGE_CBW_LENGTH); /* Use case of memcpy is verified. */ + } + + /* It's exit. */ + storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT; +} +static inline VOID _ux_host_class_storage_transport_trans_error(UX_HOST_CLASS_STORAGE *storage) +{ +UX_TRANSFER *trans = storage -> ux_host_class_storage_trans; +UCHAR stage = storage -> ux_host_class_storage_trans_stage; + if (trans -> ux_transfer_request_completion_code == UX_TRANSFER_STALLED) + { + + /* In case CBW stall, send MS Reset. */ + if (stage & UX_HOST_CLASS_STORAGE_STAGE_CBW) + { + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET; + return; + } + /* In case DATA/CSW stall, reset endpoint and try again. */ + if (stage <= UX_HOST_CLASS_STORAGE_STAGE_CSW) + { + + /* Check retry. */ + if (storage -> ux_host_class_storage_trans_retry) + { + storage -> ux_host_class_storage_trans_retry --; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET; + } + else + { + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET; + } + return; + } + + /* In other case, control transfer error. */ + storage -> ux_host_class_storage_status = UX_ERROR; + storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT; + return; + } + else + { + + /* Perform MS Reset. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET; + } +} +static inline VOID _ux_host_class_storage_transport_trans_next(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR stage = storage -> ux_host_class_storage_trans_stage; +UCHAR *cbw = storage -> ux_host_class_storage_cbw; +ULONG len = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); +UCHAR flags = *(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS); +UX_ENDPOINT *endpoint; +UX_TRANSFER *trans; +UX_HCD *hcd; + + /* Check transfer completion code. */ + trans = storage -> ux_host_class_storage_trans; + if (UX_SUCCESS != trans -> ux_transfer_request_completion_code) + { + _ux_host_class_storage_transport_trans_error(storage); + return; + } + + if (stage == UX_HOST_CLASS_STORAGE_STAGE_CBW) + { + + if (len == 0) + { + + /* There is no data, start CSW. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW; + return; + } + + /* Reset transfer count. */ + storage -> ux_host_class_storage_data_phase_length = 0; + if (flags & UX_HOST_CLASS_STORAGE_DATA_IN) + { + + /* Data IN. */ + endpoint = storage -> ux_host_class_storage_bulk_in_endpoint; + storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT; + return; + } + + /* Data OUT. */ + endpoint = storage -> ux_host_class_storage_bulk_out_endpoint; + storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT; + return; + } + if (stage == UX_HOST_CLASS_STORAGE_STAGE_DATA) + { + if (flags & UX_HOST_CLASS_STORAGE_DATA_IN) + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT; + else + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT; + return; + } + if (stage == UX_HOST_CLASS_STORAGE_STAGE_CSW) + { + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_STATUS; + return; + } + if (stage == UX_HOST_CLASS_STORAGE_STAGE_MS_RESET) + { + + /* Issue EPReset(OUT) then EPReset(IN) after MSReset(). */ + endpoint = storage -> ux_host_class_storage_bulk_out_endpoint; + storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET; + return; + } + if (stage & UX_HOST_CLASS_STORAGE_STAGE_EP_RESET) + { + + /* Reset endpoint in HCD level. */ + /* Pickup HCD pointer. */ + hcd = UX_DEVICE_HCD_GET(storage -> ux_host_class_storage_device); + + /* Get endpoint instance. */ + trans = storage -> ux_host_class_storage_trans; + endpoint = (trans -> ux_transfer_request_index & UX_ENDPOINT_DIRECTION) ? + storage -> ux_host_class_storage_bulk_in_endpoint : + storage -> ux_host_class_storage_bulk_out_endpoint; + + /* Call HCD entry function. */ + hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_ENDPOINT, endpoint); + + /* Check if it's part of MSReset() - OUT - IN. */ + if (stage & UX_HOST_CLASS_STORAGE_STAGE_MS_RESET) + { + + /* If it's last step, transport is done with error. */ + if (trans -> ux_transfer_request_index & UX_ENDPOINT_DIRECTION) + { + + storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE; + } + else + { + + /* BulkIN endpoint reset. */ + endpoint = storage -> ux_host_class_storage_bulk_in_endpoint; + storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET; + } + } + else + { + + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW; + } + return; + } +} +static inline VOID _ux_host_class_storage_transport_trans_in_next(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *cbw = storage -> ux_host_class_storage_cbw; +UX_TRANSFER *trans = storage -> ux_host_class_storage_trans; +ULONG requested_length; + + /* Get total data length. */ + requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Check if it's start of DATA phase. */ + if (storage -> ux_host_class_storage_trans_stage == UX_HOST_CLASS_STORAGE_STAGE_DATA) + { + + /* Update transferred data length. */ + storage -> ux_host_class_storage_data_phase_length += + trans -> ux_transfer_request_actual_length; + + /* Check if all data is done. */ + if ((storage -> ux_host_class_storage_data_phase_length >= requested_length) || + (trans -> ux_transfer_request_actual_length < trans -> ux_transfer_request_requested_length)) + { + + /* Start CSW. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW; + return; + } + } + else + { + + /* Initialize the request for data phase. */ + storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_DATA; + } + + + /* There is data remains, continue transfer. */ + requested_length -= storage -> ux_host_class_storage_data_phase_length; + + /* Limit max transfer size. */ + if (requested_length > UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE) + requested_length = UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE; + + /* Update transfer. */ + UX_TRANSFER_STATE_RESET(trans); + trans -> ux_transfer_request_requested_length = requested_length; + trans -> ux_transfer_request_data_pointer = + storage -> ux_host_class_storage_trans_data + + storage -> ux_host_class_storage_data_phase_length; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; +} +static inline VOID _ux_host_class_storage_transport_trans_out_next(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *cbw = storage -> ux_host_class_storage_cbw; +UX_TRANSFER *trans = storage -> ux_host_class_storage_trans; +ULONG requested_length; + + /* Get total data length. */ + requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Check if it's start of DATA phase. */ + if (storage -> ux_host_class_storage_trans_stage == UX_HOST_CLASS_STORAGE_STAGE_DATA) + { + /* Update data count. */ + storage -> ux_host_class_storage_data_phase_length += + trans -> ux_transfer_request_requested_length; + + /* Check if all data is done. */ + if (storage -> ux_host_class_storage_data_phase_length >= requested_length) + { + + /* Start CSW. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW; + return; + } + } + else + { + + /* Initialize the request for data phase. */ + storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_DATA; + } + + /* There is data remains, continue transfer. */ + requested_length -= storage -> ux_host_class_storage_data_phase_length; + + /* Limit max transfer size. */ + if (requested_length > UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE) + requested_length = UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE; + + /* Update transfer. */ + UX_TRANSFER_STATE_RESET(trans); + trans -> ux_transfer_request_requested_length = requested_length; + trans -> ux_transfer_request_data_pointer = + storage -> ux_host_class_storage_trans_data + + storage -> ux_host_class_storage_data_phase_length; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; +} +static inline VOID _ux_host_class_storage_transport_status(UX_HOST_CLASS_STORAGE *storage) +{ +UCHAR *cbw = storage -> ux_host_class_storage_cbw; +UCHAR *cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; +UCHAR *resp = storage -> ux_host_class_storage_trans_data; +ULONG sense_code; +UCHAR csw_status; + + /* Get CSW status code. */ + csw_status = storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS]; + + /* Check if it's request sense. */ + if (*(cb + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) == UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE) + { + + /* Restore command data pointer. */ + storage -> ux_host_class_storage_trans_data = + storage -> ux_host_class_storage_trans_data_bak; + + /* Get sense code from response buffer. */ + sense_code = UX_HOST_CLASS_STORAGE_SENSE_STATUS( + (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY), + (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE), + (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER)); + + /* Free buffer allocated for sense response. */ + _ux_utility_memory_free(resp); + + /* Passed, keep previous status and done. */ + if (csw_status == UX_HOST_CLASS_STORAGE_CSW_PASSED) + { + + /* Store the sense code in the storage instance. */ + storage -> ux_host_class_storage_sense_code = sense_code; + + /* Now we are done. */ + storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE; + return; + } + + /* There is issue, do MSReset() and transport done. */ + storage -> ux_host_class_storage_trans_status = UX_HOST_CLASS_STORAGE_CSW_PHASE_ERROR; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET; + return; + } + + /* Save status. */ + storage -> ux_host_class_storage_trans_status = csw_status; + + /* Success. */ + if (csw_status == UX_HOST_CLASS_STORAGE_CSW_PASSED) + { + storage -> ux_host_class_storage_status = UX_SUCCESS; + storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE; + return; + } + + /* There is error. */ + storage -> ux_host_class_storage_status = UX_ERROR; + + /* Fail. */ + if (csw_status == UX_HOST_CLASS_STORAGE_CSW_FAILED) + { + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE; + return; + } + + /* Fatal/phase error. */ + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET; + return; +} +static inline VOID _ux_host_class_storage_transport_ms_reset(UX_HOST_CLASS_STORAGE *storage) +{ +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +UX_TRANSFER *trans; + + /* Prepare MSReset() */ + interface = storage -> ux_host_class_storage_interface; + endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + trans = &endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the RESET request. */ + trans -> ux_transfer_request_data_pointer = UX_NULL; + trans -> ux_transfer_request_requested_length = 0; + trans -> ux_transfer_request_function = UX_HOST_CLASS_STORAGE_RESET; + trans -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + trans -> ux_transfer_request_value = 0; + trans -> ux_transfer_request_index = interface -> ux_interface_descriptor.bInterfaceNumber; + + UX_TRANSFER_STATE_RESET(trans); + storage -> ux_host_class_storage_trans = trans; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; + storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_MS_RESET; +} +static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORAGE *storage) +{ +UX_ENDPOINT *endpoint; +UX_TRANSFER *trans; +ULONG endpoint_address; + + /* Clear halt for current transfer. */ + + /* Get endpoint address. */ + endpoint = storage -> ux_host_class_storage_trans -> ux_transfer_request_endpoint; + endpoint_address = endpoint -> ux_endpoint_descriptor.bEndpointAddress; + + /* Send ClearEndpointFeature(EP, Halt). */ + endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + trans = &endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the CLEAR_FEATURE request. */ + trans -> ux_transfer_request_data_pointer = UX_NULL; + trans -> ux_transfer_request_requested_length = 0; + trans -> ux_transfer_request_function = UX_CLEAR_FEATURE; + trans -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_ENDPOINT; + trans -> ux_transfer_request_value = UX_ENDPOINT_HALT; + trans -> ux_transfer_request_index = endpoint_address; + + UX_TRANSFER_STATE_RESET(trans); + storage -> ux_host_class_storage_trans = trans; + storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT; + storage -> ux_host_class_storage_trans_stage |= UX_HOST_CLASS_STORAGE_STAGE_EP_RESET; +} +#endif diff --git a/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c b/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c index 10b82086..e0e68f07 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_unit_ready_test PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_unit_ready_test(UX_HOST_CLASS_STORAGE *storage) @@ -100,11 +103,20 @@ UINT command_length; /* Prepare the TEST UNIT READY command block. */ *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_TEST_READY_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_TEST_READY; - + +#if defined(UX_HOST_STANDALONE) + + /* Prepare states. */ + UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage); + storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSPORT; + storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_TEST_CHECK; + status = UX_SUCCESS; +#else + /* Send the command to transport layer. */ status = _ux_host_class_storage_transport(storage, UX_NULL); +#endif /* Return completion status. */ return(status); } - diff --git a/common/usbx_host_classes/src/ux_host_class_swar_activate.c b/common/usbx_host_classes/src/ux_host_class_swar_activate.c index df2979bd..21aff778 100644 --- a/common/usbx_host_classes/src/ux_host_class_swar_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_swar_activate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_swar_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +60,7 @@ /* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_create Create swar semaphore */ +/* _ux_host_semaphore_create Create swar semaphore */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_swar_activate(UX_HOST_CLASS_COMMAND *command) @@ -114,7 +117,7 @@ UINT status; /* Create the semaphore to protect 2 threads from accessing the same swar instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&swar -> ux_host_class_swar_semaphore, "ux_host_class_swar_semaphore", 1); + status = _ux_host_semaphore_create(&swar -> ux_host_class_swar_semaphore, "ux_host_class_swar_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } diff --git a/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c b/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c index 1eb731a8..8192e72c 100644 --- a/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_swar_deactivate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort endpoint transfer */ /* _ux_utility_memory_free Free memory block */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_delete Delete protection semaphore */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ /* CALLED BY */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_swar_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -91,7 +94,7 @@ UINT status; swar -> ux_host_class_swar_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) { @@ -112,13 +115,13 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(swar -> ux_host_class_swar_class, (VOID *) swar); /* Destroy the semaphore. */ - _ux_utility_semaphore_delete(&swar -> ux_host_class_swar_semaphore); + _ux_host_semaphore_delete(&swar -> ux_host_class_swar_semaphore); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_swar_read.c b/common/usbx_host_classes/src/ux_host_class_swar_read.c index 2b1d7c6e..170a9d65 100644 --- a/common/usbx_host_classes/src/ux_host_class_swar_read.c +++ b/common/usbx_host_classes/src/ux_host_class_swar_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_swar_read PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ /* _ux_host_stack_class_instance_verify Verify the class instance */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_swar_read(UX_HOST_CLASS_SWAR *swar, UCHAR *data_pointer, @@ -104,7 +107,7 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -137,7 +140,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer_request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -151,7 +154,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -170,7 +173,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* There was a non transfer error, no partial transfer to be checked. */ return(status); @@ -186,7 +189,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* Return success to caller. */ return(UX_SUCCESS); @@ -200,7 +203,7 @@ ULONG transfer_request_length; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_swar_write.c b/common/usbx_host_classes/src/ux_host_class_swar_write.c index f7aa4266..24b5f60f 100644 --- a/common/usbx_host_classes/src/ux_host_class_swar_write.c +++ b/common/usbx_host_classes/src/ux_host_class_swar_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_swar_write PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -62,8 +62,8 @@ /* _ux_host_stack_class_instance_verify Verify the class instance */ /* _ux_host_stack_transfer_request Process transfer request */ /* _ux_host_stack_transfer_request_abort Abort transfer request */ -/* _ux_utility_semaphore_get Get protection semaphore */ -/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_semaphore_get Get protection semaphore */ +/* _ux_host_semaphore_put Release protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_swar_write(UX_HOST_CLASS_SWAR *swar, UCHAR * data_pointer, @@ -103,7 +106,7 @@ ULONG transfer_request_length; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -136,7 +139,7 @@ ULONG transfer_request_length; { /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) @@ -150,7 +153,7 @@ ULONG transfer_request_length; *actual_length += transfer_request -> ux_transfer_request_actual_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* Set the completion code. */ transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; @@ -169,7 +172,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* There was a non transfer error, no partial transfer to be checked */ return(status); @@ -185,7 +188,7 @@ ULONG transfer_request_length; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* Return success. */ return(UX_SUCCESS); @@ -201,7 +204,7 @@ ULONG transfer_request_length; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + status = _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore); /* We get here when all the transfers went through without errors. */ return(UX_SUCCESS); diff --git a/common/usbx_host_classes/src/ux_host_class_video_activate.c b/common/usbx_host_classes/src/ux_host_class_video_activate.c index b46f89df..f75a9869 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_activate.c +++ b/common/usbx_host_classes/src/ux_host_class_video_activate.c @@ -159,7 +159,7 @@ UCHAR *baInterfaceNr; /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_activate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -190,7 +190,7 @@ UCHAR *baInterfaceNr; /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_utility_memory_allocate Allocate a memory block */ /* _ux_utility_memory_free Free a memory block */ -/* _ux_utility_semaphore_create Create protection semaphore */ +/* _ux_host_semaphore_create Create protection semaphore */ /* */ /* CALLED BY */ /* */ @@ -206,6 +206,9 @@ UCHAR *baInterfaceNr; /* created new semaphore to */ /* protect control requests, */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_activate(UX_HOST_CLASS_COMMAND *command) @@ -273,7 +276,7 @@ UX_HOST_CLASS_VIDEO_DESCRIPTORS_PARSER parser; video instance. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&video -> ux_host_class_video_semaphore, "ux_video_semaphore", 1); + status = _ux_host_semaphore_create(&video -> ux_host_class_video_semaphore, "ux_video_semaphore", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -282,7 +285,7 @@ UX_HOST_CLASS_VIDEO_DESCRIPTORS_PARSER parser; request at the same time. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&video -> ux_host_class_video_semaphore_control_request, "ux_video_semaphore_control", 1); + status = _ux_host_semaphore_create(&video -> ux_host_class_video_semaphore_control_request, "ux_video_semaphore_control", 1); if (status != UX_SUCCESS) status = UX_SEMAPHORE_ERROR; } @@ -319,7 +322,7 @@ UX_HOST_CLASS_VIDEO_DESCRIPTORS_PARSER parser; /* Destroy the semaphore. */ if (video -> ux_host_class_video_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_delete(&video -> ux_host_class_video_semaphore); /* Destroy the class instance. */ _ux_host_stack_class_instance_destroy(video -> ux_host_class_video_class, (VOID *) video); diff --git a/common/usbx_host_classes/src/ux_host_class_video_channel_start.c b/common/usbx_host_classes/src/ux_host_class_video_channel_start.c index 90f10562..02baddb8 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_channel_start.c +++ b/common/usbx_host_classes/src/ux_host_class_video_channel_start.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_channel_start PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +61,8 @@ /* Select alternate setting */ /* _ux_host_stack_interface_endpoint_get Get interface endpoint */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_long_get Get 32-bit value */ @@ -82,6 +82,9 @@ /* fixed bandwidth check, */ /* saved max payload size, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_channel_start(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL *video_parameter) @@ -101,7 +104,7 @@ UINT max_payload_size; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; @@ -116,7 +119,7 @@ UINT max_payload_size; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return error. */ return(UX_MEMORY_INSUFFICIENT); @@ -252,7 +255,7 @@ UINT max_payload_size; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -274,7 +277,7 @@ UINT max_payload_size; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_get.c b/common/usbx_host_classes/src/ux_host_class_video_control_get.c index 1e6d7010..91bf813c 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_control_get.c +++ b/common/usbx_host_classes/src/ux_host_class_video_control_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_control_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_get Read 16-bit value */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_control_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) @@ -101,7 +104,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -115,7 +118,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -123,7 +126,7 @@ UCHAR * control_buffer; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -156,7 +159,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -182,7 +185,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -206,7 +209,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_request.c b/common/usbx_host_classes/src/ux_host_class_video_control_request.c index ac811bfc..df942c27 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_control_request.c +++ b/common/usbx_host_classes/src/ux_host_class_video_control_request.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_control_request PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_control_request(UX_HOST_CLASS_VIDEO *video, @@ -99,7 +102,7 @@ UCHAR interface_number; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore_control_request, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore_control_request, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -113,7 +116,7 @@ UCHAR interface_number; { /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -133,7 +136,7 @@ UCHAR interface_number; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -141,7 +144,7 @@ UCHAR interface_number; /* Something went wrong. */ _ux_utility_memory_free(control_buffer); - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); return(status); } @@ -175,7 +178,7 @@ UCHAR interface_number; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); /* Return completion status. */ return(status); @@ -194,7 +197,7 @@ UCHAR interface_number; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c b/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c index acb7f2ba..97699a31 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c +++ b/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_control_value_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_get Read 16-bit value */ @@ -76,6 +76,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_control_value_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) @@ -101,7 +104,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -115,7 +118,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -123,7 +126,7 @@ UCHAR * control_buffer; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -156,7 +159,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -166,7 +169,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c b/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c index 7c9cda34..a9b73826 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c +++ b/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_control_value_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,8 +57,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_short_put Put 16-bit value */ @@ -75,6 +75,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_control_value_set(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) @@ -100,7 +103,7 @@ UCHAR * control_buffer; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -114,7 +117,7 @@ UCHAR * control_buffer; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return an error. */ return(UX_MEMORY_INSUFFICIENT); @@ -125,7 +128,7 @@ UCHAR * control_buffer; /* Protect the control endpoint semaphore here. It will be unprotected in the transfer request function. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); /* Check for status. */ if (status != UX_SUCCESS) @@ -152,7 +155,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(UX_TRANSFER_ERROR); @@ -162,7 +165,7 @@ UCHAR * control_buffer; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_deactivate.c b/common/usbx_host_classes/src/ux_host_class_video_deactivate.c index dcd6bd1b..d73a3318 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_deactivate.c +++ b/common/usbx_host_classes/src/ux_host_class_video_deactivate.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_deactivate PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,8 +59,8 @@ /* _ux_host_stack_class_instance_destroy Destroy class instance */ /* _ux_host_stack_endpoint_transfer_abort */ /* Abort outstanding transfer */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_thread_schedule_other Schedule other threads */ /* */ @@ -82,6 +82,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* freed descriptor memory, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -97,7 +100,7 @@ UINT status; video -> ux_host_class_video_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) /* Return error. */ @@ -109,7 +112,7 @@ UINT status; /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Free descriptor memory. */ if (video -> ux_host_class_video_configuration_descriptor) @@ -119,8 +122,8 @@ UINT status; _ux_host_stack_class_instance_destroy(video -> ux_host_class_video_class, (VOID *) video); /* Destroy the semaphores. */ - _ux_utility_semaphore_delete(&video -> ux_host_class_video_semaphore); - _ux_utility_semaphore_delete(&video -> ux_host_class_video_semaphore_control_request); + _ux_host_semaphore_delete(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_delete(&video -> ux_host_class_video_semaphore_control_request); /* Before we free the device resources, we need to inform the application that the device is removed. */ diff --git a/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c b/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c index ceb5c680..364b3f69 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c +++ b/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_frame_parameters_set PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,8 +64,8 @@ /* _ux_utility_descriptor_parse Parse descriptor */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_long_get Read 32-bit value */ /* */ /* CALLED BY */ @@ -82,6 +82,9 @@ /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */ /* validated max payload size, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_frame_parameters_set(UX_HOST_CLASS_VIDEO *video, ULONG frame_format, ULONG width, ULONG height, ULONG frame_interval) @@ -214,7 +217,7 @@ ULONG max_payload_size; return(UX_HOST_CLASS_VIDEO_PARAMETER_ERROR); /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); /* We need to get the default control endpoint transfer request pointer. */ control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; @@ -229,7 +232,7 @@ ULONG max_payload_size; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return error. */ return(UX_MEMORY_INSUFFICIENT); @@ -292,7 +295,7 @@ ULONG max_payload_size; _ux_utility_memory_free(control_buffer); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Check the transfer status. */ if (status == UX_SUCCESS) diff --git a/common/usbx_host_classes/src/ux_host_class_video_read.c b/common/usbx_host_classes/src/ux_host_class_video_read.c index 5375dc81..fa35e77f 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_read.c +++ b/common/usbx_host_classes/src/ux_host_class_video_read.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_read PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,8 +64,8 @@ /* */ /* _ux_host_class_video_transfer_request Video transfer request */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_system_error_handler System error log */ /* */ /* CALLED BY */ @@ -84,6 +84,9 @@ /* used input request length */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_read(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request) @@ -104,7 +107,7 @@ UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *transfer_list; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -117,7 +120,7 @@ UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *transfer_list; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); @@ -133,7 +136,7 @@ UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *transfer_list; status = _ux_host_class_video_transfer_request(video, transfer_list); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_stop.c b/common/usbx_host_classes/src/ux_host_class_video_stop.c index 156cf9e6..15cd33c9 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_stop.c +++ b/common/usbx_host_classes/src/ux_host_class_video_stop.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_stop PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* Abort outstanding transfer */ /* _ux_host_stack_interface_setting_select */ /* Select interface */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_stop(UX_HOST_CLASS_VIDEO *video) @@ -84,7 +87,7 @@ UINT streaming_interface; /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); /* Get the interface number of the video streaming interface. */ streaming_interface = video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; @@ -126,7 +129,7 @@ UINT streaming_interface; video -> ux_host_class_video_isochronous_endpoint = UX_NULL; /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return successful completion. */ return(UX_SUCCESS); @@ -138,7 +141,7 @@ UINT streaming_interface; } /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c index eeda6676..8bf0caf2 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_transfer_buffer_add PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,8 +60,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_system_error_handler Log system error */ /* */ /* CALLED BY */ @@ -79,6 +79,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO *video, UCHAR* buffer) @@ -103,7 +106,7 @@ ULONG packet_size; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -113,7 +116,7 @@ ULONG packet_size; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); @@ -130,7 +133,7 @@ ULONG packet_size; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return error status. */ return(UX_MEMORY_ARRAY_FULL); @@ -160,7 +163,7 @@ ULONG packet_size; status = _ux_host_stack_transfer_request(transfer_request); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c index 8c9de87f..d28f8e4f 100644 --- a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_transfer_buffers_add PORTABLE C */ -/* 6.1.9 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,8 +69,8 @@ /* */ /* _ux_host_stack_class_instance_verify Verify instance is valid */ /* _ux_host_stack_transfer_request Process transfer request */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* _ux_system_error_handler Log system error */ /* */ /* CALLED BY */ @@ -88,6 +88,9 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_transfer_buffers_add(UX_HOST_CLASS_VIDEO *video, UCHAR** buffers, ULONG num_buffers) @@ -112,7 +115,7 @@ UINT i; } /* Protect thread reentry to this instance. */ - status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return(status); @@ -122,7 +125,7 @@ UINT i; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); @@ -152,7 +155,7 @@ UINT i; { /* Unprotect thread reentry to this instance. */ - status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + status = _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return error status. */ return(status); @@ -207,7 +210,7 @@ UINT i; status = _ux_host_stack_transfer_request(transfer_request); /* Unprotect thread reentry to this instance. */ - _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore); /* Return completion status. */ return(status); diff --git a/common/usbx_host_controllers/inc/ux_hcd_ohci.h b/common/usbx_host_controllers/inc/ux_hcd_ohci.h index f18977e5..f42a0db6 100755 --- a/common/usbx_host_controllers/inc/ux_hcd_ohci.h +++ b/common/usbx_host_controllers/inc/ux_hcd_ohci.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_hcd_ohci.h PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -50,6 +50,9 @@ /* added extern "C" keyword */ /* for compatibility with C++, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Xiuwen Cai Modified comment(s), */ +/* fixed HcPeriodicStart value,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -188,6 +191,7 @@ extern "C" { #define OHCI_HC_FM_INTERVAL_CLEAR 0x8000ffffu #define OHCI_HC_FM_INTERVAL_SET 0x27780000u +#define OHCI_HC_FM_INTERVAL_FI_MASK 0x00003fffu /* Define OHCI static definition. */ @@ -204,7 +208,6 @@ extern "C" { #define UX_OHCI_COMMAND_STATUS_RESET 0 #define UX_OHCI_INIT_RESET_DELAY 10 -#define UX_OHCI_HC_PERIODIC_START_DEFAULT 0x00003e67u /* Define OHCI completion code errors. */ diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c index 991a790b..d421b0f7 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_asynch_td_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,7 +59,7 @@ /* */ /* (ux_transfer_request_completion_function) Completion function */ /* _ux_hcd_ehci_ed_clean Clean ED */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_virtual_address Get virtual address */ /* */ /* CALLED BY */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UX_EHCI_TD *_ux_hcd_ehci_asynch_td_process(UX_EHCI_ED *ed, UX_EHCI_TD *td) @@ -144,7 +147,7 @@ ULONG pid; UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, td_error, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) /* Wake up the semaphore for this request. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* Nothing else to be processed in this queue. */ return(UX_NULL); @@ -186,7 +189,7 @@ ULONG pid; transfer_request -> ux_transfer_request_completion_function(transfer_request); /* Wake up the semaphore for this request. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* Nothing else to be processed in this queue */ return(UX_NULL); diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c b/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c index 9529da60..00e0b1e9 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_door_bell_wait PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* _ux_hcd_ehci_register_read Read EHCI register */ /* _ux_hcd_ehci_register_write Write EHCI register */ -/* _ux_utility_semaphore_get Get semaphore */ -/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* _ux_host_semaphore_put Release semaphore */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ehci_door_bell_wait(UX_HCD_EHCI *hcd_ehci) @@ -82,7 +85,7 @@ UINT status; /* Protect against multiple thread entry to this HCD. */ - status = _ux_utility_semaphore_get(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, UX_WAIT_FOREVER); + status = _ux_host_semaphore_get(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, UX_WAIT_FOREVER); if (status != UX_SUCCESS) return; @@ -92,10 +95,10 @@ UINT status; _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); /* Wait for the doorbell to be awaken. */ - status = _ux_utility_semaphore_get(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, UX_WAIT_FOREVER); + _ux_host_semaphore_get_norc(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, UX_WAIT_FOREVER); /* Free the protection semaphore. */ - status = _ux_utility_semaphore_put(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); + _ux_host_semaphore_put(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); /* Return to caller. */ return; diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c index 99bcd1c7..e3e6598b 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_fsisochronous_tds_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +60,7 @@ /* CALLS */ /* */ /* (ux_transfer_request_completion_function) Completion function */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_physical_address Get physical address */ /* */ /* CALLED BY */ @@ -74,6 +74,8 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UX_EHCI_FSISO_TD* _ux_hcd_ehci_fsisochronous_tds_process( diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c index 9f7593c8..f7827a71 100755 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_hsisochronous_tds_process PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -58,7 +58,7 @@ /* (ux_transfer_request_completion_function) */ /* Transfer Completion function */ /* _ux_hcd_ehci_register_read Read EHCI register */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* _ux_utility_physical_address Get physical address */ /* */ /* CALLED BY */ @@ -75,6 +75,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed compile warnings, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UX_EHCI_HSISO_TD* _ux_hcd_ehci_hsisochronous_tds_process( @@ -257,7 +260,7 @@ UINT i; transfer -> ux_transfer_request_completion_function(transfer); /* Put semaphore. */ - _ux_utility_semaphore_put(&transfer -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer -> ux_transfer_request_semaphore); } /* for (;i < n_fr;) */ } diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c b/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c index c8cd7073..ec2cbc43 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c @@ -60,7 +60,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_initialize PORTABLE C */ -/* 6.1.8 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -88,8 +88,8 @@ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_delete Delete memory block */ /* _ux_utility_physical_address Get physical address */ -/* _ux_utility_semaphore_create Create semaphore */ -/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_create Create semaphore */ +/* _ux_host_semaphore_delete Delete semaphore */ /* _ux_utility_mutex_create Create mutex */ /* _ux_utility_mutex_delete Delete mutex */ /* _ux_utility_set_interrupt_handler Set interrupt handler */ @@ -111,6 +111,9 @@ /* 08-02-2021 Wen Wang Modified comment(s), */ /* fixed spelling error, */ /* resulting in version 6.1.8 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_ehci_initialize(UX_HCD *hcd) @@ -334,7 +337,7 @@ UINT status = UX_SUCCESS; /* We must enable the HCD protection semaphore. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, "ux_hcd_protect_semaphore", 1); + status = _ux_host_semaphore_create(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, "ux_hcd_protect_semaphore", 1); if (status != UX_SUCCESS) status = (UX_SEMAPHORE_ERROR); } @@ -342,7 +345,7 @@ UINT status = UX_SUCCESS; /* We must enable the HCD doorbell semaphore. */ if (status == UX_SUCCESS) { - status = _ux_utility_semaphore_create(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, "ux_hcd_doorbell_semaphore", 0); + status = _ux_host_semaphore_create(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, "ux_hcd_doorbell_semaphore", 0); if (status != UX_SUCCESS) status = (UX_SEMAPHORE_ERROR); } @@ -395,7 +398,7 @@ UINT status = UX_SUCCESS; /* Wakeup enum thread. */ if (status != 0) - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); /* Return successful status. */ return(UX_SUCCESS); @@ -419,9 +422,9 @@ UINT status = UX_SUCCESS; if (hcd_ehci -> ux_hcd_ehci_periodic_mutex.tx_mutex_id != 0) _ux_utility_mutex_delete(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); if (hcd_ehci -> ux_hcd_ehci_protect_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); + _ux_host_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); if (hcd_ehci -> ux_hcd_ehci_doorbell_semaphore.tx_semaphore_id != 0) - _ux_utility_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); + _ux_host_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); _ux_utility_memory_free(hcd_ehci); /* Return error status code. */ diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c index ee75d5b0..d28573a0 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_interrupt_handler PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,7 +66,7 @@ /* _ux_hcd_ehci_controller_disable Disable controller */ /* _ux_hcd_ehci_register_read Read EHCI register */ /* _ux_hcd_ehci_register_write Write EHCI register */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -79,6 +79,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ehci_interrupt_handler(VOID) @@ -127,7 +130,7 @@ ULONG port_index; /* We have some transactions done in the past frame/micro-frame. The controller thread needs to wake up and process them. */ hcd -> ux_hcd_thread_signal++; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); } if (ehci_register & EHCI_HC_STS_HSE) @@ -139,7 +142,7 @@ ULONG port_index; hcd -> ux_hcd_thread_signal++; hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; hcd -> ux_hcd_thread_signal++; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_INTERRUPT, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_DEAD); @@ -174,7 +177,7 @@ ULONG port_index; /* The controller has issued a Root hub status change signal. We need to resume the thread in charge of the USB topology. */ - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); } if (ehci_register & EHCI_HC_STS_IAA) @@ -182,7 +185,7 @@ ULONG port_index; /* The controller has issued a Door Bell status change signal. We need to resume the thread who raised the doorbell. */ - _ux_utility_semaphore_put(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); + _ux_host_semaphore_put(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); } } } diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c index 5eedf166..8277267c 100755 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_request_control_transfer PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,7 +67,7 @@ /* _ux_host_stack_transfer_request_abort Abort transfer request */ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* _ux_utility_short_put Write a 16-bit value */ /* */ /* CALLED BY */ @@ -83,6 +83,7 @@ /* prefixed UX to MS_TO_TICK, */ /* resulting in version 6.1 */ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ /* fixed compile warnings, */ /* resulting in version 6.1.2 */ /* */ @@ -211,7 +212,7 @@ UINT pid; ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) td_component; /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c index 43e8405d..22a68c19 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_request_isochronous_transfer PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,7 +67,7 @@ /* */ /* _ux_utility_mutex_on Get mutex */ /* _ux_utility_mutex_off Put mutex */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -80,6 +80,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_ehci_request_isochronous_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) @@ -170,7 +173,7 @@ UCHAR start = UX_FALSE; if (start) { hcd_ehci -> ux_hcd_ehci_hcd_owner -> ux_hcd_thread_signal ++; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); } /* Return completion status. */ diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c index 7744bc0f..f220eefd 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ehci_transfer_request_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +60,7 @@ /* CALLS */ /* */ /* (ux_transfer_request_completion_function) Transfer complete function*/ -/* _ux_utility_semaphore_put Put producer semaphore */ +/* _ux_host_semaphore_put Put producer semaphore */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ehci_transfer_request_process(UX_TRANSFER *transfer_request) @@ -86,7 +89,7 @@ VOID _ux_hcd_ehci_transfer_request_process(UX_TRANSFER *transfer_request) else /* There is a semaphore so send the signal to the class. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* Return to caller. */ return; diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c b/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c index 2aa4e1ce..48bd7d75 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ohci_done_queue_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,7 +66,7 @@ /* _ux_hcd_ohci_next_td_clean Clean next TD */ /* _ux_hcd_ohci_register_read Read OHCI register */ /* _ux_hcd_ohci_register_write Write OHCI register */ -/* _ux_utility_semaphore_put Put producer semaphore */ +/* _ux_host_semaphore_put Put producer semaphore */ /* _ux_utility_virtual_address Get virtual address */ /* */ /* CALLED BY */ @@ -80,6 +80,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ohci_done_queue_process(UX_HCD_OHCI *hcd_ohci) @@ -161,7 +164,7 @@ ULONG current_frame; transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } break; @@ -188,7 +191,7 @@ ULONG current_frame; _ux_hcd_ohci_next_td_clean(td); if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); break; @@ -201,7 +204,7 @@ ULONG current_frame; _ux_hcd_ohci_next_td_clean(td); if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_STALLED, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) @@ -220,7 +223,7 @@ ULONG current_frame; _ux_hcd_ohci_next_td_clean(td); if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) @@ -238,7 +241,7 @@ ULONG current_frame; _ux_hcd_ohci_next_td_clean(td); if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_ERROR, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) @@ -291,7 +294,7 @@ ULONG current_frame; transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) transfer_request -> ux_transfer_request_completion_function(transfer_request); - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); } break; @@ -307,7 +310,7 @@ ULONG current_frame; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_MISSED_FRAME, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); break; @@ -321,7 +324,7 @@ ULONG current_frame; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_ERROR, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); break; } } diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c b/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c index 5930ebfc..2ad62051 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ohci_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -79,6 +79,9 @@ /* optimized based on compile */ /* definitions, */ /* resulting in version 6.1 */ +/* 01-31-2022 Xiuwen Cai Modified comment(s), */ +/* fixed HcPeriodicStart value,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_ohci_initialize(UX_HCD *hcd) @@ -210,9 +213,9 @@ UINT status; ohci_register |= OHCI_HC_FM_INTERVAL_SET; _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_FM_INTERVAL, ohci_register); - /* Set the default Periodic Start value. In some controller, a reset will set the default value - but in some controller this value has to be set manually (like the LPC2468. ) */ - _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_PERIODIC_START, UX_OHCI_HC_PERIODIC_START_DEFAULT); + /* Set HcPeriodicStart to a value that is 90% of the value in FrameInterval field of the HcFmInterval register. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_FM_INTERVAL) & OHCI_HC_FM_INTERVAL_FI_MASK; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_PERIODIC_START, ohci_register * 9 / 10); /* Reset all the OHCI interrupts and re-enable only the ones we will use. */ _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_DISABLE, OHCI_HC_INTERRUPT_DISABLE_ALL); diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c index c20e6ed2..7d3486f5 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ohci_interrupt_handler PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -64,7 +64,7 @@ /* */ /* _ux_hcd_ohci_register_read Read OHCI register */ /* _ux_hcd_ohci_register_write Write OHCI register */ -/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_semaphore_put Put semaphore */ /* */ /* CALLED BY */ /* */ @@ -77,6 +77,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ohci_interrupt_handler(VOID) @@ -120,7 +123,7 @@ ULONG port_index; hcd_ohci -> ux_hcd_ohci_done_head = hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_done_head; hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_done_head = UX_NULL; hcd -> ux_hcd_thread_signal++; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); /* Since we have delayed the processing of the done queue to a thread. We need to ensure the host controller will not overwrite the done @@ -137,7 +140,7 @@ ULONG port_index; _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, OHCI_HC_CS_HCR); hcd -> ux_hcd_thread_signal++; hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); } if (ohci_register & OHCI_HC_INT_RHSC) @@ -168,7 +171,7 @@ ULONG port_index; /* We only wake up the root hub thread if there has been device insertion/extraction. */ if (root_hub_thread_wakeup != 0) - _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); } } diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c index d6adb19b..9379e3b7 100755 --- a/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ohci_request_control_transfer PORTABLE C */ -/* 6.1.2 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,7 +69,7 @@ /* _ux_utility_memory_allocate Allocate memory block */ /* _ux_utility_memory_free Release memory block */ /* _ux_utility_physical_address Get physical address */ -/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_semaphore_get Get semaphore */ /* _ux_utility_short_put Write 16-bit value */ /* _ux_utility_virtual_address Get virtual address */ /* */ @@ -88,6 +88,9 @@ /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ /* fixed compile warnings, */ /* resulting in version 6.1.2 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _ux_hcd_ohci_request_control_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) @@ -250,7 +253,7 @@ UINT status; _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, ohci_register); /* Wait for the completion of the transfer request. */ - status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); + status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); /* If the semaphore did not succeed we probably have a time out. */ if (status != UX_SUCCESS) diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c index faeede61..4a60a730 100644 --- a/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_hcd_ohci_transfer_request_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -60,7 +60,7 @@ /* CALLS */ /* */ /* (ux_transfer_request_completion_function) Completion function */ -/* _ux_utility_semaphore_put Signal transfer complete */ +/* _ux_host_semaphore_put Signal transfer complete */ /* */ /* CALLED BY */ /* */ @@ -73,6 +73,9 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined macros names, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _ux_hcd_ohci_transfer_request_process(UX_TRANSFER *transfer_request) @@ -86,7 +89,7 @@ VOID _ux_hcd_ohci_transfer_request_process(UX_TRANSFER *transfer_request) else /* There is a semaphore so send the signal to the class. */ - _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); /* Return to caller. */ return; diff --git a/ports/arm9/gnu/inc/ux_port.h b/ports/arm9/gnu/inc/ux_port.h index 79da3cfd..00882db7 100644 --- a/ports/arm9/gnu/inc/ux_port.h +++ b/ports/arm9/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h ARM9/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -207,7 +239,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/arm9/iar/inc/ux_port.h b/ports/arm9/iar/inc/ux_port.h index 069003ff..a2bc2342 100644 --- a/ports/arm9/iar/inc/ux_port.h +++ b/ports/arm9/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h ARM9/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -214,7 +246,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a15/gnu/inc/ux_port.h b/ports/cortex_a15/gnu/inc/ux_port.h index 09075c7c..79caa7f8 100644 --- a/ports/cortex_a15/gnu/inc/ux_port.h +++ b/ports/cortex_a15/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A15/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -203,7 +235,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A15/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A15/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a5/gnu/inc/ux_port.h b/ports/cortex_a5/gnu/inc/ux_port.h index d3244dac..b956ab28 100644 --- a/ports/cortex_a5/gnu/inc/ux_port.h +++ b/ports/cortex_a5/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A5/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a5/iar/inc/ux_port.h b/ports/cortex_a5/iar/inc/ux_port.h index bdc9d03a..17266c57 100644 --- a/ports/cortex_a5/iar/inc/ux_port.h +++ b/ports/cortex_a5/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A5/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a5x/ac6/inc/ux_port.h b/ports/cortex_a5x/ac6/inc/ux_port.h index 4c628fd5..7029bbcd 100644 --- a/ports/cortex_a5x/ac6/inc/ux_port.h +++ b/ports/cortex_a5x/ac6/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A5x/AC6 */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -227,7 +259,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5x/AC6 Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5x/AC6 Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a7/gnu/inc/ux_port.h b/ports/cortex_a7/gnu/inc/ux_port.h index 4fb1c283..ef0d5b41 100644 --- a/ports/cortex_a7/gnu/inc/ux_port.h +++ b/ports/cortex_a7/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A7/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -214,7 +246,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a7/iar/inc/ux_port.h b/ports/cortex_a7/iar/inc/ux_port.h index 329817d0..12e711e9 100644 --- a/ports/cortex_a7/iar/inc/ux_port.h +++ b/ports/cortex_a7/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A7/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -214,7 +246,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a8/gnu/inc/ux_port.h b/ports/cortex_a8/gnu/inc/ux_port.h index 7a29ae17..9107a7fe 100644 --- a/ports/cortex_a8/gnu/inc/ux_port.h +++ b/ports/cortex_a8/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A8/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a8/iar/inc/ux_port.h b/ports/cortex_a8/iar/inc/ux_port.h index db0a48bd..b7b67dca 100644 --- a/ports/cortex_a8/iar/inc/ux_port.h +++ b/ports/cortex_a8/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-A8/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a9/gnu/inc/ux_port.h b/ports/cortex_a9/gnu/inc/ux_port.h index 900c5358..6e4e382a 100644 --- a/ports/cortex_a9/gnu/inc/ux_port.h +++ b/ports/cortex_a9/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h ARM9/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_a9/iar/inc/ux_port.h b/ports/cortex_a9/iar/inc/ux_port.h index 5d9c6066..3041444d 100644 --- a/ports/cortex_a9/iar/inc/ux_port.h +++ b/ports/cortex_a9/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h ARM9/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m0/gnu/inc/ux_port.h b/ports/cortex_m0/gnu/inc/ux_port.h index b535aa28..74351ef1 100644 --- a/ports/cortex_m0/gnu/inc/ux_port.h +++ b/ports/cortex_m0/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M0/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -44,6 +44,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -69,6 +73,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -208,7 +240,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m0/iar/inc/ux_port.h b/ports/cortex_m0/iar/inc/ux_port.h index b975f1c1..fc7eef01 100644 --- a/ports/cortex_m0/iar/inc/ux_port.h +++ b/ports/cortex_m0/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M0/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m3/gnu/inc/ux_port.h b/ports/cortex_m3/gnu/inc/ux_port.h index 673ac752..5423f20f 100644 --- a/ports/cortex_m3/gnu/inc/ux_port.h +++ b/ports/cortex_m3/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M3/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -44,6 +44,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -69,6 +73,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -208,7 +240,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m3/iar/inc/ux_port.h b/ports/cortex_m3/iar/inc/ux_port.h index 066d9077..8b4ce6cd 100644 --- a/ports/cortex_m3/iar/inc/ux_port.h +++ b/ports/cortex_m3/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M3/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m4/gnu/inc/ux_port.h b/ports/cortex_m4/gnu/inc/ux_port.h index e83bd632..fabaed1c 100644 --- a/ports/cortex_m4/gnu/inc/ux_port.h +++ b/ports/cortex_m4/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M4/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -44,6 +44,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -69,6 +73,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -208,7 +240,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m4/iar/inc/ux_port.h b/ports/cortex_m4/iar/inc/ux_port.h index 7f4ee999..165ad8b5 100644 --- a/ports/cortex_m4/iar/inc/ux_port.h +++ b/ports/cortex_m4/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M4/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m7/gnu/inc/ux_port.h b/ports/cortex_m7/gnu/inc/ux_port.h index 475e77f4..ef2354b0 100644 --- a/ports/cortex_m7/gnu/inc/ux_port.h +++ b/ports/cortex_m7/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M7/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -44,6 +44,10 @@ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -69,6 +73,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -208,7 +240,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_m7/iar/inc/ux_port.h b/ports/cortex_m7/iar/inc/ux_port.h index 69fed1f1..cee0cb80 100644 --- a/ports/cortex_m7/iar/inc/ux_port.h +++ b/ports/cortex_m7/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-M7/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_r4/gnu/inc/ux_port.h b/ports/cortex_r4/gnu/inc/ux_port.h index ef28c910..42fc51a1 100644 --- a/ports/cortex_r4/gnu/inc/ux_port.h +++ b/ports/cortex_r4/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-R4/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -206,7 +238,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_r4/iar/inc/ux_port.h b/ports/cortex_r4/iar/inc/ux_port.h index bd39c334..66ff365c 100644 --- a/ports/cortex_r4/iar/inc/ux_port.h +++ b/ports/cortex_r4/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-R4/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_r5/gnu/inc/ux_port.h b/ports/cortex_r5/gnu/inc/ux_port.h index 3705f1b5..b1f66ca2 100644 --- a/ports/cortex_r5/gnu/inc/ux_port.h +++ b/ports/cortex_r5/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-R5/GNU */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/cortex_r5/iar/inc/ux_port.h b/ports/cortex_r5/iar/inc/ux_port.h index d188cbcf..3a19749c 100644 --- a/ports/cortex_r5/iar/inc/ux_port.h +++ b/ports/cortex_r5/iar/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Cortex-R5/IAR */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/IAR Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/IAR Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/generic/inc/ux_port.h b/ports/generic/inc/ux_port.h index ea117860..1334a3ef 100644 --- a/ports/generic/inc/ux_port.h +++ b/ports/generic/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Generic */ -/* 6.1.3 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 12-31-2020 Chaoqiong Xiao Initial Version 6.1.3 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -67,6 +71,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -210,7 +242,7 @@ VOID outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Generic Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Generic Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/linux/gnu/inc/ux_port.h b/ports/linux/gnu/inc/ux_port.h index 36593b5a..fbcd964e 100644 --- a/ports/linux/gnu/inc/ux_port.h +++ b/ports/linux/gnu/inc/ux_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* ux_port.h Linux/GNU */ -/* 6.1.9 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -42,6 +42,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 10-15-2021 Chaoqiong Xiao Initial Version 6.1.9 */ +/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved tx_api.h include and */ +/* typedefs from ux_api.h, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -73,6 +77,34 @@ #include +#if !defined(UX_STANDALONE) +#include "tx_api.h" +#else + +/* VAR types used in UX, + if TX still used, expects tx_api.h included before include this. */ +#if !defined(TX_API_H) && !defined(TX_PORT_H) + +#include +typedef void VOID; +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +typedef uint64_t ULONG64; + +#ifndef ALIGN_TYPE_DEFINED +#define ALIGN_TYPE ULONG +#endif + +#endif +#endif + + /* CPU definition for X86 systems without preemptive timer function. This will make USBX uses the controller for the timer. */ @@ -212,7 +244,7 @@ ULONG outpl(ULONG,ULONG); #ifdef UX_SYSTEM_INIT CHAR _ux_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Linux/GNU Version 6.1.9 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Linux/GNU Version 6.1.10 *"; #else extern CHAR _ux_version_id[]; #endif