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