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 (32768)
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, bmAttributes, bConfigurationValue)\
39     /* Configuration 1 descriptor 9 bytes */\
40     0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
41     (bNumInterfaces), (bConfigurationValue), 0x00,\
42     (bmAttributes), 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_simulation_0;
74 static TX_THREAD                           tx_test_thread_simulation_1;
75 static VOID                                tx_test_thread_simulation_0_entry(ULONG);
76 static VOID                                tx_test_thread_simulation_1_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_device;
88 static UCHAR                               cdc_acm_device_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 static UCHAR                               buffer[UX_DEMO_BUFFER_SIZE];
97 static UCHAR                              *device_buffer = buffer;
98 static UCHAR                              *host_buffer = &buffer[UX_DEMO_BUFFER_SIZE/2];
99 static ULONG                               device_run_count;
100 static UINT                                device_status;
101 static ULONG                               device_actual_length;
102 
103 static ULONG                               test_thread_action;
104 
105 /* Define device framework.  */
106 
107 static unsigned char device_framework_full_speed[] = {
108 
109     /* Device descriptor     18 bytes
110        0x02 bDeviceClass:    CDC class code
111        0x00 bDeviceSubclass: CDC class sub code
112        0x00 bDeviceProtocol: CDC Device protocol
113 
114        idVendor & idProduct - http://www.linux-usb.org/usb.ids
115     */
116     0x12, 0x01, 0x10, 0x01,
117     0xEF, 0x02, 0x01,
118     0x08,
119     0x84, 0x84, 0x00, 0x00,
120     0x00, 0x01,
121     0x01, 0x02, 03,
122     0x01, /* bNumConfigurations */
123 
124     /* Configuration 1 descriptor 9 bytes, total 75 bytes */
125     CFG_DESC(CFG_DESC_LEN + IAD_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 0x40, 1)
126     /* IAD 8 bytes */
127     IAD_DESC(0)
128     /* CDC_ACM interfaces */
129     CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
130 };
131 #define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      sizeof(device_framework_full_speed)
132 
133 static unsigned char device_framework_high_speed[] = {
134 
135     /* Device descriptor     18 bytes
136        0x02 bDeviceClass:    CDC class code
137        0x00 bDeviceSubclass: CDC class sub code
138        0x00 bDeviceProtocol: CDC Device protocol
139 
140        idVendor & idProduct - http://www.linux-usb.org/usb.ids
141     */
142     0x12, 0x01, 0x00, 0x02,
143     0xEF, 0x02, 0x01,
144     0x40,
145     0x84, 0x84, 0x00, 0x00,
146     0x00, 0x01,
147     0x01, 0x02, 03,
148     0x01, /* bNumConfigurations */
149 
150     /* Device qualifier descriptor 10 bytes */
151     0x0a, 0x06, 0x00, 0x02,
152     0x02, 0x00, 0x00,
153     0x40,
154     0x01,
155     0x00,
156 
157     /* Configuration 1 descriptor 9 bytes, total 75-8=67 bytes */
158     CFG_DESC(CFG_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 0x60, 1)
159     CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
160 };
161 #define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      sizeof(device_framework_high_speed)
162 
163 static unsigned char string_framework[] = {
164 
165     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
166     0x09, 0x04, 0x01, 0x0c,
167     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
168     0x6f, 0x67, 0x69, 0x63,
169 
170     /* Product string descriptor : Index 2 - "EL Composite device" */
171     0x09, 0x04, 0x02, 0x13,
172     0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
173     0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
174     0x69, 0x63, 0x65,
175 
176     /* Serial Number string descriptor : Index 3 - "0001" */
177     0x09, 0x04, 0x03, 0x04,
178     0x30, 0x30, 0x30, 0x31
179 };
180 #define             STRING_FRAMEWORK_LENGTH                 sizeof(string_framework)
181 
182 /* Multiple languages are supported on the device, to add
183     a language besides english, the unicode language code must
184     be appended to the language_id_framework array and the length
185     adjusted accordingly. */
186 static unsigned char language_id_framework[] = {
187 
188     /* English. */
189     0x09, 0x04
190 };
191 #define             LANGUAGE_ID_FRAMEWORK_LENGTH            sizeof(language_id_framework)
192 
disconnect_after_mutex_on_action_func(struct UX_TEST_ACTION_STRUCT * action,VOID * params)193 static VOID disconnect_after_mutex_on_action_func(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
194 {
195     _ux_system_slave->ux_system_slave_device.ux_slave_device_state = UX_DEVICE_ADDRESSED;
196 }
197 
198 static UX_TEST_HCD_SIM_ACTION disconnect_after_mutex_on[] = {
199     {
200         .do_after = UX_TRUE,
201         .usbx_function = UX_TEST_OVERRIDE_TX_MUTEX_GET,
202         .wait_option = TX_WAIT_FOREVER,
203         .action_func = disconnect_after_mutex_on_action_func,
204     },
205     { 0 }
206 };
207 
208 /* Define the ISR dispatch.  */
209 
210 extern VOID    (*test_isr_dispatch)(void);
211 
212 
213 /* Prototype for test control return.  */
214 
215 void  test_control_return(UINT status);
216 
217 
218 /* Define the ISR dispatch routine.  */
219 
test_isr(void)220 static void    test_isr(void)
221 {
222 
223     /* For further expansion of interrupt-level testing.  */
224 }
225 
break_on_cdc_acm_all_ready(VOID)226 static UINT break_on_cdc_acm_all_ready(VOID)
227 {
228 UINT                                 status;
229 UINT                                 i;
230 UX_HOST_CLASS                       *class;
231 UX_HOST_CLASS_CDC_ACM               *cdc_acm;
232 
233     /* Find the main cdc_acm container */
234     status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
235     if (status != UX_SUCCESS)
236         /* Do not break. */
237         return 0;
238 
239     /* Find class instances. */
240     for (i = 0; i < 2; i ++)
241     {
242         status = ux_host_stack_class_instance_get(class, i, (void **) &cdc_acm);
243         if (status != UX_SUCCESS)
244             /* Do not break. */
245             return 0;
246 
247         switch(cdc_acm->ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass)
248         {
249 
250         case UX_HOST_CLASS_CDC_CONTROL_CLASS:
251             cdc_acm_host_control = cdc_acm;
252             break;
253 
254         case UX_HOST_CLASS_CDC_DATA_CLASS:
255             cdc_acm_host_data = cdc_acm;
256             break;
257 
258         default:
259             break;
260         }
261     }
262 
263     if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL)
264         /* Do not break. */
265         return 0;
266 
267     if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
268         /* Do not break. */
269         return 0;
270 
271     if (cdc_acm_host_data->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
272         /* Do not break. */
273         return 0;
274 
275     if (_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance == UX_NULL)
276         /* Do not break. */
277         return 0;
278 
279     cdc_acm_device = (UX_SLAVE_CLASS_CDC_ACM *)_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance;
280 
281     /* All found, break. */
282     return 1;
283 }
284 
break_on_removal(VOID)285 static UINT break_on_removal(VOID)
286 {
287 
288 UINT                     status;
289 UX_DEVICE               *device;
290 
291     status = ux_host_stack_device_get(0, &device);
292     if (status == UX_SUCCESS)
293         /* Do not break. */
294         return UX_SUCCESS;
295 
296     if (_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance != UX_NULL)
297         /* Do not break. */
298         return 0;
299 
300     cdc_acm_host_data = UX_NULL;
301     cdc_acm_host_control = UX_NULL;
302     cdc_acm_device = UX_NULL;
303 
304     return 1;
305 }
306 
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)307 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
308 {
309 
310 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
311 
312     switch(event)
313     {
314 
315         case UX_DEVICE_INSERTION:
316 
317             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
318                 cdc_acm_host_control = cdc_acm;
319             else
320                 cdc_acm_host_data = cdc_acm;
321             break;
322 
323         case UX_DEVICE_REMOVAL:
324 
325             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
326                 cdc_acm_host_control = UX_NULL;
327             else
328                 cdc_acm_host_data = UX_NULL;
329             break;
330 
331         default:
332             break;
333     }
334     return 0;
335 }
336 
test_cdc_instance_activate(VOID * cdc_instance)337 static VOID    test_cdc_instance_activate(VOID *cdc_instance)
338 {
339 
340     /* Save the CDC instance.  */
341     cdc_acm_device = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
342 }
test_cdc_instance_deactivate(VOID * cdc_instance)343 static VOID    test_cdc_instance_deactivate(VOID *cdc_instance)
344 {
345 
346     /* Reset the CDC instance.  */
347     cdc_acm_device = UX_NULL;
348 }
349 
test_cdc_instance_parameter_change(VOID * cdc_instance)350 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
351 {
352 
353     /* Set CDC parameter change flag. */
354     cdc_acm_device_change = UX_TRUE;
355 }
356 
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)357 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
358 {
359     error_callback_counter ++;
360 
361     if (!error_callback_ignore)
362     {
363         {
364             /* Failed test.  */
365             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
366             test_control_return(1);
367         }
368     }
369 }
370 
371 /* Define what the initial system looks like.  */
372 
373 #ifdef CTEST
test_application_define(void * first_unused_memory)374 void test_application_define(void *first_unused_memory)
375 #else
376 void usbx_ux_host_class_cdc_acm_read_test_application_define(void *first_unused_memory)
377 #endif
378 {
379 
380 UINT                    status;
381 CHAR *                  stack_pointer;
382 CHAR *                  memory_pointer;
383 
384 
385     printf("Running ux_host_class_cdc_acm_write Test............................ ");
386 #if !UX_TEST_MULTI_IFC_ON
387     printf("Skipped\n");
388     test_control_return(0);
389     return;
390 #endif
391     stepinfo("\n");
392 
393     /* Initialize the free memory pointer */
394     stack_pointer = (CHAR *) usbx_memory;
395     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
396 
397     /* Initialize USBX Memory */
398     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
399     /* Check for error.  */
400     if (status != UX_SUCCESS)
401     {
402 
403         printf("ERROR #%d\n", __LINE__);
404         test_control_return(1);
405     }
406 
407     /* Register the error callback. */
408     _ux_utility_error_callback_register(test_ux_error_callback);
409 
410     /* The code below is required for installing the host portion of USBX */
411     status =  ux_host_stack_initialize(UX_NULL);
412     if (status != UX_SUCCESS)
413     {
414 
415         printf("ERROR #%d\n", __LINE__);
416         test_control_return(1);
417     }
418 
419     /* Register CDC ACM class */
420     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
421     if (status != UX_SUCCESS)
422     {
423 
424         printf("ERROR #%d\n", __LINE__);
425         test_control_return(1);
426     }
427 
428     /* The code below is required for installing the device portion of USBX. No call back for
429        device status change in this example. */
430     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
431                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
432                                        string_framework, STRING_FRAMEWORK_LENGTH,
433                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
434     if(status!=UX_SUCCESS)
435     {
436 
437         printf("ERROR #%d\n", __LINE__);
438         test_control_return(1);
439     }
440 
441     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
442     parameter.ux_slave_class_cdc_acm_instance_activate   =  UX_NULL;
443     parameter.ux_slave_class_cdc_acm_instance_deactivate =  UX_NULL;
444     parameter.ux_slave_class_cdc_acm_parameter_change    =  test_cdc_instance_parameter_change;
445 
446     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
447     status  =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
448                                              1,0,  &parameter);
449     status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
450                                              2,0,  &parameter);
451     status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
452                                              3,0,  &parameter);
453 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
454     if(status!=UX_SUCCESS)
455     {
456 
457         printf("ERROR #%d\n", __LINE__);
458         test_control_return(1);
459     }
460 #endif
461 
462     /* Initialize the simulated device controller.  */
463     status =  _ux_test_dcd_sim_slave_initialize();
464 
465     /* Check for error.  */
466     if (status != TX_SUCCESS)
467     {
468 
469         printf("ERROR #%d\n", __LINE__);
470         test_control_return(1);
471     }
472 
473     /* Register HCD for test */
474     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
475     if (status != UX_SUCCESS)
476     {
477 
478         printf("ERROR #%d\n", __LINE__);
479         test_control_return(1);
480     }
481 
482     /* Create the main host simulation thread.  */
483     status =  tx_thread_create(&tx_test_thread_simulation_0, "tx test host simulation", tx_test_thread_simulation_0_entry, 0,
484             stack_pointer, UX_DEMO_STACK_SIZE,
485             20, 20, 1, TX_AUTO_START);
486 
487     /* Check for error.  */
488     if (status != TX_SUCCESS)
489     {
490 
491         printf("ERROR #%d\n", __LINE__);
492         test_control_return(1);
493     }
494 
495     /* Create the main slave simulation  thread.  */
496     status =  tx_thread_create(&tx_test_thread_simulation_1, "tx test slave simulation", tx_test_thread_simulation_1_entry, 0,
497             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
498             19, 19, 1, TX_AUTO_START);
499 
500     /* Check for error.  */
501     if (status != TX_SUCCESS)
502     {
503 
504         printf("ERROR #%d\n", __LINE__);
505         test_control_return(1);
506     }
507 }
508 
tx_test_thread_simulation_0_entry(ULONG arg)509 void  tx_test_thread_simulation_0_entry(ULONG arg)
510 {
511 
512 UINT                                                status;
513 UX_ENDPOINT                                         *endpoint;
514 ULONG                                               actual_length;
515 
516     /* Test connect. */
517     stepinfo(">>>>>>>>>>>>>>>> Test connect (FS)\n");
518     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
519     ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
520     if (!(cdc_acm_host_control && cdc_acm_host_data && cdc_acm_device))
521     {
522 
523         printf("ERROR #%d: connect fail\n", __LINE__);
524         test_control_return(1);
525     }
526     if (_ux_system_slave->ux_system_slave_device.ux_slave_device_state != UX_DEVICE_CONFIGURED)
527     {
528 
529         printf("ERROR %d: device state fail 0x%lx\n", __LINE__, _ux_system_slave->ux_system_slave_device.ux_slave_device_state);
530         test_control_return(1);
531     }
532 
533     /* Test write ZLP. */
534     stepinfo(">>>>>>>>>>>>>>>> Test write ZLP\n");
535 
536     actual_length = ~0ul;
537     device_status = ~0u;
538     device_actual_length = 0ul;
539     device_run_count = 0;
540     status = ux_host_class_cdc_acm_write(cdc_acm_host_data, host_buffer, 0, &actual_length);
541     if (status != UX_SUCCESS)
542     {
543         printf("ERROR #%d: 0x%x\n", __LINE__, status);
544         error_counter ++;
545     }
546     if (actual_length != 0)
547     {
548         printf("ERROR #%d: %ld\n", __LINE__, actual_length);
549         error_counter ++;
550     }
551     if (device_status != UX_SUCCESS)
552     {
553         printf("ERROR #%d: 0x%x\n", __LINE__, device_status);
554         error_counter ++;
555     }
556     if (device_actual_length != 0)
557     {
558         printf("ERROR #%d: %ld\n", __LINE__, device_actual_length);
559         error_counter ++;
560     }
561     tx_thread_resume(&tx_test_thread_simulation_1);
562 
563     /* Test write 65B. */
564     stepinfo(">>>>>>>>>>>>>>>> Test write 65B\n");
565 
566     actual_length = ~0ul;
567     device_status = ~0u;
568     device_actual_length = 0ul;
569     device_run_count = 0;
570     status = ux_host_class_cdc_acm_write(cdc_acm_host_data, host_buffer, 65, &actual_length);
571     if (status != UX_SUCCESS)
572     {
573         printf("ERROR #%d: 0x%x\n", __LINE__, status);
574         error_counter ++;
575     }
576     if (actual_length != 65)
577     {
578         printf("ERROR #%d: %ld\n", __LINE__, actual_length);
579         error_counter ++;
580     }
581     if (device_status != UX_SUCCESS)
582     {
583         printf("ERROR #%d: 0x%x\n", __LINE__, device_status);
584         error_counter ++;
585     }
586     if (device_actual_length != 65)
587     {
588         printf("ERROR #%d: %ld\n", __LINE__, device_actual_length);
589         error_counter ++;
590     }
591     tx_thread_resume(&tx_test_thread_simulation_1);
592 
593     /* Test write 512B. */
594     stepinfo(">>>>>>>>>>>>>>>> Test write 8192B\n");
595 
596     actual_length = ~0ul;
597     device_status = ~0u;
598     device_actual_length = 0ul;
599     device_run_count = 0;
600     status = ux_host_class_cdc_acm_write(cdc_acm_host_data, host_buffer, 8192, &actual_length);
601     if (status != UX_SUCCESS)
602     {
603         printf("ERROR #%d: 0x%x\n", __LINE__, status);
604         error_counter ++;
605     }
606     if (actual_length != 8192)
607     {
608         printf("ERROR #%d: %ld\n", __LINE__, actual_length);
609         error_counter ++;
610     }
611     if (device_status != UX_SUCCESS)
612     {
613         printf("ERROR #%d: 0x%x\n", __LINE__, device_status);
614         error_counter ++;
615     }
616     if (device_actual_length != 8192)
617     {
618         printf("ERROR #%d: %ld\n", __LINE__, device_actual_length);
619         error_counter ++;
620     }
621     tx_thread_resume(&tx_test_thread_simulation_1);
622 
623     stepinfo(">>>>>>>>>>>>>>>> Deinitialize\n");
624 
625     /* Deinitialize the class.  */
626     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
627     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
628     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
629 
630     /* Deinitialize the device side of usbx.  */
631     _ux_device_stack_uninitialize();
632 
633     /* And finally the usbx system resources.  */
634     _ux_system_uninitialize();
635 
636     stepinfo(">>>>>>>>>>>>>>>> Dump results\n");
637 
638     if (error_counter > 0)
639     {
640 
641         /* Test error.  */
642         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
643         test_control_return(1);
644     }
645 
646     /* Successful test.  */
647     printf("SUCCESS!\n");
648     test_control_return(0);
649 }
650 
tx_test_thread_simulation_1_entry(ULONG arg)651 void  tx_test_thread_simulation_1_entry(ULONG arg)
652 {
653     while(1)
654     {
655         if (!cdc_acm_device)
656         {
657             _ux_utility_delay_ms(10);
658             continue;
659         }
660         device_status = ux_device_class_cdc_acm_read(cdc_acm_device, buffer, 8192, &device_actual_length);
661         device_run_count ++;
662         tx_thread_suspend(&tx_test_thread_simulation_1);
663     }
664 }
665