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