GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_rh_device_insertion.c Lines: 36 36 100.0 %
Date: 2024-12-12 17:16:36 Branches: 24 24 100.0 %

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