GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_device_resources_free.c Lines: 38 38 100.0 %
Date: 2026-03-06 18:57:10 Branches: 16 16 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_device_resources_free                PORTABLE C      */
37
/*                                                           6.1.12       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function will free all the device resources allocated.         */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    device                                Device pointer                */
49
/*                                                                        */
50
/*  OUTPUT                                                                */
51
/*                                                                        */
52
/*    Completion Status                                                   */
53
/*                                                                        */
54
/*  CALLS                                                                 */
55
/*                                                                        */
56
/*    _ux_host_stack_endpoint_transfer_abort                              */
57
/*                                          Abort transfer                */
58
/*    _ux_host_stack_endpoint_instance_delete                             */
59
/*                                          Delete endpoint instance      */
60
/*    _ux_utility_memory_free               Free memory block             */
61
/*    _ux_utility_memory_set                Set memory with a value       */
62
/*    _ux_utility_semaphore_delete          Semaphore delete              */
63
/*    _ux_utility_thread_schedule_other     Sleep thread to let others    */
64
/*                                          run                           */
65
/*    (ux_hcd_entry_function)               HCD entry function            */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    USBX Components                                                     */
70
/*                                                                        */
71
/**************************************************************************/
72
1281
UINT  _ux_host_stack_device_resources_free(UX_DEVICE *device)
73
{
74
75
UX_CONFIGURATION        *configuration;
76
UX_INTERFACE            *interface_ptr;
77
UX_ENDPOINT             *endpoint;
78
VOID                    *container;
79
ULONG                   current_alternate_setting;
80
UX_HCD                  *hcd;
81
#if UX_MAX_DEVICES > 1
82
UINT                    device_address_byte_index;
83
UINT                    device_address_bit_index;
84
UCHAR                   device_address_byte;
85
#endif
86
#if defined(UX_HOST_STANDALONE)
87
UX_DEVICE               *enum_next;
88
#endif
89
90
    /* If trace is enabled, insert this event into the trace buffer.  */
91
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_RESOURCE_FREE, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
92
93
#if defined(UX_HOST_STANDALONE)
94
95
    /* Free possible allocated enumeration resources.  */
96
    if (device -> ux_device_flags & UX_DEVICE_FLAG_ENUM)
97
    {
98
99
        /* If transfer buffer is not freed, free it.  */
100
        if (device -> ux_device_enum_trans &&
101
            device -> ux_device_enum_trans -> ux_transfer_request_data_pointer)
102
        {
103
            _ux_utility_memory_free(device -> ux_device_enum_trans ->
104
                                            ux_transfer_request_data_pointer);
105
        }
106
107
        /* If configuration is not attached, free it.  */
108
        if ((device -> ux_device_enum_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE) ||
109
            ((device -> ux_device_enum_state == UX_HOST_STACK_ENUM_TRANS_WAIT) &&
110
            (device -> ux_device_enum_next_state == UX_HOST_STACK_ENUM_CONFIG_DESCR_PARSE)))
111
        {
112
            if (device -> ux_device_enum_inst.configuration &&
113
                device -> ux_device_enum_inst.configuration ->
114
                                            ux_configuration_device == UX_NULL)
115
            {
116
                _ux_utility_memory_free(device -> ux_device_enum_inst.ptr);
117
            }
118
        }
119
    }
120
121
    /* Reset device flags.  */
122
    device -> ux_device_flags = 0;
123
124
#endif
125
126
    /* Set the alternate setting to zero.  */
127
1281
    current_alternate_setting = 0;
128
129
    /* Get the first configuration registered to the device.  */
130
1281
    configuration =  device -> ux_device_first_configuration;
131
132
    /* Parse all the configurations, remove all resources for the possible configuration.  */
133
2093
    while (configuration != UX_NULL)
134
    {
135
136
        /* We have the correct configuration, search the interface(s).  */
137
812
        interface_ptr =  configuration -> ux_configuration_first_interface;
138
139
        /* Parse all the interfaces.  */
140
2416
        while (interface_ptr != UX_NULL)
141
        {
142
143
            /* The alternate setting 0 has the selected alternate setting value.  */
144
1604
            if (interface_ptr -> ux_interface_descriptor.bAlternateSetting == 0)
145
1369
                current_alternate_setting = interface_ptr -> ux_interface_current_alternate_setting;
146
147
            /* If this is the selected interface, we need to free all the endpoints
148
            attached to the alternate setting for this interface.  */
149
1604
            endpoint =  interface_ptr -> ux_interface_first_endpoint;
150
151
            /* Parse all the endpoints.  */
152
3734
            while (endpoint != UX_NULL)
153
            {
154
155
                /* Check if this is the selected interface.  */
156
2130
                if (interface_ptr -> ux_interface_descriptor.bAlternateSetting == current_alternate_setting)
157
                {
158
159
                    /* Delete the endpoint instance first.  */
160
1767
                    _ux_host_stack_endpoint_instance_delete(endpoint);
161
                }
162
163
                /* Memorize the endpoint container address.  */
164
2130
                container =  (VOID *) endpoint;
165
166
                /* Get the next endpoint.  */
167
2130
                endpoint =  endpoint -> ux_endpoint_next_endpoint;
168
169
                /* Delete the endpoint container.  */
170
2130
                _ux_utility_memory_free(container);
171
            }
172
173
174
            /* Memorize the interface container address.  */
175
1604
            container =  (VOID *) interface_ptr;
176
177
            /* Get the next interface.  */
178
1604
            interface_ptr =  interface_ptr -> ux_interface_next_interface;
179
180
            /* Delete the interface container.  */
181
1604
            _ux_utility_memory_free(container);
182
        }
183
184
        /* Memorize this configuration address before we free it.  */
185
812
        container =  (VOID *) configuration;
186
187
        /* Move to the next configuration in the list.  */
188
812
        configuration =  configuration -> ux_configuration_next_configuration;
189
190
        /* Free the configuration.  */
191
812
        _ux_utility_memory_free(container);
192
    }
193
194
    /* If there was a copy of packed descriptor, free it.  */
195
1281
    if (device -> ux_device_packed_configuration)
196
    {
197
7
        _ux_utility_memory_free(device -> ux_device_packed_configuration);
198
199
        /* Pointer and keep count is set NULL later while reseting instance memory.  */
200
    }
201
202
    /* We need the HCD address for the control endpoint removal and to free
203
       the device address.  */
204
1281
    hcd = UX_DEVICE_HCD_GET(device);
205
206
    /* Was the control endpoint already created ? */
207
1281
    if (device -> ux_device_control_endpoint.ux_endpoint_state != 0)
208
    {
209
210
        /* There may be pending transactions on the control endpoint. They need to be aborted.  */
211
1258
        _ux_host_stack_endpoint_transfer_abort(&device -> ux_device_control_endpoint);
212
213
        /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
214
            the control endpoint to exit properly.  */
215
1258
        _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
216
217
        /* The control endpoint should be destroyed at the HCD level.  */
218
1255
        hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *) &device -> ux_device_control_endpoint);
