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