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