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 /* Define the ISR dispatch. */
179
180 extern VOID (*test_isr_dispatch)(void);
181
182
183 /* Prototype for test control return. */
184
185 void test_control_return(UINT status);
186
187
188 /* Define the ISR dispatch routine. */
189
test_isr(void)190 static void test_isr(void)
191 {
192
193 /* For further expansion of interrupt-level testing. */
194 }
195
break_on_cdc_acm_all_ready(VOID)196 static UINT break_on_cdc_acm_all_ready(VOID)
197 {
198 UINT status;
199 UX_HOST_CLASS *class;
200
201 /* Find the main cdc_acm container */
202 status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
203 if (status != UX_SUCCESS)
204 /* Do not break. */
205 return 0;
206
207 /* Find class instance. */
208 status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host_control);
209 if (status != UX_SUCCESS)
210 /* Do not break. */
211 return 0;
212
213 if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
214 /* Do not break. */
215 return 0;
216
217 /* Find class instance. */
218 status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host_data);
219 if (status != UX_SUCCESS)
220 /* Do not break. */
221 return 0;
222
223 if (cdc_acm_host_control->ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
224 /* Do not break. */
225 return 0;
226
227 if (cdc_acm_slave == UX_NULL)
228 /* Do not break. */
229 return 0;
230
231 /* All found, break. */
232 return 1;
233 }
234
break_on_removal(VOID)235 static UINT break_on_removal(VOID)
236 {
237
238 UINT status;
239 UX_DEVICE *device;
240
241 status = ux_host_stack_device_get(0, &device);
242 if (status == UX_SUCCESS)
243 /* Do not break. */
244 return UX_SUCCESS;
245
246 return 1;
247 }
248
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)249 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
250 {
251
252 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
253
254 switch(event)
255 {
256
257 case UX_DEVICE_INSERTION:
258
259 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
260 cdc_acm_host_control = cdc_acm;
261 else
262 cdc_acm_host_data = cdc_acm;
263 break;
264
265 case UX_DEVICE_REMOVAL:
266
267 if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
268 cdc_acm_host_control = UX_NULL;
269 else
270 cdc_acm_host_data = UX_NULL;
271 break;
272
273 default:
274 break;
275 }
276 return 0;
277 }
278
test_cdc_instance_activate(VOID * cdc_instance)279 static VOID test_cdc_instance_activate(VOID *cdc_instance)
280 {
281
282 /* Save the CDC instance. */
283 cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
284 }
test_cdc_instance_deactivate(VOID * cdc_instance)285 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
286 {
287
288 /* Reset the CDC instance. */
289 cdc_acm_slave = UX_NULL;
290 }
291
test_cdc_instance_parameter_change(VOID * cdc_instance)292 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
293 {
294
295 /* Set CDC parameter change flag. */
296 cdc_acm_slave_change = UX_TRUE;
297 }
298
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)299 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
300 {
301 error_callback_counter ++;
302
303 if (!error_callback_ignore)
304 {
305 {
306 /* Failed test. */
307 printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
308 // test_control_return(1);
309 }
310 }
311 }
312
313 /* Define what the initial system looks like. */
314
315 #ifdef CTEST
test_application_define(void * first_unused_memory)316 void test_application_define(void *first_unused_memory)
317 #else
318 void usbx_ux_host_class_cdc_acm_activate_test_application_define(void *first_unused_memory)
319 #endif
320 {
321
322 UINT status;
323 CHAR * stack_pointer;
324 CHAR * memory_pointer;
325
326
327 printf("Running ux_host_class_cdc_acm_activate Test......................... ");
328
329 /* Initialize the free memory pointer */
330 stack_pointer = (CHAR *) usbx_memory;
331 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
332
333 /* Initialize USBX Memory */
334 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
335 /* Check for error. */
336 if (status != UX_SUCCESS)
337 {
338
339 printf("ERROR #%d\n", __LINE__);
340 test_control_return(1);
341 }
342
343 /* Register the error callback. */
344 _ux_utility_error_callback_register(test_ux_error_callback);
345
346 /* The code below is required for installing the host portion of USBX */
347 status = ux_host_stack_initialize(UX_NULL);
348 if (status != UX_SUCCESS)
349 {
350
351 printf("ERROR #%d\n", __LINE__);
352 test_control_return(1);
353 }
354
355 /* Register CDC ACM class */
356 status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
357 if (status != UX_SUCCESS)
358 {
359
360 printf("ERROR #%d\n", __LINE__);
361 test_control_return(1);
362 }
363
364 /* The code below is required for installing the device portion of USBX. No call back for
365 device status change in this example. */
366 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
367 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
368 string_framework, STRING_FRAMEWORK_LENGTH,
369 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
370 if(status!=UX_SUCCESS)
371 {
372
373 printf("ERROR #%d\n", __LINE__);
374 test_control_return(1);
375 }
376
377 /* Set the parameters for callback when insertion/extraction of a CDC device. */
378 parameter.ux_slave_class_cdc_acm_instance_activate = test_cdc_instance_activate;
379 parameter.ux_slave_class_cdc_acm_instance_deactivate = test_cdc_instance_deactivate;
380 parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
381
382 /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
383 status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
384 1,0, ¶meter);
385
386 if(status!=UX_SUCCESS)
387 {
388
389 printf("ERROR #%d\n", __LINE__);
390 test_control_return(1);
391 }
392
393 /* Initialize the simulated device controller. */
394 status = _ux_test_dcd_sim_slave_initialize();
395
396 /* Check for error. */
397 if (status != TX_SUCCESS)
398 {
399
400 printf("ERROR #%d\n", __LINE__);
401 test_control_return(1);
402 }
403
404 /* Register HCD for test */
405 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
406 if (status != UX_SUCCESS)
407 {
408
409 printf("ERROR #%d\n", __LINE__);
410 test_control_return(1);
411 }
412
413 /* Create the main host simulation thread. */
414 status = tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_thread_host_simulation_entry, 0,
415 stack_pointer, UX_DEMO_STACK_SIZE,
416 20, 20, 1, TX_AUTO_START);
417
418 /* Check for error. */
419 if (status != TX_SUCCESS)
420 {
421
422 printf("ERROR #%d\n", __LINE__);
423 test_control_return(1);
424 }
425
426 /* Create the main slave simulation thread. */
427 status = tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
428 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
429 20, 20, 1, TX_AUTO_START);
430
431 /* Check for error. */
432 if (status != TX_SUCCESS)
433 {
434
435 printf("ERROR #%d\n", __LINE__);
436 test_control_return(1);
437 }
438 }
439
tx_test_thread_host_simulation_entry(ULONG arg)440 void tx_test_thread_host_simulation_entry(ULONG arg)
441 {
442
443 UINT status;
444
445 stepinfo("\n");
446
447 /* Test connect. */
448 stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
449 ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
450 ux_test_breakable_sleep(100, break_on_cdc_acm_all_ready);
451 if (!(cdc_acm_host_control && cdc_acm_host_data && cdc_acm_slave))
452 {
453
454 printf("ERROR #%d: connect fail\n", __LINE__);
455 test_control_return(1);
456 }
457
458 stepinfo(">>>>>>>>>>>>>>>> Deinitialize\n");
459
460 /* Deinitialize the class. */
461 status = ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
462
463 /* Deinitialize the device side of usbx. */
464 _ux_device_stack_uninitialize();
465
466 /* And finally the usbx system resources. */
467 _ux_system_uninitialize();
468
469 stepinfo(">>>>>>>>>>>>>>>> Dump results\n");
470
471 if (error_counter > 0)
472 {
473
474 /* Test error. */
475 printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
476 test_control_return(1);
477 }
478
479 /* Successful test. */
480 printf("SUCCESS!\n");
481 test_control_return(0);
482 }
483
tx_test_thread_slave_simulation_entry(ULONG arg)484 void tx_test_thread_slave_simulation_entry(ULONG arg)
485 {
486
487 while(1)
488 {
489
490 /* Sleep so ThreadX on Win32 will delete this thread. */
491 ux_utility_delay_ms(100);
492 }
493 }
494