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