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 /** Pictbridge Application */
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_pictbridge.h"
30 #include "ux_host_class_pima.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_pictbridge_dpshost_object_get PORTABLE C */
38 /* 6.1.12 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function obtains an object and execute its script. */
46 /* */
47 /* INPUT */
48 /* */
49 /* pictbridge Pictbridge instance */
50 /* object_handle Object handle */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* _ux_pictbridge_dpshost_thread */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
68 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
69 /* resulting in version 6.1 */
70 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
71 /* fixed string length check, */
72 /* resulting in version 6.1.12 */
73 /* */
74 /**************************************************************************/
_ux_pictbridge_dpshost_object_get(UX_PICTBRIDGE * pictbridge,ULONG object_handle)75 UINT _ux_pictbridge_dpshost_object_get(UX_PICTBRIDGE *pictbridge, ULONG object_handle)
76 {
77 UINT status;
78 UX_HOST_CLASS_PIMA *pima;
79 UX_HOST_CLASS_PIMA_SESSION *pima_session;
80 UX_HOST_CLASS_PIMA_OBJECT *pima_object;
81 ULONG object_length;
82 ULONG requested_length;
83 ULONG actual_length;
84 UCHAR *object_buffer;
85 UCHAR object_file_name[UX_PICTBRIDGE_MAX_FILE_NAME_SIZE + 1]; /* +1 for null-terminator */
86 UINT length, length1;
87
88 /* Get the pima instance from the pictbridge container. */
89 pima = (UX_HOST_CLASS_PIMA *) pictbridge -> ux_pictbridge_pima;
90
91 /* And now the session since we use it. */
92 pima_session = (UX_HOST_CLASS_PIMA_SESSION *) pictbridge -> ux_pictbridge_session;
93
94 /* Get the address of the object container. */
95 pima_object = (UX_HOST_CLASS_PIMA_OBJECT *) pictbridge -> ux_pictbridge_object_host;
96
97 /* Get the object info structure. */
98 status = _ux_host_class_pima_object_info_get(pima, pima_session,
99 object_handle, pima_object);
100 if (status != UX_SUCCESS)
101 {
102
103 /* Return an error. */
104 return(UX_PICTBRIDGE_ERROR_INVALID_OBJECT_HANDLE);
105 }
106
107 /* Check if this is a script. If the object is not a script or does not contain the
108 File Name we expect, we ignore it. */
109 if (pima_object -> ux_host_class_pima_object_format == UX_HOST_CLASS_PIMA_OFC_SCRIPT)
110 {
111
112 /* Yes this is a script. We need to search for the DREQUEST.DPS file name.
113 Get the file name length (with null-terminator). */
114 length1 = (UINT)(*pima_object -> ux_host_class_pima_object_filename);
115
116 /* Check the file name from this script. It should be in the form DREQUEST.DPS. */
117 if (length1 <= UX_PICTBRIDGE_MAX_FILE_NAME_SIZE)
118 {
119
120 /* Invalidate length, on error it's untouched. */
121 length = UX_PICTBRIDGE_MAX_FILE_NAME_SIZE + 1;
122 _ux_utility_string_length_check(_ux_pictbridge_drequest_name, &length, UX_PICTBRIDGE_MAX_FILE_NAME_SIZE);
123 if ((length + 1) == length1)
124 {
125
126 /* Get the file name in a ascii format (with null-terminator). */
127 _ux_utility_unicode_to_string(pima_object -> ux_host_class_pima_object_filename, object_file_name);
128
129 /* So far, the length of name of the files are the same.
130 Compare names now (since length is same just compare without null-terminator). */
131 if (_ux_utility_memory_compare(_ux_pictbridge_drequest_name, object_file_name,
132 length) == UX_SUCCESS)
133 {
134
135 /* Yes this is a script. Get the entire object in memory. */
136 /* Get script length from the object info. */
137 object_length = pima_object -> ux_host_class_pima_object_compressed_size;
138
139 /* Check for overflow. */
140 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
141 return(UX_PICTBRIDGE_ERROR_SCRIPT_BUFFER_OVERFLOW);
142
143 /* Open the object. */
144 status = _ux_host_class_pima_object_open(pima, pima_session, object_handle, pima_object);
145
146 /* Check status. */
147 if (status != UX_SUCCESS)
148 return(status);
149
150 /* Set the object buffer pointer. */
151 object_buffer = pima_object -> ux_host_class_pima_object_buffer;
152
153 /* Obtain all the object data. */
154 while(object_length != 0)
155 {
156
157 /* Calculate what length to request. */
158 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
159
160 /* Request maximum length. */
161 requested_length = UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER;
162
163 else
164
165 /* Request remaining length. */
166 requested_length = object_length;
167
168 /* Get the object data. */
169 status = _ux_host_class_pima_object_get(pima, pima_session, object_handle, pima_object,
170 object_buffer, requested_length, &actual_length);
171 if (status != UX_SUCCESS)
172 {
173
174 /* We had a problem, abort the transfer. */
175 _ux_host_class_pima_object_transfer_abort(pima, pima_session, object_handle, pima_object);
176
177 /* And close the object. */
178 _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
179
180 return(status);
181 }
182
183 /* We have received some data, update the length remaining. */
184 object_length -= actual_length;
185
186 /* Update the buffer address. */
187 object_buffer += actual_length;
188 }
189
190 /* Close the object. */
191 status = _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
192
193 /* Check the error. */
194 if (status != UX_SUCCESS)
195 return(UX_PICTBRIDGE_ERROR_INVALID_OBJECT_HANDLE);
196
197 /* We now have the entire script into memory. Parse the object and execute the script. */
198 status = _ux_pictbridge_object_parse(pictbridge, pima_object -> ux_host_class_pima_object_buffer,
199 pima_object -> ux_host_class_pima_object_compressed_size);
200
201 /* Analyze the status from the parsing and determine the result code to be sent back. */
202 switch (status)
203 {
204 case UX_SUCCESS :
205
206 /* Set the result code to OK. */
207 pictbridge -> ux_pictbridge_operation_result = UX_PICTBRIDGE_ACTION_RESULT_OK;
208 break;
209
210 case UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR :
211
212 /* Set the result code to Error. */
213 pictbridge -> ux_pictbridge_operation_result = UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_IP;
214 break;
215
216 case UX_PICTBRIDGE_ERROR_PARAMETER_UNKNOWN :
217
218 /* Set the result code to Error. */
219 pictbridge -> ux_pictbridge_operation_result = UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_UP;
220 break;
221
222 case UX_PICTBRIDGE_ERROR_PARAMETER_MISSING :
223
224 /* Set the result code to Error. */
225 pictbridge -> ux_pictbridge_operation_result = UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_MP;
226 break;
227
228 default :
229
230 /* Set the result code to Error. */
231 pictbridge -> ux_pictbridge_operation_result = UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_DEFAULT;
232 break;
233 }
234
235 /* We have completed the parsing of the XML object. We will send an object back to the client.
236 Generate the output report. */
237 status = _ux_pictbridge_dpshost_output_object_create(pictbridge);
238
239 /* Get the length of the object and store it into the object data set. */
240 pima_object -> ux_host_class_pima_object_compressed_size = pima_object -> ux_host_class_pima_object_length;
241
242 /* We need to change the file name to DRSPONSE.DPS. Encode the file name from ascii format into Unicode. */
243 _ux_utility_string_to_unicode(_ux_pictbridge_hrsponse_name, pima_object -> ux_host_class_pima_object_filename);
244
245 /* Send a script info. */
246 status = _ux_host_class_pima_object_info_send(pima, pima_session, 0, 0, pima_object);
247 if (status != UX_SUCCESS)
248 return(status);
249
250 /* Open the object. */
251 status = _ux_host_class_pima_object_open(pima, pima_session,
252 object_handle,
253 pima_object);
254 if (status != UX_SUCCESS)
255 return(status);
256
257 /* Get the object length. */
258 object_length = pima_object -> ux_host_class_pima_object_compressed_size;
259
260 /* Recall the object buffer address. */
261 object_buffer = pima_object -> ux_host_class_pima_object_buffer;
262
263 /* Send all the object data. */
264 while(object_length != 0)
265 {
266
267 /* Calculate what length to request. */
268 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
269
270 /* Request maximum length. */
271 requested_length = UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER;
272
273 else
274
275 /* Request remaining length. */
276 requested_length = object_length;
277
278
279 /* Send the object data. */
280 status = _ux_host_class_pima_object_send(pima, pima_session, pima_object,
281 object_buffer, requested_length);
282 if (status != UX_SUCCESS)
283 {
284
285 /* Abort the transfer. */
286 _ux_host_class_pima_object_transfer_abort(pima, pima_session, object_handle, pima_object);
287
288 return(status);
289 }
290
291 /* We have sent some data, update the length remaining. */
292 object_length -= requested_length;
293 }
294
295 /* Close the object. */
296 status = _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
297
298 /* Check the status. */
299 if (status != UX_SUCCESS)
300 return(status);
301 }
302 }
303 }
304 }
305
306 return(UX_SUCCESS);
307 }
308
309