diff --git a/README.md b/README.md index d0165cdb..edf9d047 100755 --- a/README.md +++ b/README.md @@ -2,106 +2,105 @@ A high-performance USB host, device, and on-the-go (OTG) embedded stack, Azure RTOS USBX is fully integrated with Azure RTOS ThreadX and available for all Azure RTOS ThreadX–supported processors. Like Azure RTOS ThreadX, Azure RTOS USBX is designed to have a small footprint and high performance, making it ideal for deeply embedded applications that require an interface with USB devices. -## Documentation +Here are the key features and modules of USBX: -Documentation for this library can be found here: http://docs.microsoft.com/azure/rtos/usbx +![USBX Key Features](./docs/usbx-features.png) -# Understanding inter-component dependencies +## Getting Started -The main components of Azure RTOS are each provided in their own repository, but there are dependencies between them--shown in the following graph--that are important to understand when setting up your builds. +Azure RTOS USBX as part of Azure RTOS has been integrated to the semiconductor's SDKs and development environment. You can develop using the tools of choice from [STMicroelectronics](https://www.st.com/content/st_com/en/campaigns/x-cube-azrtos-azure-rtos-stm32.html), [NXP](https://www.nxp.com/design/software/embedded-software/azure-rtos-for-nxp-microcontrollers:AZURE-RTOS), [Renesas](https://github.com/renesas/azure-rtos) and [Microchip](https://mu.microchip.com/get-started-simplifying-your-iot-design-with-azure-rtos). -![dependency graph](docs/deps.png) +We also provide [samples](https://github.com/azure-rtos/samples) using hero development boards from semiconductors you can build and test with. -# Building and using the library +See [Overview of Azure RTOS USBX](https://learn.microsoft.com/azure/rtos/usbx/overview-usbx) for the high-level overview, and all documentation and APIs can be found in: [Azure RTOS USBX documentation](https://learn.microsoft.com/azure/rtos/usbx/). -## Prerequisites +## Repository Structure and Usage -Install the following tools: +### Directory layout -* [CMake](https://cmake.org/download/) version 3.0 or later -* [GCC compilers for arm-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) -* [Ninja](https://ninja-build.org/) + . + ├── cmake # CMakeList files for building the project + ├── common # Core USBX files + ├── ports # Architecture and compiler specific files + ├── samples # Sample codes + ├── support # Misc platform configurations file used by USBX + ├── LICENSE.txt # License terms + ├── LICENSE-HARDWARE.txt # Licensed hardware from semiconductors + ├── CONTRIBUTING.md # Contribution guidance + └── SECURITY.md # Microsoft repo security guidance -## Cloning the repo +### Branches & Releases -```bash -$ git clone https://github.com/azure-rtos/usbx.git -``` +The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.2-rel`. -## Building as a static library +## Component dependencies -Each component of Azure RTOS comes with a composible CMake-based build system that supports many different MCUs and host systems. Integrating any of these components into your device app code is as simple as adding a git submodule and then including it in your build using the CMake command `add_subdirectory()`. +The main components of Azure RTOS are each provided in their own repository, but there are dependencies between them, as shown in the following graph. This is important to understand when setting up your builds. -While the typical usage pattern is to include threadx into your device code source tree to be built & linked with your code, you can compile this project as a standalone static library to confirm your build is set up correctly. +![dependency graph](docs/deps.png) -```bash -$ cmake -Bbuild -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake -GNinja . +> You will have to take the dependency graph above into account when building anything other than ThreadX itself. -$ cmake --build ./build -``` +### Building and using the library -NOTE: You will have to take the dependency graph above into account when building anything other than threadx itself. +Instruction for building the USBX as static library using Arm GNU Toolchain and CMake. If you are using toolchain and IDE from semiconductor, you might follow its own instructions to use Azure RTOS components as explained in the [Getting Started](#getting-started) section. -# Repository Structure and Usage +1. Install the following tools: -## Branches & Releases + * [CMake](https://cmake.org/download/) version 3.0 or later + * [Arm GNU Toolchain for arm-none-eabi](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) + * [Ninja](https://ninja-build.org/) -The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. +1. Build the [ThreadX library](https://github.com/azure-rtos/threadx#building-and-using-the-library) as the dependency. -## Releases +1. Cloning the repo. -Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.0-rel`. + ```bash + $ git clone https://github.com/azure-rtos/usbx.git + ``` -## Directory layout +1. Define the features and addons you need in `ux_user.h` and build together with the component source code. You can refer to [`ux_user_sample.h`](https://github.com/azure-rtos/usbx/blob/master/common/core/inc/ux_user_sample.h) as an example. -``` -- cmake -- common - - inc - - src -- ports - - cortex_m0/gnu - - inc - - src - - cortex_m3/gnu - - inc - - src - - cortex_m4/gnu - - inc - - src - - cortex_m7/gnu - - inc - - src -- samples -``` +1. Building as a static library -# Security + Each component of Azure RTOS comes with a composable CMake-based build system that supports many different MCUs and host systems. Integrating any of these components into your device app code is as simple as adding a git submodule and then including it in your build using the CMake `add_subdirectory()`. -Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device fully meets the evolving security requirements associated with its specific use case. + While the typical usage pattern is to include USBX into your device code source tree to be built & linked with your code, you can compile this project as a standalone static library to confirm your build is set up correctly. + + An example of building the library for Cortex-M4: + + ```bash + $ cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake . + + $ cmake --build ./build + ``` -# Licensing +## Professional support -License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined in the LICENSED-HARDWARE.txt file. If you are using hardware not defined in the LICENSED-HARDWARE.txt file or have licensing questions in general, please contact Microsoft directly at https://aka.ms/azrtos-license. +[Professional support plans](https://azure.microsoft.com/support/options/) are available from Microsoft. For community support and others, see the [Resources](#resources) section below. -# Contribution, feedback, issues, and professional support +## Licensing -If you encounter any bugs, have suggestions for new features, or if you would like to become an active contributor to this project, please follow the instructions provided in the contribution guideline for the corresponding repo. +License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined in the [LICENSED-HARDWARE.txt](./LICENSED-HARDWARE.txt) file. If you are using hardware not listed in the file or having licensing questions in general, please contact Microsoft directly at https://aka.ms/azrtos-license. -For basic support, click Issues in the command bar or post a question to [Stack Overflow](http://stackoverflow.com/questions/tagged/azure-rtos+threadx) using the `threadx` and `azure-rtos` tags. +## Resources -Professional support plans (https://azure.microsoft.com/en-us/support/options/) are available from Microsoft. +The following are references to additional Azure RTOS resources: + +- **Product introduction and white papers**: https://azure.com/rtos +- **General technical questions**: https://aka.ms/QnA/azure-rtos +- **Product issues and bugs, or feature requests**: https://github.com/azure-rtos/usbx/issues +- **Licensing and sales questions**: https://aka.ms/azrtos-license +- **Product roadmap and support policy**: https://aka.ms/azrtos/lts +- **Blogs and videos**: http://msiotblog.com and https://aka.ms/iotshow +- **Azure RTOS TraceX Installer**: https://aka.ms/azrtos-tracex-installer + +You can also check [previous questions](https://stackoverflow.com/questions/tagged/azure-rtos+usbx) or ask new ones on StackOverflow using the `azure-rtos` and `usbx` tags. + +## Security + +Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device fully meets the evolving security requirements associated with its specific use case. -# Additional Resources +## Contribution -The following are references to additional Azure RTOS and Azure IoT in general: -| Content | Link | -|---|---| -| TraceX Installer | https://aka.ms/azrtos-tracex-installer | -| Azure RTOS Documentation and Guides: | https://docs.microsoft.com/azure/rtos | -| Azure RTOS Website: | https://azure.microsoft.com/services/rtos/ | -| Azure RTOS Sales Questions: | https://aka.ms/azrtos-license | -| Azure RTOS Product Support Policy | https://aka.ms/azrtos/lts | -| Azure RTOS Functional Safety Artifacts | https://aka.ms/azrtos/tuv | -| For technical questions check out Microsoft Q/A for Azure IoT | https://aka.ms/QnA/azure-rtos | -| Internet of Things Show for latest announcements and online training | https://aka.ms/iotshow | -| IoT Tech Community | https://aka.ms/community/azure-rtos | +Please follow the instructions provided in the [CONTRIBUTING.md](./CONTRIBUTING.md) for the corresponding repository. diff --git a/common/core/inc/ux_api.h b/common/core/inc/ux_api.h old mode 100755 new mode 100644 index b8f0c6eb..cb83675c --- 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.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -122,6 +122,12 @@ /* added shared device config */ /* descriptor for enum scan, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added some ETH error codes, */ +/* allowed align minimal def, */ +/* added interface instance */ +/* creation strategy control, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -288,8 +294,8 @@ typedef signed char SCHAR; /* Define basic constants for the USBX Stack. */ #define AZURE_RTOS_USBX #define USBX_MAJOR_VERSION 6 -#define USBX_MINOR_VERSION 1 -#define USBX_PATCH_VERSION 12 +#define USBX_MINOR_VERSION 2 +#define USBX_PATCH_VERSION 0 /* Macros for concatenating tokens, where UX_CONCATn concatenates n tokens. */ @@ -1102,7 +1108,6 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_NO_ALIGN 0u #define UX_ALIGN_16 0x0fu -#define UX_ALIGN_MIN 0x0fu #define UX_ALIGN_32 0x1fu #define UX_ALIGN_64 0x3fu #define UX_ALIGN_128 0x7fu @@ -1113,6 +1118,9 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_ALIGN_4096 0xfffu #define UX_SAFE_ALIGN 0xffffffffu #define UX_MAX_SCATTER_GATHER_ALIGNMENT 4096 +#ifndef UX_ALIGN_MIN +#define UX_ALIGN_MIN UX_ALIGN_16 +#endif #define UX_MAX_USB_DEVICES 127 @@ -1483,6 +1491,10 @@ VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, UL #define UX_HOST_CLASS_AUDIO_WRONG_FREQUENCY 0x82 #define UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR 0x90 +#define UX_CLASS_ETH_LINK_STATE_DOWN_ERROR 0x90 +#define UX_CLASS_ETH_PACKET_POOL_ERROR 0x91 +#define UX_CLASS_ETH_PACKET_ERROR 0x92 +#define UX_CLASS_ETH_SIZE_ERROR 0x93 /* Define USBX HCD API function constants. */ @@ -2049,6 +2061,12 @@ typedef struct UX_CONFIGURATION_STRUCT ULONG ux_configuration_iad_protocol; } UX_CONFIGURATION; +#define UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_ALL 0 /* Default: all things created. */ +#define UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED 1 /* Owned: class owned things created. */ +#ifndef UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL +#define UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_ALL +#endif + /* Define USBX Interface Descriptor structure. */ diff --git a/common/core/inc/ux_user_sample.h b/common/core/inc/ux_user_sample.h index 0df602e1..72a7e5e8 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.12 */ +/* 6.2.0 */ /* */ /* AUTHOR */ /* */ @@ -83,6 +83,12 @@ /* added device CDC_ACM and */ /* printer write auto ZLP, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* deprecated ECM pool option, */ +/* added align minimal config, */ +/* added host stack instance */ +/* creation strategy control, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -116,6 +122,10 @@ /* Override various options with default values already assigned in ux_api.h or ux_port.h. Please also refer to ux_port.h for descriptions on each of these options. */ +/* Defined, this value represents minimal allocated memory alignment in number of bytes. + The default is UX_ALIGN_16 (0x0f) to align allocated memory to 16 bytes. */ +/* #define UX_ALIGN_MIN UX_ALIGN_16 */ + /* Defined, this value represents how many ticks per seconds for a specific hardware platform. The default is 1000 indicating 1 tick per millisecond. */ @@ -317,7 +327,9 @@ /* #define UX_HOST_CLASS_CDC_ECM_PACKET_POOL_INSTANCE_WAIT 10 */ -/* Defined, this enables CDC ECM class to use the packet pool from NetX instance. */ +/* Defined, this enables CDC ECM class to use the packet pool from NetX instance. + It's deprecated, packet pool from NetX instance is always used now. + */ /* #define UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX */ @@ -427,6 +439,15 @@ /* Defined, host audio optional interrupt endpoint is support. */ /* #define UX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT */ +/* Defined, this value controls host configuration instance creation, include all + interfaces and endpoints physical resources. + Possible settings: + UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_ALL (0) - The default, create all inside configuration. + UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED (1) - Create things owned by class driver. + Not defined, default setting is applied. + */ +/* #define UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED */ + /* Defined, this value will only enable the host side of usbx. */ /* #define UX_HOST_SIDE_ONLY */ diff --git a/common/core/src/ux_host_stack_configuration_instance_create.c b/common/core/src/ux_host_stack_configuration_instance_create.c index 678b5b5b..7d44c07c 100644 --- a/common/core/src/ux_host_stack_configuration_instance_create.c +++ b/common/core/src/ux_host_stack_configuration_instance_create.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_configuration_instance_create PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,10 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added interface instance */ +/* creation strategy control, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_stack_configuration_instance_create(UX_CONFIGURATION *configuration) @@ -93,15 +97,21 @@ UINT status; /* Check if we are dealing with the first alternate setting. */ if (interface_ptr -> ux_interface_descriptor.bAlternateSetting == 0) { - /* Create the interface. */ - status = _ux_host_stack_interface_instance_create(interface_ptr); - - /* Check status, the controller may have refused the endpoint creation. */ - if (status != UX_SUCCESS) - - /* An error occurred. The interface cannot be mounted. */ - return(status); - + +#if UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED + + /* Create the interface, if it's usable. */ + if (interface_ptr -> ux_interface_class || configuration -> ux_configuration_device -> ux_device_class) +#endif + { + status = _ux_host_stack_interface_instance_create(interface_ptr); + + /* Check status, the controller may have refused the endpoint creation. */ + if (status != UX_SUCCESS) + + /* An error occurred. The interface cannot be mounted. */ + return(status); + } } /* Next interface. */ diff --git a/common/core/src/ux_host_stack_configuration_instance_delete.c b/common/core/src/ux_host_stack_configuration_instance_delete.c index 9413c697..5834e0d4 100644 --- a/common/core/src/ux_host_stack_configuration_instance_delete.c +++ b/common/core/src/ux_host_stack_configuration_instance_delete.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_configuration_instance_delete PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,10 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added interface instance */ +/* creation strategy control, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_stack_configuration_instance_delete(UX_CONFIGURATION *configuration) @@ -102,7 +106,13 @@ ULONG current_alternate_setting; if (interface_ptr -> ux_interface_descriptor.bAlternateSetting == current_alternate_setting) { - _ux_host_stack_interface_instance_delete(interface_ptr); + +#if UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED + + /* If interface is usable, remove physical creates. */ + if (interface_ptr -> ux_interface_class || configuration -> ux_configuration_device -> ux_device_class) +#endif + _ux_host_stack_interface_instance_delete(interface_ptr); } interface_ptr = interface_ptr -> ux_interface_next_interface; diff --git a/common/core/src/ux_host_stack_hcd_thread_entry.c b/common/core/src/ux_host_stack_hcd_thread_entry.c old mode 100755 new mode 100644 diff --git a/common/core/src/ux_host_stack_hcd_unregister.c b/common/core/src/ux_host_stack_hcd_unregister.c old mode 100755 new mode 100644 diff --git a/common/core/src/ux_host_stack_rh_change_process.c b/common/core/src/ux_host_stack_rh_change_process.c old mode 100755 new mode 100644 diff --git a/common/core/src/ux_host_stack_tasks_run.c b/common/core/src/ux_host_stack_tasks_run.c index a867411c..6363268b 100644 --- a/common/core/src/ux_host_stack_tasks_run.c +++ b/common/core/src/ux_host_stack_tasks_run.c @@ -44,7 +44,7 @@ static inline VOID _ux_host_stack_pending_transfers_run(VOID); /* FUNCTION RELEASE */ /* */ /* _ux_host_stack_tasks_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -105,6 +105,11 @@ static inline VOID _ux_host_stack_pending_transfers_run(VOID); /* used shared descriptor in */ /* device instance for enum, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved internal logic, */ +/* fixed activation issue on */ +/* no class linked interfaces, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_stack_tasks_run(VOID) @@ -376,7 +381,12 @@ UX_INTERFACE *interface_inst; 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); + + /* If there is no class linked, just next state. */ + if (command -> ux_host_class_command_class_ptr != UX_NULL) + status = command -> ux_host_class_command_class_ptr -> ux_host_class_entry_function(command); + else + status = UX_STATE_NEXT; /* No wait command or ready for next state. */ if (status == UX_FUNCTION_NOT_SUPPORTED || @@ -435,6 +445,7 @@ UX_TRANSFER *trans; UX_CONFIGURATION *configuration; UX_HOST_CLASS_COMMAND class_command; UCHAR *buffer; +INT immediate_state = UX_TRUE; /* Check if the device enumeration should be processed. */ if ((device -> ux_device_flags & UX_DEVICE_FLAG_ENUM) == 0) @@ -457,7 +468,7 @@ UCHAR *buffer; } UX_RESTORE - while (1) + while (immediate_state) { switch (device -> ux_device_enum_state) { @@ -911,12 +922,17 @@ UCHAR *buffer; 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) + + /* If there class linked, start activation. */ + if (class_command.ux_host_class_command_class_ptr != UX_NULL) { - device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY; - continue; + 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. */ @@ -1078,8 +1094,11 @@ UCHAR *buffer; device -> ux_device_enum_state = UX_STATE_RESET; } - /* Run once anyway. */ - break; + /* Invalid unhandled state. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HOST_STACK, UX_INVALID_STATE); + + /* Break the immediate state loop. */ + immediate_state = UX_FALSE; } } 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 58591e96..ad1c5f76 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.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,8 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* added standalone support, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_stack_transfer_request_abort(UX_TRANSFER *transfer_request) @@ -104,14 +106,17 @@ ULONG completion_code; /* Check pending transaction. */ if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) { - + /* Send the abort command to the controller. */ hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_ABORT, transfer_request); /* Save the completion code since we're about to set it to ABORT. The reason we can't just assume its value is PENDING is that in between the completion code check and this line, it's possible that the transfer - completed, which would've changed the completion code to SUCCESS. + completed (by HCD function call below, or ISR), which would've + changed the completion code to SUCCESS and put the semaphore. + Even it's recommended to keep completion code untouched to let things + changed later here. Such a case is valid, and we want to make sure we don't put() the transfer request's semaphore again. */ completion_code = transfer_request -> ux_transfer_request_completion_code; diff --git a/common/core/src/ux_utility_delay_ms.c b/common/core/src/ux_utility_delay_ms.c old mode 100755 new mode 100644 diff --git a/common/usbx_device_classes/CMakeLists.txt b/common/usbx_device_classes/CMakeLists.txt index f3c38671..5291d4ba 100644 --- a/common/usbx_device_classes/CMakeLists.txt +++ b/common/usbx_device_classes/CMakeLists.txt @@ -10,14 +10,17 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_set.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_feedback_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_frame_write.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_send.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_interrupt_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_free.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_reception_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read16.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read24.c @@ -30,6 +33,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_commit.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_task_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_auto_seq_done.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_ccid_auto_seq_start.c @@ -144,9 +149,11 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_initialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_ioctl.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_read_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_soft_reset.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_printer_write_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_activate.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkin_thread.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkout_thread.c @@ -201,13 +208,16 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_max_payload_get.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_payload_free.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_read_thread_entry.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_reception_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_stream_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_tasks_run.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_transmission_start.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_uninitialize.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_payload_commit.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_task_function.c ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_video_write_thread_entry.c # {{END_TARGET_SOURCES}} diff --git a/common/usbx_device_classes/inc/ux_device_class_audio.h b/common/usbx_device_classes/inc/ux_device_class_audio.h index 8ce47fa0..4cc5be3a 100644 --- a/common/usbx_device_classes/inc/ux_device_class_audio.h +++ b/common/usbx_device_classes/inc/ux_device_class_audio.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_audio.h PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -59,6 +59,9 @@ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* added interrupt support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -310,6 +313,17 @@ extern "C" { #define UX_DEVICE_CLASS_AUDIO_IOCTL_GET_ARG 1 +/* Define Audio Class Task states. */ +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT (UX_STATE_STEP + 2) + +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT (UX_STATE_STEP + 2) + +#define UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT (UX_STATE_STEP + 1) /* Define Audio Class callback structure. */ @@ -336,11 +350,20 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS_STRUCT typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER_STRUCT { +#if !defined(UX_DEVICE_STANDALONE) ULONG ux_device_class_audio_stream_parameter_thread_stack_size; VOID (*ux_device_class_audio_stream_parameter_thread_entry)(ULONG id); +#else + UINT (*ux_device_class_audio_stream_parameter_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); +#endif + #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) ULONG ux_device_class_audio_stream_parameter_feedback_thread_stack_size; VOID (*ux_device_class_audio_stream_parameter_feedback_thread_entry)(ULONG id); +#else + UINT (*ux_device_class_audio_stream_parameter_feedback_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); +#endif #endif UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_parameter_callbacks; @@ -386,6 +409,10 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_audio_stream_feedback_thread_stack; UX_THREAD ux_device_class_audio_stream_feedback_thread; +#else + UINT (*ux_device_class_audio_stream_feedback_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); + UINT ux_device_class_audio_stream_feedback_task_state; + UINT ux_device_class_audio_stream_feedback_task_status; #endif #endif @@ -394,11 +421,16 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_audio_stream_thread_stack; UX_THREAD ux_device_class_audio_stream_thread; +#else + UINT (*ux_device_class_audio_stream_task_function)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT*); + UINT ux_device_class_audio_stream_task_state; + UINT ux_device_class_audio_stream_task_status; #endif UCHAR *ux_device_class_audio_stream_buffer; ULONG ux_device_class_audio_stream_buffer_size; ULONG ux_device_class_audio_stream_frame_buffer_size; + ULONG ux_device_class_audio_stream_buffer_error_count; UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_transfer_pos; UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_access_pos; @@ -429,6 +461,9 @@ typedef struct UX_DEVICE_CLASS_AUDIO_STRUCT #if !defined(UX_DEVICE_STANDALONE) UX_SEMAPHORE ux_device_class_audio_status_semaphore; UX_MUTEX ux_device_class_audio_status_mutex; +#else + UINT ux_device_class_audio_interrupt_task_state; + UINT ux_device_class_audio_interrupt_task_status; #endif #endif } UX_DEVICE_CLASS_AUDIO; @@ -452,7 +487,8 @@ UINT _ux_device_class_audio_stream_get(UX_DEVICE_CLASS_AUDIO *audio, ULONG st VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream); VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream); - +UINT _ux_device_class_audio_write_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); +UINT _ux_device_class_audio_read_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *audio); UINT _ux_device_class_audio_sample_read8(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *sample); UINT _ux_device_class_audio_sample_read16(UX_DEVICE_CLASS_AUDIO_STREAM *audio, USHORT *sample); @@ -469,13 +505,18 @@ UINT _ux_device_class_audio_write_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *aud UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM *audio, ULONG length); VOID _ux_device_class_audio_feedback_thread_entry(ULONG audio_stream); +UINT _ux_device_class_audio_feedback_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream); UINT _ux_device_class_audio_feedback_set(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *encoded_feedback); UINT _ux_device_class_audio_feedback_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *encoded_feedback); ULONG _ux_device_class_audio_speed_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio); VOID _ux_device_class_audio_interrupt_thread_entry(ULONG audio_inst); +UINT _ux_device_class_audio_interrupt_task_function(UX_DEVICE_CLASS_AUDIO *audio); UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data); +#if defined(UX_DEVICE_STANDALONE) +UINT _ux_device_class_audio_tasks_run(VOID *instance); +#endif /* Define Device Class Audio API prototypes. */ @@ -484,6 +525,9 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA #define ux_device_class_audio_read_thread_entry _ux_device_class_audio_read_thread_entry #define ux_device_class_audio_write_thread_entry _ux_device_class_audio_write_thread_entry +#define ux_device_class_audio_read_task_function _ux_device_class_audio_read_task_function +#define ux_device_class_audio_write_task_function _ux_device_class_audio_write_task_function + #define ux_device_class_audio_stream_get _ux_device_class_audio_stream_get #define ux_device_class_audio_reception_start _ux_device_class_audio_reception_start @@ -505,6 +549,7 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA #define ux_device_class_audio_speed_get _ux_device_class_audio_speed_get #define ux_device_class_audio_feedback_thread_entry _ux_device_class_audio_feedback_thread_entry +#define ux_device_class_audio_feedback_task_function _ux_device_class_audio_feedback_task_function #define ux_device_class_audio_feedback_get _ux_device_class_audio_feedback_get #define ux_device_class_audio_feedback_set _ux_device_class_audio_feedback_set diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h index 3f662d8a..54f3ac77 100644 --- a/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_cdc_ecm.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added wait definitions, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -274,6 +277,12 @@ VOID _ux_network_driver_link_down(VOID *ux_network_handle); #define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT 1000 #endif +#ifndef UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT +#define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT 1000 +#endif + +#define UX_DEVICE_CLASS_CDC_ECM_LINK_CHECK_WAIT 10 + /* Define Slave CDC_ECM Class Calling Parameter structure */ typedef struct UX_SLAVE_CLASS_CDC_ECM_PARAMETER_STRUCT @@ -316,7 +325,6 @@ typedef struct UX_SLAVE_CLASS_CDC_ECM_STRUCT UCHAR ux_slave_class_cdc_ecm_remote_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; ULONG ux_slave_class_cdc_ecm_nx_ip_address; ULONG ux_slave_class_cdc_ecm_nx_ip_network_mask; - UCHAR *ux_slave_class_cdc_ecm_pool_memory; #if !defined(UX_DEVICE_STANDALONE) NX_IP *ux_slave_class_cdc_ecm_nx_ip; @@ -324,7 +332,7 @@ typedef struct UX_SLAVE_CLASS_CDC_ECM_STRUCT NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue; NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue_tail; NX_PACKET *ux_slave_class_cdc_ecm_receive_queue; - NX_PACKET_POOL ux_slave_class_cdc_ecm_packet_pool; + NX_PACKET_POOL *ux_slave_class_cdc_ecm_packet_pool; #endif #if !defined(UX_DEVICE_STANDALONE) diff --git a/common/usbx_device_classes/inc/ux_device_class_printer.h b/common/usbx_device_classes/inc/ux_device_class_printer.h index a77aff51..52ae8ce5 100644 --- a/common/usbx_device_classes/inc/ux_device_class_printer.h +++ b/common/usbx_device_classes/inc/ux_device_class_printer.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_printer.h PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* resulting in version 6.1.11 */ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -92,6 +95,16 @@ extern "C" { #define UX_DEVICE_CLASS_PRINTER_IOCTL_READ_TIMEOUT_SET 2 #define UX_DEVICE_CLASS_PRINTER_IOCTL_WRITE_TIMEOUT_SET 3 +#if defined(UX_DEVICE_STANDALONE) + +/* Printer read state machine states. */ +#define UX_DEVICE_CLASS_PRINTER_READ_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_PRINTER_READ_WAIT (UX_STATE_STEP + 2) + +/* Printer write state machine states. */ +#define UX_DEVICE_CLASS_PRINTER_WRITE_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_PRINTER_WRITE_WAIT (UX_STATE_STEP + 2) +#endif /* Define Device Printer Class Calling Parameter structure */ @@ -117,6 +130,21 @@ typedef struct UX_DEVICE_CLASS_PRINTER_STRUCT #if !defined(UX_DEVICE_STANDALONE) UX_MUTEX ux_device_class_printer_endpoint_out_mutex; UX_MUTEX ux_device_class_printer_endpoint_in_mutex; +#else + UCHAR *ux_device_class_printer_read_buffer; + ULONG ux_device_class_printer_read_requested_length; + ULONG ux_device_class_printer_read_transfer_length; + ULONG ux_device_class_printer_read_actual_length; + UINT ux_device_class_printer_read_status; + UINT ux_device_class_printer_read_state; + + UCHAR *ux_device_class_printer_write_buffer; + ULONG ux_device_class_printer_write_transfer_length; + ULONG ux_device_class_printer_write_host_length; + ULONG ux_device_class_printer_write_requested_length; + ULONG ux_device_class_printer_write_actual_length; + UINT ux_device_class_printer_write_status; + UINT ux_device_class_printer_write_state; #endif } UX_DEVICE_CLASS_PRINTER; @@ -139,7 +167,12 @@ UINT _ux_device_class_printer_read(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buf UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioctl_function, VOID *parameter); - +#if defined(UX_DEVICE_STANDALONE) +UINT _ux_device_class_printer_write_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_printer_read_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +#endif /* Define Device Printer Class API prototypes. */ @@ -148,6 +181,11 @@ UINT _ux_device_class_printer_ioctl(UX_DEVICE_CLASS_PRINTER *printer, ULONG ioc #define ux_device_class_printer_write _ux_device_class_printer_write #define ux_device_class_printer_ioctl _ux_device_class_printer_ioctl +#if defined(UX_DEVICE_STANDALONE) +#define ux_device_class_printer_read_run _ux_device_class_printer_read_run +#define ux_device_class_printer_write_run _ux_device_class_printer_write_run +#endif + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/common/usbx_device_classes/inc/ux_device_class_rndis.h b/common/usbx_device_classes/inc/ux_device_class_rndis.h index 7ac55d82..abcd8332 100644 --- a/common/usbx_device_classes/inc/ux_device_class_rndis.h +++ b/common/usbx_device_classes/inc/ux_device_class_rndis.h @@ -24,7 +24,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_rndis.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -52,6 +52,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added wait and length DEFs, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -478,6 +481,16 @@ VOID _ux_network_driver_link_down(VOID *ux_network_handle); #define UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT 10 #endif +#ifndef UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT +#define UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT 100 +#endif + +/* Calculate message buffer length (not overflow). */ +#define UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH (UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) +#if UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH > UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#error "Error: the maximum-sized RNDIS response cannot fit inside the control endpoint's data buffer. Increase UX_SLAVE_REQUEST_DATA_MAX_LENGTH." +#endif + /* Calculate response buffer length. */ #define UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_LIST_LENGTH * 4) #define UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH) @@ -544,7 +557,6 @@ typedef struct UX_SLAVE_CLASS_RNDIS_STRUCT ULONG ux_slave_class_rndis_statistics_xmit_more_collisions; UCHAR ux_slave_class_rndis_local_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; UCHAR ux_slave_class_rndis_remote_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; - UCHAR *ux_slave_class_rndis_pool_memory; ULONG ux_slave_class_rndis_nx_ip_address; ULONG ux_slave_class_rndis_nx_ip_network_mask; @@ -553,7 +565,7 @@ typedef struct UX_SLAVE_CLASS_RNDIS_STRUCT NX_INTERFACE *ux_slave_class_rndis_nx_interface; NX_PACKET *ux_slave_class_rndis_xmit_queue; NX_PACKET *ux_slave_class_rndis_receive_queue; - NX_PACKET_POOL ux_slave_class_rndis_packet_pool; + NX_PACKET_POOL *ux_slave_class_rndis_packet_pool; #endif #if !defined(UX_DEVICE_STANDALONE) diff --git a/common/usbx_device_classes/inc/ux_device_class_video.h b/common/usbx_device_classes/inc/ux_device_class_video.h index 4c6d3e8e..9851532c 100644 --- a/common/usbx_device_classes/inc/ux_device_class_video.h +++ b/common/usbx_device_classes/inc/ux_device_class_video.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_device_class_video.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -41,6 +41,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -508,6 +511,12 @@ typedef struct UX_DEVICE_CLASS_VIDEO_PAYLOAD_HEADER_STRUCT #define UX_DEVICE_CLASS_VIDEO_STREAM_ERROR_CODE_STILL_IMAGE_CAPTURE_ERROR 7 +/* Define Video Class Task states. */ +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP (UX_STATE_RESET) +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_START (UX_STATE_STEP + 1) +#define UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT (UX_STATE_STEP + 2) + + /* Define Video Class callback structure. */ struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT; @@ -541,8 +550,12 @@ typedef struct UX_DEVICE_CLASS_VIDEO_PAYLOAD_STRUCT typedef struct UX_DEVICE_CLASS_VIDEO_STREAM_PARAMETER_STRUCT { +#if defined(UX_DEVICE_STANDALONE) + UINT (*ux_device_class_video_stream_parameter_task_function)(struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT*); +#else ULONG ux_device_class_video_stream_parameter_thread_stack_size; VOID (*ux_device_class_video_stream_parameter_thread_entry)(ULONG id); +#endif UX_DEVICE_CLASS_VIDEO_STREAM_CALLBACKS ux_device_class_video_stream_parameter_callbacks; ULONG ux_device_class_video_stream_parameter_max_payload_buffer_size; @@ -572,8 +585,13 @@ typedef struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT #if !defined(UX_DEVICE_STANDALONE) UCHAR *ux_device_class_video_stream_thread_stack; UX_THREAD ux_device_class_video_stream_thread; +#else + UINT (*ux_device_class_video_stream_task_function)(struct UX_DEVICE_CLASS_VIDEO_STREAM_STRUCT*); + UINT ux_device_class_video_stream_task_state; + UINT ux_device_class_video_stream_task_status; #endif + ULONG ux_device_class_video_stream_buffer_error_count; UCHAR *ux_device_class_video_stream_buffer; ULONG ux_device_class_video_stream_buffer_size; ULONG ux_device_class_video_stream_payload_buffer_size; @@ -636,6 +654,9 @@ UINT _ux_device_class_video_transmission_start(UX_DEVICE_CLASS_VIDEO_STREAM * UINT _ux_device_class_video_write_payload_get(UX_DEVICE_CLASS_VIDEO_STREAM *video, UCHAR **buffer, ULONG *max_length); UINT _ux_device_class_video_write_payload_commit(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG length); +UINT _ux_device_class_video_tasks_run(VOID *instance); +UINT _ux_device_class_video_read_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream); +UINT _ux_device_class_video_write_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream); /* Define Video Class API prototypes. */ @@ -663,6 +684,9 @@ UINT _ux_device_class_video_write_payload_commit(UX_DEVICE_CLASS_VIDEO_STREAM #define ux_device_class_video_ioctl _ux_device_class_video_ioctl +#define ux_device_class_video_read_task_function _ux_device_class_video_read_task_function +#define ux_device_class_video_write_task_function _ux_device_class_video_write_task_function + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_activate.c b/common/usbx_device_classes/src/ux_device_class_audio_activate.c index 53163cfe..2f9b89d7 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* names conflict C++ keyword, */ /* added interrupt support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -166,6 +169,12 @@ ULONG stream_index; /* Store the class instance into the interface. */ stream_interface -> ux_slave_interface_class_instance = (VOID *)audio; +#if defined(UX_DEVICE_STANDALONE) + + /* Reset stream task state. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_state = UX_SUCCESS; +#endif } /* If there is a activate function call it. */ diff --git a/common/usbx_device_classes/src/ux_device_class_audio_change.c b/common/usbx_device_classes/src/ux_device_class_audio_change.c index 35d4a3ae..9ac4e679 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_change.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_change PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* rx full packet for */ /* feedback, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_change(UX_SLAVE_CLASS_COMMAND *command) @@ -137,8 +140,9 @@ ULONG endpoint_dir; /* Parse all endpoints. */ #if defined(UX_DEVICE_STANDALONE) - /* Standalone mode not supported. */ - endpoint_dir = 0; + endpoint_dir = (stream -> ux_device_class_audio_stream_task_function == + _ux_device_class_audio_read_task_function) ? + UX_ENDPOINT_OUT: UX_ENDPOINT_IN; #else endpoint_dir = (stream -> ux_device_class_audio_stream_thread.tx_thread_entry == @@ -229,6 +233,15 @@ ULONG endpoint_dir; return(UX_DESCRIPTOR_CORRUPTED); } +#if defined(UX_DEVICE_STANDALONE) + + /* Reset background transfer state. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; +#endif + + /* Now reset payload buffer error count. */ + stream -> ux_device_class_audio_stream_buffer_error_count = 0; + /* Now reset frame buffers. */ frame_buffer = stream -> ux_device_class_audio_stream_buffer; while(frame_buffer < stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) @@ -243,7 +256,7 @@ ULONG endpoint_dir; } stream -> ux_device_class_audio_stream_transfer_pos = stream -> ux_device_class_audio_stream_access_pos; -#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) && !defined(UX_DEVICE_STANDALONE) /* If feedback supported, resume the thread. */ if (stream -> ux_device_class_audio_stream_feedback_thread_stack) diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c new file mode 100644 index 00000000..8bcf8573 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_task_function.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) && defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_feedback_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is background task of ISO OUT/IN (feedback of IN/OUT) */ +/* for the Audio class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to audio stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No feedback transfer running */ +/* UX_STATE_WAIT Feedback transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class (task) */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_feedback_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + +UINT status; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +ULONG transfer_length; + + + /* Get stack device instance. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get endpoint instance. */ + endpoint = stream -> ux_device_class_audio_stream_feedback; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Length is pre-set on interface alternate setting activate. */ + transfer_length = transfer -> ux_slave_transfer_request_requested_length; + + switch (stream -> ux_device_class_audio_stream_feedback_task_state) + { + case UX_STATE_RESET: + stream -> ux_device_class_audio_stream_feedback_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT; + stream -> ux_device_class_audio_stream_feedback_task_status = UX_TRANSFER_NO_ANSWER; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT: + + /* Issue transfer request. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Any error or success case. */ + if (status < UX_STATE_NEXT) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_feedback_task_status = transfer -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + stream -> ux_device_class_audio_stream_feedback_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_FEEDBACK_RW_WAIT; + stream -> ux_device_class_audio_stream_feedback_task_status = transfer -> ux_slave_transfer_request_completion_code; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: + stream -> ux_device_class_audio_stream_feedback_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_feedback_task_status = UX_INVALID_STATE; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c index 88525f1b..f71c0bd7 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_feedback_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_feedback_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,11 +70,17 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_feedback_thread_entry(ULONG audio_stream) { - +#if defined(UX_DEVICE_STANDALONE) + UX_PARAMETER_NOT_USED(audio_stream); + return; +#else UINT status; UX_DEVICE_CLASS_AUDIO_STREAM *stream; UX_SLAVE_DEVICE *device; @@ -128,5 +134,6 @@ ULONG transfer_length; /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ _ux_utility_thread_suspend(&stream -> ux_device_class_audio_stream_feedback_thread); } +#endif } #endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_initialize.c b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c index 4887494f..4ba297a3 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -84,14 +84,13 @@ /* added interrupt support, */ /* refined internal logic, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UINT status = UX_SUCCESS; UX_DEVICE_CLASS_AUDIO *audio; @@ -153,8 +152,7 @@ ULONG i; audio_parameter -> ux_device_class_audio_parameter_status_size; audio -> ux_device_class_audio_status_queue_bytes = memory_size; -#if defined(UX_DEVICE_STANDALONE) -#else +#if !defined(UX_DEVICE_STANDALONE) if (UX_OVERFLOW_CHECK_ADD_ULONG(memory_size, UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE)) { _ux_utility_memory_free(audio); @@ -217,6 +215,15 @@ ULONG i; audio -> ux_device_class_audio_status_queue = (UCHAR *)audio_class -> ux_slave_class_thread_stack + UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE; +#else + audio -> ux_device_class_audio_status_queue = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (audio -> ux_device_class_audio_status_queue == UX_NULL) + { + _ux_utility_memory_free(audio); + return(UX_MEMORY_INSUFFICIENT); + } #endif #endif @@ -268,6 +275,8 @@ ULONG i; stream -> ux_device_class_audio_stream_transfer_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)stream -> ux_device_class_audio_stream_buffer; stream -> ux_device_class_audio_stream_access_pos = stream -> ux_device_class_audio_stream_transfer_pos; +#if !defined(UX_DEVICE_STANDALONE) + /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size == 0) memory_size = UX_DEVICE_CLASS_AUDIO_FEEDBACK_THREAD_STACK_SIZE; @@ -298,13 +307,19 @@ ULONG i; } UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_thread), stream) +#else + + /* Save task function for streaming. */ + stream -> ux_device_class_audio_stream_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_task_function; +#endif #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) + /* Check entry to confirm feedback is supported. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_entry) { - /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_stack_size == 0) memory_size = UX_THREAD_STACK_SIZE; @@ -336,6 +351,14 @@ ULONG i; UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_feedback_thread), stream) } +#else + if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function) + { + + /* Save task function for streaming. */ + stream -> ux_device_class_audio_stream_feedback_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function; + } +#endif #endif /* Save callbacks. */ @@ -365,6 +388,12 @@ ULONG i; &audio_parameter -> ux_device_class_audio_parameter_callbacks, sizeof(UX_DEVICE_CLASS_AUDIO_CALLBACKS)); /* Use case of memcpy is verified. */ +#if defined(UX_DEVICE_STANDALONE) + + /* Link task function. */ + audio_class -> ux_slave_class_task_function = _ux_device_class_audio_tasks_run; +#endif + /* Return completion status. */ return(UX_SUCCESS); } @@ -377,24 +406,27 @@ ULONG i; for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) { #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_audio_stream_feedback_thread_stack) { _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_feedback_thread); _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack); } #endif +#endif +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_audio_stream_thread_stack) { _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_thread); _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); } +#endif if (stream -> ux_device_class_audio_stream_buffer) _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer); stream ++; } #if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) -#if defined(UX_DEVICE_STANDALONE) -#else +#if !defined(UX_DEVICE_STANDALONE) if (audio_class -> ux_slave_class_thread_stack) { _ux_device_thread_delete(&audio_class -> ux_slave_class_thread); @@ -403,10 +435,14 @@ ULONG i; _ux_device_semaphore_delete(&audio -> ux_device_class_audio_status_semaphore); _ux_device_mutex_delete(&audio -> ux_device_class_audio_status_mutex); } +#else + if (audio -> ux_device_class_audio_status_queue) + { + _ux_utility_memory_free(audio -> ux_device_class_audio_status_queue); + } #endif #endif _ux_utility_memory_free(audio); return(status); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c index 72c51fba..eb5d4387 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_send.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_interrupt_send PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data) @@ -77,11 +80,6 @@ UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHA UX_PARAMETER_NOT_USED(int_data); return(UX_FUNCTION_NOT_SUPPORTED); #else -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(audio); - UX_PARAMETER_NOT_USED(int_data); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_DEVICE *device; UX_SLAVE_ENDPOINT *endpoint; @@ -169,5 +167,4 @@ ULONG i; /* Return success. */ return(UX_SUCCESS); #endif -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c new file mode 100644 index 00000000..eeac5c25 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_interrupt_task_function.c @@ -0,0 +1,198 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + +#if defined(UX_DEVICE_STANDALONE) && defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_interrupt_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is task of INTERRUPT IN from the Audio class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio instance */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* UX_STATE_IDLE No interrupt transfer running */ +/* UX_STATE_WAIT Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_stack_transfer_run Run Transfer state machine */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class (task) */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_interrupt_task_function(UX_DEVICE_CLASS_AUDIO *audio) +{ + +UINT status; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *buff; + + + /* Get stack device instance. */ + device = audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get endpoint instance. */ + endpoint = audio -> ux_device_class_audio_interrupt; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + return(UX_STATE_IDLE); + } + + /* No packet in queue */ + if (audio -> ux_device_class_audio_status_queued == 0) + { + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_TRANSFER_NOT_READY; + return(UX_STATE_EXIT); + } + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(audio -> ux_device_class_audio_interrupt_task_state) + { + case UX_STATE_RESET: + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_START; + audio -> ux_device_class_audio_interrupt_task_status = UX_TRANSFER_NO_ANSWER; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_INTERRUPT_START: + if (audio -> ux_device_class_audio_status_size > transfer -> ux_slave_transfer_request_transfer_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_ERROR; + return(UX_STATE_EXIT); + } + + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + audio -> ux_device_class_audio_status_tail, audio -> ux_device_class_audio_status_size); /* Use case of memcpy is verified. */ + + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT; + + /* Fall through. */ + case UX_DEVICE_CLASS_AUDIO_INTERRUPT_WAIT: + + /* Start frame transfer anyway. */ + status = _ux_device_stack_transfer_run(transfer, audio -> ux_device_class_audio_status_size, + audio -> ux_device_class_audio_status_size); + + /* Any error or success case. */ + if (status < UX_STATE_NEXT) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = + transfer -> ux_slave_transfer_request_completion_code; + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + buff = audio -> ux_device_class_audio_status_tail; + buff += audio -> ux_device_class_audio_status_size; + + if (buff >= (audio -> ux_device_class_audio_status_queue + audio -> ux_device_class_audio_status_queue_bytes)) + buff = audio -> ux_device_class_audio_status_queue; + + audio -> ux_device_class_audio_status_tail = buff; + audio -> ux_device_class_audio_status_queued -= audio -> ux_device_class_audio_status_size; + audio -> ux_device_class_audio_interrupt_task_state = UX_DEVICE_CLASS_AUDIO_INTERRUPT_START; + audio -> ux_device_class_audio_interrupt_task_status = + transfer -> ux_slave_transfer_request_completion_code; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + audio -> ux_device_class_audio_interrupt_task_state = UX_STATE_RESET; + audio -> ux_device_class_audio_interrupt_task_status = UX_INVALID_STATE; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c new file mode 100644 index 00000000..03d43d89 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_task_function.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_read_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio stream read. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to audio stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_read_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG max_packet_size; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_audio_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, reset transfer and start polling. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT; + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Run transfer state machine. */ + max_packet_size = endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length; + status = _ux_device_stack_transfer_run(transfer, max_packet_size, max_packet_size); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Frame received, log it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = actual_length; + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_pos = 0; + _ux_utility_memory_copy(stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, + transfer -> ux_slave_transfer_request_data_pointer, + actual_length); /* Use case of memcpy is verified. */ + + /* For simple, do not advance the transfer position if there is overflow. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Check overflow! */ + if (next_frame -> ux_device_class_audio_frame_length > 0) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + else + + /* Update transfer position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c index 60460511..8af97f0e 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_read_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream) @@ -133,6 +136,7 @@ ULONG actual_length; /* Error notification! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + stream -> ux_device_class_audio_stream_buffer_error_count ++; break; } @@ -159,6 +163,7 @@ ULONG actual_length; /* Error notification! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; } else diff --git a/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c index 120eb1ea..078ce81e 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_reception_start PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -103,7 +106,15 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length > 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start read task. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; +#else + /* Start read thread. */ _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); +#endif return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c new file mode 100644 index 00000000..2518ef26 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_tasks_run.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_tasks_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_audio_stream_task_function) */ +/* Run stream task */ +/* (ux_device_class_audio_stream_feedback_task_function) */ +/* Run stream feedback task */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_tasks_run(VOID *instance) +{ +UX_SLAVE_DEVICE *device; +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +ULONG stream_index; +UINT status; +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) +ULONG interrupt_running_count = 0; +#endif +ULONG stream_running_count = 0; +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) +ULONG feedback_running_count = 0; +#endif + + /* Get audio instance. */ + audio = (UX_DEVICE_CLASS_AUDIO *) instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return(UX_STATE_EXIT); + +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) + + /* Run audio status tasks. */ + status = _ux_device_class_audio_interrupt_task_function(audio); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + interrupt_running_count++; +#endif + + for (stream_index = 0; + stream_index < audio -> ux_device_class_audio_streams_nb; + stream_index ++) + { + stream = &audio -> ux_device_class_audio_streams[stream_index]; + status = stream -> ux_device_class_audio_stream_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + stream_running_count ++; + +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + if (stream -> ux_device_class_audio_stream_feedback_task_function != UX_NULL) + { + status = stream -> ux_device_class_audio_stream_feedback_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + feedback_running_count ++; + } +#endif + } + + if ((stream_running_count > 0) +#if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT) + || (interrupt_running_count > 0) +#endif +#if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT) + || (feedback_running_count > 0) +#endif + ) + { + return UX_STATE_WAIT; + } + else + { + return UX_STATE_IDLE; + } +} + +#endif \ No newline at end of file diff --git a/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c index 050390c9..69b58c50 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_transmission_start PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_audio_transmission_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) @@ -103,7 +106,15 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length == 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start write task. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; +#else + /* Start write thread. */ _ux_device_thread_resume(&stream -> ux_device_class_audio_stream_thread); +#endif return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c b/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c new file mode 100644 index 00000000..2c30a3c3 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_task_function.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_write_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the audio stream write. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* audio_class Address of audio class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_write_task_function(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG transfer_length; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_audio_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, prepare data, reset transfer and start polling. */ + if (stream -> ux_device_class_audio_stream_task_state == UX_DEVICE_CLASS_AUDIO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_WAIT; + + /* Start frame transfer anyway (even ZLP). */ + transfer_length = stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length; + if (transfer_length) + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, transfer_length); /* Use case of memcpy is verified. */ + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Get current transfer length. */ + transfer_length = stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length; + + /* Run transfer states. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_audio_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_audio_stream_task_state = UX_DEVICE_CLASS_AUDIO_STREAM_RW_START; + stream -> ux_device_class_audio_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Frame sent, free it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = 0; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Calculate next position. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Underflow check! */ + if (transfer_length) + { + + /* Advance position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Error trap! */ + if (next_frame -> ux_device_class_audio_frame_length == 0) + { + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + } + else + { + + /* Advance position if next payload available. */ + if (next_frame -> ux_device_class_audio_frame_length) + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + else + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } + } + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c index f6c1cf0e..ce6bd7bf 100644 --- a/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_audio_write_thread_entry PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream) @@ -153,7 +156,10 @@ ULONG actual_length; /* Error trap! */ if (next_frame -> ux_device_class_audio_frame_length == 0) + { + stream -> ux_device_class_audio_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } else { @@ -162,9 +168,12 @@ ULONG actual_length; if (next_frame -> ux_device_class_audio_frame_length) stream -> ux_device_class_audio_stream_transfer_pos = next_frame; else + { /* Error trap! */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + stream -> ux_device_class_audio_stream_buffer_error_count ++; + } } /* Invoke notification callback. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c index 4086b03c..e89212a9 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read_run.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_read_run PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -79,6 +79,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* fixed return code, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, @@ -200,7 +203,7 @@ UINT status = UX_SUCCESS; cdc_acm -> ux_device_class_cdc_acm_read_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_read_status = transfer_request -> ux_slave_transfer_request_completion_code; - return(UX_STATE_EXIT); + return(UX_STATE_ERROR); } /* Success case. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c index 63c4e8f6..55f5dddb 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_tasks_run.c @@ -31,8 +31,11 @@ #if defined(UX_DEVICE_STANDALONE) + +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE static inline VOID _ux_device_class_cdc_acm_transmission_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm); static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm); +#endif /**************************************************************************/ @@ -40,7 +43,7 @@ static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLAS /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_tasks_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,21 +83,23 @@ static inline VOID _ux_device_class_cdc_acm_transmission_write_run(UX_SLAVE_CLAS /* names conflict C++ keyword, */ /* supported write auto ZLP, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile warnings, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_tasks_run(VOID *instance) { -UX_SLAVE_DEVICE *device; -UX_SLAVE_CLASS_CDC_ACM *cdc_acm; UINT status = UX_STATE_IDLE; +#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; /* Get CDC ACM instance. */ cdc_acm = (UX_SLAVE_CLASS_CDC_ACM*) instance; -#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE - /* Check if transmission is started. */ if (!cdc_acm -> ux_slave_class_cdc_acm_transmission_status) return(status); diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c index 630bea7d..35ea2ad3 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_run.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_acm_write_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* names conflict C++ keyword, */ /* added auto ZLP support, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* fixed return code, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, @@ -125,7 +128,7 @@ UINT status = 0; cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_write_status = UX_CONFIGURATION_HANDLE_UNKNOWN; - return(UX_CONFIGURATION_HANDLE_UNKNOWN); + return(UX_STATE_EXIT); } /* We need the interface to the class. */ @@ -224,7 +227,7 @@ UINT status = 0; cdc_acm -> ux_device_class_cdc_acm_write_state = UX_STATE_RESET; cdc_acm -> ux_device_class_cdc_acm_write_status = transfer_request -> ux_slave_transfer_request_completion_code; - return(UX_STATE_EXIT); + return(UX_STATE_ERROR); } /* Success case. */ diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c index a30a9bda..57968f64 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkin_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkin_thread(ULONG cdc_ecm_class) @@ -95,8 +98,8 @@ UX_SLAVE_TRANSFER *transfer_request; UINT status; ULONG actual_flags; NX_PACKET *current_packet; -UCHAR *packet_header; ULONG transfer_length; +ULONG copied; /* Cast properly the cdc_ecm instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class) @@ -148,24 +151,26 @@ ULONG transfer_length; if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) { - /* Load the address of the current packet header at the physical header. */ - packet_header = current_packet -> nx_packet_prepend_ptr; - /* Can the packet fit in the transfer requests data buffer? */ if (current_packet -> nx_packet_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH) { /* Copy the packet in the transfer descriptor buffer. */ - _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, packet_header, current_packet -> nx_packet_length); /* Use case of memcpy is verified. */ + status = nx_packet_data_extract_offset(current_packet, 0, + transfer_request -> ux_slave_transfer_request_data_pointer, + current_packet -> nx_packet_length, &copied); + if (status == UX_SUCCESS) + { - /* Calculate the transfer length. */ - transfer_length = current_packet -> nx_packet_length; - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + /* Calculate the transfer length. */ + transfer_length = current_packet -> nx_packet_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE); + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE + 1); + } /* Check error code. */ if (status != UX_SUCCESS) diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c index 6b0ba9fc..8b1cc267 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_bulkout_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -83,6 +83,11 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed EP not ready issue, */ +/* used pool from NX IP inst, */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class) @@ -94,7 +99,7 @@ UX_SLAVE_DEVICE *device; UX_SLAVE_TRANSFER *transfer_request; UINT status; NX_PACKET *packet; -ULONG ip_given_length; +USB_NETWORK_DEVICE_TYPE *ux_nx_device; /* Cast properly the cdc_ecm instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class) @@ -113,8 +118,38 @@ ULONG ip_given_length; while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) { + /* Check if packet pool is ready. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool == UX_NULL) + { + + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + + /* Get packet pool from IP instance (if available). */ + if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL) + { + cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool; + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR); + + _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT); + continue; + } + } + + /* Check if Bulk OUT endpoint is ready. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL) + { + _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_LINK_CHECK_WAIT); + continue; + } + /* We can accept new reception. Get a NX Packet */ - status = nx_packet_allocate(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet, + status = nx_packet_allocate(cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet, NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT)); if (status == NX_SUCCESS) @@ -136,7 +171,7 @@ ULONG ip_given_length; /* Send the request to the device controller. */ status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH, UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH); - + /* Check the completion code. */ if (status == UX_SUCCESS) { @@ -147,26 +182,27 @@ ULONG ip_given_length; /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ packet -> nx_packet_prepend_ptr += sizeof(USHORT); - - /* Set the prepend, length, and append fields. */ - packet -> nx_packet_length = transfer_request -> ux_slave_transfer_request_actual_length; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + transfer_request -> ux_slave_transfer_request_actual_length; - + packet -> nx_packet_append_ptr += sizeof(USHORT); + /* Copy the received packet in the IP packet data area. */ - _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer, packet -> nx_packet_length); /* Use case of memcpy is verified. */ - - /* Calculate the accurate packet length from ip header. */ - if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && - (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + status = nx_packet_data_append(packet, + transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length, + cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, + UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT)); + if (status == NX_SUCCESS) + { + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet); + } + else { - ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; - packet -> nx_packet_length = ip_given_length ; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); } - - /* Send that packet to the NetX USB broker. */ - _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet); } else diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c index f1723be2..84ae21ba 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c @@ -27,14 +27,13 @@ #include "ux_device_class_cdc_ecm.h" #include "ux_device_stack.h" -UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -61,8 +60,6 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* _ux_utility_event_flags_delete Delete Flag group */ /* _ux_device_thread_create Create Thread */ /* _ux_device_thread_delete Delete Thread */ -/* nx_packet_pool_create Create NetX packet pool */ -/* nx_packet_pool_delete Delete NetX packet pool */ /* */ /* CALLED BY */ /* */ @@ -89,6 +86,9 @@ UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -153,28 +153,6 @@ UINT status; status = (UX_MEMORY_INSUFFICIENT); } - /* Allocate some packet pool for reception. */ - if (status == UX_SUCCESS) - { - - /* UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory = - _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check for successful allocation. */ - if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory == UX_NULL) - status = (UX_MEMORY_INSUFFICIENT); - else - { - /* Create a packet pool. */ - status = nx_packet_pool_create(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, "CDC ECM Device Packet Pool", - UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory, - UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); - } - } - /* Interrupt endpoint treatment needs to be running in a different thread. So start a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread does not start until we have a instance of the class. */ @@ -267,10 +245,6 @@ UINT status; /* Free allocated resources. */ - if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool.nx_packet_pool_id) - nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); - if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory) - _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack) _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack); if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack) diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c index c429632f..43ae2175 100644 --- a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_cdc_ecm_uninitialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -82,6 +82,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_cdc_ecm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -131,14 +134,8 @@ UX_SLAVE_CLASS *class_ptr; /* Delete the interrupt thread sync event flags group. */ _ux_device_event_flags_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group); - /* Delete the reception packet pool. */ - nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); - #endif - /* Free the packet pool memory. */ - _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); - /* Free the resources. */ _ux_utility_memory_free(cdc_ecm); } diff --git a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c old mode 100755 new mode 100644 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 22f8e46b..74fc89b5 100644 --- a/common/usbx_device_classes/src/ux_device_class_hid_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_hid_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_hid_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile warnings, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -228,8 +231,13 @@ UINT status = UX_SUCCESS; } +#if !defined(UX_DEVICE_STANDALONE) || defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT) + + /* There is still initialization activities after array creation, + * and some error occurs in this stage. */ /* Free allocated event array memory. */ _ux_utility_memory_free(hid -> ux_device_class_hid_event_array); +#endif } else diff --git a/common/usbx_device_classes/src/ux_device_class_printer_initialize.c b/common/usbx_device_classes/src/ux_device_class_printer_initialize.c index 1007d29e..f07e4462 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_initialize PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,19 +69,20 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_DEVICE_CLASS_PRINTER *printer; UX_DEVICE_CLASS_PRINTER_PARAMETER *printer_parameter; UX_SLAVE_CLASS *printer_class; +#if !defined(UX_DEVICE_STANDALONE) UINT status; +#endif /* Get the class container. */ printer_class = command -> ux_slave_class_command_class_ptr; @@ -105,6 +106,7 @@ UINT status; printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_deactivate = printer_parameter -> ux_device_class_printer_instance_deactivate; printer -> ux_device_class_printer_parameter.ux_device_class_printer_soft_reset = printer_parameter -> ux_device_class_printer_soft_reset; +#if !defined(UX_DEVICE_STANDALONE) /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time. */ status = _ux_utility_mutex_create(&printer -> ux_device_class_printer_endpoint_in_mutex, "ux_device_class_printer_in_mutex"); @@ -135,11 +137,14 @@ UINT status; /* Return fatal error. */ return(UX_MUTEX_ERROR); } +#else + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; +#endif /* Reset port status. */ printer -> ux_device_class_printer_port_status = 0; /* Return completion status. */ return(UX_SUCCESS); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_read_run.c b/common/usbx_device_classes/src/ux_device_class_printer_read_run.c new file mode 100644 index 00000000..acfb3901 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_read_run.c @@ -0,0 +1,238 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_printer.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_read_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the Printer class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* received data */ +/* requested_length Length of bytes to read */ +/* actual_length Pointer to save number of */ +/* bytes read */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_NEXT Transfer done, to next state */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* (others) Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_read_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +ULONG max_transfer_length; +UINT status = UX_SUCCESS; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* Locate the endpoint. */ + endpoint = printer -> ux_device_class_printer_endpoint_out; + + /* All Printer reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(printer -> ux_device_class_printer_read_state) + { + case UX_STATE_RESET: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START; + printer -> ux_device_class_printer_read_status = UX_TRANSFER_NO_ANSWER; + printer -> ux_device_class_printer_read_buffer = buffer; + printer -> ux_device_class_printer_read_requested_length = requested_length; + printer -> ux_device_class_printer_read_actual_length = 0; + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_READ_START: + + /* Get remaining transfer length. */ + requested_length = printer -> ux_device_class_printer_read_requested_length - + printer -> ux_device_class_printer_read_actual_length; + + /* There is nothing remaining, it's done. */ + if (requested_length == 0) + { + *actual_length = printer -> ux_device_class_printer_read_actual_length; + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_SUCCESS; + return(UX_STATE_NEXT); + } + + printer -> ux_device_class_printer_read_transfer_length = requested_length; + + /* Next state. */ + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_READ_WAIT: + + /* Get a full packet each time */ + max_transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + /* Run the transfer state machine. */ + status = _ux_device_stack_transfer_run(transfer_request, + max_transfer_length, + max_transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_ERROR); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + /* Check overflow */ + if (printer -> ux_device_class_printer_read_transfer_length < + transfer_request -> ux_slave_transfer_request_actual_length) + { + printer -> ux_device_class_printer_read_state = UX_STATE_ERROR; + printer -> ux_device_class_printer_read_status = UX_TRANSFER_BUFFER_OVERFLOW; + return(UX_STATE_ERROR); + } + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(printer -> ux_device_class_printer_read_buffer, + transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */ + + /* Next buffer address. */ + printer -> ux_device_class_printer_read_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + printer -> ux_device_class_printer_read_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + printer -> ux_device_class_printer_read_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual length. */ + *actual_length = printer -> ux_device_class_printer_read_actual_length; + + /* Check short packet. */ + if (transfer_request -> ux_slave_transfer_request_actual_length < + transfer_request -> ux_slave_transfer_request_requested_length) + { + + /* It's done. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; + printer -> ux_device_class_printer_read_status = UX_INVALID_STATE; + break; + } + + /* Error cases. */ + return(UX_STATE_EXIT); +} + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c b/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c index fa96f3b7..9d41d968 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_soft_reset.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_soft_reset PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_printer_soft_reset(UX_DEVICE_CLASS_PRINTER *printer) @@ -76,11 +79,17 @@ UX_SLAVE_ENDPOINT *endpoint; /* Stop OUT. */ endpoint = printer -> ux_device_class_printer_endpoint_out; _ux_device_stack_transfer_all_request_abort(endpoint, UX_ENDPOINT_RESET); +#if defined(UX_DEVICE_STANDALONE) + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; +#endif /* Stop IN (optional). */ endpoint = printer -> ux_device_class_printer_endpoint_in; if (endpoint != UX_NULL) { _ux_device_stack_transfer_all_request_abort(endpoint, UX_ENDPOINT_RESET); +#if defined(UX_DEVICE_STANDALONE) + printer -> ux_device_class_printer_read_state = UX_STATE_RESET; +#endif } } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c index 1ff77aae..6a4e9560 100644 --- a/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c +++ b/common/usbx_device_classes/src/ux_device_class_printer_uninitialize.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_printer_uninitialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Yajun Xia Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_printer_uninitialize(UX_SLAVE_CLASS_COMMAND *command) @@ -89,13 +92,13 @@ UX_SLAVE_CLASS *class_ptr; /* Sanity check. */ if (printer != UX_NULL) { - +#if !defined(UX_DEVICE_STANDALONE) /* Delete the IN endpoint mutex. */ _ux_device_mutex_delete(&printer -> ux_device_class_printer_endpoint_in_mutex); /* Out Mutex. */ _ux_device_mutex_delete(&printer -> ux_device_class_printer_endpoint_out_mutex); - +#endif /* Free the resources. */ _ux_utility_memory_free(printer); } diff --git a/common/usbx_device_classes/src/ux_device_class_printer_write_run.c b/common/usbx_device_classes/src/ux_device_class_printer_write_run.c new file mode 100644 index 00000000..d078cd4e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_printer_write_run.c @@ -0,0 +1,258 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_printer.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_printer_write_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yajun Xia, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the Printer class. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* printer Address of printer class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write, */ +/* set to 0 to issue ZLP */ +/* actual_length Pointer to save number of */ +/* bytes written */ +/* */ +/* OUTPUT */ +/* */ +/* State machine Status to check */ +/* UX_STATE_NEXT Transfer done, to next state */ +/* UX_STATE_EXIT Abnormal, to reset state */ +/* (others) Keep running, waiting */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run Transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yajun Xia Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_printer_write_run(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT zlp = UX_FALSE; +UINT status = 0; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_WRITE, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_CONFIGURATION_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* Locate the endpoints. */ + endpoint = printer -> ux_device_class_printer_endpoint_in; + + /* Check if it's available. */ + if (endpoint == UX_NULL) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_ENDPOINT_HANDLE_UNKNOWN; + + return(UX_STATE_EXIT); + } + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Handle state cases. */ + switch(printer -> ux_device_class_printer_write_state) + { + case UX_STATE_RESET: + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_START; + printer -> ux_device_class_printer_write_status = UX_TRANSFER_NO_ANSWER; + printer -> ux_device_class_printer_write_buffer = buffer; + printer -> ux_device_class_printer_write_requested_length = requested_length; + printer -> ux_device_class_printer_write_actual_length = 0; + printer -> ux_device_class_printer_write_host_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + if (requested_length == 0) + zlp = UX_TRUE; + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_WRITE_START: + + /* Get remaining requested length. */ + requested_length = printer -> ux_device_class_printer_write_requested_length - + printer -> ux_device_class_printer_write_actual_length; + + /* There is no remaining, we are done. */ + if (requested_length == 0 && !zlp) + { + *actual_length = printer -> ux_device_class_printer_write_actual_length; + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = UX_SUCCESS; + return(UX_STATE_NEXT); + } + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + printer -> ux_device_class_printer_write_transfer_length = + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + { + + /* We can proceed with the demanded length. */ + printer -> ux_device_class_printer_write_transfer_length = requested_length; + +#if !defined(UX_DEVICE_CLASS_PRINTER_WRITE_AUTO_ZLP) + + /* Assume expected length and transfer length match. */ + printer -> ux_device_class_printer_write_host_length = requested_length; +#else + + /* Assume expected more than transfer to let stack append ZLP if needed. */ + printer -> ux_device_class_printer_write_host_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1; +#endif + } + + + /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API + easier. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + printer -> ux_device_class_printer_write_buffer, + printer -> ux_device_class_printer_write_transfer_length); /* Use case of memcpy is verified. */ + + /* Next state. */ + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_WAIT; + UX_SLAVE_TRANSFER_STATE_RESET(transfer_request); + + /* Fall through. */ + case UX_DEVICE_CLASS_PRINTER_WRITE_WAIT: + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_run(transfer_request, + printer -> ux_device_class_printer_write_transfer_length, + printer -> ux_device_class_printer_write_host_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + printer -> ux_device_class_printer_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + return(UX_STATE_ERROR); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next buffer address. */ + printer -> ux_device_class_printer_write_buffer += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + printer -> ux_device_class_printer_write_actual_length += + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Last transfer status. */ + printer -> ux_device_class_printer_write_status = + transfer_request -> ux_slave_transfer_request_completion_code; + + /* Update actual done length. */ + *actual_length = printer -> ux_device_class_printer_write_actual_length; + + /* Check ZLP case. */ + if (printer -> ux_device_class_printer_write_requested_length == 0) + { + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + return(UX_STATE_NEXT); + } + + /* Next state. */ + printer -> ux_device_class_printer_write_state = UX_DEVICE_CLASS_PRINTER_WRITE_START; + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); + + default: /* Error. */ + printer -> ux_device_class_printer_write_state = UX_STATE_RESET; + break; + } + + /* Error case. */ + return(UX_STATE_EXIT); +} + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c index be900a96..92c11151 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkin_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkin_thread(ULONG rndis_class) @@ -97,8 +100,8 @@ UX_SLAVE_TRANSFER *transfer_request; UINT status; ULONG actual_flags; NX_PACKET *current_packet; -UCHAR *packet_header; ULONG transfer_length; +ULONG copied; /* Cast properly the rndis instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, rndis_class) @@ -150,9 +153,6 @@ ULONG transfer_length; if (rndis -> ux_slave_class_rndis_link_state == UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP) { - /* Load the address of the current packet header at the physical header. */ - packet_header = current_packet -> nx_packet_prepend_ptr; - /* Calculate the transfer length. */ transfer_length = current_packet -> nx_packet_length + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH; @@ -161,21 +161,27 @@ ULONG transfer_length; { /* Copy the packet in the transfer descriptor buffer. */ - _ux_utility_memory_copy (transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, packet_header, current_packet -> nx_packet_length); /* Use case of memcpy is verified. */ - - /* Add the RNDIS header to this packet. */ - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH, transfer_length); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET, - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET); - _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH, current_packet -> nx_packet_length); - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - - /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE); - + status = nx_packet_data_extract_offset(current_packet, 0, + transfer_request -> ux_slave_transfer_request_data_pointer + + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, + current_packet -> nx_packet_length, &copied); + if (status == NX_SUCCESS) + { + + /* Add the RNDIS header to this packet. */ + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH, transfer_length); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET, + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH, current_packet -> nx_packet_length); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE + 1); + } + /* Check for error. */ if (status != UX_SUCCESS) diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c index a569e5f5..1fcc35a1 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_bulkout_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -84,6 +84,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* used NX API to copy data, */ +/* used linked NX IP pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_rndis_bulkout_thread(ULONG rndis_class) @@ -95,8 +99,8 @@ UX_SLAVE_DEVICE *device; UX_SLAVE_TRANSFER *transfer_request; UINT status; NX_PACKET *packet; -ULONG ip_given_length; ULONG packet_payload; +USB_NETWORK_DEVICE_TYPE *ux_nx_device; /* Cast properly the rndis instance. */ UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, rndis_class) @@ -117,16 +121,39 @@ ULONG packet_payload; /* As long as the device is in the CONFIGURED state. */ while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) { - + + /* Check if packet pool is ready. */ + if (rndis -> ux_slave_class_rndis_packet_pool == UX_NULL) + { + + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(rndis -> ux_slave_class_rndis_network_handle); + + /* Get packet pool from IP instance (if available). */ + if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL) + { + rndis -> ux_slave_class_rndis_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool; + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR); + + _ux_utility_delay_ms(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_INST_WAIT); + continue; + } + } + /* We can accept new reception. Get a NX Packet. */ - status = nx_packet_allocate(&rndis -> ux_slave_class_rndis_packet_pool, &packet, + status = nx_packet_allocate(rndis -> ux_slave_class_rndis_packet_pool, &packet, NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT)); if (status == NX_SUCCESS) { /* And length. */ - transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH; + transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH; transfer_request -> ux_slave_transfer_request_actual_length = 0; /* Memorize this packet at the beginning of the queue. */ @@ -136,8 +163,8 @@ ULONG packet_payload; packet -> nx_packet_queue_next = UX_NULL; /* Send the request to the device controller. */ - status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, - UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH); + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH, + UX_DEVICE_CLASS_RNDIS_MAX_MSG_LENGTH); /* Check the completion code. */ if (status == UX_SUCCESS) @@ -147,63 +174,71 @@ ULONG packet_payload; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_RECEIVE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) - /* Check the state of the transfer. If there is an error, we do not proceed with this report. Also ensure the header has a valid ID of 1. */ - if (_ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE) == UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG) + /* Check the state of the transfer. If there is an error, we do not proceed with this report. + Ensure this packet is at least larger than the header. + Also ensure the header has a valid ID of 1. */ + if (transfer_request -> ux_slave_transfer_request_actual_length > UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH && + _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE) == UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG) { - /* Ensure this packet is at least larger than the header. */ - if (transfer_request -> ux_slave_transfer_request_actual_length > UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) - { - - /* Get the size of the payload. */ - packet_payload = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH); - - /* Ensure the length reported in the RNDIS header is not larger than it actually is. - The reason we can't check to see if the length reported in the header and the - actual length are exactly equal is because there might other data after the payload - (padding, or even a message). */ - if (packet_payload <= transfer_request -> ux_slave_transfer_request_actual_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) - { + /* Get the size of the payload. */ + packet_payload = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH); - /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ - packet -> nx_packet_prepend_ptr += sizeof(USHORT); - - /* Adjust the prepend, length, and append fields. */ - packet -> nx_packet_length = packet_payload; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + packet_payload; - + /* Ensure the length reported in the RNDIS header is not larger than it actually is. + The reason we can't check to see if the length reported in the header and the + actual length are exactly equal is because there might other data after the payload + (padding, or even a message). */ + if (packet_payload <= transfer_request -> ux_slave_transfer_request_actual_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) + { - /* Copy the received packet in the IP packet data area. */ - _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER, packet_payload); /* Use case of memcpy is verified. */ - - /* Calculate the accurate packet length from ip header */ - if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && - (*(packet -> nx_packet_prepend_ptr + 13) == 0)) - { + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + packet -> nx_packet_append_ptr += sizeof(USHORT); - ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; - packet -> nx_packet_length = ip_given_length ; - packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; - } + /* Copy the received packet in the IP packet data area. */ + status = nx_packet_data_append(packet, + transfer_request -> ux_slave_transfer_request_data_pointer + + UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER, + packet_payload, + rndis -> ux_slave_class_rndis_packet_pool, + UX_MS_TO_TICK(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT)); + if (status == UX_SUCCESS) + { /* Send that packet to the NetX USB broker. */ _ux_network_driver_packet_received(rndis -> ux_slave_class_rndis_network_handle, packet); } else + { - /* We received a malformed packet. Report to application. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + /* Error. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_ERROR); + nx_packet_release(packet); + } } else + { /* We received a malformed packet. Report to application. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); + } + } + else + { + + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + nx_packet_release(packet); } } else + { /* Free the packet that was not successfully received. */ nx_packet_release(packet); + } + } else { diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c index 8af77324..18604e89 100644 --- a/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c @@ -78,7 +78,7 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* FUNCTION RELEASE */ /* */ /* _ux_device_class_rndis_initialize PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -136,6 +136,9 @@ ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORT /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_rndis_initialize(UX_SLAVE_CLASS_COMMAND *command) @@ -294,31 +297,6 @@ UINT status; status = UX_EVENT_ERROR; } - /* Allocate some packet pool for reception. */ - if (status == UX_SUCCESS) - { - - /* UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - rndis -> ux_slave_class_rndis_pool_memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check the completion status. */ - if (rndis -> ux_slave_class_rndis_pool_memory == UX_NULL) - status = UX_MEMORY_INSUFFICIENT; - } - - /* Create a packet pool. */ - if (status == UX_SUCCESS) - { - status = nx_packet_pool_create(&rndis -> ux_slave_class_rndis_packet_pool, "Rndis Device Packet Pool", - UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE, rndis -> ux_slave_class_rndis_pool_memory, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); - - /* Check for pool creation error. */ - if (status != UX_SUCCESS) - status = UX_MEMORY_INSUFFICIENT; - } - /* Create a semaphore for protecting the driver entry. */ if (status == UX_SUCCESS) { @@ -338,14 +316,6 @@ UINT status; if (rndis -> ux_slave_class_rndis_semaphore.tx_semaphore_id != 0) _ux_device_semaphore_delete(&rndis -> ux_slave_class_rndis_semaphore); - /* Delete the packet pool. */ - if (rndis -> ux_slave_class_rndis_packet_pool.nx_packet_pool_id != 0) - nx_packet_pool_delete(&rndis -> ux_slave_class_rndis_packet_pool); - - /* Free rndis -> ux_slave_class_rndis_pool_memory. */ - if (rndis -> ux_slave_class_rndis_pool_memory) - _ux_utility_memory_free(rndis -> ux_slave_class_rndis_pool_memory); - /* Delete rndis -> ux_slave_class_rndis_event_flags_group. */ if (rndis -> ux_slave_class_rndis_event_flags_group.tx_event_flags_group_id != 0) _ux_utility_event_flags_delete(&rndis -> ux_slave_class_rndis_event_flags_group); diff --git a/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c index 2acafd4e..a3652f67 100644 --- a/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c +++ b/common/usbx_device_classes/src/ux_device_class_storage_tasks_run.c @@ -65,7 +65,7 @@ static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *s /* FUNCTION RELEASE */ /* */ /* _ux_device_class_storage_tasks_run PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -125,6 +125,9 @@ static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *s /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_storage_tasks_run(VOID *instance) @@ -148,13 +151,14 @@ static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *sto UX_SLAVE_DEVICE *device; UCHAR state; UINT status; +INT immediate_state = UX_TRUE; /* Get pointer to the device. */ device = &_ux_system_slave -> ux_system_slave_device; /* Run states once. */ - while(1) + while(immediate_state) { /* General check for MSC ready. */ @@ -301,9 +305,12 @@ UINT status; break; } - /* Unhandled, just do again by app call. */ - return(UX_STATE_EXIT); + /* Unhandled, just break the loop and do again by app call. */ + immediate_state = UX_FALSE; } + + /* Unhandled state. */ + return(UX_STATE_EXIT); } static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage) @@ -979,9 +986,10 @@ static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *st { UCHAR state = storage -> ux_device_class_storage_disk_state; UINT status; +INT immediate_state = UX_TRUE; /* Run states once. */ - while(1) + while(immediate_state) { /* Update state. */ @@ -1035,8 +1043,8 @@ UINT status; break; } - /* Task run once. */ - return; + /* Task run once, break the loop. */ + immediate_state = UX_FALSE; } } static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage) @@ -1058,6 +1066,8 @@ ULONG max_n_blocks; /* Max blocks for one buffer. */ block_size = storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun]. ux_slave_class_storage_media_block_length; + if (block_size == 0) + UX_ASSERT(UX_FALSE); max_n_blocks = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE / block_size; /* Prepare next disk read. */ diff --git a/common/usbx_device_classes/src/ux_device_class_video_activate.c b/common/usbx_device_classes/src/ux_device_class_video_activate.c index 80e71f62..7d780482 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_activate.c +++ b/common/usbx_device_classes/src/ux_device_class_video_activate.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_activate(UX_SLAVE_CLASS_COMMAND *command) @@ -154,6 +157,14 @@ ULONG stream_index; /* Store the class instance into the interface. */ stream_interface -> ux_slave_interface_class_instance = (VOID *)video; + +#if defined(UX_DEVICE_STANDALONE) + + /* Reset stream task state. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = UX_SUCCESS; +#endif + } /* If there is a activate function call it. */ diff --git a/common/usbx_device_classes/src/ux_device_class_video_change.c b/common/usbx_device_classes/src/ux_device_class_video_change.c index 199fcc62..9bf5e016 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_change.c +++ b/common/usbx_device_classes/src/ux_device_class_video_change.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_change PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_change(UX_SLAVE_CLASS_COMMAND *command) @@ -160,6 +163,15 @@ ULONG stream_index; return(UX_DESCRIPTOR_CORRUPTED); } +#if defined(UX_DEVICE_STANDALONE) + + /* Reset background transfer state. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; +#endif + + /* Now reset payload buffer error count. */ + stream -> ux_device_class_video_stream_buffer_error_count = 0; + /* Now reset payload buffers. */ payload_buffer = stream -> ux_device_class_video_stream_buffer; while(payload_buffer < stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) diff --git a/common/usbx_device_classes/src/ux_device_class_video_initialize.c b/common/usbx_device_classes/src/ux_device_class_video_initialize.c index 8ffb9fe9..625bc4f0 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_initialize.c +++ b/common/usbx_device_classes/src/ux_device_class_video_initialize.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_initialize PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -67,14 +67,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_initialize(UX_SLAVE_CLASS_COMMAND *command) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(command); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UINT status = UX_SUCCESS; UX_DEVICE_CLASS_VIDEO *video; @@ -163,6 +162,9 @@ ULONG i; stream -> ux_device_class_video_stream_transfer_pos = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)stream -> ux_device_class_video_stream_buffer; stream -> ux_device_class_video_stream_access_pos = stream -> ux_device_class_video_stream_transfer_pos; + +#if !defined(UX_DEVICE_STANDALONE) + /* Create memory block for streaming thread stack in addition. */ if (stream_parameter -> ux_device_class_video_stream_parameter_thread_stack_size == 0) memory_size = UX_DEVICE_CLASS_VIDEO_THREAD_STACK_SIZE; @@ -189,6 +191,11 @@ ULONG i; break; UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_video_stream_thread), stream) +#else + + /* Save task function for streaming. */ + stream -> ux_device_class_video_stream_task_function = stream_parameter -> ux_device_class_video_stream_parameter_task_function; +#endif /* Save callbacks. */ _ux_utility_memory_copy(&stream -> ux_device_class_video_stream_callbacks, @@ -217,6 +224,12 @@ ULONG i; &video_parameter -> ux_device_class_video_parameter_callbacks, sizeof(UX_DEVICE_CLASS_VIDEO_CALLBACKS)); /* Use case of memcpy is verified. */ +#if defined(UX_DEVICE_STANDALONE) + + /* Link task function. */ + class_inst -> ux_slave_class_task_function = _ux_device_class_video_tasks_run; +#endif + /* Return completion status. */ return(UX_SUCCESS); } @@ -228,10 +241,14 @@ ULONG i; stream = video -> ux_device_class_video_streams; for (i = 0; i < video -> ux_device_class_video_streams_nb; i ++) { + +#if !defined(UX_DEVICE_STANDALONE) if (stream -> ux_device_class_video_stream_thread.tx_thread_id) _ux_utility_thread_delete(&stream -> ux_device_class_video_stream_thread); if (stream -> ux_device_class_video_stream_thread_stack) _ux_utility_memory_free(stream -> ux_device_class_video_stream_thread_stack); +#endif + if (stream -> ux_device_class_video_stream_buffer) _ux_utility_memory_free(stream -> ux_device_class_video_stream_buffer); stream ++; @@ -239,5 +256,4 @@ ULONG i; _ux_utility_memory_free(video); return(status); -#endif } diff --git a/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c b/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c new file mode 100644 index 00000000..a7422cc8 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_read_task_function.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_read_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video stream read. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* stream Pointer to video stream */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_read_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_VIDEO_PAYLOAD *next_payload; +ULONG max_packet_size; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_video_stream_video -> ux_device_class_video_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_video_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_video_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, reset transfer and start polling. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT; + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Run transfer state machine. */ + max_packet_size = endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_transfer_length; + status = _ux_device_stack_transfer_run(transfer, max_packet_size, max_packet_size); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Frame received, log it. */ + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length = actual_length; + _ux_utility_memory_copy(stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_data, + transfer -> ux_slave_transfer_request_data_pointer, + actual_length); /* Use case of memcpy is verified. */ + + /* For simple, do not advance the transfer position if there is overflow. */ + next_pos = (UCHAR *)stream -> ux_device_class_video_stream_transfer_pos; + next_pos += stream -> ux_device_class_video_stream_payload_buffer_size; + if (next_pos >= stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) + next_pos = stream -> ux_device_class_video_stream_buffer; + next_payload = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)next_pos; + + /* Check overflow! */ + if (next_payload -> ux_device_class_video_payload_length > 0) + { + + /* Error notification! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + else + + /* Update transfer position. */ + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + + /* Invoke notification callback. */ + if (stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done != UX_NULL) + stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c index e9cd669c..060723d3 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_video_read_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_read_thread_entry PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added error statistics, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_video_read_thread_entry(ULONG video_stream) @@ -145,6 +148,7 @@ ULONG actual_length; { /* Error notification! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); } else diff --git a/common/usbx_device_classes/src/ux_device_class_video_reception_start.c b/common/usbx_device_classes/src/ux_device_class_video_reception_start.c index 84be153c..342b00e1 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_reception_start.c +++ b/common/usbx_device_classes/src/ux_device_class_video_reception_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_reception_start PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,14 +65,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_reception_start(UX_DEVICE_CLASS_VIDEO_STREAM *stream) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(stream); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_ENDPOINT *endpoint; UX_SLAVE_DEVICE *device; @@ -102,8 +101,16 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length > 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start read task. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + +#else /* Start read thread. */ _ux_utility_thread_resume(&stream -> ux_device_class_video_stream_thread); - return(UX_SUCCESS); #endif + + return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c b/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c new file mode 100644 index 00000000..24ca2ede --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_tasks_run.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_tasks_run PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* instance Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* (ux_device_class_video_stream_task_function) */ +/* Run stream task */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_tasks_run(VOID *instance) +{ +UX_SLAVE_DEVICE *device; +UX_DEVICE_CLASS_VIDEO *video; +UX_DEVICE_CLASS_VIDEO_STREAM *stream; +ULONG stream_index; +UINT status; +ULONG running_count; + + + /* Get Video instance. */ + video = (UX_DEVICE_CLASS_VIDEO *) instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return(UX_STATE_EXIT); + + /* Run video streaming tasks. */ + running_count = 0; + for (stream_index = 0; + stream_index < video -> ux_device_class_video_streams_nb; + stream_index ++) + { + stream = &video -> ux_device_class_video_streams[stream_index]; + status = stream -> ux_device_class_video_stream_task_function(stream); + if (status == UX_STATE_EXIT) + return(status); + if (status == UX_STATE_WAIT) + running_count ++; + } + + /* Return state running. */ + return (running_count > 0) ? (UX_STATE_WAIT) : (UX_STATE_IDLE); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c b/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c index 63a6c303..c01f1179 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c +++ b/common/usbx_device_classes/src/ux_device_class_video_transmission_start.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_transmission_start PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -65,14 +65,13 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added standalone support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_device_class_video_transmission_start(UX_DEVICE_CLASS_VIDEO_STREAM *stream) { -#if defined(UX_DEVICE_STANDALONE) - UX_PARAMETER_NOT_USED(stream); - return(UX_FUNCTION_NOT_SUPPORTED); -#else UX_SLAVE_ENDPOINT *endpoint; UX_SLAVE_DEVICE *device; @@ -102,8 +101,17 @@ UX_SLAVE_DEVICE *device; if (stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length == 0) return(UX_BUFFER_OVERFLOW); +#if defined(UX_DEVICE_STANDALONE) + + /* Start write task. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + +#else + /* Start write thread. */ - _ux_utility_thread_resume(&stream -> ux_device_class_video_stream_thread); - return(UX_SUCCESS); + _ux_device_thread_resume(&stream -> ux_device_class_video_stream_thread); #endif + + return(UX_SUCCESS); } diff --git a/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c b/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c new file mode 100644 index 00000000..55dba42a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_video_write_task_function.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_video.h" +#include "ux_device_stack.h" + + +#if defined(UX_DEVICE_STANDALONE) +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_video_write_task_function PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the background task of the video stream write. */ +/* */ +/* It's for standalone mode. */ +/* */ +/* INPUT */ +/* */ +/* video_class Address of video class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* State machine status */ +/* UX_STATE_EXIT Device not configured */ +/* UX_STATE_IDLE No streaming transfer running */ +/* UX_STATE_WAIT Streaming transfer running */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_run Run transfer state machine */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Chaoqiong Xiao Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_video_write_task_function(UX_DEVICE_CLASS_VIDEO_STREAM *stream) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_VIDEO_PAYLOAD *next_payload; +ULONG transfer_length; +ULONG actual_length; +UINT status; + + + /* Get the pointer to the device. */ + device = stream -> ux_device_class_video_stream_video -> ux_device_class_video_device; + + /* Check if the device is configured. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + stream -> ux_device_class_video_stream_task_state = UX_STATE_EXIT; + return(UX_STATE_EXIT); + } + + /* Get the endpoint. */ + endpoint = stream -> ux_device_class_video_stream_endpoint; + + /* No endpoint ready, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + return(UX_STATE_IDLE); + + /* Check if background transfer task is started. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_STOP) + return(UX_STATE_IDLE); + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* If not started yet, prepare data, reset transfer and start polling. */ + if (stream -> ux_device_class_video_stream_task_state == UX_DEVICE_CLASS_VIDEO_STREAM_RW_START) + { + + /* Next state: transfer wait. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_WAIT; + + /* Start payload transfer anyway (even ZLP). */ + transfer_length = stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length; + if (transfer_length) + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_data, transfer_length); /* Use case of memcpy is verified. */ + + /* Reset transfer state. */ + UX_SLAVE_TRANSFER_STATE_RESET(transfer); + } + + /* Get current transfer length. */ + transfer_length = stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length; + + /* Run transfer states. */ + status = _ux_device_stack_transfer_run(transfer, transfer_length, transfer_length); + + /* Error case. */ + if (status < UX_STATE_NEXT) + { + + /* Error on background transfer task start. */ + stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + return(UX_STATE_EXIT); + } + + /* Success case. */ + if (status == UX_STATE_NEXT) + { + + /* Next state: start. */ + stream -> ux_device_class_video_stream_task_state = UX_DEVICE_CLASS_VIDEO_STREAM_RW_START; + stream -> ux_device_class_video_stream_task_status = + transfer -> ux_slave_transfer_request_completion_code; + + /* Frame sent, free it. */ + stream -> ux_device_class_video_stream_transfer_pos -> ux_device_class_video_payload_length = 0; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Calculate next position. */ + next_pos = (UCHAR *)stream -> ux_device_class_video_stream_transfer_pos; + next_pos += stream -> ux_device_class_video_stream_payload_buffer_size; + if (next_pos >= stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size) + next_pos = stream -> ux_device_class_video_stream_buffer; + next_payload = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)next_pos; + + /* Underflow check! */ + if (transfer_length) + { + + /* Advance position. */ + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + + /* Error trap! */ + if (next_payload -> ux_device_class_video_payload_length == 0) + { + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + } + else + { + + /* Advance position if next payload available. */ + if (next_payload -> ux_device_class_video_payload_length) + stream -> ux_device_class_video_stream_transfer_pos = next_payload; + else + { + + /* Error trap! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + } + + /* Invoke notification callback. */ + if (stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done != UX_NULL) + stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_payload_done(stream, actual_length); + } + + /* Keep waiting. */ + return(UX_STATE_WAIT); +} +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c index 43006d6d..3dce6367 100644 --- a/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c +++ b/common/usbx_device_classes/src/ux_device_class_video_write_thread_entry.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_video_write_thread_entry PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added error statistics, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_device_class_video_write_thread_entry(ULONG video_stream) @@ -147,7 +150,10 @@ ULONG actual_length; /* Error trap! */ if (next_payload -> ux_device_class_video_payload_length == 0) + { + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } else { @@ -156,9 +162,12 @@ ULONG actual_length; if (next_payload -> ux_device_class_video_payload_length) stream -> ux_device_class_video_stream_transfer_pos = next_payload; else + { /* Error trap! */ + stream -> ux_device_class_video_stream_buffer_error_count ++; _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } } /* Invoke notification callback. */ diff --git a/common/usbx_host_classes/inc/ux_host_class_asix.h b/common/usbx_host_classes/inc/ux_host_class_asix.h index dac0f481..250fd209 100644 --- a/common/usbx_host_classes/inc/ux_host_class_asix.h +++ b/common/usbx_host_classes/inc/ux_host_class_asix.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_asix.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -53,6 +53,13 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* refined VID/PID check flow, */ +/* removed internal NX pool, */ +/* added some new definitions, */ +/* refined reception handling, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -93,6 +100,17 @@ extern "C" { #define UX_HOST_CLASS_ASIX_VENDOR_FUJIEI_ID 0X0B95 #define UX_HOST_CLASS_ASIX_PRODUCT_FUJIEI_ID 0X772B +#define UX_HOST_CLASS_ASIX_VENDOR_LINKSYS_ID 0X13B1 +#define UX_HOST_CLASS_ASIX_PRODUCT_LINKSYS_ID 0X0018 + +/* Define ASIX supported VID and PID array (of 16-bits). */ +#ifndef UX_HOST_CLASS_ASIX_VID_PID_ARRAY +#define UX_HOST_CLASS_ASIX_VID_PID_ARRAY \ + UX_HOST_CLASS_ASIX_VENDOR_ID, UX_HOST_CLASS_ASIX_PRODUCT_ID, \ + UX_HOST_CLASS_ASIX_VENDOR_FUJIEI_ID, UX_HOST_CLASS_ASIX_PRODUCT_FUJIEI_ID, \ + UX_HOST_CLASS_ASIX_VENDOR_LINKSYS_ID, UX_HOST_CLASS_ASIX_PRODUCT_LINKSYS_ID +#endif + #define UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS 0x100 #define UX_HOST_CLASS_ASIX_SPEED_SELECTED_10MPBS 0x10 #define UX_HOST_CLASS_ASIX_LINK_STATE_DOWN 0 @@ -107,14 +125,29 @@ extern "C" { #define UX_HOST_CLASS_ASIX_ETHERNET_RARP 0x8035 #define UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE 1536 #define UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING 2 -#ifndef UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES -#define UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES 16 +#define UX_HOST_CLASS_ASIX_RX_HEADER_SIZE 4 +#define UX_HOST_CLASS_ASIX_OVERHEAD_SIZE (UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING + UX_HOST_CLASS_ASIX_RX_HEADER_SIZE) + +#define UX_HOST_CLASS_ASIX_TRANSMIT_BUFFER_SIZE UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE + +#ifndef UX_HOST_CLASS_ASIX_RECEIVE_BUFFER_SIZE +#define UX_HOST_CLASS_ASIX_RECEIVE_BUFFER_SIZE 512 /* N*512. */ +#endif + +#ifdef NX_DISABLE_PACKET_CHAIN +#undef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT +#else +#define UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT #endif #define UX_HOST_CLASS_ASIX_NX_PACKET_SIZE sizeof(NX_PACKET) -#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE, UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING), UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_calc_ovf) -#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE (UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE + UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING) +#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE, \ + UX_HOST_CLASS_ASIX_OVERHEAD_SIZE), \ + UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_calc_ovf) +#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE (UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE + UX_HOST_CLASS_ASIX_OVERHEAD_SIZE) #define UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_ASSERT \ UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_ASSERT \ @@ -124,24 +157,15 @@ extern "C" { UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_calc_ovf) #define UX_HOST_CLASS_ASIX_NX_BUFF_SIZE (UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE + UX_HOST_CLASS_ASIX_NX_PACKET_SIZE) -#define UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT \ - UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_ASSERT \ - UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG( \ - UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES, \ - UX_HOST_CLASS_ASIX_NX_BUFF_SIZE), \ - UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_calc1_ovf) \ - UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ - UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES * \ - UX_HOST_CLASS_ASIX_NX_BUFF_SIZE, \ - 32), UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) -#define UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE (UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES * UX_HOST_CLASS_ASIX_NX_BUFF_SIZE + 32) - #define UX_HOST_CLASS_ASIX_ETHERNET_SIZE 14 #define UX_HOST_CLASS_ASIX_DEVICE_INIT_DELAY (1 * UX_PERIODIC_RATE) #define UX_HOST_CLASS_ASIX_CLASS_TRANSFER_TIMEOUT 300000 #define UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE 16 +#define UX_HOST_CLASS_ASIX_PACKET_POOL_WAIT 100 +#define UX_HOST_CLASS_ASIX_PACKET_ALLOCATE_WAIT 2000 + /* Define NetX errors inside the Asix class. */ #define UX_HOST_CLASS_ASIX_NX_SUCCESS 0x00 #define UX_HOST_CLASS_ASIX_NX_NO_PACKET 0x01 @@ -206,6 +230,7 @@ extern "C" { #define UX_HOST_CLASS_ASIX_REQ_OWN_SMI 0x06 #define UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG 0x07 #define UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG 0x08 +#define UX_HOST_CLASS_ASIX_REQ_READ_STATION_STATUS 0x09 #define UX_HOST_CLASS_ASIX_REQ_WHO_OWNS_SMI 0x09 #define UX_HOST_CLASS_ASIX_REQ_RELEASE_SMI 0x0a #define UX_HOST_CLASS_ASIX_REQ_READ_SROM 0x0b @@ -280,16 +305,25 @@ extern "C" { #define UX_HOST_CLASS_ASIX_RXCR_AP 0x0020 #define UX_HOST_CLASS_ASIX_RXCR_SO 0x0080 +/* 88772. */ #define UX_HOST_CLASS_ASIX_RXCR_MFB_2048 0x0000 #define UX_HOST_CLASS_ASIX_RXCR_MFB_4096 0x0100 #define UX_HOST_CLASS_ASIX_RXCR_MFB_8192 0x0200 -#define UX_HOST_CLASS_ASIX_RXCR_MFB_16384 0x0300 +#define UX_HOST_CLASS_ASIX_RXCR_MFB_16384 0x0300 /* Default. */ + +/* 88772B. */ +#define UX_HOST_CLASS_ASIX_RXCR_RH1M 0x0100 /* Default 1. */ +#define UX_HOST_CLASS_ASIX_RXCR_RH2M 0x0200 /* Default 0. */ +#define UX_HOST_CLASS_ASIX_RXCR_RH3M 0x0400 /* Default 0. */ + /* Define ASIX Class packet equivalences. */ #define UX_HOST_CLASS_ASIX_PACKET_SIZE 128 #define UX_HOST_CLASS_ASIX_NODE_ID_LENGTH 6 +#define UX_HOST_CLASS_ASIX_RX_PACKET_LENGTH_MASK 0xFFF + /* Define ASIX PHY registers description. */ #define UX_HOST_CLASS_ASIX_PHY_REG_BMCR 0x00 @@ -391,10 +425,14 @@ typedef struct UX_HOST_CLASS_ASIX_STRUCT ULONG ux_host_class_asix_link_state; NX_PACKET *ux_host_class_asix_xmit_queue; +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT + UCHAR *ux_host_class_asix_xmit_buffer; +#endif NX_PACKET *ux_host_class_asix_receive_queue; - NX_PACKET_POOL ux_host_class_asix_packet_pool; + UCHAR *ux_host_class_asix_receive_buffer; + NX_PACKET_POOL *ux_host_class_asix_packet_pool; + ULONG ux_host_class_asix_packet_available_min; - UCHAR *ux_host_class_asix_pool_memory; UCHAR ux_host_class_asix_node_id[UX_HOST_CLASS_ASIX_NODE_ID_LENGTH]; VOID (*ux_host_class_asix_device_status_change_callback)(struct UX_HOST_CLASS_ASIX_STRUCT *asix, ULONG device_state); diff --git a/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h b/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h index 524656f9..9a8b3884 100644 --- a/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h +++ b/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* ux_host_class_cdc_ecm.h PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -57,6 +57,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -144,12 +147,19 @@ extern "C" { 32), UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) #define UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE (UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES * UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE + 32) +#ifdef NX_DISABLE_PACKET_CHAIN +#undef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT +#else +#define UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT +#endif + #define UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE 14 #define UX_HOST_CLASS_CDC_ECM_DEVICE_INIT_DELAY (1 * UX_PERIODIC_RATE) #define UX_HOST_CLASS_CDC_ECM_CLASS_TRANSFER_TIMEOUT 300000 #define UX_HOST_CLASS_CDC_ECM_SETUP_BUFFER_SIZE 16 + /* Define NetX errors inside the CDC ECM class. */ #define UX_HOST_CLASS_CDC_ECM_NX_SUCCESS 0x00 #define UX_HOST_CLASS_CDC_ECM_NX_NO_PACKET 0x01 @@ -280,11 +290,10 @@ typedef struct UX_HOST_CLASS_CDC_ECM_STRUCT ULONG ux_host_class_cdc_ecm_link_state; NX_PACKET *ux_host_class_cdc_ecm_xmit_queue_head; NX_PACKET *ux_host_class_cdc_ecm_xmit_queue_tail; -#ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX - NX_PACKET_POOL ux_host_class_cdc_ecm_packet_pool; - UCHAR *ux_host_class_cdc_ecm_pool_memory; -#else NX_PACKET_POOL *ux_host_class_cdc_ecm_packet_pool; +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + UCHAR *ux_host_class_cdc_ecm_xmit_buffer; + UCHAR *ux_host_class_cdc_ecm_receive_buffer; #endif UCHAR ux_host_class_cdc_ecm_node_id[UX_HOST_CLASS_CDC_ECM_NODE_ID_LENGTH]; 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 b8051751..b331bf4d 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.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -56,6 +56,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed clients management, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved HID OUTPUT report */ +/* handling in standalone mode,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -215,6 +219,8 @@ typedef struct UX_HOST_CLASS_HID_KEYBOARD_STRUCT UX_THREAD ux_host_class_hid_keyboard_thread; UX_SEMAPHORE ux_host_class_hid_keyboard_semaphore; #else + UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_keyboard_out_report; UINT ux_host_class_hid_keyboard_status; UCHAR ux_host_class_hid_keyboard_enum_state; UCHAR ux_host_class_hid_keyboard_next_state; diff --git a/common/usbx_host_classes/inc/ux_host_class_storage.h b/common/usbx_host_classes/inc/ux_host_class_storage.h old mode 100755 new mode 100644 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 a243a072..760b59ed 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 @@ -29,14 +29,13 @@ #include "ux_host_class_asix.h" #include "ux_host_stack.h" -UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_activate PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -87,6 +86,11 @@ UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* moved NX driver activate, */ +/* added reception buffer, */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND *command) @@ -103,7 +107,10 @@ UX_DEVICE *device; UX_HOST_CLASS_ASIX *asix; UINT status; UX_TRANSFER *transfer_request; - +ULONG physical_address_msw; +ULONG physical_address_lsw; + + /* We need to make sure that the value of the NX_PHYSICAL_HEADER is at least 20. This should be changed in the nx_user.h file */ @@ -199,27 +206,28 @@ UX_TRANSFER *transfer_request; status = _ux_host_stack_transfer_request(transfer_request); } - /* Allocate some packet pool for reception. */ + /* Allocate some memory for reception. */ if (status == UX_SUCCESS) { - - /* UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - asix -> ux_host_class_asix_pool_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE); - if (asix -> ux_host_class_asix_pool_memory == UX_NULL) + asix -> ux_host_class_asix_receive_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_RECEIVE_BUFFER_SIZE); + if (asix -> ux_host_class_asix_receive_buffer == UX_NULL) status = UX_MEMORY_INSUFFICIENT; } - /* Create a packet pool. */ + /* Activate network driver. */ if (status == UX_SUCCESS) { - status = nx_packet_pool_create(&asix -> ux_host_class_asix_packet_pool, "Asix Packet Pool", - UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE, asix -> ux_host_class_asix_pool_memory, UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE); - /* Check for pool creation error. */ - if (status) - status = UX_ERROR; + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((asix -> ux_host_class_asix_node_id[0] << 8) | (asix -> ux_host_class_asix_node_id[1])); + physical_address_lsw = (ULONG)((asix -> ux_host_class_asix_node_id[2] << 24) | (asix -> ux_host_class_asix_node_id[3] << 16) | + (asix -> ux_host_class_asix_node_id[4] << 8) | (asix -> ux_host_class_asix_node_id[5])); + + /* Register this interface to the NetX USB interface broker. */ + status = _ux_network_driver_activate((VOID *) asix, _ux_host_class_asix_write, + &asix -> ux_host_class_asix_network_handle, + physical_address_msw, + physical_address_lsw); } /* Do final things if success. */ @@ -250,12 +258,9 @@ UX_TRANSFER *transfer_request; /* There was a problem, so free the resources. */ - /* Last resource, asix -> ux_host_class_asix_packet_pool is not created or created error, - no need to free. */ - - /* Free asix -> ux_host_class_asix_pool_memory. */ - if (asix -> ux_host_class_asix_pool_memory) - _ux_utility_memory_free(asix -> ux_host_class_asix_pool_memory); + /* Free asix -> ux_host_class_asix_receive_buffer. */ + if (asix -> ux_host_class_asix_receive_buffer) + _ux_utility_memory_free(asix -> ux_host_class_asix_receive_buffer); /* Free asix -> ux_host_class_asix_thread. */ if (asix -> ux_host_class_asix_thread.tx_thread_id) 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 32853e52..20d5c610 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 @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_deactivate PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -85,6 +85,11 @@ /* internal clean up, */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* added reception buffer, */ +/* removed internal NX pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -196,12 +201,16 @@ UINT status; /* free its stack memory. */ _ux_utility_memory_free(asix -> ux_host_class_asix_thread_stack); - /* We may have allocated a packet pool. */ - if (asix -> ux_host_class_asix_pool_memory != UX_NULL) - - /* Free this pool of packets. */ - _ux_utility_memory_free(asix -> ux_host_class_asix_pool_memory); - + /* Free receive buffer memory. */ + _ux_utility_memory_free(asix -> ux_host_class_asix_receive_buffer); + +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT + + /* Free transmit buffer memory. */ + if (asix -> ux_host_class_asix_xmit_buffer) + _ux_utility_memory_free(asix -> ux_host_class_asix_xmit_buffer); +#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) diff --git a/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c index 0fae599e..7e676704 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_endpoints_get PORTABLE C */ -/* 6.1.9 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -75,6 +75,10 @@ /* use pre-calculated value */ /* instead of wMaxPacketSize, */ /* resulting in version 6.1.9 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed packet RX callback, */ +/* refined INT EP start time, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_endpoints_get(UX_HOST_CLASS_ASIX *asix) @@ -156,9 +160,6 @@ UX_TRANSFER *transfer_request; /* There is a callback function associated with the transfer request, so we need the class instance. */ endpoint -> ux_endpoint_transfer_request.ux_transfer_request_class_instance = (VOID *) asix; - /* The transfer request has a callback function. */ - endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_function = _ux_host_class_asix_reception_callback; - /* We have found the bulk endpoint, save it. */ asix -> ux_host_class_asix_bulk_in_endpoint = endpoint; break; @@ -220,22 +221,8 @@ UX_TRANSFER *transfer_request; 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); - /* If the endpoint is available and we have memory, we start the interrupt endpoint. */ - if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) - { - - /* The transfer on the interrupt endpoint can be started. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check error, if endpoint interrupt IN transfer not successful, do not proceed. */ - if (status != UX_SUCCESS) - - /* Error, do not proceed. */ - return(status); - - } - - else + /* If the endpoint is available and we have memory, it's started later after setup. */ + if (transfer_request -> ux_transfer_request_data_pointer == UX_NULL) { /* Error trap. */ diff --git a/common/usbx_host_classes/src/ux_host_class_asix_entry.c b/common/usbx_host_classes/src/ux_host_class_asix_entry.c index 8d4716eb..aba59b59 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_entry.c @@ -30,12 +30,17 @@ #include "ux_host_stack.h" +#if !defined(UX_HOST_STANDALONE) +static inline UINT _ux_host_class_asix_try_all_vid_pids(UX_HOST_CLASS_COMMAND *command); +#endif + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_entry PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +79,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed compile warning, */ +/* refined VID/PID check flow, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_entry(UX_HOST_CLASS_COMMAND *command) @@ -97,17 +106,8 @@ UINT status; this device or not. */ if(command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_PIDVID) { - - /* Try all the possible PID/VID. */ - if ((command -> ux_host_class_command_pid == UX_HOST_CLASS_ASIX_PRODUCT_ID) && - (command -> ux_host_class_command_vid == UX_HOST_CLASS_ASIX_VENDOR_ID )) - return(UX_SUCCESS); - - /* Try all the possible PID/VID. */ - if ((command -> ux_host_class_command_pid == UX_HOST_CLASS_ASIX_PRODUCT_FUJIEI_ID) && - (command -> ux_host_class_command_vid == UX_HOST_CLASS_ASIX_VENDOR_FUJIEI_ID )) - return(UX_SUCCESS); - + if (_ux_host_class_asix_try_all_vid_pids(command) == UX_SUCCESS) + return(UX_SUCCESS); } /* No match. */ @@ -139,4 +139,23 @@ UINT status; } #endif } +#if !defined(UX_HOST_STANDALONE) +static const USHORT _ux_host_class_asix_vid_pid_array[] = +{ + UX_HOST_CLASS_ASIX_VID_PID_ARRAY +}; +static inline UINT _ux_host_class_asix_try_all_vid_pids(UX_HOST_CLASS_COMMAND *command) +{ +UINT i, pos; +UINT n_ids = sizeof(_ux_host_class_asix_vid_pid_array) >> 1; +UINT n_id_pairs = n_ids >> 1; + for (i = 0, pos = 0; i < n_id_pairs; i ++, pos += 2) + { + if ((command -> ux_host_class_command_pid == _ux_host_class_asix_vid_pid_array[pos + 1]) && + (command -> ux_host_class_command_vid == _ux_host_class_asix_vid_pid_array[pos ])) + return(UX_SUCCESS); + } + return(UX_NO_CLASS_MATCH); +} +#endif 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 2a4437a6..5717311a 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.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -76,6 +76,10 @@ /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ /* refined macros names, */ /* resulting in version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* refined link up/down flow, */ +/* refined interrupt flow, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_interrupt_notification(UX_TRANSFER *transfer_request) @@ -127,6 +131,8 @@ UX_HOST_CLASS_ASIX *asix; /* We need to inform the asix thread of this change. */ _ux_host_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + /* Reactivate interrupt pipe after link up handled. */ + return; } } else @@ -138,53 +144,20 @@ UX_HOST_CLASS_ASIX *asix; { /* Memorize the new link state. */ - asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN; - - /* We may have transaction pending on bulk in. Inform the class. */ - transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; - if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) - { - - /* Set the completion error code. */ - transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; - - /* 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) - - /* Wake up the semaphore on which the transaction is waiting. */ - _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); - - } - - /* We may have transaction pending on bulk out. Inform the class. */ - transfer_request = &asix -> ux_host_class_asix_bulk_out_endpoint -> ux_endpoint_transfer_request; - if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) - { - - /* Set the completion error code. */ - transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; - - /* Error trap. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN; - /* 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) - - /* Wake up the semaphore on which the transaction is waiting. */ - _ux_host_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + /* Abort possible pending bulk in requests. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_bulk_in_endpoint); - } - - /* We need to inform the asix thread of this change. */ _ux_host_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + + /* Reactivate interrupt pipe after link down handled. */ + return; } - } - } - } + } + } + } /* Reactivate the ASIX interrupt pipe. */ _ux_host_stack_transfer_request(transfer_request); diff --git a/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c index 75ad2e98..e6bff4c0 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_reception_callback PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -46,6 +46,8 @@ /* it is called when a full or partial transfer has been done for a */ /* bulk in transfer. It calls back the application. */ /* */ +/* It's deprecated. */ +/* */ /* INPUT */ /* */ /* transfer_request Pointer to transfer request */ @@ -76,6 +78,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* deprecated, no RX callback, */ +/* modified pool reference, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_reception_callback (UX_TRANSFER *transfer_request) @@ -125,7 +131,7 @@ UINT status; nx_packet_transmit_release(packet); /* We can accept new reception. Get a NX Packet */ - if (nx_packet_allocate(&asix -> ux_host_class_asix_packet_pool, &packet, + if (nx_packet_allocate(asix -> ux_host_class_asix_packet_pool, &packet, NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_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 96f48037..9e301ddf 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 @@ -31,12 +31,15 @@ #if !defined(UX_HOST_STANDALONE) + +static inline UINT _ux_host_class_asix_link_up_controls(UX_HOST_CLASS_ASIX *asix); + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -87,35 +90,49 @@ /* internal clean up, */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* removed internal NX pool, */ +/* moved NX driver activate, */ +/* refined control REQ flow, */ +/* refined reception flow, */ +/* refined interrupt flow, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_thread(ULONG parameter) { UX_HOST_CLASS_ASIX *asix; -UCHAR *setup_buffer; -UX_ENDPOINT *control_endpoint; UX_TRANSFER *transfer_request; NX_PACKET *packet; NX_PACKET *current_packet; NX_PACKET *next_packet; +UCHAR *buffer; +ULONG buffer_count; +ULONG asix_length; +ULONG asix_count; +ULONG asix_remain; +ULONG packet_discard; +ULONG buffer_remain; +ULONG copy_length; UINT status; -ULONG physical_address_msw; -ULONG physical_address_lsw; +UX_DEVICE *device; +ULONG available0, available1; +USB_NETWORK_DEVICE_TYPE *ux_nx_device; + /* Cast the parameter passed in the thread into the asix pointer. */ UX_THREAD_EXTENSION_PTR_GET(asix, UX_HOST_CLASS_ASIX, parameter) - /* Loop forever waiting for changes signaled through the semaphore. */ + /* Loop forever waiting for changes signaled through the semaphore. */ while (1) - { + { /* Wait for the semaphore to be put by the asix interrupt event. */ status = _ux_host_semaphore_get(&asix -> ux_host_class_asix_interrupt_notification_semaphore, UX_WAIT_FOREVER); /* Check for successful completion. */ if (status != UX_SUCCESS) - return; /* Protect Thread reentry to this instance. */ @@ -123,299 +140,323 @@ ULONG physical_address_lsw; /* Check for successful completion. */ if (status != UX_SUCCESS) - return; /* Check the link state. It is either pending up or down. */ if (asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP) { - /* We need to get the default control endpoint transfer request pointer. */ - control_endpoint = &asix -> ux_host_class_asix_device -> ux_device_control_endpoint; - transfer_request = &control_endpoint -> ux_endpoint_transfer_request; - - /* Need to allocate memory for the buffer. */ - setup_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE); - if (setup_buffer == UX_NULL) + /* Issue a list of control requests to setup link up. */ + status = _ux_host_class_asix_link_up_controls(asix); + if (status != UX_SUCCESS) { /* Unprotect thread reentry to this instance. */ _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + continue; + } - return; - } - - /* Request ownership of Serial Management Interface. */ - 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_ASIX_REQ_OWN_SMI ; - transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value = 0; - transfer_request -> ux_transfer_request_index = 0; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) - { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); + /* Now the link is up. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_UP; - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(asix -> ux_host_class_asix_network_handle); - /* Return completion status. */ - return; - - } - - /* Get the value of the PHYIDR1 in the PHY register. */ - transfer_request -> ux_transfer_request_data_pointer = setup_buffer; - transfer_request -> ux_transfer_request_requested_length = 2; - transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG; - transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; - transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_ANLPAR; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || - transfer_request -> ux_transfer_request_actual_length != 2) - { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); + /* Reactivate interrupt notification polling. */ + _ux_host_stack_transfer_request(&asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request); - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Unprotect thread reentry to this instance. */ + _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); - /* Return completion status. */ - return; - - } + /* Re-check packet pool on link up. */ + asix -> ux_host_class_asix_packet_pool = UX_NULL; - /* Release SMI ownership. */ - 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_ASIX_REQ_RELEASE_SMI; - transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value = 0; - transfer_request -> ux_transfer_request_index = 0; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) - { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); + /* Keep polling if device is connected and link is up. */ - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Initialize variables. */ + device = asix -> ux_host_class_asix_device; + packet = UX_NULL; + buffer = UX_NULL; + asix_length = 0; + asix_count = 0; + buffer_count = 0; + packet_discard = UX_FALSE; + asix -> ux_host_class_asix_packet_available_min = 0xFFFFFFFF; - /* Return completion status. */ - return; - - } - - /* Check speed. */ - if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS) - - /* Set speed at 100MBPS. */ - transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_MEDIUM_PS; - - /* Write the value of the Medium Mode. */ - 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_ASIX_REQ_WRITE_MEDIUM_MODE; - transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value |= (UX_HOST_CLASS_ASIX_MEDIUM_FD | UX_HOST_CLASS_ASIX_MEDIUM_BIT2 | UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED | - UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED | UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED); - transfer_request -> ux_transfer_request_index = 0; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + /* Polling loop. */ + while(device -> ux_device_state == UX_DEVICE_CONFIGURED && + asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_UP) { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Check if packet pool is ready. */ + if (asix -> ux_host_class_asix_packet_pool == UX_NULL) + { - /* Return completion status. */ - return; - - } + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(asix -> ux_host_class_asix_network_handle); - /* Set the Rx Control register value. */ - 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_ASIX_REQ_WRITE_RX_CTL; - transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_RXCR_AM | UX_HOST_CLASS_ASIX_RXCR_AB | - UX_HOST_CLASS_ASIX_RXCR_SO | UX_HOST_CLASS_ASIX_RXCR_MFB_2048); - transfer_request -> ux_transfer_request_index = 0; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) - { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); - - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Get packet pool from IP instance (if available). */ + if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL) + { + asix -> ux_host_class_asix_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool; + } + else + { - /* Return completion status. */ - return; - - } - - /* Set the multicast value. */ - transfer_request -> ux_transfer_request_data_pointer = setup_buffer; - transfer_request -> ux_transfer_request_requested_length = 8; - transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_MULTICAST_FILTER; - transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; - transfer_request -> ux_transfer_request_value = 0; - transfer_request -> ux_transfer_request_index = 0; - - /* Fill in the multicast filter. */ - _ux_utility_memory_set(setup_buffer, 0, 8); /* Use case of memset is verified. */ - *(setup_buffer +1) = 0x40; - - /* Send request to HCD layer. */ - status = _ux_host_stack_transfer_request(transfer_request); - - /* Check status, if error, do not proceed. */ - if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || - transfer_request -> ux_transfer_request_actual_length != 8) - { - - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); - - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR); - /* Return completion status. */ - return; - - } + _ux_utility_delay_ms(UX_HOST_CLASS_ASIX_PACKET_POOL_WAIT); + continue; + } + } - /* Free all used resources. */ - _ux_utility_memory_free(setup_buffer); + /* Get transfer request for bulk in reception. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; - /* Setup the physical address of this IP instance. */ - physical_address_msw = (ULONG)((asix -> ux_host_class_asix_node_id[0] << 8) | (asix -> ux_host_class_asix_node_id[1])); - physical_address_lsw = (ULONG)((asix -> ux_host_class_asix_node_id[2] << 24) | (asix -> ux_host_class_asix_node_id[3] << 16) | - (asix -> ux_host_class_asix_node_id[4] << 8) | (asix -> ux_host_class_asix_node_id[5])); - - /* Register this interface to the NetX USB interface broker. */ - status = _ux_network_driver_activate((VOID *) asix, _ux_host_class_asix_write, - &asix -> ux_host_class_asix_network_handle, - physical_address_msw, - physical_address_lsw); - if (status != UX_SUCCESS) - { + /* If there is no buffer ready, read it. */ + if (buffer == UX_NULL) + { - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = asix -> ux_host_class_asix_receive_buffer; + + /* And length. */ + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_ASIX_RECEIVE_BUFFER_SIZE; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Schedule a reception. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check if it's started successfully. */ + if (status != UX_SUCCESS) + { + + /* If a packet (chain) is on-going, release it. */ + if (packet != UX_NULL) + { + nx_packet_release(packet); + packet = UX_NULL; + } + continue; + } + + /* Wait for transfer completion. */ + _ux_host_semaphore_get_norc(&transfer_request -> ux_transfer_request_semaphore, UX_WAIT_FOREVER); + + /* Check completion code. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Abort transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* If a packet (chain) is on-going, release it. */ + if (packet != UX_NULL) + { + nx_packet_release(packet); + packet = UX_NULL; + } + continue; + } + + /* If it's ZLP, reset buffer and ASIX packet and transfer again. */ + if (transfer_request -> ux_transfer_request_actual_length == 0) + { + + /* Packet should have been processed! */ + if (packet != UX_NULL) + { + + /* ASIX header corrupt? */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + nx_packet_release(packet); + packet = UX_NULL; + } + + buffer = UX_NULL; + buffer_count = 0; + asix_length = 0; + continue; + } + + /* Buffer is ready. */ + buffer = asix -> ux_host_class_asix_receive_buffer; + } - /* Return completion status. */ - return; - } + /* There is data in buffer, extract the data to packets. */ - /* Now the link is up. */ - asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_UP; + /* If there is no packet, allocate it. */ + if (packet == UX_NULL) + { - /* Communicate the state with the network driver. */ - _ux_network_driver_link_up(asix -> ux_host_class_asix_network_handle); - - /* We can accept reception. Get a NX Packet */ - if (nx_packet_allocate(&asix -> ux_host_class_asix_packet_pool, &packet, - NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) - { + /* Get a free NX Packet. */ + available0 = asix -> ux_host_class_asix_packet_pool -> nx_packet_pool_available; + status = nx_packet_allocate(asix -> ux_host_class_asix_packet_pool, + &packet, NX_RECEIVE_PACKET, + UX_MS_TO_TICK(UX_HOST_CLASS_ASIX_PACKET_ALLOCATE_WAIT)); + available1 = asix -> ux_host_class_asix_packet_pool -> nx_packet_pool_available; + if (asix -> ux_host_class_asix_packet_available_min > available1) + asix -> ux_host_class_asix_packet_available_min = available1; + if (asix -> ux_host_class_asix_packet_available_min > available0) + asix -> ux_host_class_asix_packet_available_min = available0; + if (status != NX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_ERROR); + continue; + } + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr; + + /* Log the packet. */ + } - /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ - packet -> nx_packet_prepend_ptr += sizeof(USHORT); + /* Get remaining in buffer. */ + buffer_remain = transfer_request -> ux_transfer_request_actual_length - + buffer_count; - /* We have a packet. Link this packet to the reception transfer request on the bulk in endpoint. */ - transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; - - /* Set the data pointer. */ - transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; + /* For new packet, get packet length from ASIX header. */ + if (asix_length == 0) + { - /* And length. */ - transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE; - transfer_request -> ux_transfer_request_actual_length = 0; + /* If remaining less than 2 bytes in buffer, read buffer again. */ + if (buffer_remain < 2) + { + buffer = UX_NULL; + buffer_count = 0; + continue; + } + + /* Get ASIX packet length. */ + asix_length = _ux_utility_short_get(buffer + buffer_count); + asix_length &= UX_HOST_CLASS_ASIX_RX_PACKET_LENGTH_MASK; + asix_count = 0; + + /* If remaining 2-3 bytes, skip 2 of next buffer. */ + if (buffer_remain < 4) + { + buffer = UX_NULL; + buffer_count = 2; + continue; + } + + /* Skip header in buffer, it's not copied to NX packet. */ + buffer_count += 4; + buffer_remain -= 4; + } - /* Store the packet that owns this transaction. */ - transfer_request -> ux_transfer_request_user_specific = packet; + /* Get remaining in ASIX packet. */ + asix_remain = asix_length - asix_count; - /* Memorize this packet at the beginning of the queue. */ - asix -> ux_host_class_asix_receive_queue = packet; - - /* Reset the queue pointer of this packet. */ - packet -> nx_packet_queue_next = UX_NULL; + /* Get actual length to process. */ + if (asix_remain <= buffer_remain) + copy_length = asix_remain; + else + copy_length = buffer_remain; - /* Ask USB to schedule a reception. */ - status = _ux_host_stack_transfer_request(transfer_request); + /* Check if the data is discarded. */ + if (packet_discard == UX_FALSE && copy_length) + { - /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ - if (status != UX_SUCCESS) + /* Append data to packet. */ + status = nx_packet_data_append(packet, + buffer + buffer_count, copy_length, + asix -> ux_host_class_asix_packet_pool, + UX_MS_TO_TICK(UX_HOST_CLASS_ASIX_PACKET_ALLOCATE_WAIT)); + if (status != NX_SUCCESS) + { + + /* There is error, this ASIX packet is discarded. */ + packet_discard = UX_TRUE; + } + } + + /* Update counts. */ + buffer_count += copy_length; + asix_count += copy_length; + + /* If packet size is odd, padding one byte is ignored. */ + if (asix_length & 0x1u) + buffer_count ++; + + /* Check if buffer ends. */ + if (buffer_count >= transfer_request -> ux_transfer_request_actual_length) { + buffer = UX_NULL; + buffer_count = 0; + } - /* Cancel the packet. */ - asix -> ux_host_class_asix_receive_queue = UX_NULL; - + /* Check if ASIX packet ends. + * - ASIX count achieve its length. + * - Buffer achieve its end and it's a short packet. + */ + if (asix_count >= asix_length || + (buffer == UX_NULL && + transfer_request -> ux_transfer_request_actual_length < + transfer_request -> ux_transfer_request_requested_length)) + { + + /* Check if packet is discarded. */ + if (packet_discard) + { + + packet_discard = UX_FALSE; + + /* Re-allocate packet. */ + nx_packet_release(packet); + packet = UX_NULL; + continue; + } + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(asix -> ux_host_class_asix_network_handle, packet); + packet = UX_NULL; + + /* Reset ASIX packet. */ + asix_length = 0; + + continue; } + /* Buffer ends but packet continues. */ + /* Buffer already reset to start reception again. */ } - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); - - return; + /* Release packet not sent to NX. */ + if (packet) + nx_packet_release(packet); } - - /* Check the link state. It is either pending up or down. */ - if (asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN) + else { - + + /* Abort pending transfers. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_bulk_out_endpoint); + /* We need to free the packets that will not be sent. */ current_packet = asix -> ux_host_class_asix_xmit_queue; - + /* Get the next packet associated with the first packet. */ next_packet = current_packet -> nx_packet_queue_next; - + /* Parse all these packets that were scheduled. */ while (current_packet != UX_NULL) { - + /* Free the packet that was just sent. First do some housekeeping. */ - current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_ASIX_ETHERNET_SIZE; /* And ask Netx to release it. */ - nx_packet_transmit_release(current_packet); - + nx_packet_transmit_release(current_packet); + /* Next packet becomes the current one. */ current_packet = next_packet; - + /* Next packet now. */ if (current_packet != UX_NULL) @@ -423,20 +464,176 @@ ULONG physical_address_lsw; next_packet = current_packet -> nx_packet_queue_next; } - + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_down(asix -> ux_host_class_asix_network_handle); /* Now the link is down. */ asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_DOWN; - /* Communicate the state with the network driver. */ - _ux_network_driver_link_down(asix -> ux_host_class_asix_network_handle); - + /* Reactivate interrupt notification polling. */ + _ux_host_stack_transfer_request(&asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request); + /* Unprotect thread reentry to this instance. */ _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); - - return; - } } } + +static inline UINT _ux_host_class_asix_link_up_controls(UX_HOST_CLASS_ASIX *asix) +{ + +UCHAR *setup_buffer; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &asix -> ux_host_class_asix_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the buffer. */ + setup_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE); + if (setup_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Request ownership of Serial Management Interface. */ + 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_ASIX_REQ_OWN_SMI ; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Get the value of the PHYIDR1 in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_ANLPAR; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Release SMI ownership. */ + 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_ASIX_REQ_RELEASE_SMI; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Check speed. */ + if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS) + + /* Set speed at 100MBPS. */ + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_MEDIUM_PS; + + /* Write the value of the Medium Mode. */ + 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_ASIX_REQ_WRITE_MEDIUM_MODE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value |= (UX_HOST_CLASS_ASIX_MEDIUM_FD | UX_HOST_CLASS_ASIX_MEDIUM_BIT2 | UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED | + UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED | UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Set the Rx Control register value. */ + 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_ASIX_REQ_WRITE_RX_CTL; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_RXCR_AM | UX_HOST_CLASS_ASIX_RXCR_AB | + UX_HOST_CLASS_ASIX_RXCR_SO | UX_HOST_CLASS_ASIX_RXCR_MFB_2048); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Set the multicast value. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 8; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_MULTICAST_FILTER; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Fill in the multicast filter. */ + _ux_utility_memory_set(setup_buffer, 0, 8); /* Use case of memset is verified. */ + *(setup_buffer +1) = 0x40; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 8) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_TRANSFER_ERROR); + } + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + return(UX_SUCCESS); +} #endif diff --git a/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c b/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c index 204af595..13f29678 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_transmission_callback PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,10 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* fixed empty queue handling, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_asix_transmission_callback (UX_TRANSFER *transfer_request) @@ -89,6 +93,9 @@ UX_HOST_CLASS_ASIX *asix; NX_PACKET *current_packet; NX_PACKET *next_packet; UCHAR *packet_header; +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT +ULONG copied; +#endif /* Get the class instance for this transfer request. */ asix = (UX_HOST_CLASS_ASIX *) transfer_request -> ux_transfer_request_class_instance; @@ -110,7 +117,19 @@ UCHAR *packet_header; /* Check if there is another transfer for this pipe. */ current_packet = asix -> ux_host_class_asix_xmit_queue; - + if (current_packet == UX_NULL) + return; + + /* Check if a ZLP is needed. */ + if ((transfer_request -> ux_transfer_request_actual_length > 0) && + ((transfer_request -> ux_transfer_request_actual_length % + transfer_request -> ux_transfer_request_packet_length) == 0)) + { + transfer_request -> ux_transfer_request_requested_length = 0; + _ux_host_stack_transfer_request(transfer_request); + return; + } + /* Get the next packet associated with the first packet. */ next_packet = current_packet -> nx_packet_queue_next; @@ -132,10 +151,33 @@ UCHAR *packet_header; /* Store the negative length of the payload in the first USHORT. */ _ux_utility_short_put(packet_header+ sizeof(USHORT), (USHORT)(~next_packet -> nx_packet_length)); - - /* Prepare the values for this new transmission. */ - transfer_request -> ux_transfer_request_data_pointer = packet_header; - transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length + (ULONG)sizeof(USHORT) * 2; + +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT + + /* Check if the packets are chained. */ + if (next_packet -> nx_packet_next) + { + + next_packet -> nx_packet_length += sizeof(USHORT) * 2; + next_packet -> nx_packet_prepend_ptr -= sizeof(USHORT) * 2; + nx_packet_data_extract_offset(next_packet, 0, asix -> ux_host_class_asix_xmit_buffer, next_packet -> nx_packet_length, &copied); + + /* Setup the transaction parameters. */ + transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length; + transfer_request -> ux_transfer_request_data_pointer = asix -> ux_host_class_asix_xmit_buffer; + + /* Restore packet status. */ + next_packet -> nx_packet_length -= sizeof(USHORT) * 2; + next_packet -> nx_packet_prepend_ptr += sizeof(USHORT) * 2; + } + else +#endif + { + + /* Prepare the values for this new transmission. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length + (ULONG)sizeof(USHORT) * 2; + } /* Store the packet that owns this transaction. */ transfer_request -> ux_transfer_request_user_specific = next_packet; diff --git a/common/usbx_host_classes/src/ux_host_class_asix_write.c b/common/usbx_host_classes/src/ux_host_class_asix_write.c index d30bf62c..175e9b6f 100644 --- a/common/usbx_host_classes/src/ux_host_class_asix_write.c +++ b/common/usbx_host_classes/src/ux_host_class_asix_write.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_asix_write PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -77,6 +77,11 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* added queue modify protect, */ +/* improved error check, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_asix_write(VOID *asix_class, NX_PACKET *packet) @@ -87,12 +92,17 @@ UINT _ux_host_class_asix_write(VOID *asix_class, NX_PACKET *packet) return(UX_FUNCTION_NOT_SUPPORTED); #else +UX_INTERRUPT_SAVE_AREA UX_TRANSFER *transfer_request; UINT status; NX_PACKET *current_packet; NX_PACKET *next_packet; UCHAR *packet_header; UX_HOST_CLASS_ASIX *asix; +ULONG adjusted_length; +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT +ULONG copied; +#endif /* Proper class casting. */ asix = (UX_HOST_CLASS_ASIX *) asix_class; @@ -100,6 +110,9 @@ UX_HOST_CLASS_ASIX *asix; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_WRITE, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + /* Critical enter. */ + UX_DISABLE + /* Ensure the instance is valid. */ if (asix -> ux_host_class_asix_state != UX_HOST_CLASS_INSTANCE_LIVE) { @@ -110,9 +123,28 @@ UX_HOST_CLASS_ASIX *asix; /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + /* Critical exit. */ + UX_RESTORE; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } + /* Ensure link state is OK. */ + if (asix -> ux_host_class_asix_link_state != UX_HOST_CLASS_ASIX_LINK_STATE_UP) + { + + /* Critical exit. */ + UX_RESTORE; + + /* Release the packet. */ + packet -> nx_packet_prepend_ptr = packet -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; + packet -> nx_packet_length = packet -> nx_packet_length - NX_ETHERNET_SIZE; + nx_packet_transmit_release(packet); + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_LINK_STATE_DOWN_ERROR); + return(UX_CLASS_ETH_LINK_STATE_DOWN_ERROR); + } + /* Load the address of the current packet header at the physical header. */ packet_header = packet -> nx_packet_prepend_ptr; @@ -120,16 +152,38 @@ UX_HOST_CLASS_ASIX *asix; packet_header -= sizeof(USHORT) * 2; #if defined(UX_HOST_CLASS_ASIX_HEADER_CHECK_ENABLE) + /* Check packet compatibility to avoid writing to unexpected area. */ if (packet_header < packet -> nx_packet_data_start) { /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + + UX_RESTORE; return(UX_HOST_CLASS_MEMORY_ERROR); } #endif + /* Packet length validation. */ + if (UX_OVERFLOW_CHECK_ADD_ULONG(packet -> nx_packet_length, sizeof(USHORT) * 2)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MATH_OVERFLOW); + UX_RESTORE + return(UX_MATH_OVERFLOW); + } + adjusted_length = packet -> nx_packet_length + sizeof(USHORT) * 2; + if (adjusted_length > UX_HOST_CLASS_ASIX_TRANSMIT_BUFFER_SIZE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_SIZE_ERROR); + UX_RESTORE + return(UX_CLASS_ETH_SIZE_ERROR); + } + /* Store the length of the payload in the first USHORT. */ _ux_utility_short_put(packet_header, (USHORT)(packet -> nx_packet_length)); @@ -140,14 +194,57 @@ UX_HOST_CLASS_ASIX *asix; if (asix -> ux_host_class_asix_xmit_queue == UX_NULL) { + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Memorize this packet at the beginning of the queue. */ + asix -> ux_host_class_asix_xmit_queue = packet; + + UX_RESTORE + /* Nothing is in the queue. We need to arm this transfer. */ /* Get the pointer to the bulk out endpoint transfer request. */ transfer_request = &asix -> ux_host_class_asix_bulk_out_endpoint -> ux_endpoint_transfer_request; - /* Setup the transaction parameters. */ - transfer_request -> ux_transfer_request_data_pointer = packet_header; - transfer_request -> ux_transfer_request_requested_length = packet -> nx_packet_length + (ULONG)sizeof(USHORT) * 2; - +#ifdef UX_HOST_CLASS_ASIX_PACKET_CHAIN_SUPPORT + + /* Check if the packets are chained. */ + if (packet -> nx_packet_next) + { + + /* Create buffer. */ + if (asix -> ux_host_class_asix_xmit_buffer == UX_NULL) + { + asix -> ux_host_class_asix_xmit_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, + UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_TRANSMIT_BUFFER_SIZE); + if (asix -> ux_host_class_asix_xmit_buffer == UX_NULL) + { + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + return(UX_MEMORY_INSUFFICIENT); + } + } + + packet -> nx_packet_length = adjusted_length; + packet -> nx_packet_prepend_ptr -= sizeof(USHORT) * 2; + nx_packet_data_extract_offset(packet, 0, asix -> ux_host_class_asix_xmit_buffer, packet -> nx_packet_length, &copied); + + /* Setup the transaction parameters. */ + transfer_request -> ux_transfer_request_requested_length = packet -> nx_packet_length; + transfer_request -> ux_transfer_request_data_pointer = asix -> ux_host_class_asix_xmit_buffer; + + /* Restore packet status. */ + packet -> nx_packet_length -= sizeof(USHORT) * 2; + packet -> nx_packet_prepend_ptr += sizeof(USHORT) * 2; + } + else +#endif + { + + /* Setup the transaction parameters. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = adjusted_length; + } + /* Store the packet that owns this transaction. */ transfer_request -> ux_transfer_request_user_specific = packet; @@ -155,22 +252,13 @@ UX_HOST_CLASS_ASIX *asix; status = _ux_host_stack_transfer_request(transfer_request); /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ - if (status == UX_SUCCESS) + if (status != UX_SUCCESS) { - - /* Memorize this packet at the beginning of the queue. */ - asix -> ux_host_class_asix_xmit_queue = packet; - - /* Reset the queue pointer of this packet. */ - packet -> nx_packet_queue_next = UX_NULL; - - } - - else /* Could not arm this transfer. */ + asix -> ux_host_class_asix_xmit_queue = UX_NULL; return(UX_ERROR); - + } } else @@ -199,6 +287,8 @@ UX_HOST_CLASS_ASIX *asix; /* The packet to be sent is the last in the chain. */ packet -> nx_packet_queue_next = NX_NULL; + + UX_RESTORE } /* We are done here. */ 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 3d1dfde8..f2613314 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 @@ -37,7 +37,7 @@ UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -100,6 +100,10 @@ UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* deprecated ECM pool option, */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_activate(UX_HOST_CLASS_COMMAND *command) @@ -208,19 +212,7 @@ UX_INTERFACE *cur_interface; if (cdc_ecm -> ux_host_class_cdc_ecm_thread_stack == UX_NULL) status = UX_MEMORY_INSUFFICIENT; } -#ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX - if (status == UX_SUCCESS) - { - /* Allocate some packet pool for reception. - * UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by - * UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. - */ - cdc_ecm -> ux_host_class_cdc_ecm_pool_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); - if (cdc_ecm -> ux_host_class_cdc_ecm_pool_memory == UX_NULL) - status = UX_MEMORY_INSUFFICIENT; - } -#endif if (status == UX_SUCCESS) { @@ -240,126 +232,110 @@ UX_INTERFACE *cur_interface; 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 - /* Create a packet pool. */ - status = nx_packet_pool_create(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, "host CDC-ECM packet pool", - UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, cdc_ecm -> ux_host_class_cdc_ecm_pool_memory, UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); + + /* Create the cdc_ecm class thread. We do not start it yet. */ + status = _ux_utility_thread_create(&cdc_ecm -> ux_host_class_cdc_ecm_thread, + "ux_host_cdc_ecm_thread", _ux_host_class_cdc_ecm_thread, + (ULONG) (ALIGN_TYPE) cdc_ecm, + cdc_ecm -> ux_host_class_cdc_ecm_thread_stack, + UX_THREAD_STACK_SIZE, + UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, + UX_NO_TIME_SLICE, UX_DONT_START); if (status == UX_SUCCESS) { -#endif - /* Create the cdc_ecm class thread. We do not start it yet. */ - status = _ux_utility_thread_create(&cdc_ecm -> ux_host_class_cdc_ecm_thread, - "ux_host_cdc_ecm_thread", _ux_host_class_cdc_ecm_thread, - (ULONG) (ALIGN_TYPE) cdc_ecm, - cdc_ecm -> ux_host_class_cdc_ecm_thread_stack, - UX_THREAD_STACK_SIZE, - UX_THREAD_PRIORITY_CLASS, - UX_THREAD_PRIORITY_CLASS, - UX_NO_TIME_SLICE, UX_DONT_START); + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_host_class_cdc_ecm_thread), cdc_ecm) + + /* We now need to retrieve the MAC address of the node which is embedded in the ECM descriptor. + We will parse the entire configuration descriptor of the device and look for the ECM Ethernet Networking Functional Descriptor. */ + status = _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm); + if (status == UX_SUCCESS) { - UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_host_class_cdc_ecm_thread), cdc_ecm) + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[0] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[1])); + physical_address_lsw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[2] << 24) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[3] << 16) | + (cdc_ecm -> ux_host_class_cdc_ecm_node_id[4] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[5])); - /* We now need to retrieve the MAC address of the node which is embedded in the ECM descriptor. - We will parse the entire configuration descriptor of the device and look for the ECM Ethernet Networking Functional Descriptor. */ - status = _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm); + /* The ethernet link is down by default. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN; + } - if (status == UX_SUCCESS) - { + if (status == UX_SUCCESS) + { - /* Setup the physical address of this IP instance. */ - physical_address_msw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[0] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[1])); - physical_address_lsw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[2] << 24) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[3] << 16) | - (cdc_ecm -> ux_host_class_cdc_ecm_node_id[4] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[5])); + /* Register this interface to the NetX USB interface broker. */ + status = _ux_network_driver_activate((VOID *) cdc_ecm, _ux_host_class_cdc_ecm_write, + &cdc_ecm -> ux_host_class_cdc_ecm_network_handle, + physical_address_msw, physical_address_lsw); + } - /* The ethernet link is down by default. */ - cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN; - } + if (status == UX_SUCCESS) + { - if (status == UX_SUCCESS) + /* Mark the cdc_ecm data instance as live now. */ + cdc_ecm -> ux_host_class_cdc_ecm_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* This instance of the device must also be stored in the interface container. */ + interface_ptr -> ux_interface_class_instance = (VOID *) cdc_ecm; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + + /* Start the interrupt pipe now if it exists. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) { - /* Register this interface to the NetX USB interface broker. */ - status = _ux_network_driver_activate((VOID *) cdc_ecm, _ux_host_class_cdc_ecm_write, - &cdc_ecm -> ux_host_class_cdc_ecm_network_handle, - physical_address_msw, physical_address_lsw); + /* Obtain the transfer request from the interrupt endpoint. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request; + status = _ux_host_stack_transfer_request(transfer_request); } if (status == UX_SUCCESS) { - /* Mark the cdc_ecm data instance as live now. */ - cdc_ecm -> ux_host_class_cdc_ecm_state = UX_HOST_CLASS_INSTANCE_LIVE; + /* Activation is complete. */ - /* This instance of the device must also be stored in the interface container. */ - interface_ptr -> ux_interface_class_instance = (VOID *) cdc_ecm; + /* Now we can start the CDC-ECM thread. */ + _ux_utility_thread_resume(&cdc_ecm -> ux_host_class_cdc_ecm_thread); - /* Create this class instance. */ - _ux_host_stack_class_instance_create(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); - - /* Start the interrupt pipe now if it exists. */ - if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) + /* We 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) { - - /* Obtain the transfer request from the interrupt endpoint. */ - transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request; - status = _ux_host_stack_transfer_request(transfer_request); + + /* Call system change function. Note that the application should + wait until the link state is up until using this instance. The + link state is changed to up by the CDC-ECM thread, which isn't + started until after the data interface has been processed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) - if (status == UX_SUCCESS) - { - - /* Activation is complete. */ - - /* Now we can start the CDC-ECM thread. */ - _ux_utility_thread_resume(&cdc_ecm -> ux_host_class_cdc_ecm_thread); - - /* We 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. Note that the application should - wait until the link state is up until using this instance. The - link state is changed to up by the CDC-ECM thread, which isn't - started until after the data interface has been processed. */ - _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); - } - - /* If trace is enabled, insert this event into the trace buffer. */ - UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 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_ecm, 0, 0, 0) - - /* Activation was successful. */ - return(UX_SUCCESS); - } + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0) - /* Error starting interrupt endpoint. */ + /* Activation was successful. */ + return(UX_SUCCESS); + } - /* Destroy this class instance. */ - _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + /* Error starting interrupt endpoint. */ - /* Unmount instance. */ - interface_ptr -> ux_interface_class_instance = UX_NULL; - } + /* Destroy this class instance. */ + _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); - /* Delete CDC-ECM thread. */ - _ux_utility_thread_delete(&cdc_ecm -> ux_host_class_cdc_ecm_thread); + /* Unmount instance. */ + interface_ptr -> ux_interface_class_instance = UX_NULL; } -#ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX - /* Delete packet pool. */ - nx_packet_pool_delete(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool); - } - else - { - /* Packet pool creation failed. Notify application. */ - _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, status); + /* Delete CDC-ECM thread. */ + _ux_utility_thread_delete(&cdc_ecm -> ux_host_class_cdc_ecm_thread); } -#endif + /* Delete interrupt notification semaphore. */ _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); } @@ -378,10 +354,7 @@ UX_INTERFACE *cur_interface; if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL && cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer != UX_NULL) _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); -#ifndef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX - if (cdc_ecm -> ux_host_class_cdc_ecm_pool_memory != UX_NULL) - _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_pool_memory); -#endif + if (cdc_ecm -> ux_host_class_cdc_ecm_thread_stack != UX_NULL) _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_thread_stack); 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 ec561e9e..3273259f 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 @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_deactivate PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -89,6 +89,10 @@ /* internal clean up, */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* deprecated ECM pool option, */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -191,13 +195,16 @@ UX_TRANSFER *transfer_request; /* Destroy the 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); - /* Free this pool of packets. */ - _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_pool_memory); +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + + /* Free packet transmission memories. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer); + if (cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer); #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) diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c index 6a65d57d..ea9f968d 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_mac_address_get PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* checked MAC string length, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* checked descriptor length, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_mac_address_get(UX_HOST_CLASS_CDC_ECM *cdc_ecm) @@ -168,6 +171,20 @@ UCHAR element_hexa_lower; descriptor_length = *descriptor; descriptor_type = *(descriptor + 1); descriptor_subtype = *(descriptor + 2); + + /* Descriptor length validation. */ + if (descriptor_length < 3 || descriptor_length > total_configuration_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* Free descriptor memory. */ + _ux_utility_memory_free(start_descriptor); + + /* Return error. */ + return(UX_DESCRIPTOR_CORRUPTED); + } /* Check the type for an interface descriptor and the subtype for a ECM functional descriptor. */ if ((descriptor_type == UX_HOST_CLASS_CDC_ECM_CS_INTERFACE) && (descriptor_subtype == UX_HOST_CLASS_CDC_ECM_FUNCTIONAL_DESCRIPTOR)) 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 24a36e86..fbed5829 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 @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_thread PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -94,6 +94,11 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* no length from IP header, */ +/* deprecated ECM pool option, */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_cdc_ecm_thread(ULONG parameter) @@ -102,11 +107,10 @@ VOID _ux_host_class_cdc_ecm_thread(ULONG parameter) UX_HOST_CLASS_CDC_ECM *cdc_ecm; UX_TRANSFER *transfer_request; NX_PACKET *packet; -ULONG ip_given_length; UINT status; -#ifdef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; -#endif +ULONG packet_buffer_size; + /* Cast the parameter passed in the thread into the cdc_ecm pointer. */ UX_THREAD_EXTENSION_PTR_GET(cdc_ecm, UX_HOST_CLASS_CDC_ECM, parameter) @@ -132,7 +136,6 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; while ((cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) && (cdc_ecm -> ux_host_class_cdc_ecm_device -> ux_device_state == UX_DEVICE_CONFIGURED)) { -#ifdef UX_HOST_CLASS_CDC_ECM_USE_PACKET_POOL_FROM_NETX /* Check if we have packet pool available. */ if (cdc_ecm -> ux_host_class_cdc_ecm_packet_pool == UX_NULL) @@ -152,7 +155,7 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; { /* IP instance is not available, wait for application to attach the interface. */ - _ux_utility_delay_ms(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_INSTANCE_WAIT); + _ux_utility_delay_ms(UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_INSTANCE_WAIT)); } continue; } @@ -160,13 +163,7 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; /* We can accept reception. Get a NX Packet. */ status = nx_packet_allocate(cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, &packet, NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT)); -#else - - /* We can accept reception. Get a NX Packet. */ - status = nx_packet_allocate(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, &packet, - NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT)); -#endif if (status == NX_SUCCESS) { @@ -175,10 +172,46 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; /* We have a packet. Link this packet to the reception transfer request on the bulk in endpoint. */ transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request; - - /* Set the data pointer. */ - transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; - + +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + + /* Check packet buffer size, if too small chain is used. */ + packet_buffer_size = (ULONG)(packet -> nx_packet_data_end - packet -> nx_packet_prepend_ptr); + if (packet_buffer_size < UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE) + { + if (cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer == UX_NULL) + { + cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer = + _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE); + if (cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer == UX_NULL) + { + + /* Memory allocation fail. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Release packet. */ + nx_packet_release(packet); + + /* Delay to let other threads to run. */ + _ux_utility_delay_ms(1); + continue; + } + + } + + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer; + } + else +#endif + { + + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; + + } + /* And length. */ transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE; transfer_request -> ux_transfer_request_actual_length = 0; @@ -216,21 +249,43 @@ USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) { - /* Get the packet length. */ - packet -> nx_packet_length = transfer_request -> ux_transfer_request_actual_length; - - /* Adjust the prepend, length, and append fields. */ - packet -> nx_packet_append_ptr = - packet->nx_packet_prepend_ptr + transfer_request -> ux_transfer_request_actual_length; - - /* Calculate the accurate packet length from ip header */ - if ((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && - (*(packet -> nx_packet_prepend_ptr + 13) == 0)) +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + + /* Check if transfer buffer is used. */ + if (packet -> nx_packet_prepend_ptr != + transfer_request -> ux_transfer_request_data_pointer) + { + + /* Adjust append_ptr for copy. */ + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr; + + /* Append data to packet. */ + status = nx_packet_data_append(packet, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length, + cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, + UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT)); + if (status != NX_SUCCESS) + { + + /* Release packet. */ + nx_packet_release(packet); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_ERROR); + continue; + } + } + else +#endif { - ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; - packet->nx_packet_length = ip_given_length ; - packet->nx_packet_append_ptr = packet->nx_packet_prepend_ptr + ip_given_length; + /* Get the packet length. */ + packet -> nx_packet_length = transfer_request -> ux_transfer_request_actual_length; + + /* Adjust the prepend, length, and append fields. */ + packet -> nx_packet_append_ptr = + packet->nx_packet_prepend_ptr + transfer_request -> ux_transfer_request_actual_length; } /* Send that packet to the NetX USB broker. */ diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c index 506097e8..157f95d1 100644 --- a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_transmission_callback PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_cdc_ecm_transmission_callback(UX_TRANSFER *transfer_request) @@ -92,6 +95,9 @@ UX_HOST_CLASS_CDC_ECM *cdc_ecm; NX_PACKET *current_packet; NX_PACKET *next_packet; UCHAR *packet_header; +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT +ULONG copied; +#endif /* Get the data and control class instances for this transfer request. */ cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance; @@ -150,8 +156,22 @@ UCHAR *packet_header; if (next_packet != UX_NULL) { - /* Load the address of the current packet header at the physical header. */ - packet_header = next_packet -> nx_packet_prepend_ptr; +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + + if (next_packet -> nx_packet_next != UX_NULL) + { + + /* Put packet to continuous buffer to transfer. */ + packet_header = cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer; + nx_packet_data_extract_offset(next_packet, 0, packet_header, next_packet -> nx_packet_length, &copied); + } + else +#endif + { + + /* Load the address of the current packet header at the physical header. */ + packet_header = next_packet -> nx_packet_prepend_ptr; + } /* Prepare the values for this new transmission. */ transfer_request -> ux_transfer_request_data_pointer = packet_header; 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 f88878e3..76667e10 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 @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_cdc_ecm_write PORTABLE C */ -/* 6.1.11 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ /* fixed standalone compile, */ /* resulting in version 6.1.11 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* supported NX packet chain, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet) @@ -92,6 +95,9 @@ UX_TRANSFER *transfer_request; UINT status; UCHAR *packet_header; UX_HOST_CLASS_CDC_ECM *cdc_ecm; +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT +ULONG copied; +#endif /* Get the instance. */ cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) cdc_ecm_class; @@ -124,6 +130,22 @@ UX_HOST_CLASS_CDC_ECM *cdc_ecm; return(UX_HOST_CLASS_INSTANCE_UNKNOWN); } + /* Validate packet length. */ + if (packet -> nx_packet_length > UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE) + { + + /* Restore interrupts. */ + UX_RESTORE + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_SIZE_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CLASS_ETH_SIZE_ERROR, cdc_ecm, packet -> nx_packet_length, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CLASS_ETH_SIZE_ERROR); + } + /* Are we in a valid state? */ if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) { @@ -147,8 +169,35 @@ UX_HOST_CLASS_CDC_ECM *cdc_ecm; /* Get the pointer to the bulk out endpoint transfer request. */ transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_endpoint -> ux_endpoint_transfer_request; - /* Load the address of the current packet header at the physical header. */ - packet_header = packet -> nx_packet_prepend_ptr; +#ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT + + if (packet -> nx_packet_next != UX_NULL) + { + + /* Create buffer. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer == UX_NULL) + { + cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, + UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE); + if (cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer == UX_NULL) + { + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + return(UX_MEMORY_INSUFFICIENT); + } + } + + /* Put packet to continuous buffer to transfer. */ + packet_header = cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer; + nx_packet_data_extract_offset(packet, 0, packet_header, packet -> nx_packet_length, &copied); + } + else +#endif + { + + /* Load the address of the current packet header at the physical header. */ + packet_header = packet -> nx_packet_prepend_ptr; + + } /* Setup the transaction parameters. */ transfer_request -> ux_transfer_request_data_pointer = packet_header; 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 index 37aa1e7f..3fdd9d16 100644 --- 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 @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hid_keyboard_tasks_run PORTABLE C */ -/* 6.1.10 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -71,6 +71,10 @@ /* DATE NAME DESCRIPTION */ /* */ /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved HID OUTPUT report */ +/* handling in standalone mode,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _ux_host_class_hid_keyboard_tasks_run(UX_HOST_CLASS_HID_CLIENT *client) @@ -108,12 +112,22 @@ UINT status; 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); + if (keyboard -> ux_host_class_hid_keyboard_out_report == UX_NULL) + { + + 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); + if (status != UX_SUCCESS) + { + keyboard -> ux_host_class_hid_keyboard_status = status; + return; + } + keyboard -> ux_host_class_hid_keyboard_out_report = report_id.ux_host_class_hid_report_get_report; + } /* 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 = keyboard -> ux_host_class_hid_keyboard_out_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; diff --git a/common/usbx_host_classes/src/ux_host_class_hub_entry.c b/common/usbx_host_classes/src/ux_host_class_hub_entry.c index abc47704..9a968d85 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_entry.c @@ -41,7 +41,7 @@ static inline UINT _ux_host_class_hub_activate_wait(UX_HOST_CLASS_COMMAND *comma /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_entry PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -80,7 +80,10 @@ static inline UINT _ux_host_class_hub_activate_wait(UX_HOST_CLASS_COMMAND *comma /* resulting in version 6.1 */ /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ /* added standalone support, */ -/* resulting in version 6.1 */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed power on delay calc, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_hub_entry(UX_HOST_CLASS_COMMAND *command) @@ -356,7 +359,7 @@ ULONG current_ms, elapsed_ms; /* Delay a while (as described by hub descriptor). */ hub -> ux_host_class_hub_wait_start = _ux_utility_time_get(); - hub -> ux_host_class_hub_wait_ms = hub -> ux_host_class_hub_descriptor.bPwrOn2PwrGood; + hub -> ux_host_class_hub_wait_ms = UX_MS_TO_TICK_NON_ZERO(hub -> ux_host_class_hub_descriptor.bPwrOn2PwrGood << 1); hub -> ux_host_class_hub_enum_state = UX_HOST_CLASS_HUB_ENUM_TRANS_WAIT; hub -> ux_host_class_hub_next_state = UX_HOST_CLASS_HUB_ENUM_PORT_POWER_ON; diff --git a/common/usbx_host_classes/src/ux_host_class_hub_tasks_run.c b/common/usbx_host_classes/src/ux_host_class_hub_tasks_run.c index c0363f33..2702c39b 100644 --- a/common/usbx_host_classes/src/ux_host_class_hub_tasks_run.c +++ b/common/usbx_host_classes/src/ux_host_class_hub_tasks_run.c @@ -40,7 +40,7 @@ static inline VOID _ux_host_class_hub_inst_tasks_run(UX_HOST_CLASS_HUB *hub); /* FUNCTION RELEASE */ /* */ /* _ux_host_class_hub_tasks_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -87,6 +87,9 @@ static inline VOID _ux_host_class_hub_inst_tasks_run(UX_HOST_CLASS_HUB *hub); /* DATE NAME DESCRIPTION */ /* */ /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* fixed reset speed handling, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_hub_tasks_run(UX_HOST_CLASS *hub_class) @@ -209,9 +212,11 @@ USHORT port_change = hub -> ux_host_class_hub_run_port_change; } static inline VOID _ux_host_class_hub_inst_tasks_run(UX_HOST_CLASS_HUB *hub) { +UX_HCD *hcd; UX_DEVICE *device; UX_DEVICE *hub_device = hub -> ux_host_class_hub_device; UX_ENDPOINT *ep0 = &hub_device -> ux_device_control_endpoint; +UX_ENDPOINT *dev_ep0; UX_TRANSFER *trans0 = &ep0 -> ux_endpoint_transfer_request; UINT status; @@ -385,16 +390,41 @@ UINT status; /* Save status and speed. */ device -> ux_device_enum_port_status = (UCHAR)hub -> ux_host_class_hub_run_port_status; + /* Append speed information. */ + switch(hub -> ux_host_class_hub_run_port_status & + (UX_HOST_CLASS_HUB_PORT_STATUS_LOW_SPEED | UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED)) + { + case 0: /* It's Full speed. */ + device -> ux_device_enum_port_status |= UX_PS_DS_FS; + device -> ux_device_speed = UX_FULL_SPEED_DEVICE; + break; + + case UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED: /* It's high speed. */ + device -> ux_device_enum_port_status |= UX_PS_DS_HS; + device -> ux_device_speed = UX_HIGH_SPEED_DEVICE; + break; + + default: /* It's Low speed. */ + device -> ux_device_speed = UX_LOW_SPEED_DEVICE; + break; + } + /* Return device address to 0. */ + hcd = UX_DEVICE_HCD_GET(device); if (device -> ux_device_address) { /* Free the address. */ - UX_DEVICE_HCD_GET(device) -> - ux_hcd_address[(device -> ux_device_address-1) >> 3] &= + hcd -> ux_hcd_address[(device -> ux_device_address-1) >> 3] &= (UCHAR)(1u << ((device -> ux_device_address-1) & 7u)); + } + /* Assume speed change, re-create EP0 at the HCD level. */ + dev_ep0 = &device -> ux_device_control_endpoint; + hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *)dev_ep0); + hcd -> ux_hcd_entry_function(hcd, UX_HCD_CREATE_ENDPOINT, (VOID *)dev_ep0); + /* Wait a while and set address. */ device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_ADDR_SET; device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT; 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 old mode 100755 new mode 100644 diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_open.c b/common/usbx_host_classes/src/ux_host_class_storage_media_open.c index 3da94807..71243767 100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_media_open.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_open.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_media_open PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -81,6 +81,9 @@ /* class specific structured */ /* data, */ /* resulting in version 6.1 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* added buffer size check, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_media_open(UX_HOST_CLASS_STORAGE *storage, ULONG hidden_sectors) @@ -127,6 +130,16 @@ UX_HOST_CLASS *class_inst; /* Save the Sector size in the storage media instance. */ storage_media -> ux_host_class_storage_media_sector_size = storage -> ux_host_class_storage_sector_size; + /* Check if media setting can support the sector size. */ + if (storage -> ux_host_class_storage_sector_size > UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + + /* Required memory is over system setting. */ + return(UX_HOST_CLASS_MEMORY_ERROR); + } + /* Save the storage media instance in the user reserved area in the UX_MEDIA structure. */ ux_media_reserved_for_user_set(media, storage_media); diff --git a/common/usbx_host_classes/src/ux_host_class_storage_partition_read.c b/common/usbx_host_classes/src/ux_host_class_storage_partition_read.c old mode 100755 new mode 100644 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 index 80fe330f..ca0c6bff 100644 --- 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 @@ -53,7 +53,7 @@ static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_ST /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_tasks_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -99,6 +99,9 @@ static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_ST /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_tasks_run(UX_HOST_CLASS *storage_class) @@ -132,6 +135,7 @@ ULONG tick_now, tick_elapsed; UINT status; UX_TRANSFER *trans; UX_INTERFACE *interface_ptr; +INT immediate_state; /* If storage not live, start initialize. */ if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_MOUNTING) @@ -187,7 +191,8 @@ UX_INTERFACE *interface_ptr; } /* Handle main states. */ - while(1) + immediate_state = UX_TRUE; + while(immediate_state) { /* Get current state. */ @@ -498,11 +503,15 @@ UX_INTERFACE *interface_ptr; } UX_RESTORE - case UX_STATE_RESET: + /* Fall through. */ + + case UX_STATE_RESET: /* Fall through. */ default: break; } - break; + + /* Break the loop. */ + immediate_state = UX_FALSE; } } @@ -730,30 +739,31 @@ INT media_index; { /* Skip used storage media slots. */ - if (storage_media -> ux_host_class_storage_media_status == UX_USED) - continue; + 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; + /* 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; + /* 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) - { + /* 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); - } + /* 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; + /* Media saved OK. */ + return; + } } /* No free slot. */ 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 index 26a09ee8..90cd2b91 100644 --- 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 @@ -63,7 +63,7 @@ static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORA /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_transport_run PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -101,13 +101,18 @@ static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORA /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE *storage) { UINT status; UCHAR state; - while(1) +INT immediate_state = UX_TRUE; + + while(immediate_state) { state = storage -> ux_host_class_storage_trans_state; switch(state) @@ -192,7 +197,9 @@ UCHAR state; default: break; } - break; + + /* Invalid unhandled state, break the loop. */ + immediate_state = UX_FALSE; } /* Unexpected state, fatal error. */ 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 66e5aff8..66343245 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 @@ -87,6 +87,13 @@ UCHAR *baInterfaceNr; /* Check if this the VC interface is expected. */ bInCollection = packed_entity_descriptor[11]; baInterfaceNr = packed_entity_descriptor + 12; + + /* Validation: + * baInterfaceNr not exceeding current descriptor. + */ + if (packed_entity_descriptor[0] + packed_entity_descriptor < baInterfaceNr + bInCollection) + return(1); + while(bInCollection) { @@ -97,6 +104,10 @@ UCHAR *baInterfaceNr; parser -> parsed_flags |= UX_HOST_CLASS_VIDEO_DESCRIPTORS_PARSER_VC_HEADER; return(0); } + + /* Next interface number in descriptor. */ + baInterfaceNr ++; + bInCollection --; } } @@ -159,7 +170,7 @@ UCHAR *baInterfaceNr; /* FUNCTION RELEASE */ /* */ /* _ux_host_class_video_activate PORTABLE C */ -/* 6.1.12 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ @@ -217,6 +228,9 @@ UCHAR *baInterfaceNr; /* fixed parameter/variable */ /* names conflict C++ keyword, */ /* resulting in version 6.1.12 */ +/* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ +/* improved VC header check, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _ux_host_class_video_activate(UX_HOST_CLASS_COMMAND *command) diff --git a/common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c b/common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/inc/ux_hcd_ehci.h b/common/usbx_host_controllers/inc/ux_hcd_ehci.h old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/inc/ux_hcd_ohci.h b/common/usbx_host_controllers/inc/ux_hcd_ohci.h old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_create.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_create.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_destroy.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_create.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_destroy.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_least_traffic_list_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_least_traffic_list_get.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_tree_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_tree_create.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_poll_rate_entry_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_poll_rate_entry_get.c old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_abort.c b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_abort.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_error_clear.c b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_error_clear.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_reset.c b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_reset.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_endpoint_destroy.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_resume.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_resume.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_suspend.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_suspend.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_down_port.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_down_port.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_on_port.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_on_port.c old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_root_hubs.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_root_hubs.c old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_abort.c b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_abort.c old mode 100755 new mode 100644 diff --git a/docs/usbx-features.png b/docs/usbx-features.png new file mode 100644 index 00000000..de5edef8 Binary files /dev/null and b/docs/usbx-features.png differ diff --git a/ports/arm9/gnu/inc/ux_port.h b/ports/arm9/gnu/inc/ux_port.h index 28c881bc..180adbf7 100644 --- a/ports/arm9/gnu/inc/ux_port.h +++ b/ports/arm9/gnu/inc/ux_port.h @@ -239,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.2.0 *"; #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 2a5e11e6..b9fd63f3 100644 --- a/ports/arm9/iar/inc/ux_port.h +++ b/ports/arm9/iar/inc/ux_port.h @@ -246,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.2.0 *"; #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 d9ea85a9..058f5095 100644 --- a/ports/cortex_a15/gnu/inc/ux_port.h +++ b/ports/cortex_a15/gnu/inc/ux_port.h @@ -235,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A15/GNU Version 6.2.0 *"; #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 742ad9bf..46babf40 100644 --- a/ports/cortex_a5/gnu/inc/ux_port.h +++ b/ports/cortex_a5/gnu/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/GNU Version 6.2.0 *"; #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 54c8d5cb..d1b61185 100644 --- a/ports/cortex_a5/iar/inc/ux_port.h +++ b/ports/cortex_a5/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5/IAR Version 6.2.0 *"; #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 1c677a54..887c2b04 100644 --- a/ports/cortex_a5x/ac6/inc/ux_port.h +++ b/ports/cortex_a5x/ac6/inc/ux_port.h @@ -259,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A5x/AC6 Version 6.2.0 *"; #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 c937a33a..86edca69 100644 --- a/ports/cortex_a7/gnu/inc/ux_port.h +++ b/ports/cortex_a7/gnu/inc/ux_port.h @@ -246,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/GNU Version 6.2.0 *"; #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 3ef6d481..dd01a952 100644 --- a/ports/cortex_a7/iar/inc/ux_port.h +++ b/ports/cortex_a7/iar/inc/ux_port.h @@ -246,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A7/IAR Version 6.2.0 *"; #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 9453e58a..5cda0b87 100644 --- a/ports/cortex_a8/gnu/inc/ux_port.h +++ b/ports/cortex_a8/gnu/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/GNU Version 6.2.0 *"; #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 7a0ee0d8..30249c4e 100644 --- a/ports/cortex_a8/iar/inc/ux_port.h +++ b/ports/cortex_a8/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-A8/IAR Version 6.2.0 *"; #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 7af6f395..e2c45f7c 100644 --- a/ports/cortex_a9/gnu/inc/ux_port.h +++ b/ports/cortex_a9/gnu/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/GNU Version 6.2.0 *"; #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 2564a8ac..7cbff016 100644 --- a/ports/cortex_a9/iar/inc/ux_port.h +++ b/ports/cortex_a9/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX ARM9/IAR Version 6.2.0 *"; #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 b22c35bf..a015ba1c 100644 --- a/ports/cortex_m0/gnu/inc/ux_port.h +++ b/ports/cortex_m0/gnu/inc/ux_port.h @@ -240,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/GNU Version 6.2.0 *"; #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 b1d10d56..8c6241a8 100644 --- a/ports/cortex_m0/iar/inc/ux_port.h +++ b/ports/cortex_m0/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/IAR Version 6.2.0 *"; #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 11ddb422..a26b679a 100644 --- a/ports/cortex_m3/gnu/inc/ux_port.h +++ b/ports/cortex_m3/gnu/inc/ux_port.h @@ -240,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/GNU Version 6.2.0 *"; #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 d3807aee..a32cb282 100644 --- a/ports/cortex_m3/iar/inc/ux_port.h +++ b/ports/cortex_m3/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/IAR Version 6.2.0 *"; #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 7113f32d..c1eb4ac4 100644 --- a/ports/cortex_m4/gnu/inc/ux_port.h +++ b/ports/cortex_m4/gnu/inc/ux_port.h @@ -240,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/GNU Version 6.2.0 *"; #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 28f56e76..22f42501 100644 --- a/ports/cortex_m4/iar/inc/ux_port.h +++ b/ports/cortex_m4/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/IAR Version 6.2.0 *"; #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 62e95678..a8e50f6d 100644 --- a/ports/cortex_m7/gnu/inc/ux_port.h +++ b/ports/cortex_m7/gnu/inc/ux_port.h @@ -240,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/GNU Version 6.2.0 *"; #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 dd8f8925..813bd4e2 100644 --- a/ports/cortex_m7/iar/inc/ux_port.h +++ b/ports/cortex_m7/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/IAR Version 6.2.0 *"; #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 09c11308..ba0a5cff 100644 --- a/ports/cortex_r4/gnu/inc/ux_port.h +++ b/ports/cortex_r4/gnu/inc/ux_port.h @@ -238,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/GNU Version 6.2.0 *"; #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 932e71a6..2d5dc12a 100644 --- a/ports/cortex_r4/iar/inc/ux_port.h +++ b/ports/cortex_r4/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R4/IAR Version 6.2.0 *"; #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 6654a7b4..940d7291 100644 --- a/ports/cortex_r5/gnu/inc/ux_port.h +++ b/ports/cortex_r5/gnu/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/GNU Version 6.2.0 *"; #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 03829ebb..c8a1bbf0 100644 --- a/ports/cortex_r5/iar/inc/ux_port.h +++ b/ports/cortex_r5/iar/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-R5/IAR Version 6.2.0 *"; #else extern CHAR _ux_version_id[]; #endif diff --git a/ports/generic/inc/ux_port.h b/ports/generic/inc/ux_port.h index 4973c2a2..8ac0137f 100644 --- a/ports/generic/inc/ux_port.h +++ b/ports/generic/inc/ux_port.h @@ -242,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Generic Version 6.2.0 *"; #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 0ebd9239..57954352 100644 --- a/ports/linux/gnu/inc/ux_port.h +++ b/ports/linux/gnu/inc/ux_port.h @@ -244,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.12 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Linux/GNU Version 6.2.0 *"; #else extern CHAR _ux_version_id[]; #endif