1 #include <stdio.h>
2 #include "tx_api.h"
3 #include "ux_api.h"
4 #include "ux_system.h"
5 #include "ux_utility.h"
6 #include "ux_device_stack.h"
7 #include "ux_host_class_hub.h"
8 #include "ux_test_dcd_sim_slave.h"
9 #include "ux_test_hcd_sim_host.h"
10 #include "ux_test_utility_sim.h"
11 #include "ux_test.h"
12 #include "ux_test_actions.h"
13 #include "ux_device_class_dummy_hub.h"
14 #include "ux_dcd_sim_slave.h"
15 #include "usbx_ux_test_hub.h"
16 
17 static ULONG set_addr_counter;
18 
19 static ULONG rsc_mem_alloc_cnt_on_set_addr;
20 static ULONG rsc_sem_on_set_addr;
21 static ULONG rsc_sem_get_on_set_addr;
22 static ULONG rsc_mutex_on_set_addr;
23 
24 static ULONG rsc_enum_sem_usage;
25 static ULONG rsc_enum_sem_get_count;
26 static ULONG rsc_enum_mutex_usage;
27 static ULONG rsc_enum_mem_alloc_count;
28 
29 static ULONG rsc_cdc_sem_usage;
30 static ULONG rsc_cdc_sem_get_count;
31 static ULONG rsc_cdc_mutex_usage;
32 static ULONG rsc_cdc_mem_alloc_count;
33 
34 static ULONG error_callback_counter;
35 
36 static UX_TEST_SETUP _SetAddress = UX_TEST_SETUP_SetAddress;
ux_test_hcd_entry_set_addr(UX_TEST_ACTION * action,VOID * _params)37 static VOID ux_test_hcd_entry_set_addr(UX_TEST_ACTION *action, VOID *_params)
38 {
39 
40     set_addr_counter ++;
41 
42     rsc_mem_alloc_cnt_on_set_addr = ux_test_utility_sim_mem_alloc_count();
43 
44     rsc_sem_on_set_addr = ux_test_utility_sim_sem_create_count();
45     rsc_sem_get_on_set_addr = ux_test_utility_sim_sem_get_count();
46     rsc_mutex_on_set_addr = ux_test_utility_sim_mutex_create_count();
47 }
48 static UX_TEST_HCD_SIM_ACTION log_on_SetAddr[] = {
49 {   .function = UX_HCD_TRANSFER_REQUEST,
50     .req_setup = &_SetAddress,
51     .req_action = UX_TEST_SETUP_MATCH_REQ,
52     .action_func = ux_test_hcd_entry_set_addr,
53     .no_return = UX_TRUE
54 }, /* Invoke callback & continue */
55 {   0   }
56 };
57 
count_error_callback(struct UX_TEST_ACTION_STRUCT * action,VOID * params)58 static void count_error_callback(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
59 {
60 UX_TEST_ERROR_CALLBACK_PARAMS *error = (UX_TEST_ERROR_CALLBACK_PARAMS *)params;
61 
62     // printf("error trap: 0x%x, 0x%x, 0x%x\n", error->system_level, error->system_context, error->error_code);
63     error_callback_counter ++;
64 }
65 
66 static UX_TEST_HCD_SIM_ACTION count_on_error_trap[] = {
67 {   .usbx_function = UX_TEST_OVERRIDE_ERROR_CALLBACK,
68     .action_func = count_error_callback,
69 },
70 {   0   }
71 };
72 
sleep_break_on_error(VOID)73 static UINT  sleep_break_on_error(VOID)
74 {
75 
76     if (error_callback_counter >= 3)
77         return error_callback_counter;
78 
79     return UX_SUCCESS;
80 }
81 
82 /* Define what the initial system looks like.  */
83 
84 #ifdef CTEST
test_application_define(void * first_unused_memory)85 void test_application_define(void *first_unused_memory)
86 #else
87 void usbx_hub_basic_memory_test_application_define(void *first_unused_memory)
88 #endif
89 {
90 
91 CHAR *memory_pointer = first_unused_memory;
92 
93     /* Inform user.  */
94     printf("Running Hub Basic Memory Functionality Test......................... ");
95 
96     stepinfo("\n");
97 
98     /* Override error trap. */
99     ux_test_link_hooks_from_array(count_on_error_trap);
100 
101     /* Reset testing counts. */
102     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
103     ux_test_utility_sim_mem_alloc_count_reset();
104     ux_test_utility_sim_mutex_create_count_reset();
105     ux_test_utility_sim_sem_create_count_reset();
106     ux_test_utility_sim_sem_get_count_reset();
107     /* Reset error generations */
108     ux_test_utility_sim_sem_error_generation_stop();
109     ux_test_utility_sim_mutex_error_generation_stop();
110     ux_test_utility_sim_sem_get_error_generation_stop();
111 
112     initialize_hub(first_unused_memory);
113 }
114 
post_init_host()115 static void post_init_host()
116 {
117 
118 ULONG               mem_free;
119 ULONG               test_n;
120 
121     /* Test disconnect. */
122     stepinfo(">>>>>>>>>>>>>>>>>>> Test disconnect\n");
123     ux_test_disconnect_slave();
124     ux_test_disconnect_host_wait_for_enum_completion();
125 
126     /* Reset testing counts. */
127     ux_test_utility_sim_mem_alloc_count_reset();
128     ux_test_utility_sim_mutex_create_count_reset();
129     ux_test_utility_sim_sem_create_count_reset();
130     ux_test_utility_sim_sem_get_count_reset();
131     ux_test_hcd_sim_host_set_actions(log_on_SetAddr);
132 
133     /* Save free memory usage. */
134     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
135 
136     stepinfo(">>>>>>>>>>>>>>>>>>> Test connect\n");
137     /* Connect. */
138     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
139     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
140     class_hub_get();
141 
142     /* Log create counts for further tests. */
143     rsc_enum_mutex_usage = rsc_mutex_on_set_addr;
144     rsc_enum_sem_usage = rsc_sem_on_set_addr;
145     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_addr;
146     /* Log create counts when instances active for further tests. */
147     rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
148     rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
149     rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
150 
151     /* Lock log base for tests. */
152     ux_test_utility_sim_mem_alloc_log_lock();
153 
154     /* Simulate detach and attach for FS enumeration,
155        and check if there is memory error in normal enumeration.
156      */
157     stepinfo(">>>>>>>>>>>>>>>>>>> Enumeration test\n");
158     mem_free = (~0);
159     for (test_n = 0; test_n < 3; test_n++)
160     {
161         stepinfo("%4ld / 2\n", test_n);
162 
163         /* Disconnect. */
164         ux_test_dcd_sim_slave_disconnect();
165         ux_test_hcd_sim_host_disconnect();
166 
167         /* Update memory free level (disconnect) */
168         if (mem_free == (~0))
169             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
170         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
171         {
172 
173             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);
174             test_control_return(1);
175         }
176 
177         /* Connect. */
178         error_callback_counter = 0;
179         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
180         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
181 
182         /* Wait and break on error. */
183         ux_test_breakable_sleep(200, sleep_break_on_error);
184 
185         /* Check */
186         if (g_hub_host_from_system_change_function == UX_NULL)
187         {
188 
189             printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
190             test_control_return(1);
191         }
192     }
193 
194     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
195     stepinfo("cdc mem : %ld\n", rsc_cdc_mem_alloc_count);
196     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);
197 
198     /* Simulate detach and attach for FS enumeration,
199        and test possible memory allocation error handlings.
200      */
201     if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>>>>> Memory errors enumeration test\n");
202     mem_free = (~0);
203     for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
204     {
205 
206         stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
207 
208         /* Disconnect. */
209         ux_test_dcd_sim_slave_disconnect();
210         ux_test_hcd_sim_host_disconnect();
211 
212         /* Update memory free level (disconnect) */
213         if (mem_free == (~0))
214             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
215         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
216         {
217 
218             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);
219             test_control_return(1);
220         }
221 
222         /* Set memory error generation */
223         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
224 
225         /* Connect. */
226         error_callback_counter = 0;
227         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
228         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
229 
230         /* Wait and break on errors. */
231         ux_test_breakable_sleep(200, sleep_break_on_error);
232 
233         /* Check error */
234         if (g_hub_host_from_system_change_function != UX_NULL)
235         {
236 
237             printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
238             test_control_return(1);
239         }
240         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
241     }
242     ux_test_utility_sim_mem_alloc_error_generation_stop();
243     if (rsc_cdc_mem_alloc_count) stepinfo("\n");
244 }
245 
post_init_device(ULONG input)246 static void post_init_device(ULONG input)
247 {
248 }