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 /**   Device Pima Class                                                   */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define UX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "ux_api.h"
28 #include "ux_device_class_pima.h"
29 #include "ux_device_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_device_class_pima_object_info_send              PORTABLE C      */
37 /*                                                           6.1.10       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function receives an object info structure from the host       */
45 /*    before receiving the actual data.                                   */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pima                                  Pointer to pima class         */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    Completion Status                                                   */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _ux_device_stack_transfer_request     Transfer request              */
58 /*    _ux_device_stack_endpoint_stall       Stall endpoint                */
59 /*    _ux_utility_long_put                  Put 32-bit value              */
60 /*    _ux_utility_short_put                 Put 32-bit value              */
61 /*    _ux_utility_memory_allocate           Allocate memory               */
62 /*    _ux_utility_memory_copy               Copy memory                   */
63 /*    _ux_utility_memory_free               Free memory                   */
64 /*    _ux_utility_descriptor_parse          Parse descriptor              */
65 /*    _ux_device_class_pima_response_send   Send PIMA response            */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Device Storage Class                                                */
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 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
81 /*                                            updated status handling,    */
82 /*                                            resulting in version 6.1.10 */
83 /*                                                                        */
84 /**************************************************************************/
_ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA * pima,ULONG storage_id,ULONG parent_object_handle)85 UINT  _ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id, ULONG parent_object_handle)
86 {
87 
88 UINT                        status;
89 UX_SLAVE_TRANSFER           *transfer_request;
90 UX_SLAVE_CLASS_PIMA_OBJECT  *object;
91 UCHAR                       *object_info;
92 UCHAR                       *object_info_pointer;
93 ULONG                       unicode_string_length;
94 ULONG                       object_handle;
95 
96     /* If trace is enabled, insert this event into the trace buffer.  */
97     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_SEND, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
98 
99     /* Obtain the pointer to the transfer request.  */
100     transfer_request =  &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request;
101 
102     /* Obtain memory for this object info. Use the transfer request pre-allocated memory.  */
103     object_info =  transfer_request -> ux_slave_transfer_request_data_pointer;
104 
105     /* Get the data payload.  */
106     status =  _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH,
107                                                     UX_DEVICE_CLASS_PIMA_TRANSFER_BUFFER_LENGTH);
108 
109     /* Check if there was an error. If so, stall the endpoint.  */
110     if (status != UX_SUCCESS)
111     {
112 
113         /* Stall the endpoint.  */
114         _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint);
115 
116         /* Return the status.  */
117         return(status);
118 
119     }
120 
121     /* Allocate some memory for the object.  */
122     object =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_OBJECT));
123 
124     /* Check for successful allocation.  */
125     if (object == UX_NULL)
126         return(UX_MEMORY_INSUFFICIENT);
127 
128     /* Allocate the device info pointer to the beginning of the dynamic object info field.  */
129     object_info_pointer = object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE;
130 
131     /* Uncompress the object descriptor, at least the fixed part.  */
132     _ux_utility_descriptor_parse(object_info_pointer,
133                         _ux_system_class_pima_object_structure,
134                         UX_DEVICE_CLASS_PIMA_OBJECT_ENTRIES,
135                         (UCHAR *) object);
136 
137     /* Copy the object filename  field.  Point to the beginning of the object description string.  */
138     object_info_pointer =  object_info_pointer + UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET;
139 
140     /* Get the unicode string length.  */
141     unicode_string_length =  ((ULONG) *object_info_pointer * 2) + 1;
142 
143     /* Ensure there's enough space for this string.  */
144     if (unicode_string_length > UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH)
145 
146         /* Return overflow error.  */
147         status =  UX_MEMORY_INSUFFICIENT;
148 
149     /* Is there enough space?  */
150     if (status == UX_SUCCESS)
151     {
152 
153         /* Copy that string into the object description field.  */
154         _ux_utility_memory_copy(object -> ux_device_class_pima_object_filename, object_info_pointer, unicode_string_length); /* Use case of memcpy is verified. */
155 
156         /* Point to the next field.  */
157         object_info_pointer += unicode_string_length;
158 
159         /* Get the unicode string length.  */
160         unicode_string_length =  ((ULONG) *object_info_pointer  * 2) + 1;
161 
162         /* Ensure there's enough space for this string.  */
163         if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH)
164 
165             /* Return overflow error.  */
166             status =  UX_MEMORY_INSUFFICIENT;
167     }
168 
169     /* Is there enough space?  */
170     if (status == UX_SUCCESS)
171     {
172 
173         /* Copy that string into the capture date field.  */
174         _ux_utility_memory_copy(object -> ux_device_class_pima_object_capture_date, object_info_pointer, unicode_string_length); /* Use case of memcpy is verified. */
175 
176         /* Point to the next field.  */
177         object_info_pointer += unicode_string_length;
178 
179         /* Get the unicode string length.  */
180         unicode_string_length =  ((ULONG) *object_info_pointer  * 2) + 1;
181 
182         /* Ensure there's enough space for this string.  */
183         if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH)
184 
185             /* Return overflow error.  */
186             status =  UX_MEMORY_INSUFFICIENT;
187     }
188 
189     /* Is there enough space?  */
190     if (status == UX_SUCCESS)
191     {
192 
193         /* Copy that string into the modification date field.  */
194         _ux_utility_memory_copy(object -> ux_device_class_pima_object_modification_date, object_info_pointer, unicode_string_length); /* Use case of memcpy is verified. */
195 
196         /* Point to the next field.  */
197         object_info_pointer += unicode_string_length;
198 
199         /* Get the unicode string length.  */
200         unicode_string_length =  ((ULONG) *object_info_pointer  * 2) + 1;
201 
202         /* Ensure there's enough space for this string.  */
203         if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH)
204 
205             /* Return overflow error.  */
206             status =  UX_MEMORY_INSUFFICIENT;
207     }
208 
209     /* Is there enough space?  */
210     if (status == UX_SUCCESS)
211     {
212 
213         /* Copy that string into the keywords field.  */
214         _ux_utility_memory_copy(object -> ux_device_class_pima_object_keywords, object_info_pointer, unicode_string_length); /* Use case of memcpy is verified. */
215 
216         /* Reset the rest of the other parameters.  */
217         object -> ux_device_class_pima_object_state            =  0;
218         object -> ux_device_class_pima_object_offset           =  0;
219         object -> ux_device_class_pima_object_transfer_status  =  0;
220         object -> ux_device_class_pima_object_handle_id        =  0;
221         object -> ux_device_class_pima_object_length           =  0;
222 
223         /* Send the object to the application.  */
224         status = pima -> ux_device_class_pima_object_info_send(pima, object, storage_id, parent_object_handle, &object_handle);
225 
226         /* Now we return a response with success.  */
227         status = (status == UX_SUCCESS) ? UX_DEVICE_CLASS_PIMA_RC_OK : status;
228         _ux_device_class_pima_response_send(pima, status, 3, pima -> ux_device_class_pima_storage_id,
229                                             object -> ux_device_class_pima_object_parent_object, object_handle);
230 
231         /* Store the object handle. It will be used for the OBJECT_SEND command.  */
232         pima -> ux_device_class_pima_current_object_handle =  object_handle;
233     }
234     else
235     {
236 
237         /* If trace is enabled, insert this event into the trace buffer.  */
238         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
239 
240         /* We return an error.  */
241         _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0);
242     }
243 
244     /* Free the resources. */
245     _ux_utility_memory_free(object);
246 
247     /* Return completion status.  */
248     return(status);
249 }
250 
251 
252