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