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