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 /**   PIMA 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_pima.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_pima_object_info_send                PORTABLE C      */
37 /*                                                           6.3.0        */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function sends an object information block prior to sending    */
45 /*    a new object.                                                       */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pima                                       Pointer to pima class    */
50 /*    pima_session                               Pointer to pima session  */
51 /*    storage_id                                 StorageID where to store */
52 /*    parent_object_id                           Parent object id         */
53 /*    object                                     Object info structure    */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    Completion Status                                                   */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _ux_host_class_pima_command               Pima command function     */
62 /*    _ux_utility_memory_allocate               Allocate memory           */
63 /*    _ux_utility_memory_copy                   Copy memory               */
64 /*    _ux_utility_memory_free                   Free allocated memory     */
65 /*    _ux_utility_descriptor_pack               Pack descriptor           */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    USB application                                                     */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            verified memset and memcpy  */
78 /*                                            cases,                      */
79 /*                                            resulting in version 6.1    */
80 /*  10-31-2023     Yajun Xia                Modified comment(s),          */
81 /*                                            fixed allocated buffer      */
82 /*                                            pointer checking issue,     */
83 /*                                            resulting in version 6.3.0  */
84 /*                                                                        */
85 /**************************************************************************/
_ux_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA * pima,UX_HOST_CLASS_PIMA_SESSION * pima_session,ULONG storage_id,ULONG parent_object_id,UX_HOST_CLASS_PIMA_OBJECT * object)86 UINT  _ux_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA *pima,
87                                         UX_HOST_CLASS_PIMA_SESSION *pima_session,
88                                         ULONG storage_id,
89                                         ULONG parent_object_id,
90                                         UX_HOST_CLASS_PIMA_OBJECT *object)
91 {
92 
93 UX_HOST_CLASS_PIMA_COMMAND           command;
94 UCHAR                                *object_buffer;
95 UCHAR                                *object_buffer_end;
96 UCHAR                                *object_pointer;
97 ULONG                                unicode_string_length;
98 ULONG                                object_info_length;
99 UINT                                 status;
100 
101     /* If trace is enabled, insert this event into the trace buffer.  */
102     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_INFO_SEND, pima, object, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
103 
104     /* Check if this session is valid or not.  */
105     if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER)
106         return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);
107 
108     /* Check if this session is opened or not.  */
109     if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED)
110         return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);
111 
112     /* Issue command to set the object info.  2 parameter.  */
113     command.ux_host_class_pima_command_nb_parameters =  2;
114 
115     /* Parameter 1 is the Storage ID.  */
116     command.ux_host_class_pima_command_parameter_1 =  storage_id;
117 
118     /* Parameter 2 is the Parent Object ID.  */
119     command.ux_host_class_pima_command_parameter_2 =  parent_object_id;
120 
121     /* Other parameters unused.  */
122     command.ux_host_class_pima_command_parameter_3 =  0;
123     command.ux_host_class_pima_command_parameter_4 =  0;
124     command.ux_host_class_pima_command_parameter_5 =  0;
125 
126     /* Then set the command to SEND_OBJECT_INFO.  */
127     command.ux_host_class_pima_command_operation_code =  UX_HOST_CLASS_PIMA_OC_SEND_OBJECT_INFO;
128 
129     /* Allocate some DMA safe memory for sending the object info block.  */
130     object_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH);
131     if (object_buffer == UX_NULL)
132         return(UX_MEMORY_INSUFFICIENT);
133 
134     /* Get the end of the object buffer.  */
135     object_buffer_end =  object_buffer + UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH;
136 
137     /* The object info structure coming from the application needs to be packed. */
138     _ux_utility_descriptor_pack((UCHAR *) object,
139                             _ux_system_class_pima_object_structure,
140                             UX_HOST_CLASS_PIMA_OBJECT_ENTRIES,
141                             object_buffer);
142 
143     /* Copy the object filename  field.  Point to the beginning of the object description string.  */
144     object_pointer =  object_buffer + UX_HOST_CLASS_PIMA_OBJECT_VARIABLE_OFFSET;
145 
146     /* Get the unicode string length for the filename.  */
147     unicode_string_length =  ((ULONG) *object -> ux_host_class_pima_object_filename * 2) + 1;
148 
149     /* Is there enough room for this string?  */
150     if (object_pointer + unicode_string_length > object_buffer_end)
151 
152         /* Return error.  */
153         status =  UX_MEMORY_INSUFFICIENT;
154 
155     else
156 
157         /* Continue.  */
158         status =  UX_SUCCESS;
159 
160     /* Is there enough space?  */
161     if (status == UX_SUCCESS)
162     {
163 
164         /* Copy that string into the object description field.  */
165         _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_filename, unicode_string_length); /* Use case of memcpy is verified. */
166 
167         /* Point to the next field.  */
168         object_pointer += unicode_string_length;
169 
170         /* Get the unicode string length of the capture date.  */
171         unicode_string_length =  ((ULONG) *object -> ux_host_class_pima_object_capture_date * 2) + 1;
172 
173         /* Is there enough room for this string?  */
174         if (object_pointer + unicode_string_length > object_buffer_end)
175 
176             /* Return error.  */
177             status =  UX_MEMORY_INSUFFICIENT;
178     }
179 
180     /* Is there enough space?  */
181     if (status == UX_SUCCESS)
182     {
183 
184         /* Copy that string into the capture date field.  */
185         _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_capture_date, unicode_string_length); /* Use case of memcpy is verified. */
186 
187         /* Point to the next field.  */
188         object_pointer += unicode_string_length;
189 
190         /* Get the unicode string length.  */
191         unicode_string_length =  ((ULONG) *object -> ux_host_class_pima_object_modification_date * 2) + 1;
192 
193         /* Is there enough room for this string?  */
194         if (object_pointer + unicode_string_length > object_buffer_end)
195 
196             /* Return error.  */
197             status =  UX_MEMORY_INSUFFICIENT;
198     }
199 
200     /* Is there enough space?  */
201     if (status == UX_SUCCESS)
202     {
203 
204         /* Copy that string into the modification date field.  */
205         _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_modification_date, unicode_string_length); /* Use case of memcpy is verified. */
206 
207         /* Point to the next field.  */
208         object_pointer += unicode_string_length;
209 
210         /* Get the unicode string length.  */
211         unicode_string_length =  ((ULONG) *object -> ux_host_class_pima_object_keywords * 2) + 1;
212 
213         /* Is there enough room for this string?  */
214         if (object_pointer + unicode_string_length > object_buffer_end)
215 
216             /* Return error.  */
217             status =  UX_MEMORY_INSUFFICIENT;
218     }
219 
220     /* Is there enough space?  */
221     if (status == UX_SUCCESS)
222     {
223 
224         /* Copy that string into the keywords field.  */
225         _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_keywords, unicode_string_length); /* Use case of memcpy is verified. */
226 
227         /* Point to the next field.  */
228         object_pointer += unicode_string_length;
229 
230         /* Calculate the length of the payload. */
231         object_info_length = (ULONG ) (object_pointer - object_buffer);
232 
233         /* Issue the command.  */
234         status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_OUT , object_buffer,
235                                             object_info_length, object_info_length);
236 
237         /* If the status is OK, the device sent us the Object handle in the response.  */
238         if (status == UX_SUCCESS)
239 
240             /* Update the object handle.  */
241             object -> ux_host_class_pima_object_handle_id = command.ux_host_class_pima_command_parameter_2;
242     }
243     else
244     {
245 
246         /* If trace is enabled, insert this event into the trace buffer.  */
247         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
248 
249         /* Report error to application.  */
250         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
251     }
252 
253     /* Free the original object info buffer.  */
254     _ux_utility_memory_free(object_buffer);
255 
256     /* Return completion status.  */
257     return(status);
258 }
259 
260 /**************************************************************************/
261 /*                                                                        */
262 /*  FUNCTION                                               RELEASE        */
263 /*                                                                        */
264 /*    _uxe_host_class_pima_object_info_send               PORTABLE C      */
265 /*                                                           6.3.0        */
266 /*  AUTHOR                                                                */
267 /*                                                                        */
268 /*    Yajun Xia, Microsoft Corporation                                    */
269 /*                                                                        */
270 /*  DESCRIPTION                                                           */
271 /*                                                                        */
272 /*    This function checks errors in pima object info send function call. */
273 /*                                                                        */
274 /*  INPUT                                                                 */
275 /*                                                                        */
276 /*    pima                                       Pointer to pima class    */
277 /*    pima_session                               Pointer to pima session  */
278 /*    storage_id                                 StorageID where to store */
279 /*    parent_object_id                           Parent object id         */
280 /*    object                                     Object info structure    */
281 /*                                                                        */
282 /*  OUTPUT                                                                */
283 /*                                                                        */
284 /*    Completion Status                                                   */
285 /*                                                                        */
286 /*  CALLS                                                                 */
287 /*                                                                        */
288 /*    _ux_host_class_pima_object_info_send  Send pima device info         */
289 /*                                                                        */
290 /*  CALLED BY                                                             */
291 /*                                                                        */
292 /*    USB application                                                     */
293 /*                                                                        */
294 /*  RELEASE HISTORY                                                       */
295 /*                                                                        */
296 /*    DATE              NAME                      DESCRIPTION             */
297 /*                                                                        */
298 /*  10-31-2023        Yajun xia             Initial Version 6.3.0         */
299 /*                                                                        */
300 /**************************************************************************/
_uxe_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA * pima,UX_HOST_CLASS_PIMA_SESSION * pima_session,ULONG storage_id,ULONG parent_object_id,UX_HOST_CLASS_PIMA_OBJECT * object)301 UINT  _uxe_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA *pima,
302                                             UX_HOST_CLASS_PIMA_SESSION *pima_session,
303                                             ULONG storage_id,
304                                             ULONG parent_object_id,
305                                             UX_HOST_CLASS_PIMA_OBJECT *object)
306 {
307 
308     /* Sanity Checks.  */
309     if ((pima == UX_NULL) || (pima_session == UX_NULL) || (object == UX_NULL))
310         return(UX_INVALID_PARAMETER);
311 
312     return(_ux_host_class_pima_object_info_send(pima, pima_session, storage_id, parent_object_id, object));
313 }
314