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