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