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     (96*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_ALL1(bIfc, bIntIn, bBulkIn, bBulkOut)\
70     /* Communication Class Interface Descriptor Requirement. 9 bytes.   */\
71     0x09, 0x04, (bIfc), 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,\
72     /* Header Functional Descriptor 5 bytes */\
73     0x05, 0x24, 0x00, 0x10, 0x01,\
74     /* ACM Functional Descriptor 4 bytes */\
75     0x04, 0x24, 0x02, 0x0f,\
76     /* Union Functional Descriptor 5 bytes */\
77     0x05, 0x24, 0x06, (bIfc), (bIfc + 1),\
78     /* Call Management Functional Descriptor 5 bytes */\
79     0x05, 0x24, 0x01, 0x03, (bIfc + 1),\
80     /* Endpoint interrupt in descriptor 7 bytes */\
81     0x07, 0x05, (bIntIn), 0x03, 0x40, 0x00, 0x10,\
82     /* Data Class Interface Descriptor Requirement 9 bytes */\
83     0x09, 0x04, (bIfc + 1), 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,\
84     /* Endpoint bulk out descriptor 7 bytes */\
85     0x07, 0x05, (bBulkOut), 0x02, 0x40, 0x00, 0x01,\
86     /* Endpoint bulk in descriptor 7 bytes */\
87     0x07, 0x05, (bBulkIn), 0x02, 0x40, 0x00, 0x01,
88 #define CDC_IFC_DESC_ALL_LEN (9+5+4+5+5+7+ 9+7+7)
89 
90 /* Define local/extern function prototypes.  */
91 static VOID                                test_thread_entry(ULONG);
92 static TX_THREAD                           tx_test_thread_host_simulation;
93 static TX_THREAD                           tx_test_thread_slave_simulation;
94 static VOID                                tx_test_thread_host_simulation_entry(ULONG);
95 static VOID                                tx_test_thread_slave_simulation_entry(ULONG);
96 
97 static VOID                                test_cdc_instance_activate(VOID  *cdc_instance);
98 static VOID                                test_cdc_instance_deactivate(VOID *cdc_instance);
99 static VOID                                test_cdc_instance_parameter_change(VOID *cdc_instance);
100 
101 /* Define global data structures.  */
102 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_control = UX_NULL;
103 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_data = UX_NULL;
104 
105 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_control1 = UX_NULL;
106 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_data1 = UX_NULL;
107 
108 static UX_SLAVE_CLASS_CDC_ACM              *cdc_acm_slave = UX_NULL;
109 
110 static UX_SLAVE_CLASS_CDC_ACM              *cdc_acm_slave1 = UX_NULL;
111 
112 static UCHAR                               cdc_acm_slave_change;
113 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER    parameter;
114 
115 static ULONG                               error_counter;
116 
117 static ULONG                               error_callback_counter;
118 static UCHAR                               error_callback_ignore;
119 
120 static ULONG                               call_counter;
121 
122 static UCHAR                               buffer[UX_DEMO_BUFFER_SIZE];
123 
124 static UCHAR                               test_slave_code = 0;
125 static UCHAR                               test_slave_state = 0;
126 
127 /* Define device framework.  */
128 
129 static unsigned char device_framework_full_speed[] = {
130 
131     /* Device descriptor     18 bytes
132        0x02 bDeviceClass:    CDC class code
133        0x00 bDeviceSubclass: CDC class sub code
134        0x00 bDeviceProtocol: CDC Device protocol
135 
136        idVendor & idProduct - http://www.linux-usb.org/usb.ids
137     */
138     0x12, 0x01, 0x10, 0x01,
139     0xEF, 0x02, 0x01,
140     0x08,
141     0x84, 0x84, 0x00, 0x00,
142     0x00, 0x01,
143     0x01, 0x02, 03,
144     0x01, /* bNumConfigurations */
145 
146     /* Configuration 1 descriptor 9 bytes, total 75 bytes */
147     CFG_DESC(CFG_DESC_LEN + (IAD_DESC_LEN + CDC_IFC_DESC_ALL_LEN) * 2, 4, 0x40, 1)
148     /* IAD 8 bytes */
149     IAD_DESC(0)
150     /* CDC_ACM interfaces */
151     CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
152     /* IAD 8 bytes */
153     IAD_DESC(2)
154     /* CDC_ACM interfaces */
155     CDC_IFC_DESC_ALL1(2, 0x86, 0x85, 0x04)
156 };
157 #define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      sizeof(device_framework_full_speed)
158 
159 static unsigned char device_framework_high_speed[] = {
160 
161     /* Device descriptor     18 bytes
162        0x02 bDeviceClass:    CDC class code
163        0x00 bDeviceSubclass: CDC class sub code
164        0x00 bDeviceProtocol: CDC Device protocol
165 
166        idVendor & idProduct - http://www.linux-usb.org/usb.ids
167     */
168     0x12, 0x01, 0x00, 0x02,
169     0xEF, 0x02, 0x01,
170     0x40,
171     0x84, 0x84, 0x00, 0x00,
172     0x00, 0x01,
173     0x01, 0x02, 03,
174     0x01, /* bNumConfigurations */
175 
176     /* Device qualifier descriptor 10 bytes */
177     0x0a, 0x06, 0x00, 0x02,
178     0x02, 0x00, 0x00,
179     0x40,
180     0x01,
181     0x00,
182 
183     /* Configuration 1 descriptor 9 bytes, total 75 bytes */
184     CFG_DESC(CFG_DESC_LEN + IAD_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 0x60, 1)
185     /* IAD 8 bytes */
186     IAD_DESC(0)
187     /* CDC_ACM interfaces */
188     CDC_IFC_DESC_ALL1(0, 0x83, 0x81, 0x02)
189     /* IAD 8 bytes */
190     IAD_DESC(2)
191     /* CDC_ACM interfaces */
192     CDC_IFC_DESC_ALL(2, 0x86, 0x85, 0x04)
193 };
194 #define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      sizeof(device_framework_high_speed)
195 
196 static unsigned char string_framework[] = {
197 
198     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
199     0x09, 0x04, 0x01, 0x0c,
200     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
201     0x6f, 0x67, 0x69, 0x63,
202 
203     /* Product string descriptor : Index 2 - "EL Composite device" */
204     0x09, 0x04, 0x02, 0x13,
205     0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
206     0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
207     0x69, 0x63, 0x65,
208 
209     /* Serial Number string descriptor : Index 3 - "0001" */
210     0x09, 0x04, 0x03, 0x04,
211     0x30, 0x30, 0x30, 0x31
212 };
213 #define             STRING_FRAMEWORK_LENGTH                 sizeof(string_framework)
214 
215 /* Multiple languages are supported on the device, to add
216     a language besides english, the unicode language code must
217     be appended to the language_id_framework array and the length
218     adjusted accordingly. */
219 static unsigned char language_id_framework[] = {
220 
221     /* English. */
222     0x09, 0x04
223 };
224 #define             LANGUAGE_ID_FRAMEWORK_LENGTH            sizeof(language_id_framework)
225 
226 /* Define the ISR dispatch.  */
227 
228 extern VOID    (*test_isr_dispatch)(void);
229 
230 
231 /* Prototype for test control return.  */
232 
233 void  test_control_return(UINT status);
234 
235 
236 /* Define the ISR dispatch routine.  */
237 
test_isr(void)238 static void    test_isr(void)
239 {
240 
241     /* For further expansion of interrupt-level testing.  */
242 }
243 
break_on_cdc_acm_all_ready(VOID)244 static UINT break_on_cdc_acm_all_ready(VOID)
245 {
246 
247     if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL)
248         /* Do not break. */
249         return 0;
250 
251     if (cdc_acm_host_control1 == UX_NULL || cdc_acm_host_data1 == UX_NULL)
252         /* Do not break. */
253         return 0;
254 
255     if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
256         /* Do not break. */
257         return 0;
258 
259     if (cdc_acm_host_data->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
260         /* Do not break. */
261         return 0;
262 
263     if (cdc_acm_host_control1->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
264         /* Do not break. */
265         return 0;
266 
267     if (cdc_acm_host_data1->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
268         /* Do not break. */
269         return 0;
270 
271     if (cdc_acm_slave == UX_NULL || cdc_acm_slave1 == UX_NULL)
272         /* Do not break. */
273         return 0;
274 
275     /* All found, break. */
276     return 1;
277 }
278 
break_on_removal(VOID)279 static UINT break_on_removal(VOID)
280 {
281 
282     if (cdc_acm_host_control != UX_NULL || cdc_acm_host_data != UX_NULL)
283         /* Do not break. */
284         return 0;
285 
286     if (cdc_acm_host_control1 != UX_NULL || cdc_acm_host_data1 != UX_NULL)
287         /* Do not break. */
288         return 0;
289 
290     if (cdc_acm_slave != UX_NULL || cdc_acm_slave1 != UX_NULL)
291         /* Do not break. */
292         return 0;
293 
294     return 1;
295 }
296 
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)297 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
298 {
299 
300 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
301 
302     switch(event)
303     {
304 
305         case UX_DEVICE_INSERTION:
306 
307             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
308             {
309                 if (cdc_acm_host_control == UX_NULL)
310                     cdc_acm_host_control = cdc_acm;
311                 else
312                     if (cdc_acm_host_control1 == UX_NULL)
313                         cdc_acm_host_control1 = cdc_acm;
314             }
315             else
316             {
317                 if (cdc_acm_host_data == UX_NULL)
318                     cdc_acm_host_data = cdc_acm;
319                 else
320                     if (cdc_acm_host_data1 == UX_NULL)
321                         cdc_acm_host_data1 = cdc_acm;
322             }
323             break;
324 
325         case UX_DEVICE_REMOVAL:
326 
327             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
328             {
329                 if (cdc_acm_host_control == cdc_acm)
330                     cdc_acm_host_control = UX_NULL;
331                 if (cdc_acm_host_control1 == cdc_acm)
332                     cdc_acm_host_control1 = UX_NULL;
333             }
334             else
335             {
336                 if (cdc_acm_host_data == cdc_acm)
337                     cdc_acm_host_data = UX_NULL;
338                 if (cdc_acm_host_data1 == cdc_acm)
339                     cdc_acm_host_data1 = UX_NULL;
340             }
341             break;
342 
343         default:
344             break;
345     }
346     return 0;
347 }
348 
test_cdc_instance_activate(VOID * cdc_instance)349 static VOID    test_cdc_instance_activate(VOID *cdc_instance)
350 {
351 
352     /* Save the CDC instance.  */
353     if (cdc_acm_slave == UX_NULL)
354         cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
355     else
356     if (cdc_acm_slave1 == UX_NULL)
357         cdc_acm_slave1 =  (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
358 }
test_cdc_instance_deactivate(VOID * cdc_instance)359 static VOID    test_cdc_instance_deactivate(VOID *cdc_instance)
360 {
361 
362     /* Reset the CDC instance.  */
363     if ((VOID *)cdc_acm_slave == cdc_instance)
364         cdc_acm_slave = UX_NULL;
365     if ((VOID *)cdc_acm_slave1 == cdc_instance)
366         cdc_acm_slave1 = UX_NULL;
367 }
368 
test_cdc_instance_parameter_change(VOID * cdc_instance)369 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
370 {
371 
372     /* Set CDC parameter change flag. */
373     cdc_acm_slave_change = UX_TRUE;
374 }
375 
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)376 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
377 {
378     error_callback_counter ++;
379 
380     if (!error_callback_ignore)
381     {
382         /* Ignore UX_DEVICE_HANDLE_UNKNOWN.  */
383         if (UX_DEVICE_HANDLE_UNKNOWN == error_code)
384             return;
385         {
386             /* Failed test.  */
387             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
388             // test_control_return(1);
389         }
390     }
391 }
392 
393 /* Define what the initial system looks like.  */
394 
395 #ifdef CTEST
test_application_define(void * first_unused_memory)396 void test_application_define(void *first_unused_memory)
397 #else
398 void usbx_ux_device_class_cdc_acm_ioctl_test_application_define(void *first_unused_memory)
399 #endif
400 {
401 
402 UINT                    status;
403 CHAR *                  stack_pointer;
404 CHAR *                  memory_pointer;
405 
406     printf("Running ux_device_class_cdc_acm_ioctl Test.......................... ");
407 
408     /* Initialize the free memory pointer */
409     stack_pointer = (CHAR *) first_unused_memory;
410     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
411 
412     /* Initialize USBX Memory */
413     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
414     /* Check for error.  */
415     if (status != UX_SUCCESS)
416     {
417 
418         printf("ERROR #%d\n", __LINE__);
419         test_control_return(1);
420     }
421 
422     /* Register the error callback. */
423     _ux_utility_error_callback_register(test_ux_error_callback);
424 
425     /* The code below is required for installing the host portion of USBX */
426     status =  ux_host_stack_initialize(test_host_change_function);
427     if (status != UX_SUCCESS)
428     {
429 
430         printf("ERROR #%d\n", __LINE__);
431         test_control_return(1);
432     }
433 
434     /* Register CDC ACM class */
435     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
436     if (status != UX_SUCCESS)
437     {
438 
439         printf("ERROR #%d\n", __LINE__);
440         test_control_return(1);
441     }
442 
443     /* The code below is required for installing the device portion of USBX. No call back for
444        device status change in this example. */
445     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
446                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
447                                        string_framework, STRING_FRAMEWORK_LENGTH,
448                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
449     if(status!=UX_SUCCESS)
450     {
451 
452         printf("ERROR #%d\n", __LINE__);
453         test_control_return(1);
454     }
455 
456     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
457     parameter.ux_slave_class_cdc_acm_instance_activate   =  test_cdc_instance_activate;
458     parameter.ux_slave_class_cdc_acm_instance_deactivate =  test_cdc_instance_deactivate;
459     parameter.ux_slave_class_cdc_acm_parameter_change    =  test_cdc_instance_parameter_change;
460 
461     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
462     status  =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
463                                              1,0,  &parameter);
464     status |=  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
465                                              1,2,  &parameter);
466     status |=  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
467                                              1,4,  &parameter);
468 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
469     if(status!=UX_SUCCESS)
470     {
471 
472         printf("ERROR #%d\n", __LINE__);
473         test_control_return(1);
474     }
475 #else
476     error_callback_ignore = UX_TRUE; /* One of interface fail.  */
477 #endif
478     /* Initialize the simulated device controller.  */
479     status =  _ux_test_dcd_sim_slave_initialize();
480 
481     /* Check for error.  */
482     if (status != TX_SUCCESS)
483     {
484 
485         printf("ERROR #%d\n", __LINE__);
486         test_control_return(1);
487     }
488 
489     /* Register HCD for test */
490     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
491     if (status != UX_SUCCESS)
492     {
493 
494         printf("ERROR #%d\n", __LINE__);
495         test_control_return(1);
496     }
497 
498     /* Create the main host simulation thread.  */
499     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_thread_host_simulation_entry, 0,
500             stack_pointer, UX_DEMO_STACK_SIZE,
501             20, 20, 1, TX_AUTO_START);
502 
503     /* Check for error.  */
504     if (status != TX_SUCCESS)
505     {
506 
507         printf("ERROR #%d\n", __LINE__);
508         test_control_return(1);
509     }
510 
511     /* Create the main slave simulation  thread.  */
512     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
513             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
514             20, 20, 1, TX_DONT_START);
515 
516     /* Check for error.  */
517     if (status != TX_SUCCESS)
518     {
519 
520         printf("ERROR #%d\n", __LINE__);
521         test_control_return(1);
522     }
523 }
524 
tx_test_thread_host_simulation_entry(ULONG arg)525 void  tx_test_thread_host_simulation_entry(ULONG arg)
526 {
527 
528 UINT                                                status;
529 UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER         line_state;
530 UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER         new_line_state;
531 UX_SLAVE_CLASS_CDC_ACM                              *slaves[2];
532 UINT                                                i;
533 
534     stepinfo("\n");
535 
536     /* Test connect. */
537     stepinfo(">>>>>>>>>>>>>>>> Test connect (FS)\n");
538     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
539     ux_test_breakable_sleep(500, break_on_cdc_acm_all_ready);
540     if (!(cdc_acm_host_control
541             && cdc_acm_host_data
542             && cdc_acm_slave
543 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
544             && cdc_acm_host_control1
545             && cdc_acm_host_data1
546             && cdc_acm_slave1
547 #endif
548             ))
549     {
550 
551         printf("ERROR #%d: connect fail\n", __LINE__);
552         test_control_return(1);
553     }
554 
555     stepinfo(">>>>>>>>>>>>>>>> Test UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE\n");
556 
557     status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE, &line_state);
558     if (status != UX_SUCCESS)
559     {
560         printf("ERROR #%d: ioctl_get_line_state error 0x%x\n", __LINE__, status);
561         error_counter ++;
562     }
563 
564     new_line_state.ux_slave_class_cdc_acm_parameter_dtr = !line_state.ux_slave_class_cdc_acm_parameter_dtr;
565     new_line_state.ux_slave_class_cdc_acm_parameter_rts = !line_state.ux_slave_class_cdc_acm_parameter_rts;
566 
567     status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE, &new_line_state);
568     if (status != UX_SUCCESS)
569     {
570         printf("ERROR #%d: ioctl_set_line_state error 0x%x\n", __LINE__, status);
571         error_counter ++;
572     }
573 
574     status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE, &line_state);
575     if (status != UX_SUCCESS)
576     {
577         printf("ERROR #%d: ioctl_get_line_state error 0x%x\n", __LINE__, status);
578         error_counter ++;
579     }
580     if (line_state.ux_slave_class_cdc_acm_parameter_dtr != new_line_state.ux_slave_class_cdc_acm_parameter_dtr)
581     {
582         printf("ERROR #%d: dtr error\n", __LINE__);
583         error_counter ++;
584     }
585     if (line_state.ux_slave_class_cdc_acm_parameter_rts != new_line_state.ux_slave_class_cdc_acm_parameter_rts)
586     {
587         printf("ERROR #%d: rts error\n", __LINE__);
588         error_counter ++;
589     }
590 
591     slaves[0] = cdc_acm_slave;
592     slaves[1] = cdc_acm_slave1;
593 
594     stepinfo(">>>>>>>>>>>>>>>> Test UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE no pending transfer\n");
595     for (i = 0; i < 2; i ++)
596     {
597         status  = ux_device_class_cdc_acm_ioctl(slaves[i], UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE, (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT);
598         status |= ux_device_class_cdc_acm_ioctl(slaves[i], UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE, (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV);
599         if (status != UX_SUCCESS)
600         {
601             printf("ERROR #%d: abort fail 0x%x\n", __LINE__, status);
602             error_counter ++;
603         }
604 
605         status  = ux_device_class_cdc_acm_ioctl(slaves[i], UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE, (VOID*)0xFF);
606         if (status != UX_ENDPOINT_HANDLE_UNKNOWN)
607         {
608             printf("ERROR #%d: abort code not expected 0x%x\n", __LINE__, status);
609             error_counter ++;
610         }
611     }
612 
613     stepinfo(">>>>>>>>>>>>>>>> Test UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE pending transfer\n");
614 
615     /* Start read on another thread.  */
616     test_slave_code = 1;
617     tx_thread_resume(&tx_test_thread_slave_simulation);
618     for (i = 0; i < 20; i ++)
619     {
620         if (test_slave_state)
621             break;
622         _ux_utility_delay_ms(5);
623     }
624     if (test_slave_state)
625     {
626         status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE, (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV);
627         if (status != UX_SUCCESS)
628         {
629             printf("ERROR #%d: abort fail 0x%x\n", __LINE__, status);
630             error_counter ++;
631         }
632         for (i = 0; i < 20; i ++)
633         {
634             if (test_slave_state == 0)
635                 break;
636             _ux_utility_delay_ms(5);
637         }
638         if (test_slave_state != 0)
639         {
640             printf("ERROR #%d: read not aborted\n", __LINE__);
641             error_counter ++;
642         }
643     }
644     else
645     {
646         printf("ERROR #%d: read not started\n", __LINE__);
647         error_counter ++;
648     }
649 #if 0 /* TODO: USBX-177 */
650     /* Start write on another thread.  */
651     test_slave_code = 2;
652     tx_thread_resume(&tx_test_thread_slave_simulation);
653     for (i = 0; i < 20; i ++)
654     {
655         if (test_slave_state)
656             break;
657         _ux_utility_delay_ms(5);
658     }
659     if (test_slave_state)
660     {
661         status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE, (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT);
662         if (status != UX_SUCCESS)
663         {
664             printf("ERROR #%d: abort fail 0x%x\n", __LINE__, status);
665             error_counter ++;
666         }
667         for (i = 0; i < 20; i ++)
668         {
669             if (test_slave_state == 0)
670                 break;
671             _ux_utility_delay_ms(5);
672         }
673         if (test_slave_state != 0)
674         {
675             printf("ERROR #%d: write not aborted\n", __LINE__);
676             error_counter ++;
677         }
678     }
679     else
680     {
681         printf("ERROR #%d: write not started\n", __LINE__);
682         error_counter ++;
683     }
684 #endif
685     stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
686     ux_test_dcd_sim_slave_disconnect();
687     ux_test_hcd_sim_host_disconnect();
688 
689     ux_test_breakable_sleep(100, break_on_removal);
690 
691     if (cdc_acm_host_control || cdc_acm_host_data || cdc_acm_slave)
692     {
693 
694         printf("ERROR #%d: disconnect fail\n", __LINE__);
695         test_control_return(1);
696     }
697 
698     stepinfo(">>>>>>>>>>>>>>>> Deinitialize\n");
699 
700     /* Deinitialize the class.  */
701     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
702     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
703     ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
704 
705     /* Deinitialize the device side of usbx.  */
706     _ux_device_stack_uninitialize();
707 
708     /* And finally the usbx system resources.  */
709     _ux_system_uninitialize();
710 
711     stepinfo(">>>>>>>>>>>>>>>> Dump results\n");
712 
713     if (error_counter > 0)
714     {
715 
716         /* Test error.  */
717         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
718         test_control_return(1);
719     }
720 
721     /* Successful test.  */
722     printf("SUCCESS!\n");
723     test_control_return(0);
724 }
725 
tx_test_thread_slave_simulation_entry(ULONG arg)726 void  tx_test_thread_slave_simulation_entry(ULONG arg)
727 {
728 UINT  status;
729 ULONG actual_length;
730 
731     while(1)
732     {
733         switch (test_slave_code)
734         {
735         case 1:
736             stepinfo(">>>>>>>>>>>>>>>> Slave read START\n");
737             test_slave_state ++;
738             status = ux_device_class_cdc_acm_read(cdc_acm_slave, buffer, 256, &actual_length);
739             stepinfo(">>>>>>>>>>>>>>>> Slave read END\n");
740             if (status != UX_ABORTED)
741             {
742                 printf("ERROR #%d: read not abort 0x%x\n", __LINE__, status);
743                 error_counter ++;
744             }
745             break;
746         case 2:
747             stepinfo(">>>>>>>>>>>>>>>> Slave write START\n");
748             test_slave_state ++;
749             status = ux_device_class_cdc_acm_write(cdc_acm_slave, buffer, 1024, &actual_length);
750             stepinfo(">>>>>>>>>>>>>>>> Slave write END\n");
751             if (status != UX_ABORTED)
752             {
753                 printf("ERROR #%d: write not abort 0x%x\n", __LINE__, status);
754                 error_counter ++;
755             }
756             break;
757         default:
758             break;
759         }
760         test_slave_state = 0;
761         tx_thread_suspend(&tx_test_thread_slave_simulation);
762     }
763 }
764