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