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: 2024-12-12 17:16:36 Branches: 10 12 83.3 %

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