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_new_interface_create                 PORTABLE C      */
36 /*                                                           6.1.12       */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function creates a new interface for the current configuration */
44 /*    scanned. A device has at least 1 alternate setting per interface    */
45 /*    which is the default one.                                           */
46 /*                                                                        */
47 /*    The interface is hooked to the configuration that owns it.          */
48 /*                                                                        */
49 /*    From the interface descriptor, all the endpoints are hooked but     */
50 /*    not activated.                                                      */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    configuration                         Configuration container that  */
55 /*                                            owns this interface         */
56 /*    interface_pointer                     Pointer to a unparsed         */
57 /*                                            interface descriptor        */
58 /*    length                                Length remaining in this      */
59 /*                                            descriptor                  */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    Completion Status                                                   */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    _ux_host_stack_new_endpoint_create    Create new endpoint           */
68 /*    _ux_utility_descriptor_parse          Parse the descriptor          */
69 /*    _ux_utility_memory_allocate           Allocate memory block         */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    USBX Components                                                     */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
80 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            fixed parameter/variable    */
84 /*                                            names conflict C++ keyword, */
85 /*                                            resulting in version 6.1.12 */
86 /*                                                                        */
87 /**************************************************************************/
_ux_host_stack_new_interface_create(UX_CONFIGURATION * configuration,UCHAR * descriptor,ULONG length)88 UINT  _ux_host_stack_new_interface_create(UX_CONFIGURATION *configuration,
89                                             UCHAR * descriptor, ULONG length)
90 {
91 
92 UX_INTERFACE        *list_interface;
93 UX_INTERFACE        *interface_ptr;
94 UINT                number_endpoints;
95 UINT                descriptor_length;
96 UINT                descriptor_type;
97 UINT                status;
98 UCHAR               *this_interface_descriptor;
99 
100     /* Obtain memory for storing this new interface.  */
101     interface_ptr =  (UX_INTERFACE *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_INTERFACE));
102 
103     /* If no memory left, exit with error.  */
104     if (interface_ptr == UX_NULL)
105         return(UX_MEMORY_INSUFFICIENT);
106 
107     /* Save the interface handle in the container, this is for ensuring the
108        interface container is not corrupted.  */
109     interface_ptr -> ux_interface_handle =  (ULONG) (ALIGN_TYPE) interface_ptr;
110 
111     /* Parse the interface descriptor and make it machine independent.  */
112     _ux_utility_descriptor_parse(descriptor,
113                             _ux_system_interface_descriptor_structure,
114                             UX_INTERFACE_DESCRIPTOR_ENTRIES,
115                             (UCHAR *) &interface_ptr -> ux_interface_descriptor);
116 
117     /* The configuration that owns this interface is memorized in the
118        interface container itself, easier for back chaining.  */
119     interface_ptr -> ux_interface_configuration =  configuration;
120 
121     /* If the interface belongs to an IAD, remember the IAD Class/SubClass/Protocol.  */
122     interface_ptr -> ux_interface_iad_class    = configuration -> ux_configuration_iad_class;
123     interface_ptr -> ux_interface_iad_subclass = configuration -> ux_configuration_iad_subclass;
124     interface_ptr -> ux_interface_iad_protocol = configuration -> ux_configuration_iad_protocol;
125 
126     /* There is 2 cases for the creation of the interface descriptor
127        if this is the first one, the interface descriptor is hooked
128        to the configuration. If it is not the first one, the interface
129        is hooked to the end of the chain of interfaces.  */
130     if (configuration -> ux_configuration_first_interface == UX_NULL)
131     {
132         configuration -> ux_configuration_first_interface =  interface_ptr;
133     }
134     else
135     {
136 
137         list_interface =  configuration -> ux_configuration_first_interface;
138 
139         /* Traverse the list until we reach the end */
140         while (list_interface -> ux_interface_next_interface != UX_NULL)
141         {
142 
143             list_interface =  list_interface -> ux_interface_next_interface;
144         }
145 
146         /* Hook the interface.  */
147         list_interface -> ux_interface_next_interface =  interface_ptr;
148     }
149 
150     /* Traverse the interface in search of all endpoints that belong to it.
151        We need the length remaining in the descriptor and the number of endpoints
152        reported for this interface.  */
153     number_endpoints =  interface_ptr -> ux_interface_descriptor.bNumEndpoints;
154 
155     this_interface_descriptor = descriptor;
156 
157     while (length && (number_endpoints != 0))
158     {
159 
160         /* Gather the length and type of the descriptor.  */
161         descriptor_length =  *descriptor;
162         descriptor_type =    *(descriptor+1);
163 
164         /* make sure this descriptor has at least the minimum length.  */
165         if (descriptor_length < 3)
166         {
167 
168             /* Error trap. */
169             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
170 
171             /* If trace is enabled, insert this event into the trace buffer.  */
172             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
173 
174             return(UX_DESCRIPTOR_CORRUPTED);
175         }
176 
177         /* Check the type for an interface descriptor.  */
178         if (descriptor_type == UX_ENDPOINT_DESCRIPTOR_ITEM)
179         {
180 
181             /* We have found an endpoint descriptor for this interface.  */
182             status =  _ux_host_stack_new_endpoint_create(interface_ptr, descriptor);
183 
184             /* Check return status.  */
185             if(status != UX_SUCCESS)
186                 return(status);
187 
188             number_endpoints--;
189         }
190 
191         /* Verify if the descriptor is still valid, or we moved to next interface.  */
192         if ((descriptor_length > length) || (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM && descriptor != this_interface_descriptor))
193         {
194 
195             /* Error trap. */
196             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
197 
198             /* If trace is enabled, insert this event into the trace buffer.  */
199             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
200 
201             return(UX_DESCRIPTOR_CORRUPTED);
202         }
203 
204         /* Jump to the next descriptor if we have not reached the end.  */
205         descriptor +=  descriptor_length;
206         length -=  descriptor_length;
207     }
208 
209     /* Return success!  */
210     return(UX_SUCCESS);
211 }
212 
213