1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
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 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            added option to disable FX  */
78 /*                                            media integration, used UX_ */
79 /*                                            things instead of FX_       */
80 /*                                            things directly, used host  */
81 /*                                            class extension pointer for */
82 /*                                            class specific structured   */
83 /*                                            data,                       */
84 /*                                            resulting in version 6.1    */
85 /*  04-02-2021     Chaoqiong Xiao           Modified comment(s),          */
86 /*                                            fixed compile issues with   */
87 /*                                            some macro options,         */
88 /*                                            resulting in version 6.1.6  */
89 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
90 /*                                            improved media insert/eject */
91 /*                                            management without FX,      */
92 /*                                            resulting in version 6.1.10 */
93 /*                                                                        */
94 /**************************************************************************/
_ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND * command)95 UINT  _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command)
96 {
97 
98 UINT                            status;
99 UX_HOST_CLASS_STORAGE           *storage;
100 UX_HOST_CLASS_STORAGE_MEDIA     *storage_media;
101 UX_HOST_CLASS                   *class_inst;
102 UINT                            inst_index;
103 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
104 UX_MEDIA                        *media;
105 VOID                            *memory;
106 #endif
107 
108 
109     /* Get the instance for this class.  */
110     storage =  (UX_HOST_CLASS_STORAGE *) command -> ux_host_class_command_instance;
111 
112     /* We need the class container.  */
113     class_inst =  storage -> ux_host_class_storage_class;
114 
115     /* Point the media structure to the first media in the container.  */
116     storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
117 
118     /* The storage device is being shut down.  */
119     storage -> ux_host_class_storage_state =  UX_HOST_CLASS_INSTANCE_SHUTDOWN;
120 
121     /* We come to this point when the device has been extracted. So there may have been a transaction
122        being scheduled. We make sure the transaction has been completed by the controller driver.
123        When the device is extracted, the controller tries multiple times the transaction and retires it
124        with a DEVICE_NOT_RESPONDING error code.
125 
126        First we take care of endpoint OUT.  */
127 
128     /* We need to abort transactions on the bulk pipes.  */
129     if (storage -> ux_host_class_storage_bulk_out_endpoint != UX_NULL)
130         _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_out_endpoint);
131 
132     /* Then endpoint IN.  */
133     if (storage -> ux_host_class_storage_bulk_in_endpoint != UX_NULL)
134         _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_in_endpoint);
135 
136 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
137     /* Was the protocol CBI ? */
138     if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI)
139     {
140 
141         /* Was there an interrupt endpoint?  */
142         if (storage -> ux_host_class_storage_interrupt_endpoint != UX_NULL)
143         {
144 
145             /* Abort the data transfer on the interrupt endpoint.  */
146             _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_interrupt_endpoint);
147 
148             /* Free the memory that was used by the interrupt endpoint.  */
149             if (storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer != UX_NULL)
150                 _ux_utility_memory_free(storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
151         }
152     }
153 #endif
154 
155     /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
156        endpoints to exit properly.  */
157     _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
158 
159 
160     /* Inform UX_MEDIA (default FileX) of the deactivation of all Media attached to this instance.  */
161     for (inst_index = 0; inst_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; inst_index++)
162     {
163 
164 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
165         /* Get the UX_MEDIA (default FileX) attached to this media.  */
166         media = &storage_media -> ux_host_class_storage_media;
167 
168         /* Check if the media belongs to the device being removed.  */
169         if (((UX_HOST_CLASS_STORAGE *) ux_media_driver_info_get(media)) == storage)
170         {
171 
172             /* Check if the media was properly opened.  */
173             if (storage_media -> ux_host_class_storage_media_status == UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED)
174             {
175 
176                 /* We preserve the memory used by this media.  */
177                 memory =  storage_media -> ux_host_class_storage_media_memory;
178 
179                 /* Ask UX_MEDIA (default FileX) to unmount the partition.  */
180                 ux_media_close(media);
181 
182                 /* This device is now unmounted.  */
183                 storage_media -> ux_host_class_storage_media_status =  UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED;
184 
185                 /* Reset the media ID.  */
186                 ux_media_id_set(media, 0);
187 
188                 /* Free the memory block used for data transfer on behalf of UX_MEDIA (default FileX).  */
189                 _ux_utility_memory_free(memory);
190             }
191         }
192 #else
193 
194         /* Check if the media is for this storage.  */
195         if (storage_media -> ux_host_class_storage_media_status == UX_USED &&
196             storage_media -> ux_host_class_storage_media_storage == storage)
197         {
198 
199             /* Free the storage media.  */
200             storage_media -> ux_host_class_storage_media_status = UX_UNUSED;
201 
202             /* Invoke callback for media removal.  */
203             if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
204             {
205 
206                 /* Call system change function.  */
207                 _ux_system_host ->  ux_system_host_change_function(UX_STORAGE_MEDIA_REMOVAL,
208                                     storage -> ux_host_class_storage_class, (VOID *) storage_media);
209             }
210         }
211 #endif
212 
213         /* Move to next entry in the media array.  */
214         storage_media++;
215     }
216 
217     /* Protect thread reentry to this instance.  */
218     status = _ux_host_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER);
219     UX_PARAMETER_NOT_USED(status);
220 
221     /* Destroy the instance.  */
222     _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage);
223 
224     /* Destroy the protection semaphore.  */
225     _ux_host_semaphore_delete(&storage -> ux_host_class_storage_semaphore);
226 
227     /* Before we free the device resources, we need to inform the application
228         that the device is removed.  */
229     if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
230     {
231 
232         /* Inform the application the device is removed.  */
233         _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, storage -> ux_host_class_storage_class, (VOID *) storage);
234     }
235 
236     /* If trace is enabled, insert this event into the trace buffer.  */
237     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_DEACTIVATE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
238 
239     /* If trace is enabled, register this object.  */
240     UX_TRACE_OBJECT_UNREGISTER(storage);
241 
242     /* Free the storage instance memory.  */
243     _ux_utility_memory_free(storage);
244 
245     /* Return successful completion.  */
246     return(UX_SUCCESS);
247 }
248 
249