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_input_object_send PORTABLE C */
38 /* 6.1.12 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function creates an input report for the dpshost */
46 /* */
47 /* INPUT */
48 /* */
49 /* pictbridge Pictbridge instance */
50 /* input_function input tag */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* */
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 /* verified memset and memcpy */
70 /* cases, used UX prefix to */
71 /* refer to TX symbols instead */
72 /* of using them directly, */
73 /* resulting in version 6.1 */
74 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
75 /* cleared compile warning, */
76 /* used macros for RTOS calls, */
77 /* resulting in version 6.1.12 */
78 /* */
79 /**************************************************************************/
_ux_pictbridge_dpshost_input_object_send(UX_PICTBRIDGE * pictbridge,ULONG input_function)80 UINT _ux_pictbridge_dpshost_input_object_send(UX_PICTBRIDGE *pictbridge, ULONG input_function)
81 {
82 UINT status;
83 ULONG object_length;
84 UCHAR *pima_object_buffer;
85 UX_HOST_CLASS_PIMA *pima;
86 UX_HOST_CLASS_PIMA_SESSION *pima_session;
87 UX_HOST_CLASS_PIMA_OBJECT *pima_object;
88 ULONG requested_length;
89 ULONG object_handle;
90 ULONG actual_flags;
91
92 /* Check the state machine. */
93 if (pictbridge -> ux_pictbridge_host_client_state_machine != UX_PICTBRIDGE_STATE_MACHINE_IDLE)
94 {
95
96 /* Set the state machine to Host Request pending. */
97 pictbridge -> ux_pictbridge_host_client_state_machine |= UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST_PENDING;
98
99 /* Wait for the client event pending request to be completed. */
100 status = _ux_system_event_flags_get(&pictbridge -> ux_pictbridge_event_flags_group,
101 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
102 UX_AND_CLEAR, &actual_flags, UX_PICTBRIDGE_EVENT_TIMEOUT);
103
104 /* Reset the state machine to not Host Request pending. */
105 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST_PENDING;
106
107 /* Check status. */
108 if (status != UX_SUCCESS)
109 return(UX_ERROR);
110
111 /* Status good means flag match, no need to check variable again, mark it unused. */
112 (void)actual_flags;
113 }
114
115 /* Change state machine to host request pending. */
116 pictbridge -> ux_pictbridge_host_client_state_machine |= UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
117
118 /* Get the pima instance from the pictbridge container. */
119 pima = (UX_HOST_CLASS_PIMA *) pictbridge -> ux_pictbridge_pima;
120
121 /* And now the session since we use it. */
122 pima_session = (UX_HOST_CLASS_PIMA_SESSION *)pictbridge -> ux_pictbridge_session;
123
124 /* Get the address of the object container. */
125 pima_object = (UX_HOST_CLASS_PIMA_OBJECT *) pictbridge -> ux_pictbridge_object_host;
126
127 /* Get the object buffer address. */
128 pima_object_buffer = pima_object -> ux_host_class_pima_object_buffer;
129
130 /* Reset the object length. */
131 object_length = 0;
132
133 /* Clear the object memory buffer. */
134 _ux_utility_memory_set(pima_object_buffer, 0, UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER); /* Use case of memset is verified. */
135
136 /* Add the line <?xml version="1.0"?> */
137 status = _ux_pictbridge_object_tag_line_add(pima_object_buffer, object_length, _ux_pictbridge_xml_tag_line_xmlversion,
138 UX_PICTBRIDGE_TAG_FLAG_BEGIN | UX_PICTBRIDGE_TAG_FLAG_FORCE_LF,
139 UX_NULL, 0, UX_NULL, &pima_object_buffer, &object_length);
140 if (status != UX_SUCCESS)
141 return(status);
142
143 /* Add the line <dps xmlns="http://www.cipa.jp/dps/schema/"> */
144 status = _ux_pictbridge_object_tag_line_add(pima_object_buffer, object_length, _ux_pictbridge_xml_tag_line_dpsxmlns,
145 UX_PICTBRIDGE_TAG_FLAG_BEGIN | UX_PICTBRIDGE_TAG_FLAG_FORCE_LF,
146 UX_NULL, 0, UX_NULL, &pima_object_buffer, &object_length);
147
148 /* Add the line <input> */
149 if (status == UX_SUCCESS)
150 {
151 status = _ux_pictbridge_object_tag_line_add(pima_object_buffer, object_length, _ux_pictbridge_xml_tag_line_input,
152 UX_PICTBRIDGE_TAG_FLAG_BEGIN | UX_PICTBRIDGE_TAG_FLAG_FORCE_LF,
153 UX_NULL, 0, UX_NULL, &pima_object_buffer, &object_length);
154 }
155
156 /* Look into the tag code from the input object and proceed to individual functions. */
157 if (status == UX_SUCCESS)
158 {
159 switch (input_function)
160 {
161
162 case UX_PICTBRIDGE_IR_NOTIFY_JOB_STATUS :
163
164 /* Insert the notifyJobStatus tag lines. */
165 status = _ux_pictbridge_dpshost_input_object_notify_job_status(pictbridge, pima_object_buffer, object_length, &pima_object_buffer, &object_length);
166 break;
167
168 case UX_PICTBRIDGE_IR_NOTIFY_DEVICE_STATUS :
169
170 /* Insert the notifyDeviceStatus tag lines. */
171 status = _ux_pictbridge_dpshost_input_object_notify_device_status(pictbridge, pima_object_buffer, object_length, &pima_object_buffer, &object_length);
172 break;
173
174 default :
175
176 /* Function not yet supported. We should never come here anyway. */
177 status = UX_ERROR;
178
179 }
180 }
181
182 /* Add the line </input> */
183 if (status == UX_SUCCESS)
184 {
185 status = _ux_pictbridge_object_tag_line_add(pima_object_buffer, object_length, _ux_pictbridge_xml_tag_line_input,
186 UX_PICTBRIDGE_TAG_FLAG_END,
187 UX_NULL, 0, UX_NULL, &pima_object_buffer, &object_length);
188 }
189
190 /* Add the line </dps> */
191 if (status == UX_SUCCESS)
192 {
193 status = _ux_pictbridge_object_tag_line_add(pima_object_buffer, object_length, _ux_pictbridge_xml_tag_line_dps,
194 UX_PICTBRIDGE_TAG_FLAG_END,
195 UX_NULL, 0, UX_NULL, &pima_object_buffer, &object_length);
196 }
197
198 /* Handle error. */
199 if (status != UX_SUCCESS)
200 {
201
202 /* Do we have a pending client event ? */
203 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
204 {
205
206 /* Yes, so we need to set the event that advertise the completion of the host request. */
207 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
208 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
209 UX_AND);
210
211 }
212
213 /* Change state machine to idle. */
214 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
215 return(UX_ERROR);
216 }
217
218 /* Store the length of the new object waiting to be sent out.
219 We do not store the length into the object itself since this function is
220 host\client agnostic. */
221 pima_object -> ux_host_class_pima_object_length = object_length;
222
223 /* Get the length of the object and store it into the object data set. */
224 pima_object -> ux_host_class_pima_object_compressed_size = object_length;
225
226 /* We need to change the file name to HREQUEST.DPS. Encode the file name from ascii format into Unicode. */
227 _ux_utility_string_to_unicode(_ux_pictbridge_hrequest_name, pima_object -> ux_host_class_pima_object_filename);
228
229 /* Set the object handle. */
230 object_handle = 1;
231
232 /* Send a script info. */
233 status = _ux_host_class_pima_object_info_send(pima, pima_session, 0, 0, pima_object);
234 if (status != UX_SUCCESS)
235 {
236
237 /* Do we have a pending client event ? */
238 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
239 {
240
241 /* Yes, so we need to set the event that advertise the completion of the host request. */
242 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
243 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
244 UX_AND);
245
246 }
247
248 /* Change state machine to idle. */
249 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
250
251 /* Return status. */
252 return(status);
253 }
254
255
256
257
258 /* Open the object. */
259 status = _ux_host_class_pima_object_open(pima, pima_session,
260 object_handle,
261 pima_object);
262 if (status != UX_SUCCESS)
263 {
264
265 /* Do we have a pending client event ? */
266 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
267 {
268
269 /* Yes, so we need to set the event that advertise the completion of the host request. */
270 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
271 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
272 UX_AND);
273
274 }
275
276 /* Change state machine to idle. */
277 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
278
279 /* Return status. */
280 return(status);
281 }
282
283 /* Get the object length. */
284 object_length = pima_object -> ux_host_class_pima_object_compressed_size;
285
286 /* Recall the object buffer address. */
287 pima_object_buffer = pima_object -> ux_host_class_pima_object_buffer;
288
289 /* Send all the object data. */
290 while(object_length != 0)
291 {
292
293 /* Calculate what length to request. */
294 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
295
296 /* Request maximum length. */
297 requested_length = UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER;
298
299 else
300
301 /* Request remaining length. */
302 requested_length = object_length;
303
304
305 /* Send the object data. */
306 status = _ux_host_class_pima_object_send(pima, pima_session, pima_object,
307 pima_object_buffer, requested_length);
308 if (status != UX_SUCCESS)
309 {
310
311 /* Abort the transfer. */
312 _ux_host_class_pima_object_transfer_abort(pima, pima_session, object_handle, pima_object);
313
314 /* Do we have a pending client event ? */
315 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
316 {
317
318 /* Yes, so we need to set the event that advertise the completion of the host request. */
319 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
320 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
321 UX_AND);
322
323 }
324
325 /* Change state machine to idle. */
326 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
327
328 /* Return status. */
329 return(status);
330
331 }
332
333 /* We have sent some data, update the length remaining. */
334 object_length -= requested_length;
335 }
336
337 /* Close the object. */
338 status = _ux_host_class_pima_object_close(pima, pima_session, object_handle, pima_object);
339
340 /* Check the status. */
341 if (status != UX_SUCCESS)
342 {
343
344 /* Do we have a pending client event ? */
345 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
346 {
347
348 /* Yes, so we need to set the event that advertise the completion of the host request. */
349 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
350 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
351 UX_AND);
352
353 }
354
355 /* Change state machine to idle. */
356 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
357
358 /* Return status. */
359 return(status);
360 }
361
362
363 /* Wait for the response from the device. */
364 status = _ux_pictbridge_dpshost_response_get(pictbridge);
365
366
367 /* Do we have a pending client event ? */
368 if (pictbridge -> ux_pictbridge_host_client_state_machine & UX_PICTBRIDGE_STATE_MACHINE_CLIENT_REQUEST_PENDING)
369 {
370
371 /* Yes, so we need to set the event that advertise the completion of the host request. */
372 _ux_system_event_flags_set(&pictbridge -> ux_pictbridge_event_flags_group,
373 UX_PICTBRIDGE_EVENT_FLAG_STATE_MACHINE_READY,
374 UX_AND);
375
376 }
377
378 /* Change state machine to idle. */
379 pictbridge -> ux_pictbridge_host_client_state_machine &= (UINT)~UX_PICTBRIDGE_STATE_MACHINE_HOST_REQUEST;
380
381 /* Return status. */
382 return(status);
383
384 }
385
386