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