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 
14 #include "ux_host_class_cdc_acm.h"
15 
16 #include "ux_test_dcd_sim_slave.h"
17 #include "ux_test_hcd_sim_host.h"
18 #include "ux_test_utility_sim.h"
19 
20 #include "ux_host_stack.h"
21 
22 /* Define constants.  */
23 #define                             UX_DEMO_DEBUG_SIZE  (4096*8)
24 #define                             UX_DEMO_STACK_SIZE  1024
25 #define                             UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
26 #define                             UX_DEMO_XMIT_BUFFER_SIZE 512
27 #define                             UX_DEMO_RECEPTION_BUFFER_SIZE 512
28 #define                             UX_DEMO_FILE_BUFFER_SIZE 512
29 #define                             UX_DEMO_RECEPTION_BLOCK_SIZE 64
30 #define                             UX_DEMO_MEMORY_SIZE     (64*1024)
31 #define                             UX_DEMO_FILE_SIZE       (128 * 1024)
32 #define                             UX_RAM_DISK_MEMORY      (256 * 1024)
33 
34 #define     LSB(x) ( (x) & 0x00ff)
35 #define     MSB(x) (((x) & 0xff00) >> 8)
36 
37 /* Configuration descriptor 9 bytes */
38 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
39     /* Configuration 1 descriptor 9 bytes */\
40     0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
41     (bNumInterfaces), (bConfigurationValue), 0x00,\
42     0x40, 0x00,
43 #define CFG_DESC_LEN 9
44 
45 #define IAD_DESC(bIfc) \
46     /* Interface association descriptor. 8 bytes.  */\
47     0x08, 0x0b, (bIfc), 0x02, 0x02, 0x02, 0x00, 0x00,
48 #define IAD_DESC_LEN 8
49 
50 #define CDC_IFC_DESC_ALL(bIfc, bIntIn, bBulkIn, bBulkOut)\
51     /* Communication Class Interface Descriptor Requirement. 9 bytes.   */\
52     0x09, 0x04, (bIfc), 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,\
53     /* Header Functional Descriptor 5 bytes */\
54     0x05, 0x24, 0x00, 0x10, 0x01,\
55     /* ACM Functional Descriptor 4 bytes */\
56     0x04, 0x24, 0x02, 0x0f,\
57     /* Union Functional Descriptor 5 bytes */\
58     0x05, 0x24, 0x06, (bIfc), (bIfc + 1),\
59     /* Call Management Functional Descriptor 5 bytes */\
60     0x05, 0x24, 0x01, 0x03, (bIfc + 1),\
61     /* Endpoint interrupt in descriptor 7 bytes */\
62     0x07, 0x05, (bIntIn), 0x03, 0x40, 0x00, 0x10,\
63     /* Data Class Interface Descriptor Requirement 9 bytes */\
64     0x09, 0x04, (bIfc + 1), 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,\
65     /* Endpoint bulk in descriptor 7 bytes */\
66     0x07, 0x05, (bBulkIn), 0x02, 0x40, 0x00, 0x01,\
67     /* Endpoint bulk out descriptor 7 bytes */\
68     0x07, 0x05, (bBulkOut), 0x02, 0x40, 0x00, 0x01,
69 #define CDC_IFC_DESC_ALL_LEN (9+5+4+5+5+7+ 9+7+7)
70 
71 /* Define local/extern function prototypes.  */
72 static VOID                                test_thread_entry(ULONG);
73 static TX_THREAD                           tx_test_thread_host_simulation;
74 static TX_THREAD                           tx_test_thread_slave_simulation;
75 static VOID                                tx_test_thread_host_simulation_entry(ULONG);
76 static VOID                                tx_test_thread_slave_simulation_entry(ULONG);
77 static VOID                                test_cdc_instance_activate(VOID  *cdc_instance);
78 static VOID                                test_cdc_instance_deactivate(VOID *cdc_instance);
79 static VOID                                test_cdc_instance_parameter_change(VOID *cdc_instance);
80 
81 /* Define global data structures.  */
82 static UCHAR                               usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
83 static UX_HOST_CLASS                       *class_driver;
84 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_control;
85 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_data;
86 
87 static UX_SLAVE_CLASS_CDC_ACM              *cdc_acm_slave;
88 static UCHAR                               cdc_acm_slave_change;
89 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER    parameter;
90 
91 static ULONG                               error_counter;
92 
93 static ULONG                               error_callback_counter;
94 static UCHAR                               error_callback_ignore;
95 
96 /* Define device framework.  */
97 
98 static unsigned char device_framework_full_speed[] = {
99 
100     /* Device descriptor     18 bytes
101        0x02 bDeviceClass:    CDC class code
102        0x00 bDeviceSubclass: CDC class sub code
103        0x00 bDeviceProtocol: CDC Device protocol
104 
105        idVendor & idProduct - http://www.linux-usb.org/usb.ids
106     */
107     0x12, 0x01, 0x10, 0x01,
108     0xEF, 0x02, 0x01,
109     0x08,
110     0x84, 0x84, 0x00, 0x00,
111     0x00, 0x01,
112     0x01, 0x02, 03,
113     0x01, /* bNumConfigurations */
114 
115     /* Configuration 1 descriptor 9 bytes, total 75 bytes */
116     CFG_DESC(CFG_DESC_LEN + IAD_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 1)
117     /* IAD 8 bytes */
118     IAD_DESC(0)
119     /* CDC_ACM interfaces */
120     CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
121 };
122 #define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      sizeof(device_framework_full_speed)
123 
124 static unsigned char device_framework_high_speed[] = {
125 
126     /* Device descriptor     18 bytes
127        0x02 bDeviceClass:    CDC class code
128        0x00 bDeviceSubclass: CDC class sub code
129        0x00 bDeviceProtocol: CDC Device protocol
130 
131        idVendor & idProduct - http://www.linux-usb.org/usb.ids
132     */
133     0x12, 0x01, 0x00, 0x02,
134     0xEF, 0x02, 0x01,
135     0x40,
136     0x84, 0x84, 0x00, 0x00,
137     0x00, 0x01,
138     0x01, 0x02, 03,
139     0x01, /* bNumConfigurations */
140 
141     /* Device qualifier descriptor 10 bytes */
142     0x0a, 0x06, 0x00, 0x02,
143     0x02, 0x00, 0x00,
144     0x40,
145     0x01,
146     0x00,
147 
148     /* Configuration 1 descriptor 9 bytes, total 75-8=67 bytes */
149     CFG_DESC(CFG_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 1)
150     CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
151 };
152 #define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      sizeof(device_framework_high_speed)
153 
154 static unsigned char string_framework[] = {
155 
156     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
157     0x09, 0x04, 0x01, 0x0c,
158     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
159     0x6f, 0x67, 0x69, 0x63,
160 
161     /* Product string descriptor : Index 2 - "EL Composite device" */
162     0x09, 0x04, 0x02, 0x13,
163     0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
164     0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
165     0x69, 0x63, 0x65,
166 
167     /* Serial Number string descriptor : Index 3 - "0001" */
168     0x09, 0x04, 0x03, 0x04,
169     0x30, 0x30, 0x30, 0x31
170 };
171 #define             STRING_FRAMEWORK_LENGTH                 sizeof(string_framework)
172 
173 /* Multiple languages are supported on the device, to add
174     a language besides english, the unicode language code must
175     be appended to the language_id_framework array and the length
176     adjusted accordingly. */
177 static unsigned char language_id_framework[] = {
178 
179     /* English. */
180     0x09, 0x04
181 };
182 #define             LANGUAGE_ID_FRAMEWORK_LENGTH            sizeof(language_id_framework)
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 
break_on_cdc_acm_all_ready(VOID)202 static UINT break_on_cdc_acm_all_ready(VOID)
203 {
204 UINT                                 status;
205 UINT                                 i;
206 UX_HOST_CLASS                       *class;
207 UX_HOST_CLASS_CDC_ACM               *cdc_acm;
208 
209     /* Find the main cdc_acm container */
210     status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
211     if (status != UX_SUCCESS)
212         /* Do not break. */
213         return 0;
214 
215     /* Find class instances. */
216     for (i = 0; i < 2; i ++)
217     {
218         status = ux_host_stack_class_instance_get(class, i, (void **) &cdc_acm);
219         if (status != UX_SUCCESS)
220             /* Do not break. */
221             return 0;
222 
223         switch(cdc_acm->ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass)
224         {
225 
226         case UX_HOST_CLASS_CDC_CONTROL_CLASS:
227             cdc_acm_host_control = cdc_acm;
228             break;
229 
230         case UX_HOST_CLASS_CDC_DATA_CLASS:
231             cdc_acm_host_data = cdc_acm;
232             break;
233 
234         default:
235             break;
236         }
237     }
238 
239     if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL)
240         /* Do not break. */
241         return 0;
242 
243     if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
244         /* Do not break. */
245         return 0;
246 
247     if (cdc_acm_host_data->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
248         /* Do not break. */
249         return 0;
250 
251     if (cdc_acm_slave == UX_NULL)
252         /* Do not break. */
253         return 0;
254 
255     /* All found, break. */
256     return 1;
257 }
258 
break_on_removal(VOID)259 static UINT break_on_removal(VOID)
260 {
261 
262 UINT                     status;
263 UX_DEVICE               *device;
264 
265     status = ux_host_stack_device_get(0, &device);
266     if (status == UX_SUCCESS)
267         /* Do not break. */
268         return UX_SUCCESS;
269 
270     cdc_acm_host_data = UX_NULL;
271     cdc_acm_host_control = UX_NULL;
272 
273     return 1;
274 }
275 
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)276 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
277 {
278 
279 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
280 
281     switch(event)
282     {
283 
284         case UX_DEVICE_INSERTION:
285 
286             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
287                 cdc_acm_host_control = cdc_acm;
288             else
289                 cdc_acm_host_data = cdc_acm;
290             break;
291 
292         case UX_DEVICE_REMOVAL:
293 
294             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
295                 cdc_acm_host_control = UX_NULL;
296             else
297                 cdc_acm_host_data = UX_NULL;
298             break;
299 
300         default:
301             break;
302     }
303     return 0;
304 }
305 
test_cdc_instance_activate(VOID * cdc_instance)306 static VOID    test_cdc_instance_activate(VOID *cdc_instance)
307 {
308 
309     /* Save the CDC instance.  */
310     cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
311 }
test_cdc_instance_deactivate(VOID * cdc_instance)312 static VOID    test_cdc_instance_deactivate(VOID *cdc_instance)
313 {
314 
315     /* Reset the CDC instance.  */
316     cdc_acm_slave = UX_NULL;
317 }
318 
test_cdc_instance_parameter_change(VOID * cdc_instance)319 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
320 {
321 
322     /* Set CDC parameter change flag. */
323     cdc_acm_slave_change = UX_TRUE;
324 }
325 
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)326 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
327 {
328     error_callback_counter ++;
329 
330     if (!error_callback_ignore)
331     {
332         {
333             /* Failed test.  */
334             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
335             // test_control_return(1);
336         }
337     }
338 }
339 
340 /* Define what the initial system looks like.  */
341 
342 #ifdef CTEST
test_application_define(void * first_unused_memory)343 void test_application_define(void *first_unused_memory)
344 #else
345 void usbx_ux_host_class_cdc_acm_entry_test_application_define(void *first_unused_memory)
346 #endif
347 {
348 
349 UINT                    status;
350 CHAR *                  stack_pointer;
351 CHAR *                  memory_pointer;
352 
353     printf("Running ux_host_class_cdc_acm_entry Test............................ ");
354 
355     /* Initialize the free memory pointer */
356     stack_pointer = (CHAR *) usbx_memory;
357     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
358 
359     /* Initialize USBX Memory */
360     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
361     /* Check for error.  */
362     if (status != UX_SUCCESS)
363     {
364 
365         printf("ERROR #%d\n", __LINE__);
366         test_control_return(1);
367     }
368 
369     /* Register the error callback. */
370     _ux_utility_error_callback_register(test_ux_error_callback);
371 
372     /* The code below is required for installing the host portion of USBX */
373     status =  ux_host_stack_initialize(UX_NULL);
374     if (status != UX_SUCCESS)
375     {
376 
377         printf("ERROR #%d\n", __LINE__);
378         test_control_return(1);
379     }
380 
381     /* Register CDC ACM class */
382     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
383     if (status != UX_SUCCESS)
384     {
385 
386         printf("ERROR #%d\n", __LINE__);
387         test_control_return(1);
388     }
389 
390     /* The code below is required for installing the device portion of USBX. No call back for
391        device status change in this example. */
392     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
393                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
394                                        string_framework, STRING_FRAMEWORK_LENGTH,
395                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
396     if(status!=UX_SUCCESS)
397     {
398 
399         printf("ERROR #%d\n", __LINE__);
400         test_control_return(1);
401     }
402 
403     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
404     parameter.ux_slave_class_cdc_acm_instance_activate   =  test_cdc_instance_activate;
405     parameter.ux_slave_class_cdc_acm_instance_deactivate =  test_cdc_instance_deactivate;
406     parameter.ux_slave_class_cdc_acm_parameter_change    =  test_cdc_instance_parameter_change;
407 
408     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
409     status  =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
410                                              1,0,  &parameter);
411     status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
412                                              2,0,  &parameter);
413     status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
414                                              3,0,  &parameter);
415 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
416     if(status!=UX_SUCCESS)
417     {
418 
419         printf("ERROR #%d\n", __LINE__);
420         test_control_return(1);
421     }
422 #endif
423 
424     /* Initialize the simulated device controller.  */
425     status =  _ux_test_dcd_sim_slave_initialize();
426 
427     /* Check for error.  */
428     if (status != TX_SUCCESS)
429     {
430 
431         printf("ERROR #%d\n", __LINE__);
432         test_control_return(1);
433     }
434 
435     /* Register HCD for test */
436     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
437     if (status != UX_SUCCESS)
438     {
439 
440         printf("ERROR #%d\n", __LINE__);
441         test_control_return(1);
442     }
443 
444     /* Create the main host simulation thread.  */
445     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_thread_host_simulation_entry, 0,
446             stack_pointer, UX_DEMO_STACK_SIZE,
447             20, 20, 1, TX_AUTO_START);
448 
449     /* Check for error.  */
450     if (status != TX_SUCCESS)
451     {
452 
453         printf("ERROR #%d\n", __LINE__);
454         test_control_return(1);
455     }
456 
457     /* Create the main slave simulation  thread.  */
458     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
459             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
460             20, 20, 1, TX_AUTO_START);
461 
462     /* Check for error.  */
463     if (status != TX_SUCCESS)
464     {
465 
466         printf("ERROR #%d\n", __LINE__);
467         test_control_return(1);
468     }
469 }
470 
tx_test_thread_host_simulation_entry(ULONG arg)471 void  tx_test_thread_host_simulation_entry(ULONG arg)
472 {
473 
474 UINT                                                status;
475 INT                                                 test_n;
476 UX_DEVICE                                          *device;
477 UCHAR                                              *framework;
478 UCHAR                                               speed;
479 UINT                                                iad_off;
480 UINT                                                ifc_off;
481 
482     stepinfo("\n");
483 
484     /* Test connect. */
485     stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
486     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
487     ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
488     if (!(cdc_acm_host_control && cdc_acm_host_data && cdc_acm_slave))
489     {
490 
491         printf("ERROR #%d: connect fail\n", __LINE__);
492         test_control_return(1);
493     }
494 
495     /* Get device instance. */
496     status = ux_host_stack_device_get(0, &device);
497     if (status != UX_SUCCESS)
498     {
499 
500         printf("ERROR #%d: device_get fail\n", __LINE__);
501         test_control_return(1);
502     }
503 
504     error_callback_ignore = UX_TRUE;
505 
506     for (test_n = 0; test_n < 2; test_n ++)
507     {
508 
509         framework = test_n ? device_framework_high_speed : device_framework_full_speed;
510         speed = test_n ? UX_HIGH_SPEED_DEVICE : UX_FULL_SPEED_DEVICE;
511         iad_off = (18+9);
512         ifc_off = test_n ? (18+10+9) : (18+9+8);
513 
514         if (test_n == 0)
515         {
516 
517             stepinfo(">>>>>>>>>>>>>>>> Test %s IAD IAD.bClass error\n", test_n ? "no" : "with");
518 
519             /* Modify IAD.bClass.  */
520             ux_test_dcd_sim_slave_disconnect();
521             ux_test_hcd_sim_host_disconnect();
522             ux_test_breakable_sleep(100, break_on_removal);
523             framework[iad_off + 4] = 4;
524 
525             ux_test_dcd_sim_slave_connect(speed);
526             ux_test_hcd_sim_host_connect(speed);
527             ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
528 
529             if (cdc_acm_host_control || cdc_acm_host_data)
530             {
531 
532                 printf("ERROR #%d.%d: expect enum fail\n", __LINE__, test_n);
533                 error_counter ++;
534             }
535             framework[iad_off + 4] = 2;
536 
537             stepinfo(">>>>>>>>>>>>>>>> Test %s IAD IAD.bSubClass error\n", test_n ? "no" : "width");
538 
539             /* Modify IAD.bSubClass.  */
540             ux_test_dcd_sim_slave_disconnect();
541             ux_test_hcd_sim_host_disconnect();
542             ux_test_breakable_sleep(100, break_on_removal);
543             framework[iad_off + 5] = 4;
544 
545             ux_test_dcd_sim_slave_connect(speed);
546             ux_test_hcd_sim_host_connect(speed);
547             ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
548 
549             if (cdc_acm_host_control || cdc_acm_host_data)
550             {
551 
552                 printf("ERROR #%d.%d: expect enum fail\n", __LINE__, test_n);
553                 error_counter ++;
554             }
555             framework[iad_off + 5] = 2;
556 
557             stepinfo(">>>>>>>>>>>>>>>> Test %s IAD IAD.bClass&bSubClass 0&0\n", test_n ? "no" : "with");
558 
559             /* Modify IAD.bClass&bSubClass.  */
560             ux_test_dcd_sim_slave_disconnect();
561             ux_test_hcd_sim_host_disconnect();
562             ux_test_breakable_sleep(100, break_on_removal);
563             framework[iad_off + 4] = 0;
564             framework[iad_off + 5] = 0;
565 
566             ux_test_dcd_sim_slave_connect(speed);
567             ux_test_hcd_sim_host_connect(speed);
568             ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
569 
570             if (cdc_acm_host_control == UX_NULL)
571             {
572 
573                 printf("ERROR #%d.%d: expect enum OK\n", __LINE__, test_n);
574                 error_counter ++;
575             }
576             framework[iad_off + 4] = 2;
577             framework[iad_off + 5] = 2;
578 
579             stepinfo(">>>>>>>>>>>>>>>> Test %s IAD IAD.bClass&bSubClass 0&4\n", test_n ? "no" : "with");
580 
581             /* Modify IAD.bClass&bSubClass.  */
582             ux_test_dcd_sim_slave_disconnect();
583             ux_test_hcd_sim_host_disconnect();
584             ux_test_breakable_sleep(100, break_on_removal);
585             framework[iad_off + 4] = 0;
586             framework[iad_off + 5] = 4;
587 
588             ux_test_dcd_sim_slave_connect(speed);
589             ux_test_hcd_sim_host_connect(speed);
590             ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
591 
592             if (cdc_acm_host_control != UX_NULL)
593             {
594 
595                 printf("ERROR #%d.%d: expect enum fail\n", __LINE__, test_n);
596                 error_counter ++;
597             }
598             framework[iad_off + 4] = 2;
599             framework[iad_off + 5] = 2;
600         }
601 
602         stepinfo(">>>>>>>>>>>>>>>> Test %s IAD interface.bClass error\n", test_n ? "no" : "with");
603 
604         /* Modify Interface.bClass.  */
605         ux_test_dcd_sim_slave_disconnect();
606         ux_test_hcd_sim_host_disconnect();
607         ux_test_breakable_sleep(100, break_on_removal);
608         framework[ifc_off + 5] = 4;
609 
610         ux_test_dcd_sim_slave_connect(speed);
611         ux_test_hcd_sim_host_connect(speed);
612         ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
613 
614         if (cdc_acm_host_control)
615         {
616 
617             printf("ERROR #%d.%d: expect control interface fail\n", __LINE__, test_n);
618             error_counter ++;
619         }
620         framework[ifc_off + 5] = 2;
621 
622         stepinfo(">>>>>>>>>>>>>>>> Test %s IAD interface.bSubClass error\n", test_n ? "no" : "with");
623 
624         /* Modify Interface.bSubClass.  */
625         ux_test_dcd_sim_slave_disconnect();
626         ux_test_hcd_sim_host_disconnect();
627         ux_test_breakable_sleep(100, break_on_removal);
628         framework[ifc_off + 6] = 4;
629 
630         ux_test_dcd_sim_slave_connect(speed);
631         ux_test_hcd_sim_host_connect(speed);
632         ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
633 
634         if (cdc_acm_host_control)
635         {
636 
637             printf("ERROR #%d.%d: expect control interface fail\n", __LINE__, test_n);
638             error_counter ++;
639         }
640         framework[ifc_off + 6] = 2;
641 
642     }
643 
644     error_callback_ignore = UX_FALSE;
645 
646     stepinfo(">>>>>>>>>>>>>>>> Deinitialize\n");
647 
648     /* Deinitialize the class.  */
649     status =  ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
650 
651     /* Deinitialize the device side of usbx.  */
652     _ux_device_stack_uninitialize();
653 
654     /* And finally the usbx system resources.  */
655     _ux_system_uninitialize();
656 
657     stepinfo(">>>>>>>>>>>>>>>> Dump results\n");
658 
659     if (error_counter > 0)
660     {
661 
662         /* Test error.  */
663         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
664         test_control_return(1);
665     }
666 
667     /* Successful test.  */
668     printf("SUCCESS!\n");
669     test_control_return(0);
670 }
671 
tx_test_thread_slave_simulation_entry(ULONG arg)672 void  tx_test_thread_slave_simulation_entry(ULONG arg)
673 {
674 
675     while(1)
676     {
677 
678         /* Sleep so ThreadX on Win32 will delete this thread. */
679         ux_utility_delay_ms(100);
680     }
681 }
682