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 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_storage_activate                     PORTABLE C      */
37 /*                                                           6.3.0        */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function activates an instance of the storage class.           */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    command                               Pointer to class command      */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_host_class_storage_configure      Configure storage device      */
57 /*    _ux_host_class_storage_device_support_check                         */
58 /*                                          Check protocol support        */
59 /*    _ux_host_class_storage_endpoints_get  Get all endpoints             */
60 /*    _ux_host_class_storage_device_initialize                            */
61 /*                                          Initialize storage device     */
62 /*    _ux_host_stack_class_instance_create  Create class instance         */
63 /*    _ux_host_stack_class_instance_destroy Destroy class instance        */
64 /*    _ux_utility_memory_allocate           Allocate memory block         */
65 /*    _ux_utility_memory_free               Free memory block             */
66 /*    _ux_host_semaphore_create             Create semaphore              */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    Storage Class                                                       */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
77 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            resulting in version 6.1    */
79 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
80 /*                                            added standalone support.   */
81 /*                                            resulting in version 6.1.10 */
82 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            fixed parameter/variable    */
84 /*                                            names conflict C++ keyword, */
85 /*                                            resulting in version 6.1.12 */
86 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
87 /*                                            moved class/sub/protocol    */
88 /*                                            check and endpoints get     */
89 /*                                            into _activate function,    */
90 /*                                            resulting in version 6.3.0  */
91 /*                                                                        */
92 /**************************************************************************/
_ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND * command)93 UINT  _ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND *command)
94 {
95 
96 UX_INTERFACE            *interface_ptr;
97 UX_HOST_CLASS_STORAGE   *storage;
98 UINT                    status;
99 
100 
101     /* The storage is always activated by the interface descriptor and not the
102        device descriptor.  */
103     interface_ptr =  (UX_INTERFACE *) command -> ux_host_class_command_container;
104 
105     /* Obtain memory for this class instance.  The memory used MUST BE allocated from a CACHE SAFE memory
106        since the buffer for the CSW is an array contained within each storage instance. */
107     storage =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_STORAGE));
108     if (storage == UX_NULL)
109         return(UX_MEMORY_INSUFFICIENT);
110 
111     /* Store the class container into this instance */
112     storage -> ux_host_class_storage_class =  command -> ux_host_class_command_class_ptr;
113 
114     /* Store the interface container into the storage class instance.  */
115     storage -> ux_host_class_storage_interface =  interface_ptr;
116 
117     /* Store the device container into the storage class instance.  */
118     storage -> ux_host_class_storage_device =  interface_ptr -> ux_interface_configuration -> ux_configuration_device;
119 
120     /* Check class,sub class, protocol.  */
121     status =  _ux_host_class_storage_device_support_check(storage);
122     if (status != UX_SUCCESS)
123     {
124         _ux_utility_memory_free(storage);
125         return(status);
126     }
127 
128     /* Search all the endpoints for the storage interface (Bulk Out, Bulk in,
129        and optional Interrupt endpoint).  */
130     status =  _ux_host_class_storage_endpoints_get(storage);
131     if (status != UX_SUCCESS)
132     {
133         _ux_utility_memory_free(storage);
134         return(status);
135     }
136 
137     /* Create this class instance.  */
138     _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) storage);
139 
140     /* This instance of the device must also be stored in the interface container.  */
141     interface_ptr -> ux_interface_class_instance =  (VOID *) storage;
142 
143 #if defined(UX_HOST_STANDALONE)
144 
145     /* Activate storage class task function.  */
146     storage -> ux_host_class_storage_class -> ux_host_class_task_function = _ux_host_class_storage_tasks_run;
147 
148     /* Mark the storage as live now (media mounts in task).  */
149     storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_MOUNTING;
150 
151     /* Keep storage locked before it's initialized.  */
152     storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_LOCK;
153 #else
154 
155     /* Configure the USB storage device.  */
156     status =  _ux_host_class_storage_configure(storage);
157 
158     /* Create the semaphore to protect multiple threads from accessing the same storage instance.  */
159     if (status == UX_SUCCESS)
160     {
161         status = _ux_host_semaphore_create(&storage -> ux_host_class_storage_semaphore, "ux_host_class_storage_semaphore", 1);
162         if (status != UX_SUCCESS)
163             status = UX_SEMAPHORE_ERROR;
164     }
165 
166     /* Error case, free resources.  */
167     if (status != UX_SUCCESS)
168     {
169 
170         /* Last one, semaphore not created or created error, no need to free.  */
171 
172         /* Error, destroy the class and return an error.  */
173         _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage);
174 
175         /* This instance of the device must also be removed in the interface container.  */
176         interface_ptr -> ux_interface_class_instance =  (VOID *) UX_NULL;
177 
178         /* Free memory for class instance.  */
179         _ux_utility_memory_free(storage);
180 
181         return(status);
182     }
183 
184     /* Mark the storage as mounting now.  */
185     storage -> ux_host_class_storage_state =  UX_HOST_CLASS_INSTANCE_MOUNTING;
186 
187     /* Initialize the USB storage device.  We do not check the status at this stage. We let the instance of this
188        class live even if there was a failure. Because the storage class has many media instance, we will let the
189        disconnection signal clean the instance at a later stage.  */
190     _ux_host_class_storage_device_initialize(storage);
191 
192     /* Mark the storage as live now.  */
193     storage -> ux_host_class_storage_state =  UX_HOST_CLASS_INSTANCE_LIVE;
194 
195 #endif
196 
197     /* If all is fine and the device is mounted, we may need to inform the application
198        if a function has been programmed in the system structure.  */
199     if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
200     {
201 
202         /* Call system change function.  */
203         _ux_system_host ->  ux_system_host_change_function(UX_DEVICE_INSERTION, storage -> ux_host_class_storage_class, (VOID *) storage);
204     }
205 
206     /* If trace is enabled, insert this event into the trace buffer.  */
207     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_ACTIVATE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
208 
209     /* If trace is enabled, register this object.  */
210     UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, storage, 0, 0, 0)
211 
212     /* Return completion status. Force it to success. */
213     return(UX_SUCCESS);
214 }
215 
216