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
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_pictbridge_object_tag_line_add PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function adds a tag line into the target xml object */
44 /* */
45 /* INPUT */
46 /* */
47 /* pima_object_buffer Pointer to object buffer */
48 /* object_length Length of the object */
49 /* tag_element Tag to insert */
50 /* tag_flag Flags */
51 /* tag_variable Variable if any */
52 /* tag_variable_value Variable value if any */
53 /* tag_element element to insert after tag */
54 /* pima_object_buffer_updated Updated Address of the object */
55 /* object_length_updated Updated length */
56 /* */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* Completion Status */
61 /* */
62 /* CALLS */
63 /* */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _ux_pictbridge_dpshost_object_get */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
74 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
75 /* verified memset and memcpy */
76 /* cases, */
77 /* resulting in version 6.1 */
78 /* */
79 /**************************************************************************/
_ux_pictbridge_object_tag_line_add(UCHAR * pima_object_buffer,ULONG object_length,UCHAR * tag_element_string,ULONG tag_flag,UCHAR * tag_variable,ULONG tag_variable_value,VOID * tag_element,UCHAR ** pima_object_buffer_updated,ULONG * object_length_updated)80 UINT _ux_pictbridge_object_tag_line_add(UCHAR *pima_object_buffer,
81 ULONG object_length,
82 UCHAR *tag_element_string,
83 ULONG tag_flag,
84 UCHAR *tag_variable,
85 ULONG tag_variable_value,
86 VOID *tag_element,
87 UCHAR **pima_object_buffer_updated,
88 ULONG *object_length_updated)
89 {
90
91 UINT element_length = 0;
92 ULONG value_index;
93 UINT status;
94
95 /* Check if we need to insert a beginning tag. */
96 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
97 {
98
99 /* Going to add '<'. */
100 object_length += 1;
101
102 /* Calculate the length of the element. */
103 status = _ux_utility_string_length_check(tag_element_string, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
104 if (status != UX_SUCCESS)
105
106 /* Bad element. */
107 return(status);
108
109 /* Going to add element. */
110 object_length += element_length;
111
112 /* Do bounds-checking. */
113 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
114 return(UX_MEMORY_INSUFFICIENT);
115
116 /* Insert a "<". */
117 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_START_BRACKET;
118
119 /* Create the element string. */
120 _ux_utility_memory_copy(pima_object_buffer, tag_element_string, element_length); /* Use case of memcpy is verified. */
121
122 /* Update the object pointer position. */
123 pima_object_buffer += element_length;
124
125 /* Do we have a variable to insert after the opening tag ? */
126 if (tag_variable != UX_NULL)
127 {
128
129 /* Going to add " ". */
130 object_length += 1;
131
132 /* Insert the variable. First calculate the length of the variable. */
133 status = _ux_utility_string_length_check(tag_variable, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
134 if (status != UX_SUCCESS)
135
136 /* Bad element. */
137 return(status);
138
139 /* Going to add element. */
140 object_length += element_length;
141
142 /* Going to insert "=". */
143 object_length += 1;
144
145 /* Going to insert a quote. */
146 object_length += 1;
147
148 /* Going to insert 8 hex chars. */
149 object_length += 8;
150
151 /* Going to insert a quote. */
152 object_length += 1;
153
154 /* Do bounds-checking. */
155 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
156 return(UX_MEMORY_INSUFFICIENT);
157
158 /* Insert a " ". */
159 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
160
161 /* Create the variable string. */
162 _ux_utility_memory_copy(pima_object_buffer, tag_variable, element_length); /* Use case of memcpy is verified. */
163
164 /* Update the object pointer position. */
165 pima_object_buffer += element_length;
166
167 /* Insert a "=". */
168 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_EQUAL;
169
170 /* Insert a quote. */
171 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_QUOTE;
172
173 /* Insert a value in between the quote. This value is always of type hexa. */
174 status = _ux_pictbridge_hexa_to_element(tag_variable_value, pima_object_buffer);
175 if (status != UX_SUCCESS)
176
177 /* Bad element. */
178 return(status);
179
180 /* Update the object pointer position. */
181 pima_object_buffer += 8;
182
183 /* Insert a quote. */
184 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_QUOTE;
185 }
186
187 /* Check if we need to insert a slash at the end of the tag. */
188 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_FORCE_SLASH_AT_END)
189 {
190
191 /* Going to insert a "/". */
192 object_length += 1;
193
194 /* Do bounds-checking. */
195 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
196 return(UX_MEMORY_INSUFFICIENT);
197
198 /* Insert a "/". */
199 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SLASH;
200 }
201
202 /* Going to insert a ">". */
203 object_length += 1;
204
205 /* Do bounds-checking. */
206 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
207 return(UX_MEMORY_INSUFFICIENT);
208
209 /* Insert a ">". */
210 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_END_BRACKET;
211 }
212
213 /* Is there a tag element to add between the begin tag and end tag ? */
214 /* We do have something to insert, this element can have multiple format and
215 can be a single value or an array of values. */
216 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE)
217 {
218
219 /* We have a single variable. Check its nature. Is it hexa ? */
220 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_HEXA)
221 {
222
223 /* Going to insert 8 hex chars. Do bounds-checking. */
224 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
225 return(UX_MEMORY_INSUFFICIENT);
226
227 /* We have a single hexa value to insert. */
228 status = _ux_pictbridge_hexa_to_element((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer);
229 if (status != UX_SUCCESS)
230
231 /* Bad element. */
232 return(status);
233 element_length = 8;
234 }
235
236 /* Is it decimal ? */
237 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_DECIMAL)
238 {
239
240 /* Going to insert at maximum 8 chars. Do bounds-checking. */
241 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
242 return(UX_MEMORY_INSUFFICIENT);
243
244 /* We have a single decimal value to insert. */
245 status = _ux_pictbridge_hexa_to_decimal_string((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_OFF, 8);
246 if (status != UX_SUCCESS)
247
248 /* Bad element. */
249 return(status);
250 _ux_utility_string_length_check(pima_object_buffer, &element_length, 8);
251 }
252
253 /* Is it 3 decimal with leading zeroes ? */
254 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_DECIMAL_3DIGITS)
255 {
256
257 /* Going to insert at maximum 3 chars. Do bounds-checking. */
258 if (object_length + 3 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
259 return(UX_MEMORY_INSUFFICIENT);
260
261 /* We have a single decimal value to insert but 3 digits only and leading zeroes. */
262 status = _ux_pictbridge_hexa_to_decimal_string((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_ON, 3);
263 if (status != UX_SUCCESS)
264
265 /* Bad element. */
266 return(status);
267 element_length = 3;
268 }
269
270 /* Is it in the form 00.00 ? */
271 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_MAJOR_MINOR)
272 {
273
274 /* Going to insert at maximum 5 chars. Do bounds-checking. */
275 if (object_length + 5 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
276 return(UX_MEMORY_INSUFFICIENT);
277
278 /* We have a major minor value to insert. */
279 status = _ux_pictbridge_hexa_to_major_minor((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer);
280 if (status != UX_SUCCESS)
281
282 /* Bad element. */
283 return(status);
284 element_length = 5;
285 }
286
287 /* Is it a ascii string ? */
288 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_STRING)
289 {
290
291 /* Calculate the length of the element to be inserted. */
292 status = _ux_utility_string_length_check((UCHAR *) tag_element, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
293 if (status != UX_SUCCESS)
294
295 /* Bad element. */
296 return(status);
297
298 /* Going to insert element. Do bounds-checking. */
299 if (object_length + element_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
300 return(UX_MEMORY_INSUFFICIENT);
301
302 /* We have a string to insert. */
303 _ux_utility_memory_copy(pima_object_buffer, (UCHAR *) tag_element, element_length); /* Use case of memcpy is verified. */
304 }
305
306 /* Update the object pointer position. */
307 pima_object_buffer += element_length;
308
309 object_length += element_length;
310 }
311
312 /* Is there an array to insert ? */
313 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY)
314 {
315
316 /* We have an array to insert. First reset the value index. */
317 value_index = 0;
318
319 /* Parse all qualities supported and insert their values. */
320 while( *((ULONG *)tag_element + value_index) != 0)
321 {
322
323 /* If this value is not the first, we must use a space separator. */
324 if (value_index != 0)
325 {
326
327 /* Going to insert a space. */
328 object_length += 1;
329
330 /* Do bounds-checking. */
331 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
332 return(UX_MEMORY_INSUFFICIENT);
333
334 /* Insert a space. */
335 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
336 }
337
338 /* We have a array variable. Check its nature. Is it hexa ? */
339 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_HEXA)
340 {
341
342 /* Going to insert 8 hex chars. Do bounds-checking. */
343 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
344 return(UX_MEMORY_INSUFFICIENT);
345
346 /* We have a single hexa value to insert. */
347 status = _ux_pictbridge_hexa_to_element( *((ULONG *) tag_element + value_index), pima_object_buffer);
348 if (status != UX_SUCCESS)
349
350 /* Bad element. */
351 return(status);
352 element_length = 8;
353 }
354
355 /* Is it decimal ? */
356 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_DECIMAL)
357 {
358
359 /* Going to insert at maximum 8 chars. Do bounds-checking. */
360 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
361 return(UX_MEMORY_INSUFFICIENT);
362
363 /* We have a array of decimal value to insert. */
364 status = _ux_pictbridge_hexa_to_decimal_string( *((ULONG *)tag_element + value_index), pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_OFF, 8);
365 if (status != UX_SUCCESS)
366
367 /* Bad element. */
368 return(status);
369 _ux_utility_string_length_check(pima_object_buffer, &element_length, 8);
370 }
371
372 /* Is it in the form 00.00 ? */
373 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_MAJOR_MINOR)
374 {
375
376 /* Going to insert at maximum 5 chars. Do bounds-checking. */
377 if (object_length + 5 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
378 return(UX_MEMORY_INSUFFICIENT);
379
380 /* We have a array of major minor value to insert. */
381 status = _ux_pictbridge_hexa_to_major_minor( *((ULONG *) tag_element + value_index), pima_object_buffer);
382 if (status != UX_SUCCESS)
383
384 /* Bad element. */
385 return(status);
386 element_length = 5;
387 }
388
389 /* Is it a ascii string ? */
390 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_STRING)
391 {
392
393 /* Calculate the length of the element to be inserted. */
394 status = _ux_utility_string_length_check((UCHAR *) (*((ALIGN_TYPE *)tag_element)), &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
395 if (status != UX_SUCCESS)
396
397 /* Bad element. */
398 return(status);
399
400 /* Going to insert element. Do bounds-checking. */
401 if (object_length + element_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
402 return(UX_MEMORY_INSUFFICIENT);
403
404 /* We have a string to insert. */
405 _ux_utility_memory_copy(pima_object_buffer, (UCHAR *) (*((ALIGN_TYPE *)tag_element)), element_length); /* Use case of memcpy is verified. */
406 }
407
408 /* Update the object pointer position. */
409 pima_object_buffer += element_length;
410
411 /* And update the cumulated length of the object. */
412 object_length += element_length;
413
414 /* Next index value. */
415 value_index++;
416 }
417 }
418
419 /* Check if we need to insert an end tag. */
420 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_END)
421 {
422
423 /* Going to insert a "<". */
424 object_length += 1;
425
426 /* Going to insert a "/". */
427 object_length += 1;
428
429 /* Calculate the length of the element. */
430 status = _ux_utility_string_length_check(tag_element_string, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
431 if (status != UX_SUCCESS)
432
433 /* Bad element. */
434 return(status);
435
436 /* Going to insert element. */
437 object_length += element_length;
438
439 /* Going to insert a ">". */
440 object_length += 1;
441
442 /* Going to insert a LF. */
443 object_length += 1;
444
445 /* Do bounds-checking. */
446 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
447 return(UX_MEMORY_INSUFFICIENT);
448
449 /* Insert a "<". */
450 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_START_BRACKET;
451
452 /* Insert a "/". */
453 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SLASH;
454
455 /* Create the element string. */
456 _ux_utility_memory_copy(pima_object_buffer, tag_element_string, element_length); /* Use case of memcpy is verified. */
457
458 /* Update the object pointer position. */
459 pima_object_buffer += element_length;
460
461 /* Insert a ">". */
462 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_END_BRACKET;
463
464 /* Insert a LF. */
465 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_LF;
466 }
467
468 /* Check if we need to force a LF at end. */
469 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_FORCE_LF)
470 {
471
472 /* Going to insert a LF. */
473 object_length += 1;
474
475 /* Do bounds-checking. */
476 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
477 return(UX_MEMORY_INSUFFICIENT);
478
479 /* Insert a LF. */
480 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_LF;
481 }
482
483 /* Update the caller's object position. */
484 *pima_object_buffer_updated = pima_object_buffer;
485
486 /* Update the caller's object length . */
487 *object_length_updated = object_length;
488
489 /* Return completion status. */
490 return(UX_SUCCESS);
491 }
492