1 #include "ux_test.h"
2 #include "ux_test_hcd_sim_host.h"
3 #include "ux_test_dcd_sim_slave.h"
4 
5 #ifndef _ux_utility_time_elapsed
6 #define _ux_utility_time_elapsed(t0,t1) ((t1)>=(t0) ? ((t1)-(t0)) : (0xFFFFFFFF - (t0) + (t1)))
7 #endif
8 
9 #define UX_TEST_TIMEOUT_MS 3000
10 
11 static UX_TEST_ACTION ux_test_action_handler_check(UX_TEST_ACTION *action, UX_TEST_FUNCTION usbx_function, void *params, UCHAR advance);
12 
13 UINT  _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
14 UINT  _ux_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter);
15 void test_control_return(UINT);
16 extern ULONG ux_test_port_status;
17 
18 static UX_TEST_ACTION   *ux_test_hook_action_list; /* Link list, with .next NULL as end.  */
19 static UX_TEST_ACTION   *ux_test_main_action_list; /* Link list, with .next NULL as end.  */
20 static UX_TEST_ACTION   *ux_test_user_list_actions;/* Link list, with .created_list_next NULL as end.  */
21 static UCHAR            ux_test_expedient = 1;
22 static UCHAR            ignore_all_errors = 0;
23 static UCHAR            exit_on_errors = 0;
24 static ULONG            ux_test_memory_test_no_device_memory_free_amount;
25 
26 static UCHAR            ux_test_assert_hit_hint_off = 0;
27 static UCHAR            ux_test_assert_hit_exit_off = 0;
28 static ULONG            ux_test_assert_hit_count = 0;
29 static UINT             ux_test_assert_hit_exit_code = 1;
30 
_ux_test_main_action_list_thread_update(TX_THREAD * old,TX_THREAD * new)31 VOID _ux_test_main_action_list_thread_update(TX_THREAD *old, TX_THREAD *new)
32 {
33     UX_TEST_ACTION *list = ux_test_main_action_list;
34     if (old != new)
35     {
36         while(list)
37         {
38             if (list->thread_ptr == old)
39                 list->thread_ptr == new;
40             list = list->next;
41         }
42     }
43 }
44 
_ux_test_main_action_list_semaphore_update(TX_SEMAPHORE * old,TX_SEMAPHORE * new)45 VOID _ux_test_main_action_list_semaphore_update(TX_SEMAPHORE *old, TX_SEMAPHORE *new)
46 {
47     UX_TEST_ACTION *list = ux_test_main_action_list;
48     if (old != new)
49     {
50         while(list)
51         {
52             if (list->semaphore_ptr == old)
53                 list->semaphore_ptr == new;
54             list = list->next;
55         }
56     }
57 }
58 
_ux_test_main_action_list_mutex_update(TX_MUTEX * old,TX_MUTEX * new)59 VOID _ux_test_main_action_list_mutex_update(TX_MUTEX *old, TX_MUTEX *new)
60 {
61     UX_TEST_ACTION *list = ux_test_main_action_list;
62     if (old != new)
63     {
64         while(list)
65         {
66             if (list->mutex_ptr == old)
67                 list->mutex_ptr == new;
68             list = list->next;
69         }
70     }
71 }
72 
73 
_ux_test_check_action_function(UX_TEST_ACTION * new_actions)74 UCHAR _ux_test_check_action_function(UX_TEST_ACTION *new_actions)
75 {
76 
77 UCHAR result;
78 
79 
80 #ifndef UX_TEST_RACE_CONDITION_TESTS_ON
81     result = (new_actions->usbx_function > 0 && new_actions->usbx_function < (ULONG)UX_TEST_OVERRIDE_RACE_CONDITION_OVERRIDES);
82 #else
83     result = (new_actions->_usbx_function > 0 && new_actions->_usbx_function < (ULONG)UX_TEST_NUMBER_OVERRIDES);
84 #endif
85 
86     return result;
87 }
88 
_ux_test_append_action(UX_TEST_ACTION * list,UX_TEST_ACTION * new_action)89 VOID _ux_test_append_action(UX_TEST_ACTION *list, UX_TEST_ACTION *new_action)
90 {
91 
92 UX_TEST_ACTION *tail;
93 
94 
95     tail = list;
96     while (tail->next != UX_NULL)
97         tail = tail->next;
98     tail->next = new_action;
99 }
100 
ux_test_list_action_compare(UX_TEST_ACTION * list_item,UX_TEST_ACTION * action)101 UINT ux_test_list_action_compare(UX_TEST_ACTION *list_item, UX_TEST_ACTION *action)
102 {
103 UX_TEST_ACTION temp;
104 UINT           status;
105 
106     /* It's created one, check its contents.  */
107     if (list_item->created_list_next == list_item)
108     {
109         /* Copy action contents to test.  */
110         temp = *action;
111 
112         /* Set action next, created to match.  */
113         temp.next = list_item->next;
114         temp.created_list_next = list_item->created_list_next;
115 
116         /* Compare.  */
117         status = ux_utility_memory_compare(list_item, &temp, sizeof(temp));
118 
119         /* Return success if equal.  */
120         if (status == UX_SUCCESS)
121             return status;
122     }
123     else
124     {
125 
126         /* It's static one, check address.  */
127         if (list_item == action)
128             return UX_SUCCESS;
129     }
130 
131     /* No, they do not match.  */
132     return UX_NO_CLASS_MATCH;
133 }
134 
ux_test_remove_hook(UX_TEST_ACTION * action)135 VOID ux_test_remove_hook(UX_TEST_ACTION *action)
136 {
137 UX_TEST_ACTION *item;
138 UX_TEST_ACTION *previous;
139 
140     item = ux_test_hook_action_list;
141     while(item)
142     {
143         if (ux_test_list_action_compare(item, action) != UX_SUCCESS)
144         {
145             previous = item;
146             item = item->next;
147             continue;
148         }
149 
150         /* Remove action from head. */
151         if (item == ux_test_hook_action_list)
152         {
153             ux_test_hook_action_list = item->next;
154         }
155 
156         /* Remove action from list. */
157         else
158         {
159             previous->next = action->next;
160         }
161 
162         /* Free if it's created.  */
163         if (action->created_list_next == action)
164             free(action);
165 
166         /* Remove is done. */
167         return;
168     }
169 }
170 
ux_test_link_hook(UX_TEST_ACTION * action)171 UINT ux_test_link_hook(UX_TEST_ACTION *action)
172 {
173 UX_TEST_ACTION  *tail;
174 
175     if (ux_test_hook_action_list == UX_NULL)
176     {
177         ux_test_hook_action_list = action;
178     }
179     else
180     {
181         tail = ux_test_hook_action_list;
182         while(tail)
183         {
184             /* Check existing. */
185             if (ux_test_list_action_compare(tail, action) == UX_SUCCESS)
186                 return UX_ERROR;
187 
188             /* Check next.  */
189             if (tail->next == UX_NULL)
190                 break;
191 
192             tail = tail->next;
193         }
194         tail->next = action;
195     }
196     return UX_SUCCESS;
197 }
198 
ux_test_add_hook(UX_TEST_ACTION action)199 UINT ux_test_add_hook(UX_TEST_ACTION action)
200 {
201 UX_TEST_ACTION *created_action;
202 UINT           status;
203 
204     created_action = (UX_TEST_ACTION *)malloc(sizeof(UX_TEST_ACTION));
205     UX_TEST_ASSERT(created_action);
206 
207     *created_action = action;
208 
209     created_action->next = UX_NULL;
210 
211     /* We use the memory pointer to indicate it's added by memory allocation.
212      * On clean up or free we should free allocated memory.
213      */
214     created_action->created_list_next = created_action;
215 
216     status = ux_test_link_hook(created_action);
217     if (status != UX_SUCCESS)
218     {
219         free(created_action);
220     }
221     return status;
222 }
223 
ux_test_remove_hooks_from_array(UX_TEST_ACTION * actions)224 VOID ux_test_remove_hooks_from_array(UX_TEST_ACTION *actions)
225 {
226 UX_TEST_ACTION *action;
227 
228     action = actions;
229     while(action->usbx_function)
230     {
231         //printf("rm %p\n", action);
232         UX_TEST_ASSERT(_ux_test_check_action_function(action));
233         ux_test_remove_hook(action);
234         action ++;
235     }
236 }
237 
ux_test_remove_hooks_from_list(UX_TEST_ACTION * actions)238 VOID ux_test_remove_hooks_from_list(UX_TEST_ACTION *actions)
239 {
240 UX_TEST_ACTION *action;
241 UX_TEST_ACTION *next;
242 
243     action = actions;
244     while(action)
245     {
246         UX_TEST_ASSERT(_ux_test_check_action_function(action));
247         next = action->next;
248         ux_test_remove_hook(action);
249         action = next;
250     }
251 }
252 
ux_test_link_hooks_from_array(UX_TEST_ACTION * actions)253 VOID ux_test_link_hooks_from_array(UX_TEST_ACTION *actions)
254 {
255 UX_TEST_ACTION *action;
256 
257     action = actions;
258     while(action->usbx_function)
259     {
260         UX_TEST_ASSERT(_ux_test_check_action_function(action));
261         ux_test_link_hook(action);
262         action ++;
263     }
264 }
265 
ux_test_link_hooks_from_list(UX_TEST_ACTION * actions)266 VOID ux_test_link_hooks_from_list(UX_TEST_ACTION *actions)
267 {
268 UX_TEST_ACTION *action;
269 
270     action = actions;
271     while(action)
272     {
273         UX_TEST_ASSERT(_ux_test_check_action_function(action));
274         ux_test_link_hook(action);
275         action = action->next;
276     }
277 }
278 
ux_test_add_hooks_from_array(UX_TEST_ACTION * actions)279 VOID ux_test_add_hooks_from_array(UX_TEST_ACTION *actions)
280 {
281 UX_TEST_ACTION *action;
282 
283     action = actions;
284     while(action->usbx_function)
285     {
286         UX_TEST_ASSERT(_ux_test_check_action_function(action));
287         ux_test_add_hook(*action);
288         action ++;
289     }
290 }
291 
ux_test_add_hooks_from_list(UX_TEST_ACTION * actions)292 VOID ux_test_add_hooks_from_list(UX_TEST_ACTION *actions)
293 {
294 UX_TEST_ACTION *action;
295 
296     action = actions;
297     while(action)
298     {
299         UX_TEST_ASSERT(_ux_test_check_action_function(action));
300         ux_test_add_hook(*action);
301         action = action->next;
302     }
303 }
304 
ux_test_do_hooks_before(UX_TEST_FUNCTION usbx_function,VOID * params)305 ULONG ux_test_do_hooks_before(UX_TEST_FUNCTION usbx_function, VOID *params)
306 {
307 UX_TEST_ACTION *list;
308 UX_TEST_ACTION action;
309 ULONG          action_count = 0;
310 ULONG          action_return = 0;
311 
312     list = ux_test_hook_action_list;
313     while(list)
314     {
315         action = ux_test_action_handler_check(list, usbx_function, params, UX_FALSE);
316         if (action.matched  && !action.do_after)
317         {
318             action_count ++;
319             if (!action.no_return)
320                 action_return = 0x80000000u;
321         }
322         ux_test_do_action_before(&action, params);
323         list = list->next;
324     }
325     return (action_count | action_return);
326 }
327 
ux_test_do_hooks_after(UX_TEST_FUNCTION usbx_function,VOID * params)328 VOID ux_test_do_hooks_after(UX_TEST_FUNCTION usbx_function, VOID *params)
329 {
330 UX_TEST_ACTION *list;
331 UX_TEST_ACTION action;
332 ULONG          action_count = 0;
333 
334     list = ux_test_hook_action_list;
335     while(list)
336     {
337         action = ux_test_action_handler_check(list, usbx_function, params, UX_FALSE);
338         if (action.matched)
339             action_count ++;
340         ux_test_do_action_after(&action, params);
341         list = list->next;
342     }
343 }
344 
ux_test_free_hook_actions()345 VOID ux_test_free_hook_actions()
346 {
347 UX_TEST_ACTION  *action;
348 
349     while(ux_test_hook_action_list)
350     {
351         action = ux_test_hook_action_list;
352         ux_test_hook_action_list = ux_test_hook_action_list->next;
353 
354         /* If this action is added/created, free allocated memory.  */
355         if (action->created_list_next == action)
356         {
357             free(action);
358         }
359     }
360 }
361 
_ux_test_add_action_to_list(UX_TEST_ACTION * list,UX_TEST_ACTION action)362 VOID _ux_test_add_action_to_list(UX_TEST_ACTION *list, UX_TEST_ACTION action)
363 {
364 
365 UX_TEST_ACTION  *new_action = UX_NULL;
366 UX_TEST_ACTION  *tail;
367 
368 
369     /* Do some idiot-proof checks.  */
370     {
371         /* Check the function. */
372 #ifndef UX_TEST_RACE_CONDITION_TESTS_ON
373         UX_TEST_ASSERT((action.usbx_function > 0 && action.usbx_function < (ULONG)UX_TEST_OVERRIDE_RACE_CONDITION_OVERRIDES));
374 #else
375         UX_TEST_ASSERT((action._usbx_function > 0 && action._usbx_function < (ULONG)UX_TEST_NUMBER_OVERRIDES));
376 #endif
377 
378         /* Make sure expedient is on when it should be. */
379         if (action.no_return == 0 &&
380             /* For user callbacks, it's okay. */
381             action.usbx_function < UX_TEST_OVERRIDE_USER_CALLBACKS)
382         {
383             /* Allowed if flow stopped to avoid low level operations.  */
384             #if 0
385             UX_TEST_ASSERT(ux_test_is_expedient_on());
386             #endif
387         }
388     }
389 
390     if (/* Is this the main list? */
391         list == ux_test_main_action_list ||
392         /* Is the head of user-list already an action? */
393         list->usbx_function)
394     {
395         new_action = (UX_TEST_ACTION *)malloc(sizeof(UX_TEST_ACTION));
396         *new_action = action;
397         new_action->next = UX_NULL;
398     }
399 
400     if (list == ux_test_main_action_list)
401     {
402 
403         if (!ux_test_main_action_list)
404             ux_test_main_action_list = new_action;
405         else
406             _ux_test_append_action(list, new_action);
407     }
408     else
409     {
410 
411         if (!list->usbx_function)
412             *list = action;
413         else
414         {
415 
416             /* Append to user created list. */
417             if (!ux_test_user_list_actions)
418                 ux_test_user_list_actions = new_action;
419             else
420             {
421 
422                 tail = ux_test_user_list_actions;
423                 while (tail->created_list_next)
424                     tail = tail->created_list_next;
425                 tail->created_list_next = new_action;
426             }
427 
428             _ux_test_append_action(list, new_action);
429         }
430     }
431 }
432 
ux_test_add_action_to_main_list(UX_TEST_ACTION new_action)433 VOID ux_test_add_action_to_main_list(UX_TEST_ACTION new_action)
434 {
435 
436     _ux_test_add_action_to_list(ux_test_main_action_list, new_action);
437 }
438 
ux_test_add_action_to_main_list_multiple(UX_TEST_ACTION new_action,UINT num)439 VOID ux_test_add_action_to_main_list_multiple(UX_TEST_ACTION new_action, UINT num)
440 {
441 
442     while (num--)
443         _ux_test_add_action_to_list(ux_test_main_action_list, new_action);
444 }
445 
ux_test_add_action_to_user_list(UX_TEST_ACTION * list,UX_TEST_ACTION new_action)446 VOID ux_test_add_action_to_user_list(UX_TEST_ACTION *list, UX_TEST_ACTION new_action)
447 {
448 
449     _ux_test_add_action_to_list(list, new_action);
450 }
451 
ux_test_set_main_action_list_from_list(UX_TEST_ACTION * new_actions)452 VOID ux_test_set_main_action_list_from_list(UX_TEST_ACTION *new_actions)
453 {
454 
455     UX_TEST_ASSERT(!ux_test_main_action_list);
456     while (new_actions)
457     {
458 
459         ux_test_add_action_to_main_list(*new_actions);
460         new_actions = new_actions->next;
461     }
462 }
463 
ux_test_set_main_action_list_from_array(UX_TEST_ACTION * new_actions)464 VOID ux_test_set_main_action_list_from_array(UX_TEST_ACTION *new_actions)
465 {
466 
467     UX_TEST_ASSERT(!ux_test_main_action_list);
468     while (new_actions->usbx_function)
469     {
470 
471         ux_test_add_action_to_main_list(*new_actions);
472         new_actions++;
473     }
474 }
475 
ux_test_free_user_list_actions()476 VOID ux_test_free_user_list_actions()
477 {
478 
479 UX_TEST_ACTION *action;
480 
481 
482     while (ux_test_user_list_actions)
483     {
484 
485         action = ux_test_user_list_actions;
486         ux_test_user_list_actions = ux_test_user_list_actions->created_list_next;
487         free(action);
488     }
489 }
490 
_ux_test_advance_actions()491 static VOID _ux_test_advance_actions()
492 {
493 
494 UX_TEST_ACTION *action;
495 
496 
497     UX_TEST_ASSERT(ux_test_main_action_list != UX_NULL);
498     action = ux_test_main_action_list;
499     ux_test_main_action_list = ux_test_main_action_list->next;
500     free(action);
501 }
502 
ux_test_clear_main_list_actions()503 VOID ux_test_clear_main_list_actions()
504 {
505 
506     while (ux_test_main_action_list)
507         _ux_test_advance_actions();
508 }
509 
_ux_test_set_actions_and_set_function(UX_TEST_ACTION * new_actions,UX_TEST_FUNCTION function)510 VOID _ux_test_set_actions_and_set_function(UX_TEST_ACTION *new_actions, UX_TEST_FUNCTION function)
511 {
512 
513     UX_TEST_ASSERT(new_actions != UX_NULL);
514 
515     while (new_actions->function || new_actions->usbx_function)
516     {
517 
518         if (new_actions->function && !new_actions->usbx_function)
519             new_actions->usbx_function = function;
520         ux_test_add_action_to_main_list(*new_actions);
521         new_actions++;
522     }
523 }
524 
ux_test_hcd_sim_host_set_actions(UX_TEST_ACTION * new_actions)525 VOID ux_test_hcd_sim_host_set_actions(UX_TEST_ACTION *new_actions)
526 {
527 
528     ux_test_clear_main_list_actions();
529 
530     if (new_actions != UX_NULL)
531         _ux_test_set_actions_and_set_function(new_actions, UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY);
532 }
533 
ux_test_dcd_sim_slave_set_actions(UX_TEST_ACTION * new_actions)534 VOID ux_test_dcd_sim_slave_set_actions(UX_TEST_ACTION *new_actions)
535 {
536 
537     ux_test_clear_main_list_actions();
538 
539     if (new_actions != UX_NULL)
540         _ux_test_set_actions_and_set_function(new_actions, UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION);
541 }
542 
543 /* Returns whether there are any actions in the list.  */
ux_test_check_actions_empty()544 UCHAR ux_test_check_actions_empty()
545 {
546     return(ux_test_main_action_list == UX_NULL ? UX_TRUE : UX_FALSE);
547 }
548 
ux_test_wait_for_empty_actions()549 UINT ux_test_wait_for_empty_actions()
550 {
551     return ux_test_wait_for_null((VOID **)&ux_test_main_action_list);
552 }
553 
ux_test_wait_for_empty_actions_wait_time(UINT wait_time_ms)554 UINT ux_test_wait_for_empty_actions_wait_time(UINT wait_time_ms)
555 {
556     return ux_test_wait_for_null_wait_time((VOID **)&ux_test_main_action_list, wait_time_ms);
557 }
558 
ux_test_get_num_actions_left()559 UINT ux_test_get_num_actions_left()
560 {
561 
562 UINT            num_actions_remaining = 0;
563 UX_TEST_ACTION  *action = ux_test_main_action_list;
564 
565 
566     while (action)
567     {
568         num_actions_remaining++;
569         action = action->next;
570     }
571 
572     return(num_actions_remaining);
573 }
574 
575 VOID _ux_host_class_storage_driver_read_write_notify(VOID *func);
576 
ux_test_cleanup_everything(VOID)577 VOID ux_test_cleanup_everything(VOID)
578 {
579 
580     /* Free main list actions. */
581     ux_test_clear_main_list_actions();
582 
583     /* Free allocated user list actions.  */
584     ux_test_free_user_list_actions();
585 
586     /* Free added hook actions.  */
587     ux_test_free_hook_actions();
588 
589     /* Reset expedient value.  */
590     ux_test_expedient = UX_TRUE;
591 
592     /* Reset free memory test amount. */
593     ux_test_memory_test_no_device_memory_free_amount = 0;
594 
595     /* Assert related.  */
596     ux_test_assert_hit_count = 0;
597     ux_test_assert_hit_hint_off = 0;
598     ux_test_assert_hit_exit_off = 0;
599     ux_test_assert_hit_exit_code = 1;
600 
601 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
602     _ux_host_class_storage_driver_read_write_notify(UX_NULL);
603 #endif
604 }
605 
ux_test_do_action_before(UX_TEST_ACTION * action,VOID * params)606 VOID ux_test_do_action_before(UX_TEST_ACTION *action, VOID *params)
607 {
608 
609     if (action->matched && !action->do_after)
610     {
611         if (action->action_func)
612         {
613             action->action_func(action, params);
614         }
615     }
616 }
617 
ux_test_do_action_after(UX_TEST_ACTION * action,VOID * params)618 VOID ux_test_do_action_after(UX_TEST_ACTION *action, VOID *params)
619 {
620 
621     if (action->matched && action->do_after)
622     {
623         if (action->action_func)
624         {
625             action->action_func(action, params);
626         }
627     }
628 }
629 
ux_test_turn_on_expedient(UCHAR * original_expedient)630 VOID ux_test_turn_on_expedient(UCHAR *original_expedient)
631 {
632 
633     if (original_expedient)
634     {
635         *original_expedient = ux_test_expedient;
636     }
637     ux_test_expedient = 1;
638 }
639 
ux_test_turn_off_expedient(UCHAR * original_expedient)640 VOID ux_test_turn_off_expedient(UCHAR *original_expedient)
641 {
642 
643     if (original_expedient)
644     {
645         *original_expedient = ux_test_expedient;
646     }
647     ux_test_expedient = 0;
648 }
649 
ux_test_set_expedient(UCHAR value)650 VOID ux_test_set_expedient(UCHAR value)
651 {
652 
653     ux_test_expedient = value;
654 }
655 
ux_test_is_expedient_on()656 UCHAR ux_test_is_expedient_on()
657 {
658 
659     return(ux_test_expedient);
660 }
661 
ux_test_action_handler(UX_TEST_FUNCTION usbx_function,void * params)662 UX_TEST_ACTION ux_test_action_handler(UX_TEST_FUNCTION usbx_function, void *params)
663 {
664     return ux_test_action_handler_check(ux_test_main_action_list, usbx_function, params, UX_TRUE);
665 }
666 
ux_test_action_handler_check(UX_TEST_ACTION * list,UX_TEST_FUNCTION usbx_function,void * params,UCHAR advance)667 static UX_TEST_ACTION ux_test_action_handler_check(UX_TEST_ACTION *list, UX_TEST_FUNCTION usbx_function, void *params, UCHAR advance)
668 {
669 
670 UINT                                                    i;
671 UINT                                                    min;
672 UX_TEST_ACTION                                          *this = list;
673 UX_TEST_ACTION                                          result = { 0 };
674 UCHAR                                                   act = 0;
675 UX_TRANSFER                                             *host_req;
676 UX_SLAVE_TRANSFER                                       *slave_req;
677 ULONG                                                   *slave_req_code = UX_NULL;
678 UINT                                                    *req_code = UX_NULL;
679 ULONG                                                   *req_actual_len = UX_NULL;
680 UX_ENDPOINT                                             *ep;
681 TX_THREAD                                               *this_thread;
682 UX_TEST_SETUP                                           req_setup;
683 UX_TEST_SIM_ENTRY_ACTION                                generic_transfer_parameter = { 0 };
684 UX_TEST_GENERIC_CD                                      *generic_cd_params;
685 UX_TEST_GENERIC_CD                                      _generic_cd_params;
686 UINT                                                    str_len0;
687 UINT                                                    str_len1;
688 UCHAR                                                   ignore_param_checks = 0;
689 UX_TEST_OVERRIDE_TX_SEMAPHORE_GET_PARAMS                *semaphore_get_params;
690 UX_TEST_OVERRIDE_TX_SEMAPHORE_CREATE_PARAMS             *semaphore_create_params;
691 UX_TEST_OVERRIDE_TX_THREAD_CREATE_PARAMS                *thread_create_params;
692 UX_TEST_ERROR_CALLBACK_PARAMS                           *error_callback_params;
693 UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_READ_WRITE_FLUSH_PARAMS*device_media_read_write_flush_params;
694 UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_STATUS_PARAMS          *device_media_status_params;
695 UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST_PARAMS  *host_stack_transfer_request_params;
696 UX_TEST_OVERRIDE_TX_THREAD_PREEMPTION_CHANGE_PARAMS     *thread_preemption_change_params;
697 UX_TEST_OVERRIDE_UX_HOST_STACK_INTERFACE_SET_PARAMS     *host_stack_interface_set_params;
698 UX_TEST_OVERRIDE_TX_MUTEX_GET_PARAMS                    *mutex_get_params;
699 UX_TEST_OVERRIDE_TX_MUTEX_PUT_PARAMS                    *mutex_put_params;
700 UX_TEST_OVERRIDE_TX_MUTEX_CREATE_PARAMS                 *mutex_create_params;
701 UX_TEST_OVERRIDE_NX_PACKET_POOL_CREATE_PARAMS           *packet_pool_create_params;
702 UX_TEST_OVERRIDE_NX_PACKET_ALLOCATE_PARAMS              *packet_allocate_params;
703 
704 
705     if (this)
706     {
707 
708         if (this->usbx_function == usbx_function)
709         {
710 
711             /* If appropriate, setup generic controller driver (CD) parameter. */
712             if (this->usbx_function == UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY ||
713                 this->usbx_function == UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION ||
714                 this->usbx_function == UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST)
715             {
716                 /* Treat a transfer request action like an HCD action. */
717                 if (usbx_function == UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST)
718                 {
719                     host_stack_transfer_request_params = params;
720                     generic_cd_params = &_generic_cd_params;
721                     generic_cd_params->parameter = host_stack_transfer_request_params->transfer_request;
722                     generic_cd_params->function = UX_HCD_TRANSFER_REQUEST;
723                 }
724                 else
725                 {
726                     generic_cd_params = params;
727                 }
728             }
729 
730             /* Should we ignore the param checking? */
731             if (this->ignore_params)
732             {
733                 if (this->usbx_function == UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY ||
734                     this->usbx_function == UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION)
735                 {
736                     /* Check the sub-function. */
737                     if (this->function == generic_cd_params->function)
738                     {
739                         ignore_param_checks = 1;
740                     }
741                 }
742                 else
743                 {
744                     /* There is no sub-function. */
745                     ignore_param_checks = 1;
746                 }
747             }
748 
749             act = 1;
750             if (!ignore_param_checks)
751             {
752                 switch (usbx_function)
753                 {
754 
755                 case UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY:
756                 case UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION:
757                 case UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST:
758 
759                     act = 0;
760                     if (this->function == generic_cd_params->function)
761                     {
762 
763                         act = 1;
764                         switch (generic_cd_params->function)
765                         {
766 
767                             /* We have action on endpoint entries */
768                         case UX_HCD_CREATE_ENDPOINT:
769                         //case UX_DCD_CREATE_ENDPOINT:
770                         case UX_HCD_DESTROY_ENDPOINT:
771                         //case UX_DCD_DESTROY_ENDPOINT:
772                         case UX_HCD_RESET_ENDPOINT:
773                         //case UX_DCD_RESET_ENDPOINT:
774                         case UX_DCD_ENDPOINT_STATUS:
775                         case UX_DCD_STALL_ENDPOINT:
776 
777                             ep = generic_cd_params->parameter;
778 
779                             if ((this->req_action & UX_TEST_MATCH_EP) &&
780                                 this->req_ep_address != ep->ux_endpoint_descriptor.bEndpointAddress)
781                                 act = 0;
782 
783                             break;
784 
785                             /* We have action on transfer request abort */
786                         case UX_HCD_TRANSFER_ABORT:
787                         //case UX_DCD_TRANSFER_ABORT:
788 
789                             if (UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION != usbx_function)
790                             {
791 
792                                 host_req = (UX_TRANSFER *)generic_cd_params->parameter;
793                                 if ((this->req_action & UX_TEST_MATCH_EP) &&
794                                     this->req_ep_address != host_req->ux_transfer_request_endpoint->ux_endpoint_descriptor.bEndpointAddress)
795                                     act = 0;
796                             }
797                             else
798                             {
799 
800                                 slave_req = (UX_SLAVE_TRANSFER *)generic_cd_params->parameter;
801                                 if ((this->req_action & UX_TEST_MATCH_EP) &&
802                                     this->req_ep_address != slave_req->ux_slave_transfer_request_endpoint->ux_slave_endpoint_descriptor.bEndpointAddress)
803                                     act = 0;
804                             }
805                             break;
806 
807                             /* We have action on transfer request */
808                         case UX_HCD_TRANSFER_REQUEST:
809                         //case UX_DCD_TRANSFER_REQUEST:
810 
811                             generic_transfer_parameter.req_setup = &req_setup;
812 
813                             if (usbx_function == UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY ||
814                                 usbx_function == UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST)
815                             {
816                                 host_req = generic_cd_params->parameter;
817 
818                                 generic_transfer_parameter.req_actual_len = host_req->ux_transfer_request_actual_length;
819                                 generic_transfer_parameter.req_data = host_req->ux_transfer_request_data_pointer;
820                                 generic_transfer_parameter.req_ep_address = host_req->ux_transfer_request_endpoint->ux_endpoint_descriptor.bEndpointAddress;
821                                 generic_transfer_parameter.req_requested_len = host_req->ux_transfer_request_requested_length;
822                                 generic_transfer_parameter.req_status = host_req->ux_transfer_request_status;
823                                 generic_transfer_parameter.req_setup->ux_test_setup_index = host_req->ux_transfer_request_index;
824                                 generic_transfer_parameter.req_setup->ux_test_setup_request = host_req->ux_transfer_request_function;
825                                 generic_transfer_parameter.req_setup->ux_test_setup_type = host_req->ux_transfer_request_type;
826                                 generic_transfer_parameter.req_setup->ux_test_setup_value = host_req->ux_transfer_request_value;
827 
828                                 req_actual_len = &host_req->ux_transfer_request_actual_length;
829                                 req_code = &host_req->ux_transfer_request_completion_code;
830                             }
831                             else
832                             {
833                                 slave_req = generic_cd_params->parameter;
834 
835                                 generic_transfer_parameter.req_actual_len = slave_req->ux_slave_transfer_request_actual_length;
836                                 generic_transfer_parameter.req_data = slave_req->ux_slave_transfer_request_data_pointer;
837                                 generic_transfer_parameter.req_ep_address = slave_req->ux_slave_transfer_request_endpoint->ux_slave_endpoint_descriptor.bEndpointAddress;
838                                 generic_transfer_parameter.req_requested_len = slave_req->ux_slave_transfer_request_requested_length;
839                                 generic_transfer_parameter.req_status = slave_req->ux_slave_transfer_request_status;
840                                 generic_transfer_parameter.req_setup->ux_test_setup_type = (UCHAR)slave_req->ux_slave_transfer_request_type;
841 
842                                 req_actual_len = &slave_req->ux_slave_transfer_request_actual_length;
843                                 slave_req_code = &slave_req->ux_slave_transfer_request_completion_code;
844                             }
845 
846                             if (this->req_action & UX_TEST_MATCH_EP &&
847                                 this->req_ep_address != generic_transfer_parameter.req_ep_address)
848                                 act = 0;
849 
850                             /* We must confirm request setup is matching */
851                             if (this->req_setup)
852                             {
853 
854                                 if ((this->req_action & UX_TEST_SETUP_MATCH_REQUEST) &&
855                                     (generic_transfer_parameter.req_setup->ux_test_setup_type != this->req_setup->ux_test_setup_type))
856                                     act = 0;
857 
858                                 if ((this->req_action & UX_TEST_SETUP_MATCH_REQUEST) &&
859                                     (generic_transfer_parameter.req_setup->ux_test_setup_request != this->req_setup->ux_test_setup_request))
860                                     act = 0;
861 
862                                 if ((this->req_action & UX_TEST_SETUP_MATCH_VALUE) &&
863                                     (generic_transfer_parameter.req_setup->ux_test_setup_value != this->req_setup->ux_test_setup_value))
864                                     act = 0;
865 
866                                 if ((this->req_action & UX_TEST_SETUP_MATCH_INDEX) &&
867                                     (generic_transfer_parameter.req_setup->ux_test_setup_index != this->req_setup->ux_test_setup_index))
868                                     act = 0;
869                             }
870 
871                             /* Compare data. We only do the comparison if this action is not meant for substituting data. */
872                             if (!(this->req_action & UX_TEST_SIM_REQ_ANSWER) && this->req_data)
873                             {
874                                 if (generic_transfer_parameter.req_data == UX_NULL ||
875                                     /* Make sure we don't go off the end during the compare. */
876                                     generic_transfer_parameter.req_requested_len < this->req_actual_len)
877                                     act = 0;
878                                 else
879                                 {
880 
881                                     /* Is there no mask? */
882                                     if (!this->req_data_match_mask)
883                                     {
884                                         if (ux_utility_memory_compare(generic_transfer_parameter.req_data, this->req_data, this->req_actual_len) == UX_ERROR)
885                                         {
886                                             act = 0;
887                                         }
888                                     }
889                                     else
890                                     {
891                                         /* Compare with mask. */
892                                         for (i = 0; i < this->req_actual_len; i++)
893                                         {
894                                             if (this->req_data_match_mask[i] &&
895                                                 this->req_data[i] != generic_transfer_parameter.req_data[i])
896                                             {
897                                                 act = 0;
898                                                 break;
899                                             }
900                                         }
901                                     }
902                                 }
903                             }
904 
905                             /* Compare requested lengths. */
906                             if ((this->req_action & UX_TEST_MATCH_REQ_LEN) &&
907                                 (generic_transfer_parameter.req_requested_len != this->req_requested_len))
908                                 act = 0;
909 
910                             /* Do additional check. */
911                             if (this->check_func && !this->check_func())
912                                 act = 0;
913 
914                             break;
915 
916                         case UX_DCD_CHANGE_STATE:
917                         case UX_HCD_RESET_PORT:
918                         case UX_HCD_ENABLE_PORT:
919                         case UX_HCD_GET_PORT_STATUS:
920 
921                             /* AFAIK, there's nothing to check here. */
922 
923                             break;
924 
925                             /* The other entries are not handled now */
926                         default:
927                             UX_TEST_ASSERT(0);
928                             break;
929                         }
930                     }
931                     break;
932 
933     #if 0
934                 case UX_TEST_OVERRIDE_UX_UTILITY_MEMORY_ALLOCATE:
935 
936                     memory_allocate_params = params;
937                     if (memory_allocate_params->memory_alignment != this->memory_alignment ||
938                         memory_allocate_params->memory_cache_flag != this->memory_cache_flag ||
939                         memory_allocate_params->memory_size_requested != this->memory_size_requested)
940                     {
941                         act = 0;
942                     }
943                     break;
944     #endif
945 
946                 case UX_TEST_OVERRIDE_TX_SEMAPHORE_GET:
947 
948                     semaphore_get_params = params;
949 
950                     if (this->semaphore_ptr != UX_NULL && semaphore_get_params->semaphore_ptr != this->semaphore_ptr ||
951                         semaphore_get_params->wait_option != this->wait_option)
952                     {
953                         act = 0;
954                     }
955                     break;
956 
957                 case UX_TEST_OVERRIDE_ERROR_CALLBACK:
958 
959                     error_callback_params = params;
960                     if ((this->error_code && error_callback_params->error_code != this->error_code) ||
961                         (this->system_context && error_callback_params->system_context != this->system_context) ||
962                         (this->system_level && error_callback_params->system_level != this->system_level))
963                     {
964                         act = 0;
965                     }
966                     break;
967 
968                 case UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_READ:
969 
970                     device_media_read_write_flush_params = params;
971                     if ((device_media_read_write_flush_params->lba != this->lba ||
972                         device_media_read_write_flush_params->lun != this->lun ||
973                         device_media_read_write_flush_params->number_blocks != this->number_blocks))
974                     {
975                         act = 0;
976                     }
977                     break;
978 
979                 case UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_WRITE:
980 
981                     device_media_read_write_flush_params = params;
982                     if ((device_media_read_write_flush_params->lba != this->lba ||
983                         device_media_read_write_flush_params->lun != this->lun ||
984                         device_media_read_write_flush_params->number_blocks != this->number_blocks))
985                     {
986                         act = 0;
987                     }
988                     break;
989 
990                 case UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_FLUSH:
991 
992                     device_media_read_write_flush_params = params;
993                     if ((device_media_read_write_flush_params->lba != this->lba ||
994                         device_media_read_write_flush_params->lun != this->lun ||
995                         device_media_read_write_flush_params->number_blocks != this->number_blocks))
996                     {
997                         act = 0;
998                     }
999                     break;
1000 
1001                 case UX_TEST_OVERRIDE_UX_DEVICE_MEDIA_STATUS:
1002 
1003                     device_media_status_params = params;
1004                     if ((device_media_status_params->lun != this->lun ||
1005                         device_media_status_params->media_id != this->media_id))
1006                     {
1007                         act = 0;
1008                     }
1009                     break;
1010 
1011                 case UX_TEST_OVERRIDE_NX_PACKET_POOL_CREATE:
1012 
1013                     packet_pool_create_params = params;
1014 
1015                     /* We just compare names. */
1016 
1017                     UX_TEST_ASSERT(this->name_ptr != UX_NULL);
1018 
1019                     if (strcmp(packet_pool_create_params->name_ptr, this->name_ptr))
1020                     {
1021                         act = 0;
1022                     }
1023 
1024                     break;
1025 
1026                 case UX_TEST_OVERRIDE_NX_PACKET_ALLOCATE:
1027 
1028                     packet_allocate_params = params;
1029 
1030                     /* We just compare names. */
1031 
1032                     UX_TEST_ASSERT(this->name_ptr != UX_NULL);
1033 
1034                     if (strcmp(packet_allocate_params->pool_ptr->nx_packet_pool_name, this->name_ptr))
1035                     {
1036                         act = 0;
1037                     }
1038 
1039                     break;
1040 
1041                 case UX_TEST_OVERRIDE_TX_THREAD_CREATE:
1042 
1043                     thread_create_params = params;
1044 
1045                     /* We just compare names. */
1046 
1047                     UX_TEST_ASSERT(this->name_ptr != UX_NULL);
1048 
1049                     if (strcmp(thread_create_params->name_ptr, this->name_ptr))
1050                     {
1051                         act = 0;
1052                     }
1053 
1054                     break;
1055 
1056                 case UX_TEST_OVERRIDE_TX_SEMAPHORE_CREATE:
1057 
1058                     semaphore_create_params = params;
1059 
1060                     /* We just compare names. */
1061 
1062                     UX_TEST_ASSERT(this->semaphore_name != UX_NULL);
1063 
1064                     if (strcmp(semaphore_create_params->semaphore_name, this->semaphore_name))
1065                     {
1066                         act = 0;
1067                     }
1068 
1069                     break;
1070 
1071                 case UX_TEST_OVERRIDE_TX_THREAD_PREEMPTION_CHANGE:
1072 
1073                     thread_preemption_change_params = params;
1074                     if (this->thread_ptr != thread_preemption_change_params->thread_ptr ||
1075                         this->new_threshold != thread_preemption_change_params->new_threshold)
1076                     {
1077                         act = 0;
1078                     }
1079                     break;
1080 
1081                 case UX_TEST_OVERRIDE_UX_HOST_STACK_INTERFACE_SET:
1082 
1083                     host_stack_interface_set_params = params;
1084                     if (this->interface->ux_interface_descriptor.bInterfaceNumber != host_stack_interface_set_params->interface->ux_interface_descriptor.bInterfaceNumber ||
1085                         this->interface->ux_interface_descriptor.bAlternateSetting != host_stack_interface_set_params->interface->ux_interface_descriptor.bAlternateSetting)
1086                     {
1087                         act = 0;
1088                     }
1089                     break;
1090 
1091                 case UX_TEST_OVERRIDE_TX_MUTEX_GET:
1092 
1093                     mutex_get_params = params;
1094                     if (this->mutex_ptr &&
1095                         this->mutex_ptr != mutex_get_params->mutex_ptr)
1096                     {
1097                         act = 0;
1098                     }
1099                     if (mutex_get_params->wait_option != this->wait_option)
1100                     {
1101                         act = 0;
1102                     }
1103                     break;
1104 
1105                 case UX_TEST_OVERRIDE_TX_MUTEX_CREATE:
1106 
1107                     mutex_create_params = params;
1108                     if (this->mutex_ptr &&
1109                         this->mutex_ptr != mutex_create_params->mutex_ptr)
1110                     {
1111                         act = 0;
1112                     }
1113                     if (mutex_create_params->inherit != this->inherit)
1114                     {
1115                         act = 0;
1116                     }
1117                     if (this->name_ptr != UX_NULL)
1118                     {
1119                         str_len0 = 0;
1120                         _ux_utility_string_length_check(this->name_ptr, &str_len0, 2048);
1121                         if (mutex_create_params->name_ptr != UX_NULL)
1122                         {
1123                             str_len1 = 0;
1124                             _ux_utility_string_length_check(mutex_create_params->name_ptr, &str_len1, 2048);
1125                         }
1126                         else
1127                         {
1128                             str_len1 = 0;
1129                         }
1130                         if (str_len0 != str_len1)
1131                         {
1132                             act = 0;
1133                         }
1134                         if (str_len0 == str_len1 &&
1135                             ux_utility_memory_compare(this->name_ptr, mutex_create_params->name_ptr, str_len0) != UX_SUCCESS)
1136                         {
1137                             act = 0;
1138                         }
1139                     }
1140                     break;
1141 
1142                 case UX_TEST_OVERRIDE_TX_MUTEX_PUT:
1143 
1144                     mutex_put_params = params;
1145                     if (this->mutex_ptr != UX_NULL &&
1146                         this->mutex_ptr != mutex_put_params->mutex_ptr)
1147                     {
1148                         act = 0;
1149                     }
1150                     break;
1151                 }
1152             }
1153 
1154             /* Non-param checks - these checks happen regardless of the "ignore_params"
1155                value. */
1156 
1157             if (this->thread_to_match)
1158             {
1159                 this_thread = tx_thread_identify();
1160                 if (this_thread != this->thread_to_match)
1161                     act = 0;
1162             }
1163 
1164             if (this->check_func && this->check_func(params) != UX_TRUE)
1165             {
1166                 act = 0;
1167             }
1168         }
1169     }
1170 
1171     if (act)
1172     {
1173 
1174         //stepinfo("    action matched; usbx_function: %d\n", usbx_function);
1175 
1176         if (usbx_function == UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY ||
1177             usbx_function == UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION ||
1178             usbx_function == UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST)
1179         {
1180 
1181             /* Apply to port status */
1182             if (this -> port_action)
1183             {
1184 
1185                 UX_TEST_ASSERT(!this->no_return);
1186 
1187                 ux_test_port_status = this -> port_status;
1188                 // printf("Port status -> %lx\n", port_status);
1189                 /* Signal change on the port (HCD0.RH.PORT0). */
1190                 _ux_system_host -> ux_system_host_hcd_array -> ux_hcd_root_hub_signal[0] = 1;
1191                 /* Signal detach to host enum thread. */
1192                 _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
1193             }
1194 
1195             /* Apply to transfer */
1196             if (this -> req_action & UX_TEST_SIM_REQ_ANSWER)
1197             {
1198 
1199                 /* We should always return, otherwise the data we copy will just
1200                    get overridden by the actual transfer request. */
1201                 UX_TEST_ASSERT(!this->no_return);
1202 
1203                 /* Is there data to copy? */
1204                 if (this->req_data)
1205                 {
1206                     /* Make sure we don't overflow. */
1207                     min = generic_transfer_parameter.req_requested_len < this->req_actual_len ? generic_transfer_parameter.req_requested_len : this->req_actual_len;
1208 
1209                     /* Copy the data. */
1210                     _ux_utility_memory_copy(generic_transfer_parameter.req_data, this->req_data, min);
1211                 }
1212 
1213                 /* Set actual length */
1214                 if (this->req_actual_len == (~0))
1215                     *req_actual_len = generic_transfer_parameter.req_requested_len;
1216                 else
1217                     *req_actual_len = this->req_actual_len;
1218 
1219                 /* Set status code */
1220                 if (usbx_function == UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY ||
1221                     usbx_function == UX_TEST_OVERRIDE_UX_HOST_STACK_TRANSFER_REQUEST)
1222                     *req_code = this->req_status;
1223                 else
1224                     *slave_req_code = this->req_status;
1225             }
1226         }
1227 
1228         result = *this;
1229         result.matched = 1;
1230 
1231         if (advance)
1232             _ux_test_advance_actions();
1233     }
1234 
1235     return result;
1236 }
1237 
1238 #define SLEEP_STEP 1
ux_test_breakable_sleep(ULONG tick,UINT (* sleep_break_check_callback)(VOID))1239 UINT ux_test_breakable_sleep(ULONG tick, UINT (*sleep_break_check_callback)(VOID))
1240 {
1241 
1242 UINT  status;
1243 ULONG t;
1244 
1245     while(tick) {
1246 
1247         /* Sleep for a while. */
1248         t = (tick > SLEEP_STEP) ? SLEEP_STEP : tick;
1249 #if defined(UX_HOST_STANDALONE) || defined(UX_DEVICE_STANDALONE)
1250         ux_system_tasks_run();
1251 #endif
1252         tx_thread_sleep(t);
1253 
1254         /* Check if we want to break. */
1255         if (sleep_break_check_callback)
1256         {
1257 
1258             status = sleep_break_check_callback();
1259             if (status != UX_SUCCESS)
1260             {
1261 
1262                 /* We break sleep loop!
1263                    Status is returned for use to check. */
1264                 return status;
1265             }
1266         }
1267 
1268         /* Update remaining ticks. */
1269         tick -= t;
1270     }
1271 
1272     /* Normal end. */
1273     return UX_SUCCESS;
1274 }
ux_test_sleep_break_if(ULONG tick,UINT (* check)(VOID),UINT break_on_match_or_not,UINT rc_to_check)1275 UINT ux_test_sleep_break_if(ULONG tick, UINT (*check)(VOID),
1276                             UINT break_on_match_or_not,
1277                             UINT rc_to_check)
1278 {
1279 ULONG   t0, t1;
1280 UINT    status;
1281 
1282     t0 = tx_time_get();
1283     while(1)
1284     {
1285 #if defined(UX_HOST_STANDALONE)
1286         ux_system_tasks_run();
1287         tx_thread_relinquish();
1288 #else
1289         tx_thread_sleep(1);
1290 #endif
1291         if (check)
1292         {
1293             status = check();
1294             if (break_on_match_or_not)
1295             {
1296                 /* If RC match expected, break.  */
1297                 if (status == rc_to_check)
1298                     break;
1299             }
1300             else
1301             {
1302                 /* If RC not match expected, break.  */
1303                 if (status != rc_to_check)
1304                     break;
1305             }
1306         }
1307         t1 = tx_time_get();
1308         if (_ux_utility_time_elapsed(t0, t1) >= tick)
1309         {
1310             return(UX_TIMEOUT);
1311         }
1312     }
1313     return(UX_SUCCESS);
1314 }
1315 
1316 /* Error callback */
1317 
1318 UX_TEST_ERROR_CALLBACK_ERROR ux_error_hcd_transfer_stalled = { UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_STALLED };
1319 
ux_test_ignore_all_errors()1320 VOID ux_test_ignore_all_errors()
1321 {
1322     ignore_all_errors = UX_TRUE;
1323 }
1324 
ux_test_unignore_all_errors()1325 VOID ux_test_unignore_all_errors()
1326 {
1327     ignore_all_errors = UX_FALSE;
1328 }
1329 
1330 void test_control_return(UINT status);
ux_test_error_callback(UINT system_level,UINT system_context,UINT error_code)1331 VOID ux_test_error_callback(UINT system_level, UINT system_context, UINT error_code)
1332 {
1333 
1334 UX_TEST_ERROR_CALLBACK_PARAMS   params = { system_level, system_context, error_code };
1335 UX_TEST_ACTION                  action;
1336 
1337 
1338     if (ignore_all_errors == UX_TRUE)
1339     {
1340         return;
1341     }
1342 
1343     if (ux_test_do_hooks_before(UX_TEST_OVERRIDE_ERROR_CALLBACK, &params))
1344         return;
1345 
1346     action = ux_test_action_handler(UX_TEST_OVERRIDE_ERROR_CALLBACK, &params);
1347     if (action.matched)
1348     {
1349         return;
1350     }
1351 
1352     /* Failed test. Windows has some stupid printf bug where it stalls
1353        everything if other threads are printing as well. Doesn't matter anyways,
1354        since I use breakpoints for debugging this error. */
1355 #ifndef WIN32
1356     printf("%s:%d Unexpected error: 0x%x, 0x%x, 0x%x\n", __FILE__, __LINE__, system_level, system_context, error_code);
1357 #endif
1358 
1359     if (exit_on_errors)
1360         test_control_return(1);
1361 }
1362 
1363 /* Utility methods. */
1364 
1365 static ULONG ux_test_memory_test_no_device_memory_free_amount;
1366 
ux_test_memory_test_initialize()1367 void ux_test_memory_test_initialize()
1368 {
1369 
1370 UCHAR connected_when_started = 0;
1371 
1372     /* Are we connected? */
1373     if (_ux_system_host->ux_system_host_hcd_array[0].ux_hcd_nb_devices != 0)
1374     {
1375         /* Yes. */
1376         connected_when_started = 1;
1377 
1378         /* Then disconnect. */
1379         ux_test_disconnect_slave_and_host_wait_for_enum_completion();
1380     }
1381 
1382     /* Get normal amount of free memory when disconnected. This is to detect
1383        memory leaks. */
1384     ux_test_memory_test_no_device_memory_free_amount = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
1385     ux_test_connect_slave_and_host_wait_for_enum_completion();
1386 
1387     /* With basic free memory amount, do basic memory test. */
1388     ux_test_disconnect_slave_and_host_wait_for_enum_completion();
1389     ux_test_connect_slave_and_host_wait_for_enum_completion();
1390 
1391     /* (Let's be nice to the user.) Hello user! :) */
1392     if (!connected_when_started)
1393     {
1394         ux_test_disconnect_slave_and_host_wait_for_enum_completion();
1395     }
1396 }
1397 
ux_test_memory_test_check()1398 void ux_test_memory_test_check()
1399 {
1400 
1401     /* Has the memory check value not been initialized yet? */
1402     if (ux_test_memory_test_no_device_memory_free_amount == 0)
1403         return;
1404     UX_TEST_ASSERT(_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available == ux_test_memory_test_no_device_memory_free_amount);
1405 }
1406 
1407 #if defined(UX_HOST_STANDALONE)
_host_enum_is_pending(void)1408 static UINT _host_enum_is_pending(void)
1409 {
1410 UX_DEVICE           *enum_device = _ux_system_host -> ux_system_host_enum_device;
1411     /* Case 1 : there is nothing in enum list, nothing pending.  */
1412     if (enum_device == UX_NULL)
1413         return(UX_ERROR);
1414     /* Case 2 : enum list is not NULL, check enum flags each device.  */
1415     while(enum_device)
1416     {
1417         if (enum_device -> ux_device_flags & UX_DEVICE_FLAG_ENUM)
1418             return(UX_SUCCESS);
1419         enum_device = enum_device -> ux_device_enum_next;
1420     }
1421     return(UX_ERROR);
1422 }
_host_rh_removal_is_pending(void)1423 static UINT _host_rh_removal_is_pending(void)
1424 {
1425 UX_HCD  *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
1426     /* If device connected, pending.  */
1427     if (hcd -> ux_hcd_rh_device_connection)
1428         return(UX_SUCCESS);
1429     return(UX_ERROR);
1430 }
1431 #endif
1432 
1433 /* Wait for the enum thread to finish whatever it's currently doing. Note that
1434    this implies it's actually _doing_ something when this is called.
1435 
1436    Specifics: We do this by simply waiting for the the enum thread's semaphore's
1437    suspended count to be non-zero. */
ux_test_wait_for_enum_thread_completion()1438 VOID ux_test_wait_for_enum_thread_completion()
1439 {
1440 #if !defined(UX_HOST_STANDALONE)
1441     /* Is it actually running? */
1442     if (_ux_system_host -> ux_system_host_enum_semaphore.tx_semaphore_suspended_count == 0)
1443     {
1444 
1445         /* Wait for enum thread to complete. */
1446         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&_ux_system_host -> ux_system_host_enum_semaphore.tx_semaphore_suspended_count, 1));
1447     }
1448 #else
1449     {
1450         UINT    status;
1451         if (ux_test_port_status & UX_PS_CCS)
1452         {
1453             /* Loop a while to confirm enumeration start.  */
1454             status = ux_test_sleep_break_on_success(10, _host_enum_is_pending);
1455             if (status == UX_SUCCESS)
1456             {
1457                 /* Loop a while to confirm enumeration end.  */
1458                 status = ux_test_sleep_break_on_error(100, _host_enum_is_pending);
1459                 UX_ASSERT(status == UX_SUCCESS);
1460             }
1461         }
1462         else
1463         {
1464             /* Loop a while to confirm device removal.  */
1465             status = ux_test_sleep_break_on_error(100, _host_rh_removal_is_pending);
1466             UX_ASSERT(status == UX_SUCCESS);
1467         }
1468     }
1469 #endif
1470 }
1471 
ux_test_disconnect_host_no_wait()1472 VOID ux_test_disconnect_host_no_wait()
1473 {
1474 
1475     ux_test_hcd_sim_host_disconnect_no_wait();
1476 }
1477 
ux_test_disconnect_host_wait_for_enum_completion()1478 VOID ux_test_disconnect_host_wait_for_enum_completion()
1479 {
1480 
1481     /* No wait because ux_test_wait_for_enum_completion() expects the enum thread
1482        to be running when it's called. */
1483     ux_test_hcd_sim_host_disconnect_no_wait();
1484     ux_test_wait_for_enum_thread_completion();
1485     ux_test_memory_test_check();
1486 }
1487 
1488 /* This function should not be called from inside USBX because we wait for the
1489    deactivation to finish. If we have a semaphore the deactivation routine requires,
1490    then we have deadlock. */
ux_test_disconnect_slave_and_host_wait_for_enum_completion()1491 void ux_test_disconnect_slave_and_host_wait_for_enum_completion()
1492 {
1493 
1494 UX_HCD *hcd = &_ux_system_host->ux_system_host_hcd_array[0];
1495 
1496     ux_test_dcd_sim_slave_disconnect();
1497     /* No wait because below. */
1498     ux_test_disconnect_host_wait_for_enum_completion();
1499     ux_test_memory_test_check();
1500 }
1501 
ux_test_disconnect_slave()1502 VOID ux_test_disconnect_slave()
1503 {
1504 
1505     ux_test_dcd_sim_slave_disconnect();
1506 }
1507 
ux_test_connect_slave()1508 VOID ux_test_connect_slave()
1509 {
1510 
1511     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
1512 }
1513 
ux_test_connect_host_wait_for_enum_completion()1514 VOID ux_test_connect_host_wait_for_enum_completion()
1515 {
1516 
1517     /* No wait because ux_test_wait_for_enum_completion() expects the enum thread
1518        to be running when it's called. */
1519     ux_test_hcd_sim_host_connect_no_wait(UX_FULL_SPEED_DEVICE);
1520     ux_test_wait_for_enum_thread_completion();
1521 }
1522 
ux_test_connect_slave_and_host_wait_for_enum_completion()1523 VOID ux_test_connect_slave_and_host_wait_for_enum_completion()
1524 {
1525 
1526     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
1527     ux_test_connect_host_wait_for_enum_completion();
1528 }
1529 
1530 /* This is supposed to only change these parameters. In other words, the same
1531    classes should still be registered after calling this. */
ux_test_change_device_parameters(UCHAR * device_framework_high_speed,ULONG device_framework_length_high_speed,UCHAR * device_framework_full_speed,ULONG device_framework_length_full_speed,UCHAR * string_framework,ULONG string_framework_length,UCHAR * language_id_framework,ULONG language_id_framework_length,UINT (* ux_system_slave_change_function)(ULONG))1532 VOID ux_test_change_device_parameters(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed,
1533                                       UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed,
1534                                       UCHAR * string_framework, ULONG string_framework_length,
1535                                       UCHAR * language_id_framework, ULONG language_id_framework_length,
1536                                       UINT(*ux_system_slave_change_function)(ULONG))
1537 {
1538 
1539 UX_SLAVE_CLASS *class;
1540 UX_SLAVE_CLASS classes_copy[UX_MAX_SLAVE_CLASS_DRIVER];
1541 ULONG          class_index;
1542 
1543     /* Disconnect device. */
1544     ux_test_dcd_sim_slave_disconnect();
1545 
1546     /* First, save the classes. */
1547     memcpy(classes_copy, _ux_system_slave->ux_system_slave_class_array, sizeof(classes_copy));
1548 
1549     /* Uninitialize classes. */
1550     for (class_index = 0; class_index < UX_SYSTEM_DEVICE_MAX_CLASS_GET(); class_index++)
1551     {
1552 
1553         class = &_ux_system_slave->ux_system_slave_class_array[class_index];
1554         if (class->ux_slave_class_status == UX_USED)
1555             UX_TEST_CHECK_SUCCESS(ux_device_stack_class_unregister((UCHAR *)class->ux_slave_class_name, class->ux_slave_class_entry_function));
1556     }
1557 
1558     /* Uninitialize the stack. */
1559     UX_TEST_CHECK_SUCCESS(ux_device_stack_uninitialize());
1560 
1561     /* Now re-initialize stack with correct stuff. */
1562     UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_framework_high_speed, device_framework_length_high_speed,
1563                                                      device_framework_full_speed, device_framework_length_full_speed,
1564                                                      string_framework, string_framework_length,
1565                                                      language_id_framework, language_id_framework_length,
1566                                                      ux_system_slave_change_function));
1567 
1568     /* Now re-register the classes. */
1569     for (class_index = 0; class_index < UX_SYSTEM_DEVICE_MAX_CLASS_GET(); class_index++)
1570     {
1571 
1572         class = &classes_copy[class_index];
1573         if (class->ux_slave_class_status == UX_USED)
1574             UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register((UCHAR *)class->ux_slave_class_name,
1575                                                                  class->ux_slave_class_entry_function,
1576                                                                  class->ux_slave_class_configuration_number,
1577                                                                  class->ux_slave_class_interface_number,
1578                                                                  class->ux_slave_class_interface_parameter));
1579     }
1580 }
1581 
ux_test_host_stack_class_instance_get(UX_HOST_CLASS * host_class,UINT class_index,VOID ** class_instance)1582 UINT ux_test_host_stack_class_instance_get(UX_HOST_CLASS *host_class, UINT class_index, VOID **class_instance)
1583 {
1584 
1585 UINT status;
1586 UINT timeout_ms = UX_TEST_TIMEOUT_MS;
1587 #if defined(UX_HOST_STANDALONE)
1588 ULONG t0, t, elapsed;
1589     t0 = ux_utility_time_get();
1590 #endif
1591 
1592     do
1593     {
1594 
1595         status =  ux_host_stack_class_instance_get(host_class, class_index, class_instance);
1596 #if defined(UX_HOST_STANDALONE)
1597         ux_system_tasks_run();
1598         tx_thread_relinquish();
1599         t = ux_utility_time_get();
1600         elapsed = ux_utility_time_elapsed(t0, t);
1601         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1602             return(UX_ERROR);
1603 #else
1604         tx_thread_sleep(MS_TO_TICK(10));
1605         timeout_ms -= 10;
1606 #endif
1607 
1608     } while (status != UX_SUCCESS && timeout_ms);
1609 
1610     if (timeout_ms == 0)
1611         return UX_ERROR;
1612 
1613     return UX_SUCCESS;
1614 }
1615 
ux_test_wait_for_value_uint(UINT * current_value_ptr,UINT desired_value)1616 UINT ux_test_wait_for_value_uint(UINT *current_value_ptr, UINT desired_value)
1617 {
1618 
1619 UINT timeout_ms = UX_TEST_TIMEOUT_MS;
1620 #if defined(UX_HOST_STANDALONE)
1621 ULONG t0, t, elapsed;
1622     t0 = ux_utility_time_get();
1623 #endif
1624 
1625     while (*current_value_ptr != desired_value && timeout_ms)
1626     {
1627 
1628 #if defined(UX_HOST_STANDALONE)
1629         ux_system_tasks_run();
1630         tx_thread_relinquish();
1631         t = ux_utility_time_get();
1632         elapsed = ux_utility_time_elapsed(t0, t);
1633         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1634             return(UX_ERROR);
1635 #else
1636         tx_thread_sleep(MS_TO_TICK(10));
1637         timeout_ms -= 10;
1638 #endif
1639     }
1640 
1641     if (timeout_ms == 0)
1642         return UX_ERROR;
1643 
1644     return UX_SUCCESS;
1645 }
1646 
ux_test_wait_for_value_ulong(ULONG * current_value_ptr,ULONG desired_value)1647 UINT ux_test_wait_for_value_ulong(ULONG *current_value_ptr, ULONG desired_value)
1648 {
1649 
1650 UINT timeout_ms = UX_TEST_TIMEOUT_MS;
1651 #if defined(UX_HOST_STANDALONE)
1652 ULONG t0, t, elapsed;
1653     t0 = ux_utility_time_get();
1654 #endif
1655 
1656     while (*current_value_ptr != desired_value && timeout_ms)
1657     {
1658 
1659 #if defined(UX_HOST_STANDALONE)
1660         ux_system_tasks_run();
1661         tx_thread_relinquish();
1662         t = ux_utility_time_get();
1663         elapsed = ux_utility_time_elapsed(t0, t);
1664         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1665             return(UX_ERROR);
1666 #else
1667         tx_thread_sleep(MS_TO_TICK(10));
1668         timeout_ms -= 10;
1669 #endif
1670     }
1671 
1672     if (timeout_ms == 0)
1673         return UX_ERROR;
1674 
1675     return UX_SUCCESS;
1676 }
1677 
ux_test_wait_for_value_uchar(UCHAR * current_value_ptr,UCHAR desired_value)1678 UINT ux_test_wait_for_value_uchar(UCHAR *current_value_ptr, UCHAR desired_value)
1679 {
1680 
1681 UINT timeout_ms = UX_TEST_TIMEOUT_MS;
1682 #if defined(UX_HOST_STANDALONE)
1683 ULONG t0, t, elapsed;
1684     t0 = ux_utility_time_get();
1685 #endif
1686 
1687     while (*current_value_ptr != desired_value && timeout_ms)
1688     {
1689 
1690 #if defined(UX_HOST_STANDALONE)
1691         ux_system_tasks_run();
1692         tx_thread_relinquish();
1693         t = ux_utility_time_get();
1694         elapsed = ux_utility_time_elapsed(t0, t);
1695         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1696             return(UX_ERROR);
1697 #else
1698         tx_thread_sleep(MS_TO_TICK(10));
1699         timeout_ms -= 10;
1700 #endif
1701     }
1702 
1703     if (timeout_ms == 0)
1704         return UX_ERROR;
1705 
1706     return UX_SUCCESS;
1707 }
1708 
ux_test_wait_for_non_null(VOID ** current_value_ptr)1709 UINT ux_test_wait_for_non_null(VOID **current_value_ptr)
1710 {
1711 
1712 UINT timeout_ms = UX_TEST_TIMEOUT_MS;
1713 #if defined(UX_HOST_STANDALONE)
1714 ULONG t0, t, elapsed;
1715     t0 = ux_utility_time_get();
1716 #endif
1717 
1718     while (*current_value_ptr == UX_NULL && timeout_ms)
1719     {
1720 
1721 #if defined(UX_HOST_STANDALONE)
1722         ux_system_tasks_run();
1723         tx_thread_relinquish();
1724         t = ux_utility_time_get();
1725         elapsed = ux_utility_time_elapsed(t0, t);
1726         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1727             return(UX_ERROR);
1728 #else
1729         tx_thread_sleep(MS_TO_TICK(10));
1730         timeout_ms -= 10;
1731 #endif
1732     }
1733 
1734     if (timeout_ms == 0)
1735         return UX_ERROR;
1736 
1737     return UX_SUCCESS;
1738 }
1739 
ux_test_wait_for_null_wait_time(VOID ** current_value_ptr,UINT wait_time_ms)1740 UINT ux_test_wait_for_null_wait_time(VOID **current_value_ptr, UINT wait_time_ms)
1741 {
1742 
1743 UINT timeout_ms = wait_time_ms;
1744 #if defined(UX_HOST_STANDALONE)
1745 ULONG t0, t, elapsed;
1746     t0 = ux_utility_time_get();
1747 #endif
1748 
1749     while (*current_value_ptr != UX_NULL && timeout_ms)
1750     {
1751 
1752 #if defined(UX_HOST_STANDALONE)
1753         ux_system_tasks_run();
1754         tx_thread_relinquish();
1755         t = ux_utility_time_get();
1756         elapsed = ux_utility_time_elapsed(t0, t);
1757         if (elapsed >= UX_MS_TO_TICK_NON_ZERO(timeout_ms))
1758             return(UX_ERROR);
1759 #else
1760         tx_thread_sleep(MS_TO_TICK(10));
1761         timeout_ms -= 10;
1762 #endif
1763     }
1764 
1765     if (*current_value_ptr == UX_NULL)
1766         return(UX_SUCCESS);
1767 
1768         return UX_ERROR;
1769 }
1770 
ux_test_wait_for_null(VOID ** current_value_ptr)1771 UINT ux_test_wait_for_null(VOID **current_value_ptr)
1772 {
1773     return ux_test_wait_for_null_wait_time(current_value_ptr, UX_TEST_TIMEOUT_MS);
1774 }
1775 
ux_test_file_base_name(char * path,int n)1776 char *ux_test_file_base_name(char *path, int n)
1777 {
1778     char *ptr = path, *slash = path;
1779     int i;
1780     for (i = 0; i < n; i ++)
1781     {
1782         if (*ptr == 0)
1783             break;
1784         if (*ptr == '\\' || *ptr == '/')
1785             slash = ptr + 1;
1786         ptr ++;
1787     }
1788     return(slash);
1789 }
1790 
ux_test_assert_hit_hint(UCHAR on_off)1791 void ux_test_assert_hit_hint(UCHAR on_off)
1792 {
1793     ux_test_assert_hit_hint_off = !on_off;
1794 }
ux_test_assert_hit_exit(UCHAR on_off)1795 void ux_test_assert_hit_exit(UCHAR on_off)
1796 {
1797     ux_test_assert_hit_exit_off = !on_off;
1798 }
ux_test_assert_hit_count_get(void)1799 ULONG ux_test_assert_hit_count_get(void)
1800 {
1801     return ux_test_assert_hit_count;
1802 }
ux_test_assert_hit_count_reset(void)1803 void ux_test_assert_hit_count_reset(void)
1804 {
1805     ux_test_assert_hit_count = 0;
1806 }
ux_test_assert_hit(char * file,INT line)1807 void ux_test_assert_hit(char* file, INT line)
1808 {
1809     ux_test_assert_hit_count ++;
1810     if (!ux_test_assert_hit_hint_off)
1811         printf("%s:%d Assert HIT!\n", file, line);
1812     if (!ux_test_assert_hit_exit_off)
1813         test_control_return(ux_test_assert_hit_exit_code);
1814 }
1815 
ux_test_host_endpoint_write(UX_ENDPOINT * endpoint,UCHAR * buffer,ULONG length,ULONG * actual_length)1816 UINT ux_test_host_endpoint_write(UX_ENDPOINT *endpoint, UCHAR *buffer, ULONG length, ULONG *actual_length)
1817 {
1818 UINT            status;
1819 UX_TRANSFER     *transfer = &endpoint->ux_endpoint_transfer_request;
1820     transfer->ux_transfer_request_data_pointer = buffer;
1821     transfer->ux_transfer_request_requested_length = length;
1822     status = ux_host_stack_transfer_request(transfer);
1823 #if !defined(UX_HOST_STANDALONE)
1824     if (status == UX_SUCCESS)
1825     {
1826         status = tx_semaphore_get(&transfer->ux_transfer_request_semaphore,
1827                                   transfer->ux_transfer_request_timeout_value);
1828         if (status != TX_SUCCESS)
1829         {
1830             ux_host_stack_transfer_request_abort(transfer);
1831             status = UX_TRANSFER_TIMEOUT;
1832         }
1833     }
1834 #endif
1835     if (actual_length)
1836         *actual_length = transfer->ux_transfer_request_actual_length;
1837     return(status);
1838 }
1839