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 /** System */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Define UX_SYSTEM_INIT to bring in the USBX version ID string. */
24
25 #define UX_SYSTEM_INIT
26
27
28 /* Include necessary system files. */
29
30 #define UX_SOURCE_CODE
31
32 #include "ux_api.h"
33 #include "ux_system.h"
34
35 /* Define the USBX system data structure. */
36
37 UX_SYSTEM *_ux_system;
38 UX_SYSTEM_OTG *_ux_system_otg;
39
40 /* Define names of all the packed descriptors in USBX. */
41
42 UCHAR _ux_system_endpoint_descriptor_structure[] = {1,1,1,1,2,1 };
43 UCHAR _ux_system_device_descriptor_structure[] = {1,1,2,1,1,1,1,2,2,2,1,1,1,1};
44 UCHAR _ux_system_configuration_descriptor_structure[] = {1,1,2,1,1,1,1,1};
45 UCHAR _ux_system_interface_descriptor_structure[] = {1,1,1,1,1,1,1,1,1};
46 UCHAR _ux_system_interface_association_descriptor_structure[] = {1,1,1,1,1,1,1,1};
47 UCHAR _ux_system_string_descriptor_structure[] = {1,1,2};
48 UCHAR _ux_system_dfu_functional_descriptor_structure[] = {1,1,1,2,2,2};
49 UCHAR _ux_system_class_audio_interface_descriptor_structure[] = {1,1,1,1,1,1,1,1};
50 UCHAR _ux_system_class_audio_input_terminal_descriptor_structure[] = {1,1,1,1,2,1,1,2,1,1};
51 UCHAR _ux_system_class_audio_output_terminal_descriptor_structure[] = {1,1,1,1,2,1,1,1};
52 UCHAR _ux_system_class_audio_feature_unit_descriptor_structure[] = {1,1,1,1,1,1,1};
53 UCHAR _ux_system_class_audio_streaming_interface_descriptor_structure[] = {1,1,1,1,1,1};
54 UCHAR _ux_system_class_audio_streaming_endpoint_descriptor_structure[] = {1,1,1,1,1,1};
55 UCHAR _ux_system_hub_descriptor_structure[] = {1,1,1,2,1,1,1,1};
56 UCHAR _ux_system_hid_descriptor_structure[] = {1,1,2,1,1,1,2};
57 UCHAR _ux_system_class_pima_storage_structure[] = {2,2,2,4,4,4,4,4};
58 UCHAR _ux_system_class_pima_object_structure[] = {4,2,2,4,2,4,4,4,4,4,4,4,2,4,4};
59 UCHAR _ux_system_ecm_interface_descriptor_structure[] = {1,1,1,1,4,2,2,1};
60
61 UCHAR _ux_system_bos_descriptor_structure[] = {1,1,2,1};
62 UCHAR _ux_system_usb_2_0_extension_descriptor_structure[] = {1,1,1,4};
63 UCHAR _ux_system_container_id_descriptor_structure[] = {1,1,1,1,4,4,4,4};
64
65
66 /**************************************************************************/
67 /* */
68 /* FUNCTION RELEASE */
69 /* */
70 /* _ux_system_initialize PORTABLE C */
71 /* 6.3.0 */
72 /* AUTHOR */
73 /* */
74 /* Chaoqiong Xiao, Microsoft Corporation */
75 /* */
76 /* DESCRIPTION */
77 /* */
78 /* This function initializes the various control data structures for */
79 /* the USBX system. */
80 /* */
81 /* INPUT */
82 /* */
83 /* regular_memory_pool_start Start of non cached memory pool */
84 /* regular_memory_size Size of non cached memory pool */
85 /* cache_safe_memory_pool_start Start of cached memory pool */
86 /* cache_safe_memory_size Size of cached memory pool */
87 /* */
88 /* OUTPUT */
89 /* */
90 /* None */
91 /* */
92 /* CALLS */
93 /* */
94 /* _ux_utility_memory_allocate Allocate memory */
95 /* _ux_utility_memory_set Set memory */
96 /* _ux_utility_mutex_create Create mutex */
97 /* */
98 /* CALLED BY */
99 /* */
100 /* Application */
101 /* */
102 /* RELEASE HISTORY */
103 /* */
104 /* DATE NAME DESCRIPTION */
105 /* */
106 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
107 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
108 /* verified memset and memcpy */
109 /* cases, */
110 /* resulting in version 6.1 */
111 /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
112 /* added BOS support, */
113 /* resulting in version 6.1.3 */
114 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
115 /* added standalone support, */
116 /* resulting in version 6.1.10 */
117 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
118 /* refined memory management, */
119 /* added UX_ASSERT check for */
120 /* STD descriptor parse size, */
121 /* resulting in version 6.3.0 */
122 /* */
123 /**************************************************************************/
_ux_system_initialize(VOID * regular_memory_pool_start,ULONG regular_memory_size,VOID * cache_safe_memory_pool_start,ULONG cache_safe_memory_size)124 UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size,
125 VOID *cache_safe_memory_pool_start, ULONG cache_safe_memory_size)
126 {
127 ALIGN_TYPE int_memory_pool_start;
128 VOID *regular_memory_pool_end;
129 VOID *cache_safe_memory_pool_end;
130 ULONG memory_pool_offset;
131 #if !defined(UX_STANDALONE)
132 UINT status;
133 #endif
134 ULONG pool_size;
135
136 /* Check if the regular memory pool is valid. */
137 if ((regular_memory_pool_start == UX_NULL) || (regular_memory_size == 0))
138 return(UX_INVALID_PARAMETER);
139
140 /* Reset memory block */
141 _ux_utility_memory_set(regular_memory_pool_start, 0, regular_memory_size); /* Use case of memset is verified. */
142
143 /* Set the _ux_system structure at the start of our regular memory */
144 _ux_system = (UX_SYSTEM *) regular_memory_pool_start;
145
146 /* Add to the memory offset the size of the allocated block. */
147 memory_pool_offset = sizeof(UX_SYSTEM);
148
149 #ifndef UX_DEVICE_SIDE_ONLY
150
151 /* Set the _ux_system_host structure. */
152 _ux_system_host = (UX_SYSTEM_HOST *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
153
154 /* Add to the memory offset the size of the allocated block. */
155 memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_HOST);
156
157 #endif
158
159 #ifndef UX_HOST_SIDE_ONLY
160
161 /* Set the _ux_system_slave structure. */
162 _ux_system_slave = (UX_SYSTEM_SLAVE *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
163
164 /* Add to the memory offset the size of the allocated block. */
165 memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_SLAVE);
166
167 #endif
168
169
170 #ifdef UX_OTG_SUPPORT
171
172 /* Set the _ux_system_otg structure. */
173 _ux_system_otg = (UX_SYSTEM_OTG *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
174
175 /* Add to the memory offset the size of the allocated block. */
176 memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_OTG);
177 #endif
178
179 /* Set the regular memory pool structure. */
180 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] = (UX_MEMORY_BYTE_POOL *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
181
182 /* Add to the memory offset the size of the allocated block. */
183 memory_pool_offset += (ULONG)sizeof(UX_MEMORY_BYTE_POOL);
184
185 /* Check if the cache save memory pool is valid. */
186 if ((cache_safe_memory_pool_start != UX_NULL) && (cache_safe_memory_size != 0))
187 {
188
189 /* Set the cache safe memory pool structure. */
190 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] = (UX_MEMORY_BYTE_POOL *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
191
192 /* Add to the memory offset the size of the allocated block. */
193 memory_pool_offset += (ULONG)sizeof(UX_MEMORY_BYTE_POOL);
194 }
195 else
196 {
197
198 /* Set the cache safe memory pool structure to regular pool. */
199 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR];
200 }
201
202 /* Make sure the regular memory pool is aligned properly */
203 int_memory_pool_start = (ALIGN_TYPE) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset);
204 int_memory_pool_start += UX_ALIGN_MIN;
205 int_memory_pool_start &= ~((ALIGN_TYPE)UX_ALIGN_MIN);
206
207 /* Set the end of the regular memory pool. */
208 regular_memory_pool_end = (void *) (((UCHAR *) regular_memory_pool_start) + regular_memory_size);
209
210 /* Check if we have memory available. */
211 if (int_memory_pool_start >= (ALIGN_TYPE)regular_memory_pool_end)
212 {
213
214 /* No memory available. */
215 return(UX_MEMORY_INSUFFICIENT);
216 }
217
218 /* get the regular memory pool size. */
219 pool_size = (ULONG) (((ALIGN_TYPE) regular_memory_pool_end) - int_memory_pool_start);
220
221 /* Create the regular memory pool. */
222 _ux_utility_memory_byte_pool_create(_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR],
223 (UX_MEMORY_BYTE_POOL *)int_memory_pool_start,
224 pool_size);
225
226 /* Check the definition of the cache safe pool. If the application or controller do not require any cache safe memory,
227 define the cached safe memory region as the regular memory region. */
228 if ((cache_safe_memory_pool_start != UX_NULL) && (cache_safe_memory_size != 0))
229 {
230
231 /* Reset this memory block */
232 _ux_utility_memory_set(cache_safe_memory_pool_start, 0, cache_safe_memory_size); /* Use case of memset is verified. */
233
234 /* Make sure the cache safe memory pool is aligned properly */
235 int_memory_pool_start = (ALIGN_TYPE) cache_safe_memory_pool_start;
236 int_memory_pool_start += UX_ALIGN_MIN;
237 int_memory_pool_start &= ~((ALIGN_TYPE)UX_ALIGN_MIN);
238
239 cache_safe_memory_pool_end = (void *) (((UCHAR *) cache_safe_memory_pool_start) + cache_safe_memory_size);
240
241 /* Check if we have memory available. */
242 if (int_memory_pool_start >= (ALIGN_TYPE) cache_safe_memory_pool_end)
243 {
244
245 /* No memory available. */
246 return(UX_MEMORY_INSUFFICIENT);
247 }
248
249 pool_size = (ULONG) (((ALIGN_TYPE) cache_safe_memory_pool_end) - int_memory_pool_start);
250
251 _ux_utility_memory_byte_pool_create(_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE],
252 (UX_MEMORY_BYTE_POOL *)int_memory_pool_start, pool_size);
253 }
254
255 #ifdef UX_ENABLE_MEMORY_STATISTICS
256 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_min_free =
257 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
258 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_min_free =
259 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
260
261 /* Other fields are kept zero. */
262 #endif
263
264 #ifdef UX_ENABLE_DEBUG_LOG
265
266 /* Obtain memory for storing the debug log. */
267 _ux_system -> ux_system_debug_log_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_DEBUG_LOG_SIZE);
268 if (_ux_system -> ux_system_debug_log_buffer == UX_NULL)
269 return(UX_MEMORY_INSUFFICIENT);
270
271 /* Setup the head and tail pointers. */
272 _ux_system -> ux_system_debug_log_head = _ux_system -> ux_system_debug_log_buffer;
273 _ux_system -> ux_system_debug_log_tail = _ux_system -> ux_system_debug_log_buffer;
274
275 /* Keep the size in system structure variable. */
276 _ux_system -> ux_system_debug_log_size = UX_DEBUG_LOG_SIZE;
277
278 #endif
279
280 #if !defined(UX_STANDALONE)
281
282 /* Create the Mutex object used by USBX to control critical sections. */
283 status = _ux_system_mutex_create(&_ux_system -> ux_system_mutex, "ux_system_mutex");
284 if(status != UX_SUCCESS)
285 return(UX_MUTEX_ERROR);
286 #endif
287
288 return(UX_SUCCESS);
289 }
290
291
292 /**************************************************************************/
293 /* */
294 /* FUNCTION RELEASE */
295 /* */
296 /* _uxe_system_initialize PORTABLE C */
297 /* 6.3.0 */
298 /* AUTHOR */
299 /* */
300 /* Chaoqiong Xiao, Microsoft Corporation */
301 /* */
302 /* DESCRIPTION */
303 /* */
304 /* This function checks errors in system initialization function call. */
305 /* */
306 /* INPUT */
307 /* */
308 /* regular_memory_pool_start Start of non cached memory pool */
309 /* regular_memory_size Size of non cached memory pool */
310 /* cache_safe_memory_pool_start Start of cached memory pool */
311 /* cache_safe_memory_size Size of cached memory pool */
312 /* */
313 /* OUTPUT */
314 /* */
315 /* None */
316 /* */
317 /* CALLS */
318 /* */
319 /* _ux_system_initialize Get encoded feedback */
320 /* */
321 /* CALLED BY */
322 /* */
323 /* Application */
324 /* */
325 /* RELEASE HISTORY */
326 /* */
327 /* DATE NAME DESCRIPTION */
328 /* */
329 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
330 /* */
331 /**************************************************************************/
_uxe_system_initialize(VOID * regular_memory_pool_start,ULONG regular_memory_size,VOID * cache_safe_memory_pool_start,ULONG cache_safe_memory_size)332 UINT _uxe_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size,
333 VOID *cache_safe_memory_pool_start, ULONG cache_safe_memory_size)
334 {
335
336 /* Compiling option check of descriptors structs. */
337 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_endpoint_descriptor_structure, UX_ENDPOINT_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_ENDPOINT_DESCRIPTOR));
338 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_DEVICE_DESCRIPTOR));
339 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_configuration_descriptor_structure, UX_CONFIGURATION_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_CONFIGURATION_DESCRIPTOR));
340 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_interface_descriptor_structure, UX_INTERFACE_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_INTERFACE_DESCRIPTOR));
341 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_interface_association_descriptor_structure, UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_INTERFACE_ASSOCIATION_DESCRIPTOR));
342 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_string_descriptor_structure, UX_STRING_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_STRING_DESCRIPTOR));
343 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_dfu_functional_descriptor_structure, UX_DFU_FUNCTIONAL_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_DFU_FUNCTIONAL_DESCRIPTOR));
344 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_bos_descriptor_structure, UX_BOS_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_BOS_DESCRIPTOR));
345 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_usb_2_0_extension_descriptor_structure, UX_USB_2_0_EXTENSION_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_USB_2_0_EXTENSION_DESCRIPTOR));
346 UX_ASSERT((_ux_utility_descriptor_parse_size(_ux_system_container_id_descriptor_structure, UX_CONTAINER_ID_DESCRIPTOR_ENTRIES, 0x3u)) == sizeof(UX_CONTAINER_ID_DESCRIPTOR));
347
348
349 /* Sanity check. */
350 if ((regular_memory_pool_start == UX_NULL) || (regular_memory_size == 0))
351 return(UX_INVALID_PARAMETER);
352
353 /* Invoke system initialization function. */
354 return(_ux_system_initialize(regular_memory_pool_start, regular_memory_size,
355 cache_safe_memory_pool_start, cache_safe_memory_size));
356 }
357