1 /* This test is designed to test the _ux_host_stack_hcd_thread_entry. */
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_stack.h"
9 #include "ux_host_class_dpump.h"
10 #include "ux_device_class_dpump.h"
11
12
13 /* Define USBX test constants. */
14
15 #define UX_TEST_STACK_SIZE 4096
16 #define UX_TEST_BUFFER_SIZE 2048
17 #define UX_TEST_RUN 1
18 #define UX_TEST_MEMORY_SIZE (64*1024)
19
20
21 /* Define the counters used in the test application... */
22
23 static ULONG thread_0_counter;
24 static ULONG thread_1_counter;
25 static ULONG error_counter;
26
27 static ULONG hcd_thread_counter[UX_MAX_HCD];
28
29 static ULONG error_callback_ignore = UX_FALSE;
30
31
32 /* Define USBX test global variables. */
33
34 static unsigned char host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
35 static unsigned char host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
36 static unsigned char slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
37
38 static UX_HOST_CLASS *class_driver;
39 static UX_HOST_CLASS_DPUMP *dpump;
40 static UX_SLAVE_CLASS_DPUMP *dpump_slave;
41
42
43 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50
44 static UCHAR device_framework_full_speed[] = {
45
46 /* Device descriptor */
47 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
48 0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x01,
50
51 /* Configuration descriptor */
52 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
53 0x32,
54
55 /* Interface descriptor */
56 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
57 0x00,
58
59 /* Endpoint descriptor (Bulk Out) */
60 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
61
62 /* Endpoint descriptor (Bulk In) */
63 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
64 };
65
66
67 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60
68 static UCHAR device_framework_high_speed[] = {
69
70 /* Device descriptor */
71 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
72 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
73 0x03, 0x01,
74
75 /* Device qualifier descriptor */
76 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
77 0x01, 0x00,
78
79 /* Configuration descriptor */
80 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
81 0x32,
82
83 /* Interface descriptor */
84 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
85 0x00,
86
87 /* Endpoint descriptor (Bulk Out) */
88 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
89
90 /* Endpoint descriptor (Bulk In) */
91 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
92 };
93
94 /* String Device Framework :
95 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
96 Byte 2 : Byte containing the index of the descriptor
97 Byte 3 : Byte containing the length of the descriptor string
98 */
99
100 #define STRING_FRAMEWORK_LENGTH 38
101 static UCHAR string_framework[] = {
102
103 /* Manufacturer string descriptor : Index 1 */
104 0x09, 0x04, 0x01, 0x0c,
105 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
106 0x6f, 0x67, 0x69, 0x63,
107
108 /* Product string descriptor : Index 2 */
109 0x09, 0x04, 0x02, 0x0c,
110 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
111 0x44, 0x65, 0x6d, 0x6f,
112
113 /* Serial Number string descriptor : Index 3 */
114 0x09, 0x04, 0x03, 0x04,
115 0x30, 0x30, 0x30, 0x31
116 };
117
118
119 /* Multiple languages are supported on the device, to add
120 a language besides English, the unicode language code must
121 be appended to the language_id_framework array and the length
122 adjusted accordingly. */
123 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
124 static UCHAR language_id_framework[] = {
125
126 /* English. */
127 0x09, 0x04
128 };
129
130
131 /* Define prototypes for external Host Controller's (HCDs), classes and clients. */
132
133 static VOID ux_test_instance_activate(VOID *dpump_instance);
134 static VOID ux_test_instance_deactivate(VOID *dpump_instance);
135
136 UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
137 UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
138 ULONG requested_length, ULONG *actual_length);
139 UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
140 ULONG requested_length, ULONG *actual_length);
141
142 static TX_THREAD ux_test_thread_host_simulation;
143 static TX_THREAD ux_test_thread_slave_simulation;
144 static void ux_test_thread_host_simulation_entry(ULONG);
145 static void ux_test_thread_slave_simulation_entry(ULONG);
146
147
148 /* Define the ISR dispatch. */
149
150 extern VOID (*test_isr_dispatch)(void);
151
152
153 /* Prototype for test control return. */
154
155 void test_control_return(UINT status);
156
157
158 /* Define the ISR dispatch routine. */
159
test_isr(void)160 static void test_isr(void)
161 {
162
163 /* For further expansion of interrupt-level testing. */
164 }
165
166
error_callback(UINT system_level,UINT system_context,UINT error_code)167 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
168 {
169 if (error_callback_ignore != UX_TRUE &&
170 error_code != UX_CONFIGURATION_HANDLE_UNKNOWN)
171 {
172 /* Failed test. */
173 printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
174 test_control_return(1);
175 }
176 }
177
_ux_hcd_test_host_entry(UX_HCD * hcd,UINT function,VOID * parameter)178 UINT _ux_hcd_test_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
179 {
180
181 UINT status;
182
183
184 /* Check the status of the controller. */
185 if (hcd -> ux_hcd_status == UX_UNUSED)
186 {
187
188 /* Error trap. */
189 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_UNKNOWN);
190
191 /* If trace is enabled, insert this event into the trace buffer. */
192 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
193
194 return(UX_CONTROLLER_UNKNOWN);
195 }
196
197 hcd_thread_counter[hcd -> ux_hcd_io] ++;
198
199 /* look at the function and route it. */
200 switch(function)
201 {
202
203 case UX_HCD_GET_PORT_STATUS:
204
205 status = UX_PORT_INDEX_UNKNOWN;
206 break;
207 case UX_HCD_GET_FRAME_NUMBER:
208 case UX_HCD_DISABLE_CONTROLLER:
209 case UX_HCD_ENABLE_PORT:
210 case UX_HCD_DISABLE_PORT:
211 case UX_HCD_POWER_ON_PORT:
212 case UX_HCD_POWER_DOWN_PORT:
213 case UX_HCD_SUSPEND_PORT:
214 case UX_HCD_RESUME_PORT:
215 case UX_HCD_RESET_PORT:
216 case UX_HCD_SET_FRAME_NUMBER:
217 case UX_HCD_TRANSFER_REQUEST:
218 case UX_HCD_TRANSFER_ABORT:
219 case UX_HCD_CREATE_ENDPOINT:
220 case UX_HCD_DESTROY_ENDPOINT:
221 case UX_HCD_RESET_ENDPOINT:
222 case UX_HCD_PROCESS_DONE_QUEUE:
223
224 status = UX_SUCCESS;
225 break;
226
227
228 default:
229
230 /* Error trap. */
231 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED);
232
233 /* If trace is enabled, insert this event into the trace buffer. */
234 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
235
236 /* Unknown request, return an error. */
237 status = UX_FUNCTION_NOT_SUPPORTED;
238 }
239
240 /* Return completion status. */
241 return(status);
242 }
243
_ux_hcd_test_host_signal_event(UX_HCD * hcd)244 static void _ux_hcd_test_host_signal_event(UX_HCD *hcd)
245 {
246 hcd -> ux_hcd_thread_signal ++;
247 _ux_utility_semaphore_put(&_ux_system_host->ux_system_host_hcd_semaphore);
248 }
249
_ux_hcd_test_host_initialize(UX_HCD * hcd)250 UINT _ux_hcd_test_host_initialize(UX_HCD *hcd)
251 {
252
253 /* Initialize the function collector for this HCD. */
254 hcd -> ux_hcd_entry_function = _ux_hcd_test_host_entry;
255
256 /* Set the host controller into the operational state. */
257 hcd -> ux_hcd_status = UX_HCD_STATUS_OPERATIONAL;
258
259 /* Get the number of ports on the controller. The number of ports needs to be reflected both
260 for the generic HCD container and the local sim_host container. In the simulator,
261 the number of ports is hardwired to 1 only. */
262 hcd -> ux_hcd_nb_root_hubs = 1;
263
264 /* Something happened on this port. Signal it to the root hub thread. */
265 hcd -> ux_hcd_root_hub_signal[0] = 1;
266
267 /* We need to simulate a Root HUB Status Change for the USB stack since the simulator
268 has not root HUB per se. */
269 _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
270
271 /* Return successful completion. */
272 return(UX_SUCCESS);
273 }
274
275
276 /* Define what the initial system looks like. */
277
278 #ifdef CTEST
test_application_define(void * first_unused_memory)279 void test_application_define(void *first_unused_memory)
280 #else
281 void usbx_ux_host_stack_hcd_thread_entry_test_application_define(void *first_unused_memory)
282 #endif
283 {
284
285 UINT status;
286 CHAR *stack_pointer;
287 CHAR *memory_pointer;
288 UX_SLAVE_CLASS_DPUMP_PARAMETER parameter;
289
290
291 /* Inform user. */
292 printf("Running _ux_host_stack_hcd_thread_entry Test........................ ");
293
294 /* Initialize the free memory pointer. */
295 stack_pointer = (CHAR *) first_unused_memory;
296 memory_pointer = stack_pointer + (UX_TEST_STACK_SIZE * 2);
297
298 /* Initialize USBX Memory. */
299 status = ux_system_initialize(memory_pointer, UX_TEST_MEMORY_SIZE, UX_NULL, 0);
300
301 /* Check for error. */
302 if (status != UX_SUCCESS)
303 {
304
305 printf("ERROR #1\n");
306 test_control_return(1);
307 }
308
309 /* Register the error callback. */
310 _ux_utility_error_callback_register(error_callback);
311
312 /* The code below is required for installing the host portion of USBX. */
313 status = ux_host_stack_initialize(UX_NULL);
314
315 /* Check for error. */
316 if (status != UX_SUCCESS)
317 {
318
319 printf("ERROR #2\n");
320 test_control_return(1);
321 }
322
323 /* Register all the host class drivers for this USBX implementation. */
324 status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry);
325
326 /* Check for error. */
327 if (status != UX_SUCCESS)
328 {
329
330 printf("ERROR #3\n");
331 test_control_return(1);
332 }
333
334 /* The code below is required for installing the device portion of USBX */
335 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
336 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
337 string_framework, STRING_FRAMEWORK_LENGTH,
338 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
339
340 /* Check for error. */
341 if (status != UX_SUCCESS)
342 {
343
344 printf("ERROR #5\n");
345 test_control_return(1);
346 }
347
348 /* Set the parameters for callback when insertion/extraction of a Data Pump device. */
349 parameter.ux_slave_class_dpump_instance_activate = ux_test_instance_activate;
350 parameter.ux_slave_class_dpump_instance_deactivate = ux_test_instance_deactivate;
351
352 /* Initialize the device dpump class. The class is connected with interface 0 */
353 status = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
354 1, 0, ¶meter);
355
356 /* Check for error. */
357 if (status != UX_SUCCESS)
358 {
359
360 printf("ERROR #6\n");
361 test_control_return(1);
362 }
363
364 /* Initialize the simulated device controller. */
365 status = _ux_dcd_sim_slave_initialize();
366
367 /* Check for error. */
368 if (status != UX_SUCCESS)
369 {
370
371 printf("ERROR #7\n");
372 test_control_return(1);
373 }
374
375 /* Register all the USB host controllers available in this system */
376 hcd_thread_counter[0] = 0;
377 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
378
379 /* Check for error. */
380 if (status != UX_SUCCESS)
381 {
382
383 printf("ERROR #4\n");
384 test_control_return(1);
385 }
386
387 #if UX_MAX_HCD > 1
388 /* Register all the USB host controllers available in this system */
389 hcd_thread_counter[1] = 0;
390 status = ux_host_stack_hcd_register("hcd_test_driver 1", _ux_hcd_test_host_initialize, 1, 0);
391
392 /* Check for error. */
393 if (status != UX_SUCCESS)
394 {
395
396 printf("ERROR #4\n");
397 test_control_return(1);
398 }
399 #endif
400
401 /* Create the main host simulation thread. */
402 status = tx_thread_create(&ux_test_thread_host_simulation, "test host simulation", ux_test_thread_host_simulation_entry, 0,
403 stack_pointer, UX_TEST_STACK_SIZE,
404 20, 20, 1, TX_AUTO_START);
405
406 /* Check for error. */
407 if (status != TX_SUCCESS)
408 {
409
410 printf("ERROR #8\n");
411 test_control_return(1);
412 }
413 }
414
415
ux_test_thread_host_simulation_entry(ULONG arg)416 static void ux_test_thread_host_simulation_entry(ULONG arg)
417 {
418
419 UINT status;
420 UX_HOST_CLASS *class;
421
422 /* Find the main data pump container. */
423 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
424
425 /* Check for error. */
426 if (status != UX_SUCCESS)
427 {
428
429 /* DPUMP basic test error. */
430 printf("ERROR #10\n");
431 test_control_return(1);
432 }
433
434 /* We get the first instance of the data pump device. */
435 do
436 {
437
438 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
439 tx_thread_relinquish();
440 } while (status != UX_SUCCESS);
441
442 /* We still need to wait for the data pump status to be live. */
443 while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
444 {
445
446 tx_thread_relinquish();
447 }
448
449 /* At this point, the data pump class has been found. */
450
451 #if UX_MAX_HCD > 1
452 /* Check if thread entry is called once. */
453 if (hcd_thread_counter[1] != 1)
454 {
455 printf("ERROR #%d, %d\n", __LINE__, hcd_thread_counter[1]);
456 test_control_return(1);
457 }
458
459 /* Check if thread entry is called. */
460 _ux_hcd_test_host_signal_event(&_ux_system_host->ux_system_host_hcd_array[1]);
461 _ux_utility_delay_ms(10);
462 if (hcd_thread_counter[1] != 2)
463 {
464 printf("ERROR #%d, %d\n", __LINE__, hcd_thread_counter[1]);
465 test_control_return(1);
466 }
467
468 /* Check if thread entry is still called when first HCD unregistered. */
469 error_callback_ignore = UX_TRUE;
470 ux_host_stack_hcd_unregister(_ux_system_host_hcd_simulator_name, 0, 0);
471 _ux_utility_delay_ms(10);
472 if (_ux_system_host->ux_system_host_hcd_array[0].ux_hcd_status == UX_HCD_STATUS_OPERATIONAL)
473 {
474 printf("ERROR #%d, HCD unregister fail\n", __LINE__);
475 test_control_return(1);
476 }
477
478 _ux_hcd_test_host_signal_event(&_ux_system_host->ux_system_host_hcd_array[1]);
479 _ux_utility_delay_ms(10);
480 if (hcd_thread_counter[1] != 3)
481 {
482 printf("ERROR #%d, %d\n", __LINE__, hcd_thread_counter[1]);
483 test_control_return(1);
484 }
485 #endif
486
487 /* Sleep for a tick to make sure everything is complete. */
488 tx_thread_sleep(1);
489
490 /* Check for errors from other threads. */
491 if (error_counter)
492 {
493
494 /* Test error. */
495 printf("ERROR #14\n");
496 test_control_return(1);
497 }
498 else
499 {
500
501 /* Successful test. */
502 printf("SUCCESS!\n");
503 test_control_return(0);
504 }
505 }
506
ux_test_instance_activate(VOID * dpump_instance)507 static VOID ux_test_instance_activate(VOID *dpump_instance)
508 {
509
510 /* Save the DPUMP instance. */
511 dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
512 }
513
ux_test_instance_deactivate(VOID * dpump_instance)514 static VOID ux_test_instance_deactivate(VOID *dpump_instance)
515 {
516
517 /* Reset the DPUMP instance. */
518 dpump_slave = UX_NULL;
519 }
520
521