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