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 /**************************************************************************/
_ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND * command)94 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     storage =  (UX_HOST_CLASS_STORAGE *) command -> ux_host_class_command_instance;
110 
111     /* We need the class container.  */
112     class_inst =  storage -> ux_host_class_storage_class;
113 
114     /* Point the media structure to the first media in the container.  */
115     storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
116 
117     /* The storage device is being shut down.  */
118     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     if (storage -> ux_host_class_storage_bulk_out_endpoint != UX_NULL)
129         _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_out_endpoint);
130 
131     /* Then endpoint IN.  */
132     if (storage -> ux_host_class_storage_bulk_in_endpoint != UX_NULL)
133         _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     _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     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         media = &storage_media -> ux_host_class_storage_media;
166 
167         /* Check if the media belongs to the device being removed.  */
168         if (((UX_HOST_CLASS_STORAGE *) ux_media_driver_info_get(media)) == storage)
169         {
170 
171             /* Check if the media was properly opened.  */
172             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                 memory =  storage_media -> ux_host_class_storage_media_memory;
177 
178                 /* Ask UX_MEDIA (default FileX) to unmount the partition.  */
179                 ux_media_close(media);
180 
181                 /* This device is now unmounted.  */
182                 storage_media -> ux_host_class_storage_media_status =  UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED;
183 
184                 /* Reset the media ID.  */
185                 ux_media_id_set(media, 0);
186 
187                 /* Free the memory block used for data transfer on behalf of UX_MEDIA (default FileX).  */
188                 _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         storage_media++;
214     }
215 
216     /* Protect thread reentry to this instance.  */
217     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     _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage);
222 
223     /* Destroy the protection semaphore.  */
224     _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     if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
229     {
230 
231         /* Inform the application the device is removed.  */
232         _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     _ux_utility_memory_free(storage);
243 
244     /* Return successful completion.  */
245     return(UX_SUCCESS);
246 }
247 
248