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