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, ¶ms))
1344 return;
1345
1346 action = ux_test_action_handler(UX_TEST_OVERRIDE_ERROR_CALLBACK, ¶ms);
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