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 /**   PIMA Class                                                          */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_pima.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_pima_device_info_get                 PORTABLE C      */
38 /*                                                           6.1.12       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function gets the device information block.                    */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pima                                       Pointer to pima class    */
50 /*    pima_device                                Device structure to fill */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_host_class_pima_command               Pima command function     */
59 /*    _ux_utility_descriptor_parse              Unpack descriptor         */
60 /*    _ux_utility_memory_allocate               Allocate memory           */
61 /*    _ux_utility_memory_copy                   Copy memory               */
62 /*    _ux_utility_memory_free                   Free allocated memory     */
63 /*    _ux_utility_short_get                     Get 16-bit value          */
64 /*    _ux_utility_long_get                      Get 32-bit value          */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    USB application                                                     */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
75 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            verified memset and memcpy  */
77 /*                                            cases,                      */
78 /*                                            resulting in version 6.1    */
79 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
80 /*                                            fixed DeviceInfo extract,   */
81 /*                                            resulting in version 6.1.12 */
82 /*                                                                        */
83 /**************************************************************************/
_ux_host_class_pima_device_info_get(UX_HOST_CLASS_PIMA * pima,UX_HOST_CLASS_PIMA_DEVICE * pima_device)84 UINT  _ux_host_class_pima_device_info_get(UX_HOST_CLASS_PIMA *pima,
85                                         UX_HOST_CLASS_PIMA_DEVICE *pima_device)
86 {
87 
88 UX_HOST_CLASS_PIMA_COMMAND           command;
89 UCHAR                                *device_buffer;
90 UCHAR                                *device_pointer;
91 ULONG                                unicode_string_length;
92 ULONG                                array_length = 0;
93 UINT                                 status;
94 
95     /* If trace is enabled, insert this event into the trace buffer.  */
96     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_DEVICE_INFO_GET, pima, pima_device, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
97 
98     /* Issue command to get the device info.  no parameter.  */
99     command.ux_host_class_pima_command_nb_parameters =  0;
100 
101     /* Other parameters unused.  */
102     command.ux_host_class_pima_command_parameter_1 =  0;
103     command.ux_host_class_pima_command_parameter_2 =  0;
104     command.ux_host_class_pima_command_parameter_3 =  0;
105     command.ux_host_class_pima_command_parameter_4 =  0;
106     command.ux_host_class_pima_command_parameter_5 =  0;
107 
108     /* Then set the command to GET_DEVICE_INFO.  */
109     command.ux_host_class_pima_command_operation_code =  UX_HOST_CLASS_PIMA_OC_GET_DEVICE_INFO;
110 
111     /* Allocate some DMA safe memory for receiving the device info block.  */
112     device_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH);
113     if (device_buffer == UX_NULL)
114         return(UX_MEMORY_INSUFFICIENT);
115 
116     /* Issue the command.  */
117     status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , device_buffer,
118                                         UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH, UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH);
119 
120     /* Check the result. If the result is OK, the device info block was read properly. */
121     if (status == UX_SUCCESS)
122     {
123 
124         /* Read and store the Standard Version field (2).  */
125         pima_device -> ux_host_class_pima_device_standard_version =  _ux_utility_short_get(device_buffer +
126                                                                                             UX_HOST_CLASS_PIMA_DEVICE_STANDARD_VERSION);
127 
128         /* Read and store the Vendor Extension ID (4).  */
129         pima_device -> ux_host_class_pima_device_vendor_extension_id =  _ux_utility_long_get(device_buffer +
130                                                                                             UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_ID);
131 
132         /* Read and store the Vendor Extension Version (2).  */
133         pima_device -> ux_host_class_pima_device_vendor_extension_version =  _ux_utility_long_get(device_buffer +
134                                                                                             UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_VERSION);
135 
136         /* Copy the vendor extension descriptor (String).   */
137         device_pointer =  device_buffer + UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_DESC;
138 
139         /* Get the unicode string length in chars.  */
140         unicode_string_length =  (ULONG) *device_pointer;
141 
142         /* Check if the string can fit in our buffer.  */
143         if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH / 2)
144 
145             /* Return error.  */
146             status =  UX_MEMORY_INSUFFICIENT;
147 
148         /* Is there enough space?  */
149         if (status == UX_SUCCESS)
150         {
151 
152             /* Copy that unicode string (with null ending) into the object description field.  */
153             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_vendor_extension_desc, device_pointer + 1, unicode_string_length << 1); /* Use case of memcpy is verified. */
154 
155             /* Point to the next field.  */
156             device_pointer += 1 + (unicode_string_length << 1);
157 
158             /* Read and store the Functional Mode (2).  */
159             pima_device -> ux_host_class_pima_device_functional_mode =  _ux_utility_short_get(device_pointer);
160 
161             /* Point to the next field (OperationsSupported OperationCode Array of 16-bit).  */
162             device_pointer += sizeof(USHORT);
163 
164             /* Get the number of elements in array and compute total length.  */
165             array_length = _ux_utility_long_get(device_pointer);
166 
167             if (array_length > (UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH - sizeof(ULONG)) / 2)
168                 status = UX_MEMORY_INSUFFICIENT;
169             else
170             {
171                 array_length <<= 1;
172                 array_length += sizeof(ULONG);
173             }
174         }
175 
176         /* Is there enough space?  */
177         if (status == UX_SUCCESS)
178         {
179 
180             /* Copy the array of supported operations (OperationCode).  */
181             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_operations_supported, device_pointer, array_length); /* Use case of memcpy is verified. */
182 
183             /* Point to the next field (EventsSupported EventCode Array of 16-bit).  */
184             device_pointer += array_length;
185 
186             /* Get the number of elements in array and compute total length.  */
187             array_length = _ux_utility_long_get(device_pointer);
188             if (array_length > (UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH - sizeof(ULONG)) / 2)
189                 status = UX_MEMORY_INSUFFICIENT;
190             else
191             {
192                 array_length <<= 1;
193                 array_length += sizeof(ULONG);
194             }
195         }
196 
197         /* Is there enough space?  */
198         if (status == UX_SUCCESS)
199         {
200 
201             /* Copy the array of events supported (EventCode).  */
202             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_events_supported, device_pointer, array_length); /* Use case of memcpy is verified. */
203 
204             /* Point to the next field (DevicePropertiesSupported DevicePropCode Array of 16-bit).  */
205             device_pointer += array_length;
206 
207             /* Get the number of elements in array and compute total length.  */
208             array_length = _ux_utility_long_get(device_pointer);
209             if (array_length > (UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH - sizeof(ULONG)) / 2)
210                 status = UX_MEMORY_INSUFFICIENT;
211             else
212             {
213                 array_length <<= 1;
214                 array_length += sizeof(ULONG);
215             }
216         }
217 
218         /* Is there enough space?  */
219         if (status == UX_SUCCESS)
220         {
221 
222             /* Copy the array of device properties (DevicePropCode).  */
223             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_properties_supported, device_pointer, array_length); /* Use case of memcpy is verified. */
224 
225             /* Point to the next field (CaptureFormats ObjectFormatCode Array of 16-bit).  */
226             device_pointer += array_length;
227 
228             /* Get the number of elements in array and compute total length.  */
229             array_length = _ux_utility_long_get(device_pointer);
230             if (array_length > (UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH - sizeof(ULONG)) / 2)
231                 status = UX_MEMORY_INSUFFICIENT;
232             else
233             {
234                 array_length <<= 1;
235                 array_length += sizeof(ULONG);
236             }
237         }
238 
239         /* Is there enough space?  */
240         if (status == UX_SUCCESS)
241         {
242 
243             /* Copy the array of capture formats (CaptureFormats ObjectFormatCode).  */
244             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_capture_formats, device_pointer, array_length); /* Use case of memcpy is verified. */
245 
246             /* Point to the next field (ImageFormats ObjectFormatCode Array of 16-bit).  */
247             device_pointer += array_length;
248 
249             /* Get the number of elements in array and compute total length.  */
250             array_length = _ux_utility_long_get(device_pointer);
251             if (array_length > (UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH - sizeof(ULONG)) / 2)
252                 status = UX_MEMORY_INSUFFICIENT;
253             else
254             {
255                 array_length <<= 1;
256                 array_length += sizeof(ULONG);
257             }
258         }
259 
260         /* Is there enough space?  */
261         if (status == UX_SUCCESS)
262         {
263 
264             /* Copy the array of supported operations (ImageFormats ObjectFormatCode).  */
265             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_image_formats, device_pointer, array_length); /* Use case of memcpy is verified. */
266 
267             /* Point to the next field (Manufacturer String).  */
268             device_pointer += array_length;
269 
270             /* Get the unicode string length.  */
271             unicode_string_length =  (ULONG) *device_pointer;
272 
273             /* Ensure the string can fit in our buffer.  */
274             if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH / 2)
275 
276                 /* Return overflow error.  */
277                 status =  UX_MEMORY_INSUFFICIENT;
278         }
279 
280         /* Is there enough space?  */
281         if (status == UX_SUCCESS)
282         {
283 
284             /* Copy that string into the manufacturer field (Manufacturer String).  */
285             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_manufacturer, device_pointer + 1, unicode_string_length << 1); /* Use case of memcpy is verified. */
286 
287             /* Point to the next field (Model String).  */
288             device_pointer += (unicode_string_length << 1) + 1;
289 
290             /* Get the unicode string length.  */
291             unicode_string_length =  (ULONG) *device_pointer ;
292 
293             /* Ensure the string can fit in our buffer.  */
294             if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH / 2)
295 
296                 /* Return overflow error.  */
297                 status =  UX_MEMORY_INSUFFICIENT;
298         }
299 
300         /* Is there enough space?  */
301         if (status == UX_SUCCESS)
302         {
303 
304             /* Copy that string into the model date field (Model String).  */
305             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_model, device_pointer + 1, unicode_string_length << 1); /* Use case of memcpy is verified. */
306 
307             /* Point to the next field (DeviceVersion String).  */
308             device_pointer += (unicode_string_length << 1) + 1;
309 
310             /* Get the unicode string length.  */
311             unicode_string_length =  (ULONG) *device_pointer ;
312 
313             /* Ensure the string can fit in our buffer.  */
314             if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH / 2)
315 
316                 /* Return overflow error.  */
317                 status =  UX_MEMORY_INSUFFICIENT;
318         }
319 
320         /* Is there enough space?  */
321         if (status == UX_SUCCESS)
322         {
323 
324             /* Copy that string into the version field (DeviceVersion String).  */
325             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_version, device_pointer + 1, unicode_string_length << 1); /* Use case of memcpy is verified. */
326 
327             /* Point to the next field (SerialNumber String).  */
328             device_pointer += (unicode_string_length << 1) + 1;
329 
330             /* Get the unicode string length.  */
331             unicode_string_length =  (ULONG) *device_pointer ;
332 
333             /* Ensure the string can fit in our buffer.  */
334             if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH / 2)
335 
336                 /* Return overflow error.  */
337                 status =  UX_MEMORY_INSUFFICIENT;
338         }
339 
340         /* Is there enough space?  */
341         if (status == UX_SUCCESS)
342 
343             /* Copy that string into the serial number field (SerialNumber String).  */
344             _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_serial_number, device_pointer + 1, unicode_string_length << 1); /* Use case of memcpy is verified. */
345 
346         else
347         {
348 
349             /* If trace is enabled, insert this event into the trace buffer.  */
350             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
351 
352             /* Report error to application.  */
353             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
354         }
355     }
356 
357     /* Free the original object info buffer.  */
358     _ux_utility_memory_free(device_buffer);
359 
360     /* Return completion status.  */
361     return(status);
362 }
363