summaryrefslogtreecommitdiff
path: root/common/usbx_host_classes
diff options
context:
space:
mode:
authorTiejun Zhou <[email protected]>2022-10-26 23:43:22 +0000
committerTiejun Zhou <[email protected]>2022-10-26 23:43:22 +0000
commit232e89f35b3714d735e3d44c33c0cf419de74504 (patch)
tree567402c81a7208f55fea445c3599e3110c8aa361 /common/usbx_host_classes
parentcd55ec74569aa3fbfbd8f02d025a47c5a51a285a (diff)
Release 6.2.0v6.2.0_rel
Diffstat (limited to 'common/usbx_host_classes')
-rw-r--r--common/usbx_host_classes/inc/ux_host_class_asix.h78
-rw-r--r--common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h19
-rw-r--r--common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h8
-rw-r--r--[-rwxr-xr-x]common/usbx_host_classes/inc/ux_host_class_storage.h0
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_activate.c49
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_deactivate.c23
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c27
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_entry.c43
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c59
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c10
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_thread.c691
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c54
-rw-r--r--common/usbx_host_classes/src/ux_host_class_asix_write.c124
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c189
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c19
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c19
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c113
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c26
-rw-r--r--common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c55
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hid_keyboard_tasks_run.c24
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hub_entry.c9
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hub_tasks_run.c36
-rw-r--r--[-rwxr-xr-x]common/usbx_host_classes/src/ux_host_class_storage_entry.c0
-rw-r--r--common/usbx_host_classes/src/ux_host_class_storage_media_open.c15
-rw-r--r--[-rwxr-xr-x]common/usbx_host_classes/src/ux_host_class_storage_partition_read.c0
-rw-r--r--common/usbx_host_classes/src/ux_host_class_storage_tasks_run.c56
-rw-r--r--common/usbx_host_classes/src/ux_host_class_storage_transport_run.c13
-rw-r--r--common/usbx_host_classes/src/ux_host_class_video_activate.c16
-rw-r--r--[-rwxr-xr-x]common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c0
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