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 #include "ux_host_class_dummy.h"
9 #include "ux_device_class_dummy.h"
10 #include "ux_test.h"
11
12
13 /* Define USBX demo constants. */
14
15 #define UX_DEMO_STACK_SIZE 4096
16 #define UX_DEMO_BUFFER_SIZE 2048
17 #define UX_DEMO_RUN 1
18 #define UX_DEMO_MEMORY_SIZE (64*1024)
19
20
21 /* Define the counters used in the demo application... */
22
23 static ULONG thread_0_counter;
24 static ULONG thread_1_counter;
25 static ULONG error_counter;
26
27
28 /* Define USBX demo global variables. */
29
30 static UX_HOST_CLASS *class_driver;
31 static UX_HOST_CLASS_DUMMY *dummy;
32 static UX_DEVICE_CLASS_DUMMY *dummy_slave;
33
34 static UINT expected_error;
35
36 #define _W0(w) ( (w) & 0xFF)
37 #define _W1(w) (((w) >> 8) & 0xFF)
38
39 #define _DEVICE_DESCRIPTOR(cls, sub, protocol, pktsize, vid, pid, n_cfg) \
40 0x12, 0x01, 0x10, 0x01, \
41 (cls), (sub), (protocol), (pktsize), \
42 _W0(vid), _W1(vid), _W0(pid), _W1(pid), \
43 0x00, 0x00, 0x00, 0x00, 0x00, (n_cfg),
44
45 #define _QUALIFIER_DESCRIPTOR(cls, sub, protocol, n_cfg) \
46 0x0a, 0x06, 0x00, 0x02, \
47 (cls), (sub), (protocol), 0x40, (n_cfg), 0x00,
48
49 #define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
50 0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
51 0x00, 0xc0, 0x32,
52
53 #define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
54 0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
55
56 #define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
57 0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
58
59 #define _CONFIGURATION_TOTAL_LENGTH (9+9*3+7*4)
60 #define _CONFIGURATION_DESCRIPTORS(hs) \
61 _CONFIGURATION_DESCRIPTOR(_CONFIGURATION_TOTAL_LENGTH, 3, 1) \
62 _INTERFACE_DESCRIPTOR(0, 0, 1, 0x0E, 0x00, 0x00) \
63 _ENDPOINT_DESCRIPTOR(0x03, 0x02, 8, 0x04) \
64 _INTERFACE_DESCRIPTOR(1, 0, 2, 0x99, 0x99, 0x99) \
65 _ENDPOINT_DESCRIPTOR(0x01, 0x02, (hs) ? 512 : 64, 0x00) \
66 _ENDPOINT_DESCRIPTOR(0x82, 0x02, (hs) ? 512 : 64, 0x00) \
67 _INTERFACE_DESCRIPTOR(2, 0, 1, 0x0E, 0x00, 0x00) \
68 _ENDPOINT_DESCRIPTOR(0x84, 0x02,32, 0x04)
69
70 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
71 static UCHAR device_framework_full_speed[] = {
72 _DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 8, 0x08EC, 0x0001, 1)
73 _CONFIGURATION_DESCRIPTORS(0)
74 };
75
76
77 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
78 static UCHAR device_framework_high_speed[] = {
79 _DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 64, 0x08EC, 0x0001, 1)
80 _QUALIFIER_DESCRIPTOR(0, 0, 0, 1)
81 _CONFIGURATION_DESCRIPTORS(1)
82 };
83
84 /* String Device Framework :
85 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
86 Byte 2 : Byte containing the index of the descriptor
87 Byte 3 : Byte containing the length of the descriptor string
88 */
89 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
90 static UCHAR string_framework[] = {
91
92 /* Manufacturer string descriptor : Index 1 */
93 0x09, 0x04, 0x01, 0x0c,
94 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
95 0x6f, 0x67, 0x69, 0x63,
96
97 /* Product string descriptor : Index 2 */
98 0x09, 0x04, 0x02, 0x0c,
99 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
100 0x44, 0x65, 0x6d, 0x6f,
101
102 /* Serial Number string descriptor : Index 3 */
103 0x09, 0x04, 0x03, 0x04,
104 0x30, 0x30, 0x30, 0x31
105 };
106
107
108 /* Multiple languages are supported on the device, to add
109 a language besides English, the unicode language code must
110 be appended to the language_id_framework array and the length
111 adjusted accordingly. */
112 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
113 static UCHAR language_id_framework[] = {
114
115 /* English. */
116 0x09, 0x04
117 };
118
119
120 static UX_HOST_CLASS_DUMMY_QUERY _accept_0x99_0x99_0x99[] =
121 {
122 {.ux_host_class_query_on = UX_TRUE,
123 .ux_host_class_query_usage = UX_HOST_CLASS_COMMAND_USAGE_CSP,
124 .ux_host_class_query_class = 0x99,
125 .ux_host_class_query_subclass = 0x99,
126 .ux_host_class_query_protocol = 0x99},
127 {0}
128 };
129
130 /* Define prototypes for external Host Controller's (HCDs), classes and clients. */
131
132 static VOID tx_demo_instance_activate(VOID *dummy_instance);
133 static VOID tx_demo_instance_deactivate(VOID *dummy_instance);
134 static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy_instance);
135
136 #if defined(UX_HOST_STANDALONE)
137 static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
138 #else
139 #define tx_demo_host_change_function UX_NULL
140 #endif
141
142 UINT ux_hcd_sim_initialize(UX_HCD *hcd);
143
144 static TX_THREAD tx_demo_thread_host_simulation;
145 static TX_THREAD tx_demo_thread_slave_simulation;
146 static void tx_demo_thread_host_simulation_entry(ULONG);
147 static void tx_demo_thread_slave_simulation_entry(ULONG);
148
149
150 /* Define the ISR dispatch. */
151
152 extern VOID (*test_isr_dispatch)(void);
153
154
155 /* Prototype for test control return. */
156
157 void test_control_return(UINT status);
158
159
160 /* Define the ISR dispatch routine. */
161
test_isr(void)162 static void test_isr(void)
163 {
164
165 /* For further expansion of interrupt-level testing. */
166 }
167
168
error_callback(UINT system_level,UINT system_context,UINT error_code)169 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
170 {
171 if (expected_error == 0 || error_code != expected_error)
172 {
173 /* Failed test. */
174 printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
175 // test_control_return(1);
176 }
177 }
178
179 /* Define what the initial system looks like. */
180
181 #ifdef CTEST
test_application_define(void * first_unused_memory)182 void test_application_define(void *first_unused_memory)
183 #else
184 void usbx_class_multi_interface_enumeration_test_application_define(void *first_unused_memory)
185 #endif
186 {
187
188 UINT status;
189 CHAR *stack_pointer;
190 CHAR *memory_pointer;
191 UX_DEVICE_CLASS_DUMMY_PARAMETER parameter;
192
193
194 printf("Running Multiple Interface Class Enumeration Test................... ");
195
196 /* Initialize the free memory pointer. */
197 stack_pointer = (CHAR *) first_unused_memory;
198 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
199
200 /* Initialize USBX Memory. */
201 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
202
203 /* Check for error. */
204 if (status != UX_SUCCESS)
205 {
206
207 printf("ERROR #%d\n", __LINE__);
208 test_control_return(1);
209 }
210
211 /* Register the error callback. */
212 _ux_utility_error_callback_register(error_callback);
213
214 /* The code below is required for installing the host portion of USBX. */
215 status = ux_host_stack_initialize(tx_demo_host_change_function);
216
217 /* Check for error. */
218 if (status != UX_SUCCESS)
219 {
220
221 printf("ERROR #%d\n", __LINE__);
222 test_control_return(1);
223 }
224
225 /* Register all the host class drivers for this USBX implementation. */
226 status = ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_entry);
227
228 /* Check for error. */
229 if (status != UX_SUCCESS)
230 {
231
232 printf("ERROR #%d\n", __LINE__);
233 test_control_return(1);
234 }
235
236 /* The code below is required for installing the device portion of USBX */
237 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
238 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
239 string_framework, STRING_FRAMEWORK_LENGTH,
240 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
241
242 /* Check for error. */
243 if (status != UX_SUCCESS)
244 {
245
246 printf("ERROR #%d\n", __LINE__);
247 test_control_return(1);
248 }
249
250 /* Set the parameters for callback when insertion/extraction of a Data Pump device. */
251 _ux_utility_memory_set((void *)¶meter, 0x00, sizeof(parameter));
252 parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_activate = tx_demo_instance_activate;
253 parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_deactivate = tx_demo_instance_deactivate;
254 parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_change = tx_demo_instance_change;
255
256 /* Initialize the device dpump class. The class is connected with interface 0 */
257 _ux_host_class_dummy_query_reject_unknown_set(UX_TRUE);
258 _ux_host_class_dummy_query_list_set(_accept_0x99_0x99_0x99);
259 status = ux_device_stack_class_register(_ux_device_class_dummy_name, _ux_device_class_dummy_entry,
260 1, 0, ¶meter);
261
262 /* Check for error. */
263 if (status != UX_SUCCESS)
264 {
265
266 printf("ERROR #%d\n", __LINE__);
267 test_control_return(1);
268 }
269
270 /* Initialize the simulated device controller. */
271 status = _ux_dcd_sim_slave_initialize();
272
273 /* Check for error. */
274 if (status != UX_SUCCESS)
275 {
276
277 printf("ERROR #%d\n", __LINE__);
278 test_control_return(1);
279 }
280
281 /* Register all the USB host controllers available in this system */
282 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
283
284 /* Check for error. */
285 if (status != UX_SUCCESS)
286 {
287
288 printf("ERROR #%d\n", __LINE__);
289 test_control_return(1);
290 }
291
292 /* Create the main host simulation thread. */
293 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
294 stack_pointer, UX_DEMO_STACK_SIZE,
295 20, 20, 1, TX_AUTO_START);
296
297 /* Check for error. */
298 if (status != TX_SUCCESS)
299 {
300
301 printf("ERROR #%d\n", __LINE__);
302 test_control_return(1);
303 }
304
305 /* Create the main demo thread. */
306 status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
307 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
308 20, 20, 1, TX_AUTO_START);
309
310 /* Check for error. */
311 if (status != TX_SUCCESS)
312 {
313
314 printf("ERROR #%d\n", __LINE__);
315 test_control_return(1);
316 }
317 }
318
ux_demo_dummy_instance_check(VOID)319 static UINT ux_demo_dummy_instance_check(VOID)
320 {
321 UINT status;
322 UX_HOST_CLASS *cls;
323 status = ux_host_stack_class_get(_ux_host_class_dummy_name, &cls);
324 if (status != UX_SUCCESS)
325 return(status);
326 status = ux_host_stack_class_instance_get(cls, 0, (VOID **) &dummy);
327 if (status != UX_SUCCESS)
328 return(status);
329 if (dummy -> ux_host_class_dummy_state != UX_HOST_CLASS_INSTANCE_LIVE)
330 return(UX_NO_CLASS_MATCH);
331 return(UX_SUCCESS);
332 }
333
ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)334 static UINT ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)
335 {
336 ULONG t0 = tx_time_get(), t1;
337 while(1)
338 {
339 #if defined(UX_HOST_STANDALONE)
340 ux_system_tasks_run();
341 #endif
342 if (UX_SUCCESS == ux_demo_dummy_instance_check())
343 return(UX_SUCCESS);
344 tx_thread_relinquish();
345
346 /* Wait forever. */
347 if (wait_ticks == 0xFFFFFFFFul)
348 continue;
349
350 /* No wait. */
351 if (wait_ticks == 0)
352 break;
353
354 /* Check timeout. */
355 t1 = tx_time_get();
356 if (t1 >= t0)
357 t1 = t1 - t0;
358 else
359 t1 = 0xFFFFFFFFul - t0 + t1;
360 if (t1 > wait_ticks)
361 break;
362 }
363 return(UX_ERROR);
364 }
365
ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)366 static UINT ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)
367 {
368 ULONG t0 = tx_time_get(), t1;
369 while(1)
370 {
371 #if defined(UX_HOST_STANDALONE)
372 ux_system_tasks_run();
373 #endif
374 if (UX_SUCCESS != ux_demo_dummy_instance_check())
375 {
376 dummy = UX_NULL;
377 return(UX_SUCCESS);
378 }
379 tx_thread_relinquish();
380
381 /* Wait forever. */
382 if (wait_ticks == 0xFFFFFFFFul)
383 continue;
384
385 /* No wait. */
386 if (wait_ticks == 0)
387 break;
388
389 /* Check timeout. */
390 t1 = tx_time_get();
391 if (t1 >= t0)
392 t1 = t1 - t0;
393 else
394 t1 = 0xFFFFFFFFul - t0 + t1;
395 if (t1 > wait_ticks)
396 break;
397 }
398 return(UX_ERROR);
399 }
400
tx_demo_thread_host_simulation_entry(ULONG arg)401 static void tx_demo_thread_host_simulation_entry(ULONG arg)
402 {
403 UINT status;
404 UX_DEVICE *device;
405 UX_CONFIGURATION *configuration;
406 UX_INTERFACE *interface_ptr;
407 UX_ENDPOINT *endpoint;
408
409 stepinfo(">>>> Dummy Class Connection Wait\n");
410 status = ux_demo_dummy_instance_connect_wait(100);
411 if (status != UX_SUCCESS)
412 {
413 printf("ERROR #%d\n", __LINE__);
414 test_control_return(1);
415 }
416
417 stepinfo(">>>> Dummy Class Configuration Deactivate\n");
418 interface_ptr = dummy -> ux_host_class_dummy_interface;
419 configuration = interface_ptr -> ux_interface_configuration;
420 device = configuration -> ux_configuration_device;
421 status = ux_host_stack_device_configuration_deactivate(device);
422 if (status != UX_SUCCESS)
423 {
424 printf("ERROR #%d\n", __LINE__);
425 test_control_return(1);
426 }
427 status = ux_demo_dummy_instance_remove_wait(10);
428 if (status != UX_SUCCESS)
429 {
430 printf("ERROR #%d\n", __LINE__);
431 test_control_return(1);
432 }
433
434 stepinfo(">>>> Dummy Class Configuration Activate\n");
435 status = ux_host_stack_device_configuration_activate(configuration);
436 if (status != UX_SUCCESS)
437 {
438 printf("ERROR #%d\n", __LINE__);
439 test_control_return(1);
440 }
441 status = ux_demo_dummy_instance_connect_wait(100);
442 if (status != UX_SUCCESS)
443 {
444 printf("ERROR #%d\n", __LINE__);
445 test_control_return(1);
446 }
447
448 #if UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_ALL
449 stepinfo(">>>> Check physical endpoints (create all)\n");
450 status = ux_host_stack_configuration_interface_get(configuration, 0, 0, &interface_ptr);
451 UX_TEST_CHECK_SUCCESS(status);
452 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
453 UX_TEST_CHECK_SUCCESS(status);
454 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
455
456 status = ux_host_stack_configuration_interface_get(configuration, 1, 0, &interface_ptr);
457 UX_TEST_CHECK_SUCCESS(status);
458 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
459 UX_TEST_CHECK_SUCCESS(status);
460 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
461 status = ux_host_stack_interface_endpoint_get(interface_ptr, 1, &endpoint);
462 UX_TEST_CHECK_SUCCESS(status);
463 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
464
465 status = ux_host_stack_configuration_interface_get(configuration, 2, 0, &interface_ptr);
466 UX_TEST_CHECK_SUCCESS(status);
467 UX_TEST_CHECK_SUCCESS(status);
468 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
469 UX_TEST_CHECK_SUCCESS(status);
470 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
471
472 #elif UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED
473 stepinfo(">>>> Check physical endpoints (create owned)\n");
474 status = ux_host_stack_configuration_interface_get(configuration, 0, 0, &interface_ptr);
475 UX_TEST_CHECK_SUCCESS(status);
476 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
477 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed == UX_NULL);
478
479 status = ux_host_stack_configuration_interface_get(configuration, 1, 0, &interface_ptr);
480 UX_TEST_CHECK_SUCCESS(status);
481 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
482 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
483 status = ux_host_stack_interface_endpoint_get(interface_ptr, 1, &endpoint);
484 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
485
486 status = ux_host_stack_configuration_interface_get(configuration, 2, 0, &interface_ptr);
487 UX_TEST_CHECK_SUCCESS(status);
488 status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
489 UX_TEST_ASSERT(endpoint -> ux_endpoint_ed == UX_NULL);
490
491 #endif
492
493 expected_error = 0;
494
495 /* Sleep for a tick to make sure everything is complete. */
496 tx_thread_sleep(1);
497
498 /* Check for errors from other threads. */
499 if (error_counter)
500 {
501
502 /* DPUMP error. */
503 printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
504 test_control_return(1);
505 }
506 else
507 {
508
509 /* Successful test. */
510 printf("SUCCESS!\n");
511 test_control_return(0);
512 }
513 }
514
515
tx_demo_thread_slave_simulation_entry(ULONG arg)516 static void tx_demo_thread_slave_simulation_entry(ULONG arg)
517 {
518
519 UINT status;
520 ULONG actual_length;
521
522
523 while(1)
524 {
525 #if defined(UX_DEVICE_STANDALONE)
526
527 /* Run device tasks. */
528 ux_system_tasks_run();
529 #endif
530 /* Increment thread counter. */
531 thread_1_counter++;
532
533 /* Relinquish to other thread. */
534 tx_thread_relinquish();
535 }
536 }
537
tx_demo_instance_activate(VOID * inst)538 static VOID tx_demo_instance_activate(VOID *inst)
539 {
540 dummy_slave = (UX_DEVICE_CLASS_DUMMY *)inst;
541 }
542
tx_demo_instance_deactivate(VOID * inst)543 static VOID tx_demo_instance_deactivate(VOID *inst)
544 {
545 dummy_slave = UX_NULL;
546 }
547
tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY * dummy)548 static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy)
549 {
550 UX_PARAMETER_NOT_USED(dummy);
551 }
552
553 #if defined(UX_HOST_STANDALONE)
tx_demo_host_change_function(ULONG e,UX_HOST_CLASS * c,VOID * p)554 static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
555 {
556 if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
557 {
558 tx_thread_relinquish();
559 }
560 }
561 #endif
562