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