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