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