@@ -82,17 +82,19 @@ static const std::map<unsigned, std::string> *libcamera_find_control_ids(unsigne
8282 return &iter->second .enum_values ;
8383}
8484
85- static long long libcamera_find_control_id_named_value (unsigned control_id, const char *name )
85+ static long long libcamera_find_control_id_named_value (unsigned control_id, const char **value )
8686{
8787 auto named_values = libcamera_find_control_ids (control_id);
8888 if (named_values) {
8989 for (const auto & named_value : *named_values) {
90- if (device_option_is_equal (named_value.second .c_str (), name))
90+ if (device_option_is_equal (named_value.second .c_str (), *value)) {
91+ *value += named_value.second .length ();
9192 return named_value.first ;
93+ }
9294 }
9395 }
9496
95- return strtoll (name, NULL , 10 );
97+ return strtoll (*value, ( char **)value , 10 );
9698}
9799
98100static libcamera::ControlInfoMap::Map libcamera_control_list (device_t *dev)
@@ -140,9 +142,9 @@ void libcamera_device_dump_options(device_t *dev, FILE *stream)
140142 auto control_key = libcamera_device_option_normalize (control_id->name ());
141143 auto control_info = control.second ;
142144
143- fprintf (stream, " - available option: %s (%08x, type=%s): %s\n " ,
145+ fprintf (stream, " - available option: %s (%08x, type=%s%s ): %s\n " ,
144146 control_id->name ().c_str (), control_id->id (),
145- control_type_values[control_id->type ()].c_str (),
147+ control_type_values[control_id->type ()].c_str (), control_id-> isArray () ? " Array " : " " ,
146148 control_info.toString ().c_str ());
147149
148150 auto named_values = libcamera_find_control_ids (control_id->id ());
@@ -321,101 +323,107 @@ int libcamera_device_dump_options2(device_t *dev, device_option_fn fn, void *opa
321323 return n;
322324}
323325
324- static libcamera::Rectangle libcamera_parse_rectangle (const char *value)
326+ static float libcamera_parse_float (const char **value)
327+ {
328+ return strtof (*value, (char **)value);
329+ }
330+
331+ static libcamera::Rectangle libcamera_parse_rectangle (const char **value)
325332{
326333 static const char *RECTANGLE_PATTERNS[] =
327334 {
328- " (%d,%d)/%ux%u" ,
329- " %d,%d,%u,%u" ,
335+ " (%d,%d)/%ux%u%n " ,
336+ " %d,%d,%u,%u%n " ,
330337 NULL
331338 };
332339
333340 for (int i = 0 ; RECTANGLE_PATTERNS[i]; i++) {
334341 libcamera::Rectangle rectangle;
342+ int read = 0 ;
335343
336- if (4 == sscanf (value, RECTANGLE_PATTERNS[i],
344+ if (4 == sscanf (* value, RECTANGLE_PATTERNS[i],
337345 &rectangle.x , &rectangle.y ,
338- &rectangle.width , &rectangle.height )) {
346+ &rectangle.width , &rectangle.height , &read)) {
347+ *value += read;
339348 return rectangle;
340349 }
341350 }
342351
352+ value = NULL ;
343353 return libcamera::Rectangle ();
344354}
345355
346- static libcamera::Size libcamera_parse_size (const char *value)
356+ static libcamera::Size libcamera_parse_size (const char ** value)
347357{
348358 static const char *SIZE_PATTERNS[] =
349359 {
350- " %ux%u" ,
351- " %u,%u" ,
360+ " %ux%u%n " ,
361+ " %u,%u%n " ,
352362 NULL
353363 };
354364
355365 for (int i = 0 ; SIZE_PATTERNS[i]; i++) {
356366 libcamera::Size size;
367+ int read = 0 ;
357368
358- if (2 == sscanf (value, SIZE_PATTERNS[i], &size.width , &size.height )) {
369+ if (2 == sscanf (*value, SIZE_PATTERNS[i], &size.width , &size.height , &read)) {
370+ *value += read;
359371 return size;
360372 }
361373 }
362374
375+ *value = NULL ;
363376 return libcamera::Size ();
364377}
365378
366379#if LIBCAMERA_VERSION_MAJOR == 0 && LIBCAMERA_VERSION_MINOR > 3 && LIBCAMERA_VERSION_PATCH >= 2 // Support for older libcamera versions
367- static libcamera::Point libcamera_parse_point (const char *value)
380+ static libcamera::Point libcamera_parse_point (const char ** value)
368381{
369382 static const char *POINT_PATTERNS[] =
370383 {
371- " (%d,%d)" ,
372- " %d,%d" ,
384+ " (%d,%d)%n " ,
385+ " %d,%d%n " ,
373386 NULL
374387 };
375388
376389 for (int i = 0 ; POINT_PATTERNS[i]; i++) {
377390 libcamera::Point point;
391+ int read = 0 ;
378392
379- if (2 == sscanf (value, POINT_PATTERNS[i],
380- &point.x , &point.y )) {
393+ if (2 == sscanf (*value, POINT_PATTERNS[i],
394+ &point.x , &point.y , &read)) {
395+ *value += read;
381396 return point;
382397 }
383398 }
384399
400+ *value = NULL ;
385401 return libcamera::Point ();
386402}
387403#endif
388404
389- template <typename T, typename F >
390- static bool libcamera_parse_control_value (libcamera::ControlValue &control_value, const char *value, const F & fn)
405+ template <typename T>
406+ static bool libcamera_parse_control_value (libcamera::ControlValue &control_value, bool control_array, const char *value, const std::function<T( const char **)>& fn)
391407{
392- std::vector<T> parsed ;
408+ std::vector<T> items ;
393409
394410 while (value && *value) {
395- std::string current_value;
396-
397- if (const char *next = strchr (value, ' ,' )) {
398- current_value.assign (value, next);
399- value = &next[1 ];
400- } else {
401- current_value.assign (value);
402- value = NULL ;
403- }
404-
405- if (current_value.empty ())
406- continue ;
407-
408- parsed.push_back (fn (current_value.c_str ()));
411+ items.push_back (fn (&value));
412+ if (!value)
413+ return false ; // failed to parse
414+ else if (!*value)
415+ break ; // reached end of elements
416+ else if (*value != ' ,' )
417+ return false ; // expected comma to split items
418+ value++;
409419 }
410420
411- if (parsed .empty ()) {
421+ if (items .empty ()) {
412422 return false ;
413- }
414-
415- if (parsed.size () > 1 ) {
416- control_value.set <libcamera::Span<T> >(parsed);
423+ } else if (control_array) {
424+ control_value.set <libcamera::Span<T> >(items);
417425 } else {
418- control_value.set <T>(parsed [0 ]);
426+ control_value.set <T>(items [0 ]);
419427 }
420428
421429 return true ;
@@ -433,42 +441,46 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val
433441 continue ;
434442
435443 libcamera::ControlValue control_value;
444+ bool control_array = control_id->isArray ();
436445
437446 switch (control_id->type ()) {
438447 case libcamera::ControlTypeNone:
439448 break ;
440449
441450 case libcamera::ControlTypeBool:
451+ if (control_array) {
452+ throw std::runtime_error (" Array ControlType for boolean is not supported" );
453+ }
442454 control_value.set <bool >(atoi (value));
443455 break ;
444456
445457 case libcamera::ControlTypeByte:
446- libcamera_parse_control_value<unsigned char >(control_value, value,
447- [control_id](const char *value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
458+ libcamera_parse_control_value<unsigned char >(control_value, control_array, value,
459+ [control_id](const char ** value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
448460 break ;
449461
450462 case libcamera::ControlTypeInteger32:
451- libcamera_parse_control_value<int32_t >(control_value, value,
452- [control_id](const char *value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
463+ libcamera_parse_control_value<int32_t >(control_value, control_array, value,
464+ [control_id](const char ** value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
453465 break ;
454466
455467 case libcamera::ControlTypeInteger64:
456- libcamera_parse_control_value<int64_t >(control_value, value,
457- [control_id](const char *value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
468+ libcamera_parse_control_value<int64_t >(control_value, control_array, value,
469+ [control_id](const char ** value) { return libcamera_find_control_id_named_value (control_id->id (), value); });
458470 break ;
459471
460472 case libcamera::ControlTypeFloat:
461- libcamera_parse_control_value<float >(control_value, value, atof );
473+ libcamera_parse_control_value<float >(control_value, control_array, value, libcamera_parse_float );
462474 break ;
463475
464476 case libcamera::ControlTypeRectangle:
465477 libcamera_parse_control_value<libcamera::Rectangle>(
466- control_value, value, libcamera_parse_rectangle);
478+ control_value, control_array, value, libcamera_parse_rectangle);
467479 break ;
468480
469481 case libcamera::ControlTypeSize:
470482 libcamera_parse_control_value<libcamera::Size>(
471- control_value, value, libcamera_parse_size);
483+ control_value, control_array, value, libcamera_parse_size);
472484 break ;
473485
474486 case libcamera::ControlTypeString:
@@ -477,7 +489,7 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val
477489#if LIBCAMERA_VERSION_MAJOR == 0 && LIBCAMERA_VERSION_MINOR > 3 && LIBCAMERA_VERSION_PATCH >= 2 // Support for older libcamera versions
478490 case libcamera::ControlTypePoint:
479491 libcamera_parse_control_value<libcamera::Point>(
480- control_value, value, libcamera_parse_point);
492+ control_value, control_array, value, libcamera_parse_point);
481493 break ;
482494#endif
483495
0 commit comments