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 /** USBX Component */
14 /** */
15 /** Device CDC Class */
16 /** */
17 /**************************************************************************/
18 /**************************************************************************/
19
20 #define UX_SOURCE_CODE
21
22
23 /* Include necessary system files. */
24
25 #include "ux_api.h"
26 #include "ux_device_class_pima.h"
27 #include "ux_device_stack.h"
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _ux_device_class_pima_initialize PORTABLE C */
35 /* 6.3.0 */
36 /* AUTHOR */
37 /* */
38 /* Chaoqiong Xiao, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function initializes the USB Pima device class */
43 /* */
44 /* INPUT */
45 /* */
46 /* command Pointer to pima command */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* Completion Status */
51 /* */
52 /* CALLS */
53 /* */
54 /* _ux_utility_memory_allocate Allocate memory */
55 /* _ux_utility_memory_free Free memory */
56 /* _ux_device_thread_create Create thread */
57 /* */
58 /* CALLED BY */
59 /* */
60 /* USBX Source Code */
61 /* */
62 /* RELEASE HISTORY */
63 /* */
64 /* DATE NAME DESCRIPTION */
65 /* */
66 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
67 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
68 /* used UX prefix to refer to */
69 /* TX symbols instead of using */
70 /* them directly, */
71 /* resulting in version 6.1 */
72 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
73 /* refined macros names, */
74 /* added cancel callback, */
75 /* resulting in version 6.1.10 */
76 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
77 /* fixed standalone compile, */
78 /* resulting in version 6.1.11 */
79 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
80 /* fixed parameter/variable */
81 /* names conflict C++ keyword, */
82 /* resulting in version 6.1.12 */
83 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
84 /* added a new mode to manage */
85 /* endpoint buffer in classes, */
86 /* resulting in version 6.3.0 */
87 /* */
88 /**************************************************************************/
_ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND * command)89 UINT _ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command)
90 {
91 #if defined(UX_DEVICE_STANDALONE)
92 UX_PARAMETER_NOT_USED(command);
93 return(UX_FUNCTION_NOT_SUPPORTED);
94 #else
95 UINT status;
96 UX_SLAVE_CLASS_PIMA *pima;
97 UX_SLAVE_CLASS_PIMA_PARAMETER *pima_parameter;
98 UX_SLAVE_CLASS *class_ptr;
99
100 /* Get the class container. */
101 class_ptr = command -> ux_slave_class_command_class_ptr;
102
103 /* Create an instance of the device pima class. */
104 pima = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA));
105
106 /* Check for successful allocation. */
107 if (pima == UX_NULL)
108 return(UX_MEMORY_INSUFFICIENT);
109
110 /* Save the address of the PIMA instance inside the PIMA container. */
111 class_ptr -> ux_slave_class_instance = (VOID *) pima;
112
113 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
114
115 /* Allocate some memory for endpoints. */
116 UX_ASSERT(!UX_DEVICE_CLASS_PIMA_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW);
117 pima -> ux_device_class_pima_endpoint_buffer =
118 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY,
119 UX_DEVICE_CLASS_PIMA_ENDPOINT_BUFFER_SIZE);
120 if (pima -> ux_device_class_pima_endpoint_buffer == UX_NULL)
121 {
122 _ux_utility_memory_free(pima);
123 return(UX_MEMORY_INSUFFICIENT);
124 }
125 #endif
126
127 /* Allocate some memory for the thread stack. */
128 class_ptr -> ux_slave_class_thread_stack =
129 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
130
131 /* Check for successful allocation. */
132 if (class_ptr -> ux_slave_class_thread_stack == UX_NULL)
133 status = UX_MEMORY_INSUFFICIENT;
134 else
135 status = UX_SUCCESS;
136
137 /* This instance needs to be running in a different thread. So start
138 a new thread. We pass a pointer to the class to the new thread. This thread
139 does not start until we have a instance of the class. */
140 if (status == UX_SUCCESS)
141 {
142 status = _ux_device_thread_create(&class_ptr -> ux_slave_class_thread, "ux_slave_class_thread",
143 _ux_device_class_pima_thread,
144 (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) class_ptr -> ux_slave_class_thread_stack,
145 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
146 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
147
148 /* Check the creation of this thread. */
149 if (status != UX_SUCCESS)
150 status = UX_THREAD_ERROR;
151 }
152
153 UX_THREAD_EXTENSION_PTR_SET(&(class_ptr -> ux_slave_class_thread), class_ptr)
154
155 /* There is error, free resources and return error. */
156 if (status != UX_SUCCESS)
157 {
158
159 /* The last resource, thread is not created or created error,
160 no need to free. */
161
162 if (class_ptr -> ux_slave_class_thread_stack)
163 _ux_utility_memory_free(class_ptr -> ux_slave_class_thread_stack);
164
165 /* Detach instance and free memory. */
166 class_ptr -> ux_slave_class_instance = UX_NULL;
167 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
168 _ux_utility_memory_free(pima -> ux_device_class_pima_endpoint_buffer);
169 #endif
170 _ux_utility_memory_free(pima);
171
172 /* Return completion status. */
173 return(status);
174 }
175
176 /* Success, complete remaining settings. */
177
178 /* Get the pointer to the application parameters for the pima class. */
179 pima_parameter = command -> ux_slave_class_command_parameter;
180
181 /* Store all the application parameter information about the media. */
182 pima -> ux_device_class_pima_manufacturer = pima_parameter -> ux_device_class_pima_parameter_manufacturer;
183 pima -> ux_device_class_pima_model = pima_parameter -> ux_device_class_pima_parameter_model;
184 pima -> ux_device_class_pima_device_version = pima_parameter -> ux_device_class_pima_parameter_device_version;
185 pima -> ux_device_class_pima_serial_number = pima_parameter -> ux_device_class_pima_parameter_serial_number;
186
187 /* Store all the application parameter information about the storage. */
188 pima -> ux_device_class_pima_storage_id = pima_parameter -> ux_device_class_pima_parameter_storage_id;
189 pima -> ux_device_class_pima_storage_type = pima_parameter -> ux_device_class_pima_parameter_storage_type;
190 pima -> ux_device_class_pima_storage_file_system_type = pima_parameter -> ux_device_class_pima_parameter_storage_file_system_type;
191 pima -> ux_device_class_pima_storage_access_capability = pima_parameter -> ux_device_class_pima_parameter_storage_access_capability;
192 pima -> ux_device_class_pima_storage_max_capacity_low = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_low;
193 pima -> ux_device_class_pima_storage_max_capacity_high = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_high;
194 pima -> ux_device_class_pima_storage_free_space_low = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_low;
195 pima -> ux_device_class_pima_storage_free_space_high = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_high;
196 pima -> ux_device_class_pima_storage_free_space_image = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_image;
197 pima -> ux_device_class_pima_storage_description = pima_parameter -> ux_device_class_pima_parameter_storage_description;
198 pima -> ux_device_class_pima_storage_volume_label = pima_parameter -> ux_device_class_pima_parameter_storage_volume_label;
199
200 /* Update device properties supported. */
201 pima -> ux_device_class_pima_device_properties_list = pima_parameter -> ux_device_class_pima_parameter_device_properties_list;
202
203 /* Update the capture formats supported list. */
204 pima -> ux_device_class_pima_supported_capture_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_capture_formats_list;
205
206 /* Update the image formats supported list. */
207 pima -> ux_device_class_pima_supported_image_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_image_formats_list;
208
209 #ifdef UX_PIMA_WITH_MTP_SUPPORT
210 /* Update the internal pima structure with the object properties. */
211 pima -> ux_device_class_pima_object_properties_list = pima_parameter -> ux_device_class_pima_parameter_object_properties_list;
212
213 #endif
214
215 /* Store the callback functions for request. */
216 pima -> ux_device_class_pima_cancel = pima_parameter -> ux_device_class_pima_parameter_cancel;
217
218 /* Store the callback functions for device. */
219 pima -> ux_device_class_pima_device_reset = pima_parameter -> ux_device_class_pima_parameter_device_reset;
220 pima -> ux_device_class_pima_device_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get;
221 pima -> ux_device_class_pima_device_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_get;
222 pima -> ux_device_class_pima_device_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_set;
223
224 /* Store the callback functions for storage. */
225 pima -> ux_device_class_pima_storage_format = pima_parameter -> ux_device_class_pima_parameter_storage_format;
226 pima -> ux_device_class_pima_storage_info_get = pima_parameter -> ux_device_class_pima_parameter_storage_info_get;
227
228 /* Store the callback functions for objects. */
229 pima -> ux_device_class_pima_object_number_get = pima_parameter -> ux_device_class_pima_parameter_object_number_get;
230 pima -> ux_device_class_pima_object_handles_get = pima_parameter -> ux_device_class_pima_parameter_object_handles_get;
231 pima -> ux_device_class_pima_object_info_get = pima_parameter -> ux_device_class_pima_parameter_object_info_get;
232 pima -> ux_device_class_pima_object_data_get = pima_parameter -> ux_device_class_pima_parameter_object_data_get;
233 pima -> ux_device_class_pima_object_info_send = pima_parameter -> ux_device_class_pima_parameter_object_info_send;
234 pima -> ux_device_class_pima_object_data_send = pima_parameter -> ux_device_class_pima_parameter_object_data_send;
235 pima -> ux_device_class_pima_object_delete = pima_parameter -> ux_device_class_pima_parameter_object_delete;
236
237
238 #ifdef UX_PIMA_WITH_MTP_SUPPORT
239 /* Add the MTP specific callback functions. */
240 pima -> ux_device_class_pima_object_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_desc_get;
241 pima -> ux_device_class_pima_object_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_get;
242 pima -> ux_device_class_pima_object_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_set;
243 pima -> ux_device_class_pima_object_references_get = pima_parameter -> ux_device_class_pima_parameter_object_references_get;
244 pima -> ux_device_class_pima_object_references_set = pima_parameter -> ux_device_class_pima_parameter_object_references_set;
245 #endif
246
247 /* Store the application owner. */
248 pima -> ux_device_class_pima_application = pima_parameter -> ux_device_class_pima_parameter_application;
249
250 /* Store the start and stop signals if needed by the application. */
251 pima -> ux_device_class_pima_instance_activate = pima_parameter -> ux_device_class_pima_instance_activate;
252 pima -> ux_device_class_pima_instance_deactivate = pima_parameter -> ux_device_class_pima_instance_deactivate;
253
254 /* Return completion status. */
255 return(status);
256 #endif
257 }
258
259
260 /**************************************************************************/
261 /* */
262 /* FUNCTION RELEASE */
263 /* */
264 /* _uxe_device_class_pima_initialize PORTABLE C */
265 /* 6.3.0 */
266 /* AUTHOR */
267 /* */
268 /* Chaoqiong Xiao, Microsoft Corporation */
269 /* */
270 /* DESCRIPTION */
271 /* */
272 /* This function checks errors in PIMA initialization function call. */
273 /* */
274 /* INPUT */
275 /* */
276 /* command Pointer to pima command */
277 /* */
278 /* OUTPUT */
279 /* */
280 /* Completion Status */
281 /* */
282 /* CALLS */
283 /* */
284 /* _ux_device_class_pima_initialize Initialize pima instance */
285 /* */
286 /* CALLED BY */
287 /* */
288 /* Device PIMA Class */
289 /* */
290 /* RELEASE HISTORY */
291 /* */
292 /* DATE NAME DESCRIPTION */
293 /* */
294 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
295 /* */
296 /**************************************************************************/
_uxe_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND * command)297 UINT _uxe_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command)
298 {
299
300 UX_SLAVE_CLASS_PIMA_PARAMETER *pima_parameter;
301
302 /* Get the pointer to the application parameters for the pima class. */
303 pima_parameter = command -> ux_slave_class_command_parameter;
304
305 /* Sanity checks. */
306 if (
307 /* Property lists check. */
308 /* pima_parameter -> ux_device_class_pima_parameter_device_properties_list can be UX_NULL */
309 /* pima_parameter -> ux_device_class_pima_parameter_supported_capture_formats_list can be UX_NULL */
310 /* pima_parameter -> ux_device_class_pima_parameter_supported_image_formats_list can be UX_NULL */
311
312 /* Callback functions check. */
313 /* pima_parameter -> ux_device_class_pima_parameter_cancel can be NULL */
314 (pima_parameter -> ux_device_class_pima_parameter_device_reset == UX_NULL) ||
315 (pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get == UX_NULL) ||
316 (pima_parameter -> ux_device_class_pima_parameter_device_prop_value_get == UX_NULL) ||
317 (pima_parameter -> ux_device_class_pima_parameter_device_prop_value_set == UX_NULL) ||
318 (pima_parameter -> ux_device_class_pima_parameter_storage_format == UX_NULL) ||
319 /* pima_parameter -> ux_device_class_pima_parameter_storage_info_get can be UX_NULL */
320 (pima_parameter -> ux_device_class_pima_parameter_object_number_get == UX_NULL) ||
321 (pima_parameter -> ux_device_class_pima_parameter_object_handles_get == UX_NULL) ||
322 (pima_parameter -> ux_device_class_pima_parameter_object_info_get == UX_NULL) ||
323 (pima_parameter -> ux_device_class_pima_parameter_object_data_get == UX_NULL) ||
324 (pima_parameter -> ux_device_class_pima_parameter_object_info_send == UX_NULL) ||
325 (pima_parameter -> ux_device_class_pima_parameter_object_data_send == UX_NULL) ||
326 (pima_parameter -> ux_device_class_pima_parameter_object_delete == UX_NULL)
327 #ifdef UX_PIMA_WITH_MTP_SUPPORT
328 || (pima_parameter -> ux_device_class_pima_parameter_object_properties_list == UX_NULL)
329 || (pima_parameter -> ux_device_class_pima_parameter_object_prop_desc_get == UX_NULL)
330 || (pima_parameter -> ux_device_class_pima_parameter_object_prop_value_get == UX_NULL)
331 || (pima_parameter -> ux_device_class_pima_parameter_object_prop_value_set == UX_NULL)
332 || (pima_parameter -> ux_device_class_pima_parameter_object_references_get == UX_NULL)
333 || (pima_parameter -> ux_device_class_pima_parameter_object_references_set == UX_NULL)
334 #endif
335 )
336 {
337 return(UX_INVALID_PARAMETER);
338 }
339
340 /* Invoke PIMA initialize function. */
341 return(_ux_device_class_pima_initialize(command));
342 }
343