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_response_get                 PORTABLE C      */
38 /*                                                           6.1.12       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function obtains a response.                                   */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pictbridge                             Pictbridge instance          */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    Completion Status                                                   */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*                                                                        */
58 /*  CALLED BY                                                             */
59 /*                                                                        */
60 /*    _ux_pictbridge_dpshost_thread                                       */
61 /*                                                                        */
62 /*  RELEASE HISTORY                                                       */
63 /*                                                                        */
64 /*    DATE              NAME                      DESCRIPTION             */
65 /*                                                                        */
66 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
67 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
68 /*                                            resulting in version 6.1    */
69 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            fixed string length check,  */
71 /*                                            used macros for RTOS calls, */
72 /*                                            resulting in version 6.1.12 */
73 /*                                                                        */
74 /**************************************************************************/
_ux_pictbridge_dpshost_response_get(UX_PICTBRIDGE * pictbridge)75 UINT  _ux_pictbridge_dpshost_response_get(UX_PICTBRIDGE *pictbridge)
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 ULONG                               object_handle;
87 UX_PICTBRIDGE_EVENT                 *pictbridge_event;
88 UINT                                length, length1;
89 
90     /* Get the pima instance from the pictbridge container.  */
91     pima = (UX_HOST_CLASS_PIMA *) pictbridge -> ux_pictbridge_pima;
92 
93     /* And now the session since we use it.  */
94     pima_session =  (UX_HOST_CLASS_PIMA_SESSION *) pictbridge -> ux_pictbridge_session;
95 
96     /* Get the address of the object container.  */
97     pima_object =  (UX_HOST_CLASS_PIMA_OBJECT *) pictbridge -> ux_pictbridge_object_host;
98 
99     /* Wait for the semaphore to be put by the root hub or a regular hub.  */
100     _ux_system_semaphore_get_norc(&pictbridge -> ux_pictbridge_notification_semaphore, UX_WAIT_FOREVER);
101 
102     /* Check if there is an event. Normally there should be at least one since we got awaken. */
103     if (pictbridge -> ux_pictbridge_event_array_tail != pictbridge -> ux_pictbridge_event_array_head)
104     {
105 
106         /* Get the current event tail.  */
107         pictbridge_event = pictbridge -> ux_pictbridge_event_array_tail;
108 
109         /* Analyze the event type.  */
110         switch (pictbridge_event -> ux_pictbridge_event_code)
111         {
112 
113 
114             /* The DSC client is informing us that an object is ready.  */
115             case UX_PICTBRIDGE_EC_OBJECT_ADDED                  :
116             case UX_PICTBRIDGE_EC_REQUEST_OBJECT_TRANSFER       :
117 
118                 /* Obtain the object handle.  */
119                 object_handle =  pictbridge_event -> ux_pictbridge_event_parameter_1;
120                 break;
121 
122             default                                             :
123                 return(UX_ERROR);
124         }
125 
126         /* Compute the next entry in the event array.  */
127         if ((pictbridge -> ux_pictbridge_event_array_tail + 1) == pictbridge -> ux_pictbridge_event_array_end)
128 
129             /* Start at the beginning of the list.  */
130             pictbridge_event = pictbridge -> ux_pictbridge_event_array;
131         else
132 
133             /* Point to the next entry in the event array.  */
134             pictbridge_event = pictbridge -> ux_pictbridge_event_array_tail + 1;
135 
136         /* Now, store the new event tail.  */
137         pictbridge -> ux_pictbridge_event_array_tail =  pictbridge_event;
138 
139     }
140 
141     else
142 
143         /* We have an error. Got awaken for nothing ! */
144         return(UX_ERROR);
145 
146     /* Get the object info structure.  */
147     status = _ux_host_class_pima_object_info_get(pima, pima_session,
148                                              object_handle, pima_object);
149     if (status != UX_SUCCESS)
150     {
151 
152         /* Return an error.  */
153         return(UX_PICTBRIDGE_ERROR_INVALID_OBJECT_HANDLE);
154     }
155 
156     /* Check if this is a script.  If the object is not a script or does not contain the
157        File Name we expect, we ignore it.  */
158     if (pima_object -> ux_host_class_pima_object_format == UX_HOST_CLASS_PIMA_OFC_SCRIPT)
159     {
160 
161         /* Yes this is a script. We need to search for the DRSPONSE.DPS file name.
162            Get the file name length (with null-terminator).  */
163         length1 = (UINT)(*pima_object -> ux_host_class_pima_object_filename);
164 
165         /* Check the file name from this script. It should be in the form DRSPONSE.DPS.  */
166         if (length1 <= UX_PICTBRIDGE_MAX_FILE_NAME_SIZE)
167         {
168 
169             /* Invalidate length, on error it's untouched.  */
170             length = UX_PICTBRIDGE_MAX_FILE_NAME_SIZE + 1;
171             _ux_utility_string_length_check(_ux_pictbridge_drsponse_name, &length, UX_PICTBRIDGE_MAX_FILE_NAME_SIZE);
172             if ((length + 1) == length1)
173             {
174 
175                 /* Get the file name in a ascii format (with null-terminator).   */
176                 _ux_utility_unicode_to_string(pima_object -> ux_host_class_pima_object_filename, object_file_name);
177 
178                 /* So far, the length of name of the files are the same.
179                 Compare names now (since length is same just compare without null-terminator). */
180                 if (_ux_utility_memory_compare(_ux_pictbridge_drsponse_name, object_file_name,
181                                                 length) ==  UX_SUCCESS)
182                 {
183 
184                     /* Yes this is a script. Get the entire object in memory.  */
185                     /* Get script length from the object info.  */
186                     object_length = pima_object -> ux_host_class_pima_object_compressed_size;
187 
188                     /* Check for overflow.  */
189                     if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
190                         return(UX_PICTBRIDGE_ERROR_SCRIPT_BUFFER_OVERFLOW);
191 
192                     /* Open the object.  */
193                     status = _ux_host_class_pima_object_open(pima, pima_session, object_handle, pima_object);
194 
195                     /* Check status.  */
196                     if (status != UX_SUCCESS)
197                         return(status);
198 
199                     /* Set the object buffer pointer.  */
200                     object_buffer = pima_object -> ux_host_class_pima_object_buffer;
201 
202                     /* Obtain all the object data.  */
203                     while(object_length != 0)
204                     {
205 
206                         /* Calculate what length to request.  */
207                         if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
208 
209                             /* Request maximum length.  */
210                             requested_length = UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER;
211 
212                         else
213 
214                             /* Request remaining length.  */
215                             requested_length = object_length;
216 
217                         /* Get the object data.  */
218                         status = _ux_host_class_pima_object_get(pima, pima_session, object_handle, pima_object,
219                                                                 object_buffer, requested_length, &actual_length);
220                         if (status != UX_SUCCESS)
221                         {
222 
223                             /* We had a problem, abort the transfer.  */
224                             _ux_host_class_pima_object_transfer_abort(pima, pima_session, object_handle, pima_object);
225 
226                             /* And close the object.  */
227                             _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
228 
229                             return(status);
230                         }
231 
232                         /* We have received some data, update the length remaining.  */
233                         object_length -= actual_length;
234 
235                         /* Update the buffer address.  */
236                         object_buffer += actual_length;
237                     }
238 
239                     /* Close the object.  */
240                     status = _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
241 
242                     /* Check the error.  */
243                     if (status != UX_SUCCESS)
244                         return(UX_PICTBRIDGE_ERROR_INVALID_OBJECT_HANDLE);
245 
246                     /* We now have the entire script into memory. Parse the object and execute the script.  */
247                     status = _ux_pictbridge_object_parse(pictbridge, pima_object -> ux_host_class_pima_object_buffer,
248                                                 pima_object -> ux_host_class_pima_object_compressed_size);
249 
250                     /* Analyze the status from the parsing and determine the result code.  */
251                     switch (status)
252                     {
253                         case UX_SUCCESS                                     :
254 
255                             /* Set the result code to OK.  */
256                             pictbridge -> ux_pictbridge_operation_result =  UX_PICTBRIDGE_ACTION_RESULT_OK;
257                             break;
258 
259                         case UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR        :
260 
261                             /* Set the result code to Error.  */
262                             pictbridge -> ux_pictbridge_operation_result =  UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_IP;
263                             break;
264 
265                         case UX_PICTBRIDGE_ERROR_PARAMETER_UNKNOWN          :
266 
267                             /* Set the result code to Error.  */
268                             pictbridge -> ux_pictbridge_operation_result =  UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_UP;
269                             break;
270 
271                         case UX_PICTBRIDGE_ERROR_PARAMETER_MISSING          :
272 
273                             /* Set the result code to Error.  */
274                             pictbridge -> ux_pictbridge_operation_result =  UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_MP;
275                             break;
276 
277                         default :
278 
279                             /* Set the result code to Error.  */
280                             pictbridge -> ux_pictbridge_operation_result =  UX_PICTBRIDGE_ACTION_RESULT_NOT_SUPPORTED_DEFAULT;
281                             break;
282                     }
283 
284                     if (status != UX_SUCCESS)
285                         return(status);
286                 }
287             }
288         }
289     }
290 
291     return(UX_SUCCESS);
292 }
293 
294