GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_new_interface_create.c Lines: 36 36 100.0 %
Date: 2026-03-06 18:57:10 Branches: 22 22 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
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_host_stack_new_interface_create                 PORTABLE C      */
37
/*                                                           6.1.12       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function creates a new interface for the current configuration */
45
/*    scanned. A device has at least 1 alternate setting per interface    */
46
/*    which is the default one.                                           */
47
/*                                                                        */
48
/*    The interface is hooked to the configuration that owns it.          */
49
/*                                                                        */
50
/*    From the interface descriptor, all the endpoints are hooked but     */
51
/*    not activated.                                                      */
52
/*                                                                        */
53
/*  INPUT                                                                 */
54
/*                                                                        */
55
/*    configuration                         Configuration container that  */
56
/*                                            owns this interface         */
57
/*    interface_pointer                     Pointer to a unparsed         */
58
/*                                            interface descriptor        */
59
/*    length                                Length remaining in this      */
60
/*                                            descriptor                  */
61
/*                                                                        */
62
/*  OUTPUT                                                                */
63
/*                                                                        */
64
/*    Completion Status                                                   */
65
/*                                                                        */
66
/*  CALLS                                                                 */
67
/*                                                                        */
68
/*    _ux_host_stack_new_endpoint_create    Create new endpoint           */
69
/*    _ux_utility_descriptor_parse          Parse the descriptor          */
70
/*    _ux_utility_memory_allocate           Allocate memory block         */
71
/*                                                                        */
72
/*  CALLED BY                                                             */
73
/*                                                                        */
74
/*    USBX Components                                                     */
75
/*                                                                        */
76
/**************************************************************************/
77
1973
UINT  _ux_host_stack_new_interface_create(UX_CONFIGURATION *configuration,
78
                                            UCHAR * descriptor, ULONG length)
79
{
80
81
UX_INTERFACE        *list_interface;
82
UX_INTERFACE        *interface_ptr;
83
UINT                number_endpoints;
84
UINT                descriptor_length;
85
UINT                descriptor_type;
86
UINT                status;
87
UCHAR               *this_interface_descriptor;
88
89
    /* Obtain memory for storing this new interface.  */
90
1973
    interface_ptr =  (UX_INTERFACE *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_INTERFACE));
91
92
    /* If no memory left, exit with error.  */
93
1973
    if (interface_ptr == UX_NULL)
94
3
        return(UX_MEMORY_INSUFFICIENT);
95
96
    /* Save the interface handle in the container, this is for ensuring the
97
       interface container is not corrupted.  */
98
1970
    interface_ptr -> ux_interface_handle =  (ULONG) (ALIGN_TYPE) interface_ptr;
99
100
    /* Parse the interface descriptor and make it machine independent.  */
101
1970
    _ux_utility_descriptor_parse(descriptor,
102
                            _ux_system_interface_descriptor_structure,
103
                            UX_INTERFACE_DESCRIPTOR_ENTRIES,
104
1970
                            (UCHAR *) &interface_ptr -> ux_interface_descriptor);
105
106
    /* The configuration that owns this interface is memorized in the
107
       interface container itself, easier for back chaining.  */
108
1970
    interface_ptr -> ux_interface_configuration =  configuration;
109
110
    /* If the interface belongs to an IAD, remember the IAD Class/SubClass/Protocol.  */
111
1970
    interface_ptr -> ux_interface_iad_class    = configuration -> ux_configuration_iad_class;
112
1970
    interface_ptr -> ux_interface_iad_subclass = configuration -> ux_configuration_iad_subclass;
113
1970
    interface_ptr -> ux_interface_iad_protocol = configuration -> ux_configuration_iad_protocol;
114
115
    /* There is 2 cases for the creation of the interface descriptor
116
       if this is the first one, the interface descriptor is hooked
117
       to the configuration. If it is not the first one, the interface
118
       is hooked to the end of the chain of interfaces.  */
119
1970
    if (configuration -> ux_configuration_first_interface == UX_NULL)
120
    {
121
1049
        configuration -> ux_configuration_first_interface =  interface_ptr;
122
    }
123
    else
124
    {
125
126
921
        list_interface =  configuration -> ux_configuration_first_interface;
127
128
        /* Traverse the list until we reach the end */
129
1397
        while (list_interface -> ux_interface_next_interface != UX_NULL)
130
        {
131
132
476
            list_interface =  list_interface -> ux_interface_next_interface;
133
        }
134
135
        /* Hook the interface.  */
136
921
        list_interface -> ux_interface_next_interface =  interface_ptr;
137
    }
138
139
    /* Traverse the interface in search of all endpoints that belong to it.
140
       We need the length remaining in the descriptor and the number of endpoints
141
       reported for this interface.  */
142
1970
    number_endpoints =  interface_ptr -> ux_interface_descriptor.bNumEndpoints;
143
144
1970
    this_interface_descriptor = descriptor;
145
146

8041
    while (length && (number_endpoints != 0))
147
    {
148
149
        /* Gather the length and type of the descriptor.  */
150
6189
        descriptor_length =  *descriptor;
151
6189
        descriptor_type =    *(descriptor+1);
152
153
        /* make sure this descriptor has at least the minimum length.  */
154
6189
        if (descriptor_length < 3)
155
        {
156
157
            /* Error trap. */
158
3
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
159
160
            /* If trace is enabled, insert this event into the trace buffer.  */
161
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
162
163
3
            return(UX_DESCRIPTOR_CORRUPTED);
164
        }
165
166
        /* Check the type for an interface descriptor.  */
167
6186
        if (descriptor_type == UX_ENDPOINT_DESCRIPTOR_ITEM)
168
        {
169
170
            /* We have found an endpoint descriptor for this interface.  */
171
2709
            status =  _ux_host_stack_new_endpoint_create(interface_ptr, descriptor);
172
173
            /* Check return status.  */
174
2709
            if(status != UX_SUCCESS)
175
109
                return(status);
176
177
2600
            number_endpoints--;
178
        }
179
180
        /* Verify if the descriptor is still valid, or we moved to next interface.  */
181

6077
        if ((descriptor_length > length) || (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM && descriptor != this_interface_descriptor))
182
        {
183
184
            /* Error trap. */
185
6
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
186
187
            /* If trace is enabled, insert this event into the trace buffer.  */
188
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
189
190
6
            return(UX_DESCRIPTOR_CORRUPTED);
191
        }
192
193
        /* Jump to the next descriptor if we have not reached the end.  */
194
6071
        descriptor +=  descriptor_length;
195
6071
        length -=  descriptor_length;
196
    }
197
198
    /* Return success!  */
199
1852
    return(UX_SUCCESS);
200
}
201