diff options
| author | Tiejun Zhou <[email protected]> | 2022-10-26 23:43:22 +0000 |
|---|---|---|
| committer | Tiejun Zhou <[email protected]> | 2022-10-26 23:43:22 +0000 |
| commit | 232e89f35b3714d735e3d44c33c0cf419de74504 (patch) | |
| tree | 567402c81a7208f55fea445c3599e3110c8aa361 /common/usbx_host_classes | |
| parent | cd55ec74569aa3fbfbd8f02d025a47c5a51a285a (diff) | |
Release 6.2.0v6.2.0_rel
Diffstat (limited to 'common/usbx_host_classes')
29 files changed, 1184 insertions, 591 deletions
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 dac0f48..250fd20 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 524656f..9a8b388 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 b805175..b331bf4 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 index 8082256..8082256 100755..100644 --- a/common/usbx_host_classes/inc/ux_host_class_storage.h +++ b/common/usbx_host_classes/inc/ux_host_class_storage.h 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 a243a07..760b59e 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 32853e5..20d5c61 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 0fae599..7e67670 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 8d4716e..aba59b5 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 2a4437a..5717311 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) - { + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN; - /* Set the completion error code. */ - transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; + /* Abort possible pending bulk in requests. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_bulk_in_endpoint); - /* 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 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 75ad2e9..e6bff4c 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 96f4803..9e301dd 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; - } + /* Now the link is up. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_UP; - /* 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); + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(asix -> ux_host_class_asix_network_handle); - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Reactivate interrupt notification polling. */ + _ux_host_stack_transfer_request(&asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request); - /* 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); + /* 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); + /* Re-check packet pool on link up. */ + asix -> ux_host_class_asix_packet_pool = UX_NULL; - /* Return completion status. */ - return; - - } + /* Keep polling if device is connected and link is up. */ - /* 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) + /* 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; + + /* 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; - - } - - /* 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); + /* Get the network device handle. */ + ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(asix -> ux_host_class_asix_network_handle); - /* 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; - - } + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_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); - - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + _ux_utility_delay_ms(UX_HOST_CLASS_ASIX_PACKET_POOL_WAIT); + continue; + } + } - /* 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; + /* Get transfer request for bulk in reception. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; - /* 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); + /* If there is no buffer ready, read it. */ + if (buffer == UX_NULL) + { - /* Return completion status. */ - return; - - } + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = asix -> ux_host_class_asix_receive_buffer; - /* Free all used resources. */ - _ux_utility_memory_free(setup_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; - /* 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) - { + /* Schedule a reception. */ + status = _ux_host_stack_transfer_request(transfer_request); - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* Check if it's started successfully. */ + if (status != UX_SUCCESS) + { - /* Return completion status. */ - return; - } + /* If a packet (chain) is on-going, release it. */ + if (packet != UX_NULL) + { + nx_packet_release(packet); + packet = UX_NULL; + } + continue; + } - /* Now the link is up. */ - asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_UP; + /* Wait for transfer completion. */ + _ux_host_semaphore_get_norc(&transfer_request -> ux_transfer_request_semaphore, UX_WAIT_FOREVER); - /* 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) - { + /* Check completion code. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + /* Abort transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); - /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ - packet -> nx_packet_prepend_ptr += sizeof(USHORT); + /* If a packet (chain) is on-going, release it. */ + if (packet != UX_NULL) + { + nx_packet_release(packet); + packet = UX_NULL; + } + continue; + } - /* 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; + /* If it's ZLP, reset buffer and ASIX packet and transfer again. */ + if (transfer_request -> ux_transfer_request_actual_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; + /* Packet should have been processed! */ + if (packet != UX_NULL) + { - /* Store the packet that owns this transaction. */ - transfer_request -> ux_transfer_request_user_specific = packet; + /* 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; + } - /* 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; + buffer = UX_NULL; + buffer_count = 0; + asix_length = 0; + continue; + } - /* Ask USB to schedule a reception. */ - status = _ux_host_stack_transfer_request(transfer_request); + /* Buffer is ready. */ + buffer = asix -> ux_host_class_asix_receive_buffer; + } - /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ - if (status != UX_SUCCESS) + /* There is data in buffer, extract the data to packets. */ + + /* If there is no packet, allocate it. */ + if (packet == UX_NULL) { - /* Cancel the packet. */ - asix -> ux_host_class_asix_receive_queue = UX_NULL; - + /* 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. */ + } - } + /* Get remaining in buffer. */ + buffer_remain = transfer_request -> ux_transfer_request_actual_length - + buffer_count; - /* Unprotect thread reentry to this instance. */ - _ux_host_semaphore_put(&asix -> ux_host_class_asix_semaphore); + /* For new packet, get packet length from ASIX header. */ + if (asix_length == 0) + { - return; - } + /* If remaining less than 2 bytes in buffer, read buffer again. */ + if (buffer_remain < 2) + { + buffer = UX_NULL; + buffer_count = 0; + continue; + } - /* 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) + /* 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; + } + + /* Get remaining in ASIX packet. */ + asix_remain = asix_length - asix_count; + + /* Get actual length to process. */ + if (asix_remain <= buffer_remain) + copy_length = asix_remain; + else + copy_length = buffer_remain; + + /* Check if the data is discarded. */ + if (packet_discard == UX_FALSE && copy_length) + { + + /* 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; + } + + /* 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. */ + } + + /* Release packet not sent to NX. */ + if (packet) + nx_packet_release(packet); + } + 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 204af59..13f2967 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 d30bf62..175e9b6 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 3d1dfde..f261331 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) + /* 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); - } + /* Activation was successful. */ + return(UX_SUCCESS); + } - /* Error starting interrupt endpoint. */ + /* Error starting interrupt endpoint. */ - /* Destroy this class instance. */ - _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + /* Destroy this class instance. */ + _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); - /* Unmount instance. */ - interface_ptr -> ux_interface_class_instance = UX_NULL; - } - - /* 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 ec561e9..3273259 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 6a65d57..ea9f968 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 24a36e8..fbed582 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) { - 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; + /* 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 + { + + /* 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 506097e..157f95d 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 f88878e..76667e1 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 37aa1e7..3fdd9d1 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 abc4770..9a968d8 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 c0363f3..2702c39 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 index 68c68a4..68c68a4 100755..100644 --- a/common/usbx_host_classes/src/ux_host_class_storage_entry.c +++ b/common/usbx_host_classes/src/ux_host_class_storage_entry.c 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 3da9480..7124376 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 index c3e17fa..c3e17fa 100755..100644 --- 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 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 80fe330..ca0c6bf 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 26a09ee..90cd2b9 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 66e5aff..6634324 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 index 2bb2b3c..2bb2b3c 100755..100644 --- 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 |