219
    }
220
221
    /* The semaphore attached to the control endpoint must be destroyed.  */
222
1278
    _ux_host_semaphore_delete(&device -> ux_device_control_endpoint.ux_endpoint_transfer_request.ux_transfer_request_semaphore);
223
224
#if UX_MAX_DEVICES > 1
225
    /* Check if the device had an assigned address.  */
226
1278
    if (device -> ux_device_address != 0)
227
    {
228
229
        /* The USB address of this device can now be returned to the pool
230
           We need the HCD pointer for this operation.  */
231
232
        /* Calculate in which byte index the device address belongs.  */
233
1255
        device_address_byte_index =  (UINT) (device -> ux_device_address-1)/8;
234
235
        /* Now calculate the amount left in the byte index in bit.  */
236
1255
        device_address_bit_index =  (UINT) (device -> ux_device_address-1)%8;
237
238
        /* Build the mask for the address.  */
239
1255
        device_address_byte =  (UCHAR)(1 << device_address_bit_index);
240
241
        /* Free the address.  */
242
1255
        hcd -> ux_hcd_address[device_address_byte_index] &=  (UCHAR)~device_address_byte;
243
    }
244
#endif
245
246
    /* The semaphore for endpoint 0 protection must be destroyed.  */
247
1278
    _ux_host_semaphore_delete(&device -> ux_device_protection_semaphore);
248
249
    /* Now this device can be free and its container return to the pool.  */
250
#if defined(UX_HOST_STANDALONE)
251
    enum_next = device -> ux_device_enum_next;
252
    _ux_utility_memory_set(device, 0, sizeof(UX_DEVICE)); /* Use case of memset is verified. */
253
    device -> ux_device_enum_next = enum_next;
254
#else
255
256
1278
    _ux_utility_memory_set(device, 0, sizeof(UX_DEVICE)); /* Use case of memset is verified. */
257
#endif
258
259
    /* Mark the device handle as unused.  */
260
1278
    device -> ux_device_handle =  UX_UNUSED;
261
262
    /* Return successful completion.  */
263
1278
    return(UX_SUCCESS);
264
}
265