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