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
49 static UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
50 static UCHAR cdc_acm_slave_change;
51 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
52
53 static ULONG set_cfg_counter;
54
55 static ULONG rsc_mem_alloc_cnt_on_set_cfg;
56 static ULONG rsc_sem_on_set_cfg;
57 static ULONG rsc_sem_get_on_set_cfg;
58 static ULONG rsc_mutex_on_set_cfg;
59
60 static ULONG rsc_enum_sem_usage;
61 static ULONG rsc_enum_sem_get_count;
62 static ULONG rsc_enum_mutex_usage;
63 static ULONG rsc_enum_mem_alloc_count;
64
65 static ULONG rsc_cdc_sem_usage;
66 static ULONG rsc_cdc_sem_get_count;
67 static ULONG rsc_cdc_mutex_usage;
68 static ULONG rsc_cdc_mem_alloc_count;
69
70 static ULONG interaction_count;
71
72 static UCHAR error_callback_ignore = UX_TRUE;
73 static ULONG error_callback_counter;
74
75 /* Define device framework. */
76
77 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 93
78 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 103
79 #define STRING_FRAMEWORK_LENGTH 47
80 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
81
82 static unsigned char device_framework_full_speed[] = {
83
84 /* Device descriptor 18 bytes
85 0x02 bDeviceClass: CDC class code
86 0x00 bDeviceSubclass: CDC class sub code
87 0x00 bDeviceProtocol: CDC Device protocol
88
89 idVendor & idProduct - http://www.linux-usb.org/usb.ids
90 */
91 0x12, 0x01, 0x10, 0x01,
92 0xEF, 0x02, 0x01,
93 0x08,
94 0x84, 0x84, 0x00, 0x00,
95 0x00, 0x01,
96 0x01, 0x02, 03,
97 0x01,
98
99 /* Configuration 1 descriptor 9 bytes */
100 0x09, 0x02, 0x4b, 0x00,
101 0x02, 0x01, 0x00,
102 0x40, 0x00,
103
104 /* Interface association descriptor. 8 bytes. */
105 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
106
107 /* Communication Class Interface Descriptor Requirement. 9 bytes. */
108 0x09, 0x04, 0x00,
109 0x00,
110 0x01,
111 0x02, 0x02, 0x01,
112 0x00,
113
114 /* Header Functional Descriptor 5 bytes */
115 0x05, 0x24, 0x00,
116 0x10, 0x01,
117
118 /* ACM Functional Descriptor 4 bytes */
119 0x04, 0x24, 0x02,
120 0x0f,
121
122 /* Union Functional Descriptor 5 bytes */
123 0x05, 0x24, 0x06,
124 0x00, /* Master interface */
125 0x01, /* Slave interface */
126
127 /* Call Management Functional Descriptor 5 bytes */
128 0x05, 0x24, 0x01,
129 0x03,
130 0x01, /* Data interface */
131
132 /* Endpoint 0x83 descriptor 7 bytes */
133 0x07, 0x05, 0x83,
134 0x03,
135 0x08, 0x00,
136 0xFF,
137
138 /* Data Class Interface Descriptor Requirement 9 bytes */
139 0x09, 0x04, 0x01,
140 0x00,
141 0x02,
142 0x0A, 0x00, 0x00,
143 0x00,
144
145 /* Endpoint 0x02 descriptor 7 bytes */
146 0x07, 0x05, 0x02, /* @ 93 - 14 + 2 = 81 */
147 0x02,
148 0x40, 0x00,
149 0x00,
150
151 /* Endpoint 0x81 descriptor 7 bytes */
152 0x07, 0x05, 0x81, /* @ 93 - 7 + 2 = 88 */
153 0x02,
154 0x40, 0x00,
155 0x00,
156
157 };
158
159 #define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
160 #define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
161
162 static unsigned char device_framework_high_speed[] = {
163
164 /* Device descriptor
165 0x02 bDeviceClass: CDC class code
166 0x00 bDeviceSubclass: CDC class sub code
167 0x00 bDeviceProtocol: CDC Device protocol
168
169 idVendor & idProduct - http://www.linux-usb.org/usb.ids
170 */
171 0x12, 0x01, 0x00, 0x02,
172 0xEF, 0x02, 0x01,
173 0x40,
174 0x84, 0x84, 0x00, 0x00,
175 0x00, 0x01,
176 0x01, 0x02, 03,
177 0x01,
178
179 /* Device qualifier descriptor */
180 0x0a, 0x06, 0x00, 0x02,
181 0x02, 0x00, 0x00,
182 0x40,
183 0x01,
184 0x00,
185
186 /* Configuration 1 descriptor */
187 0x09, 0x02, 0x4b, 0x00,
188 0x02, 0x01, 0x00,
189 0x40, 0x00,
190
191 /* Interface association descriptor. */
192 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
193
194 /* Communication Class Interface Descriptor Requirement */
195 0x09, 0x04, 0x00,
196 0x00,
197 0x01,
198 0x02, 0x02, 0x01,
199 0x00,
200
201 /* Header Functional Descriptor */
202 0x05, 0x24, 0x00,
203 0x10, 0x01,
204
205 /* ACM Functional Descriptor */
206 0x04, 0x24, 0x02,
207 0x0f,
208
209 /* Union Functional Descriptor */
210 0x05, 0x24, 0x06,
211 0x00,
212 0x01,
213
214 /* Call Management Functional Descriptor */
215 0x05, 0x24, 0x01,
216 0x00,
217 0x01,
218
219 /* Endpoint 0x83 descriptor */
220 0x07, 0x05, 0x83,
221 0x03,
222 0x08, 0x00,
223 0xFF,
224
225 /* Data Class Interface Descriptor Requirement */
226 0x09, 0x04, 0x01,
227 0x00,
228 0x02,
229 0x0A, 0x00, 0x00,
230 0x00,
231
232 /* Endpoint 0x02 descriptor */
233 0x07, 0x05, 0x02, /* @ 103 - 14 + 2 = 91 */
234 0x02,
235 0x40, 0x00,
236 0x00,
237
238 /* Endpoint 0x81 descriptor */
239 0x07, 0x05, 0x81, /* @ 103 - 7 + 2 = 98 */
240 0x02,
241 0x40, 0x00,
242 0x00,
243
244 };
245
246 #define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
247 #define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
248
249 static unsigned char string_framework[] = {
250
251 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
252 0x09, 0x04, 0x01, 0x0c,
253 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
254 0x6f, 0x67, 0x69, 0x63,
255
256 /* Product string descriptor : Index 2 - "EL Composite device" */
257 0x09, 0x04, 0x02, 0x13,
258 0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
259 0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
260 0x69, 0x63, 0x65,
261
262 /* Serial Number string descriptor : Index 3 - "0001" */
263 0x09, 0x04, 0x03, 0x04,
264 0x30, 0x30, 0x30, 0x31
265 };
266
267
268 /* Multiple languages are supported on the device, to add
269 a language besides english, the unicode language code must
270 be appended to the language_id_framework array and the length
271 adjusted accordingly. */
272 static unsigned char language_id_framework[] = {
273
274 /* English. */
275 0x09, 0x04
276 };
277
278 /* Setup requests */
279
280 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
281
282 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
283 /* function, request to match,
284 port action, port status,
285 request action, request EP, request data, request actual length, request status,
286 status, additional callback,
287 no_return */
288 { UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
289 UX_FALSE, UX_TEST_PORT_STATUS_DISC,
290 UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
291 UX_SUCCESS, ux_test_hcd_entry_set_cfg,
292 UX_TRUE}, /* Invoke callback & continue */
293 { 0 }
294 };
295
296 /* Define the ISR dispatch. */
297
298 extern VOID (*test_isr_dispatch)(void);
299
300
301 /* Prototype for test control return. */
302
303 void test_control_return(UINT status);
304
305
306 /* Define the ISR dispatch routine. */
307
test_isr(void)308 static void test_isr(void)
309 {
310
311 /* For further expansion of interrupt-level testing. */
312 }
313
error_callback(UINT system_level,UINT system_context,UINT error_code)314 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
315 {
316
317 error_callback_counter ++;
318
319 if (!error_callback_ignore)
320 {
321 {
322 /* Failed test. */
323 printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
324 test_control_return(1);
325 }
326 }
327 }
328
sleep_break_on_error(VOID)329 static UINT sleep_break_on_error(VOID)
330 {
331
332 if (error_callback_counter >= 3)
333 return error_callback_counter;
334
335 return UX_SUCCESS;
336 }
337
demo_class_cdc_acm_get(void)338 static UINT demo_class_cdc_acm_get(void)
339 {
340
341 UINT status;
342 UX_HOST_CLASS *class;
343 UX_HOST_CLASS_CDC_ACM *cdc_acm_host;
344
345
346 /* Find the main cdc_acm container */
347 status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
348 if (status != UX_SUCCESS)
349 return(status);
350
351 /* We get the first instance of the cdc_acm device */
352 do
353 {
354
355 status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
356 tx_thread_sleep(10);
357 } while (status != UX_SUCCESS);
358
359 /* We still need to wait for the cdc_acm status to be live */
360 while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
361 tx_thread_sleep(10);
362
363 /* Isolate both the control and data interfaces. */
364 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
365 {
366 /* This is the data interface. */
367 cdc_acm_host_data = cdc_acm_host;
368
369 /* In that case, the second one should be the control interface. */
370 status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
371
372 /* Check error. */
373 if (status != UX_SUCCESS)
374 return(status);
375
376 /* Check for the control interfaces. */
377 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
378 {
379
380 /* This is the control interface. */
381 cdc_acm_host_control = cdc_acm_host;
382
383 return(UX_SUCCESS);
384
385 }
386 }
387 else
388 {
389 /* Check for the control interfaces. */
390 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
391 {
392
393 /* This is the control interface. */
394 cdc_acm_host_control = cdc_acm_host;
395
396 /* In that case, the second one should be the data interface. */
397 status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
398
399 /* Check error. */
400 if (status != UX_SUCCESS)
401 return(status);
402
403 /* Check for the data interface. */
404 if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
405 {
406
407 /* This is the data interface. */
408 cdc_acm_host_data = cdc_acm_host;
409
410 return(UX_SUCCESS);
411
412 }
413 }
414 }
415
416 /* Return ERROR. */
417 return(UX_ERROR);
418 }
419
demo_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)420 static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
421 {
422
423 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
424
425 switch(event)
426 {
427
428 case UX_DEVICE_INSERTION:
429
430 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
431 cdc_acm_host_control = cdc_acm;
432 else
433 cdc_acm_host_data = cdc_acm;
434 break;
435
436 case UX_DEVICE_REMOVAL:
437
438 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
439 cdc_acm_host_control = UX_NULL;
440 else
441 cdc_acm_host_data = UX_NULL;
442 break;
443
444 default:
445 break;
446 }
447 return 0;
448 }
449
test_cdc_instance_activate(VOID * cdc_instance)450 static VOID test_cdc_instance_activate(VOID *cdc_instance)
451 {
452
453 /* Save the CDC instance. */
454 cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
455 }
test_cdc_instance_deactivate(VOID * cdc_instance)456 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
457 {
458
459 /* Reset the CDC instance. */
460 cdc_acm_slave = UX_NULL;
461 }
462
test_cdc_instance_parameter_change(VOID * cdc_instance)463 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
464 {
465
466 /* Set CDC parameter change flag. */
467 cdc_acm_slave_change = UX_TRUE;
468 }
469
test_swap_framework_bulk_ep_descriptors(VOID)470 static VOID test_swap_framework_bulk_ep_descriptors(VOID)
471 {
472 UCHAR tmp;
473
474 tmp = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS];
475 device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS] = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS];
476 device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS] = tmp;
477
478 tmp = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS];
479 device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS] = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS];
480 device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS] = tmp;
481 }
482
test_slave_cdc_acm_transfer_disconnect(UX_SLAVE_CLASS_CDC_ACM * cdc_acm,ULONG ep_dir)483 static VOID test_slave_cdc_acm_transfer_disconnect(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ep_dir)
484 {
485
486 UX_SLAVE_ENDPOINT *endpoint;
487 UX_SLAVE_DEVICE *device;
488 UX_SLAVE_INTERFACE *interface;
489 UX_SLAVE_TRANSFER *transfer_request;
490
491 /* Get the pointer to the device. */
492 device = &_ux_system_slave -> ux_system_slave_device;
493
494 /* This is the first time we are activated. We need the interface to the class. */
495 interface = cdc_acm -> ux_slave_class_cdc_acm_interface;
496
497 /* Locate the endpoints. */
498 endpoint = interface -> ux_slave_interface_first_endpoint;
499
500 /* Check the endpoint direction, if OUT we have the correct endpoint. */
501 if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != ep_dir)
502 {
503
504 /* So the next endpoint has to be the OUT endpoint. */
505 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
506 }
507
508 /* All CDC reading are on the endpoint OUT, from the host. */
509 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
510
511 /* Continue transfer. */
512 transfer_request -> ux_slave_transfer_request_actual_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
513
514 /* Change device state. */
515 device -> ux_slave_device_state = UX_DEVICE_ATTACHED;
516
517 /* Inform hcd. */
518 _ux_utility_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore);
519
520 /* Wait a while for transfer request handling. */
521 tx_thread_sleep(50);
522
523 /* Change device state. */
524 device -> ux_slave_device_state = UX_DEVICE_CONFIGURED;
525 }
526
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)527 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
528 {
529
530 set_cfg_counter ++;
531
532 rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
533
534 rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
535 rsc_sem_get_on_set_cfg = ux_test_utility_sim_sem_get_count();
536 rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
537 }
538
539 /* Define what the initial system looks like. */
540
541 #ifdef CTEST
test_application_define(void * first_unused_memory)542 void test_application_define(void *first_unused_memory)
543 #else
544 void usbx_cdc_acm_basic_memory_test_application_define(void *first_unused_memory)
545 #endif
546 {
547
548 UINT status;
549 CHAR * stack_pointer;
550 CHAR * memory_pointer;
551
552 /* Inform user. */
553 printf("Running CDC ACM Basic Memory Test................................... ");
554
555 /* Reset testing counts. */
556 ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
557 ux_test_utility_sim_mem_alloc_count_reset();
558 ux_test_utility_sim_mutex_create_count_reset();
559 ux_test_utility_sim_sem_create_count_reset();
560 ux_test_utility_sim_sem_get_count_reset();
561 /* Reset error generations */
562 ux_test_utility_sim_sem_error_generation_stop();
563 ux_test_utility_sim_mutex_error_generation_stop();
564 ux_test_utility_sim_sem_get_error_generation_stop();
565
566 /* Initialize the free memory pointer */
567 stack_pointer = (CHAR *) usbx_memory;
568 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
569
570 /* Initialize USBX Memory */
571 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
572
573 /* Check for error. */
574 if (status != UX_SUCCESS)
575 {
576
577 printf("ERROR #1\n");
578 test_control_return(1);
579 }
580
581 /* Register the error callback. */
582 _ux_utility_error_callback_register(error_callback);
583
584 /* The code below is required for installing the host portion of USBX */
585 status = ux_host_stack_initialize(demo_system_host_change_function);
586 if (status != UX_SUCCESS)
587 {
588
589 printf("ERROR #2\n");
590 test_control_return(1);
591 }
592
593 /* Register CDC-ACM class. */
594 status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
595 if (status != UX_SUCCESS)
596 {
597
598 printf("ERROR #3\n");
599 test_control_return(1);
600 }
601
602 /* The code below is required for installing the device portion of USBX. No call back for
603 device status change in this example. */
604 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
605 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
606 string_framework, STRING_FRAMEWORK_LENGTH,
607 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
608 if(status!=UX_SUCCESS)
609 {
610
611 printf("ERROR #5\n");
612 test_control_return(1);
613 }
614
615 /* Set the parameters for callback when insertion/extraction of a CDC device. */
616 parameter.ux_slave_class_cdc_acm_instance_activate = test_cdc_instance_activate;
617 parameter.ux_slave_class_cdc_acm_instance_deactivate = test_cdc_instance_deactivate;
618 parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
619
620 /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
621 status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
622 1,0, ¶meter);
623
624 if(status!=UX_SUCCESS)
625 {
626
627 printf("ERROR #6\n");
628 test_control_return(1);
629 }
630
631 /* Initialize the simulated device controller. */
632 status = _ux_dcd_sim_slave_initialize();
633
634 /* Check for error. */
635 if (status != TX_SUCCESS)
636 {
637
638 printf("ERROR #7\n");
639 test_control_return(1);
640 }
641
642 /* Register all the USB host controllers available in this system */
643 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
644 if (status != UX_SUCCESS)
645 {
646
647 printf("ERROR #4\n");
648 test_control_return(1);
649 }
650
651 /* Create the main host simulation thread. */
652 status = tx_thread_create(&ux_test_thread_host_simulation, "tx demo host simulation", ux_test_thread_host_simulation_entry, 0,
653 stack_pointer, UX_DEMO_STACK_SIZE,
654 20, 20, 1, TX_AUTO_START);
655
656 /* Check for error. */
657 if (status != TX_SUCCESS)
658 {
659
660 printf("ERROR #8\n");
661 test_control_return(1);
662 }
663
664 /* Create the main slave simulation thread. */
665 status = tx_thread_create(&ux_test_thread_slave_simulation, "tx demo slave simulation", ux_test_thread_slave_simulation_entry, 0,
666 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
667 20, 20, 1, TX_AUTO_START);
668
669 /* Check for error. */
670 if (status != TX_SUCCESS)
671 {
672
673 printf("ERROR #9\n");
674 test_control_return(1);
675 }
676 }
677
ux_test_thread_host_simulation_entry(ULONG arg)678 void ux_test_thread_host_simulation_entry(ULONG arg)
679 {
680
681 UINT status;
682 UX_SLAVE_CLASS_CDC_ACM * cdc_acm_slave_bak;
683 UX_HOST_CLASS_CDC_ACM * cdc_acm_host_ctrl_bak;
684 UX_HOST_CLASS_CDC_ACM * cdc_acm_host_data_bak;
685 ULONG test_n;
686 ULONG mem_free;
687 ULONG retry;
688
689 stepinfo("\n");
690
691 /* Find the cdc_acm class and wait for the link to be up. */
692 status = demo_class_cdc_acm_get();
693 if (status != UX_SUCCESS)
694 {
695
696 /* CDC ACM basic test error. */
697 printf("ERROR #10\n");
698 test_control_return(1);
699 }
700
701 /* Save slave instance for later tests. */
702 cdc_acm_slave_bak = cdc_acm_slave;
703 /* Save host instances for later tests. */
704 cdc_acm_host_ctrl_bak = cdc_acm_host_control;
705 cdc_acm_host_data_bak = cdc_acm_host_data;
706
707 /* Test disconnect. */
708 ux_test_dcd_sim_slave_disconnect();
709 ux_test_hcd_sim_host_disconnect();
710
711 /* Reset testing counts. */
712 ux_test_utility_sim_mem_alloc_count_reset();
713 ux_test_utility_sim_mutex_create_count_reset();
714 ux_test_utility_sim_sem_create_count_reset();
715 ux_test_utility_sim_sem_get_count_reset();
716 ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
717
718 /* Save free memory usage. */
719 mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
720 ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
721 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
722 for (retry = 0; (retry < 10) && (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL); retry ++)
723 tx_thread_sleep(10);
724
725 /* Log create counts for further tests. */
726 rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
727 rsc_enum_sem_usage = rsc_sem_on_set_cfg;
728 rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
729 /* Log create counts when instances active for further tests. */
730 rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
731 rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
732 rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
733
734 /* Lock log base for tests. */
735 ux_test_utility_sim_mem_alloc_log_lock();
736
737 stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
738 stepinfo("cdc mem : %ld\n", rsc_cdc_mem_alloc_count);
739 stepinfo("mem free: %ld, %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
740
741 /* Simulate detach and attach for FS enumeration,
742 and check if there is memory error in normal enumeration.
743 */
744 stepinfo(">>>>>>>>>>>> Enumeration test\n");
745 mem_free = (~0);
746 for (test_n = 0; test_n < 3; test_n++)
747 {
748 stepinfo("%4ld / 2\n", test_n);
749
750 /* Disconnect. */
751 ux_test_dcd_sim_slave_disconnect();
752 ux_test_hcd_sim_host_disconnect();
753
754 /* Update memory free level (disconnect) */
755 if (mem_free == (~0))
756 mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
757 else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
758 {
759
760 printf("ERROR #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
761 test_control_return(1);
762 }
763
764 /* Connect. */
765 error_callback_counter = 0;
766 ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
767 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
768
769 /* Wait and break on error. */
770 ux_test_breakable_sleep(100, sleep_break_on_error);
771
772 /* Check */
773 if (!cdc_acm_host_control || !cdc_acm_host_data)
774 {
775
776 printf("ERROR #12.%ld: Enumeration fail\n", test_n);
777 test_control_return(1);
778 }
779 }
780
781 /* Simulate detach and attach for FS enumeration,
782 and test possible memory allocation error handlings.
783 */
784 if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
785 mem_free = (~0);
786 for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
787 {
788
789 stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
790
791 /* Disconnect. */
792 ux_test_dcd_sim_slave_disconnect();
793 ux_test_hcd_sim_host_disconnect();
794
795 /* Update memory free level (disconnect) */
796 if (mem_free == (~0))
797 mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
798 else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
799 {
800
801 printf("ERROR #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
802 test_control_return(1);
803 }
804
805 /* Set memory error generation */
806 ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
807
808 /* Connect. */
809 error_callback_counter = 0;
810 ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
811 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
812
813 /* Wait and break on errors. */
814 ux_test_breakable_sleep(100, sleep_break_on_error);
815
816 /* Check error */
817 if (cdc_acm_host_control && cdc_acm_host_data)
818 {
819
820 printf("ERROR #12.%ld: device detected when there is memory error\n", test_n);
821 test_control_return(1);
822 }
823 stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
824 }
825 ux_test_utility_sim_mem_alloc_error_generation_stop();
826 if (rsc_cdc_mem_alloc_count) stepinfo("\n");
827
828 /* Finally disconnect the device. */
829 ux_device_stack_disconnect();
830
831 /* And deinitialize the class. */
832 status = ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
833
834 /* Deinitialize the device side of usbx. */
835 _ux_device_stack_uninitialize();
836
837 /* And finally the usbx system resources. */
838 _ux_system_uninitialize();
839
840 /* Successful test. */
841 printf("SUCCESS!\n");
842 test_control_return(0);
843
844 }
845
ux_test_thread_slave_simulation_entry(ULONG arg)846 void ux_test_thread_slave_simulation_entry(ULONG arg)
847 {
848
849 while(1)
850 {
851 /* Sleep so ThreadX on Win32 will delete this thread. */
852 tx_thread_sleep(10);
853 }
854 }
855