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