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