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 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HCD), UX_MAX_HCD), UX_MAX_HCD_mul_ovf)
32 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS), UX_MAX_CLASS_DRIVER), UX_MAX_CLASS_DRIVER_mul_ovf)
33 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_DEVICE), UX_MAX_DEVICES), UX_MAX_DEVICES_mul_ovf)
34 
35 #ifndef UX_HOST_HNP_POLLING_THREAD_STACK_SIZE
36 #define UX_HOST_HNP_POLLING_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE
37 #endif
38 
39 /* Defined USBX host variables.  */
40 
41 UX_SYSTEM_HOST     *_ux_system_host;
42 
43 /* Define table of periodic tree entries, properly indexed.  */
44 
45 UINT _ux_system_host_hcd_periodic_tree_entries[32] = {
46                                                                             0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
47                                                                             0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
48                                                                             0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
49                                                                             0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f};
50 
51 /* Define the names of all the USB Classes of USBX.  */
52 
53 UCHAR _ux_system_host_class_hub_name[] =                                    "ux_host_class_hub";
54 UCHAR _ux_system_host_class_printer_name[] =                                "ux_host_class_printer";
55 UCHAR _ux_system_host_class_storage_name[] =                                "ux_host_class_storage";
56 UCHAR _ux_system_host_class_hid_name[] =                                    "ux_host_class_hid";
57 UCHAR _ux_system_host_class_audio_name[] =                                  "ux_host_class_audio";
58 UCHAR _ux_system_host_class_cdc_acm_name[] =                                "ux_host_class_cdc_acm";
59 UCHAR _ux_system_host_class_cdc_dlc_name[] =                                "ux_host_class_cdc_dlc";
60 UCHAR _ux_system_host_class_cdc_ecm_name[] =                                "ux_host_class_cdc_ecm";
61 UCHAR _ux_system_host_class_prolific_name[] =                               "ux_host_class_prolific";
62 UCHAR _ux_system_host_class_pima_name[] =                                   "ux_host_class_pima";
63 UCHAR _ux_system_host_class_dpump_name[] =                                  "ux_host_class_dpump";
64 UCHAR _ux_system_host_class_asix_name[] =                                   "ux_host_class_asix";
65 UCHAR _ux_system_host_class_swar_name[] =                                   "ux_host_class_sierra_wireless";
66 UCHAR _ux_system_host_class_gser_name[] =                                   "ux_host_class_generic_serial";
67 UCHAR _ux_system_host_class_hid_client_remote_control_name[] =              "ux_host_class_hid_client_remote_control";
68 UCHAR _ux_system_host_class_hid_client_mouse_name[] =                       "ux_host_class_hid_client_mouse";
69 UCHAR _ux_system_host_class_hid_client_keyboard_name[] =                    "ux_host_class_hid_client_keyboard";
70 
71 /* Define the name of all the USB Host Controllers of USBX.  */
72 
73 UCHAR _ux_system_host_hcd_ohci_name[] =                                     "ux_hcd_ohci";
74 UCHAR _ux_system_host_hcd_ehci_name[] =                                     "ux_hcd_ehci";
75 UCHAR _ux_system_host_hcd_isp1161_name[] =                                  "ux_hcd_isp1161";
76 UCHAR _ux_system_host_hcd_isp1362_name[] =                                  "ux_hcd_isp1362";
77 UCHAR _ux_system_host_hcd_sh2_name[] =                                      "ux_hcd_rx";
78 UCHAR _ux_system_host_hcd_rx_name[] =                                       "ux_hcd_sh2";
79 UCHAR _ux_system_host_hcd_pic32_name[] =                                    "ux_hcd_pic32";
80 UCHAR _ux_system_host_hcd_stm32_name[] =                                    "ux_hcd_stm32";
81 UCHAR _ux_system_host_hcd_musb_name[] =                                     "ux_hcd_musb";
82 UCHAR _ux_system_host_hcd_atm7_name[] =                                     "ux_hcd_atm7";
83 UCHAR _ux_system_host_hcd_simulator_name[] =                                "ux_hcd_simulator";
84 
85 /**************************************************************************/
86 /*                                                                        */
87 /*  FUNCTION                                               RELEASE        */
88 /*                                                                        */
89 /*    _ux_host_stack_initialize                           PORTABLE C      */
90 /*                                                           6.1.10       */
91 /*  AUTHOR                                                                */
92 /*                                                                        */
93 /*    Chaoqiong Xiao, Microsoft Corporation                               */
94 /*                                                                        */
95 /*  DESCRIPTION                                                           */
96 /*                                                                        */
97 /*    This function initializes all the host code for USBX to work on a   */
98 /*    specific platform.                                                  */
99 /*                                                                        */
100 /*  INPUT                                                                 */
101 /*                                                                        */
102 /*    (ux_system_host_change_function)        Function pointer to the     */
103 /*                                            callback function for a     */
104 /*                                            device change               */
105 /*                                                                        */
106 /*  OUTPUT                                                                */
107 /*                                                                        */
108 /*    Completion Status                                                   */
109 /*                                                                        */
110 /*                                                                        */
111 /*  CALLS                                                                 */
112 /*                                                                        */
113 /*    _ux_utility_memory_allocate           Allocate host memory          */
114 /*    _ux_utility_semaphore_create          Create host semaphore         */
115 /*    _ux_utility_mutex_create             Create host mutex              */
116 /*    _ux_utility_thread_create             Create host thread            */
117 /*                                                                        */
118 /*  CALLED BY                                                             */
119 /*                                                                        */
120 /*    Application                                                         */
121 /*                                                                        */
122 /*  RELEASE HISTORY                                                       */
123 /*                                                                        */
124 /*    DATE              NAME                      DESCRIPTION             */
125 /*                                                                        */
126 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
127 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
128 /*                                            optimized based on compile  */
129 /*                                            definitions, used UX prefix */
130 /*                                            to refer to TX symbols      */
131 /*                                            instead of using them       */
132 /*                                            directly,                   */
133 /*                                            resulting in version 6.1    */
134 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
135 /*                                            added standalone support,   */
136 /*                                            resulting in version 6.1.10 */
137 /*                                                                        */
138 /**************************************************************************/
_ux_host_stack_initialize(UINT (* ux_system_host_change_function)(ULONG,UX_HOST_CLASS *,VOID *))139 UINT  _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *))
140 {
141 
142 UINT        status;
143 UCHAR       *memory;
144 #if defined(UX_HOST_STANDALONE)
145 UINT        i;
146 UX_DEVICE   *device;
147 #endif
148 
149     /* If trace is enabled, insert this event into the trace buffer.  */
150     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
151 
152     /* Initialize some of the global so that we don't have to recompile the
153        core code when one item is adjusted.  */
154     _ux_system_host -> ux_system_host_max_ed =        UX_MAX_ED;
155     _ux_system_host -> ux_system_host_max_td =        UX_MAX_TD;
156     _ux_system_host -> ux_system_host_max_iso_td =    UX_MAX_ISO_TD;
157     UX_SYSTEM_HOST_MAX_CLASS_SET(UX_MAX_CLASS_DRIVER);
158     UX_SYSTEM_HOST_MAX_HCD_SET(UX_MAX_HCD);
159     UX_SYSTEM_HOST_MAX_DEVICES_SET(UX_MAX_DEVICES);
160 
161     /* Set the change device function address.  */
162     _ux_system_host -> ux_system_host_change_function =  ux_system_host_change_function;
163 
164     /* Allocate memory for the HCDs.
165      * sizeof(UX_HCD)*UX_MAX_HCD overflow is checked outside of the function.
166      */
167     memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD)*UX_MAX_HCD);
168 
169     /* Check for successful allocation.  */
170     if (memory == UX_NULL)
171         return(UX_MEMORY_INSUFFICIENT);
172 
173     /* Set to success by default.  */
174     status = UX_SUCCESS;
175 
176     /* Store memory in system structure.  */
177     _ux_system_host -> ux_system_host_hcd_array =  (UX_HCD *) memory;
178 
179     /* Allocate memory for the classes.
180      * sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER overflow is checked outside of the function.
181      */
182     memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER);
183 
184     /* Check for successful allocation.  */
185     if (memory == UX_NULL)
186         status = UX_MEMORY_INSUFFICIENT;
187     else
188 
189         /* Store memory in system structure.  */
190         _ux_system_host -> ux_system_host_class_array =  (UX_HOST_CLASS *) memory;
191 
192     /* Allocate memory for the device containers.
193      * sizeof(UX_DEVICE)*UX_MAX_DEVICES overflow is checked outside of the function.
194      */
195     if (status == UX_SUCCESS)
196     {
197         memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DEVICE)*UX_MAX_DEVICES);
198 
199         /* Check for successful allocation.  */
200         if(memory == UX_NULL)
201             status = UX_MEMORY_INSUFFICIENT;
202         else
203 
204             /* Store memory in system structure.  */
205             _ux_system_host -> ux_system_host_device_array =  (UX_DEVICE *) memory;
206 
207 #if defined(UX_HOST_STANDALONE)
208 
209         /* Add devices to the enumeration list, with ENUM flags cleared.  */
210         if (status == UX_SUCCESS)
211         {
212 
213             /* Start from the last device instance.  */
214             device = &_ux_system_host -> ux_system_host_device_array[UX_MAX_DEVICES - 1];
215 
216             /* Insert all devices to enumeration list head.  */
217             for (i = 0; i < UX_MAX_DEVICES; i ++)
218             {
219 
220                 /* Insert to head.  */
221                 device -> ux_device_enum_next = _ux_system_host -> ux_system_host_enum_device;
222                 _ux_system_host -> ux_system_host_enum_device = device;
223 
224                 /* Next device.  */
225                 device --;
226             }
227         }
228 #endif
229 
230     }
231 
232 #if !defined(UX_HOST_STANDALONE)
233     /* Obtain enough stack for the two USBX host threads.  */
234     if (status == UX_SUCCESS)
235     {
236         _ux_system_host -> ux_system_host_enum_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
237                                                                             UX_HOST_ENUM_THREAD_STACK_SIZE);
238 
239         /* Check for successful allocation.  */
240         if (_ux_system_host -> ux_system_host_enum_thread_stack == UX_NULL)
241             status = UX_MEMORY_INSUFFICIENT;
242     }
243 
244     /* Allocate another stack area.  */
245     if (status == UX_SUCCESS)
246     {
247         _ux_system_host -> ux_system_host_hcd_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
248                                                                             UX_HOST_HCD_THREAD_STACK_SIZE);
249 
250         /* Check for successful allocation.  */
251         if (_ux_system_host -> ux_system_host_hcd_thread_stack == UX_NULL)
252             status = UX_MEMORY_INSUFFICIENT;
253     }
254 
255     /* Create the semaphores used by the hub and root hub to awake the enumeration thread.  */
256     if (status == UX_SUCCESS)
257     {
258         status =  _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_enum_semaphore, "ux_system_host_enum_semaphore", 0);
259         if(status != UX_SUCCESS)
260             status = UX_SEMAPHORE_ERROR;
261     }
262 
263     /* Create the semaphores used by the HCD to perform the completion phase of transfer_requests.  */
264     if (status == UX_SUCCESS)
265     {
266         status =  _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_hcd_semaphore, "ux_system_host_hcd_semaphore", 0);
267         if(status != UX_SUCCESS)
268             status = UX_SEMAPHORE_ERROR;
269     }
270 
271     /* Create the enumeration thread of USBX.  */
272     if (status == UX_SUCCESS)
273     {
274         status =  _ux_utility_thread_create(&_ux_system_host -> ux_system_host_enum_thread, "ux_system_host_enum_thread", _ux_host_stack_enum_thread_entry,
275                             0, _ux_system_host -> ux_system_host_enum_thread_stack,
276                             UX_HOST_ENUM_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM,
277                             UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, UX_AUTO_START);
278 
279         /* Check the completion status.  */
280         if(status != UX_SUCCESS)
281             status = UX_THREAD_ERROR;
282     }
283 
284     /* Create the HCD thread of USBX.  */
285     if (status == UX_SUCCESS)
286     {
287         status =  _ux_utility_thread_create(&_ux_system_host -> ux_system_host_hcd_thread, "ux_host_stack_hcd_thread", _ux_host_stack_hcd_thread_entry,
288                             0, _ux_system_host -> ux_system_host_hcd_thread_stack,
289                             UX_HOST_HCD_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_HCD,
290                             UX_THREAD_PRIORITY_HCD, UX_NO_TIME_SLICE,UX_AUTO_START);
291 
292         /* Check the completion status.  */
293         if(status != UX_SUCCESS)
294             status = UX_THREAD_ERROR;
295     }
296 #endif
297 
298 #if defined(UX_OTG_SUPPORT) && !defined(UX_OTG_STANDALONE)
299     /* Allocate another stack area for the HNP polling thread.  */
300     if (status == UX_SUCCESS)
301     {
302         _ux_system_host -> ux_system_host_hnp_polling_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
303                                                                             UX_HOST_HNP_POLLING_THREAD_STACK_SIZE);
304 
305         /* Check for successful allocation.  */
306         if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack == UX_NULL)
307             status = UX_MEMORY_INSUFFICIENT;
308     }
309 
310     /* Create the HNP polling thread of USBX.  */
311     if (status == UX_SUCCESS)
312     {
313         status =  _ux_utility_thread_create(&_ux_system_host -> ux_system_host_hnp_polling_thread, "ux_host_stack_hnp_polling_thread", _ux_host_stack_hnp_polling_thread_entry,
314                             0, _ux_system_host -> ux_system_host_hnp_polling_thread_stack,
315                             UX_HOST_HNP_POLLING_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM,
316                             UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, UX_AUTO_START);
317 
318         /* Check the completion status.  */
319         if (status != UX_SUCCESS)
320             status = UX_THREAD_ERROR;
321 
322         /* Return success (SUCCESS).  */
323         else
324             return(status);
325     }
326 
327     /* Free up resources on error cases.  */
328 
329     /* Last resource, _ux_system_host -> ux_system_host_hnp_polling_thread is not created or created error,
330      * no need to delete it.  */
331 
332     /* Free _ux_system_host -> ux_system_host_hnp_polling_thread_stack.  */
333     if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack)
334         _ux_utility_memory_free(_ux_system_host -> ux_system_host_hnp_polling_thread_stack);
335 
336     /* Delete _ux_system_host -> ux_system_host_hcd_thread.  */
337     if (_ux_system_host -> ux_system_host_hcd_thread.tx_thread_id != 0)
338         _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_hcd_thread);
339 #else
340 
341     /* Return completion status to caller if success.  */
342     if (status == UX_SUCCESS)
343         return(status);
344 
345     /* Free up resources on error cases.  */
346 
347     /* Last resource, _ux_system_host -> ux_system_host_hcd_thread is not created or created error,
348      * no need to delete it.  */
349 #endif
350 
351 #if !defined(UX_HOST_STANDALONE)
352     /* Delete _ux_system_host -> ux_system_host_enum_thread.  */
353     if (_ux_system_host -> ux_system_host_enum_thread.tx_thread_id != 0)
354         _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_enum_thread);
355 
356     /* Delete _ux_system_host -> ux_system_host_hcd_semaphore.  */
357     if (_ux_system_host -> ux_system_host_hcd_semaphore.tx_semaphore_id != 0)
358         _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_hcd_semaphore);
359 
360     /* Delete _ux_system_host -> ux_system_host_enum_semaphore.  */
361     if (_ux_system_host -> ux_system_host_enum_semaphore.tx_semaphore_id != 0)
362         _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_enum_semaphore);
363 
364     /* Free _ux_system_host -> ux_system_host_hcd_thread_stack.  */
365     if (_ux_system_host -> ux_system_host_hcd_thread_stack)
366         _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_thread_stack);
367 
368     /* Free _ux_system_host -> ux_system_host_enum_thread_stack.  */
369     if (_ux_system_host -> ux_system_host_enum_thread_stack)
370         _ux_utility_memory_free(_ux_system_host -> ux_system_host_enum_thread_stack);
371 #endif
372 
373     /* Free _ux_system_host -> ux_system_host_device_array.  */
374     if (_ux_system_host -> ux_system_host_device_array)
375         _ux_utility_memory_free(_ux_system_host -> ux_system_host_device_array);
376 
377     /* Free _ux_system_host -> ux_system_host_class_array.  */
378     if (_ux_system_host -> ux_system_host_class_array)
379         _ux_utility_memory_free(_ux_system_host -> ux_system_host_class_array);
380 
381     /* Free _ux_system_host -> ux_system_host_hcd_array.  */
382     _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_array);
383 
384     /* Return completion status to caller.  */
385     return(status);
386 }
387 
388