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, 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_ALL_LEN (9+5+4+5+5+7+ 9+7+7)
70
71 /* Define local/extern function prototypes. */
72 static VOID test_thread_entry(ULONG);
73 static TX_THREAD tx_test_thread_simulation_0;
74 static TX_THREAD tx_test_thread_simulation_1;
75 static VOID tx_test_thread_simulation_0_entry(ULONG);
76 static VOID tx_test_thread_simulation_1_entry(ULONG);
77 static VOID test_cdc_instance_activate(VOID *cdc_instance);
78 static VOID test_cdc_instance_deactivate(VOID *cdc_instance);
79 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance);
80
81 /* Define global data structures. */
82 static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
83 static UX_HOST_CLASS *class_driver;
84 static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_control;
85 static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_data;
86
87 static UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
88 static UCHAR cdc_acm_slave_change;
89 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
90
91 static ULONG error_counter;
92
93 static ULONG error_callback_counter;
94 static UCHAR error_callback_ignore;
95
96 static UCHAR buffer[UX_DEMO_BUFFER_SIZE];
97
98 static ULONG test_thread_action;
99
100 /* Define device framework. */
101
102 static unsigned char device_framework_full_speed[] = {
103
104 /* Device descriptor 18 bytes
105 0x02 bDeviceClass: CDC class code
106 0x00 bDeviceSubclass: CDC class sub code
107 0x00 bDeviceProtocol: CDC Device protocol
108
109 idVendor & idProduct - http://www.linux-usb.org/usb.ids
110 */
111 0x12, 0x01, 0x10, 0x01,
112 0xEF, 0x02, 0x01,
113 0x08,
114 0x84, 0x84, 0x00, 0x00,
115 0x00, 0x01,
116 0x01, 0x02, 03,
117 0x01, /* bNumConfigurations */
118
119 /* Configuration 1 descriptor 9 bytes, total 75 bytes */
120 CFG_DESC(CFG_DESC_LEN + IAD_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 0x40, 1)
121 /* IAD 8 bytes */
122 IAD_DESC(0)
123 /* CDC_ACM interfaces */
124 CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
125 };
126 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
127
128 static unsigned char device_framework_high_speed[] = {
129
130 /* Device descriptor 18 bytes
131 0x02 bDeviceClass: CDC class code
132 0x00 bDeviceSubclass: CDC class sub code
133 0x00 bDeviceProtocol: CDC Device protocol
134
135 idVendor & idProduct - http://www.linux-usb.org/usb.ids
136 */
137 0x12, 0x01, 0x00, 0x02,
138 0xEF, 0x02, 0x01,
139 0x40,
140 0x84, 0x84, 0x00, 0x00,
141 0x00, 0x01,
142 0x01, 0x02, 03,
143 0x01, /* bNumConfigurations */
144
145 /* Device qualifier descriptor 10 bytes */
146 0x0a, 0x06, 0x00, 0x02,
147 0x02, 0x00, 0x00,
148 0x40,
149 0x01,
150 0x00,
151
152 /* Configuration 1 descriptor 9 bytes, total 75-8=67 bytes */
153 CFG_DESC(CFG_DESC_LEN + CDC_IFC_DESC_ALL_LEN, 2, 0x60, 1)
154 CDC_IFC_DESC_ALL(0, 0x83, 0x81, 0x02)
155 };
156 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
157
158 static unsigned char string_framework[] = {
159
160 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
161 0x09, 0x04, 0x01, 0x0c,
162 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
163 0x6f, 0x67, 0x69, 0x63,
164
165 /* Product string descriptor : Index 2 - "EL Composite device" */
166 0x09, 0x04, 0x02, 0x13,
167 0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
168 0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
169 0x69, 0x63, 0x65,
170
171 /* Serial Number string descriptor : Index 3 - "0001" */
172 0x09, 0x04, 0x03, 0x04,
173 0x30, 0x30, 0x30, 0x31
174 };
175 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
176
177 /* Multiple languages are supported on the device, to add
178 a language besides english, the unicode language code must
179 be appended to the language_id_framework array and the length
180 adjusted accordingly. */
181 static unsigned char language_id_framework[] = {
182
183 /* English. */
184 0x09, 0x04
185 };
186 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
187
disconnect_after_mutex_on_action_func(struct UX_TEST_ACTION_STRUCT * action,VOID * params)188 static VOID disconnect_after_mutex_on_action_func(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
189 {
190 _ux_system_slave->ux_system_slave_device.ux_slave_device_state = UX_DEVICE_ADDRESSED;
191 }
192
193 static UX_TEST_HCD_SIM_ACTION disconnect_after_mutex_on[] = {
194 {
195 .do_after = UX_TRUE,
196 .usbx_function = UX_TEST_OVERRIDE_TX_MUTEX_GET,
197 .wait_option = TX_WAIT_FOREVER,
198 .action_func = disconnect_after_mutex_on_action_func,
199 },
200 { 0 }
201 };
202
203 /* Define the ISR dispatch. */
204
205 extern VOID (*test_isr_dispatch)(void);
206
207
208 /* Prototype for test control return. */
209
210 void test_control_return(UINT status);
211
212
213 /* Define the ISR dispatch routine. */
214
test_isr(void)215 static void test_isr(void)
216 {
217
218 /* For further expansion of interrupt-level testing. */
219 }
220
break_on_cdc_acm_all_ready(VOID)221 static UINT break_on_cdc_acm_all_ready(VOID)
222 {
223 UINT status;
224 UINT i;
225 UX_HOST_CLASS *class;
226 UX_HOST_CLASS_CDC_ACM *cdc_acm;
227
228 /* Find the main cdc_acm container */
229 status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
230 if (status != UX_SUCCESS)
231 /* Do not break. */
232 return 0;
233
234 /* Find class instances. */
235 for (i = 0; i < 2; i ++)
236 {
237 status = ux_host_stack_class_instance_get(class, i, (void **) &cdc_acm);
238 if (status != UX_SUCCESS)
239 /* Do not break. */
240 return 0;
241
242 switch(cdc_acm->ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass)
243 {
244
245 case UX_HOST_CLASS_CDC_CONTROL_CLASS:
246 cdc_acm_host_control = cdc_acm;
247 break;
248
249 case UX_HOST_CLASS_CDC_DATA_CLASS:
250 cdc_acm_host_data = cdc_acm;
251 break;
252
253 default:
254 break;
255 }
256 }
257
258 if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL)
259 /* Do not break. */
260 return 0;
261
262 if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
263 /* Do not break. */
264 return 0;
265
266 if (cdc_acm_host_data->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
267 /* Do not break. */
268 return 0;
269
270 if (_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance == UX_NULL)
271 /* Do not break. */
272 return 0;
273
274 cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *)_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance;
275
276 /* All found, break. */
277 return 1;
278 }
279
break_on_removal(VOID)280 static UINT break_on_removal(VOID)
281 {
282
283 UINT status;
284 UX_DEVICE *device;
285
286 status = ux_host_stack_device_get(0, &device);
287 if (status == UX_SUCCESS)
288 /* Do not break. */
289 return UX_SUCCESS;
290
291 if (_ux_system_slave->ux_system_slave_class_array[0].ux_slave_class_instance != UX_NULL)
292 /* Do not break. */
293 return 0;
294
295 cdc_acm_host_data = UX_NULL;
296 cdc_acm_host_control = UX_NULL;
297 cdc_acm_slave = UX_NULL;
298
299 return 1;
300 }
301
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)302 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
303 {
304
305 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
306
307 switch(event)
308 {
309
310 case UX_DEVICE_INSERTION:
311
312 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
313 cdc_acm_host_control = cdc_acm;
314 else
315 cdc_acm_host_data = cdc_acm;
316 break;
317
318 case UX_DEVICE_REMOVAL:
319
320 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
321 cdc_acm_host_control = UX_NULL;
322 else
323 cdc_acm_host_data = UX_NULL;
324 break;
325
326 default:
327 break;
328 }
329 return 0;
330 }
331
test_cdc_instance_activate(VOID * cdc_instance)332 static VOID test_cdc_instance_activate(VOID *cdc_instance)
333 {
334
335 /* Save the CDC instance. */
336 cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
337 }
test_cdc_instance_deactivate(VOID * cdc_instance)338 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
339 {
340
341 /* Reset the CDC instance. */
342 cdc_acm_slave = UX_NULL;
343 }
344
test_cdc_instance_parameter_change(VOID * cdc_instance)345 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
346 {
347
348 /* Set CDC parameter change flag. */
349 cdc_acm_slave_change = UX_TRUE;
350 }
351
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)352 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
353 {
354 error_callback_counter ++;
355
356 if (!error_callback_ignore)
357 {
358 {
359 /* Failed test. */
360 // printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
361 // test_control_return(1);
362 }
363 }
364 }
365
366 /* Define what the initial system looks like. */
367
368 #ifdef CTEST
test_application_define(void * first_unused_memory)369 void test_application_define(void *first_unused_memory)
370 #else
371 void usbx_ux_device_class_cdc_acm_write_test_application_define(void *first_unused_memory)
372 #endif
373 {
374
375 UINT status;
376 CHAR * stack_pointer;
377 CHAR * memory_pointer;
378
379 printf("Running ux_device_class_cdc_acm_write Test.......................... ");
380 stepinfo("\n");
381
382 /* Initialize the free memory pointer */
383 stack_pointer = (CHAR *) usbx_memory;
384 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
385
386 /* Initialize USBX Memory */
387 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
388 /* Check for error. */
389 if (status != UX_SUCCESS)
390 {
391
392 printf("ERROR #%d\n", __LINE__);
393 test_control_return(1);
394 }
395
396 /* Register the error callback. */
397 _ux_utility_error_callback_register(test_ux_error_callback);
398
399 /* The code below is required for installing the host portion of USBX */
400 status = ux_host_stack_initialize(UX_NULL);
401 if (status != UX_SUCCESS)
402 {
403
404 printf("ERROR #%d\n", __LINE__);
405 test_control_return(1);
406 }
407
408 /* Register CDC ACM class */
409 status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
410 if (status != UX_SUCCESS)
411 {
412
413 printf("ERROR #%d\n", __LINE__);
414 test_control_return(1);
415 }
416
417 /* The code below is required for installing the device portion of USBX. No call back for
418 device status change in this example. */
419 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
420 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
421 string_framework, STRING_FRAMEWORK_LENGTH,
422 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
423 if(status!=UX_SUCCESS)
424 {
425
426 printf("ERROR #%d\n", __LINE__);
427 test_control_return(1);
428 }
429
430 /* Set the parameters for callback when insertion/extraction of a CDC device. */
431 parameter.ux_slave_class_cdc_acm_instance_activate = UX_NULL;
432 parameter.ux_slave_class_cdc_acm_instance_deactivate = UX_NULL;
433 parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
434
435 /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
436 status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
437 1,0, ¶meter);
438 status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
439 2,0, ¶meter);
440 status |= ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
441 3,0, ¶meter);
442 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
443 if(status!=UX_SUCCESS)
444 {
445
446 printf("ERROR #%d\n", __LINE__);
447 test_control_return(1);
448 }
449 #endif
450
451 /* Initialize the simulated device controller. */
452 status = _ux_test_dcd_sim_slave_initialize();
453
454 /* Check for error. */
455 if (status != TX_SUCCESS)
456 {
457
458 printf("ERROR #%d\n", __LINE__);
459 test_control_return(1);
460 }
461
462 /* Register HCD for test */
463 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
464 if (status != UX_SUCCESS)
465 {
466
467 printf("ERROR #%d\n", __LINE__);
468 test_control_return(1);
469 }
470
471 /* Create the main host simulation thread. */
472 status = tx_thread_create(&tx_test_thread_simulation_0, "tx test host simulation", tx_test_thread_simulation_0_entry, 0,
473 stack_pointer, UX_DEMO_STACK_SIZE,
474 20, 20, 1, TX_AUTO_START);
475
476 /* Check for error. */
477 if (status != TX_SUCCESS)
478 {
479
480 printf("ERROR #%d\n", __LINE__);
481 test_control_return(1);
482 }
483
484 /* Create the main slave simulation thread. */
485 status = tx_thread_create(&tx_test_thread_simulation_1, "tx test slave simulation", tx_test_thread_simulation_1_entry, 0,
486 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
487 20, 20, 1, TX_NO_ACTIVATE);
488
489 /* Check for error. */
490 if (status != TX_SUCCESS)
491 {
492
493 printf("ERROR #%d\n", __LINE__);
494 test_control_return(1);
495 }
496 }
497
tx_test_thread_simulation_0_entry(ULONG arg)498 void tx_test_thread_simulation_0_entry(ULONG arg)
499 {
500
501 UINT i;
502
503 /* Test connect. */
504 stepinfo(">>>>>>>>>>>>>>>> Test connect (FS)\n");
505 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
506 ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
507 if (!(cdc_acm_host_control && cdc_acm_host_data && cdc_acm_slave))
508 {
509
510 printf("ERROR #%d: connect fail\n", __LINE__);
511 test_control_return(1);
512 }
513 if (_ux_system_slave->ux_system_slave_device.ux_slave_device_state != UX_DEVICE_CONFIGURED)
514 {
515
516 printf("ERROR %d: device state fail 0x%lx\n", __LINE__, _ux_system_slave->ux_system_slave_device.ux_slave_device_state);
517 test_control_return(1);
518 }
519
520 /* Test write. */
521 stepinfo(">>>>>>>>>>>>>>>> Test write disconnect after mutex_on\n");
522
523 test_thread_action = 1;
524 tx_thread_resume(&tx_test_thread_simulation_1);
525
526 for (i = 0; i < 10; i ++)
527 {
528 if (test_thread_action < 2)
529 _ux_utility_delay_ms(10);
530 }
531 if (test_thread_action < 2)
532 {
533 printf("ERROR %d: test no progress\n", __LINE__);
534 error_counter ++;
535 }
536
537 /* Restore state. */
538 _ux_system_slave->ux_system_slave_device.ux_slave_device_state = UX_DEVICE_CONFIGURED;
539
540 stepinfo(">>>>>>>>>>>>>>>> Deinitialize\n");
541
542 /* Deinitialize the class. */
543 ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
544 ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
545 ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
546
547 /* Deinitialize the device side of usbx. */
548 _ux_device_stack_uninitialize();
549
550 /* And finally the usbx system resources. */
551 _ux_system_uninitialize();
552
553 stepinfo(">>>>>>>>>>>>>>>> Dump results\n");
554
555 if (error_counter > 0)
556 {
557
558 /* Test error. */
559 printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
560 test_control_return(1);
561 }
562
563 /* Successful test. */
564 printf("SUCCESS!\n");
565 test_control_return(0);
566 }
567
tx_test_thread_simulation_1_entry(ULONG arg)568 void tx_test_thread_simulation_1_entry(ULONG arg)
569 {
570
571 UINT status;
572 ULONG actual_length;
573
574 while(1)
575 {
576 if (test_thread_action == 1)
577 {
578 ux_test_set_main_action_list_from_array(disconnect_after_mutex_on);
579 status = ux_device_class_cdc_acm_write(cdc_acm_slave, buffer, 128, &actual_length);
580 if (status == UX_SUCCESS)
581 {
582 printf("ERROR %d: expect fail\n", __LINE__);
583 error_counter ++;
584 }
585 test_thread_action ++;
586 }
587 tx_thread_suspend(&tx_test_thread_simulation_1);
588 }
589 }
590