GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hub_descriptor_get.c Lines: 49 49 100.0 %
Date: 2024-12-12 17:16:36 Branches: 18 18 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
/**   HUB Class                                                           */
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_class_hub.h"
29
#include "ux_host_stack.h"
30
31
32
#if UX_MAX_DEVICES > 1
33
34
#if defined(UX_HOST_STANDALONE)
35
UINT _ux_host_class_hub_descriptor_parse(UX_HOST_CLASS_HUB *hub, UCHAR *descriptor);
36
UINT
37
#else
38
static inline UINT
39
#endif
40
59
_ux_host_class_hub_descriptor_parse(UX_HOST_CLASS_HUB *hub, UCHAR *descriptor)
41
{
42
59
UINT            status = UX_SUCCESS;
43
ULONG           tt_protocols; /* (bDeviceProtocol << 8) | bInterfaceProtocol  */
44
ULONG           port_index;
45
46
    /* Parse the device descriptor and create the local descriptor.  */
47
59
    _ux_utility_descriptor_parse(descriptor, _ux_system_hub_descriptor_structure, UX_HUB_DESCRIPTOR_ENTRIES,
48
59
                                                            (UCHAR *) &hub -> ux_host_class_hub_descriptor);
49
50
    /* Check the protocol used by the HUB. This will indicate if the HUB supports multiple TTs in high speed mode.  */
51
59
    tt_protocols = ((ULONG)hub -> ux_host_class_hub_device -> ux_device_descriptor.bDeviceProtocol << 8) |
52
59
                    hub -> ux_host_class_hub_interface -> ux_interface_descriptor.bInterfaceProtocol;
53

59
    switch(tt_protocols)
54
    {
55
56
    /* 1. A hub operating at full-/low-speed has a device descriptor with a bDeviceProtocol field set to zero(0)
57
     *    and an interface descriptor with a bInterfaceProtocol field set to zero(0).
58
     */
59
1
    case (UX_HOST_CLASS_HUB_PROTOCOL_FS << 8):
60
61
        /* In the case of full speed hub, there are no TTs to declare */
62
1
        break;
63
64
    /* 2. A hub that has a single TT must set the bDeviceProtocol field of the device descriptor to one(1) and
65
     *    the interface descriptor bInterfaceProtocol field set to 0.
66
     * 3. A multiple TT hub must set the bDeviceProtocol field of the device descriptor to two (2).
67
     *    The first interface descriptor has the bInterfaceProtocol field set to one(1).
68
     */
69
53
    case (UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT << 8): /* Fall through.  */
70
    case (UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT << 8) | UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT:
71
72
        /* Single TT hub or single TT interface.  */
73
        /* Check if current setting supports this Hub.  */
74
53
        if (hub -> ux_host_class_hub_descriptor.bNbPorts > UX_MAX_TT)
75
        {
76
77
6
            status = UX_TOO_MANY_HUB_PORTS;
78
6
            break;
79
        }
80
81
        /* In a single TT state, all the downstream ports report to the same
82
           TT and share the 1.1 USB segment bandwidth. This is a very crude
83
           but working method, we simply set all the ports bits to the first
84
           TT.  */
85
47
        hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_port_mapping =   UX_TT_MASK;
86
47
        hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_max_bandwidth =  UX_TT_BANDWIDTH;
87
47
        break;
88
89
    /* 3. A multiple TT hub must set the bDeviceProtocol field of the device descriptor to two (2).
90
        *    The first interface descriptor has the bInterfaceProtocol field set to one(1).
91
        *    Such a hub also has a second interface descriptor where the bInterfaceProtocol is set to two(2).
92
        */
93
2
    case (UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT << 8) | UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT:
94
95
        /* Multiple TTs.  */
96
        /* Check if current setting supports this Hub.  */
97
2
        if (hub -> ux_host_class_hub_descriptor.bNbPorts > UX_MAX_TT)
98
        {
99
100
1
            status = UX_TOO_MANY_HUB_PORTS;
101
1
            break;
102
        }
103
104
        /* In the case of multiple TTs, each downstream port can sustain the USB 1.1
105
            max bandwidth and therefore we allocate one TT per port with that bandwidth.  */
106
2
        for (port_index = 0; port_index < hub -> ux_host_class_hub_descriptor.bNbPorts; port_index++)
107
        {
108
109
1
            hub -> ux_host_class_hub_device -> ux_device_hub_tt[port_index].ux_hub_tt_port_mapping =   (ULONG)(1 << port_index);
110
1
            hub -> ux_host_class_hub_device -> ux_device_hub_tt[port_index].ux_hub_tt_max_bandwidth =  UX_TT_BANDWIDTH;
111
        }
112
1
        break;
113
114
3
    default: /* Invalid bDeviceProtocol and bInterfaceProtocol pair.  */
115
116
        /* We should never get here. In this case the protocol value of the HUB is illegal.  */
117
3
        status =  UX_DESCRIPTOR_CORRUPTED;
118
    }
119
120
    /* Return status.  */
121
59
    return(status);
122
}
123
#endif
124
125
126
/**************************************************************************/
127
/*                                                                        */
128
/*  FUNCTION                                               RELEASE        */
129
/*                                                                        */
130
/*    _ux_host_class_hub_descriptor_get                   PORTABLE C      */
131
/*                                                           6.3.0        */
132
/*  AUTHOR                                                                */
133
/*                                                                        */
134
/*    Chaoqiong Xiao, Microsoft Corporation                               */
135
/*                                                                        */
136
/*  DESCRIPTION                                                           */
137
/*                                                                        */
138
/*    This function obtains the HUB descriptor. This descriptor contains  */
139
/*    the number of downstream ports and the power characteristics of the */
140
/*    HUB (self powered or bus powered).                                  */
141
/*                                                                        */
142
/*  INPUT                                                                 */
143
/*                                                                        */
144
/*    hub                                   Pointer to HUB                */
145
/*                                                                        */
146
/*  OUTPUT                                                                */
147
/*                                                                        */
148
/*    Completion Status                                                   */
149
/*                                                                        */
150
/*  CALLS                                                                 */
151
/*                                                                        */
152
/*    _ux_host_stack_transfer_request       Process transfer request      */
153
/*    _ux_utility_memory_allocate           Allocate memory block         */
154
/*    _ux_utility_memory_free               Release memory block          */
155
/*    _ux_utility_descriptor_parse          Parse descriptor              */
156
/*                                                                        */
157
/*  CALLED BY                                                             */
158
/*                                                                        */
159
/*    HUB Class                                                           */
160
/*                                                                        */
161
/*  RELEASE HISTORY                                                       */
162
/*                                                                        */
163
/*    DATE              NAME                      DESCRIPTION             */
164
/*                                                                        */
165
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
166
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
167
/*                                            optimized based on compile  */
168
/*                                            definitions,                */
169
/*                                            resulting in version 6.1    */
170
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
171
/*                                            improved protocol handling, */
172
/*                                            resulting in version 6.1.10 */
173
/*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
174
/*                                            added standalone support,   */
175
/*                                            resulting in version 6.1.12 */
176
/*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
177
/*                                            fixed compile warnings,     */
178
/*                                            resulting in version 6.3.0  */
179
/*                                                                        */
180
/**************************************************************************/
181
66
UINT  _ux_host_class_hub_descriptor_get(UX_HOST_CLASS_HUB *hub)
182
{
183
184
UCHAR           *descriptor;
185
UX_ENDPOINT     *control_endpoint;
186
UX_TRANSFER     *transfer_request;
187
UINT            status;
188
189
190
    /* We need to get the default control endpoint transfer request pointer.  */
191
66
    control_endpoint =  &hub -> ux_host_class_hub_device -> ux_device_control_endpoint;
192
66
    transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
193
194
    /* Need to allocate memory for the descriptor.  */
195
66
    descriptor =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HUB_DESCRIPTOR_LENGTH);
