1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** USBX Component                                                        */
15 /**                                                                       */
16 /**   Device Stack                                                        */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 #define UX_SOURCE_CODE
22 
23 /* Include necessary system files.  */
24 
25 #include "ux_api.h"
26 #include "ux_host_stack.h"
27 
28 #if defined(UX_HOST_STANDALONE)
29 
30 
31 #define UX_HOST_STACK_ENUM_TRANS_ERROR(t)       (                               \
32     (t)->ux_transfer_request_completion_code != UX_SUCCESS ||                   \
33     (t)->ux_transfer_request_actual_length !=                                   \
34         (t)->ux_transfer_request_requested_length)
35 
36 static inline VOID _ux_host_stack_port_check_run(VOID);
37 static inline VOID _ux_host_stack_enum_run(VOID);
38 static inline VOID _ux_host_stack_pending_transfers_run(VOID);
39 
40 
41 /**************************************************************************/
42 /*                                                                        */
43 /*  FUNCTION                                                 RELEASE      */
44 /*                                                                        */
45 /*    _ux_host_stack_tasks_run                              PORTABLE C    */
46 /*                                                             6.3.0      */
47 /*  AUTHOR                                                                */
48 /*                                                                        */
49 /*    Chaoqiong Xiao, Microsoft Corporation                               */
50 /*                                                                        */
51 /*  DESCRIPTION                                                           */
52 /*                                                                        */
53 /*    This function runs host stack and registered classes tasks.         */
54 /*                                                                        */
55 /*    It's valid only in standalone mode.                                 */
56 /*    It's non-blocking.                                                  */
57 /*                                                                        */
58 /*  INPUT                                                                 */
59 /*                                                                        */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    Completion State Status                                             */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    (ux_hcd_entry_function)               HCD function                  */
68 /*    (ux_host_class_task_function)         Host class task function      */
69 /*    (ux_system_host_change_function)      Host change callback function */
70 /*    (ux_system_host_enum_hub_function)    Host hub enumeration function */
71 /*    _ux_host_stack_rh_change_process      Host Root Hub process         */
72 /*    _ux_host_stack_device_address_set     Start process to set address  */
73 /*    _ux_host_stack_configuration_set      Start process to set config   */
74 /*    _ux_host_stack_device_descriptor_read Start process to read device  */
75 /*                                          descriptor                    */
76 /*    _ux_host_stack_new_configuration_create                             */
77 /*                                          Link a new configuration to   */
78 /*                                          a device                      */
79 /*    _ux_host_stack_configuration_instance_create                        */
80 /*                                          Create configuration instance */
81 /*    _ux_host_stack_transfer_run           Runs transfer state machine   */
82 /*    _ux_host_stack_class_device_scan      Query device class driver     */
83 /*    _ux_host_stack_class_interface_scan   Query interface class driver  */
84 /*    _ux_host_stack_interfaces_scan        Parse interfaces in a         */
85 /*                                          configuration                 */
86 /*    _ux_host_stack_device_remove          Remove a device               */
87 /*    _ux_utility_descriptor_parse          Parse a descriptor            */
88 /*    _ux_utility_memory_allocate           Allocate memory               */
89 /*    _ux_utility_memory_free               Free memory                   */
90 /*    _ux_utility_time_get                  Get current time tick         */
91 /*    _ux_system_error_handler              Error trap                    */
92 /*                                                                        */
93 /*  CALLED BY                                                             */
94 /*                                                                        */
95 /*    Application                                                         */
96 /*                                                                        */
97 /*  RELEASE HISTORY                                                       */
98 /*                                                                        */
99 /*    DATE              NAME                      DESCRIPTION             */
100 /*                                                                        */
101 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
102 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
103 /*                                            added standalone hub,       */
104 /*                                            used shared descriptor in   */
105 /*                                            device instance for enum,   */
106 /*                                            resulting in version 6.1.12 */
107 /*  10-31-2022     Chaoqiong Xiao           Modified comment(s),          */
108 /*                                            improved internal logic,    */
109 /*                                            fixed activation issue on   */
110 /*                                            no class linked interfaces, */
111 /*                                            resulting in version 6.2.0  */
112 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
113 /*                                            improved enum transfer,     */
114 /*                                            resulting in version 6.3.0  */
115 /*                                                                        */
116 /**************************************************************************/
_ux_host_stack_tasks_run(VOID)117 UINT _ux_host_stack_tasks_run(VOID)
118 {
119 
120 UX_HCD *hcd_inst;
121 ULONG hcd_index;
122 UX_HOST_CLASS *class_inst;
123 ULONG class_index;
124 
125     /* =========== Run all HCD tasks.  */
126     for (hcd_index = 0; hcd_index < UX_SYSTEM_HOST_MAX_HCD_GET(); hcd_index++)
127     {
128         hcd_inst = &_ux_system_host->ux_system_host_hcd_array[hcd_index];
129         if (hcd_inst -> ux_hcd_status != UX_HCD_STATUS_OPERATIONAL ||
130             hcd_inst -> ux_hcd_entry_function == UX_NULL)
131             continue;
132         hcd_inst -> ux_hcd_entry_function(hcd_inst, UX_HCD_TASKS_RUN, UX_NULL);
133     }
134 
135     /* =========== Run port check process.  */
136     _ux_host_stack_port_check_run();
137 
138     /* =========== Run enumeration process.  */
139     _ux_host_stack_enum_run();
140 
141     /* =========== Run classes tasks.  */
142     for (class_index = 0; class_index < UX_SYSTEM_HOST_MAX_CLASS_GET(); class_index++)
143     {
144         class_inst = &_ux_system_host->ux_system_host_class_array[class_index];
145         if ((class_inst -> ux_host_class_status == UX_UNUSED) ||
146             (class_inst -> ux_host_class_task_function == UX_NULL))
147             continue;
148         class_inst -> ux_host_class_task_function(class_inst);
149     }
150 
151     /* =========== Run pending transfer tasks.  */
152     _ux_host_stack_pending_transfers_run();
153 
154     /* =========== Run background tasks.  */
155     if (_ux_system_host -> ux_system_host_change_function)
156     {
157         _ux_system_host -> ux_system_host_change_function(
158                         UX_STANDALONE_WAIT_BACKGROUND_TASK, UX_NULL, UX_NULL);
159     }
160 
161     /* No idle report support now.  */
162     return (UX_STATE_WAIT);
163 }
164 
_ux_host_stack_port_check_run(VOID)165 static inline VOID _ux_host_stack_port_check_run(VOID)
166 {
167 #if UX_MAX_DEVICES > 1
168 
169     /* We try the hub first. For this we look into the USBX project
170         structure to see if there is at least one hub.  */
171     if (_ux_system_host->ux_system_host_enum_hub_function != UX_NULL)
172     {
173 
174         /* Yes, there is a HUB function, call it!  */
175         _ux_system_host->ux_system_host_enum_hub_function();
176     }
177 #endif
178 
179     /* Check root hub changes.  */
180     _ux_host_stack_rh_change_process();
181 }
182 
_ux_host_stack_rh_port_enable(UX_DEVICE * device)183 static inline UINT _ux_host_stack_rh_port_enable(UX_DEVICE *device)
184 {
185 UX_HCD          *hcd = UX_DEVICE_HCD_GET(device);
186 ALIGN_TYPE      port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device);
187     return hcd -> ux_hcd_entry_function(hcd, UX_HCD_ENABLE_PORT, (VOID *)port_index);
188 }
_ux_host_stack_rh_port_reset(UX_DEVICE * device)189 static inline UINT _ux_host_stack_rh_port_reset(UX_DEVICE *device)
190 {
191 UX_HCD          *hcd = UX_DEVICE_HCD_GET(device);
192 ALIGN_TYPE      port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device);
193     return hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_PORT, (VOID *)port_index);
194 }
_ux_host_stack_rh_port_status_get(UX_DEVICE * device)195 static inline UINT _ux_host_stack_rh_port_status_get(UX_DEVICE *device)
196 {
197 UX_HCD          *hcd = UX_DEVICE_HCD_GET(device);
198 ALIGN_TYPE      port_index = (ALIGN_TYPE)UX_DEVICE_PORT_LOCATION_GET(device);
199     return hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)port_index);
200 }
_ux_host_stack_enum_address_sent(UX_DEVICE * device)201 static inline VOID _ux_host_stack_enum_address_sent(UX_DEVICE *device)
202 {
203 
204     /* Address (request wValue) applied to device.  */
205     device -> ux_device_address = device -> ux_device_control_endpoint.
206                 ux_endpoint_transfer_request.ux_transfer_request_value & 0x7F;
207     device -> ux_device_state = UX_DEVICE_ADDRESSED;
208 
209     /* Unlock enumeration.  */
210     _ux_system_host -> ux_system_host_enum_lock = UX_NULL;
211 }
_ux_host_stack_enum_device_descriptor_parse0(UX_DEVICE * device,UCHAR * descriptor)212 static inline VOID _ux_host_stack_enum_device_descriptor_parse0(
213     UX_DEVICE *device, UCHAR *descriptor)
214 {
215 
216     /* Endpoint descriptor updated.  */
217     device -> ux_device_descriptor.bMaxPacketSize0 = descriptor[7];
218 
219     /* Update EP0 wMaxPacketSize.  */
220     device -> ux_device_control_endpoint.
221                 ux_endpoint_descriptor.wMaxPacketSize = descriptor[7];
222 }
_ux_host_stack_enum_configuration_descriptor_parse0(UX_DEVICE * device,UX_CONFIGURATION * configuration,UCHAR * descriptor)223 static inline VOID _ux_host_stack_enum_configuration_descriptor_parse0(
224     UX_DEVICE *device, UX_CONFIGURATION *configuration, UCHAR *descriptor)
225 {
226     /* This configuration must be linked to the device.  */
227     _ux_host_stack_new_configuration_create(device, configuration);
228 
229     /* The descriptor is in a packed format, parse it locally.  */
230     _ux_utility_descriptor_parse(descriptor,
231         _ux_system_configuration_descriptor_structure,
232         UX_CONFIGURATION_DESCRIPTOR_ENTRIES,
233         (UCHAR *) &configuration -> ux_configuration_descriptor);
234 }
_ux_host_stack_enum_configuration_read(UX_DEVICE * device)235 static inline UINT _ux_host_stack_enum_configuration_read(UX_DEVICE *device)
236 {
237 
238 UX_CONFIGURATION    *configuration;
239 UCHAR               *descriptor;
240 UX_ENDPOINT         *control_endpoint;
241 UX_TRANSFER         *transfer_request;
242 
243     /* Allocate configuration containter for the descriptor.  */
244     configuration = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
245                                                     sizeof(UX_CONFIGURATION));
246     if (configuration == UX_NULL)
247         return(UX_MEMORY_INSUFFICIENT);
248 
249     /* Need to allocate memory for the configuration descriptor the first time we read
250        only the configuration descriptor when we have the configuration descriptor, we have
251        the length of the entire configuration\interface\endpoint descriptors.  */
252     descriptor =  _ux_utility_memory_allocate(UX_SAFE_ALIGN,
253                     UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH);
254     if (descriptor == UX_NULL)
255     {
256         _ux_utility_memory_free(configuration);
257         return(UX_MEMORY_INSUFFICIENT);
258     }
259 
260     /* Save allocated configuration container.  */
261     device -> ux_device_enum_inst.configuration = configuration;
262 
263     /* Retrieve the pointer to the control endpoint and its transfer_request.  */
264     control_endpoint =  &device -> ux_device_control_endpoint;
265     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
266 
267     /* Create a transfer_request for the GET_DESCRIPTOR request.  */
268     transfer_request -> ux_transfer_request_data_pointer =      descriptor;
269     transfer_request -> ux_transfer_request_requested_length =  UX_CONFIGURATION_DESCRIPTOR_LENGTH;
270     transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
271     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN |
272                                                                 UX_REQUEST_TYPE_STANDARD |
273                                                                 UX_REQUEST_TARGET_DEVICE;
274     transfer_request -> ux_transfer_request_value =             (UINT)device -> ux_device_enum_index |
275                                                                 (UINT)(UX_CONFIGURATION_DESCRIPTOR_ITEM << 8);
276     transfer_request -> ux_transfer_request_index =             0;
277 
278     /* Transfer for wait.  */
279     UX_TRANSFER_STATE_RESET(transfer_request);
280     device -> ux_device_enum_trans = transfer_request;
281 
282     return(UX_SUCCESS);
283 }
_ux_host_stack_configuration_parsed(UX_DEVICE * device)284 static inline VOID _ux_host_stack_configuration_parsed(UX_DEVICE *device)
285 {
286 UINT            status;
287 
288     /* By default (error) configuration not activated.  */
289     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
290 
291     /* Query device class driver.  */
292     status =  _ux_host_stack_class_device_scan(device);
293     if (status == UX_SUCCESS)
294     {
295 
296         /* Prepare device activation.  */
297         device -> ux_device_enum_index = 0xFF;
298         device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE;
299         device -> ux_device_enum_inst.device = device;
300     }
301     else if (status == UX_NO_CLASS_MATCH)
302     {
303 
304         /* Query interface class driver.  */
305         status =  _ux_host_stack_class_interface_scan(device);
306         if (status == UX_SUCCESS)
307         {
308 
309             /* Prepare interfaces activation.  */
310             device -> ux_device_enum_index = 0;
311             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_SET;
312             device -> ux_device_enum_inst.configuration =
313                                         device -> ux_device_first_configuration;
314         }
315     }
316 }
317 
_ux_host_stack_device_enumerated(UX_DEVICE * device)318 static inline VOID _ux_host_stack_device_enumerated(UX_DEVICE *device)
319 {
320 
321     /* If trace is enabled, register this object.  */
322     UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_DEVICE,
323             UX_DEVICE_HCD_GET(device), UX_DEVICE_PARENT_GET(device),
324             UX_DEVICE_PORT_LOCATION_GET(device), 0);
325 
326     /* Check if there is unnecessary resource to free.  */
327     if (device -> ux_device_packed_configuration &&
328         device -> ux_device_packed_configuration_keep_count == 0)
329     {
330         _ux_utility_memory_free(device -> ux_device_packed_configuration);
331         device -> ux_device_packed_configuration = UX_NULL;
332     }
333 
334     /* Reset enumeration state.  */
335     device -> ux_device_enum_state = UX_STATE_IDLE;
336 
337     /* Unlock device EP0.  */
338     device -> ux_device_control_endpoint.ux_endpoint_transfer_request.
339                         ux_transfer_request_flags &= ~UX_TRANSFER_FLAG_LOCK;
340 
341     /* Disconnect from enumeration list.  */
342 
343     /* Clear enumeration flag to stop enumeration sequence.  */
344     device -> ux_device_flags &= ~UX_DEVICE_FLAG_ENUM;
345 
346     /* If HCD is dead or device disconnected, free device.  */
347     if (UX_DEVICE_HCD_GET(device) -> ux_hcd_status != UX_HCD_STATUS_OPERATIONAL ||
348         (device -> ux_device_enum_port_status & UX_PS_CCS) == 0)
349     {
350         _ux_host_stack_device_remove(UX_DEVICE_HCD_GET(device),
351                                      UX_DEVICE_PARENT_GET(device),
352                                      UX_DEVICE_PORT_LOCATION_GET(device));
353 
354         /* Done without notification.  */
355         return;
356     }
357 
358     /* Device connected and enumerated success/fail.  */
359 
360     /* For root hub, set root hub connection status.  */
361     if (UX_DEVICE_PARENT_IS_ROOTHUB(device))
362     {
363         UX_DEVICE_HCD_GET(device) -> ux_hcd_rh_device_connection |=
364                     (ULONG)(1 << UX_DEVICE_PORT_LOCATION_GET(device));
365     }
366 
367     /* If change function available, notify device connection.  */
368     if (_ux_system_host -> ux_system_host_change_function)
369     {
370         _ux_system_host -> ux_system_host_change_function(
371                         UX_DEVICE_CONNECTION, UX_NULL, (VOID*)device);
372     }
373 }
374 
_ux_host_stack_interface_activate_wait(UX_DEVICE * device,UX_HOST_CLASS_COMMAND * command)375 static inline UINT _ux_host_stack_interface_activate_wait(UX_DEVICE *device,
376     UX_HOST_CLASS_COMMAND *command)
377 {
378 UINT            status;
379 UX_INTERFACE    *interface_inst;
380 
381     command -> ux_host_class_command_container = device -> ux_device_enum_inst.ptr;
382     command -> ux_host_class_command_class_ptr = (device -> ux_device_enum_index == 0xFF) ?
383                 device -> ux_device_class :
384                 device -> ux_device_enum_inst.interface -> ux_interface_class;
385     command -> ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT;
386 
387     /* If there is no class linked, just next state.  */
388     if (command -> ux_host_class_command_class_ptr != UX_NULL)
389         status = command -> ux_host_class_command_class_ptr -> ux_host_class_entry_function(command);
390     else
391         status = UX_STATE_NEXT;
392 
393     /* No wait command or ready for next state.  */
394     if (status == UX_FUNCTION_NOT_SUPPORTED ||
395         status == UX_STATE_NEXT)
396     {
397 
398         /* Activate for device class driver.  */
399         if (device -> ux_device_enum_index == 0xFF)
400         {
401 
402             /* Enumeration done (class driver controls device configuration).  */
403             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE;
404             return(UX_STATE_NEXT);
405         }
406         else
407         {
408 
409             /* Activate next interface (default setting).  */
410             interface_inst = device -> ux_device_enum_inst.interface -> ux_interface_next_interface;
411             while(interface_inst != UX_NULL &&
412                 interface_inst -> ux_interface_descriptor.bAlternateSetting != 0)
413             {
414                 interface_inst = interface_inst -> ux_interface_next_interface;
415             }
416             if (interface_inst != UX_NULL)
417             {
418                 device -> ux_device_enum_inst.interface = interface_inst;
419                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE;
420                 return(UX_STATE_NEXT);
421             }
422 
423             /* Enumeration is done.  */
424             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE;
425             return(UX_STATE_NEXT);
426         }
427     }
428 
429     /* Error cases.  */
430     if (status < UX_STATE_NEXT)
431     {
432         device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
433         return(UX_STATE_NEXT);
434     }
435 
436     /* Keep waiting.  */
437     return(UX_STATE_WAIT);
438 }
439 
440 
_ux_host_stack_device_enum_run(UX_DEVICE * device)441 static inline VOID _ux_host_stack_device_enum_run(UX_DEVICE *device)
442 {
443 UX_INTERRUPT_SAVE_AREA
444 UINT                    status;
445 ULONG                   current_ms, elapsed_ms;
446 UX_TRANSFER             *trans;
447 UX_CONFIGURATION        *configuration;
448 UX_HOST_CLASS_COMMAND   class_command;
449 UCHAR                   *buffer;
450 INT                     immediate_state = UX_TRUE;
451 
452     /* Check if the device enumeration should be processed.  */
453     if ((device -> ux_device_flags & UX_DEVICE_FLAG_ENUM) == 0)
454         return;
455 
456     /* Enumeration lock check, devices not addressed should wait.  */
457     UX_DISABLE
458     if (_ux_system_host -> ux_system_host_enum_lock &&
459         device -> ux_device_address == 0)
460     {
461 
462         /* Check if the device is the one locks, others should wait.  */
463         if (device != _ux_system_host -> ux_system_host_enum_lock)
464         {
465 
466             /* Wait, return.  */
467             UX_RESTORE
468             return;
469         }
470     }
471     UX_RESTORE
472 
473     while (immediate_state)
474     {
475         switch (device -> ux_device_enum_state)
476         {
477         case UX_STATE_RESET:
478 
479             /* Reset retry counts.  */
480             device -> ux_device_enum_retry = UX_RH_ENUMERATION_RETRY;
481 
482             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_PORT_ENABLE;
483             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_ENABLE;
484             device -> ux_device_enum_port_status = UX_PS_CCS;
485 
486             /* Fall through.  */
487         case UX_HOST_STACK_ENUM_PORT_ENABLE:
488 
489             /* Lock enumeration any way.  */
490             _ux_system_host -> ux_system_host_enum_lock = device;
491 
492 #if UX_MAX_DEVICES > 1
493             if (UX_DEVICE_PARENT_IS_HUB(device))
494             {
495 
496                 /* Issue a port reset on hub side.  */
497                 device -> ux_device_flags |= UX_DEVICE_FLAG_RESET;
498                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_HUB_OPERATION_WAIT;
499                 return;
500             }
501 #endif
502 
503             /* For device connected to roohub, we may need port enable (OHCI).  */
504             status = _ux_host_stack_rh_port_enable(device);
505             if (status == UX_PORT_INDEX_UNKNOWN)
506             {
507 
508                 /* No retry, enumeration fail.  */
509                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
510                 continue;
511             }
512 
513             /* Wait a while after port connection.  */
514             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_RESET;
515             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT;
516             device -> ux_device_enum_wait_start = _ux_utility_time_get();
517             device -> ux_device_enum_wait_ms =
518                         UX_MS_TO_TICK_NON_ZERO(UX_RH_ENUMERATION_RETRY_DELAY);
519             continue;
520 
521 #if UX_MAX_DEVICES > 1
522         case UX_HOST_STACK_ENUM_HUB_OPERATION_WAIT:
523 
524             /* Keep waiting, state is changed in hub tasks.  */
525             return;
526 #endif
527 
528         case UX_HOST_STACK_ENUM_PORT_RESET:
529 
530             /* Reset may blocking, wait the reset done.  */
531             /* Fall through.  */
532         case UX_HOST_STACK_ENUM_PORT_RESET_WAIT:
533 
534             /* Run states for reset.  */
535             status = _ux_host_stack_rh_port_reset(device);
536 
537             /* Check fatal error (exit enumeration).  */
538             if (status < UX_STATE_ERROR)
539             {
540 
541                 /* Fail no retry.  */
542                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
543                 continue;
544             }
545 
546             /* Check error.  */
547             if (status == UX_STATE_ERROR)
548             {
549 
550                 /* Fail retry.  */
551                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
552                 continue;
553             }
554 
555             /* Ready for next state.  */
556             if (status == UX_STATE_NEXT)
557             {
558 
559                 /* Return device address to 0.  */
560 #if UX_MAX_DEVICES > 1
561                 if (device -> ux_device_address)
562                 {
563 
564                     /* Free the address.  */
565                     UX_DEVICE_HCD_GET(device) ->
566                     ux_hcd_address[(device -> ux_device_address-1) >> 3] &=
567                         (UCHAR)(1u << ((device -> ux_device_address-1) & 7u));
568                 }
569 #endif
570 
571                 /* Get port status.  */
572                 status = _ux_host_stack_rh_port_status_get(device);
573                 if (status == UX_PORT_INDEX_UNKNOWN)
574                 {
575 
576                     /* Fail no retry: No connection.  */
577                     device -> ux_device_enum_port_status = 0;
578                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
579                     continue;
580                 }
581 
582                 /* Save port status, next : SetAddress.  */
583                 device -> ux_device_enum_port_status = (UCHAR)status;
584                 device -> ux_device_enum_trans = &device ->
585                         ux_device_control_endpoint.ux_endpoint_transfer_request;
586                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT;
587                 device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_ADDR_SET;
588                 continue;
589             }
590 
591             /* Keep waiting.  */
592             return;
593 
594         case UX_HOST_STACK_ENUM_DEVICE_ADDR_SET:
595 
596             /* Check port connection status.  */
597             if ((device -> ux_device_enum_port_status & UX_PS_CCS) == 0)
598             {
599 
600                 /* Port disconnected, no retry, just fail.  */
601                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
602                 continue;
603             }
604 
605             /* Set device speed.  */
606             device -> ux_device_speed = device -> ux_device_enum_port_status >> UX_PS_DS;
607 
608             /* Reset bMaxPacketSize0.  */
609             device -> ux_device_descriptor.bMaxPacketSize0 = 0;
610 
611             /* Start SetAddress().  */
612             status = _ux_host_stack_device_address_set(device);
613             if (status != UX_SUCCESS)
614             {
615 
616                 /* Request fail, retry.  */
617                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
618                 continue;
619             }
620 
621             /* Wait request progress done.  */
622             UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans);
623             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
624             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_ADDR_SENT;
625             continue;
626 
627         case UX_HOST_STACK_ENUM_DEVICE_ADDR_SENT:
628 
629             /* Transfer error check.  */
630             trans = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
631             if (trans -> ux_transfer_request_completion_code != UX_SUCCESS)
632             {
633                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
634                 continue;
635             }
636 
637             /* Address is already sent to device.  */
638             _ux_host_stack_enum_address_sent(device);
639 
640             /* Wait at least 2ms after address is sent.  */
641             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_READ;
642             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT;
643             device -> ux_device_enum_wait_start = _ux_utility_time_get();
644             device -> ux_device_enum_wait_ms = UX_MS_TO_TICK_NON_ZERO(2);
645             continue;
646 
647         case UX_HOST_STACK_ENUM_DEVICE_DESCR_READ:
648 
649             /* Start GetDescriptor(Device).  */
650             status = _ux_host_stack_device_descriptor_read(device);
651             if (status != UX_SUCCESS)
652             {
653                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
654                 continue;
655             }
656             UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans);
657             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
658             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE;
659             continue;
660 
661         case UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE:
662 
663             /* Transfer error check.  */
664             trans = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
665             buffer = trans -> ux_transfer_request_data_pointer;
666             if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans))
667             {
668                 _ux_utility_memory_free(buffer);
669                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
670                 continue;
671             }
672 
673             /* Device bMaxPacketSize0 not available, update it.  */
674             if(device -> ux_device_descriptor.bMaxPacketSize0 == 0)
675             {
676                 /* Validate the bMaxPacketSize0.  */
677                 if (buffer[7] != 8 && buffer[7] != 16 && buffer[7] != 32 && buffer[7] != 64)
678                 {
679 
680                     _ux_utility_memory_free(buffer);
681                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
682                     continue;
683                 }
684 
685                 /* Validate the USB-IF bDeviceClass class code.  */
686 #if defined(UX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE)
687                 switch(buffer[4])
688                 {
689                 case 0x00: /* Fall through.  */
690                 case 0x02: /* Fall through.  */
691                 case 0x09: /* Fall through.  */
692                 case 0x11: /* Fall through.  */
693                 case 0xDC: /* Fall through.  */
694                 case 0xEF: /* Fall through.  */
695                 case 0xFF:
696                     break;
697                 default:
698 
699                     /* Invalid device class code.  */
700                     _ux_utility_memory_free(buffer);
701                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
702                     continue;
703                 }
704 #endif
705 
706                 _ux_host_stack_enum_device_descriptor_parse0(device, buffer);
707 
708                 /* Update SETUP wLength.  */
709                 trans -> ux_transfer_request_requested_length = UX_DEVICE_DESCRIPTOR_LENGTH;
710 
711                 /* Issue GetDescriptor(Device) again and parse it.  */
712                 device -> ux_device_enum_trans = trans;
713                 UX_TRANSFER_STATE_RESET(trans);
714                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
715                 device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_DEVICE_DESCR_PARSE;
716                 continue;
717             }
718 
719             /* Parse the device descriptor.  */
720             _ux_utility_descriptor_parse(buffer,
721                 _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES,
722                 (UCHAR *) &device -> ux_device_descriptor);
723             _ux_utility_memory_free(buffer);
724             trans -> ux_transfer_request_data_pointer = UX_NULL;
725 
726             /* Start configuration enumeration, from index 0.  */
727             device -> ux_device_enum_index = 0;
728 
729             /* Fall through.  */
730         case UX_HOST_STACK_ENUM_CONFIG_DESCR_READ:
731 
732             /* Start GetDescriptor(Configuration, 9).  */
733             status = _ux_host_stack_enum_configuration_read(device);
734             if (status != UX_SUCCESS)
735             {
736                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
737                 continue;
738             }
739             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
740             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE;
741 
742             /* In this case, there are two memory blocks allocated floating:
743                - UX_CONFIGURATION
744                - configuration descriptor RX buffer.  */
745             continue;
746 
747         case UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE:
748 
749             /* Transfer error check.  */
750             trans = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
751             buffer = trans -> ux_transfer_request_data_pointer;
752             if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans))
753             {
754                 _ux_utility_memory_free(buffer);
755                 _ux_utility_memory_free(device -> ux_device_enum_inst.ptr);
756                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
757                 continue;
758             }
759 
760             /* Load current parsing configuration.  */
761             configuration = device -> ux_device_enum_inst.configuration;
762 
763             /* Get configuration descriptor only.  */
764             if (trans -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)
765             {
766 
767                 /* Parse the configuration descriptor and free descriptor buffer.  */
768                 _ux_host_stack_enum_configuration_descriptor_parse0(device, configuration, buffer);
769 
770                 /* Release descriptor buffer.  */
771                 _ux_utility_memory_free(buffer);
772                 trans -> ux_transfer_request_data_pointer = UX_NULL;
773 
774                 /* If there is no interface for the configuration, check next.  */
775                 if (configuration -> ux_configuration_descriptor.wTotalLength ==
776                     UX_CONFIGURATION_DESCRIPTOR_LENGTH)
777                 {
778                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_NEXT;
779                     continue;
780                 }
781 
782                 /* Allocate new buffer for total configuration.  */
783                 buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN,
784                     UX_CACHE_SAFE_MEMORY,
785                     configuration -> ux_configuration_descriptor.wTotalLength);
786                 if (buffer == UX_NULL)
787                 {
788                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
789                     continue;
790                 }
791                 trans -> ux_transfer_request_data_pointer = buffer;
792 
793                 /* Modify transfer length for total configuration  */
794                 trans -> ux_transfer_request_requested_length =
795                     configuration -> ux_configuration_descriptor.wTotalLength;
796 
797                 /* Start transfer again.  */
798                 device -> ux_device_enum_trans = trans;
799                 UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans);
800                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
801                 device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE;
802 
803                 /* In this case, there is one memory blocks allocated floating:
804                     - configuration descriptor RX buffer.  */
805                 continue;
806             }
807 
808             /* Parse configuration and it's interfaces.  */
809             status = _ux_host_stack_interfaces_scan(configuration, buffer);
810 
811             /* Release descriptor memory.  */
812             _ux_utility_memory_free(buffer);
813             trans -> ux_transfer_request_data_pointer = UX_NULL;
814 
815             /* Check operation status.  */
816             if (status != UX_SUCCESS)
817             {
818                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
819                 continue;
820             }
821 
822             /* Enumerate next configuration.  */
823             /* Fall through.  */
824         case UX_HOST_STACK_ENUM_CONFIG_DESCR_NEXT:
825             device -> ux_device_enum_index ++;
826             if (device -> ux_device_enum_index <
827                 device -> ux_device_descriptor.bNumConfigurations)
828             {
829                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_CONFIG_DESCR_READ;
830                 continue;
831             }
832 
833             /* All configurations are enumerated.  */
834             _ux_host_stack_configuration_parsed(device);
835 
836             /* Roll back to next state.  */
837             continue;
838 
839         case UX_HOST_STACK_ENUM_CONFIG_SET:
840 
841             /* The device is now in the unconfigured state. We need to deal
842                with the amount of power the device is consuming before allowing
843                it to be configured. Otherwise we may run the risk of an over
844                current fault. */
845             configuration = device -> ux_device_enum_inst.configuration;
846             if (((configuration -> ux_configuration_descriptor.bmAttributes &
847                     UX_CONFIGURATION_DEVICE_SELF_POWERED) == 0) &&
848                  (configuration -> ux_configuration_descriptor.MaxPower >
849                     UX_DEVICE_MAX_POWER_GET(device)))
850             {
851 
852                 /* Error trap. */
853                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_OVER_CURRENT_CONDITION);
854 
855                 /* If trace is enabled, insert this event into the trace buffer.  */
856                 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_OVER_CURRENT_CONDITION, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0)
857 
858                 /* Enumeration fail without retry.  */
859                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
860                 continue;
861             }
862 
863             /* Prepare transfer request SetConfiguration().  */
864             _ux_host_stack_configuration_set(configuration);
865 
866             /* Roll back to start transfer wait.  */
867             UX_TRANSFER_STATE_RESET(device -> ux_device_enum_trans);
868             device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_CONFIG_ACTIVATE;
869             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_TRANS_WAIT;
870             continue;
871 
872         case UX_HOST_STACK_ENUM_CONFIG_ACTIVATE:
873             trans = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
874             if (UX_HOST_STACK_ENUM_TRANS_ERROR(trans))
875             {
876                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
877                 continue;
878             }
879 
880             /* Set device state to configured.  */
881             configuration = device -> ux_device_enum_inst.configuration;
882             device -> ux_device_state = UX_DEVICE_CONFIGURED;
883             device -> ux_device_current_configuration = configuration;
884 
885             /* Create the configuration instance.  */
886             status =  _ux_host_stack_configuration_instance_create(configuration);
887             if (status != UX_SUCCESS)
888             {
889                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
890                 continue;
891             }
892 
893             if (configuration -> ux_configuration_first_interface)
894             {
895 
896                 /* Activate classes.  */
897                 device -> ux_device_enum_index = 0;
898                 device -> ux_device_enum_inst.interface =
899                             configuration -> ux_configuration_first_interface;
900             }
901             else
902             {
903 
904                 /* No activation, done  */
905                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_DONE;
906                 continue;
907             }
908 
909             /* Fall through.  */
910         case UX_HOST_STACK_ENUM_ACTIVATE:
911 
912             /* Class activate.  */
913             class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE_START;
914             if (device -> ux_device_enum_index == 0xFF)
915             {
916 
917                 /* Device class driver.  */
918                 class_command.ux_host_class_command_container = device;
919                 class_command.ux_host_class_command_class_ptr = device -> ux_device_class;
920             }
921             else
922             {
923 
924                 /* Interface class driver.  */
925                 class_command.ux_host_class_command_container = device -> ux_device_enum_inst.ptr;
926                 class_command.ux_host_class_command_class_ptr =
927                                     device -> ux_device_enum_inst.interface -> ux_interface_class;
928             }
929 
930             /* If there class linked, start activation.  */
931             if (class_command.ux_host_class_command_class_ptr != UX_NULL)
932             {
933                 status = class_command.ux_host_class_command_class_ptr ->
934                                     ux_host_class_entry_function(&class_command);
935                 if (status != UX_SUCCESS)
936                 {
937                     device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
938                     continue;
939                 }
940             }
941 
942             /* Class activate execute wait.  */
943             device -> ux_device_enum_state = UX_HOST_STACK_ENUM_ACTIVATE_WAIT;
944 
945             /* Fall through.  */
946         case UX_HOST_STACK_ENUM_ACTIVATE_WAIT:
947 
948             /* Class activate execution wait.  */
949             status = _ux_host_stack_interface_activate_wait(device, &class_command);
950 
951             /* Next state.  */
952             if (status != UX_STATE_WAIT)
953                 continue;
954 
955             /* Keep waiting.  */
956             return;
957 
958         case UX_HOST_STACK_ENUM_TRANS_WAIT:
959 
960             /* Poll transfer task.  */
961             trans = device -> ux_device_enum_trans;
962             status = _ux_host_stack_transfer_run(trans);
963 
964             /* Transfer done - next state.  */
965             if (status == UX_STATE_NEXT || status == UX_STATE_IDLE)
966             {
967                 device -> ux_device_enum_trans = UX_NULL;
968                 device -> ux_device_enum_state = device -> ux_device_enum_next_state;
969                 continue;
970             }
971 
972             /* Check error.  */
973             if (status < UX_STATE_ERROR)
974             {
975 
976                 /* No retry, fail.  */
977                 if (trans -> ux_transfer_request_data_pointer)
978                 {
979                     _ux_utility_memory_free(trans -> ux_transfer_request_data_pointer);
980                     trans -> ux_transfer_request_data_pointer = UX_NULL;
981                 }
982                 if (device -> ux_device_enum_next_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE)
983                 {
984                     _ux_utility_memory_free(device -> ux_device_enum_inst.ptr);
985                     device -> ux_device_enum_inst.ptr = UX_NULL;
986                 }
987                 device -> ux_device_enum_trans = UX_NULL;
988                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_FAIL;
989                 continue;
990             }
991             if (status < UX_STATE_NEXT)
992             {
993 
994                 /* Error, retry.  */
995                 if (trans -> ux_transfer_request_data_pointer)
996                 {
997                     _ux_utility_memory_free(trans -> ux_transfer_request_data_pointer);
998                     trans -> ux_transfer_request_data_pointer = UX_NULL;
999                 }
1000                 if (device -> ux_device_enum_next_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE)
1001                 {
1002                     _ux_utility_memory_free(device -> ux_device_enum_inst.ptr);
1003                     device -> ux_device_enum_inst.ptr = UX_NULL;
1004                 }
1005                 device -> ux_device_enum_trans = UX_NULL;
1006                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_RETRY;
1007                 continue;
1008             }
1009 
1010             /* Transfer in progress, wait.  */
1011             return;
1012 
1013         case UX_HOST_STACK_ENUM_TRANS_LOCK_WAIT:
1014             trans = device -> ux_device_enum_trans;
1015             UX_DISABLE
1016             if (trans -> ux_transfer_request_flags & UX_TRANSFER_FLAG_LOCK)
1017             {
1018 
1019                 /* Keep waiting.  */
1020                 UX_RESTORE;
1021                 return;
1022             }
1023 
1024             /* Lock it.  */
1025             trans -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_LOCK;
1026             UX_RESTORE
1027 
1028             /* Apply next expected state.  */
1029             device -> ux_device_enum_state = device -> ux_device_enum_next_state;
1030             continue;
1031 
1032         case UX_HOST_STACK_ENUM_WAIT:
1033             current_ms = _ux_utility_time_get();
1034             elapsed_ms = _ux_utility_time_elapsed(current_ms,
1035                                                   device -> ux_device_enum_wait_start);
1036             if (elapsed_ms < device -> ux_device_enum_wait_ms)
1037 
1038                 /* Keep waiting.  */
1039                 return;
1040 
1041             /* Next pre-defined state.  */
1042             device -> ux_device_enum_state = device -> ux_device_enum_next_state;
1043             continue;
1044 
1045         case UX_HOST_STACK_ENUM_RETRY:
1046 
1047             /* Check remaining retry count. */
1048             if (device -> ux_device_enum_retry > 0)
1049             {
1050                 device -> ux_device_enum_retry --;
1051 
1052                 /* Check if there is unnecessary resource to free.  */
1053                 if (device -> ux_device_packed_configuration &&
1054                     device -> ux_device_packed_configuration_keep_count == 0)
1055                 {
1056                     _ux_utility_memory_free(device -> ux_device_packed_configuration);
1057                     device -> ux_device_packed_configuration = UX_NULL;
1058                 }
1059 
1060                 /* Start from port enable delay.  */
1061                 device -> ux_device_enum_next_state = UX_HOST_STACK_ENUM_PORT_RESET;
1062                 device -> ux_device_enum_state = UX_HOST_STACK_ENUM_WAIT;
1063                 device -> ux_device_enum_wait_start = _ux_utility_time_get();
1064                 device -> ux_device_enum_wait_ms =
1065                         UX_MS_TO_TICK_NON_ZERO(UX_RH_ENUMERATION_RETRY_DELAY);
1066                 continue;
1067             }
1068 
1069             /* Tried several times, fail case.  */
1070             /* Fall through.  */
1071         case UX_HOST_STACK_ENUM_FAIL:
1072 
1073             /* Clear lock anyway.  */
1074             if (device == _ux_system_host -> ux_system_host_enum_lock)
1075                 _ux_system_host -> ux_system_host_enum_lock = UX_NULL;
1076 
1077             /* Error trap. */
1078             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD,
1079                 UX_DEVICE_PARENT_IS_HUB(device) ? UX_SYSTEM_CONTEXT_HUB :
1080                                                   UX_SYSTEM_CONTEXT_ROOT_HUB,
1081                 UX_DEVICE_ENUMERATION_FAILURE);
1082 
1083             /* If trace is enabled, insert this event into the trace buffer.  */
1084             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE,
1085                 UX_DEVICE_PORT_LOCATION_GET(device), 0, 0, UX_TRACE_ERRORS, 0, 0);
1086 
1087             /* Fall through.  */
1088         case UX_HOST_STACK_ENUM_DONE:
1089             _ux_host_stack_device_enumerated(device);
1090 
1091             /* We are done now.  */
1092             /* Fall through.  */
1093         case UX_HOST_STACK_ENUM_IDLE:
1094 
1095             /* Nothing to run.  */
1096             return;
1097 
1098         default:
1099 
1100             /* Invalid state, reset.  */
1101             device -> ux_device_enum_state = UX_STATE_RESET;
1102         }
1103 
1104         /* Invalid unhandled state.  */
1105         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HOST_STACK, UX_INVALID_STATE);
1106 
1107         /* Break the immediate state loop.  */
1108         immediate_state = UX_FALSE;
1109     }
1110 }
1111 
_ux_host_stack_enum_run(VOID)1112 static inline VOID _ux_host_stack_enum_run(VOID)
1113 {
1114 
1115 UX_DEVICE           *enum_device;
1116 
1117     /* Check if there is device pending enumeration.  */
1118     enum_device = _ux_system_host -> ux_system_host_enum_device;
1119 
1120     /* Run enumeration task for each device.  */
1121     while(enum_device != UX_NULL)
1122     {
1123 
1124         /* Run enumeration task on the device.  */
1125         if ((enum_device -> ux_device_flags & UX_DEVICE_FLAG_PROTECT) == 0)
1126         {
1127             enum_device -> ux_device_flags |= UX_DEVICE_FLAG_PROTECT;
1128             _ux_host_stack_device_enum_run(enum_device);
1129             enum_device -> ux_device_flags &= ~UX_DEVICE_FLAG_PROTECT;
1130         }
1131 
1132         /* Check device lock.  */
1133         if (enum_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)
1134         {
1135             break;
1136         }
1137 
1138         /* Check next enumerating device.  */
1139         enum_device = enum_device -> ux_device_enum_next;
1140     }
1141 }
1142 
_ux_host_stack_pending_transfers_run(VOID)1143 static inline VOID _ux_host_stack_pending_transfers_run(VOID)
1144 {
1145 UX_TRANSFER         *transfer, *next;
1146     transfer = _ux_system_host -> ux_system_host_pending_transfers;
1147     while(transfer)
1148     {
1149         next = transfer -> ux_transfer_request_next_pending;
1150         _ux_host_stack_transfer_run(transfer);
1151         if (transfer == next || _ux_system_host -> ux_system_host_pending_transfers == next)
1152             break;
1153         transfer = next;
1154     }
1155 }
1156 #endif
1157