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