GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hub_configure.c Lines: 31 31 100.0 %
Date: 2026-03-06 18:57:10 Branches: 14 14 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
/**   HUB Class                                                           */
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_class_hub.h"
30
#include "ux_host_stack.h"
31
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_host_class_hub_configure                        PORTABLE C      */
38
/*                                                           6.1.11       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function calls the USBX stack to do a SET_CONFIGURATION to the */
46
/*    HUB. Once the HUB is configured, its interface will be activated    */
47
/*    and all the endpoints enumerated (1 interrupt endpoint in the case  */
48
/*    of the HUB).                                                        */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    hub                                   Pointer to HUB                */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    Completion Status                                                   */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _ux_host_stack_device_configuration_get Get device configuration    */
61
/*    _ux_host_stack_device_configuration_select                          */
62
/*                                          Select device configuration   */
63
/*    _ux_host_stack_configuration_interface_get                          */
64
/*                                          Get interface                 */
65
/*    _ux_host_stack_transfer_request       Process transfer request      */
66
/*    _ux_utility_memory_allocate           Allocate memory block         */
67
/*    _ux_utility_memory_free               Release memory block          */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    HUB Class                                                           */
72
/*                                                                        */
73
/**************************************************************************/
74
71
UINT  _ux_host_class_hub_configure(UX_HOST_CLASS_HUB *hub)
75
{
76
77
UINT                    status;
78
UX_CONFIGURATION        *configuration;
79
UX_DEVICE               *device;
80
UX_ENDPOINT             *control_endpoint;
81
UCHAR                   *device_status_data;
82
UX_TRANSFER             *transfer_request;
83
#if UX_MAX_DEVICES > 1
84
UX_DEVICE               *parent_device;
85
#endif
86
87
88
    /* A HUB normally has one configuration. So retrieve the 1st configuration
89
       only.  */
90
71
    _ux_host_stack_device_configuration_get(hub -> ux_host_class_hub_device, 0, &configuration);
91
92
    /* Get the device container for this configuration.  */
93
71
    device =  configuration -> ux_configuration_device;
94
95
    /* To find the true source of the HUB power source, we need to do a GET_STATUS of
96
       the device.  */
97
71
    control_endpoint =  &device -> ux_device_control_endpoint;
98
71
    transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
99
100
    /* Allocate a buffer for the device status: 2 bytes.  */
101
71
    device_status_data =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2);
102
71
    if (device_status_data == UX_NULL)
103
1
        return(UX_MEMORY_INSUFFICIENT);
104
105
    /* Create a transfer_request for the GET_STATUS request, 2 bytes are returned.  */
106
70
    transfer_request -> ux_transfer_request_requested_length =  2;
107
70
    transfer_request -> ux_transfer_request_data_pointer =      device_status_data;
108
70
    transfer_request -> ux_transfer_request_function =          UX_GET_STATUS;
109
70
    transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
110
70
    transfer_request -> ux_transfer_request_value =             0;
111
70
    transfer_request -> ux_transfer_request_index =             0;
112
113
    /* Send request to HCD layer.  */
114
70
    status =  _ux_host_stack_transfer_request(transfer_request);
115
116
    /* Check the status and the length of the data returned.  */
117

70
    if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2))
118
    {
119
120
        /* The data returned is good, now analyze power source.  */
121
66
        if (*device_status_data & UX_STATUS_DEVICE_SELF_POWERED)
122
30
            device -> ux_device_power_source =  UX_DEVICE_SELF_POWERED;
123
        else
124
36
            device -> ux_device_power_source =  UX_DEVICE_BUS_POWERED;
125
126
        /* Free the buffer resource now.  */
127
66
        _ux_utility_memory_free(device_status_data);
128
    }
129
    else
130
    {
131
132
        /* Free the buffer resource now.  */
133
4
        _ux_utility_memory_free(device_status_data);
134
135
        /* Error trap. */
136
4
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE);
137
138
        /* If trace is enabled, insert this event into the trace buffer.  */
139
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0)
140
141
        /* Return an error.  */
142
4
        return(UX_CONNECTION_INCOMPATIBLE);
143
    }
144
145
#if UX_MAX_DEVICES > 1
146
    /* Check the HUB power source and check the parent power source for
147
       incompatible connections.  */
148
66
    if (hub -> ux_host_class_hub_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)
149
    {
150
151
        /* Get the parent container for this device.  */
152
36
        parent_device =  device -> ux_device_parent;
153
154
        /* If the device is NULL, the parent is the root HUB and we don't have to worry
155
           if the parent is not the root HUB, check for its power source.  */
156

36
        if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED))
157
        {
158
159
            /* Error trap. */
160
1
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE);
161
162
            /* If trace is enabled, insert this event into the trace buffer.  */
163
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0)
164
165
1
            return(UX_CONNECTION_INCOMPATIBLE);
166
        }
167
    }
168
#endif
169
170
    /* We have the valid configuration. Ask the USBX stack to set this configuration.  */
171
65
    _ux_host_stack_device_configuration_select(configuration);
172
173
    /* If the operation went well, the HUB default alternate setting for the HUB interface is
174
       active and the interrupt endpoint is now enabled. We have to memorize the first interface
175
       since the interrupt endpoint is hooked to it. */
176
65
    status =  _ux_host_stack_configuration_interface_get(configuration, 0, 0, &hub -> ux_host_class_hub_interface);
177
178
    /* Return completion status.  */
179
65
    return(status);
180
}
181