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