GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_storage_deactivate.c Lines: 27 27 100.0 %
Date: 2026-03-06 18:57:10 Branches: 10 12 83.3 %

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
/**   Storage Class                                                       */
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_class_storage.h"
30
#include "ux_host_stack.h"
31
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_host_class_storage_deactivate                   PORTABLE C      */
38
/*                                                           6.1.10       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function is called when this instance of the storage device    */
46
/*    has been removed from the bus either directly or indirectly. The    */
47
/*    bulk in\out pipes will be destroyed and the instanced removed.      */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    command                               Pointer to class command      */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    Completion Status                                                   */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    ux_media_close                        Close media                   */
60
/*    _ux_host_stack_endpoint_transfer_abort Abort transfer request       */
61
/*    _ux_host_stack_class_instance_destroy Destroy class instance        */
62
/*    _ux_utility_memory_free               Free memory block             */
63
/*    _ux_host_semaphore_get                Get protection semaphore      */
64
/*    _ux_host_semaphore_delete             Delete protection semaphore   */
65
/*    _ux_utility_thread_schedule_other     Schedule other threads        */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    Storage Class                                                       */
70
/*                                                                        */
71
/**************************************************************************/
72
85
UINT  _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command)
73
{
74
75
UINT                            status;
76
UX_HOST_CLASS_STORAGE           *storage;
77
UX_HOST_CLASS_STORAGE_MEDIA     *storage_media;
78
UX_HOST_CLASS                   *class_inst;
79
UINT                            inst_index;
80
#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
81
UX_MEDIA                        *media;
82
VOID                            *memory;
83
#endif
84
85
86
    /* Get the instance for this class.  */
87
85
    storage =  (UX_HOST_CLASS_STORAGE *) command -> ux_host_class_command_instance;
88
89
    /* We need the class container.  */
90
85
    class_inst =  storage -> ux_host_class_storage_class;
91
92
    /* Point the media structure to the first media in the container.  */
93
85
    storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
94
95
    /* The storage device is being shut down.  */
96
85
    storage -> ux_host_class_storage_state =  UX_HOST_CLASS_INSTANCE_SHUTDOWN;
97
98
    /* We come to this point when the device has been extracted. So there may have been a transaction
99
       being scheduled. We make sure the transaction has been completed by the controller driver.
100
       When the device is extracted, the controller tries multiple times the transaction and retires it
101
       with a DEVICE_NOT_RESPONDING error code.
102
103
       First we take care of endpoint OUT.  */
104
105
    /* We need to abort transactions on the bulk pipes.  */
106
85
    if (storage -> ux_host_class_storage_bulk_out_endpoint != UX_NULL)
107
85
        _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_out_endpoint);
108
109
    /* Then endpoint IN.  */
110
85
    if (storage -> ux_host_class_storage_bulk_in_endpoint != UX_NULL)
111
85
        _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_in_endpoint);
112
113
#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
114
    /* Was the protocol CBI ? */
115
    if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI)
116
    {
117
118
        /* Was there an interrupt endpoint?  */
119
        if (storage -> ux_host_class_storage_interrupt_endpoint != UX_NULL)
120
        {
121
122
            /* Abort the data transfer on the interrupt endpoint.  */
123
            _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_interrupt_endpoint);
124
125
            /* Free the memory that was used by the interrupt endpoint.  */
126
            if (storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer != UX_NULL)
127
                _ux_utility_memory_free(storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
128
        }
129
    }
130
#endif
131
132
    /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
133
       endpoints to exit properly.  */
134
85
    _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
135
136
137
    /* Inform UX_MEDIA (default FileX) of the deactivation of all Media attached to this instance.  */
138
255
    for (inst_index = 0; inst_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; inst_index++)
139
    {
140
141
#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
142
        /* Get the UX_MEDIA (default FileX) attached to this media.  */
143
170
        media = &storage_media -> ux_host_class_storage_media;
144
145
        /* Check if the media belongs to the device being removed.  */
146
170
        if (((UX_HOST_CLASS_STORAGE *) ux_media_driver_info_get(media)) == storage)
147
        {
148
149
            /* Check if the media was properly opened.  */
150
144
            if (storage_media -> ux_host_class_storage_media_status == UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED)
151
            {
152
153
                /* We preserve the memory used by this media.  */
154
70
                memory =  storage_media -> ux_host_class_storage_media_memory;
155
156
                /* Ask UX_MEDIA (default FileX) to unmount the partition.  */
157
70
                ux_media_close(media);
158
159
                /* This device is now unmounted.  */
160
70
                storage_media -> ux_host_class_storage_media_status =  UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED;
161
162
                /* Reset the media ID.  */
163
70
                ux_media_id_set(media, 0);
164
165
                /* Free the memory block used for data transfer on behalf of UX_MEDIA (default FileX).  */
166
70
                _ux_utility_memory_free(memory);
167
            }
168
        }
169
#else
170
171
        /* Check if the media is for this storage.  */
172
        if (storage_media -> ux_host_class_storage_media_status == UX_USED &&
173
            storage_media -> ux_host_class_storage_media_storage == storage)
174
        {
175
176
            /* Free the storage media.  */
177
            storage_media -> ux_host_class_storage_media_status = UX_UNUSED;
178
179
            /* Invoke callback for media removal.  */
180
            if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
181
            {
182
183
                /* Call system change function.  */
184
                _ux_system_host ->  ux_system_host_change_function(UX_STORAGE_MEDIA_REMOVAL,
185
                                    storage -> ux_host_class_storage_class, (VOID *) storage_media);
186
            }
187
        }
188
#endif
189
190
        /* Move to next entry in the media array.  */
191
170
        storage_media++;
192
    }
193
194
    /* Protect thread reentry to this instance.  */
195
85
    status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER);
196
    UX_PARAMETER_NOT_USED(status);
197
198
    /* Destroy the instance.  */
199
85
    _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage);
200
201
    /* Destroy the protection semaphore.  */
202
85
    _ux_host_semaphore_delete(&storage -> ux_host_class_storage_semaphore);
203
204
    /* Before we free the device resources, we need to inform the application
205
        that the device is removed.  */
206
85
    if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
207
    {
208
209
        /* Inform the application the device is removed.  */
210
62
        _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, storage -> ux_host_class_storage_class, (VOID *) storage);
211
    }
212
213
    /* If trace is enabled, insert this event into the trace buffer.  */
214
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_DEACTIVATE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
215
216
    /* If trace is enabled, register this object.  */
217
    UX_TRACE_OBJECT_UNREGISTER(storage);
218
219
    /* Free the storage instance memory.  */
220
85
    _ux_utility_memory_free(storage);
221
222
    /* Return successful completion.  */
223
85
    return(UX_SUCCESS);
224
}
225