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