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 }