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 #include "ux_host_class_cdc_acm.h"
14
15 #include "ux_test_dcd_sim_slave.h"
16 #include "ux_test_hcd_sim_host.h"
17 #include "ux_test_utility_sim.h"
18
19 /* Define constants. */
20 #define UX_DEMO_DEBUG_SIZE (4096*8)
21 #define UX_DEMO_STACK_SIZE 1024
22 #define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
23 #define UX_DEMO_XMIT_BUFFER_SIZE 512
24 #define UX_DEMO_RECEPTION_BUFFER_SIZE 512
25 #define UX_DEMO_FILE_BUFFER_SIZE 512
26 #define UX_DEMO_RECEPTION_BLOCK_SIZE 64
27 #define UX_DEMO_MEMORY_SIZE (64*1024)
28 #define UX_DEMO_FILE_SIZE (128 * 1024)
29 #define UX_RAM_DISK_MEMORY (256 * 1024)
30
31 /* Define local/extern function prototypes. */
32 static TX_THREAD ux_test_thread_host_simulation;
33 static TX_THREAD ux_test_thread_slave_simulation;
34 static void ux_test_thread_host_simulation_entry(ULONG);
35 static void ux_test_thread_slave_simulation_entry(ULONG);
36
37 static VOID test_cdc_instance_activate(VOID *cdc_instance);
38 static VOID test_cdc_instance_deactivate(VOID *cdc_instance);
39 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance);
40
41 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params);
42
43 /* Define global data structures. */
44 static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
45 static UX_HOST_CLASS *class_driver;
46 static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_control;
47 static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_data;
48 static UX_HOST_CLASS_CDC_ACM_RECEPTION cdc_acm_host_reception;
49 static UCHAR cdc_acm_host_reception_buffer[UX_DEMO_RECEPTION_BUFFER_SIZE];
50 static UINT cdc_acm_host_reception_status = 0;
51 static ULONG cdc_acm_host_reception_count = 0;
52 static UCHAR cdc_acm_host_read_buffer[UX_SLAVE_REQUEST_DATA_MAX_LENGTH * 2];
53 static ULONG cdc_acm_host_read_buffer_length;
54
55 static UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
56 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
57 static UCHAR cdc_acm_slave_change;
58 static UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER cdc_acm_slave_line_coding;
59 static UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER cdc_acm_slave_line_state;
60 static ULONG device_read_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
61 static UCHAR device_buffer[UX_SLAVE_REQUEST_DATA_MAX_LENGTH * 2];
62
63 static UCHAR host_buffer[UX_SLAVE_REQUEST_DATA_MAX_LENGTH * 2];
64
65 static ULONG set_cfg_counter;
66
67 static ULONG rsc_mem_alloc_cnt_on_set_cfg;
68 static ULONG rsc_sem_on_set_cfg;
69 static ULONG rsc_sem_get_on_set_cfg;
70 static ULONG rsc_mutex_on_set_cfg;
71
72 static ULONG rsc_enum_sem_usage;
73 static ULONG rsc_enum_sem_get_count;
74 static ULONG rsc_enum_mutex_usage;
75 static ULONG rsc_enum_mem_alloc_count;
76
77 static ULONG rsc_cdc_sem_usage;
78 static ULONG rsc_cdc_sem_get_count;
79 static ULONG rsc_cdc_mutex_usage;
80 static ULONG rsc_cdc_mem_alloc_count;
81
82 static ULONG interaction_count;
83
84 static UCHAR error_callback_ignore = UX_TRUE;
85 static ULONG error_callback_counter;
86
87 /* Define device framework. */
88
89 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 93
90 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 103
91 #define STRING_FRAMEWORK_LENGTH 47
92 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
93
94 static unsigned char device_framework_full_speed[] = {
95
96 /* Device descriptor 18 bytes
97 0x02 bDeviceClass: CDC class code
98 0x00 bDeviceSubclass: CDC class sub code
99 0x00 bDeviceProtocol: CDC Device protocol
100
101 idVendor & idProduct - http://www.linux-usb.org/usb.ids
102 */
103 0x12, 0x01, 0x10, 0x01,
104 0xEF, 0x02, 0x01,
105 0x08,
106 0x84, 0x84, 0x00, 0x00,
107 0x00, 0x01,
108 0x01, 0x02, 03,
109 0x01,
110
111 /* Configuration 1 descriptor 9 bytes */
112 0x09, 0x02, 0x4b, 0x00,
113 0x02, 0x01, 0x00,
114 0x40, 0x00,
115
116 /* Interface association descriptor. 8 bytes. */
117 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
118
119 /* Communication Class Interface Descriptor Requirement. 9 bytes. */
120 0x09, 0x04, 0x00,
121 0x00,
122 0x01,
123 0x02, 0x02, 0x01,
124 0x00,
125
126 /* Header Functional Descriptor 5 bytes */
127 0x05, 0x24, 0x00,
128 0x10, 0x01,
129
130 /* ACM Functional Descriptor 4 bytes */
131 0x04, 0x24, 0x02,
132 0x0f,
133
134 /* Union Functional Descriptor 5 bytes */
135 0x05, 0x24, 0x06,
136 0x00, /* Master interface */
137 0x01, /* Slave interface */
138
139 /* Call Management Functional Descriptor 5 bytes */
140 0x05, 0x24, 0x01,
141 0x03,
142 0x01, /* Data interface */
143
144 /* Endpoint 0x83 descriptor 7 bytes */
145 0x07, 0x05, 0x83,
146 0x03,
147 0x08, 0x00,
148 0xFF,
149
150 /* Data Class Interface Descriptor Requirement 9 bytes */
151 0x09, 0x04, 0x01,
152 0x00,
153 0x02,
154 0x0A, 0x00, 0x00,
155 0x00,
156
157 /* Endpoint 0x02 descriptor 7 bytes */
158 0x07, 0x05, 0x02, /* @ 93 - 14 + 2 = 81 */
159 0x02,
160 0x40, 0x00,
161 0x00,
162
163 /* Endpoint 0x81 descriptor 7 bytes */
164 0x07, 0x05, 0x81, /* @ 93 - 7 + 2 = 88 */
165 0x02,
166 0x40, 0x00,
167 0x00,
168
169 };
170
171 #define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
172 #define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
173
174 static unsigned char device_framework_high_speed[] = {
175
176 /* Device descriptor
177 0x02 bDeviceClass: CDC class code
178 0x00 bDeviceSubclass: CDC class sub code
179 0x00 bDeviceProtocol: CDC Device protocol
180
181 idVendor & idProduct - http://www.linux-usb.org/usb.ids
182 */
183 0x12, 0x01, 0x00, 0x02,
184 0xEF, 0x02, 0x01,
185 0x40,
186 0x84, 0x84, 0x00, 0x00,
187 0x00, 0x01,
188 0x01, 0x02, 03,
189 0x01,
190
191 /* Device qualifier descriptor */
192 0x0a, 0x06, 0x00, 0x02,
193 0x02, 0x00, 0x00,
194 0x40,
195 0x01,
196 0x00,
197
198 /* Configuration 1 descriptor */
199 0x09, 0x02, 0x4b, 0x00,
200 0x02, 0x01, 0x00,
201 0x40, 0x00,
202
203 /* Interface association descriptor. */
204 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
205
206 /* Communication Class Interface Descriptor Requirement */
207 0x09, 0x04, 0x00,
208 0x00,
209 0x01,
210 0x02, 0x02, 0x01,
211 0x00,
212
213 /* Header Functional Descriptor */
214 0x05, 0x24, 0x00,
215 0x10, 0x01,
216
217 /* ACM Functional Descriptor */
218 0x04, 0x24, 0x02,
219 0x0f,
220
221 /* Union Functional Descriptor */
222 0x05, 0x24, 0x06,
223 0x00,
224 0x01,
225
226 /* Call Management Functional Descriptor */
227 0x05, 0x24, 0x01,
228 0x00,
229 0x01,
230
231 /* Endpoint 0x83 descriptor */
232 0x07, 0x05, 0x83,
233 0x03,
234 0x08, 0x00,
235 0xFF,
236
237 /* Data Class Interface Descriptor Requirement */
238 0x09, 0x04, 0x01,
239 0x00,
240 0x02,
241 0x0A, 0x00, 0x00,
242 0x00,
243
244 /* Endpoint 0x02 descriptor */
245 0x07, 0x05, 0x02, /* @ 103 - 14 + 2 = 91 */
246 0x02,
247 0x40, 0x00,
248 0x00,
249
250 /* Endpoint 0x81 descriptor */
251 0x07, 0x05, 0x81, /* @ 103 - 7 + 2 = 98 */
252 0x02,
253 0x40, 0x00,
254 0x00,
255
256 };
257
258 #define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
259 #define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
260
261 static unsigned char string_framework[] = {
262
263 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
264 0x09, 0x04, 0x01, 0x0c,
265 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
266 0x6f, 0x67, 0x69, 0x63,
267
268 /* Product string descriptor : Index 2 - "EL Composite device" */
269 0x09, 0x04, 0x02, 0x13,
270 0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
271 0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
272 0x69, 0x63, 0x65,
273
274 /* Serial Number string descriptor : Index 3 - "0001" */
275 0x09, 0x04, 0x03, 0x04,
276 0x30, 0x30, 0x30, 0x31
277 };
278
279
280 /* Multiple languages are supported on the device, to add
281 a language besides english, the unicode language code must
282 be appended to the language_id_framework array and the length
283 adjusted accordingly. */
284 static unsigned char language_id_framework[] = {
285
286 /* English. */
287 0x09, 0x04
288 };
289
290 /* Setup requests */
291
292 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
293
294 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
295 /* function, request to match,
296 port action, port status,
297 request action, request EP, request data, request actual length, request status,
298 status, additional callback,
299 no_return */
300 { UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
301 UX_FALSE, UX_TEST_PORT_STATUS_DISC,
302 UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
303 UX_SUCCESS, ux_test_hcd_entry_set_cfg,
304 UX_TRUE}, /* Invoke callback & continue */
305 { 0 }
306 };
307
308 /* Define the ISR dispatch. */
309
310 extern VOID (*test_isr_dispatch)(void);
311
312
313 /* Prototype for test control return. */
314
315 void test_control_return(UINT status);
316
317
318 /* Define the ISR dispatch routine. */
319
test_isr(void)320 static void test_isr(void)
321 {
322
323 /* For further expansion of interrupt-level testing. */
324 }
325
error_callback(UINT system_level,UINT system_context,UINT error_code)326 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
327 {
328
329 error_callback_counter ++;
330
331 if (!error_callback_ignore)
332 {
333 {
334 /* Failed test. */
335 printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
336 test_control_return(1);
337 }
338 }
339 }
340
sleep_break_on_error(VOID)341 static UINT sleep_break_on_error(VOID)
342 {
343
344 if (error_callback_counter >= 3)
345 return error_callback_counter;
346
347 return UX_SUCCESS;
348 }
349
demo_class_cdc_acm_get(void)350 static UINT demo_class_cdc_acm_get(void)
351 {
352
353 UINT status;
354 UX_HOST_CLASS *class;
355 UX_HOST_CLASS_CDC_ACM *cdc_acm_host;
356
357
358 /* Find the main cdc_acm container */
359 status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
360 if (status != UX_SUCCESS)
361 return(status);
362
363 /* We get the first instance of the cdc_acm device */
364 do
365 {
366
367 status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
368 tx_thread_sleep(10);
369 } while (status != UX_SUCCESS);
370
371 /* We still need to wait for the cdc_acm status to be live */
372 while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
373 tx_thread_sleep(10);
374
375 /* Isolate both the control and data interfaces. */
376 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
377 {
378 /* This is the data interface. */
379 cdc_acm_host_data = cdc_acm_host;
380
381 /* In that case, the second one should be the control interface. */
382 status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
383
384 /* Check error. */
385 if (status != UX_SUCCESS)
386 return(status);
387
388 /* Check for the control interfaces. */
389 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
390 {
391
392 /* This is the control interface. */
393 cdc_acm_host_control = cdc_acm_host;
394
395 return(UX_SUCCESS);
396
397 }
398 }
399 else
400 {
401 /* Check for the control interfaces. */
402 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
403 {
404
405 /* This is the control interface. */
406 cdc_acm_host_control = cdc_acm_host;
407
408 /* In that case, the second one should be the data interface. */
409 status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
410
411 /* Check error. */
412 if (status != UX_SUCCESS)
413 return(status);
414
415 /* Check for the data interface. */
416 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
417 {
418
419 /* This is the data interface. */
420 cdc_acm_host_data = cdc_acm_host;
421
422 return(UX_SUCCESS);
423
424 }
425 }
426 }
427
428 /* Return ERROR. */
429 return(UX_ERROR);
430 }
431
demo_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)432 static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
433 {
434
435 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
436
437 switch(event)
438 {
439
440 case UX_DEVICE_INSERTION:
441
442 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
443 cdc_acm_host_control = cdc_acm;
444 else
445 cdc_acm_host_data = cdc_acm;
446 break;
447
448 case UX_DEVICE_REMOVAL:
449
450 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
451 cdc_acm_host_control = UX_NULL;
452 else
453 cdc_acm_host_data = UX_NULL;
454 break;
455
456 default:
457 break;
458 }
459 return 0;
460 }
461
test_cdc_instance_activate(VOID * cdc_instance)462 static VOID test_cdc_instance_activate(VOID *cdc_instance)
463 {
464
465 /* Save the CDC instance. */
466 cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
467 }
test_cdc_instance_deactivate(VOID * cdc_instance)468 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
469 {
470
471 /* Reset the CDC instance. */
472 cdc_acm_slave = UX_NULL;
473 }
474
test_cdc_instance_parameter_change(VOID * cdc_instance)475 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
476 {
477
478 /* Set CDC parameter change flag. */
479 cdc_acm_slave_change = UX_TRUE;
480
481 /* Get new paramster. */
482 ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
483 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING,
484 (VOID*)&cdc_acm_slave_line_coding);
485 ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
486 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING,
487 (VOID*)&cdc_acm_slave_line_state);
488 }
489
test_swap_framework_bulk_ep_descriptors(VOID)490 static VOID test_swap_framework_bulk_ep_descriptors(VOID)
491 {
492 UCHAR tmp;
493
494 tmp = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS];
495 device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS] = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS];
496 device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS] = tmp;
497
498 tmp = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS];
499 device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS] = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS];
500 device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS] = tmp;
501 }
502
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)503 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
504 {
505
506 set_cfg_counter ++;
507
508 rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
509
510 rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
511 rsc_sem_get_on_set_cfg = ux_test_utility_sim_sem_get_count();
512 rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
513 }
514
515 /* Define what the initial system looks like. */
516
517 #ifdef CTEST
test_application_define(void * first_unused_memory)518 void test_application_define(void *first_unused_memory)
519 #else
520 void usbx_standalone_device_cdc_acm_basic_test_application_define(void *first_unused_memory)
521 #endif
522 {
523
524 UINT status;
525 CHAR * stack_pointer;
526 CHAR * memory_pointer;
527
528 /* Inform user. */
529 printf("Running STANDALONE CDC ACM Basic Test............................... ");
530
531 /* Reset testing counts. */
532 ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
533 ux_test_utility_sim_mem_alloc_count_reset();
534 ux_test_utility_sim_mutex_create_count_reset();
535 ux_test_utility_sim_sem_create_count_reset();
536 ux_test_utility_sim_sem_get_count_reset();
537 /* Reset error generations */
538 ux_test_utility_sim_sem_error_generation_stop();
539 ux_test_utility_sim_mutex_error_generation_stop();
540 ux_test_utility_sim_sem_get_error_generation_stop();
541
542 /* Initialize the free memory pointer */
543 stack_pointer = (CHAR *) usbx_memory;
544 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
545
546 /* Initialize USBX Memory */
547 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
548
549 /* Check for error. */
550 if (status != UX_SUCCESS)
551 {
552
553 printf("ERROR #1\n");
554 test_control_return(1);
555 }
556
557 /* Register the error callback. */
558 _ux_utility_error_callback_register(error_callback);
559
560 /* The code below is required for installing the host portion of USBX */
561 status = ux_host_stack_initialize(demo_system_host_change_function);
562 if (status != UX_SUCCESS)
563 {
564
565 printf("ERROR #2\n");
566 test_control_return(1);
567 }
568
569 /* Register CDC-ACM class. */
570 status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
571 if (status != UX_SUCCESS)
572 {
573
574 printf("ERROR #3\n");
575 test_control_return(1);
576 }
577
578 /* The code below is required for installing the device portion of USBX. No call back for
579 device status change in this example. */
580 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
581 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
582 string_framework, STRING_FRAMEWORK_LENGTH,
583 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
584 if(status!=UX_SUCCESS)
585 {
586
587 printf("ERROR #5\n");
588 test_control_return(1);
589 }
590
591 /* Set the parameters for callback when insertion/extraction of a CDC device. */
592 parameter.ux_slave_class_cdc_acm_instance_activate = test_cdc_instance_activate;
593 parameter.ux_slave_class_cdc_acm_instance_deactivate = test_cdc_instance_deactivate;
594 parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
595
596 /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
597 status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
598 1,0, ¶meter);
599
600 if(status!=UX_SUCCESS)
601 {
602
603 printf("ERROR #6\n");
604 test_control_return(1);
605 }
606
607 /* Initialize the simulated device controller. */
608 status = _ux_dcd_sim_slave_initialize();
609
610 /* Check for error. */
611 if (status != TX_SUCCESS)
612 {
613
614 printf("ERROR #7\n");
615 test_control_return(1);
616 }
617
618 /* Register all the USB host controllers available in this system */
619 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
620 if (status != UX_SUCCESS)
621 {
622
623 printf("ERROR #4\n");
624 test_control_return(1);
625 }
626
627 /* Create the main host simulation thread. */
628 status = tx_thread_create(&ux_test_thread_host_simulation, "tx demo host simulation", ux_test_thread_host_simulation_entry, 0,
629 stack_pointer, UX_DEMO_STACK_SIZE,
630 20, 20, 1, TX_AUTO_START);
631
632 /* Check for error. */
633 if (status != TX_SUCCESS)
634 {
635
636 printf("ERROR #8\n");
637 test_control_return(1);
638 }
639
640 /* Create the main slave simulation thread. */
641 status = tx_thread_create(&ux_test_thread_slave_simulation, "tx demo slave simulation", ux_test_thread_slave_simulation_entry, 0,
642 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
643 20, 20, 1, TX_AUTO_START);
644
645 /* Check for error. */
646 if (status != TX_SUCCESS)
647 {
648
649 printf("ERROR #9\n");
650 test_control_return(1);
651 }
652 }
653
test_cdc_acm_device_ioctl_parameters(void)654 static void test_cdc_acm_device_ioctl_parameters(void)
655 {
656 UINT status;
657 if (cdc_acm_slave == UX_NULL)
658 {
659 printf("ERROR #%d, device instance not ready\n", __LINE__);
660 test_control_return(1);
661 }
662
663 /* Get and check default line coding. */
664 ux_utility_memory_set(&cdc_acm_slave_line_coding, 0, sizeof(cdc_acm_slave_line_coding));
665 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
666 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING,
667 (VOID*)&cdc_acm_slave_line_coding);
668 UX_TEST_ASSERT(status == UX_SUCCESS);
669 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_baudrate ==
670 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE);
671 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_stop_bit ==
672 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT);
673 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_parity ==
674 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY);
675 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_data_bit ==
676 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT);
677
678 /* Set new line coding, read back to test. */
679 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_baudrate ++;
680 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_stop_bit ++;
681 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_parity ++;
682 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_data_bit ++;
683 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
684 UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING,
685 (VOID*)&cdc_acm_slave_line_coding);
686 UX_TEST_ASSERT(status == UX_SUCCESS);
687
688 ux_utility_memory_set(&cdc_acm_slave_line_coding, 0, sizeof(cdc_acm_slave_line_coding));
689 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
690 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING,
691 (VOID*)&cdc_acm_slave_line_coding);
692 UX_TEST_ASSERT(status == UX_SUCCESS);
693 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_baudrate ==
694 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE + 1);
695 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_stop_bit ==
696 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT + 1);
697 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_parity ==
698 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY + 1);
699 UX_TEST_ASSERT(cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_data_bit ==
700 UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT + 1);
701
702 /* Set line coding back. */
703 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_baudrate --;
704 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_stop_bit --;
705 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_parity --;
706 cdc_acm_slave_line_coding.ux_slave_class_cdc_acm_parameter_data_bit --;
707 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
708 UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING,
709 (VOID*)&cdc_acm_slave_line_coding);
710 UX_TEST_ASSERT(status == UX_SUCCESS);
711
712 /* Get and check line state. */
713 ux_utility_memory_set(&cdc_acm_slave_line_state, 0, sizeof(cdc_acm_slave_line_state));
714 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
715 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE,
716 (VOID*)&cdc_acm_slave_line_state);
717 UX_TEST_ASSERT(status == UX_SUCCESS);
718 UX_TEST_ASSERT(cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_dtr == 1);
719 UX_TEST_ASSERT(cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_rts == 1);
720
721 /* Set new line state, read back to test. */
722 cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_dtr ++;
723 cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_rts ++;
724 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
725 UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE,
726 (VOID*)&cdc_acm_slave_line_state);
727 UX_TEST_ASSERT(status == UX_SUCCESS);
728
729 ux_utility_memory_set(&cdc_acm_slave_line_state, 0, sizeof(cdc_acm_slave_line_state));
730 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
731 UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE,
732 (VOID*)&cdc_acm_slave_line_state);
733 UX_TEST_ASSERT(status == UX_SUCCESS);
734 UX_TEST_ASSERT(cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_dtr == 2);
735 UX_TEST_ASSERT(cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_rts == 2);
736
737 /* Set line state back. */
738 cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_dtr --;
739 cdc_acm_slave_line_state.ux_slave_class_cdc_acm_parameter_rts --;
740 status = ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
741 UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE,
742 (VOID*)&cdc_acm_slave_line_state);
743 UX_TEST_ASSERT(status == UX_SUCCESS);
744 }
745
746
test_thread_host_reception_callback(UX_HOST_CLASS_CDC_ACM * cdc_acm,UINT status,UCHAR * reception_buffer,ULONG reception_size)747 static void test_thread_host_reception_callback(UX_HOST_CLASS_CDC_ACM *cdc_acm, UINT status, UCHAR *reception_buffer, ULONG reception_size)
748 {
749 ULONG i;
750
751 /* And move to the next reception buffer. Check if we are at the end of the application buffer. */
752 if (cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_tail +
753 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_block_size >=
754 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_buffer +
755 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_buffer_size)
756
757 /* We are at the end of the buffer. Move back to the beginning. */
758 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_tail =
759 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_buffer;
760
761 else
762
763 /* Program the tail to be after the current buffer. */
764 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_tail +=
765 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_block_size;
766
767 cdc_acm_host_reception_status = status;
768 cdc_acm_host_reception_count ++;
769
770 /* Save buffer. */
771 for (i = 0;
772 (i < reception_size) &&
773 (cdc_acm_host_read_buffer_length < sizeof(cdc_acm_host_read_buffer));
774 i ++, cdc_acm_host_read_buffer_length ++)
775 {
776 cdc_acm_host_read_buffer[cdc_acm_host_read_buffer_length] = reception_buffer[i];
777 }
778
779 return;
780 }
781
test_cdc_acm_device_read_write(void)782 static void test_cdc_acm_device_read_write(void)
783 {
784 UINT status;
785 ULONG actual_length;
786 UCHAR test_chr;
787 ULONG test_length;
788 ULONG i, test;
789 #define N_TEST 6
790 struct {
791 UCHAR chr;
792 ULONG len;
793 } tests[N_TEST] = {
794 {'$', 1}, {'A', 64}, {'N', 65},
795 {'3', UX_SLAVE_REQUEST_DATA_MAX_LENGTH - 64},
796 {'G', UX_SLAVE_REQUEST_DATA_MAX_LENGTH},
797 {'H', UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1},
798 };
799
800 /* Reception parameter */
801 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_block_size = UX_DEMO_RECEPTION_BLOCK_SIZE;
802 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_buffer = cdc_acm_host_reception_buffer;
803 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_data_buffer_size = UX_DEMO_RECEPTION_BUFFER_SIZE;
804 cdc_acm_host_reception.ux_host_class_cdc_acm_reception_callback = test_thread_host_reception_callback;
805
806 /* Start reception. */
807 status = ux_host_class_cdc_acm_reception_start(cdc_acm_host_data, &cdc_acm_host_reception);
808 if (status != UX_SUCCESS)
809 {
810 printf("ERROR #%d: reception start fail %x\n", __LINE__, status);
811 test_control_return(1);
812 }
813
814 for (test = 0; test < N_TEST; test ++)
815 {
816 test_chr = tests[test].chr;
817 test_length = tests[test].len;
818
819 for (i = 0; i < test_length; i ++)
820 {
821 host_buffer[i] = test_chr;
822 cdc_acm_host_read_buffer[i] = ~test_chr;
823 }
824 cdc_acm_host_read_buffer_length = 0;
825
826 status = ux_host_class_cdc_acm_write(cdc_acm_host_data, host_buffer,
827 test_length, &actual_length);
828 UX_TEST_ASSERT_MESSAGE(status == UX_SUCCESS, "test_length %ld\n", test_length);
829 if ((test_length & 63) == 0)
830 {
831 status = ux_host_class_cdc_acm_write(cdc_acm_host_data, host_buffer,
832 0, &actual_length);
833 UX_TEST_ASSERT_MESSAGE(status == UX_SUCCESS, "test_length %ld\n", test_length);
834 }
835 /* Wait a while for background reception. */
836 tx_thread_sleep(test_length/64 + 1);
837
838 UX_TEST_ASSERT_MESSAGE(cdc_acm_host_reception_status == UX_SUCCESS, "test_length %ld\n", test_length);
839 if (cdc_acm_host_read_buffer_length != test_length)
840 {
841 printf("ERROR #%d, length not match %ld <> %ld\n", __LINE__,
842 test_length, cdc_acm_host_read_buffer_length);
843 test_control_return(1);
844 }
845 for (i = 0; i < test_length; i ++)
846 {
847 UX_TEST_ASSERT_MESSAGE(cdc_acm_host_read_buffer[i] == test_chr, "test_length %ld\n", test_length);
848 }
849 }
850
851 /* Stop reception. */
852 ux_host_class_cdc_acm_reception_stop(cdc_acm_host_data, &cdc_acm_host_reception);
853 }
854
ux_test_thread_host_simulation_entry(ULONG arg)855 void ux_test_thread_host_simulation_entry(ULONG arg)
856 {
857
858 UINT status;
859
860 stepinfo("\n");
861
862 /* Find the cdc_acm class and wait for the link to be up. */
863 status = demo_class_cdc_acm_get();
864 if (status != UX_SUCCESS)
865 {
866
867 /* CDC ACM basic test error. */
868 printf("ERROR #10\n");
869 test_control_return(1);
870 }
871
872 test_cdc_acm_device_ioctl_parameters();
873 test_cdc_acm_device_read_write();
874
875 /* Finally disconnect the device. */
876 ux_device_stack_disconnect();
877
878 /* And deinitialize the class. */
879 status = ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
880
881 /* Deinitialize the device side of usbx. */
882 _ux_device_stack_uninitialize();
883
884 /* And finally the usbx system resources. */
885 _ux_system_uninitialize();
886
887 /* Successful test. */
888 printf("SUCCESS!\n");
889 test_control_return(0);
890
891 }
892
ux_test_thread_slave_simulation_entry(ULONG arg)893 void ux_test_thread_slave_simulation_entry(ULONG arg)
894 {
895
896 UINT status;
897 ULONG actual_length;
898 ULONG read_length = device_read_length;
899 ULONG write_length, write_zlp = UX_FALSE;
900 #define CDC_ACM_DEVICE_STATE_READ UX_STATE_STEP
901 #define CDC_ACM_DEVICE_STATE_WRITE UX_STATE_STEP + 1
902 #define CDC_ACM_DEVICE_STATE_ZLP UX_STATE_STEP + 2
903 UINT cdc_acm_device_state = UX_STATE_RESET;
904
905 while(1)
906 {
907
908 /* Keep running device stack tasks. */
909 ux_system_tasks_run();
910
911 /* Reset state if read length changed. */
912 if (read_length != device_read_length)
913 {
914 cdc_acm_device_state = UX_STATE_RESET;
915 read_length = device_read_length;
916 }
917
918 /* CDC ACM echo state machine. */
919 switch(cdc_acm_device_state)
920 {
921 case UX_STATE_RESET:
922 if (cdc_acm_slave != UX_NULL)
923 {
924 ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
925 UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE,
926 (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT);
927 ux_device_class_cdc_acm_ioctl(cdc_acm_slave,
928 UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE,
929 (VOID*)UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV);
930 cdc_acm_device_state = CDC_ACM_DEVICE_STATE_READ;
931 }
932 break;
933 case CDC_ACM_DEVICE_STATE_READ:
934 if (cdc_acm_slave == UX_NULL)
935 {
936 cdc_acm_device_state = UX_STATE_RESET;
937 break;
938 }
939 status = ux_device_class_cdc_acm_read_run(cdc_acm_slave,
940 device_buffer, device_read_length, &actual_length);
941 if (status < UX_STATE_NEXT)
942 {
943 printf("ERROR #%d: read status 0x%x\n", __LINE__, status);
944 return;
945 }
946 if (status == UX_STATE_NEXT)
947 {
948 write_length = actual_length;
949 if ((actual_length < device_read_length) &&
950 ((actual_length & 63) == 0))
951 {
952 write_zlp = UX_TRUE;
953 }
954 cdc_acm_device_state = CDC_ACM_DEVICE_STATE_WRITE;
955 }
956 break;
957 case CDC_ACM_DEVICE_STATE_WRITE:
958 if (cdc_acm_slave == UX_NULL)
959 {
960 cdc_acm_device_state = UX_STATE_RESET;
961 break;
962 }
963 status = ux_device_class_cdc_acm_write_run(cdc_acm_slave,
964 device_buffer, write_length, &actual_length);
965 if (status < UX_STATE_NEXT)
966 {
967 printf("ERROR #%d: write status 0x%x\n", __LINE__, status);
968 return;
969 }
970 if (status == UX_STATE_NEXT)
971 {
972 if (write_zlp && ((write_length % 64) == 0))
973 {
974 cdc_acm_device_state = CDC_ACM_DEVICE_STATE_ZLP;
975 break;
976 }
977 cdc_acm_device_state = CDC_ACM_DEVICE_STATE_READ;
978 break;
979 }
980 case CDC_ACM_DEVICE_STATE_ZLP:
981 if (cdc_acm_slave == UX_NULL)
982 {
983 cdc_acm_device_state = UX_STATE_RESET;
984 break;
985 }
986 status = ux_device_class_cdc_acm_write_run(cdc_acm_slave,
987 device_buffer, 0, &actual_length);
988 if (status < UX_STATE_NEXT)
989 {
990 printf("ERROR #%d: ZLP status 0x%x\n", __LINE__, status);
991 return;
992 }
993 if (status == UX_STATE_NEXT)
994 cdc_acm_device_state = CDC_ACM_DEVICE_STATE_READ;
995 break;
996 default:
997 cdc_acm_device_state = UX_STATE_RESET;
998 }
999
1000 /* Let other threads run. */
1001 tx_thread_relinquish();
1002 }
1003 }
1004