From 4e3f835126b5116f5cec88634e18f3d54900892d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Mar 2020 17:51:42 +0200 Subject: libcamera: controls: Add support for string controls String controls are stored internally as an array of char, but the ControlValue constructor, get() and set() functions operate on an std::string for convenience. Array of strings are thus not supported. Unlike for other control types, the ControlInfo range reports the minimum and maximum allowed lengths of the string (the minimum will usually be 0), not the minimum and maximum value of each element. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/controls.h | 30 ++++++++++++++++++++++++------ src/libcamera/control_serializer.cpp | 22 ++++++++++++++++++++++ src/libcamera/controls.cpp | 33 +++++++++++++++++++++++++++++++-- src/libcamera/gen-controls.py | 18 ++++++++++-------- 4 files changed, 87 insertions(+), 16 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 9c6cbffb..5cf6280e 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -26,6 +26,7 @@ enum ControlType { ControlTypeInteger32, ControlTypeInteger64, ControlTypeFloat, + ControlTypeString, }; namespace details { @@ -64,6 +65,11 @@ struct control_type { static constexpr ControlType value = ControlTypeFloat; }; +template<> +struct control_type { + static constexpr ControlType value = ControlTypeString; +}; + template struct control_type> : public control_type> { }; @@ -76,7 +82,9 @@ public: ControlValue(); #ifndef __DOXYGEN__ - template::value, std::nullptr_t> = nullptr> + template::value && + !std::is_same>::value, + std::nullptr_t> = nullptr> ControlValue(const T &value) : type_(ControlTypeNone), numElements_(0) { @@ -84,7 +92,9 @@ public: &value, 1, sizeof(T)); } - template::value, std::nullptr_t> = nullptr> + template::value || + std::is_same>::value, + std::nullptr_t> = nullptr> #else template #endif @@ -115,7 +125,9 @@ public: } #ifndef __DOXYGEN__ - template::value, std::nullptr_t> = nullptr> + template::value && + !std::is_same>::value, + std::nullptr_t> = nullptr> T get() const { assert(type_ == details::control_type>::value); @@ -124,7 +136,9 @@ public: return *reinterpret_cast(data().data()); } - template::value, std::nullptr_t> = nullptr> + template::value || + std::is_same>::value, + std::nullptr_t> = nullptr> #else template #endif @@ -139,14 +153,18 @@ public: } #ifndef __DOXYGEN__ - template::value, std::nullptr_t> = nullptr> + template::value && + !std::is_same>::value, + std::nullptr_t> = nullptr> void set(const T &value) { set(details::control_type>::value, false, reinterpret_cast(&value), 1, sizeof(T)); } - template::value, std::nullptr_t> = nullptr> + template::value || + std::is_same>::value, + std::nullptr_t> = nullptr> #else template #endif diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index eef875f4..808419f2 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -314,6 +314,22 @@ ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer, return value; } +template<> +ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer, + bool isArray, + unsigned int count) +{ + ControlValue value; + + const char *data = buffer.read(count); + if (!data) + return value; + + value.set(std::string{ data, count }); + + return value; +} + ControlValue ControlSerializer::loadControlValue(ControlType type, ByteStreamBuffer &buffer, bool isArray, @@ -335,6 +351,9 @@ ControlValue ControlSerializer::loadControlValue(ControlType type, case ControlTypeFloat: return loadControlValue(buffer, isArray, count); + case ControlTypeString: + return loadControlValue(buffer, isArray, count); + case ControlTypeNone: return ControlValue(); } @@ -345,6 +364,9 @@ ControlValue ControlSerializer::loadControlValue(ControlType type, ControlInfo ControlSerializer::loadControlInfo(ControlType type, ByteStreamBuffer &b) { + if (type == ControlTypeString) + type = ControlTypeInteger32; + ControlValue min = loadControlValue(type, b); ControlValue max = loadControlValue(type, b); diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 53649fe8..11cec519 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -57,6 +57,7 @@ static constexpr size_t ControlValueSize[] = { [ControlTypeInteger32] = sizeof(int32_t), [ControlTypeInteger64] = sizeof(int64_t), [ControlTypeFloat] = sizeof(float), + [ControlTypeString] = sizeof(char), }; } /* namespace */ @@ -76,6 +77,8 @@ static constexpr size_t ControlValueSize[] = { * The control stores a 64-bit integer value * \var ControlTypeFloat * The control stores a 32-bit floating point value + * \var ControlTypeString + * The control stores a string value as an array of char */ /** @@ -164,7 +167,8 @@ ControlValue &ControlValue::operator=(const ControlValue &other) * \brief Retrieve the number of elements stored in the ControlValue * * For instances storing an array, this function returns the number of elements - * in the array. Otherwise, it returns 1. + * in the array. For instances storing a string, it returns the length of the + * string, not counting the terminating '\0'. Otherwise, it returns 1. * * \return The number of elements stored in the ControlValue */ @@ -192,6 +196,11 @@ std::string ControlValue::toString() const return ""; const uint8_t *data = ControlValue::data().data(); + + if (type_ == ControlTypeString) + return std::string(reinterpret_cast(data), + numElements_); + std::string str(isArray_ ? "[ " : ""); for (unsigned int i = 0; i < numElements_; ++i) { @@ -222,6 +231,7 @@ std::string ControlValue::toString() const break; } case ControlTypeNone: + case ControlTypeString: break; } @@ -439,12 +449,22 @@ ControlInfo::ControlInfo(const ControlValue &min, /** * \fn ControlInfo::min() * \brief Retrieve the minimum value of the control + * + * For string controls, this is the minimum length of the string, not counting + * the terminating '\0'. For all other control types, this is the minimum value + * of each element. + * * \return A ControlValue with the minimum value for the control */ /** * \fn ControlInfo::max() * \brief Retrieve the maximum value of the control + * + * For string controls, this is the maximum length of the string, not counting + * the terminating '\0'. For all other control types, this is the maximum value + * of each element. + * * \return A ControlValue with the maximum value for the control */ @@ -653,7 +673,16 @@ void ControlInfoMap::generateIdmap() idmap_.clear(); for (const auto &ctrl : *this) { - if (ctrl.first->type() != ctrl.second.min().type()) { + /* + * For string controls, min and max define the valid + * range for the string size, not for the individual + * values. + */ + ControlType rangeType = ctrl.first->type() == ControlTypeString + ? ControlTypeInteger32 : ctrl.first->type(); + const ControlInfo &info = ctrl.second; + + if (info.min().type() != rangeType) { LOG(Controls, Error) << "Control " << utils::hex(ctrl.first->id()) << " type and info type mismatch"; diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py index ff8bda6b..87c3d52a 100755 --- a/src/libcamera/gen-controls.py +++ b/src/libcamera/gen-controls.py @@ -42,10 +42,11 @@ ${description} name, ctrl = ctrl.popitem() id_name = snake_case(name).upper() - if ctrl.get('size'): - ctrl_type = 'Span' % ctrl['type'] - else: - ctrl_type = ctrl['type'] + ctrl_type = ctrl['type'] + if ctrl_type == 'string': + ctrl_type = 'std::string' + elif ctrl.get('size'): + ctrl_type = 'Span' % ctrl_type info = { 'name': name, @@ -97,10 +98,11 @@ def generate_h(controls): ids.append('\t' + id_name + ' = ' + str(id_value) + ',') - if ctrl.get('size'): - ctrl_type = 'Span' % ctrl['type'] - else: - ctrl_type = ctrl['type'] + ctrl_type = ctrl['type'] + if ctrl_type == 'string': + ctrl_type = 'std::string' + elif ctrl.get('size'): + ctrl_type = 'Span' % ctrl_type info = { 'name': name, -- cgit v1.2.1