1 /* Include necessary system files.  */
2 
3 #include "usbx_ux_test_cdc_ecm.h"
4 
5 /* Resource usage */
6 
7 static ULONG                               set_cfg_counter;
8 
9 static ULONG                               rsc_mem_alloc_cnt_on_set_cfg;
10 static ULONG                               rsc_sem_on_set_cfg;
11 static ULONG                               rsc_sem_get_on_set_cfg;
12 static ULONG                               rsc_mutex_on_set_cfg;
13 
14 static ULONG                               rsc_enum_sem_usage;
15 static ULONG                               rsc_enum_sem_get_count;
16 static ULONG                               rsc_enum_mutex_usage;
17 static ULONG                               rsc_enum_mem_alloc_count;
18 
19 static ULONG                               rsc_cdc_sem_usage;
20 static ULONG                               rsc_cdc_sem_get_count;
21 static ULONG                               rsc_cdc_mutex_usage;
22 static ULONG                               rsc_cdc_mem_alloc_count;
23 static ULONG                               rsc_cdc_mem_tx_rx_count;
24 
25 static ULONG                               error_callback_counter;
26 
27 /* Log resources usage on SetConfigure */
28 
29 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
30 
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)31 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
32 {
33 
34     set_cfg_counter ++;
35 
36     rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
37 
38     rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
39     rsc_sem_get_on_set_cfg = ux_test_utility_sim_sem_get_count();
40     rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
41 }
42 
43 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
44 {   .function = UX_HCD_TRANSFER_REQUEST,
45     .req_setup = &_SetConfigure,
46     .req_action = UX_TEST_SETUP_MATCH_REQ,
47     .action_func = ux_test_hcd_entry_set_cfg,
48     .no_return = UX_TRUE
49 }, /* Invoke callback & continue */
50 {   0   }
51 };
52 
count_error_callback(struct UX_TEST_ACTION_STRUCT * action,VOID * params)53 static void count_error_callback(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
54 {
55 UX_TEST_ERROR_CALLBACK_PARAMS *error = (UX_TEST_ERROR_CALLBACK_PARAMS *)params;
56 
57     // printf("error trap: 0x%x, 0x%x, 0x%x\n", error->system_level, error->system_context, error->error_code);
58     error_callback_counter ++;
59 }
60 
61 static UX_TEST_HCD_SIM_ACTION count_on_error_trap[] = {
62 {   .usbx_function = UX_TEST_OVERRIDE_ERROR_CALLBACK,
63     .action_func = count_error_callback,
64 },
65 {   0   }
66 };
67 
sleep_break_on_error(VOID)68 static UINT  sleep_break_on_error(VOID)
69 {
70 
71     if (error_callback_counter >= 3)
72         return error_callback_counter;
73 
74     return UX_SUCCESS;
75 }
76 
sleep_break_on_host_tx_or_rx_buffer_allocated(VOID)77 static UINT  sleep_break_on_host_tx_or_rx_buffer_allocated(VOID)
78 {
79 UINT        buffer_count = 0;
80     if (cdc_ecm_host == UX_NULL)
81         return(UX_SUCCESS);
82     if (cdc_ecm_host -> ux_host_class_cdc_ecm_xmit_buffer)
83         buffer_count ++;
84     if (cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer)
85         buffer_count ++;
86     return (buffer_count);
87 }
88 
sleep_break_on_host_tx_and_rx_buffer_allocated(VOID)89 static UINT  sleep_break_on_host_tx_and_rx_buffer_allocated(VOID)
90 {
91 UINT        buffer_count = 0;
92     if (cdc_ecm_host == UX_NULL)
93         return(UX_SUCCESS);
94     if (cdc_ecm_host -> ux_host_class_cdc_ecm_xmit_buffer)
95         buffer_count ++;
96     if (cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer)
97         buffer_count ++;
98     return ((buffer_count >=2) ? buffer_count : UX_SUCCESS);
99 }
100 
101 /* Define what the initial system looks like.  */
102 #ifdef CTEST
test_application_define(void * first_unused_memory)103 void test_application_define(void *first_unused_memory)
104 #else
105 void usbx_cdc_ecm_basic_memory_test_application_define(void *first_unused_memory)
106 #endif
107 {
108 
109     /* Inform user.  */
110     printf("Running CDC ECM Basic Memory Test................................... ");
111 
112     stepinfo("\n");
113 
114     /* Override error trap. */
115     ux_test_link_hooks_from_array(count_on_error_trap);
116 
117     /* Reset testing counts. */
118     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
119     ux_test_utility_sim_mem_alloc_count_reset();
120     ux_test_utility_sim_mutex_create_count_reset();
121     ux_test_utility_sim_sem_create_count_reset();
122     ux_test_utility_sim_sem_get_count_reset();
123     /* Reset error generations */
124     ux_test_utility_sim_sem_error_generation_stop();
125     ux_test_utility_sim_mutex_error_generation_stop();
126     ux_test_utility_sim_sem_get_error_generation_stop();
127 
128     ux_test_cdc_ecm_initialize(first_unused_memory);
129 }
130 
post_init_host()131 static void post_init_host()
132 {
133 
134 UINT                                                status;
135 ULONG                                               mem_free;
136 ULONG                                               test_n;
137 
138 
139     /* Test disconnect. */
140     stepinfo(">>>>>>>>>>>>>>>>>>> Test disconnect\n");
141     ux_test_disconnect_slave();
142     ux_test_disconnect_host_wait_for_enum_completion();
143 
144     /* Reset testing counts. */
145     ux_test_utility_sim_mem_alloc_count_reset();
146     ux_test_utility_sim_mutex_create_count_reset();
147     ux_test_utility_sim_sem_create_count_reset();
148     ux_test_utility_sim_sem_get_count_reset();
149     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
150 
151     /* Save free memory usage. */
152     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
153 
154     stepinfo(">>>>>>>>>>>>>>>>>>> Test connect\n");
155     /* Connect. */
156     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
157     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
158     class_cdc_ecm_get_host();
159 
160     /* Log create counts for further tests. */
161     rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
162     rsc_enum_sem_usage = rsc_sem_on_set_cfg;
163     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
164     /* Log create counts when instances active for further tests. */
165     rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
166     rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
167     rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
168     /* Some allocation does not affect enum.  */
169     rsc_cdc_mem_tx_rx_count = 0;
170     if (cdc_ecm_host->ux_host_class_cdc_ecm_receive_buffer)
171         rsc_cdc_mem_tx_rx_count ++;
172     if (cdc_ecm_host->ux_host_class_cdc_ecm_xmit_buffer)
173         rsc_cdc_mem_tx_rx_count ++;
174     /* Lock log base for tests. */
175     ux_test_utility_sim_mem_alloc_log_lock();
176 
177     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
178     stepinfo("cdc mem : %ld\n", rsc_cdc_mem_alloc_count);
179     stepinfo("mem free: %ld, %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
180 
181     /* Simulate detach and attach for FS enumeration,
182        and check if there is memory error in normal enumeration.
183      */
184     stepinfo(">>>>>>>>>>>>>>>>>>> Enumeration test\n");
185     mem_free = (~0);
186     for (test_n = 0; test_n < 3; test_n++)
187     {
188         stepinfo("%4ld / 2\n", test_n);
189 
190         /* Disconnect. */
191         ux_test_dcd_sim_slave_disconnect();
192         ux_test_hcd_sim_host_disconnect();
193 
194         /* Update memory free level (disconnect) */
195         if (mem_free == (~0))
196             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
197         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
198         {
199 
200             printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
201             test_control_return(1);
202         }
203 
204         /* Connect. */
205         error_callback_counter = 0;
206         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
207         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
208 
209         /* Wait and break on error. */
210         ux_test_breakable_sleep(200, sleep_break_on_error);
211 
212         /* Check */
213         if (cdc_ecm_host_from_system_change_function == UX_NULL)
214         {
215 
216             printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
217             test_control_return(1);
218         }
219     }
220 
221     /* Simulate detach and attach for FS enumeration,
222        and test possible memory allocation error handlings.
223      */
224     if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>>>>> Memory errors enumeration test\n");
225     mem_free = (~0);
226     for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
227     {
228 
229         stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
230 
231         /* Disconnect. */
232         ux_test_dcd_sim_slave_disconnect();
233         ux_test_hcd_sim_host_disconnect();
234 
235         /* Update memory free level (disconnect) */
236         if (mem_free == (~0))
237             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
238         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
239         {
240 
241             printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
242             test_control_return(1);
243         }
244 
245         /* Set memory error generation */
246         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
247 
248         /* Connect. */
249         error_callback_counter = 0;
250         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
251         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
252 
253         if (test_n >= rsc_cdc_mem_alloc_count - rsc_cdc_mem_tx_rx_count)
254         {
255 
256             /* Wait and break on errors. */
257             ux_test_breakable_sleep(200, sleep_break_on_error);
258         }
259         else
260         {
261 
262             /* Wait and break on errors. */
263             ux_test_breakable_sleep(200, sleep_break_on_error);
264 
265             /* Check error */
266             if (cdc_ecm_host_from_system_change_function != UX_NULL)
267             {
268 
269                 printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
270                 test_control_return(1);
271             }
272         }
273 
274         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
275     }
276     ux_test_utility_sim_mem_alloc_error_generation_stop();
277     if (rsc_cdc_mem_alloc_count) stepinfo("\n");
278 
279     /* Test device deinit. */
280     stepinfo(">>>>>>>>>>>>>>>>>>> Test class deinit\n");
281     ux_test_disconnect_slave();
282     ux_test_disconnect_host_wait_for_enum_completion();
283     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry);
284 
285     /* Reset testing counts. */
286     ux_test_utility_sim_mem_alloc_count_reset();
287     ux_test_utility_sim_mutex_create_count_reset();
288     ux_test_utility_sim_sem_create_count_reset();
289     ux_test_utility_sim_sem_get_count_reset();
290 
291     stepinfo(">>>>>>>>>>>>>>>>>>> Test class init\n");
292     UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
293 
294     /* Log create counts for further tests. */
295     rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count();
296     rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count();
297     rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count();
298 
299     /* Lock log base for tests. */
300     ux_test_utility_sim_mem_alloc_log_lock();
301 
302     if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>>>>> Memory errors class init test\n");
303     mem_free = (~0);
304     for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
305     {
306 
307         stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
308 
309         /* Deinit. */
310         ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry);
311 
312         /* Update memory free level (disconnect) */
313         if (mem_free == (~0))
314             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
315         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
316         {
317 
318             printf("ERROR #%d.%ld: Memory level different after re-init %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
319             test_control_return(1);
320         }
321 
322         /* Set memory error generation */
323         ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
324 
325         /* Init. */
326 
327         status = ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter);
328 
329         /* Check error */
330         if (status != UX_MEMORY_INSUFFICIENT)
331         {
332 
333             printf("ERROR #%d.%ld: code 0x%x\n", __LINE__, test_n, status);
334             test_control_return(1);
335         }
336         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
337     }
338     ux_test_utility_sim_mem_alloc_error_generation_stop();
339     if (rsc_cdc_mem_alloc_count) stepinfo("\n");
340 
341     stepinfo(">>>>>>>>>>>>>>>>>>> Test connect to avoid post post operation\n");
342     /* Connect. */
343     UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
344     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
345     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
346     class_cdc_ecm_get_host();
347 
348     stepinfo(">>>>>>>>>>>>>>>>>>> post_init_host done\n");
349 }
350 
post_init_device()351 static void post_init_device()
352 {
353     stepinfo(">>>>>>>>>>>>>>>>>>> post_init_device empty\n");
354 }