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