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