1 #include <stdio.h>
2 #include "tx_api.h"
3 #include "ux_api.h"
4 #include "ux_system.h"
5 #include "ux_utility.h"
6 #include "ux_device_stack.h"
7 #include "ux_host_class_hub.h"
8 #include "ux_host_class_dpump.h"
9 #include "ux_test_dcd_sim_slave.h"
10 #include "ux_test_hcd_sim_host.h"
11 #include "ux_test_utility_sim.h"
12 #include "ux_test.h"
13 #include "ux_test_actions.h"
14 #include "ux_device_class_dummy.h"
15 #include "ux_dcd_sim_slave.h"
16 #include "ux_device_class_dummy_hub.h"
17
18 /* Define local constants. */
19
20 #define UX_TEST_HUB_PORT_STATUS_FULL_SPEED 0x0000
21
22 #define UX_DEMO_STACK_SIZE (4*1024)
23 #define UX_USBX_MEMORY_SIZE (128*1024)
24
25 /* Define structs. */
26
27 typedef struct DEVICE_INIT_DATA_STRUCT
28 {
29 UCHAR *framework;
30 ULONG framework_length;
31 UCHAR *hub_descriptor;
32 ULONG hub_descriptor_length;
33 UCHAR dont_enumerate;
34 } DEVICE_INIT_DATA;
35
36 /* Host */
37
38 static TX_THREAD g_thread_host;
39 static UCHAR g_thread_stack_host[UX_DEMO_STACK_SIZE];
40 static UX_HOST_CLASS *g_class_driver_host;
41 static UX_HOST_CLASS_HUB *g_hub_host;
42 static UX_HOST_CLASS_HUB *g_hub_host_from_system_change_function;
43 static UX_HOST_CLASS_DPUMP *g_dpump_host;
44 static UX_HOST_CLASS_DPUMP *g_dpump_host_from_system_change_function;
45
46 static TX_THREAD g_thread_cmd;
47 static UCHAR g_thread_cmd_stack[UX_DEMO_STACK_SIZE];
48 static ULONG g_thread_cmd_cmd = 0;
49 #define CMD_SET_AND_SEND_PORT_EVENT_1 0 /* 1 byte port 1 change. */
50 #define CMD_SET_AND_SEND_PORT_EVENT_2 1 /* 2 bytes port 1 change. */
51 #define CMD_SET_AND_SEND_PORT_EVENT_3 2 /* 2 bytes device change | port 1 change. */
52
53 #define UX_TEST_HOST_CHANGE_LOG_N 16
54 static struct {
55 ULONG event;
56 UX_HOST_CLASS *class;
57 VOID *instance;
58 } g_host_change_logs[UX_TEST_HOST_CHANGE_LOG_N];
59 static ULONG g_host_change_count;
60
61 /* Device */
62
63 static TX_THREAD g_thread_device;
64 static UCHAR g_thread_stack_device[UX_DEMO_STACK_SIZE];
65 static UX_DEVICE_CLASS_HUB *g_hub_device;
66 static UX_DEVICE_CLASS_HUB_PARAMS g_hub_device_parameter;
67
68 static UCHAR g_device_can_go;
69
70 /* Define local prototypes and definitions. */
71
72 static void thread_entry_host(ULONG arg);
73 static void thread_entry_device(ULONG arg);
74 static void thread_entry_cmd(ULONG arg);
75 static void post_init_host();
76 static void post_init_device();
77
78 /* Define device framework. */
79
80 static unsigned char default_device_framework[] = {
81
82 /* Device Descriptor */
83 0x12, /* bLength */
84 0x01, /* bDescriptorType */
85 0x00, 0x02, /* bcdUSB */
86 0x09, /* bDeviceClass - Hub */
87 0x00, /* bDeviceSubClass */
88 0x01, /* bDeviceProtocol */
89 0x40, /* bMaxPacketSize0 */
90 0x24, 0x04, /* idVendor */
91 0x12, 0x24, /* idProduct */
92 0xb2, 0x0b, /* bcdDevice */
93 0x00, /* iManufacturer */
94 0x00, /* iProduct */
95 0x00, /* iSerialNumber */
96 0x01, /* bNumConfigurations */
97
98 /* Configuration Descriptor */
99 0x09, /* bLength */
100 0x02, /* bDescriptorType */
101 0x19, 0x00, /* wTotalLength */
102 0x01, /* bNumInterfaces */
103 0x01, /* bConfigurationValue */
104 0x00, /* iConfiguration */
105 0xe0, /* bmAttributes - Self-powered */
106 0x01, /* bMaxPower */
107
108 /* Interface Descriptor */
109 0x09, /* bLength */
110 0x04, /* bDescriptorType */
111 0x00, /* bInterfaceNumber */
112 0x00, /* bAlternateSetting */
113 0x01, /* bNumEndpoints */
114 0x09, /* bInterfaceClass - Hub */
115 0x00, /* bInterfaceSubClass */
116 0x00, /* bInterfaceProtocol */
117 0x00, /* iInterface */
118
119 /* Endpoint Descriptor */
120 0x07, /* bLength */
121 0x05, /* bDescriptorType */
122 0x81, /* bEndpointAddress */
123 0x03, /* bmAttributes - Interrupt */
124 0x02, 0x00, /* wMaxPacketSize */
125 0x0c, /* bInterval */
126
127 };
128
129 static unsigned char default_hub_descriptor[] = {
130
131 /* Hub Descriptor */
132 0x09, /* bLength */
133 0x29, /* bDescriptorType */
134 0x02, /* bNbrPorts */
135 0x09, 0x00, /* wHubCharacteristics */
136 0x32, /* bPwrOn2PwrGood */
137 0x01, /* bHubContrCurrent */
138 0x00, /* DeviceRemovable */
139 0xff, /* PortPwrCtrlMask */
140
141 };
142
143 static unsigned char string_framework[] = {
144
145 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
146 0x09, 0x04, 0x01, 0x0c,
147 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
148 0x6f, 0x67, 0x69, 0x63,
149
150 /* Product string descriptor : Index 2 - "EL Composite device" */
151 0x09, 0x04, 0x02, 0x13,
152 0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
153 0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
154 0x69, 0x63, 0x65,
155
156 /* Serial Number string descriptor : Index 3 - "0001" */
157 0x09, 0x04, 0x03, 0x04,
158 0x30, 0x30, 0x30, 0x31
159 };
160
161
162 /* Multiple languages are supported on the device, to add
163 a language besides english, the unicode language code must
164 be appended to the language_id_framework array and the length
165 adjusted accordingly. */
166 static unsigned char language_id_framework[] = {
167
168 /* English. */
169 0x09, 0x04
170 };
171
172 static UCHAR dpump_framework[] = {
173
174 /* Device descriptor */
175 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
176 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
177 0x03, 0x01,
178
179 /* Device qualifier descriptor */
180 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
181 0x01, 0x00,
182
183 /* Configuration descriptor */
184 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
185 0x32,
186
187 /* Interface descriptor */
188 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
189 0x00,
190
191 /* Endpoint descriptor (Bulk Out) */
192 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
193
194 /* Endpoint descriptor (Bulk In) */
195 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
196 };
197
198 /* This function is invoked by the simulator when the control transfer is meant
199 for a device on the hub. */
hub_control_request_handler(UX_SLAVE_TRANSFER * transfer_request)200 static UINT hub_control_request_handler(UX_SLAVE_TRANSFER *transfer_request)
201 {
202
203 UX_SLAVE_DCD *dcd;
204 UX_SLAVE_DEVICE *device;
205 ULONG request_type;
206 ULONG request;
207 ULONG request_value;
208 ULONG request_index;
209 ULONG request_length;
210 UINT status = UX_ERROR;
211 UCHAR *original_framework;
212 ULONG original_framework_length;
213
214 /* Get the pointer to the DCD. */
215 dcd = &_ux_system_slave -> ux_system_slave_dcd;
216
217 /* Get the pointer to the device. */
218 device = &_ux_system_slave -> ux_system_slave_device;
219
220 /* Ensure that the Setup request has been received correctly. */
221 if (transfer_request -> ux_slave_transfer_request_completion_code == UX_SUCCESS)
222 {
223
224 /* Seems so far, the Setup request is valid. Extract all fields of
225 the request. */
226 request_type = *transfer_request -> ux_slave_transfer_request_setup;
227 request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
228 request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE);
229 request_index = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX);
230 request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
231
232 /* Filter for GET_DESCRIPTOR/SET_DESCRIPTOR commands. If the descriptor to be returned is not a standard descriptor,
233 treat the command as a CLASS command. */
234 if ((request == UX_GET_DESCRIPTOR || request == UX_SET_DESCRIPTOR) && (((request_value >> 8) & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_STANDARD))
235 {
236
237 /* This request is to be handled by the class layer. */
238 request_type &= (UINT)~UX_REQUEST_TYPE;
239 request_type |= UX_REQUEST_TYPE_CLASS;
240 }
241
242 /* Ensure it's not vendor. */
243 UX_TEST_ASSERT((request_type & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_VENDOR);
244
245 /* We don't support any class commands right now. */
246 UX_TEST_ASSERT((request_type & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_CLASS);
247
248 /* Here we proceed only the standard request we know of at the device level. */
249 switch (request)
250 {
251
252 case UX_GET_STATUS:
253
254 UX_TEST_ASSERT(0);
255 break;
256
257 case UX_CLEAR_FEATURE:
258
259 UX_TEST_ASSERT(0);
260 break;
261
262 case UX_SET_FEATURE:
263
264 UX_TEST_ASSERT(0);
265 break;
266
267 case UX_SET_ADDRESS:
268
269 /* Don't do anything. */
270 break;
271
272 case UX_GET_DESCRIPTOR:
273
274 /* We need to trick USBX into sending a different framework than
275 the hub's. */
276
277 original_framework = _ux_system_slave->ux_system_slave_device_framework;
278 original_framework_length = _ux_system_slave->ux_system_slave_device_framework_length;
279
280 /* USBX sends looks here for the framework, so just change it do
281 our liking. */
282 _ux_system_slave->ux_system_slave_device_framework = dpump_framework;
283 _ux_system_slave->ux_system_slave_device_framework_length = sizeof(dpump_framework);
284
285 /* Kindly ask USBX to send our descriptor. */
286 UX_TEST_CHECK_SUCCESS(_ux_device_stack_descriptor_send(request_value, request_index, request_length));
287
288 _ux_system_slave->ux_system_slave_device_framework = original_framework;
289 _ux_system_slave->ux_system_slave_device_framework_length = original_framework_length;
290
291 break;
292
293 case UX_SET_DESCRIPTOR:
294
295 UX_TEST_ASSERT(0);
296 break;
297
298 case UX_GET_CONFIGURATION:
299
300 UX_TEST_ASSERT(0);
301 break;
302
303 case UX_SET_CONFIGURATION:
304
305 /* Do nothing. */
306 break;
307
308 case UX_GET_INTERFACE:
309
310 UX_TEST_ASSERT(0);
311 break;
312
313 case UX_SET_INTERFACE:
314
315 /* Do nothing. */
316 break;
317
318 case UX_SYNCH_FRAME:
319
320 UX_TEST_ASSERT(0);
321 break;
322
323 default:
324
325 UX_TEST_ASSERT(0);
326 return(UX_ERROR);
327 }
328 return(UX_SUCCESS);
329 }
330 return(UX_ERROR);
331 }
332
class_dpump_get(void)333 static UINT class_dpump_get(void)
334 {
335
336 UX_HOST_CLASS *class;
337
338 /* Find the main dpump container. */
339 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class));
340
341 /* Get the class. */
342 UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &g_dpump_host));
343
344 /* We still need to wait for the dpump status to be live. */
345 UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&g_dpump_host -> ux_host_class_dpump_state, UX_HOST_CLASS_INSTANCE_LIVE));
346
347 /* In virtually all cases, we want the enumeration thread to be finished. */
348 ux_test_wait_for_enum_thread_completion();
349
350 /* Return success. */
351 return(UX_SUCCESS);
352 }
353
354 /* Leave all the fields null. */
355 static DEVICE_INIT_DATA default_device_init_data;
356
357 /* Define what the initial system looks like. */
358
initialize_hub_with_device_init_data(void * first_unused_memory,DEVICE_INIT_DATA * device_init_data)359 static void initialize_hub_with_device_init_data(void *first_unused_memory, DEVICE_INIT_DATA *device_init_data)
360 {
361
362 UCHAR *memory_pointer = (UCHAR *)first_unused_memory;
363
364 stepinfo("\n");
365
366 if (device_init_data->framework == UX_NULL)
367 {
368 device_init_data->framework = default_device_framework;
369 device_init_data->framework_length = sizeof(default_device_framework);
370 }
371
372 if (device_init_data->hub_descriptor == UX_NULL)
373 {
374 device_init_data->hub_descriptor = default_hub_descriptor;
375 device_init_data->hub_descriptor_length = sizeof(default_hub_descriptor);
376 }
377
378 /* Initialize USBX Memory. */
379 ux_system_initialize(memory_pointer, UX_USBX_MEMORY_SIZE, UX_NULL, 0);
380 memory_pointer += UX_USBX_MEMORY_SIZE;
381
382 /* It looks weird if this doesn't have a comment! */
383 ux_utility_error_callback_register(ux_test_error_callback);
384
385 /* Create the host thread. */
386 UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_host, "host thread", thread_entry_host, (ULONG)(ALIGN_TYPE)device_init_data,
387 g_thread_stack_host, UX_DEMO_STACK_SIZE,
388 30, 30, 1, TX_DONT_START));
389 UX_THREAD_EXTENSION_PTR_SET(&g_thread_host, device_init_data)
390 tx_thread_resume(&g_thread_host);
391
392 /* Create the slave thread. */
393 UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_device, "device thread", thread_entry_device, (ULONG)(ALIGN_TYPE)device_init_data,
394 g_thread_stack_device, UX_DEMO_STACK_SIZE,
395 30, 30, 1, TX_DONT_START));
396 UX_THREAD_EXTENSION_PTR_SET(&g_thread_device, device_init_data)
397 tx_thread_resume(&g_thread_device);
398
399 /* Create the command thread. */
400 UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_cmd, "cmd thread", thread_entry_cmd, 0,
401 g_thread_cmd_stack, UX_DEMO_STACK_SIZE,
402 30, 30, 1, TX_DONT_START));
403 }
404
initialize_hub(void * first_unused_memory)405 static void initialize_hub(void *first_unused_memory)
406 {
407
408 initialize_hub_with_device_init_data(first_unused_memory, &default_device_init_data);
409 }
410
class_hub_get(void)411 static UINT class_hub_get(void)
412 {
413
414 UX_HOST_CLASS *class;
415
416
417 /* Find the main dpump container. */
418 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_hub_name, &class));
419
420 /* Get the class. */
421 UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &g_hub_host));
422
423 /* We still need to wait for the dpump status to be live. */
424 UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&g_hub_host -> ux_host_class_hub_state, UX_HOST_CLASS_INSTANCE_LIVE));
425
426 /* Return success. */
427 return(UX_SUCCESS);
428 }
429
device_hub_instance_activate(VOID * instance)430 static VOID device_hub_instance_activate(VOID *instance)
431 {
432 g_hub_device = (UX_DEVICE_CLASS_HUB *)instance;
433 }
434
device_hub_instance_deactivate(VOID * instance)435 static VOID device_hub_instance_deactivate(VOID *instance)
436 {
437 g_hub_device = (UX_DEVICE_CLASS_HUB *)UX_NULL;
438 }
439
system_change_function(ULONG event,UX_HOST_CLASS * class,VOID * instance)440 static UINT system_change_function(ULONG event, UX_HOST_CLASS *class, VOID *instance)
441 {
442 if (g_host_change_count < UX_TEST_HOST_CHANGE_LOG_N)
443 {
444 g_host_change_logs[g_host_change_count].event = event;
445 g_host_change_logs[g_host_change_count].class = class;
446 g_host_change_logs[g_host_change_count].instance = instance;
447 g_host_change_count ++;
448 }
449
450 if (class == UX_NULL)
451 return(UX_SUCCESS);
452
453 if (!memcmp(class->ux_host_class_name, _ux_system_host_class_hub_name, strlen(_ux_system_host_class_hub_name)))
454 {
455 if (event == UX_DEVICE_INSERTION)
456 {
457 g_hub_host_from_system_change_function = instance;
458 }
459 else if (event == UX_DEVICE_REMOVAL)
460 {
461 g_hub_host_from_system_change_function = UX_NULL;
462 }
463 }
464 else if (!memcmp(class->ux_host_class_name, _ux_system_host_class_dpump_name, strlen(_ux_system_host_class_dpump_name)))
465 {
466 if (event == UX_DEVICE_INSERTION)
467 {
468 g_dpump_host_from_system_change_function = instance;
469 }
470 else if (event == UX_DEVICE_REMOVAL)
471 {
472 g_dpump_host_from_system_change_function = UX_NULL;
473 }
474 }
475 return(UX_SUCCESS);
476 }
thread_entry_cmd(ULONG arg)477 static void thread_entry_cmd(ULONG arg)
478 {
479 ULONG temp;
480 while(1)
481 {
482 if (g_hub_device)
483 {
484 switch(g_thread_cmd_cmd)
485 {
486 case CMD_SET_AND_SEND_PORT_EVENT_1:
487 _ux_device_class_hub_notify_change(g_hub_device, 1, 1);
488 break;
489 case CMD_SET_AND_SEND_PORT_EVENT_2:
490 _ux_device_class_hub_notify_change(g_hub_device, 1, 2);
491 break;
492 case CMD_SET_AND_SEND_PORT_EVENT_3:
493 temp = 0x3u;
494 _ux_device_class_hub_notify_changes(g_hub_device, (UCHAR*)&temp, 2);
495 break;
496 default:
497 break;
498 }
499 }
500 tx_thread_suspend(&g_thread_cmd);
501 }
502 }
set_and_send_port_event(UINT port_status,UINT port_change)503 static VOID set_and_send_port_event(UINT port_status, UINT port_change)
504 {
505
506 /* Setup the approriate fields in the hub instance. */
507 g_hub_device->port_status = port_status;
508 g_hub_device->port_change = port_change;
509
510 g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_1;
511 tx_thread_resume(&g_thread_cmd);
512 }
513
connect_device_to_hub_speed(UINT speed)514 static VOID connect_device_to_hub_speed(UINT speed)
515 {
516
517 set_and_send_port_event(speed | UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION | UX_HOST_CLASS_HUB_PORT_STATUS_POWER,
518 UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION);
519 }
520
connect_device_to_hub()521 static VOID connect_device_to_hub()
522 {
523 connect_device_to_hub_speed(UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED);
524 }
525
connect_device_to_hub_short_with_hub()526 static VOID connect_device_to_hub_short_with_hub()
527 {
528
529 /* Setup the approriate fields in the hub instance. */
530 g_hub_device->port_status = UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION | UX_HOST_CLASS_HUB_PORT_STATUS_POWER;
531 g_hub_device->port_change = UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION;
532
533 g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_3;
534 tx_thread_resume(&g_thread_cmd);
535 }
536
disconnect_device_from_hub()537 static VOID disconnect_device_from_hub()
538 {
539
540 /* Setup the approriate fields in the hub instance. */
541 g_hub_device->port_status = 0; /* Make sure the connection bit is off. */
542 g_hub_device->port_change = UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION;
543
544 g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_1;
545 tx_thread_resume(&g_thread_cmd);
546 }
547
thread_entry_host(ULONG device_init_data_ptr)548 static void thread_entry_host(ULONG device_init_data_ptr)
549 {
550
551 UX_DCD_SIM_SLAVE *dcd_sim_slave;
552 DEVICE_INIT_DATA *device_init_data;
553
554 UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr)
555
556 /* The code below is required for installing the device portion of USBX.
557 In this demo, DFU is possible and we have a call back for state change. */
558 UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_init_data->framework, device_init_data->framework_length,
559 device_init_data->framework, device_init_data->framework_length,
560 string_framework, sizeof(string_framework),
561 language_id_framework, sizeof(language_id_framework),
562 UX_NULL));
563
564 g_hub_device_parameter.instance_activate = device_hub_instance_activate;
565 g_hub_device_parameter.instance_deactivate = device_hub_instance_deactivate;
566 g_hub_device_parameter.descriptor = device_init_data->hub_descriptor;
567 g_hub_device_parameter.descriptor_length = device_init_data->hub_descriptor_length;
568
569 /* Initialize the device hub class. */
570 UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_device_class_hub_name, _ux_device_class_hub_entry, 1, 0, &g_hub_device_parameter));
571
572 /* The code below is required for installing the host portion of USBX. */
573 UX_TEST_CHECK_SUCCESS(ux_host_stack_initialize(system_change_function));
574
575 /* Register hub class. */
576 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_hub_name, ux_host_class_hub_entry));
577
578 #if UX_MAX_CLASS_DRIVER > 1
579 /* Register dpump class. */
580 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry));
581 #endif
582
583 /* Initialize the simulated device controller. */
584 UX_TEST_CHECK_SUCCESS(_ux_test_dcd_sim_slave_initialize());
585
586 /* Get the DCD sim slave. */
587 dcd_sim_slave = (UX_DCD_SIM_SLAVE *)_ux_system_slave->ux_system_slave_dcd.ux_slave_dcd_controller_hardware;
588
589 /* Set the hub control request handler. */
590 dcd_sim_slave->ux_dcd_sim_slave_dcd_control_request_process_hub = hub_control_request_handler;
591
592 if (!device_init_data->dont_enumerate)
593 {
594
595 /* Register all the USB host controllers available in this system. */
596 UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
597
598 /* Sim HCD init will put() the enum thread semaphore. */
599 ux_test_wait_for_enum_thread_completion();
600
601 /* Get the hub instance. */
602 class_hub_get();
603 }
604
605 /* Inform device. */
606 g_device_can_go = 1;
607
608 /* Call application. */
609 post_init_host();
610
611 /* Disconnect. */
612 ux_test_disconnect_slave_and_host_wait_for_enum_completion();
613
614 UX_TEST_ASSERT(ux_test_check_actions_empty() == UX_TRUE);
615
616 /* And finally the usbx system resources. */
617 _ux_system_uninitialize();
618
619 /* Successful test. */
620 printf("SUCCESS!\n");
621 test_control_return(0);
622 }
623
thread_entry_device(ULONG input)624 static void thread_entry_device(ULONG input)
625 {
626
627 /* Wait for host to give us the go ahead. */
628 UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&g_device_can_go, 1));
629
630 /* Call the application. */
631 post_init_device();
632 }
633