196
66
    if (descriptor == UX_NULL)
197
3
        return(UX_MEMORY_INSUFFICIENT);
198
199
    /* Create a transfer request for the GET_DESCRIPTOR request.  */
200
63
    transfer_request -> ux_transfer_request_data_pointer =      descriptor;
201
63
    transfer_request -> ux_transfer_request_requested_length =  UX_HUB_DESCRIPTOR_LENGTH;
202
63
    transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_HUB_GET_DESCRIPTOR;
203
63
    transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_DEVICE;
204
63
    transfer_request -> ux_transfer_request_value =             (UX_HUB_DESCRIPTOR_ITEM << 8);
205
63
    transfer_request -> ux_transfer_request_index =             0;
206
207
#if defined(UX_HOST_STANDALONE)
208
209
    /* Save allocated buffer pointer.  */
210
    hub -> ux_host_class_hub_allocated = descriptor;
211
212
    /* Link to running transfer.  */
213
    UX_TRANSFER_STATE_RESET(transfer_request);
214
    hub -> ux_host_class_hub_transfer = transfer_request;
215
    status = UX_SUCCESS;
216
#else
217
218
    /* Send request to HCD layer.  */
219
63
    status =  _ux_host_stack_transfer_request(transfer_request);
220
221
    /* Did the transfer succeed?  */
222
63
    if (status == UX_SUCCESS)
223
    {
224
225
        /* Is the length valid?  */
226
62
        if (transfer_request -> ux_transfer_request_actual_length == UX_HUB_DESCRIPTOR_LENGTH)
227
        {
228
229
#if UX_MAX_DEVICES > 1
230
59
            status = _ux_host_class_hub_descriptor_parse(hub, descriptor);
231
59
            if (status != UX_SUCCESS)
232
            {
233
234
                /* Error trap. */
235
10
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, status);
236
237
                /* If trace is enabled, insert this event into the trace buffer.  */
238
                UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
239
            }
240
#endif
241
        }
242
        else
243
        {
244
245
            /* Error trap. */
246
3
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_DESCRIPTOR_CORRUPTED);
247
248
            /* If trace is enabled, insert this event into the trace buffer.  */
249
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
250
251
            /* The descriptor must be corrupted if we got an invalid length.  */
252
3
            status =  UX_DESCRIPTOR_CORRUPTED;
253
        }
254
    }
255
256
    /* Free the memory for the descriptor.  */
257
63
    _ux_utility_memory_free(descriptor);
258
#endif
259
260
    /* Return completion status.  */
261
63
    return(status);
262
}