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
UX_OVERFLOW_CHECK_MULC_ULONG(sizeof (UX_HOST_CLASS_STORAGE_MEDIA),UX_HOST_CLASS_STORAGE_MAX_MEDIA)32 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS_STORAGE_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA_mul_ovf)
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _ux_host_class_storage_entry PORTABLE C */
39 /* 6.1.10 */
40 /* AUTHOR */
41 /* */
42 /* Chaoqiong Xiao, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function is the entry point of the storage class. It will be */
47 /* called by the USBX stack enumeration module when there is a new */
48 /* USB disk on the bus or when the USB disk is removed. */
49 /* */
50 /* Version 2.0 of the storage class only supports USB FAT media and */
51 /* not CD-ROM. */
52 /* */
53 /* INPUT */
54 /* */
55 /* command Pointer to class command */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* Completion Status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _ux_host_class_storage_activate Activate storage class */
64 /* _ux_host_class_storage_deactivate Deactivate storage class */
65 /* _ux_utility_memory_allocate Allocate memory block */
66 /* _ux_utility_memory_free Free memory block */
67 /* _ux_utility_thread_create Create storage class thread */
68 /* _ux_utility_thread_delete Delete storage class thread */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Host Stack */
73 /* */
74 /* RELEASE HISTORY */
75 /* */
76 /* DATE NAME DESCRIPTION */
77 /* */
78 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
79 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
80 /* added destroy command, */
81 /* used host class extension */
82 /* pointer for class specific */
83 /* structured data, */
84 /* used UX prefix to refer to */
85 /* TX symbols instead of using */
86 /* them directly, */
87 /* resulting in version 6.1 */
88 /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */
89 /* fixed class ext access, */
90 /* resulting in version 6.1.2 */
91 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
92 /* added standalone support, */
93 /* resulting in version 6.1.10 */
94 /* */
95 /**************************************************************************/
96 UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command)
97 {
98
99 UINT status;
100 UX_HOST_CLASS *class_inst;
101 #if !defined(UX_HOST_STANDALONE)
102 UX_HOST_CLASS_STORAGE_EXT *class_ext;
103 #endif
104
105
106 /* The command request will tell us we need to do here, either a enumeration
107 query, an activation or a deactivation. */
108 switch (command -> ux_host_class_command_request)
109 {
110
111 case UX_HOST_CLASS_COMMAND_QUERY:
112
113 /* The query command is used to let the stack enumeration process know if we want to own
114 this device or not. */
115 if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
116 (command -> ux_host_class_command_class == UX_HOST_CLASS_STORAGE_CLASS))
117 return(UX_SUCCESS);
118 else
119 return(UX_NO_CLASS_MATCH);
120
121 case UX_HOST_CLASS_COMMAND_ACTIVATE:
122
123 /* We are assuming the device will mount. If this is the first activation of
124 the storage class, we have to fire up one thread for the media insertion
125 and acquire some memory for the media array. */
126
127 /* Get class. */
128 class_inst = command -> ux_host_class_command_class_ptr;
129
130 #if !defined(UX_HOST_STANDALONE)
131
132 /* Allocate UX_HOST_CLASS_STORAGE_EXT. */
133 if (class_inst -> ux_host_class_ext == UX_NULL)
134 {
135
136 /* Need memory for extension fields. */
137 class_ext = _ux_utility_memory_allocate(UX_NO_ALIGN,
138 UX_REGULAR_MEMORY,
139 sizeof(UX_HOST_CLASS_STORAGE_EXT));
140
141 /* Check completion status. */
142 if (class_ext == UX_NULL)
143 return(UX_MEMORY_INSUFFICIENT);
144
145 /* Create the storage class thread. */
146 status = _ux_host_thread_create(&class_ext -> ux_host_class_thread,
147 "ux_host_storage_thread",
148 _ux_host_class_storage_thread_entry,
149 (ULONG) (ALIGN_TYPE) class_inst,
150 class_ext -> ux_host_class_thread_stack,
151 UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE,
152 UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS,
153 UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS,
154 UX_NO_TIME_SLICE, UX_DONT_START);
155
156 /* Check the completion status. */
157 if (status != UX_SUCCESS)
158 {
159 _ux_utility_memory_free(class_ext);
160 class_inst -> ux_host_class_ext = UX_NULL;
161 return(UX_THREAD_ERROR);
162 }
163
164 /* Set thead ext ptr. */
165 UX_THREAD_EXTENSION_PTR_SET(&(class_ext -> ux_host_class_thread), class_inst);
166
167 /* Save extension. */
168 class_inst -> ux_host_class_ext = (VOID *)class_ext;
169 }
170 else
171 {
172
173 /* Get storage class extension. */
174 class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext;
175 }
176 #endif
177
178 /* Allocate some memory for the media structures used by UX_MEDIA (default FileX). */
179 if (class_inst -> ux_host_class_media == UX_NULL)
180 {
181
182 /* UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA) overflow
183 * is checked outside of function.
184 */
185 class_inst -> ux_host_class_media =
186 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
187 UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA));
188
189 /* Check the completion status. */
190 if (class_inst -> ux_host_class_media == UX_NULL)
191 return(UX_MEMORY_INSUFFICIENT);
192 }
193
194 /* Now that the extension pointer has been set, resume the thread. */
195 _ux_host_thread_resume(&class_ext -> ux_host_class_thread);
196
197 /* The activate command is used when the device inserted has found a parent and
198 is ready to complete the enumeration. */
199 status = _ux_host_class_storage_activate(command);
200
201 /* Return the completion status. */
202 return(status);
203
204 case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
205 return(UX_STATE_NEXT);
206
207 case UX_HOST_CLASS_COMMAND_DEACTIVATE:
208
209 /* The deactivate command is used when the device has been extracted either
210 directly or when its parents has been extracted. */
211 status = _ux_host_class_storage_deactivate(command);
212
213 /* Return the completion status. */
214 return(status);
215
216 case UX_HOST_CLASS_COMMAND_DESTROY:
217
218 /* The destroy command is used when the class is unregistered. */
219
220 /* Get class. */
221 class_inst = command -> ux_host_class_command_class_ptr;
222
223 /* Free allocated media structures. */
224 if (class_inst -> ux_host_class_media)
225 {
226 _ux_utility_memory_free(class_inst -> ux_host_class_media);
227 class_inst -> ux_host_class_media = UX_NULL;
228 }
229
230 #if !defined(UX_HOST_STANDALONE)
231
232 /* Free class extension resources. */
233 if (class_inst -> ux_host_class_ext)
234 {
235
236 /* Get storage class extension. */
237 class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext;
238
239 /* Delete storage thread. */
240 _ux_host_thread_delete(&class_ext -> ux_host_class_thread);
241
242 /* Free class extension memory. */
243 _ux_utility_memory_free(class_ext);
244
245 /* Set extension pointer to NULL. */
246 class_inst -> ux_host_class_ext = UX_NULL;
247 }
248 #endif
249
250 /* Return success. */
251 return(UX_SUCCESS);
252
253 default:
254
255 /* Error trap. */
256 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
257
258 /* If trace is enabled, insert this event into the trace buffer. */
259 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
260
261 /* Return an error. */
262 return(UX_FUNCTION_NOT_SUPPORTED);
263 }
264 }
265
266