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_interfaces_scan PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function scans all the interfaces and alternate settings for */
44 /* particular configuration. */
45 /* */
46 /* INPUT */
47 /* */
48 /* configuration Where the interface(s) will */
49 /* be attached */
50 /* descriptor Contains the entire descriptor*/
51 /* for this configuration */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* None */
56 /* */
57 /* CALLS */
58 /* */
59 /* _ux_utility_descriptor_parse Parse interface descriptor */
60 /* _ux_host_stack_new_interface_create Create new interface */
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 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_ux_host_stack_interfaces_scan(UX_CONFIGURATION * configuration,UCHAR * descriptor)75 UINT _ux_host_stack_interfaces_scan(UX_CONFIGURATION *configuration, UCHAR * descriptor)
76 {
77
78 ULONG total_configuration_length;
79 UINT descriptor_length;
80 UINT descriptor_type;
81 ULONG status;
82 ULONG interface_association_descriptor_present;
83 ULONG interface_in_iad_count;
84 UX_INTERFACE_ASSOCIATION_DESCRIPTOR interface_association;
85
86 /* Retrieve the size of all the configuration descriptor. */
87 total_configuration_length = configuration -> ux_configuration_descriptor.wTotalLength;
88
89 /* Set the IAD to false. */
90 interface_association_descriptor_present = UX_FALSE;
91
92 /* Set the IAD interface count to zero. */
93 interface_in_iad_count = 0;
94
95 /* Scan the entire descriptor and search for interfaces. We should also ensure that
96 the descriptor is valid by verifying the length of each descriptor scanned. */
97 while (total_configuration_length)
98 {
99
100 /* Gather the length and type of the descriptor. */
101 descriptor_length = *descriptor;
102 descriptor_type = *(descriptor + 1);
103
104 /* Make sure this descriptor has at least the minimum length. */
105 if (descriptor_length < 3)
106 {
107
108 /* Error trap. */
109 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
110
111 /* If trace is enabled, insert this event into the trace buffer. */
112 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
113
114 return(UX_DESCRIPTOR_CORRUPTED);
115 }
116
117 /* Check the type for an interface association descriptor. */
118 if (descriptor_type == UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM)
119 {
120
121 /* Parse the interface association descriptor and make it machine independent. */
122 _ux_utility_descriptor_parse(descriptor,
123 _ux_system_interface_association_descriptor_structure,
124 UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ENTRIES,
125 (UCHAR *) &interface_association);
126
127 /* Retrieve the CLASS/SUBCLASS from descriptor and store it in the configuration instance. */
128 configuration -> ux_configuration_iad_class = interface_association.bFunctionClass;
129 configuration -> ux_configuration_iad_subclass = interface_association.bFunctionSubClass;
130 configuration -> ux_configuration_iad_protocol = interface_association.bFunctionProtocol;
131
132 /* We have an IAD. */
133 interface_association_descriptor_present = UX_TRUE;
134
135 /* Memorize the number of interfaces attached to this IAD. */
136 interface_in_iad_count = interface_association.bInterfaceCount;
137 }
138
139 /* Check the type for an interface descriptor. */
140 if (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM)
141 {
142
143 /* We have found an interface descriptor. This descriptor contains at least
144 the default alternate setting (with value 0) and may have others. */
145 status = _ux_host_stack_new_interface_create(configuration, descriptor, total_configuration_length);
146
147 /* Are we within an IAD ? */
148 if (interface_association_descriptor_present == UX_TRUE)
149 {
150
151 /* Decrement the number of interfaces attached here. */
152 interface_in_iad_count--;
153
154 /* Are we at the end of the interface count ? */
155 if (interface_in_iad_count == 0)
156 {
157
158 /* Set the IAD to false now. */
159 interface_association_descriptor_present = UX_FALSE;
160
161 /* Reset the IAD Class/Subclass/Protocol. */
162 configuration -> ux_configuration_iad_class = 0;
163 configuration -> ux_configuration_iad_subclass = 0;
164 configuration -> ux_configuration_iad_protocol = 0;
165
166 }
167 }
168
169 /* Check return status. */
170 if(status != UX_SUCCESS)
171 return(status);
172 }
173
174 /* Check the type for an OTG descriptor. */
175 if (descriptor_type == UX_OTG_DESCRIPTOR_ITEM)
176
177 /* Retrieve the bmAttributes for SRP/HNP support. */
178 configuration -> ux_configuration_otg_capabilities = (ULONG) *(descriptor + UX_OTG_BM_ATTRIBUTES);
179
180 /* Verify if the descriptor is still valid. */
181 if (descriptor_length > total_configuration_length)
182 {
183
184 /* Error trap. */
185 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
186
187 /* If trace is enabled, insert this event into the trace buffer. */
188 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
189
190 return(UX_DESCRIPTOR_CORRUPTED);
191 }
192 /* Jump to the next descriptor if we have not reached the end. */
193 descriptor += descriptor_length;
194
195 /* And adjust the length left to parse in the descriptor. */
196 total_configuration_length -= descriptor_length;
197 }
198
199 /* Return successful completion. */
200 return(UX_SUCCESS);
201 }
202
203