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