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 "ux_device_class_cdc_acm.h"
10 #include "ux_host_class_cdc_acm.h"
11 
12 #include "ux_device_stack.h"
13 #include "ux_host_stack.h"
14 
15 #include "ux_test_hcd_sim_host.h"
16 #include "ux_test_utility_sim.h"
17 
18 /* Define USBX demo constants.  */
19 
20 #define UX_DEMO_STACK_SIZE      4096
21 #define UX_DEMO_BUFFER_SIZE     2048
22 #define UX_DEMO_RUN             1
23 #define UX_DEMO_MEMORY_SIZE     (64*1024)
24 
25 #define     LSB(x) (x & 0x00ff)
26 #define     MSB(x) ((x & 0xff00) >> 8)
27 
28 /* CDC IAD 8 bytes */
29 #define CDC_IAD_DESC(comm_ifc) \
30     /* Interface association descriptor. 8 bytes.  */\
31     0x08, 0x0b, (comm_ifc), 0x02, 0x02, 0x02, 0x00, 0x00,
32 #define CDC_IAD_DESC_LEN 8
33 
34 /* CDC Communication interface descriptors 9+5+4+5+5+7=35 bytes */
35 #define CDC_COMM_IFC_DESC_ALL(comm_ifc, data_ifc, interrupt_epa) \
36     /* Communication Class Interface Descriptor. 9 bytes. */\
37     0x09, 0x04, (comm_ifc), 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,\
38     /* Header Functional Descriptor 5 bytes */\
39     0x05, 0x24, 0x00, 0x10, 0x01,\
40     /* ACM Functional Descriptor 4 bytes */\
41     0x04, 0x24, 0x02, 0x0f,\
42     /* Union Functional Descriptor 5 bytes */\
43     0x05, 0x24, 0x06,\
44     (comm_ifc),                          /* Master interface */\
45     (data_ifc),                          /* Slave interface  */\
46     /* Call Management Functional Descriptor 5 bytes */\
47     0x05, 0x24, 0x01, 0x03,\
48     (data_ifc),                          /* Data interface   */\
49     /* Endpoint 0x83 descriptor 7 bytes */\
50     0x07, 0x05, (interrupt_epa),\
51     0x03,\
52     0x08, 0x00,\
53     0xFF,
54 #define CDC_COMM_IFC_DESC_ALL_LEN 35
55 
56 /* CDC Data interface descriptors 9+7+7=23 bytes */
57 #define CDC_DATA_IFC_DESC_ALL(ifc, bulk_in_epa, bulk_out_epa) \
58     /* Data Class Interface Descriptor Requirement 9 bytes */\
59     0x09, 0x04, (ifc),\
60     0x00, /* bAlternateSetting */\
61     0x02, /* bNumEndpoints */\
62     0x0A, 0x00, 0x00,\
63     0x00,\
64     /* Endpoint bulk IN descriptor 7 bytes */\
65     0x07, 0x05, (bulk_in_epa),\
66     0x02,\
67     0x40, 0x00,\
68     0x00,\
69     /* Endpoint bulk OUT descriptor 7 bytes */\
70     0x07, 0x05, (bulk_out_epa),\
71     0x02,\
72     0x40, 0x00,\
73     0x00,
74 #define CDC_DATA_IFC_DESC_ALL_LEN 23
75 
76 /* Configuration descriptor 9 bytes */
77 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
78     /* Configuration 1 descriptor 9 bytes */\
79     0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
80     (bNumInterfaces), (bConfigurationValue), 0x00,\
81     0x40, 0x00,
82 #define CFG_DESC_LEN 9
83 
84 /* Define the counters used in the demo application...  */
85 
86 static ULONG                           test_error_cases = UX_FALSE;
87 static ULONG                           test_error_counter;
88 
89 static ULONG                           thread_0_counter;
90 static ULONG                           thread_1_counter;
91 static ULONG                           error_counter;
92 
93 /* Define USBX demo global variables.  */
94 
95 static UX_HOST_CLASS                   *class_driver;
96 static UX_HOST_CLASS_CDC_ACM           *cdc_acm_host_control;
97 static UX_HOST_CLASS_CDC_ACM           *cdc_acm_host_data;
98 static UX_SLAVE_CLASS_CDC_ACM          *cdc_acm_slave;
99 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER cdc_acm_parameter;
100 
101 static UCHAR                           detect_insertion;
102 static UCHAR                           detect_extraction;
103 
104 
105 static UCHAR device_framework_full_speed[] = {
106 
107     /* Device descriptor     18 bytes
108        0x02 bDeviceClass:    CDC class code
109        0x00 bDeviceSubclass: CDC class sub code
110        0x00 bDeviceProtocol: CDC Device protocol
111 
112        idVendor & idProduct - http://www.linux-usb.org/usb.ids
113     */
114     0x12, 0x01, 0x10, 0x01,
115     0xEF, 0x02, 0x01,
116     0x08,
117     0x84, 0x84, 0x00, 0x00,
118     0x00, 0x01,
119     0x01, 0x02, 03,
120     0x03,
121 
122     /* Configuration 1 descriptor 9 bytes */
123     0x09, 0x02, 0x4b, 0x00,
124     0x02, 0x01, 0x00,
125     0x40, 0x00,
126 
127     /* Interface association descriptor. 8 bytes.  */
128     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
129 
130     /* Communication Class Interface Descriptor Requirement. 9 bytes.   */
131     0x09, 0x04, 0x00,
132     0x00,
133     0x01,
134     0x02, 0x02, 0x01,
135     0x00,
136 
137     /* Header Functional Descriptor 5 bytes */
138     0x05, 0x24, 0x00,
139     0x10, 0x01,
140 
141     /* ACM Functional Descriptor 4 bytes */
142     0x04, 0x24, 0x02,
143     0x0f,
144 
145     /* Union Functional Descriptor 5 bytes */
146     0x05, 0x24, 0x06,
147     0x00,                          /* Master interface */
148     0x01,                          /* Slave interface  */
149 
150     /* Call Management Functional Descriptor 5 bytes */
151     0x05, 0x24, 0x01,
152     0x03,
153     0x01,                          /* Data interface   */
154 
155     /* Endpoint 0x83 descriptor 7 bytes */
156     0x07, 0x05, 0x83,
157     0x03,
158     0x08, 0x00,
159     0xFF,
160 
161     /* Data Class Interface Descriptor Requirement 9 bytes */
162     0x09, 0x04, 0x01,
163     0x00,
164     0x02,
165     0x0A, 0x00, 0x00,
166     0x00,
167 
168     /* Endpoint 0x02 descriptor 7 bytes */
169     0x07, 0x05, 0x02, /* @ 93 - 14 + 2 = 81 */
170     0x02,
171     0x40, 0x00,
172     0x00,
173 
174     /* Endpoint 0x81 descriptor 7 bytes */
175     0x07, 0x05, 0x81, /* @ 93 - 7 + 2 = 88 */
176     0x02,
177     0x40, 0x00,
178     0x00,
179 
180     /* Configuration 2: CDC */
181     CFG_DESC(CFG_DESC_LEN+(CDC_IAD_DESC_LEN+CDC_COMM_IFC_DESC_ALL_LEN+CDC_DATA_IFC_DESC_ALL_LEN), 2, 2)
182     CDC_IAD_DESC(0)
183     CDC_COMM_IFC_DESC_ALL(0, 1, 0x83)
184     CDC_DATA_IFC_DESC_ALL(1, 0x81, 0x02)
185 
186     /* Configuration 3: CDC */
187     CFG_DESC(CFG_DESC_LEN+(CDC_IAD_DESC_LEN+CDC_COMM_IFC_DESC_ALL_LEN+CDC_DATA_IFC_DESC_ALL_LEN), 3, 2)
188     CDC_IAD_DESC(0)
189     CDC_COMM_IFC_DESC_ALL(0, 1, 0x83)
190     CDC_DATA_IFC_DESC_ALL(1, 0x81, 0x02)
191 };
192 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
193 
194 
195 static UCHAR device_framework_high_speed[] = {
196 
197     /* Device descriptor
198        0x02 bDeviceClass:    CDC class code
199        0x00 bDeviceSubclass: CDC class sub code
200        0x00 bDeviceProtocol: CDC Device protocol
201 
202        idVendor & idProduct - http://www.linux-usb.org/usb.ids
203     */
204     0x12, 0x01, 0x00, 0x02,
205     0xEF, 0x02, 0x01,
206     0x40,
207     0x84, 0x84, 0x00, 0x00,
208     0x00, 0x01,
209     0x01, 0x02, 03,
210     0x01,
211 
212     /* Device qualifier descriptor */
213     0x0a, 0x06, 0x00, 0x02,
214     0x02, 0x00, 0x00,
215     0x40,
216     0x01,
217     0x00,
218 
219     /* Configuration 1 descriptor */
220     0x09, 0x02, 0x4b, 0x00,
221     0x02, 0x01, 0x00,
222     0x40, 0x00,
223 
224     /* Interface association descriptor. */
225     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
226 
227     /* Communication Class Interface Descriptor Requirement */
228     0x09, 0x04, 0x00,
229     0x00,
230     0x01,
231     0x02, 0x02, 0x01,
232     0x00,
233 
234     /* Header Functional Descriptor */
235     0x05, 0x24, 0x00,
236     0x10, 0x01,
237 
238     /* ACM Functional Descriptor */
239     0x04, 0x24, 0x02,
240     0x0f,
241 
242     /* Union Functional Descriptor */
243     0x05, 0x24, 0x06,
244     0x00,
245     0x01,
246 
247     /* Call Management Functional Descriptor */
248     0x05, 0x24, 0x01,
249     0x00,
250     0x01,
251 
252     /* Endpoint 0x83 descriptor */
253     0x07, 0x05, 0x83,
254     0x03,
255     0x08, 0x00,
256     0xFF,
257 
258     /* Data Class Interface Descriptor Requirement */
259     0x09, 0x04, 0x01,
260     0x00,
261     0x02,
262     0x0A, 0x00, 0x00,
263     0x00,
264 
265     /* Endpoint 0x02 descriptor */
266     0x07, 0x05, 0x02, /* @ 103 - 14 + 2 = 91 */
267     0x02,
268     0x40, 0x00,
269     0x00,
270 
271     /* Endpoint 0x81 descriptor */
272     0x07, 0x05, 0x81, /* @ 103 - 7 + 2 = 98 */
273     0x02,
274     0x40, 0x00,
275     0x00,
276 
277     /* Configuration 2: CDC */
278     CFG_DESC(CFG_DESC_LEN+(CDC_IAD_DESC_LEN+CDC_COMM_IFC_DESC_ALL_LEN+CDC_DATA_IFC_DESC_ALL_LEN), 2, 2)
279     CDC_IAD_DESC(0)
280     CDC_COMM_IFC_DESC_ALL(0, 1, 0x83)
281     CDC_DATA_IFC_DESC_ALL(1, 0x81, 0x02)
282 
283     /* Configuration 3: CDC */
284     CFG_DESC(CFG_DESC_LEN+(CDC_IAD_DESC_LEN+CDC_COMM_IFC_DESC_ALL_LEN+CDC_DATA_IFC_DESC_ALL_LEN), 3, 2)
285     CDC_IAD_DESC(0)
286     CDC_COMM_IFC_DESC_ALL(0, 1, 0x83)
287     CDC_DATA_IFC_DESC_ALL(1, 0x81, 0x02)
288 };
289 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
290 
291 /* String Device Framework :
292     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
293     Byte 2       : Byte containing the index of the descriptor
294     Byte 3       : Byte containing the length of the descriptor string
295 */
296 static UCHAR string_framework[] = {
297 
298     /* Manufacturer string descriptor : Index 1 */
299     0x09, 0x04, 0x01, 0x0c,
300     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
301     0x6f, 0x67, 0x69, 0x63,
302 
303     /* Product string descriptor : Index 2 */
304     0x09, 0x04, 0x02, 0x0c,
305     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
306     0x44, 0x65, 0x6d, 0x6f,
307 
308     /* Serial Number string descriptor : Index 3 */
309     0x09, 0x04, 0x03, 0x04,
310     0x30, 0x30, 0x30, 0x31
311 };
312 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
313 
314 /* Multiple languages are supported on the device, to add
315     a language besides English, the unicode language code must
316     be appended to the language_id_framework array and the length
317     adjusted accordingly. */
318 static UCHAR language_id_framework[] = {
319 
320     /* English. */
321     0x09, 0x04
322 };
323 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
324 
325 
326 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
327 
328 static VOID                test_cdc_instance_activate(VOID  *cdc_instance);
329 static VOID                test_cdc_instance_deactivate(VOID *cdc_instance);
330 
331 static UINT                test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst);
332 
333 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
334 
335 static TX_THREAD           tx_test_thread_host_simulation;
336 static TX_THREAD           tx_test_thread_slave_simulation;
337 static void                tx_test_thread_host_simulation_entry(ULONG);
338 static void                tx_test_thread_slave_simulation_entry(ULONG);
339 
340 /* Define the ISR dispatch.  */
341 
342 extern VOID    (*test_isr_dispatch)(void);
343 
344 
345 /* Prototype for test control return.  */
346 
347 void  test_control_return(UINT status);
348 
349 
350 /* Define the ISR dispatch routine.  */
351 
test_isr(void)352 static void    test_isr(void)
353 {
354 
355     /* For further expansion of interrupt-level testing.  */
356 }
357 
358 
error_callback(UINT system_level,UINT system_context,UINT error_code)359 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
360 {
361     test_error_counter ++;
362 
363     /* Failed test.  */
364     if (!test_error_cases)
365     {
366 
367         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
368         test_control_return(1);
369     }
370 }
371 
372 /* Define what the initial system looks like.  */
373 
374 #ifdef CTEST
test_application_define(void * first_unused_memory)375 void test_application_define(void *first_unused_memory)
376 #else
377 void    usbx_ux_host_stack_new_configuration_create_test_application_define(void *first_unused_memory)
378 #endif
379 {
380 
381 UINT status;
382 CHAR                            *stack_pointer;
383 CHAR                            *memory_pointer;
384 
385 
386     /* Initialize the free memory pointer.  */
387     stack_pointer = (CHAR *) first_unused_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 
393     /* Check for error.  */
394     if (status != UX_SUCCESS)
395     {
396 
397         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #1\n");
398         test_control_return(1);
399     }
400 
401     /* Register the error callback. */
402     _ux_utility_error_callback_register(error_callback);
403 
404     /* The code below is required for installing the host portion of USBX.  */
405     status =  ux_host_stack_initialize(test_host_change_function);
406 
407     /* Check for error.  */
408     if (status != UX_SUCCESS)
409     {
410 
411         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #2\n");
412         test_control_return(1);
413     }
414 
415     /* Register CDC-ACM class.  */
416     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
417 
418     /* Check for error.  */
419     if (status != UX_SUCCESS)
420     {
421 
422         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #3\n");
423         test_control_return(1);
424     }
425 
426     /* The code below is required for installing the device portion of USBX */
427     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
428                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
429                                        string_framework, STRING_FRAMEWORK_LENGTH,
430                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
431 
432     /* Check for error.  */
433     if (status != UX_SUCCESS)
434     {
435 
436         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #5\n");
437         test_control_return(1);
438     }
439 
440     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
441     cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate   =  test_cdc_instance_activate;
442     cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate =  test_cdc_instance_deactivate;
443     cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change    =  UX_NULL;
444 
445     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
446     status =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
447                                              1,0,  &cdc_acm_parameter);
448 
449     /* Check for error.  */
450     if (status != UX_SUCCESS)
451     {
452 
453         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #6\n");
454         test_control_return(1);
455     }
456 
457     /* Initialize the simulated device controller.  */
458     status =  _ux_dcd_sim_slave_initialize();
459 
460     /* Check for error.  */
461     if (status != UX_SUCCESS)
462     {
463 
464         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #7\n");
465         test_control_return(1);
466     }
467 
468     /* Register all the USB host controllers available in this system */
469     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
470 
471     /* Check for error.  */
472     if (status != UX_SUCCESS)
473     {
474 
475         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #4\n");
476         test_control_return(1);
477     }
478 
479     /* Create the main host simulation thread.  */
480     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_thread_host_simulation_entry, 0,
481             stack_pointer, UX_DEMO_STACK_SIZE,
482             20, 20, 1, TX_AUTO_START);
483 
484     /* Check for error.  */
485     if (status != TX_SUCCESS)
486     {
487 
488         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #8\n");
489         test_control_return(1);
490     }
491 
492     /* Create the main demo thread.  */
493     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_thread_slave_simulation_entry, 0,
494             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
495             20, 20, 1, TX_AUTO_START);
496 
497     /* Check for error.  */
498     if (status != TX_SUCCESS)
499     {
500 
501         printf("Running ux_host_stack_new_configuration_create Test................. ERROR #9\n");
502         test_control_return(1);
503     }
504 }
505 
506 
tx_test_thread_host_simulation_entry(ULONG arg)507 static void  tx_test_thread_host_simulation_entry(ULONG arg)
508 {
509 
510 UINT             status;
511 UX_DEVICE       *device;
512 
513     /* Inform user.  */
514     printf("Running ux_host_stack_new_configuration_create Test................. ");
515 
516     /* Wait connect. */
517     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
518     tx_thread_sleep(100);
519     if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL || cdc_acm_slave == UX_NULL)
520     {
521 
522         printf("ERROR #%d: connection not detected\n", __LINE__);
523         test_control_return(1);
524     }
525 
526     status = ux_host_stack_device_get(0, &device);
527     if (status != UX_SUCCESS)
528     {
529 
530         printf("ERROR #%d: fail to get device instance\n", __LINE__);
531         test_control_return(1);
532     }
533 
534     /* No other simulation. */
535 
536 
537     /* Sleep for a tick to make sure everything is complete.  */
538     tx_thread_sleep(1);
539 
540     /* Check for errors from other threads.  */
541     if (error_counter)
542     {
543 
544         /* DPUMP error.  */
545         printf("ERROR #14\n");
546         test_control_return(1);
547     }
548     else
549     {
550 
551         /* Successful test.  */
552         printf("SUCCESS!\n");
553         test_control_return(0);
554     }
555 }
556 
557 
tx_test_thread_slave_simulation_entry(ULONG arg)558 static void  tx_test_thread_slave_simulation_entry(ULONG arg)
559 {
560 
561     while(1)
562     {
563 
564         /* Ensure the dpump class on the device is still alive.  */
565         if (cdc_acm_slave != UX_NULL)
566         {
567 
568             /* Increment thread counter.  */
569             thread_1_counter++;
570         }
571 
572         /* Let other thread run.  */
573         tx_thread_sleep(10);
574     }
575 }
576 
test_cdc_instance_activate(VOID * cdc_instance)577 static VOID  test_cdc_instance_activate(VOID *cdc_instance)
578 {
579 
580     /* Save the CDC instance.  */
581     cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
582 }
583 
test_cdc_instance_deactivate(VOID * cdc_instance)584 static VOID  test_cdc_instance_deactivate(VOID *cdc_instance)
585 {
586 
587     /* Reset the CDC instance.  */
588     cdc_acm_slave = UX_NULL;
589 }
590 
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)591 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
592 {
593 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
594 
595     switch(event)
596     {
597 
598         case UX_DEVICE_INSERTION:
599 
600             detect_insertion = UX_TRUE;
601 
602             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
603                 cdc_acm_host_control = cdc_acm;
604             else
605                 cdc_acm_host_data = cdc_acm;
606             break;
607 
608         case UX_DEVICE_REMOVAL:
609 
610             detect_extraction = UX_TRUE;
611 
612             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
613                 cdc_acm_host_control = UX_NULL;
614             else
615                 cdc_acm_host_data = UX_NULL;
616             break;
617 
618         default:
619             break;
620     }
621     return UX_SUCCESS;
622 }