GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_initialize.c Lines: 66 66 100.0 %
Date: 2024-12-12 17:16:36 Branches: 48 48 100.0 %

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