diff --git a/common/core/inc/ux_utility.h b/common/core/inc/ux_utility.h index 8a8ea986..c2fd8f4b 100644 --- a/common/core/inc/ux_utility.h +++ b/common/core/inc/ux_utility.h @@ -172,7 +172,7 @@ extern ULONG _ux_utility_time_get(VOID); #endif #ifndef _ux_utility_time_elapsed -#define _ux_utility_time_elapsed(a,b) (((b)>=(a)) ? ((b)-(a)) : (0xFFFFFFFFul-(b)+(a)+1)) +#define _ux_utility_time_elapsed(a,b) (((b)>=(a)) ? ((b)-(a)) : (0xFFFFFFFFul-(a)+(b)+1)) #else extern ALIGN_TYPE _ux_utility_time_elapsed(ALIGN_TYPE, ALIGN_TYPE); #endif diff --git a/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c index 08db3f2f..290bea15 100644 --- a/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c +++ b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c @@ -169,10 +169,10 @@ UCHAR *buffer; _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_1, pima_event.ux_device_class_pima_event_parameter_1); /* Put the value of parameter 2. */ - _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2, pima_event.ux_device_class_pima_event_parameter_3); + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2, pima_event.ux_device_class_pima_event_parameter_2); /* Put the value of parameter 3. */ - _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2, pima_event.ux_device_class_pima_event_parameter_3); + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_3, pima_event.ux_device_class_pima_event_parameter_3); /* Send the request to the device controller. */ status = _ux_device_stack_transfer_request(transfer_request_in, UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH, UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH); 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 8c24bc1c..88d0a4c4 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 @@ -1,18 +1,18 @@ /*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * + * Copyright (c) 2024 Microsoft Corporation + * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. - * + * * SPDX-License-Identifier: MIT **************************************************************************/ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** CDC_ECM Class */ /** */ @@ -30,32 +30,32 @@ #if !defined(UX_HOST_STANDALONE) -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_cdc_ecm_thread PORTABLE C */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_thread PORTABLE C */ /* 6.2.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ +/* */ /* This is the CDC ECM thread that monitors the link change flag, */ /* receives data from the device, and passes the data to the NetX-USB */ -/* broker. */ -/* */ -/* INPUT */ -/* */ -/* cdc_ecm CDC ECM instance */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ +/* broker. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm CDC ECM instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ /* _ux_host_class_cdc_ecm_transmit_queue_clean */ /* Clean transmit queue */ /* _ux_host_stack_transfer_request Transfer request */ @@ -67,15 +67,15 @@ /* _ux_network_driver_packet_received Process received packet */ /* nx_packet_allocate Allocate NetX packet */ /* nx_packet_release Free NetX packet */ -/* */ -/* CALLED BY */ -/* */ -/* CDC ECM class initialization */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ +/* */ +/* CALLED BY */ +/* */ +/* CDC ECM class initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ /* prefixed UX to MS_TO_TICK, */ @@ -114,9 +114,9 @@ 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) - /* 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 cdc_ecm interrupt event. */ _ux_host_semaphore_get_norc(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, UX_WAIT_FOREVER); @@ -130,10 +130,10 @@ ULONG packet_buffer_size; /* Communicate the state with the network driver. */ _ux_network_driver_link_up(cdc_ecm -> ux_host_class_cdc_ecm_network_handle); - + /* As long as we are connected, configured and link up ... do some work.... */ 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)) + (cdc_ecm -> ux_host_class_cdc_ecm_device -> ux_device_state == UX_DEVICE_CONFIGURED)) { /* Check if we have packet pool available. */ @@ -154,7 +154,7 @@ ULONG packet_buffer_size; { /* IP instance is not available, wait for application to attach the interface. */ - _ux_utility_delay_ms(UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_INSTANCE_WAIT)); + _ux_utility_delay_ms(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_INSTANCE_WAIT); } continue; } @@ -168,7 +168,7 @@ ULONG packet_buffer_size; /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ packet -> nx_packet_prepend_ptr += sizeof(USHORT); - + /* 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; @@ -206,18 +206,18 @@ ULONG packet_buffer_size; #endif { - /* Set the data pointer. */ + /* 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; - + /* Store the packet that owns this transaction. */ transfer_request -> ux_transfer_request_user_specific = packet; - + /* Reset the queue pointer of this packet. */ packet -> nx_packet_queue_next = UX_NULL; @@ -235,7 +235,7 @@ ULONG packet_buffer_size; cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_FALSE; if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); - + /* Check if the transaction was armed successfully. */ if (status == UX_SUCCESS) { @@ -280,13 +280,13 @@ ULONG packet_buffer_size; { /* 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_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. */ _ux_network_driver_packet_received(cdc_ecm -> ux_host_class_cdc_ecm_network_handle, packet); } @@ -345,6 +345,6 @@ ULONG packet_buffer_size; /* Set the link state. */ cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN; } - } + } } #endif diff --git a/test/cmake/usbx/regression/CMakeLists.txt b/test/cmake/usbx/regression/CMakeLists.txt index 372f235c..8d29d436 100644 --- a/test/cmake/usbx/regression/CMakeLists.txt +++ b/test/cmake/usbx/regression/CMakeLists.txt @@ -512,6 +512,7 @@ set(ux_utility_test_cases ${SOURCE_DIR}/usbx_ux_utility_pci_class_scan_test.c ${SOURCE_DIR}/usbx_ux_utility_physical_address_test.c ${SOURCE_DIR}/usbx_ux_utility_string_length_check_test.c + ${SOURCE_DIR}/usbx_ux_utility_time_elapsed_test.c ${SOURCE_DIR}/usbx_ux_utility_unicode_to_string_test.c ) set(ux_utility_os_test_cases diff --git a/test/regression/usbx_ux_utility_time_elapsed_test.c b/test/regression/usbx_ux_utility_time_elapsed_test.c new file mode 100644 index 00000000..f651867b --- /dev/null +++ b/test/regression/usbx_ux_utility_time_elapsed_test.c @@ -0,0 +1,366 @@ +/* This test is designed to test the ux_utility_time_elapsed macro.... */ + +#include +#include "tx_api.h" +#include "ux_api.h" +#include "ux_system.h" +#include "ux_utility.h" + +#include "ux_host_stack.h" +#include "ux_device_stack.h" + +#include "ux_device_class_cdc_acm.h" +#include "ux_host_class_cdc_acm.h" + +#include "ux_host_class_dpump.h" +#include "ux_device_class_dpump.h" + +#include "ux_host_class_hid.h" +#include "ux_device_class_hid.h" + +#include "ux_host_class_storage.h" +#include "ux_device_class_storage.h" + +#include "ux_test_dcd_sim_slave.h" +#include "ux_test_hcd_sim_host.h" +#include "ux_test_utility_sim.h" + + +/* Define USBX test constants. */ + +#define UX_TEST_STACK_SIZE 4096 +#define UX_TEST_BUFFER_SIZE 2048 +#define UX_TEST_RUN 1 +#define UX_TEST_MEMORY_SIZE (64*1024) + +#define LSB(x) ( (x) & 0x00ff) +#define MSB(x) (((x) & 0xff00) >> 8) + +/* Configuration descriptor 9 bytes */ +#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\ + /* Configuration 1 descriptor 9 bytes */\ + 0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\ + (bNumInterfaces), (bConfigurationValue), 0x00,\ + 0x40, 0x00, +#define CFG_DESC_LEN 9 + +/* DPUMP interface descriptors. */ +#define DPUMP_IFC_DESC(ifc, alt, nb_ep) \ + /* Interface descriptor */\ + 0x09, 0x04, (ifc), (alt), (nb_ep), 0x99, 0x99, 0x99, 0x00, + +#define DPUMP_IFC_EP_DESC(epaddr, eptype, epsize) \ + /* Endpoint descriptor */\ + 0x07, 0x05, (epaddr), (eptype), LSB(epsize), MSB(epsize), 0x01, + +#define DPUMP_IFC_DESC_ALL_LEN(nb_ep) (9 + (nb_ep) * 7) + +#define CFG_DESC_ALL_LEN (CFG_DESC_LEN + DPUMP_IFC_DESC_ALL_LEN(4)) + +#define CFG_DESC_ALL \ + CFG_DESC(CFG_DESC_ALL_LEN, 1, 1)\ + DPUMP_IFC_DESC(0, 0, 4)\ + DPUMP_IFC_EP_DESC(0x81, 2, 64)\ + DPUMP_IFC_EP_DESC(0x02, 2, 64)\ + DPUMP_IFC_EP_DESC(0x83, 1, 64)\ + DPUMP_IFC_EP_DESC(0x84, 3, 64)\ + +/* Define the counters used in the test application... */ + +static ULONG thread_0_counter; +static ULONG thread_1_counter; +static ULONG error_counter; + +static UCHAR error_callback_ignore = UX_FALSE; +static ULONG error_callback_counter; + +static UCHAR buffer[UX_TEST_BUFFER_SIZE]; + +static TX_TIMER test_timer; + +/* Define USBX test global variables. */ + +static UX_HOST_CLASS *class_driver; +static UX_HOST_CLASS_DPUMP *dpump; +static UX_SLAVE_CLASS_DPUMP *dpump_slave = UX_NULL; + +static UCHAR device_framework_full_speed[] = { + + /* Device descriptor 18 bytes */ + 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, + 0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + + CFG_DESC_ALL +}; +#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed) + +static UCHAR device_framework_high_speed[] = { + + /* Device descriptor */ + 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02, + 0x03, 0x01, + + /* Device qualifier descriptor */ + 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x00, + + CFG_DESC_ALL +}; +#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed) + +/* String Device Framework : + Byte 0 and 1 : Word containing the language ID : 0x0904 for US + Byte 2 : Byte containing the index of the descriptor + Byte 3 : Byte containing the length of the descriptor string +*/ + +#define NUM_TEST_VALUES 2 +#define TEST_VALUES_LENGTH 3 + +static UINT test_values[NUM_TEST_VALUES][TEST_VALUES_LENGTH] = +{ + {0xFU, 0x1U, 0xFFFFFFF2U}, + {0xFFFFFFF0, 0x1U, 0x11U} +}; + +static UCHAR string_framework[] = { + + /* Manufacturer string descriptor : Index 1 */ + 0x09, 0x04, 0x01, 0x0c, + 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c, + 0x6f, 0x67, 0x69, 0x63, + + /* Product string descriptor : Index 2 */ + 0x09, 0x04, 0x02, 0x0c, + 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70, + 0x44, 0x65, 0x6d, 0x6f, + + /* Serial Number string descriptor : Index 3 */ + 0x09, 0x04, 0x03, 0x04, + 0x30, 0x30, 0x30, 0x31 +}; +#define STRING_FRAMEWORK_LENGTH sizeof(string_framework) + + /* Multiple languages are supported on the device, to add + a language besides English, the unicode language code must + be appended to the language_id_framework array and the length + adjusted accordingly. */ +static UCHAR language_id_framework[] = { + +/* English. */ + 0x09, 0x04 +}; +#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework) + +/* Define prototypes for external Host Controller's (HCDs), classes and clients. */ + +static VOID ux_test_instance_activate(VOID *dpump_instance); +static VOID ux_test_instance_deactivate(VOID *dpump_instance); + +UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command); +UINT ux_hcd_sim_initialize(UX_HCD *hcd); +UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); + +static TX_THREAD ux_test_thread_simulation_0; +static TX_THREAD ux_test_thread_simulation_1; +static void ux_test_thread_simulation_0_entry(ULONG); +static void ux_test_thread_simulation_1_entry(ULONG); + + +/* Define the ISR dispatch. */ + +extern VOID (*test_isr_dispatch)(void); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + +/* Simulator actions. */ + +static UX_TEST_HCD_SIM_ACTION endpoint0x83_create_del_skip[] = { +/* function, request to match, + port action, port status, + request action, request EP, request data, request actual length, request status, + status, additional callback, + no_return */ +{ UX_HCD_CREATE_ENDPOINT, NULL, + UX_FALSE, 0, + UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0, + UX_SUCCESS}, +{ UX_HCD_CREATE_ENDPOINT, NULL, + UX_FALSE, 0, + UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0, + UX_SUCCESS}, +{ 0 } +}; + +/* Define the ISR dispatch routine. */ + +static void test_isr(void) +{ + + /* For further expansion of interrupt-level testing. */ +} + + +static VOID error_callback(UINT system_level, UINT system_context, UINT error_code) +{ + + error_callback_counter ++; + + if (!error_callback_ignore) + { + { + /* Failed test. */ + printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code); + // test_control_return(1); + } + } +} + +static UINT break_on_dpump_ready(VOID) +{ + +UINT status; +UX_HOST_CLASS *class; + + /* Find the main data pump container. */ + status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class); + if (status != UX_SUCCESS) + /* Do not break. */ + return UX_SUCCESS; + + /* Find the instance. */ + status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump); + if (status != UX_SUCCESS) + /* Do not break. */ + return UX_SUCCESS; + + if (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE) + /* Do not break. */ + return UX_SUCCESS; + + return 1; +} + +static UINT break_on_removal(VOID) +{ + +UINT status; +UX_DEVICE *device; + + status = ux_host_stack_device_get(0, &device); + if (status == UX_SUCCESS) + /* Do not break. */ + return UX_SUCCESS; + + return 1; +} + + +static UINT test_ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + switch(command->ux_slave_class_command_request) + { + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + case UX_SLAVE_CLASS_COMMAND_QUERY: + case UX_SLAVE_CLASS_COMMAND_CHANGE: + return UX_SUCCESS; + + default: + return UX_NO_CLASS_MATCH; + } +} + +static UINT test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command) +{ + switch (command -> ux_host_class_command_request) + { + case UX_HOST_CLASS_COMMAND_QUERY: + default: + return _ux_host_class_dpump_entry(command); + } +} + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void usbx_ux_utility_timer_test_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *stack_pointer; +CHAR *memory_pointer; +CHAR *rpool_start; +CHAR *cpool_start; +const CHAR flags[] = { + UX_REGULAR_MEMORY, UX_CACHE_SAFE_MEMORY, 0xFF +}; +const CHAR expect_error[] = { + UX_FALSE, UX_FALSE, UX_TRUE +}; + + /* Inform user. */ + printf("Running ux_utility_time_elapsed... Test................................... "); + + /* Initialize the free memory pointer. */ + stack_pointer = (CHAR *) first_unused_memory; + memory_pointer = stack_pointer + (UX_TEST_STACK_SIZE * 2); + + rpool_start = memory_pointer; + cpool_start = memory_pointer + UX_TEST_MEMORY_SIZE; + + /* Initialize USBX Memory. */ + status = ux_system_initialize(rpool_start, UX_TEST_MEMORY_SIZE, cpool_start, UX_TEST_MEMORY_SIZE); + + /* Check for error. */ + if (status != UX_SUCCESS) + { + + printf("ERROR #%d\n", __LINE__); + test_control_return(1); + } + + /* Register the error callback. */ + _ux_utility_error_callback_register(error_callback); + + /* Create the simulation thread. */ + status = tx_thread_create(&ux_test_thread_simulation_0, "test simulation", ux_test_thread_simulation_0_entry, 0, + stack_pointer, UX_TEST_STACK_SIZE, + 20, 20, 1, TX_AUTO_START); + + /* Check for error. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #%d\n", __LINE__); + test_control_return(1); + } +} + +static void ux_test_thread_simulation_0_entry(ULONG arg) +{ + + + for (UINT i = 0; i < NUM_TEST_VALUES; ++i) + { + if (ux_utility_time_elapsed(test_values[i][0], test_values[i][1]) != test_values[i][2]) + { + printf("ERROR #%d: time elapsed incorrect\n", __LINE__); + test_control_return(1); + } + } + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} \ No newline at end of file diff --git a/test/regression/ux_test.c b/test/regression/ux_test.c index aaf845aa..b2eeb8e6 100644 --- a/test/regression/ux_test.c +++ b/test/regression/ux_test.c @@ -2,10 +2,6 @@ #include "ux_test_hcd_sim_host.h" #include "ux_test_dcd_sim_slave.h" -#ifndef _ux_utility_time_elapsed -#define _ux_utility_time_elapsed(t0,t1) ((t1)>=(t0) ? ((t1)-(t0)) : (0xFFFFFFFF - (t0) + (t1))) -#endif - #define UX_TEST_TIMEOUT_MS 3000 static UX_TEST_ACTION ux_test_action_handler_check(UX_TEST_ACTION *action, UX_TEST_FUNCTION usbx_function, void *params, UCHAR advance);