GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_rh_device_insertion.c Lines: 36 36 100.0 %
Date: 2026-03-06 18:57:10 Branches: 24 24 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** USBX Component                                                        */
17
/**                                                                       */
18
/**   Host Stack                                                          */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
24
/* Include necessary system files.  */
25
26
#define UX_SOURCE_CODE
27
28
#include "ux_api.h"
29
#include "ux_host_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_host_stack_rh_device_insertion                  PORTABLE C      */
37
/*                                                           6.1.11       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function handles a device insertion on a downstream port of    */
45
/*    the root hub pointed by HCD.                                        */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    HCD                                   Pointer to HCD structure      */
50
/*    port_index                            Port index of insertion       */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    Completion Status                                                   */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _ux_utility_delay_ms                  Thread sleep                  */
59
/*    _ux_host_stack_new_device_create      New device create             */
60
/*    _ux_host_stack_device_remove          Device remove                 */
61
/*    (hcd_entry_function)                  Entry function of HCD driver  */
62
/*                                                                        */
63
/*  CALLED BY                                                             */
64
/*                                                                        */
65
/*    USBX Components                                                     */
66
/*                                                                        */
67
/**************************************************************************/
68
856
UINT  _ux_host_stack_rh_device_insertion(UX_HCD *hcd, UINT port_index)
69
{
70
#if defined(UX_HOST_STANDALONE)
71
UX_DEVICE   *device;
72
UINT        status;
73
74
75
    /* If trace is enabled, insert this event into the trace buffer.  */
76
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_DEVICE_INSERTION, hcd, port_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
77
78
    /* Anyway there is device connected.  */
79
    hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index);
80
81
    /* Create a new device slot for enumeration.  */
82
    status =  _ux_host_stack_new_device_create(hcd, UX_NULL, port_index,
83
                                        UX_FULL_SPEED_DEVICE, UX_MAX_SELF_POWER,
84
                                        &device);
85
86
    /* Link the device in enumeration list.  */
87
    if (status == UX_SUCCESS)
88
    {
89
90
        /* Set enumeration flag to process enumeration sequence.  */
91
        device -> ux_device_flags |= UX_DEVICE_FLAG_ENUM;
92
93
        /* Done success.  */
94
        return(UX_SUCCESS);
95
    }
96
97
#else
98
856
UX_DEVICE   *device = UX_NULL;
99
UINT        index_loop;
100
UINT        device_speed;
101
ULONG       port_status;
102
UINT        status;
103
104
    /* If trace is enabled, insert this event into the trace buffer.  */
105
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_DEVICE_INSERTION, hcd, port_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
106
107
    /* Perform a PORT_ENABLE command.  */
108
856
    port_status =  hcd -> ux_hcd_entry_function(hcd, UX_HCD_ENABLE_PORT, (VOID *)((ALIGN_TYPE)port_index));
109
110
    /* Check return status.  */
111
856
    if (port_status == UX_PORT_INDEX_UNKNOWN)
112
1
        return(port_status);
113
114
    /* A debounce interval with a minimum duration of 100 ms on attach.  */
115
855
    _ux_utility_delay_ms(100);
116
117
    /* The first attempts to do a device enumeration may fail.
118
       Typically, after the port is reset and the first command is sent to
119
       the device, there is no answer. In this case, we reset the port again
120
       and retry. Usually that does the trick!  */
121
1851
    for (index_loop = 0; index_loop < UX_RH_ENUMERATION_RETRY; index_loop++)
122
    {
123
124
        /* Now we have to do a PORT_RESET command.  */
125
1525
        port_status =  hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_PORT, (VOID *)((ALIGN_TYPE)port_index));
126
1525
        if (port_status == UX_SUCCESS)
127
        {
128
129
            /* The port reset phase was successful. Before we invoke the device enumeration function,
130
               we need to know the speed of the device.  */
131
1522
            port_status =  hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)((ALIGN_TYPE)port_index));
132
133
            /* Check return status.  */
134
1522
            if (port_status == UX_PORT_INDEX_UNKNOWN)
135
            {
136
137
                /* Error trap. */
138
1
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE);
139
140
                /* If trace is enabled, insert this event into the trace buffer.  */
141
                UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0)
142
143
1
                return(UX_DEVICE_ENUMERATION_FAILURE);
144
            }
145
146
            /* Check if device is still connected.  */
147
1521
            if ((port_status & UX_PS_CCS) == 0)
148
            {
149
150
                /* Device disconnected during enumeration retries.  */
151
14
                return(UX_DEVICE_ENUMERATION_FAILURE);
152
            }
153
154
            /* Set the device speed.  */
155
1507
            device_speed =  port_status >> UX_PS_DS;
156
157
            /* Ask the USB stack to enumerate this device. A root hub is considered self
158
               powered. */
159
1507
            status =  _ux_host_stack_new_device_create(hcd, UX_NULL, port_index, device_speed, UX_MAX_SELF_POWER, &device);
160
161
            /* Check return status.  */
162
1505
            if (status == UX_SUCCESS)
163
            {
164
165
                /* Successful device create.  */
166
167
                /* The device has been mounted properly, we have to remember this
168
                   so when the device is removed, we have to invoke the enumeration
169
                   function again */
170
489
                hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index);
171
172
                /* If the device instance is ready, notify application for connection.  */
173
489
                if (_ux_system_host -> ux_system_host_change_function)
174
                {
175
284
                    _ux_system_host -> ux_system_host_change_function(UX_DEVICE_CONNECTION, UX_NULL, (VOID*)device);
176
                }
177
178
                /* Return success to the caller.  */
179
489
                return(UX_SUCCESS);
180
            }
181
            else
182
            {
183
184
                /* Return error if HCD is dead.  */
185
1016
                if (hcd -> ux_hcd_status != UX_HCD_STATUS_OPERATIONAL)
186
7
                    return(UX_CONTROLLER_DEAD);
187
188
                /* No retry if there are too many devices.  */
189
1009
                if (status == UX_TOO_MANY_DEVICES)
190
1
                    break;
191
192
                /* No retry if there is no class found.  */
193
1008
                if (status == UX_NO_CLASS_MATCH)
194
13
                    break;
195
196
                /* Simulate remove to free allocated resources if retry.  */
197
995
                if (index_loop < UX_RH_ENUMERATION_RETRY - 1)
198
670
                    _ux_host_stack_device_remove(hcd, UX_NULL, port_index);
199
            }
200
        }
201
202
        /* We get here if something did not go well. Either the port did not respond
203
           well to the ENABLE\RESET phases or the device did not enumerate well
204
           so we try again ! */
205
997
        _ux_utility_delay_ms(UX_RH_ENUMERATION_RETRY_DELAY);
206
    }
207
#endif /* defined(UX_HOST_STANDALONE)  */
208
209
    /* If we get here, the device did not enumerate completely.
210
       The device is still attached to the root hub and therefore
211
       there could be a physical connection with a unconfigured device.  */
212
340
    hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index);
213
214
    /* Notify application for a physical connection failed to be enumed.
215
       Device instance NULL indicates too many devices.
216
       Device state unconfigured indicates enumeration fail.  */
217
340
    if (_ux_system_host -> ux_system_host_change_function)
218
    {
219
312
        _ux_system_host -> ux_system_host_change_function(UX_DEVICE_CONNECTION, UX_NULL, (VOID*)device);
220
    }
221
222
    /* Error trap. */
223
340
    _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE);
224
225
    /* If trace is enabled, insert this event into the trace buffer.  */
226
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0)
227
228
    /* Return a failed enumeration.  */
229
340
    return(UX_DEVICE_ENUMERATION_FAILURE);
230
}