1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
/***************************************************************************/
/* Copyright (c) 2024 Microsoft Corporation */
/* Copyright (c) 2026 Eclipse ThreadX contributors */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the MIT License which is available at */
/* https://opensource.org/licenses/MIT. */
/* */
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
/* This test the case where a LINK DOWN event is received while transfers are
ongoing. */
#include "usbx_ux_test_cdc_ecm.h"
#include "ux_device_stack.h"
static ULONG global_basic_test_num_writes_host;
static ULONG global_basic_test_num_reads_host;
static ULONG global_basic_test_num_writes_device;
static ULONG global_basic_test_num_reads_device;
static UCHAR host_waiting_for_link_down;
static UCHAR host_waiting_for_link_up;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_link_down_while_ongoing_transfers_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Link Down While Ongoing Transfers Test......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void basic_test_host()
{
UINT num_iters;
UINT i;
/*** Basic test - no transfers going on. ***/
stepinfo("Basic test - no transfers going on.\n");
/* Now wait for the link to be down. */
host_waiting_for_link_down = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN));
/* Wait for everything to get cleaned up. */
tx_thread_sleep(MS_TO_TICK(1000));
/* Now wait for the link to be up. */
host_waiting_for_link_up = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
/* Run that basic test again. */
for (num_iters = 0; num_iters < 10; num_iters++)
{
for (i = 0; i < 10; i++)
write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, global_basic_test_num_writes_host++, "host");
for (i = 0; i < 10; i++)
read_packet_udp(&udp_socket_host, global_basic_test_num_reads_host++, "host");
}
/* Wait for all transfers to complete. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_host, 100));
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_device, 100));
}
static void basic_test_device()
{
UINT num_iters;
UINT i;
/*** Basic test. ***/
/* Wait for host to wait for link down. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_down, 1));
host_waiting_for_link_down = 0;
/* Now set the link to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN);
/* Wait for host to wait for link up. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_up, 1));
host_waiting_for_link_up = 0;
/* Now set the link to up. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP);
/* Now do basic test. */
for (num_iters = 0; num_iters < 10; num_iters++)
{
for (i = 0; i < 10; i++)
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, global_basic_test_num_writes_device++, "device");
for (i = 0; i < 10; i++)
read_packet_udp(&udp_socket_device, global_basic_test_num_reads_device++, "device");
}
/* Wait for all transfers to complete. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_host, 100));
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_device, 100));
}
#define NUM_WRITES 500
#define NUM_WRITES_BEFORE_LINK_DOWN 10
#define MAX_WRITE_WHILE_LINK_DOWN (NUM_WRITES - NUM_WRITES_BEFORE_LINK_DOWN)
static void ongoing_writes_test_host()
{
UINT i;
UINT pre_write_fail_num_packet_pool_packets_available;
UINT num_writes = 0;
/*** Link down when there are queued writes, and we try to add writes. ***/
stepinfo("Ongoing writes test.\n");
pre_write_fail_num_packet_pool_packets_available = packet_pool_host.nx_packet_pool_available;
/* We expect some errors. */
UX_TEST_ACTION error_match_action = create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR);
ux_test_add_action_to_main_list_multiple(error_match_action, MAX_WRITE_WHILE_LINK_DOWN);
/* Queue up some writes - device isn't going to read them, so they stay queued. */
for (i = 0; i < NUM_WRITES; i++)
{
/* Write packet. */
write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, num_writes++, "host");
/* Have we queued 10 packets? */
if (i == NUM_WRITES_BEFORE_LINK_DOWN)
{
/* Set the link to down. The _hope_ here is to have the CDC-ECM thread
process the link down while we're still writing packets. This
should be improved in the future. I don't want to be the poor
SOB that has to do it!
We cheat here by calling a device API from the host. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN);
while (cdc_ecm_host->ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN)
tx_thread_sleep(10);
}
}
/* Make sure everything is ok. */
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN);
NX_PACKET_POOL *packet_pool_host_local = &packet_pool_host;
UX_HOST_CLASS_CDC_ECM *cdc_ecm_host_local = cdc_ecm_host;
UX_TEST_ASSERT(packet_pool_host.nx_packet_pool_available == pre_write_fail_num_packet_pool_packets_available);
/* Make sure at least one error was reported. */
UX_TEST_ASSERT(ux_test_get_num_actions_left() != 90);
/* Now clear the error match actions out. */
ux_test_clear_main_list_actions();
/* Run that basic test again. */
/* Now wait for the link to be up. */
host_waiting_for_link_up = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
}
static void ongoing_writes_test_device()
{
/*** Ongoing writes test. ***/
/* The host is gonna do all the work. At some point, he'll want the link back
up to run the basic test again. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_up, 1));
/* Set link to up. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP);
/* Now do basic test. */
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}
static void post_init_host()
{
//basic_test_host();
ongoing_writes_test_host();
}
static void post_init_device(ULONG input)
{
//basic_test_device();
ongoing_writes_test_device();
}
|