GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_initialize.c Lines: 66 66 100.0 %
Date: 2026-03-06 18:57:10 Branches: 48 48 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/**************************************************************************/
123
373
UINT  _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *))
124
{
125
126
UINT        status;
127
UCHAR       *memory;
128
#if defined(UX_HOST_STANDALONE)
129
UINT        i;
130
UX_DEVICE   *device;
131
#endif
132
133
    /* If trace is enabled, insert this event into the trace buffer.  */
134
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
135
136
    /* Initialize some of the global so that we don't have to recompile the
137
       core code when one item is adjusted.  */
138
373
    _ux_system_host -> ux_system_host_max_ed =        UX_MAX_ED;
139
373
    _ux_system_host -> ux_system_host_max_td =        UX_MAX_TD;
140
373
    _ux_system_host -> ux_system_host_max_iso_td =    UX_MAX_ISO_TD;
141
373
    UX_SYSTEM_HOST_MAX_CLASS_SET(UX_MAX_CLASS_DRIVER);
142
373
    UX_SYSTEM_HOST_MAX_HCD_SET(UX_MAX_HCD);
143
373
    UX_SYSTEM_HOST_MAX_DEVICES_SET(UX_MAX_DEVICES);
144
145
    /* Set the change device function address.  */
146
373
    _ux_system_host -> ux_system_host_change_function =  ux_system_host_change_function;
147
148
    /* Allocate memory for the HCDs.
149
     * sizeof(UX_HCD)*UX_MAX_HCD overflow is checked outside of the function.
150
     */
151
373
    memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD)*UX_MAX_HCD);
152
153
    /* Check for successful allocation.  */
154
373
    if (memory == UX_NULL)
155
1
        return(UX_MEMORY_INSUFFICIENT);
156
157
    /* Set to success by default.  */
158
372
    status = UX_SUCCESS;
159
160
    /* Store memory in system structure.  */
161
372
    _ux_system_host -> ux_system_host_hcd_array =  (UX_HCD *) memory;
162
163
    /* Allocate memory for the classes.
164
     * sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER overflow is checked outside of the function.
165
     */
166
372
    memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER);
167
168
    /* Check for successful allocation.  */
169
372
    if (memory == UX_NULL)
170
1
        status = UX_MEMORY_INSUFFICIENT;
171
    else
172
173
        /* Store memory in system structure.  */
174
371
        _ux_system_host -> ux_system_host_class_array =  (UX_HOST_CLASS *) memory;
175
176
    /* Allocate memory for the device containers.
177
     * sizeof(UX_DEVICE)*UX_MAX_DEVICES overflow is checked outside of the function.
178
     */
179
372
    if (status == UX_SUCCESS)
180
    {
181
371
        memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DEVICE)*UX_MAX_DEVICES);
182
183
        /* Check for successful allocation.  */
184
371
        if(memory == UX_NULL)
185
1
            status = UX_MEMORY_INSUFFICIENT;
186
        else
187
188
            /* Store memory in system structure.  */
189
370
            _ux_system_host -> ux_system_host_device_array =  (UX_DEVICE *) memory;
190
191
#if defined(UX_HOST_STANDALONE)
192
193
        /* Add devices to the enumeration list, with ENUM flags cleared.  */
194
        if (status == UX_SUCCESS)
195
        {
196
197
            /* Start from the last device instance.  */
198
            device = &_ux_system_host -> ux_system_host_device_array[UX_MAX_DEVICES - 1];
199
200
            /* Insert all devices to enumeration list head.  */
201
            for (i = 0; i < UX_MAX_DEVICES; i ++)
202
            {
203
204
                /* Insert to head.  */
205
                device -> ux_device_enum_next = _ux_system_host -> ux_system_host_enum_device;
206
                _ux_system_host -> ux_system_host_enum_device = device;
207
208
                /* Next device.  */
209
                device --;
210
            }
211
        }
212
#endif
213
214
    }
215
216
#if !defined(UX_HOST_STANDALONE)
217
    /* Obtain enough stack for the two USBX host threads.  */
218
372
    if (status == UX_SUCCESS)
219
    {
220
370
        _ux_system_host -> ux_system_host_enum_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
221
                                                                            UX_HOST_ENUM_THREAD_STACK_SIZE);
222
223
        /* Check for successful allocation.  */
224
370
        if (_ux_system_host -> ux_system_host_enum_thread_stack == UX_NULL)
225
1
            status = UX_MEMORY_INSUFFICIENT;
226
    }
227
228
    /* Allocate another stack area.  */
229
372
    if (status == UX_SUCCESS)
230
    {
231
369
        _ux_system_host -> ux_system_host_hcd_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
232
                                                                            UX_HOST_HCD_THREAD_STACK_SIZE);
233
234
        /* Check for successful allocation.  */
235
369
        if (_ux_system_host -> ux_system_host_hcd_thread_stack == UX_NULL)
236
1
            status = UX_MEMORY_INSUFFICIENT;
237
    }
238
239
    /* Create the semaphores used by the hub and root hub to awake the enumeration thread.  */
240
372
    if (status == UX_SUCCESS)
241
    {
242
368
        status =  _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_enum_semaphore, "ux_system_host_enum_semaphore", 0);
243
368
        if(status != UX_SUCCESS)
244
1
            status = UX_SEMAPHORE_ERROR;
245
    }
246
247
    /* Create the semaphores used by the HCD to perform the completion phase of transfer_requests.  */
248
372
    if (status == UX_SUCCESS)
249
    {
250
367
        status =  _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_hcd_semaphore, "ux_system_host_hcd_semaphore", 0);
251
367
        if(status != UX_SUCCESS)
