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