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