252
1
            status = UX_SEMAPHORE_ERROR;
253
    }
254
255
    /* Create the enumeration thread of USBX.  */
256
372
    if (status == UX_SUCCESS)
257
    {
258
366
        status =  _ux_utility_thread_create(&_ux_system_host -> ux_system_host_enum_thread, "ux_system_host_enum_thread", _ux_host_stack_enum_thread_entry,
259
366
                            0, _ux_system_host -> ux_system_host_enum_thread_stack,
260
                            UX_HOST_ENUM_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM,
261
                            UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, UX_AUTO_START);
262
263
        /* Check the completion status.  */
264
366
        if(status != UX_SUCCESS)
265
1
            status = UX_THREAD_ERROR;
266
    }
267
268
    /* Create the HCD thread of USBX.  */
269
372
    if (status == UX_SUCCESS)
270
    {
271
365
        status =  _ux_utility_thread_create(&_ux_system_host -> ux_system_host_hcd_thread, "ux_host_stack_hcd_thread", _ux_host_stack_hcd_thread_entry,
272
365
                            0, _ux_system_host -> ux_system_host_hcd_thread_stack,
273
                            UX_HOST_HCD_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_HCD,
274
                            UX_THREAD_PRIORITY_HCD, UX_NO_TIME_SLICE,UX_AUTO_START);
275
276
        /* Check the completion status.  */
277
365
        if(status != UX_SUCCESS)
278
1
            status = UX_THREAD_ERROR;
279
    }
280
#endif
281
282
#if defined(UX_OTG_SUPPORT) && !defined(UX_OTG_STANDALONE)
283
    /* Allocate another stack area for the HNP polling thread.  */
284
    if (status == UX_SUCCESS)
285
    {
286
        _ux_system_host -> ux_system_host_hnp_polling_thread_stack =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
287
                                                                            UX_HOST_HNP_POLLING_THREAD_STACK_SIZE);
288
289
        /* Check for successful allocation.  */
290
        if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack == UX_NULL)
291
            status = UX_MEMORY_INSUFFICIENT;
292
    }
293
294
    /* Create the HNP polling thread of USBX.  */
295
    if (status == UX_SUCCESS)
296
    {
297
        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,
298
                            0, _ux_system_host -> ux_system_host_hnp_polling_thread_stack,
299
                            UX_HOST_HNP_POLLING_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM,
300
                            UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, UX_AUTO_START);
301
302
        /* Check the completion status.  */
303
        if (status != UX_SUCCESS)
304
            status = UX_THREAD_ERROR;
305
306
        /* Return success (SUCCESS).  */
307
        else
308
            return(status);
309
    }
310
311
    /* Free up resources on error cases.  */
312
313
    /* Last resource, _ux_system_host -> ux_system_host_hnp_polling_thread is not created or created error,
314
     * no need to delete it.  */
315
316
    /* Free _ux_system_host -> ux_system_host_hnp_polling_thread_stack.  */
317
    if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack)
318
        _ux_utility_memory_free(_ux_system_host -> ux_system_host_hnp_polling_thread_stack);
319
320
    /* Delete _ux_system_host -> ux_system_host_hcd_thread.  */
321
    if (_ux_host_thread_created(&_ux_system_host -> ux_system_host_hcd_thread))
322
        _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_hcd_thread);
323
#else
324
325
    /* Return completion status to caller if success.  */
326
372
    if (status == UX_SUCCESS)
327
364
        return(status);
328
329
    /* Free up resources on error cases.  */
330
331
    /* Last resource, _ux_system_host -> ux_system_host_hcd_thread is not created or created error,
332
     * no need to delete it.  */
333
#endif
334
335
#if !defined(UX_HOST_STANDALONE)
336
    /* Delete _ux_system_host -> ux_system_host_enum_thread.  */
337
8
    if (_ux_system_thread_created(&_ux_system_host -> ux_system_host_enum_thread))
338
1
        _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_enum_thread);
339
340
    /* Delete _ux_system_host -> ux_system_host_hcd_semaphore.  */
341
8
    if (_ux_host_semaphore_created(&_ux_system_host -> ux_system_host_hcd_semaphore))
342
2
        _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_hcd_semaphore);
343
344
    /* Delete _ux_system_host -> ux_system_host_enum_semaphore.  */
345
8
    if (_ux_host_semaphore_created(&_ux_system_host -> ux_system_host_enum_semaphore))
346
3
        _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_enum_semaphore);
347
348
    /* Free _ux_system_host -> ux_system_host_hcd_thread_stack.  */
349
8
    if (_ux_system_host -> ux_system_host_hcd_thread_stack)
350
4
        _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_thread_stack);
351
352
    /* Free _ux_system_host -> ux_system_host_enum_thread_stack.  */
353
8
    if (_ux_system_host -> ux_system_host_enum_thread_stack)
354
5
        _ux_utility_memory_free(_ux_system_host -> ux_system_host_enum_thread_stack);
355
#endif
356
357
    /* Free _ux_system_host -> ux_system_host_device_array.  */
358
8
    if (_ux_system_host -> ux_system_host_device_array)
359
6
        _ux_utility_memory_free(_ux_system_host -> ux_system_host_device_array);
360
361
    /* Free _ux_system_host -> ux_system_host_class_array.  */
362
8
    if (_ux_system_host -> ux_system_host_class_array)
363
7
        _ux_utility_memory_free(_ux_system_host -> ux_system_host_class_array);
364
365
    /* Free _ux_system_host -> ux_system_host_hcd_array.  */
366
8
    _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_array);
367
368
    /* Return completion status to caller.  */
369
8
    return(status);
370
}
371