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