1 /* This test is designed to test the simple dpump host/device class operation. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "ux_api.h"
6 #include "ux_system.h"
7 #include "ux_utility.h"
8
9 #include "fx_api.h"
10
11 #include "ux_device_class_dummy_printer.h"
12 #include "ux_device_stack.h"
13 #include "ux_host_class_printer.h"
14
15 #include "ux_test_dcd_sim_slave.h"
16 #include "ux_test_hcd_sim_host.h"
17 #include "ux_test_utility_sim.h"
18
19 /* Define constants. */
20 #define UX_DEMO_DEBUG_SIZE (4096*8)
21 #define UX_DEMO_STACK_SIZE 1024
22 #define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
23 #define UX_DEMO_XMIT_BUFFER_SIZE 512
24 #define UX_DEMO_RECEPTION_BUFFER_SIZE 512
25 #define UX_DEMO_FILE_BUFFER_SIZE 512
26 #define UX_DEMO_RECEPTION_BLOCK_SIZE 64
27 #define UX_DEMO_MEMORY_SIZE (64*1024)
28 #define UX_DEMO_FILE_SIZE (128 * 1024)
29 #define UX_RAM_DISK_MEMORY (256 * 1024)
30
31 /* Define local/extern function prototypes. */
32 static VOID test_thread_entry(ULONG);
33 static TX_THREAD tx_test_thread_host_simulation;
34 static TX_THREAD tx_test_thread_slave_simulation;
35 static VOID tx_test_thread_host_simulation_entry(ULONG);
36 static VOID tx_test_thread_slave_simulation_entry(ULONG);
37
38 static TX_THREAD tx_test_thread_printer_read;
39 static TX_THREAD tx_test_thread_printer_write;
40 static TX_SEMAPHORE tx_test_semaphore_printer_trigger;
41 static VOID tx_test_printer_read_entry(ULONG);
42 static VOID tx_test_printer_write_entry(ULONG);
43
44 static VOID ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION *action, VOID *params);
45 static VOID ux_test_hcd_entry_disconnect(UX_TEST_ACTION *action, VOID *params);
46 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params);
47
48 /* Define global data structures. */
49 static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
50
51 static UX_DEVICE *device = UX_NULL;
52 static UX_HOST_CLASS_PRINTER *host_printer = UX_NULL;
53 static UCHAR host_buffer[UX_DEMO_BUFFER_SIZE * 8];
54
55 static ULONG enum_counter;
56
57 static ULONG error_counter;
58 static ULONG error_callback_counter;
59
60 static ULONG set_cfg_counter;
61
62 static ULONG rsc_mem_alloc_cnt_on_set_cfg;
63 static ULONG rsc_mem_free_on_set_cfg;
64 static ULONG rsc_sem_on_set_cfg;
65 static ULONG rsc_sem_get_on_set_cfg;
66 static ULONG rsc_mutex_on_set_cfg;
67
68 static ULONG rsc_enum_sem_usage;
69 static ULONG rsc_enum_sem_get_count;
70 static ULONG rsc_enum_mutex_usage;
71 static ULONG rsc_enum_mem_usage;
72 static ULONG rsc_enum_mem_alloc_count;
73
74 static ULONG rsc_test_sem_usage;
75 static ULONG rsc_test_sem_get_count;
76 static ULONG rsc_test_mutex_usage;
77 static ULONG rsc_test_mem_alloc_count;
78
79 static UX_DEVICE_CLASS_PRINTER *device_printer = UX_NULL;
80 static UX_DEVICE_CLASS_PRINTER_PARAMS device_printer_parameter;
81 static UCHAR device_buffer[UX_DEMO_BUFFER_SIZE * 8];
82 static ULONG device_buffer_length = 0;
83
84 /* Device printer device ID. */
85 static UCHAR printer_device_id[] =
86 {
87 "MFG:Generic;" // manufacturer (case sensitive)
88 "MDL:Generic_/_Text_Only;" // model (case sensitive)
89 "CMD:1284.4;" // PDL command set
90 "CLS:PRINTER;" // class
91 "DES:Generic text only printer;" // description
92 };
93
94 /* Define device framework. */
95
96 #define _W0(w) ( (w) & 0xFF)
97 #define _W1(w) (((w) >> 8) & 0xFF)
98
99 #define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
100 0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
101 0x00, 0xc0, 0x32,
102
103 #define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
104 0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
105
106 #define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
107 0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
108
109 #define _CFG_TOTAL_LEN (9+9+7+7)
110
111 #define STRING_FRAMEWORK_LENGTH 47
112 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
113
114 static unsigned char device_framework_full_speed[] = {
115
116 /* Device descriptor 18 bytes
117 0xEF bDeviceClass: Composite class code
118 0x02 bDeviceSubclass: class sub code
119 0x00 bDeviceProtocol: Device protocol
120 idVendor & idProduct - http://www.linux-usb.org/usb.ids
121 */
122 0x12, 0x01, 0x10, 0x01,
123 0x00, 0x00, 0x00,
124 0x08,
125 0x84, 0x84, 0x00, 0x00,
126 0x00, 0x01,
127 0x01, 0x02, 0x03,
128 0x01,
129
130 _CONFIGURATION_DESCRIPTOR(_CFG_TOTAL_LEN, 1, 1)
131 _INTERFACE_DESCRIPTOR(0, 0, 2, 0x07, 0x01, 0x02)
132 _ENDPOINT_DESCRIPTOR(0x01, 0x02, 64, 0x00)
133 _ENDPOINT_DESCRIPTOR(0x82, 0x02, 64, 0x00)
134 };
135
136 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
137 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_full_speed)
138 #define device_framework_high_speed device_framework_full_speed
139
140 static unsigned char string_framework[] = {
141
142 /* Manufacturer string descriptor : Index 1 - "AzureRTOS" */
143 0x09, 0x04, 0x01, 9,
144 'A','z','u','r','e','R','T','O','S',
145
146 /* Product string descriptor : Index 2 - "Printer device" */
147 0x09, 0x04, 0x02, 14,
148 'P','r','i','n','t','e','r',' ','d','e','v','i','c','e',
149
150 /* Serial Number string descriptor : Index 3 - "0001" */
151 0x09, 0x04, 0x03, 0x04,
152 0x30, 0x30, 0x30, 0x31
153 };
154
155
156 /* Multiple languages are supported on the device, to add
157 a language besides english, the unicode language code must
158 be appended to the language_id_framework array and the length
159 adjusted accordingly. */
160 static unsigned char language_id_framework[] = {
161
162 /* English. */
163 0x09, 0x04
164 };
165
166 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
167
168 /* Test interactions */
169
170 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
171 /* function, request to match,
172 port action, port status,
173 request action, request EP, request data, request actual length, request status,
174 status, additional callback,
175 no_return */
176 { UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
177 UX_FALSE, UX_TEST_PORT_STATUS_DISC,
178 UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
179 UX_SUCCESS, ux_test_hcd_entry_set_cfg,
180 UX_TRUE}, /* Invoke callback & continue */
181 { 0 }
182 };
183
184 /* Define the ISR dispatch. */
185
186 extern VOID (*test_isr_dispatch)(void);
187
188
189 /* Prototype for test control return. */
190
191 void test_control_return(UINT status);
192
193
194 /* Define the ISR dispatch routine. */
195
test_isr(void)196 static void test_isr(void)
197 {
198
199 /* For further expansion of interrupt-level testing. */
200 }
201
test_slave_change_function(ULONG change)202 static UINT test_slave_change_function(ULONG change)
203 {
204 return 0;
205 }
206
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)207 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
208 {
209
210 UX_HOST_CLASS_PRINTER *printer_inst = (UX_HOST_CLASS_PRINTER *) inst;
211
212 switch(event)
213 {
214
215 case UX_DEVICE_INSERTION:
216 host_printer = printer_inst;
217 break;
218
219 case UX_DEVICE_REMOVAL:
220 if (host_printer == printer_inst)
221 host_printer = UX_NULL;
222 break;
223
224 case UX_DEVICE_CONNECTION:
225 device = (UX_DEVICE *)inst;
226 break;
227
228 case UX_DEVICE_DISCONNECTION:
229 if ((VOID *)device == inst)
230 device = UX_NULL;
231 break;
232
233 #if defined(UX_HOST_STANDALONE)
234 case UX_STANDALONE_WAIT_BACKGROUND_TASK:
235 tx_thread_relinquish();
236 break;
237 #endif
238
239 default:
240 break;
241 }
242 return 0;
243 }
244
test_printer_instance_activate(VOID * dummy_instance)245 static VOID test_printer_instance_activate(VOID *dummy_instance)
246 {
247 if (device_printer == UX_NULL)
248 device_printer = (UX_DEVICE_CLASS_PRINTER *)dummy_instance;
249 }
test_printer_instance_deactivate(VOID * dummy_instance)250 static VOID test_printer_instance_deactivate(VOID *dummy_instance)
251 {
252 if ((VOID*)device_printer == dummy_instance)
253 device_printer = UX_NULL;
254 }
255
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)256 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
257 {
258 error_callback_counter ++;
259 }
260
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * params)261 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params)
262 {
263
264 set_cfg_counter ++;
265
266 rsc_mem_free_on_set_cfg = _ux_system->ux_system_regular_memory_pool_free;
267
268 rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
269
270 rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
271 rsc_enum_sem_get_count = ux_test_utility_sim_sem_get_count();
272 rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
273 }
274
275 /* Define what the initial system looks like. */
276
277 #ifdef CTEST
test_application_define(void * first_unused_memory)278 void test_application_define(void *first_unused_memory)
279 #else
280 void usbx_host_class_printer_basic_test_application_define(void *first_unused_memory)
281 #endif
282 {
283
284 UINT status;
285 CHAR * stack_pointer;
286 CHAR * memory_pointer;
287
288
289 printf("Running Host Class Printer Basic Functionality Test................. ");
290 #if defined(UX_DEVICE_STANDALONE)
291 printf("Skip\n");
292 test_control_return(0);
293 #endif
294
295 /* Reset testing counts. */
296 ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
297 ux_test_utility_sim_mem_alloc_count_reset();
298 ux_test_utility_sim_mutex_create_count_reset();
299 ux_test_utility_sim_sem_create_count_reset();
300 ux_test_utility_sim_sem_get_count_reset();
301 /* Reset error generations */
302 ux_test_utility_sim_sem_error_generation_stop();
303 ux_test_utility_sim_mutex_error_generation_stop();
304 ux_test_utility_sim_sem_get_error_generation_stop();
305
306 /* Initialize the free memory pointer */
307 stack_pointer = (CHAR *) usbx_memory;
308 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 4);
309
310 /* Initialize USBX Memory */
311 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
312
313 /* Check for error. */
314 if (status != UX_SUCCESS)
315 {
316
317 printf(" ERROR #1\n");
318 test_control_return(1);
319 }
320
321 /* Register the error callback. */
322 _ux_utility_error_callback_register(test_ux_error_callback);
323
324 /* The code below is required for installing the host portion of USBX */
325 status = ux_host_stack_initialize(test_host_change_function);
326 if (status != UX_SUCCESS)
327 {
328
329 printf(" ERROR #2\n");
330 test_control_return(1);
331 }
332
333 /* Register CDC-ACM class. */
334 status = ux_host_stack_class_register(_ux_system_host_class_printer_name, ux_host_class_printer_entry);
335 if (status != UX_SUCCESS)
336 {
337
338 printf(" ERROR #3\n");
339 test_control_return(1);
340 }
341
342 /* The code below is required for installing the device portion of USBX. No call back for
343 device status change in this example. */
344 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
345 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
346 string_framework, STRING_FRAMEWORK_LENGTH,
347 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,
348 test_slave_change_function);
349 if(status!=UX_SUCCESS)
350 {
351
352 printf(" ERROR #5\n");
353 test_control_return(1);
354 }
355
356 /* Set the parameters for callback when insertion/extraction of a printer device. */
357 _ux_utility_memory_set(&device_printer_parameter, 0, sizeof(device_printer_parameter));
358 device_printer_parameter.device_id = printer_device_id;
359 device_printer_parameter.device_id_length = sizeof(printer_device_id);
360 device_printer_parameter.instance_activate = test_printer_instance_activate;
361 device_printer_parameter.instance_deactivate = test_printer_instance_deactivate;
362 /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
363 status = ux_device_stack_class_register(_ux_device_class_printer_name,
364 _ux_device_class_printer_entry,
365 1, 0, &device_printer_parameter);
366 /* Initialize the simulated device controller. */
367 status = _ux_test_dcd_sim_slave_initialize();
368
369 /* Check for error. */
370 if (status != TX_SUCCESS)
371 {
372
373 printf(" ERROR #8\n");
374 test_control_return(1);
375 }
376
377 /* Register all the USB host controllers available in this system */
378 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
379 if (status != UX_SUCCESS)
380 {
381
382 printf(" ERROR #4\n");
383 test_control_return(1);
384 }
385
386 /* Create the main host simulation thread. */
387 status = tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_thread_host_simulation_entry, 0,
388 stack_pointer, UX_DEMO_STACK_SIZE,
389 20, 20, 1, TX_AUTO_START);
390
391 /* Check for error. */
392 if (status != TX_SUCCESS)
393 {
394
395 printf(" ERROR #9\n");
396 test_control_return(1);
397 }
398
399 /* Create the main slave simulation thread. */
400 stack_pointer += UX_DEMO_STACK_SIZE;
401 status = tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
402 stack_pointer, UX_DEMO_STACK_SIZE,
403 20, 20, 1, TX_AUTO_START);
404
405 /* Check for error. */
406 if (status != TX_SUCCESS)
407 {
408
409 printf(" ERROR #10\n");
410 test_control_return(1);
411 }
412
413 /* Create the device printer read thread. */
414 stack_pointer += UX_DEMO_STACK_SIZE;
415 status = tx_thread_create(&tx_test_thread_printer_read, "tx test printer read",
416 tx_test_printer_read_entry, UX_TRUE,
417 stack_pointer, UX_DEMO_STACK_SIZE,
418 20, 20, 1, TX_AUTO_START);
419
420 /* Check for error. */
421 if (status != TX_SUCCESS)
422 {
423
424 printf(" ERROR #%d\n", __LINE__);
425 test_control_return(1);
426 }
427
428 /* Create the device printer write thread. */
429 stack_pointer += UX_DEMO_STACK_SIZE;
430 status = tx_thread_create(&tx_test_thread_printer_write, "tx test printer write",
431 tx_test_printer_write_entry, UX_FALSE,
432 stack_pointer, UX_DEMO_STACK_SIZE,
433 20, 20, 1, TX_AUTO_START);
434
435 /* Check for error. */
436 if (status != TX_SUCCESS)
437 {
438
439 printf(" ERROR #%d\n", __LINE__);
440 test_control_return(1);
441 }
442
443 /* Create the device printer write trigger. */
444 status = tx_semaphore_create(&tx_test_semaphore_printer_trigger,
445 "tx test printer trigger",
446 0);
447
448 /* Check for error. */
449 if (status != TX_SUCCESS)
450 {
451
452 printf(" ERROR #%d\n", __LINE__);
453 test_control_return(1);
454 }
455 }
456
_test_check_host_connection_error(VOID)457 static UINT _test_check_host_connection_error(VOID)
458 {
459 if (device_printer && host_printer)
460 return(UX_SUCCESS);
461 if (error_callback_counter >= 3)
462 return(UX_SUCCESS);
463 return(UX_ERROR);
464 }
465
_test_check_host_connection_success(VOID)466 static UINT _test_check_host_connection_success(VOID)
467 {
468 if (device_printer && host_printer)
469 return(UX_SUCCESS);
470 return(UX_ERROR);
471 }
472
_test_check_host_disconnection_success(VOID)473 static UINT _test_check_host_disconnection_success(VOID)
474 {
475 if (device_printer == UX_NULL && host_printer == UX_NULL)
476 return(UX_SUCCESS);
477 return(UX_ERROR);
478 }
479
_printer_enumeration_test(VOID)480 static VOID _printer_enumeration_test(VOID)
481 {
482 UINT status;
483 ULONG mem_free;
484 ULONG test_n;
485
486 stepinfo(">>>>>>>>>>>> Enumeration information collection\n");
487 {
488
489 /* Test disconnect. */
490 ux_test_dcd_sim_slave_disconnect();
491 ux_test_hcd_sim_host_disconnect();
492
493 /* Check connection. */
494 status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
495 UX_TEST_ASSERT(status == UX_SUCCESS);
496
497 /* Reset testing counts. */
498 ux_test_utility_sim_mem_alloc_count_reset();
499 ux_test_utility_sim_mutex_create_count_reset();
500 ux_test_utility_sim_sem_create_count_reset();
501 ux_test_utility_sim_sem_get_count_reset();
502 ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
503
504 /* Save free memory usage. */
505 mem_free = _ux_system->ux_system_regular_memory_pool_free;
506 ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
507 ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
508
509 /* Check connection. */
510 status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
511 UX_TEST_ASSERT(status == UX_SUCCESS);
512
513 /* Log create counts for further tests. */
514 rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
515 rsc_enum_sem_usage = rsc_sem_on_set_cfg;
516 rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
517 /* Log create counts when instances active for further tests. */
518 rsc_test_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
519 rsc_test_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
520 rsc_test_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
521
522 /* Lock log base for tests. */
523 ux_test_utility_sim_mem_alloc_log_lock();
524
525 stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
526 stepinfo("test mem : %ld\n", rsc_test_mem_alloc_count);
527 stepinfo("mem free: %ld, %ld\n", _ux_system->ux_system_regular_memory_pool_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
528 }
529
530 stepinfo(">>>>>>>>>>>> Enumeration test\n");
531 mem_free = (~0);
532 for (test_n = 0; test_n < 3; test_n++)
533 {
534 stepinfo("%4ld / 2\n", test_n);
535
536 /* Disconnect. */
537 ux_test_dcd_sim_slave_disconnect();
538 ux_test_hcd_sim_host_disconnect();
539
540 /* Check */
541 status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
542 if (status != UX_SUCCESS)
543 {
544
545 printf("ERROR #%d.%ld: Disconnect fail\n", __LINE__, test_n);
546 test_control_return(1);
547 }
548
549 /* Update memory free level (disconnect) */
550 if (mem_free == (~0))
551 mem_free = _ux_system->ux_system_regular_memory_pool_free;
552 else if (mem_free != _ux_system->ux_system_regular_memory_pool_free)
553 {
554
555 printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system->ux_system_regular_memory_pool_free);
556 test_control_return(1);
557 }
558
559 /* Connect. */
560 error_callback_counter = 0;
561 ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
562 ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
563
564 /* Wait and break on error. */
565 error_callback_counter = 0;
566 status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
567
568 /* Check */
569 if (status != UX_SUCCESS)
570 {
571
572 printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
573 test_control_return(1);
574 }
575 }
576 stepinfo("\n");
577
578 if (rsc_test_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
579 mem_free = (~0);
580 for (test_n = 0; test_n < rsc_test_mem_alloc_count; test_n ++)
581 {
582
583 stepinfo("%4ld / %4ld\n", test_n, rsc_test_mem_alloc_count - 1);
584
585 /* Disconnect. */
586 ux_test_dcd_sim_slave_disconnect();
587 ux_test_hcd_sim_host_disconnect();
588
589 /* Check */
590 status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
591 if (status != UX_SUCCESS)
592 {
593
594 stepinfo("ERROR #%d.%ld: Disconnect fail\n", __LINE__, test_n);
595 test_control_return(1);
596 }
597
598 /* Update memory free level (disconnect) */
599 if (mem_free == (~0))
600 mem_free = _ux_system->ux_system_regular_memory_pool_free;
601 else if (mem_free != _ux_system->ux_system_regular_memory_pool_free)
602 {
603
604 stepinfo("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system->ux_system_regular_memory_pool_free);
605 test_control_return(1);
606 }
607
608 /* Set memory error generation */
609 ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
610
611 /* Connect. */
612 error_callback_counter = 0;
613 ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
614 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
615
616 /* Wait and break on errors. */
617 status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
618
619 /* Check error */
620 if (status != UX_SUCCESS)
621 {
622
623 /* Check error trap. */
624 if (error_callback_counter == 0)
625 {
626 stepinfo("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
627 test_control_return(1);
628 }
629 }
630 stepinfo("mem free: %ld\n", _ux_system->ux_system_regular_memory_pool_free);
631 }
632 ux_test_utility_sim_mem_alloc_error_generation_stop();
633 if (rsc_test_mem_alloc_count) stepinfo("\n");
634
635 /* If device disconnected, re-connect. */
636 if (_test_check_host_connection_success() != UX_SUCCESS)
637 {
638 ux_test_dcd_sim_slave_disconnect();
639 ux_test_hcd_sim_host_disconnect();
640 ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
641 ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
642
643 /* Check */
644 status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
645 if (status != UX_SUCCESS)
646 {
647
648 printf("ERROR #%d: Enumeration fail\n", __LINE__);
649 test_control_return(1);
650 }
651 }
652 }
_printer_requests_test(VOID)653 static VOID _printer_requests_test(VOID)
654 {
655 UINT status;
656 ULONG printer_port_status;
657
658 stepinfo(">>>>>>>>>>>>>>>> Test GET_DEVICE_ID\n");
659 status = ux_host_class_printer_device_id_get(host_printer, host_buffer, sizeof(host_buffer));
660 UX_TEST_ASSERT(status == UX_SUCCESS);
661
662 stepinfo(">>>>>>>>>>>>>>>> Test GET_PORT_STATUS\n");
663 device_printer->port_status = 0x73;
664 status = ux_host_class_printer_status_get(host_printer, &printer_port_status);
665 UX_TEST_ASSERT(status == UX_SUCCESS);
666 UX_TEST_ASSERT(printer_port_status == 0x73);
667
668 stepinfo(">>>>>>>>>>>>>>>> Test SOFT_RESET\n");
669 device_printer->soft_reset = 0;
670 status = ux_host_class_printer_soft_reset(host_printer);
671 UX_TEST_ASSERT(status == UX_SUCCESS);
672 UX_TEST_ASSERT(device_printer->soft_reset != 0);
673 }
674
tx_test_printer_read_entry(ULONG arg)675 void tx_test_printer_read_entry(ULONG arg)
676 {
677 UINT status;
678 UX_SLAVE_TRANSFER *transfer;
679 ULONG save_length;
680 while(1)
681 {
682 if (device_printer == UX_NULL ||
683 device_printer->bulk_out_endpoint == UX_NULL)
684 {
685 tx_thread_sleep(10);
686 continue;
687 }
688 transfer = &device_printer->bulk_out_endpoint->ux_slave_endpoint_transfer_request;
689 transfer->ux_slave_transfer_request_timeout=UX_WAIT_FOREVER;
690 status = ux_device_stack_transfer_request(transfer,
691 UX_SLAVE_REQUEST_DATA_MAX_LENGTH,
692 UX_SLAVE_REQUEST_DATA_MAX_LENGTH);
693 if (status != UX_SUCCESS)
694 {
695 tx_thread_sleep(1);
696 continue;
697 }
698 save_length = transfer->ux_slave_transfer_request_actual_length;
699 if (save_length)
700 {
701 if (device_buffer_length >= sizeof(device_buffer))
702 {
703 /* Discard data. */
704 continue;
705 }
706 /* Save data. */
707 if (device_buffer_length + save_length > sizeof(device_buffer))
708 save_length = sizeof(device_buffer) - device_buffer_length;
709 ux_utility_memory_copy(device_buffer + device_buffer_length,
710 transfer->ux_slave_transfer_request_data_pointer,
711 save_length);
712 device_buffer_length += save_length;
713 }
714 }
715 }
716
tx_test_printer_write_entry(ULONG arg)717 void tx_test_printer_write_entry(ULONG arg)
718 {
719 UINT status;
720 UX_SLAVE_TRANSFER *transfer;
721 ULONG send_length;
722 ULONG send_total;
723 while(1)
724 {
725 /* Wait a trigger. */
726 status = tx_semaphore_get(&tx_test_semaphore_printer_trigger, TX_WAIT_FOREVER);
727 if (status != TX_SUCCESS)
728 {
729 tx_thread_sleep(10);
730 continue;
731 }
732 /* Send device_buffer_length. */
733 send_total = 0;
734 while (device_printer != UX_NULL &&
735 device_printer->bulk_in_endpoint != UX_NULL)
736 {
737 /* All sent. */
738 if (send_total >= device_buffer_length)
739 break;
740 transfer = &device_printer->bulk_in_endpoint->ux_slave_endpoint_transfer_request;
741 send_length = device_buffer_length - send_total;
742 if (send_length >= UX_SLAVE_REQUEST_DATA_MAX_LENGTH)
743 send_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
744 ux_utility_memory_copy(transfer->ux_slave_transfer_request_data_pointer,
745 device_buffer + send_total, send_length);
746 status = ux_device_stack_transfer_request(transfer, send_length, send_length);
747 if (status != UX_SUCCESS)
748 break;
749 send_total += send_length;
750 }
751 }
752 }
753
_printer_read_write_test(VOID)754 static VOID _printer_read_write_test(VOID)
755 {
756 struct _TEST_DEF {
757 ULONG fill;
758 ULONG length;
759 ULONG zlp;
760 } tests[] = {
761 {0x5A, 1, 0},
762 {0x7E, 512, 1},
763 {0xC2, 513, 0},
764 {0x4C, UX_SLAVE_REQUEST_DATA_MAX_LENGTH, 0},
765 {0xA5, UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1, 0},
766 {0x3C, sizeof(device_buffer), 0},
767 {0xC4, sizeof(device_buffer) - 1, 0},
768 };
769 #define _TEST_N (sizeof(tests)/sizeof(struct _TEST_DEF))
770 INT i;
771 ULONG actual_length;
772 UINT status;
773 for(i = 0; i < _TEST_N; i ++)
774 {
775 stepinfo(">>>>>>>>>>>>>>>> Test Write %ld\n", tests[i].length);
776 device_buffer_length = 0;
777 ux_utility_memory_set(device_buffer, ~tests[i].fill, tests[i].length);
778 ux_utility_memory_set(host_buffer, tests[i].fill, tests[i].length);
779 status = ux_host_class_printer_write(host_printer, host_buffer, tests[i].length, &actual_length);
780 UX_TEST_ASSERT(status == UX_SUCCESS);
781 UX_TEST_ASSERT(tests[i].length == actual_length);
782 if (tests[i].zlp)
783 {
784 status = ux_host_class_printer_write(host_printer, host_buffer, 0, &actual_length);
785 UX_TEST_ASSERT(status == UX_SUCCESS);
786 UX_TEST_ASSERT(0 == actual_length);
787 }
788 UX_TEST_ASSERT(device_buffer_length == tests[i].length);
789 status = ux_utility_memory_compare(device_buffer, host_buffer, tests[i].length);
790 UX_TEST_ASSERT(status == UX_SUCCESS);
791
792 stepinfo(">>>>>>>>>>>>>>>> Test Read %ld\n", tests[i].length);
793 status = tx_semaphore_put(&tx_test_semaphore_printer_trigger);
794 UX_TEST_ASSERT(status == TX_SUCCESS);
795 ux_utility_memory_set(host_buffer, ~tests[i].fill, tests[i].length);
796 status = ux_host_class_printer_read(host_printer, host_buffer, tests[i].length, &actual_length);
797 UX_TEST_ASSERT(status == UX_SUCCESS);
798 UX_TEST_ASSERT(tests[i].length == actual_length);
799 UX_TEST_ASSERT(host_buffer[0] == tests[i].fill);
800 UX_TEST_ASSERT(host_buffer[tests[i].length - 1] == tests[i].fill);
801
802 }
803 }
804
tx_test_thread_host_simulation_entry(ULONG arg)805 void tx_test_thread_host_simulation_entry(ULONG arg)
806 {
807
808 UINT status;
809 ULONG test_n;
810 ULONG mem_free;
811 ULONG loop;
812 ULONG parameter_u32[64/4];
813 USHORT *parameter_u16 = (USHORT*)parameter_u32;
814 UCHAR *parameter_u8 = (UCHAR*)parameter_u32;
815
816
817 stepinfo("\n");
818 stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
819 ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
820 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
821 status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
822 UX_TEST_ASSERT(status == UX_SUCCESS);
823
824 _printer_enumeration_test();
825 _printer_requests_test();
826 _printer_read_write_test();
827
828 /* Test disconnect. */
829 stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
830 ux_test_dcd_sim_slave_disconnect();
831 ux_test_hcd_sim_host_disconnect();
832 if (host_printer != UX_NULL)
833 {
834
835 printf("ERROR #13: instance not removed when disconnect");
836 test_control_return(1);
837 }
838
839 /* Finally disconnect the device. */
840 ux_device_stack_disconnect();
841
842 /* And deinitialize the class. */
843 status = ux_device_stack_class_unregister(_ux_device_class_printer_name, _ux_device_class_printer_entry);
844
845 /* Deinitialize the device side of usbx. */
846 _ux_device_stack_uninitialize();
847
848 /* And finally the usbx system resources. */
849 _ux_system_uninitialize();
850
851 /* Successful test. */
852 printf("SUCCESS!\n");
853 test_control_return(0);
854
855 }
856
tx_test_thread_slave_simulation_entry(ULONG arg)857 void tx_test_thread_slave_simulation_entry(ULONG arg)
858 {
859
860 while(1)
861 {
862 #if defined(UX_DEVICE_STANDALONE)
863 ux_system_tasks_run();
864 tx_thread_relinquish();
865 #else
866 /* Sleep so ThreadX on Win32 will delete this thread. */
867 tx_thread_sleep(10);
868 #endif
869 }
870 }
871