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_cdc_acm.h"
12 #include "ux_device_stack.h"
13 #include "ux_host_class_cdc_acm.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 TX_THREAD   ux_test_thread_host_simulation;
33 static TX_THREAD   ux_test_thread_slave_simulation;
34 static void        ux_test_thread_host_simulation_entry(ULONG);
35 static void        ux_test_thread_slave_simulation_entry(ULONG);
36 
37 static VOID        test_cdc_instance_activate(VOID  *cdc_instance);
38 static VOID        test_cdc_instance_deactivate(VOID *cdc_instance);
39 static VOID        test_cdc_instance_parameter_change(VOID *cdc_instance);
40 
41 static VOID        ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params);
42 
43 /* Define global data structures.  */
44 static UCHAR                               usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
45 static UX_HOST_CLASS                       *class_driver;
46 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_control;
47 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_data;
48 
49 static UX_SLAVE_CLASS_CDC_ACM              *cdc_acm_slave;
50 static UCHAR                               cdc_acm_slave_change;
51 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER    parameter;
52 
53 static ULONG                               set_cfg_counter;
54 
55 static ULONG                               rsc_mem_alloc_cnt_on_set_cfg;
56 static ULONG                               rsc_sem_on_set_cfg;
57 static ULONG                               rsc_sem_get_on_set_cfg;
58 static ULONG                               rsc_mutex_on_set_cfg;
59 
60 static ULONG                               rsc_enum_sem_usage;
61 static ULONG                               rsc_enum_sem_get_count;
62 static ULONG                               rsc_enum_mutex_usage;
63 static ULONG                               rsc_enum_mem_alloc_count;
64 
65 static ULONG                               rsc_cdc_sem_usage;
66 static ULONG                               rsc_cdc_sem_get_count;
67 static ULONG                               rsc_cdc_mutex_usage;
68 static ULONG                               rsc_cdc_mem_alloc_count;
69 
70 static ULONG                               interaction_count;
71 
72 static UCHAR                               error_callback_ignore = UX_TRUE;
73 static ULONG                               error_callback_counter;
74 
75 /* Define device framework.  */
76 
77 #define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      93
78 #define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      103
79 #define             STRING_FRAMEWORK_LENGTH                 47
80 #define             LANGUAGE_ID_FRAMEWORK_LENGTH            2
81 
82 static unsigned char device_framework_full_speed[] = {
83 
84     /* Device descriptor     18 bytes
85        0x02 bDeviceClass:    CDC class code
86        0x00 bDeviceSubclass: CDC class sub code
87        0x00 bDeviceProtocol: CDC Device protocol
88 
89        idVendor & idProduct - http://www.linux-usb.org/usb.ids
90     */
91     0x12, 0x01, 0x10, 0x01,
92     0xEF, 0x02, 0x01,
93     0x08,
94     0x84, 0x84, 0x00, 0x00,
95     0x00, 0x01,
96     0x01, 0x02, 03,
97     0x01,
98 
99     /* Configuration 1 descriptor 9 bytes */
100     0x09, 0x02, 0x4b, 0x00,
101     0x02, 0x01, 0x00,
102     0x40, 0x00,
103 
104     /* Interface association descriptor. 8 bytes.  */
105     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
106 
107     /* Communication Class Interface Descriptor Requirement. 9 bytes.   */
108     0x09, 0x04, 0x00,
109     0x00,
110     0x01,
111     0x02, 0x02, 0x01,
112     0x00,
113 
114     /* Header Functional Descriptor 5 bytes */
115     0x05, 0x24, 0x00,
116     0x10, 0x01,
117 
118     /* ACM Functional Descriptor 4 bytes */
119     0x04, 0x24, 0x02,
120     0x0f,
121 
122     /* Union Functional Descriptor 5 bytes */
123     0x05, 0x24, 0x06,
124     0x00,                          /* Master interface */
125     0x01,                          /* Slave interface  */
126 
127     /* Call Management Functional Descriptor 5 bytes */
128     0x05, 0x24, 0x01,
129     0x03,
130     0x01,                          /* Data interface   */
131 
132     /* Endpoint 0x83 descriptor 7 bytes */
133     0x07, 0x05, 0x83,
134     0x03,
135     0x08, 0x00,
136     0xFF,
137 
138     /* Data Class Interface Descriptor Requirement 9 bytes */
139     0x09, 0x04, 0x01,
140     0x00,
141     0x02,
142     0x0A, 0x00, 0x00,
143     0x00,
144 
145     /* Endpoint 0x02 descriptor 7 bytes */
146     0x07, 0x05, 0x02, /* @ 93 - 14 + 2 = 81 */
147     0x02,
148     0x40, 0x00,
149     0x00,
150 
151     /* Endpoint 0x81 descriptor 7 bytes */
152     0x07, 0x05, 0x81, /* @ 93 - 7 + 2 = 88 */
153     0x02,
154     0x40, 0x00,
155     0x00,
156 
157 };
158 
159 #define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
160 #define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
161 
162 static unsigned char device_framework_high_speed[] = {
163 
164     /* Device descriptor
165        0x02 bDeviceClass:    CDC class code
166        0x00 bDeviceSubclass: CDC class sub code
167        0x00 bDeviceProtocol: CDC Device protocol
168 
169        idVendor & idProduct - http://www.linux-usb.org/usb.ids
170     */
171     0x12, 0x01, 0x00, 0x02,
172     0xEF, 0x02, 0x01,
173     0x40,
174     0x84, 0x84, 0x00, 0x00,
175     0x00, 0x01,
176     0x01, 0x02, 03,
177     0x01,
178 
179     /* Device qualifier descriptor */
180     0x0a, 0x06, 0x00, 0x02,
181     0x02, 0x00, 0x00,
182     0x40,
183     0x01,
184     0x00,
185 
186     /* Configuration 1 descriptor */
187     0x09, 0x02, 0x4b, 0x00,
188     0x02, 0x01, 0x00,
189     0x40, 0x00,
190 
191     /* Interface association descriptor. */
192     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
193 
194     /* Communication Class Interface Descriptor Requirement */
195     0x09, 0x04, 0x00,
196     0x00,
197     0x01,
198     0x02, 0x02, 0x01,
199     0x00,
200 
201     /* Header Functional Descriptor */
202     0x05, 0x24, 0x00,
203     0x10, 0x01,
204 
205     /* ACM Functional Descriptor */
206     0x04, 0x24, 0x02,
207     0x0f,
208 
209     /* Union Functional Descriptor */
210     0x05, 0x24, 0x06,
211     0x00,
212     0x01,
213 
214     /* Call Management Functional Descriptor */
215     0x05, 0x24, 0x01,
216     0x00,
217     0x01,
218 
219     /* Endpoint 0x83 descriptor */
220     0x07, 0x05, 0x83,
221     0x03,
222     0x08, 0x00,
223     0xFF,
224 
225     /* Data Class Interface Descriptor Requirement */
226     0x09, 0x04, 0x01,
227     0x00,
228     0x02,
229     0x0A, 0x00, 0x00,
230     0x00,
231 
232     /* Endpoint 0x02 descriptor */
233     0x07, 0x05, 0x02, /* @ 103 - 14 + 2 = 91 */
234     0x02,
235     0x40, 0x00,
236     0x00,
237 
238     /* Endpoint 0x81 descriptor */
239     0x07, 0x05, 0x81, /* @ 103 - 7 + 2 = 98 */
240     0x02,
241     0x40, 0x00,
242     0x00,
243 
244 };
245 
246 #define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
247 #define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
248 
249 static unsigned char string_framework[] = {
250 
251     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
252         0x09, 0x04, 0x01, 0x0c,
253         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
254         0x6f, 0x67, 0x69, 0x63,
255 
256     /* Product string descriptor : Index 2 - "EL Composite device" */
257         0x09, 0x04, 0x02, 0x13,
258         0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
259         0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
260         0x69, 0x63, 0x65,
261 
262     /* Serial Number string descriptor : Index 3 - "0001" */
263         0x09, 0x04, 0x03, 0x04,
264         0x30, 0x30, 0x30, 0x31
265     };
266 
267 
268     /* Multiple languages are supported on the device, to add
269        a language besides english, the unicode language code must
270        be appended to the language_id_framework array and the length
271        adjusted accordingly. */
272 static unsigned char language_id_framework[] = {
273 
274     /* English. */
275         0x09, 0x04
276     };
277 
278 /* Setup requests */
279 
280 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
281 
282 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
283 /* function, request to match,
284    port action, port status,
285    request action, request EP, request data, request actual length, request status,
286    status, additional callback,
287    no_return */
288 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
289         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
290         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
291         UX_SUCCESS, ux_test_hcd_entry_set_cfg,
292         UX_TRUE}, /* Invoke callback & continue */
293 {   0   }
294 };
295 
296 /* Define the ISR dispatch.  */
297 
298 extern VOID    (*test_isr_dispatch)(void);
299 
300 
301 /* Prototype for test control return.  */
302 
303 void  test_control_return(UINT status);
304 
305 
306 /* Define the ISR dispatch routine.  */
307 
test_isr(void)308 static void    test_isr(void)
309 {
310 
311     /* For further expansion of interrupt-level testing.  */
312 }
313 
error_callback(UINT system_level,UINT system_context,UINT error_code)314 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
315 {
316 
317     error_callback_counter ++;
318 
319     if (!error_callback_ignore)
320     {
321         {
322             /* Failed test.  */
323             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
324             test_control_return(1);
325         }
326     }
327 }
328 
sleep_break_on_error(VOID)329 static UINT  sleep_break_on_error(VOID)
330 {
331 
332     if (error_callback_counter >= 3)
333         return error_callback_counter;
334 
335     return UX_SUCCESS;
336 }
337 
demo_class_cdc_acm_get(void)338 static UINT  demo_class_cdc_acm_get(void)
339 {
340 
341 UINT                                status;
342 UX_HOST_CLASS                       *class;
343 UX_HOST_CLASS_CDC_ACM               *cdc_acm_host;
344 
345 
346     /* Find the main cdc_acm container */
347     status =  ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
348     if (status != UX_SUCCESS)
349         return(status);
350 
351     /* We get the first instance of the cdc_acm device */
352     do
353     {
354 
355         status =  ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
356         tx_thread_sleep(10);
357     } while (status != UX_SUCCESS);
358 
359     /* We still need to wait for the cdc_acm status to be live */
360     while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
361         tx_thread_sleep(10);
362 
363     /* Isolate both the control and data interfaces.  */
364     if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
365     {
366         /* This is the data interface.  */
367         cdc_acm_host_data = cdc_acm_host;
368 
369         /* In that case, the second one should be the control interface.  */
370         status =  ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
371 
372         /* Check error.  */
373         if (status != UX_SUCCESS)
374             return(status);
375 
376         /* Check for the control interfaces.  */
377         if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
378         {
379 
380             /* This is the control interface.  */
381             cdc_acm_host_control = cdc_acm_host;
382 
383             return(UX_SUCCESS);
384 
385         }
386     }
387     else
388     {
389         /* Check for the control interfaces.  */
390         if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
391         {
392 
393             /* This is the control interface.  */
394             cdc_acm_host_control = cdc_acm_host;
395 
396             /* In that case, the second one should be the data interface.  */
397             status =  ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
398 
399             /* Check error.  */
400             if (status != UX_SUCCESS)
401                 return(status);
402 
403             /* Check for the data interface.  */
404             if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
405             {
406 
407                 /* This is the data interface.  */
408                 cdc_acm_host_data = cdc_acm_host;
409 
410                 return(UX_SUCCESS);
411 
412             }
413         }
414     }
415 
416     /* Return ERROR.  */
417     return(UX_ERROR);
418 }
419 
demo_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)420 static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
421 {
422 
423 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
424 
425     switch(event)
426     {
427 
428         case UX_DEVICE_INSERTION:
429 
430             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
431                 cdc_acm_host_control = cdc_acm;
432             else
433                 cdc_acm_host_data = cdc_acm;
434             break;
435 
436         case UX_DEVICE_REMOVAL:
437 
438             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
439                 cdc_acm_host_control = UX_NULL;
440             else
441                 cdc_acm_host_data = UX_NULL;
442             break;
443 
444         default:
445             break;
446     }
447     return 0;
448 }
449 
test_cdc_instance_activate(VOID * cdc_instance)450 static VOID    test_cdc_instance_activate(VOID *cdc_instance)
451 {
452 
453     /* Save the CDC instance.  */
454     cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
455 }
test_cdc_instance_deactivate(VOID * cdc_instance)456 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
457 {
458 
459     /* Reset the CDC instance.  */
460     cdc_acm_slave = UX_NULL;
461 }
462 
test_cdc_instance_parameter_change(VOID * cdc_instance)463 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
464 {
465 
466     /* Set CDC parameter change flag. */
467     cdc_acm_slave_change = UX_TRUE;
468 }
469 
test_swap_framework_bulk_ep_descriptors(VOID)470 static VOID test_swap_framework_bulk_ep_descriptors(VOID)
471 {
472 UCHAR tmp;
473 
474     tmp = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS];
475     device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS] = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS];
476     device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS] = tmp;
477 
478     tmp = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS];
479     device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS] = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS];
480     device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS] = tmp;
481 }
482 
test_slave_cdc_acm_transfer_disconnect(UX_SLAVE_CLASS_CDC_ACM * cdc_acm,ULONG ep_dir)483 static VOID test_slave_cdc_acm_transfer_disconnect(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ep_dir)
484 {
485 
486 UX_SLAVE_ENDPOINT           *endpoint;
487 UX_SLAVE_DEVICE             *device;
488 UX_SLAVE_INTERFACE          *interface;
489 UX_SLAVE_TRANSFER           *transfer_request;
490 
491     /* Get the pointer to the device.  */
492     device =  &_ux_system_slave -> ux_system_slave_device;
493 
494     /* This is the first time we are activated. We need the interface to the class.  */
495     interface =  cdc_acm -> ux_slave_class_cdc_acm_interface;
496 
497     /* Locate the endpoints.  */
498     endpoint =  interface -> ux_slave_interface_first_endpoint;
499 
500     /* Check the endpoint direction, if OUT we have the correct endpoint.  */
501     if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != ep_dir)
502     {
503 
504         /* So the next endpoint has to be the OUT endpoint.  */
505         endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
506     }
507 
508     /* All CDC reading  are on the endpoint OUT, from the host.  */
509     transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
510 
511     /* Continue transfer. */
512     transfer_request -> ux_slave_transfer_request_actual_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
513 
514     /* Change device state. */
515     device -> ux_slave_device_state = UX_DEVICE_ATTACHED;
516 
517     /* Inform hcd. */
518     _ux_utility_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore);
519 
520     /* Wait a while for transfer request handling. */
521     tx_thread_sleep(50);
522 
523     /* Change device state. */
524     device -> ux_slave_device_state = UX_DEVICE_CONFIGURED;
525 }
526 
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)527 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
528 {
529 
530     set_cfg_counter ++;
531 
532     rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
533 
534     rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
535     rsc_sem_get_on_set_cfg = ux_test_utility_sim_sem_get_count();
536     rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
537 }
538 
539 /* Define what the initial system looks like.  */
540 
541 #ifdef CTEST
test_application_define(void * first_unused_memory)542 void test_application_define(void *first_unused_memory)
543 #else
544 void    usbx_cdc_acm_basic_memory_test_application_define(void *first_unused_memory)
545 #endif
546 {
547 
548 UINT                    status;
549 CHAR *                  stack_pointer;
550 CHAR *                  memory_pointer;
551 
552     /* Inform user.  */
553     printf("Running CDC ACM Basic Memory Test................................... ");
554 
555     /* Reset testing counts. */
556     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
557     ux_test_utility_sim_mem_alloc_count_reset();
558     ux_test_utility_sim_mutex_create_count_reset();
559     ux_test_utility_sim_sem_create_count_reset();
560     ux_test_utility_sim_sem_get_count_reset();
561     /* Reset error generations */
562     ux_test_utility_sim_sem_error_generation_stop();
563     ux_test_utility_sim_mutex_error_generation_stop();
564     ux_test_utility_sim_sem_get_error_generation_stop();
565 
566     /* Initialize the free memory pointer */
567     stack_pointer = (CHAR *) usbx_memory;
568     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
569 
570     /* Initialize USBX Memory */
571     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
572 
573     /* Check for error.  */
574     if (status != UX_SUCCESS)
575     {
576 
577         printf("ERROR #1\n");
578         test_control_return(1);
579     }
580 
581     /* Register the error callback. */
582     _ux_utility_error_callback_register(error_callback);
583 
584     /* The code below is required for installing the host portion of USBX */
585     status =  ux_host_stack_initialize(demo_system_host_change_function);
586     if (status != UX_SUCCESS)
587     {
588 
589         printf("ERROR #2\n");
590         test_control_return(1);
591     }
592 
593     /* Register CDC-ACM class.  */
594     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
595     if (status != UX_SUCCESS)
596     {
597 
598         printf("ERROR #3\n");
599         test_control_return(1);
600     }
601 
602     /* The code below is required for installing the device portion of USBX. No call back for
603        device status change in this example. */
604     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
605                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
606                                        string_framework, STRING_FRAMEWORK_LENGTH,
607                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
608     if(status!=UX_SUCCESS)
609     {
610 
611         printf("ERROR #5\n");
612         test_control_return(1);
613     }
614 
615     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
616     parameter.ux_slave_class_cdc_acm_instance_activate   =  test_cdc_instance_activate;
617     parameter.ux_slave_class_cdc_acm_instance_deactivate =  test_cdc_instance_deactivate;
618     parameter.ux_slave_class_cdc_acm_parameter_change    =  test_cdc_instance_parameter_change;
619 
620     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
621     status =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
622                                              1,0,  &parameter);
623 
624     if(status!=UX_SUCCESS)
625     {
626 
627         printf("ERROR #6\n");
628         test_control_return(1);
629     }
630 
631     /* Initialize the simulated device controller.  */
632     status =  _ux_dcd_sim_slave_initialize();
633 
634     /* Check for error.  */
635     if (status != TX_SUCCESS)
636     {
637 
638         printf("ERROR #7\n");
639         test_control_return(1);
640     }
641 
642     /* Register all the USB host controllers available in this system */
643     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
644     if (status != UX_SUCCESS)
645     {
646 
647         printf("ERROR #4\n");
648         test_control_return(1);
649     }
650 
651     /* Create the main host simulation thread.  */
652     status =  tx_thread_create(&ux_test_thread_host_simulation, "tx demo host simulation", ux_test_thread_host_simulation_entry, 0,
653             stack_pointer, UX_DEMO_STACK_SIZE,
654             20, 20, 1, TX_AUTO_START);
655 
656     /* Check for error.  */
657     if (status != TX_SUCCESS)
658     {
659 
660         printf("ERROR #8\n");
661         test_control_return(1);
662     }
663 
664     /* Create the main slave simulation  thread.  */
665     status =  tx_thread_create(&ux_test_thread_slave_simulation, "tx demo slave simulation", ux_test_thread_slave_simulation_entry, 0,
666             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
667             20, 20, 1, TX_AUTO_START);
668 
669     /* Check for error.  */
670     if (status != TX_SUCCESS)
671     {
672 
673         printf("ERROR #9\n");
674         test_control_return(1);
675     }
676 }
677 
ux_test_thread_host_simulation_entry(ULONG arg)678 void  ux_test_thread_host_simulation_entry(ULONG arg)
679 {
680 
681 UINT                                                status;
682 UX_SLAVE_CLASS_CDC_ACM *                            cdc_acm_slave_bak;
683 UX_HOST_CLASS_CDC_ACM *                             cdc_acm_host_ctrl_bak;
684 UX_HOST_CLASS_CDC_ACM *                             cdc_acm_host_data_bak;
685 ULONG                                               test_n;
686 ULONG                                               mem_free;
687 ULONG                                               retry;
688 
689     stepinfo("\n");
690 
691     /* Find the cdc_acm class and wait for the link to be up.  */
692     status =  demo_class_cdc_acm_get();
693     if (status != UX_SUCCESS)
694     {
695 
696         /* CDC ACM basic test error.  */
697         printf("ERROR #10\n");
698         test_control_return(1);
699     }
700 
701     /* Save slave instance for later tests. */
702     cdc_acm_slave_bak = cdc_acm_slave;
703     /* Save host instances for later tests. */
704     cdc_acm_host_ctrl_bak = cdc_acm_host_control;
705     cdc_acm_host_data_bak = cdc_acm_host_data;
706 
707     /* Test disconnect. */
708     ux_test_dcd_sim_slave_disconnect();
709     ux_test_hcd_sim_host_disconnect();
710 
711     /* Reset testing counts. */
712     ux_test_utility_sim_mem_alloc_count_reset();
713     ux_test_utility_sim_mutex_create_count_reset();
714     ux_test_utility_sim_sem_create_count_reset();
715     ux_test_utility_sim_sem_get_count_reset();
716     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
717 
718     /* Save free memory usage. */
719     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
720     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
721     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
722     for (retry = 0; (retry < 10) && (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL); retry ++)
723         tx_thread_sleep(10);
724 
725     /* Log create counts for further tests. */
726     rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
727     rsc_enum_sem_usage = rsc_sem_on_set_cfg;
728     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
729     /* Log create counts when instances active for further tests. */
730     rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
731     rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
732     rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
733 
734     /* Lock log base for tests. */
735     ux_test_utility_sim_mem_alloc_log_lock();
736 
737     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
738     stepinfo("cdc mem : %ld\n", rsc_cdc_mem_alloc_count);
739     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);
740 
741     /* Simulate detach and attach for FS enumeration,
742        and check if there is memory error in normal enumeration.
743      */
744     stepinfo(">>>>>>>>>>>> Enumeration test\n");
745     mem_free = (~0);
746     for (test_n = 0; test_n < 3; test_n++)
747     {
748         stepinfo("%4ld / 2\n", test_n);
749 
750         /* Disconnect. */
751         ux_test_dcd_sim_slave_disconnect();
752         ux_test_hcd_sim_host_disconnect();
753 
754         /* Update memory free level (disconnect) */
755         if (mem_free == (~0))
756             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
757         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
758         {
759 
760             printf("ERROR #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
761             test_control_return(1);
762         }
763 
764         /* Connect. */
765         error_callback_counter = 0;
766         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
767         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
768 
769         /* Wait and break on error. */
770         ux_test_breakable_sleep(100, sleep_break_on_error);
771 
772         /* Check */
773         if (!cdc_acm_host_control || !cdc_acm_host_data)
774         {
775 
776             printf("ERROR #12.%ld: Enumeration fail\n", test_n);
777             test_control_return(1);
778         }
779     }
780 
781     /* Simulate detach and attach for FS enumeration,
782        and test possible memory allocation error handlings.
783      */
784     if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
785     mem_free = (~0);
786     for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
787     {
788 
789         stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
790 
791         /* Disconnect. */
792         ux_test_dcd_sim_slave_disconnect();
793         ux_test_hcd_sim_host_disconnect();
794 
795         /* Update memory free level (disconnect) */
796         if (mem_free == (~0))
797             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
798         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
799         {
800 
801             printf("ERROR #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
802             test_control_return(1);
803         }
804 
805         /* Set memory error generation */
806         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
807 
808         /* Connect. */
809         error_callback_counter = 0;
810         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
811         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
812 
813         /* Wait and break on errors. */
814         ux_test_breakable_sleep(100, sleep_break_on_error);
815 
816         /* Check error */
817         if (cdc_acm_host_control && cdc_acm_host_data)
818         {
819 
820             printf("ERROR #12.%ld: device detected when there is memory error\n", test_n);
821             test_control_return(1);
822         }
823         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
824     }
825     ux_test_utility_sim_mem_alloc_error_generation_stop();
826     if (rsc_cdc_mem_alloc_count) stepinfo("\n");
827 
828     /* Finally disconnect the device. */
829     ux_device_stack_disconnect();
830 
831     /* And deinitialize the class.  */
832     status =  ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
833 
834     /* Deinitialize the device side of usbx.  */
835     _ux_device_stack_uninitialize();
836 
837     /* And finally the usbx system resources.  */
838     _ux_system_uninitialize();
839 
840     /* Successful test.  */
841     printf("SUCCESS!\n");
842     test_control_return(0);
843 
844 }
845 
ux_test_thread_slave_simulation_entry(ULONG arg)846 void  ux_test_thread_slave_simulation_entry(ULONG arg)
847 {
848 
849     while(1)
850     {
851         /* Sleep so ThreadX on Win32 will delete this thread. */
852         tx_thread_sleep(10);
853     }
854 }
855