From patchwork Mon Mar 9 16:24:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3066 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 502FC628BD for ; Mon, 9 Mar 2020 17:21:28 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 0820360015 for ; Mon, 9 Mar 2020 16:21:27 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:04 +0100 Message-Id: <20200309162414.720306-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/11] libcamera: controls: Name all ControlInfoMap instance variables infoMap X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:28 -0000 From: Laurent Pinchart To prepare for the rename of ControlRange to ControlInfo, rename all the ControlInfoMap instance variables currently named info to infoMap. This will help avoiding namespace clashes. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/controls.h | 2 +- src/libcamera/control_serializer.cpp | 29 ++++++++++--------- src/libcamera/controls.cpp | 6 ++-- src/libcamera/include/control_serializer.h | 4 +-- ...{control_info.cpp => control_info_map.cpp} | 18 ++++++------ test/controls/meson.build | 8 ++--- test/v4l2_videodevice/controls.cpp | 18 ++++++------ 7 files changed, 43 insertions(+), 42 deletions(-) rename test/controls/{control_info.cpp => control_info_map.cpp} (74%) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 0e111ab72bce..3d2250f43f3c 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -313,7 +313,7 @@ private: public: ControlList(); ControlList(const ControlIdMap &idmap, ControlValidator *validator = nullptr); - ControlList(const ControlInfoMap &info, ControlValidator *validator = nullptr); + ControlList(const ControlInfoMap &infoMap, ControlValidator *validator = nullptr); using iterator = ControlListMap::iterator; using const_iterator = ControlListMap::const_iterator; diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index 004735fb2aa0..dcc63d20c06c 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -106,19 +106,19 @@ size_t ControlSerializer::binarySize(const ControlRange &range) /** * \brief Retrieve the size in bytes required to serialize a ControlInfoMap - * \param[in] info The control info map + * \param[in] infoMap The control info map * * Compute and return the size in bytes required to store the serialized * ControlInfoMap. * * \return The size in bytes required to store the serialized ControlInfoMap */ -size_t ControlSerializer::binarySize(const ControlInfoMap &info) +size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap) { size_t size = sizeof(struct ipa_controls_header) - + info.size() * sizeof(struct ipa_control_range_entry); + + infoMap.size() * sizeof(struct ipa_control_range_entry); - for (const auto &ctrl : info) + for (const auto &ctrl : infoMap) size += binarySize(ctrl.second); return size; @@ -159,32 +159,33 @@ void ControlSerializer::store(const ControlRange &range, /** * \brief Serialize a ControlInfoMap in a buffer - * \param[in] info The control info map to serialize + * \param[in] infoMap The control info map to serialize * \param[in] buffer The memory buffer where to serialize the ControlInfoMap * - * Serialize the \a info map into the \a buffer using the serialization format + * Serialize the \a infoMap into the \a buffer using the serialization format * defined by the IPA context interface in ipa_controls.h. * - * The serializer stores a reference to the \a info internally. The caller - * shall ensure that \a info stays valid until the serializer is reset(). + * The serializer stores a reference to the \a infoMap internally. The caller + * shall ensure that \a infoMap stays valid until the serializer is reset(). * * \return 0 on success, a negative error code otherwise * \retval -ENOSPC Not enough space is available in the buffer */ -int ControlSerializer::serialize(const ControlInfoMap &info, +int ControlSerializer::serialize(const ControlInfoMap &infoMap, ByteStreamBuffer &buffer) { /* Compute entries and data required sizes. */ - size_t entriesSize = info.size() * sizeof(struct ipa_control_range_entry); + size_t entriesSize = infoMap.size() + * sizeof(struct ipa_control_range_entry); size_t valuesSize = 0; - for (const auto &ctrl : info) + for (const auto &ctrl : infoMap) valuesSize += binarySize(ctrl.second); /* Prepare the packet header, assign a handle to the ControlInfoMap. */ struct ipa_controls_header hdr; hdr.version = IPA_CONTROLS_FORMAT_VERSION; hdr.handle = ++serial_; - hdr.entries = info.size(); + hdr.entries = infoMap.size(); hdr.size = sizeof(hdr) + entriesSize + valuesSize; hdr.data_offset = sizeof(hdr) + entriesSize; @@ -197,7 +198,7 @@ int ControlSerializer::serialize(const ControlInfoMap &info, ByteStreamBuffer entries = buffer.carveOut(entriesSize); ByteStreamBuffer values = buffer.carveOut(valuesSize); - for (const auto &ctrl : info) { + for (const auto &ctrl : infoMap) { const ControlId *id = ctrl.first; const ControlRange &range = ctrl.second; @@ -217,7 +218,7 @@ int ControlSerializer::serialize(const ControlInfoMap &info, * Store the map to handle association, to be used to serialize and * deserialize control lists. */ - infoMapHandles_[&info] = hdr.handle; + infoMapHandles_[&infoMap] = hdr.handle; return 0; } diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 4326174adf86..833a436c64df 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -706,11 +706,11 @@ ControlList::ControlList(const ControlIdMap &idmap, ControlValidator *validator) /** * \brief Construct a ControlList with the idmap of a control info map - * \param[in] info The ControlInfoMap for the control list target object + * \param[in] infoMap The ControlInfoMap for the control list target object * \param[in] validator The validator (may be null) */ -ControlList::ControlList(const ControlInfoMap &info, ControlValidator *validator) - : validator_(validator), idmap_(&info.idmap()), infoMap_(&info) +ControlList::ControlList(const ControlInfoMap &infoMap, ControlValidator *validator) + : validator_(validator), idmap_(&infoMap.idmap()), infoMap_(&infoMap) { } diff --git a/src/libcamera/include/control_serializer.h b/src/libcamera/include/control_serializer.h index b91d13155f5e..026e62340328 100644 --- a/src/libcamera/include/control_serializer.h +++ b/src/libcamera/include/control_serializer.h @@ -24,10 +24,10 @@ public: void reset(); - static size_t binarySize(const ControlInfoMap &info); + static size_t binarySize(const ControlInfoMap &infoMap); static size_t binarySize(const ControlList &list); - int serialize(const ControlInfoMap &info, ByteStreamBuffer &buffer); + int serialize(const ControlInfoMap &infoMap, ByteStreamBuffer &buffer); int serialize(const ControlList &list, ByteStreamBuffer &buffer); template diff --git a/test/controls/control_info.cpp b/test/controls/control_info_map.cpp similarity index 74% rename from test/controls/control_info.cpp rename to test/controls/control_info_map.cpp index fa9d7bae97d0..eeb702db095b 100644 --- a/test/controls/control_info.cpp +++ b/test/controls/control_info_map.cpp @@ -36,41 +36,41 @@ protected: int run() override { - const ControlInfoMap &info = camera_->controls(); + const ControlInfoMap &infoMap = camera_->controls(); /* Test looking up a valid control by ControlId. */ - if (info.count(&controls::Brightness) != 1) { + if (infoMap.count(&controls::Brightness) != 1) { cerr << "count() on valid control failed" << endl; return TestFail; } - if (info.find(&controls::Brightness) == info.end()) { + if (infoMap.find(&controls::Brightness) == infoMap.end()) { cerr << "find() on valid control failed" << endl; return TestFail; } - info.at(&controls::Brightness); + infoMap.at(&controls::Brightness); /* Test looking up a valid control by numerical ID. */ - if (info.count(controls::Brightness.id()) != 1) { + if (infoMap.count(controls::Brightness.id()) != 1) { cerr << "count() on valid ID failed" << endl; return TestFail; } - if (info.find(controls::Brightness.id()) == info.end()) { + if (infoMap.find(controls::Brightness.id()) == infoMap.end()) { cerr << "find() on valid ID failed" << endl; return TestFail; } - info.at(controls::Brightness.id()); + infoMap.at(controls::Brightness.id()); /* Test looking up an invalid control by numerical ID. */ - if (info.count(12345) != 0) { + if (infoMap.count(12345) != 0) { cerr << "count() on invalid ID failed" << endl; return TestFail; } - if (info.find(12345) != info.end()) { + if (infoMap.find(12345) != infoMap.end()) { cerr << "find() on invalid ID failed" << endl; return TestFail; } diff --git a/test/controls/meson.build b/test/controls/meson.build index f0850df28c8a..16a7f33fdcc6 100644 --- a/test/controls/meson.build +++ b/test/controls/meson.build @@ -1,8 +1,8 @@ control_tests = [ - [ 'control_info', 'control_info.cpp' ], - [ 'control_list', 'control_list.cpp' ], - [ 'control_range', 'control_range.cpp' ], - [ 'control_value', 'control_value.cpp' ], + [ 'control_info_map', 'control_info_map.cpp' ], + [ 'control_list', 'control_list.cpp' ], + [ 'control_range', 'control_range.cpp' ], + [ 'control_value', 'control_value.cpp' ], ] foreach t : control_tests diff --git a/test/v4l2_videodevice/controls.cpp b/test/v4l2_videodevice/controls.cpp index 42c653d4435a..1b71bf0633b4 100644 --- a/test/v4l2_videodevice/controls.cpp +++ b/test/v4l2_videodevice/controls.cpp @@ -26,27 +26,27 @@ public: protected: int run() { - const ControlInfoMap &info = capture_->controls(); + const ControlInfoMap &infoMap = capture_->controls(); /* Test control enumeration. */ - if (info.empty()) { + if (infoMap.empty()) { cerr << "Failed to enumerate controls" << endl; return TestFail; } - if (info.find(V4L2_CID_BRIGHTNESS) == info.end() || - info.find(V4L2_CID_CONTRAST) == info.end() || - info.find(V4L2_CID_SATURATION) == info.end()) { + if (infoMap.find(V4L2_CID_BRIGHTNESS) == infoMap.end() || + infoMap.find(V4L2_CID_CONTRAST) == infoMap.end() || + infoMap.find(V4L2_CID_SATURATION) == infoMap.end()) { cerr << "Missing controls" << endl; return TestFail; } - const ControlRange &brightness = info.find(V4L2_CID_BRIGHTNESS)->second; - const ControlRange &contrast = info.find(V4L2_CID_CONTRAST)->second; - const ControlRange &saturation = info.find(V4L2_CID_SATURATION)->second; + const ControlRange &brightness = infoMap.find(V4L2_CID_BRIGHTNESS)->second; + const ControlRange &contrast = infoMap.find(V4L2_CID_CONTRAST)->second; + const ControlRange &saturation = infoMap.find(V4L2_CID_SATURATION)->second; /* Test getting controls. */ - ControlList ctrls(info); + ControlList ctrls(infoMap); ctrls.set(V4L2_CID_BRIGHTNESS, -1); ctrls.set(V4L2_CID_CONTRAST, -1); ctrls.set(V4L2_CID_SATURATION, -1); From patchwork Mon Mar 9 16:24:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3067 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BEC59628BD for ; Mon, 9 Mar 2020 17:21:28 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 757A86001A for ; Mon, 9 Mar 2020 16:21:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:05 +0100 Message-Id: <20200309162414.720306-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/11] libcamera: controls: Rename ControlRange to ControlInfo X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:28 -0000 From: Laurent Pinchart To prepare for storage of additional information in the ControlRange structure, rename it to ControlInfo. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/ipa/ipa_controls.h | 2 +- include/libcamera/controls.h | 16 ++++---- src/libcamera/control_serializer.cpp | 33 ++++++++------- src/libcamera/controls.cpp | 40 +++++++++---------- src/libcamera/include/control_serializer.h | 6 +-- src/libcamera/include/v4l2_controls.h | 4 +- src/libcamera/ipa_controls.cpp | 38 +++++++++--------- src/libcamera/pipeline/uvcvideo.cpp | 4 +- src/libcamera/pipeline/vimc.cpp | 4 +- src/libcamera/v4l2_controls.cpp | 30 +++++++------- src/libcamera/v4l2_device.cpp | 2 +- .../{control_range.cpp => control_info.cpp} | 10 ++--- test/controls/meson.build | 2 +- test/serialization/serialization_test.cpp | 4 +- test/v4l2_videodevice/controls.cpp | 6 +-- 15 files changed, 100 insertions(+), 101 deletions(-) rename test/controls/{control_range.cpp => control_info.cpp} (83%) diff --git a/include/ipa/ipa_controls.h b/include/ipa/ipa_controls.h index 37f97d6ad2a4..6d3bf279c22d 100644 --- a/include/ipa/ipa_controls.h +++ b/include/ipa/ipa_controls.h @@ -33,7 +33,7 @@ struct ipa_control_value_entry { uint32_t padding[1]; }; -struct ipa_control_range_entry { +struct ipa_control_info_entry { uint32_t id; uint32_t type; uint32_t offset; diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 3d2250f43f3c..9c6cbffb88b5 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -229,12 +229,12 @@ private: Control &operator=(const Control &) = delete; }; -class ControlRange +class ControlInfo { public: - explicit ControlRange(const ControlValue &min = 0, - const ControlValue &max = 0, - const ControlValue &def = 0); + explicit ControlInfo(const ControlValue &min = 0, + const ControlValue &max = 0, + const ControlValue &def = 0); const ControlValue &min() const { return min_; } const ControlValue &max() const { return max_; } @@ -242,12 +242,12 @@ public: std::string toString() const; - bool operator==(const ControlRange &other) const + bool operator==(const ControlInfo &other) const { return min_ == other.min_ && max_ == other.max_; } - bool operator!=(const ControlRange &other) const + bool operator!=(const ControlInfo &other) const { return !(*this == other); } @@ -260,10 +260,10 @@ private: using ControlIdMap = std::unordered_map; -class ControlInfoMap : private std::unordered_map +class ControlInfoMap : private std::unordered_map { public: - using Map = std::unordered_map; + using Map = std::unordered_map; ControlInfoMap() = default; ControlInfoMap(const ControlInfoMap &other) = default; diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index dcc63d20c06c..eef875f4d96c 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -99,9 +99,9 @@ size_t ControlSerializer::binarySize(const ControlValue &value) return value.data().size_bytes(); } -size_t ControlSerializer::binarySize(const ControlRange &range) +size_t ControlSerializer::binarySize(const ControlInfo &info) { - return binarySize(range.min()) + binarySize(range.max()); + return binarySize(info.min()) + binarySize(info.max()); } /** @@ -116,7 +116,7 @@ size_t ControlSerializer::binarySize(const ControlRange &range) size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap) { size_t size = sizeof(struct ipa_controls_header) - + infoMap.size() * sizeof(struct ipa_control_range_entry); + + infoMap.size() * sizeof(struct ipa_control_info_entry); for (const auto &ctrl : infoMap) size += binarySize(ctrl.second); @@ -150,11 +150,10 @@ void ControlSerializer::store(const ControlValue &value, buffer.write(value.data()); } -void ControlSerializer::store(const ControlRange &range, - ByteStreamBuffer &buffer) +void ControlSerializer::store(const ControlInfo &info, ByteStreamBuffer &buffer) { - store(range.min(), buffer); - store(range.max(), buffer); + store(info.min(), buffer); + store(info.max(), buffer); } /** @@ -176,7 +175,7 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap, { /* Compute entries and data required sizes. */ size_t entriesSize = infoMap.size() - * sizeof(struct ipa_control_range_entry); + * sizeof(struct ipa_control_info_entry); size_t valuesSize = 0; for (const auto &ctrl : infoMap) valuesSize += binarySize(ctrl.second); @@ -200,15 +199,15 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap, for (const auto &ctrl : infoMap) { const ControlId *id = ctrl.first; - const ControlRange &range = ctrl.second; + const ControlInfo &info = ctrl.second; - struct ipa_control_range_entry entry; + struct ipa_control_info_entry entry; entry.id = id->id(); entry.type = id->type(); entry.offset = values.offset(); entries.write(&entry); - store(range, values); + store(info, values); } if (buffer.overflow()) @@ -343,13 +342,13 @@ ControlValue ControlSerializer::loadControlValue(ControlType type, return ControlValue(); } -ControlRange ControlSerializer::loadControlRange(ControlType type, - ByteStreamBuffer &b) +ControlInfo ControlSerializer::loadControlInfo(ControlType type, + ByteStreamBuffer &b) { ControlValue min = loadControlValue(type, b); ControlValue max = loadControlValue(type, b); - return ControlRange(min, max); + return ControlInfo(min, max); } /** @@ -397,7 +396,7 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & ControlInfoMap::Map ctrls; for (unsigned int i = 0; i < hdr->entries; ++i) { - const struct ipa_control_range_entry *entry = + const struct ipa_control_info_entry *entry = entries.read(); if (!entry) { LOG(Serializer, Error) << "Out of data"; @@ -419,9 +418,9 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & return {}; } - /* Create and store the ControlRange. */ + /* Create and store the ControlInfo. */ ctrls.emplace(controlIds_.back().get(), - loadControlRange(type, values)); + loadControlInfo(type, values)); } /* diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 833a436c64df..53649fe897db 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -414,50 +414,50 @@ void ControlValue::set(ControlType type, bool isArray, const void *data, */ /** - * \class ControlRange + * \class ControlInfo * \brief Describe the limits of valid values for a Control * - * The ControlRange expresses the constraints on valid values for a control. + * The ControlInfo expresses the constraints on valid values for a control. * The constraints depend on the object the control applies to, and are * constant for the lifetime of that object. They are typically constructed by * pipeline handlers to describe the controls they support. */ /** - * \brief Construct a ControlRange with minimum and maximum range parameters + * \brief Construct a ControlInfo with minimum and maximum range parameters * \param[in] min The control minimum value * \param[in] max The control maximum value * \param[in] def The control default value */ -ControlRange::ControlRange(const ControlValue &min, - const ControlValue &max, - const ControlValue &def) +ControlInfo::ControlInfo(const ControlValue &min, + const ControlValue &max, + const ControlValue &def) : min_(min), max_(max), def_(def) { } /** - * \fn ControlRange::min() + * \fn ControlInfo::min() * \brief Retrieve the minimum value of the control * \return A ControlValue with the minimum value for the control */ /** - * \fn ControlRange::max() + * \fn ControlInfo::max() * \brief Retrieve the maximum value of the control * \return A ControlValue with the maximum value for the control */ /** - * \fn ControlRange::def() + * \fn ControlInfo::def() * \brief Retrieve the default value of the control * \return A ControlValue with the default value for the control */ /** - * \brief Provide a string representation of the ControlRange + * \brief Provide a string representation of the ControlInfo */ -std::string ControlRange::toString() const +std::string ControlInfo::toString() const { std::stringstream ss; @@ -467,15 +467,15 @@ std::string ControlRange::toString() const } /** - * \fn bool ControlRange::operator==() - * \brief Compare ControlRange instances for equality - * \return True if the ranges have identical min and max, false otherwise + * \fn bool ControlInfo::operator==() + * \brief Compare ControlInfo instances for equality + * \return True if the constraints have identical min and max, false otherwise */ /** - * \fn bool ControlRange::operator!=() - * \brief Compare ControlRange instances for non equality - * \return False if the ranges have identical min and max, true otherwise + * \fn bool ControlInfo::operator!=() + * \brief Compare ControlInfo instances for non equality + * \return True if the constraints have different min and max, false otherwise */ /** @@ -489,10 +489,10 @@ std::string ControlRange::toString() const /** * \class ControlInfoMap - * \brief A map of ControlId to ControlRange + * \brief A map of ControlId to ControlInfo * * The ControlInfoMap class describes controls supported by an object as an - * unsorted map of ControlId pointers to ControlRange instances. Unlike the + * unsorted map of ControlId pointers to ControlInfo instances. Unlike the * standard std::unsorted_map<> class, it is designed the be immutable once * constructed, and thus only exposes the read accessors of the * std::unsorted_map<> base class. @@ -656,7 +656,7 @@ void ControlInfoMap::generateIdmap() if (ctrl.first->type() != ctrl.second.min().type()) { LOG(Controls, Error) << "Control " << utils::hex(ctrl.first->id()) - << " type and range type mismatch"; + << " type and info type mismatch"; idmap_.clear(); clear(); return; diff --git a/src/libcamera/include/control_serializer.h b/src/libcamera/include/control_serializer.h index 026e62340328..70aa28fd5f58 100644 --- a/src/libcamera/include/control_serializer.h +++ b/src/libcamera/include/control_serializer.h @@ -35,17 +35,17 @@ public: private: static size_t binarySize(const ControlValue &value); - static size_t binarySize(const ControlRange &range); + static size_t binarySize(const ControlInfo &info); static void store(const ControlValue &value, ByteStreamBuffer &buffer); - static void store(const ControlRange &range, ByteStreamBuffer &buffer); + static void store(const ControlInfo &info, ByteStreamBuffer &buffer); template ControlValue loadControlValue(ByteStreamBuffer &buffer, bool isArray, unsigned int count); ControlValue loadControlValue(ControlType type, ByteStreamBuffer &buffer, bool isArray = false, unsigned int count = 1); - ControlRange loadControlRange(ControlType type, ByteStreamBuffer &buffer); + ControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer); unsigned int serial_; std::vector> controlIds_; diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index 882546a89340..cffe9efd9919 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -20,10 +20,10 @@ public: V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl); }; -class V4L2ControlRange : public ControlRange +class V4L2ControlInfo : public ControlInfo { public: - V4L2ControlRange(const struct v4l2_query_ext_ctrl &ctrl); + V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl); }; } /* namespace libcamera */ diff --git a/src/libcamera/ipa_controls.cpp b/src/libcamera/ipa_controls.cpp index da4724b178e2..b1d14190e3fe 100644 --- a/src/libcamera/ipa_controls.cpp +++ b/src/libcamera/ipa_controls.cpp @@ -18,7 +18,7 @@ * transfer them through the IPA C interface and IPA IPC transports. * * A control packet contains a list of entries, each of them describing a single - * control range or control value. The packet starts with a fixed-size header + * control info or control value. The packet starts with a fixed-size header * described by the ipa_controls_header structure, followed by an array of * fixed-size entries. Each entry is associated with data, stored either * directly in the entry, or in a data section after the entries array. @@ -79,19 +79,19 @@ * | | | | | * \ | | | | * +-------------------------+ | | - * / | ipa_control_range_entry | | hdr.data_offset | + * / | ipa_control_info_entry | | hdr.data_offset | * | | #0 | | | * Control | +-------------------------+ | | - * range | | ... | | | + * info | | ... | | | * entries | +-------------------------+ | | - * | | ipa_control_range_entry | | hdr.size | + * | | ipa_control_info_entry | | hdr.size | * \ | #hdr.entries - 1 | | | * +-------------------------+ | | * | empty space (optional) | | | * +-------------------------+ <--´ . | * / | ... | | entry[n].offset | * Data | | ... | | | - * section | | range data for entry #n | <-----´ | + * section | | info data for entry #n | <-----´ | * \ | ... | | * +-------------------------+ | * | empty space (optional) | | @@ -100,8 +100,8 @@ * * The packet header is identical to the ControlList packet header. * - * Entries are described by the ipa_control_range_entry structure. They contain - * the numerical ID and type of the control. The control range data is stored + * Entries are described by the ipa_control_info_entry structure. They contain + * the numerical ID and type of the control. The control info data is stored * in the data section as described by the following diagram. * * ~~~~ @@ -117,10 +117,10 @@ * ~~~~ * * The minimum and maximum value are stored in the platform's native data - * format. The ipa_control_range_entry::offset field stores the offset from the - * beginning of the data section to the range data. + * format. The ipa_control_info_entry::offset field stores the offset from the + * beginning of the data section to the info data. * - * Range data in the data section shall be stored in the same order as the + * Info data in the data section shall be stored in the same order as the * entries array, shall be aligned to a multiple of 8 bytes, and shall be * contiguous in memory. * @@ -178,18 +178,18 @@ static_assert(sizeof(ipa_control_value_entry) == 16, "Invalid ABI size change for struct ipa_control_value_entry"); /** - * \struct ipa_control_range_entry - * \brief Description of a serialized ControlRange entry - * \var ipa_control_range_entry::id + * \struct ipa_control_info_entry + * \brief Description of a serialized ControlInfo entry + * \var ipa_control_info_entry::id * The numerical ID of the control - * \var ipa_control_range_entry::type + * \var ipa_control_info_entry::type * The type of the control (defined by enum ControlType) - * \var ipa_control_range_entry::offset + * \var ipa_control_info_entry::offset * The offset in bytes from the beginning of the data section to the control - * range data (shall be a multiple of 8 bytes) - * \var ipa_control_range_entry::padding + * info data (shall be a multiple of 8 bytes) + * \var ipa_control_info_entry::padding * Padding bytes (shall be set to 0) */ -static_assert(sizeof(ipa_control_range_entry) == 16, - "Invalid ABI size change for struct ipa_control_range_entry"); +static_assert(sizeof(ipa_control_info_entry) == 16, + "Invalid ABI size change for struct ipa_control_info_entry"); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 29afb121aa46..24abc986112f 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -342,7 +342,7 @@ int UVCCameraData::init(MediaEntity *entity) ControlInfoMap::Map ctrls; for (const auto &ctrl : controls) { - const ControlRange &range = ctrl.second; + const ControlInfo &info = ctrl.second; const ControlId *id; switch (ctrl.first->id()) { @@ -365,7 +365,7 @@ int UVCCameraData::init(MediaEntity *entity) continue; } - ctrls.emplace(id, range); + ctrls.emplace(id, info); } controlInfo_ = std::move(ctrls); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 5d3d12fef30b..529909714bf5 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -431,7 +431,7 @@ int VimcCameraData::init(MediaDevice *media) ControlInfoMap::Map ctrls; for (const auto &ctrl : controls) { - const ControlRange &range = ctrl.second; + const ControlInfo &info = ctrl.second; const ControlId *id; switch (ctrl.first->id()) { @@ -448,7 +448,7 @@ int VimcCameraData::init(MediaDevice *media) continue; } - ctrls.emplace(id, range); + ctrls.emplace(id, info); } controlInfo_ = std::move(ctrls); diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 7446c3880330..4861f9778df3 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -104,37 +104,37 @@ V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl) } /** - * \class V4L2ControlRange - * \brief Convenience specialisation of ControlRange for V4L2 controls + * \class V4L2ControlInfo + * \brief Convenience specialisation of ControlInfo for V4L2 controls * - * The V4L2ControlRange class is a specialisation of the ControlRange for V4L2 + * The V4L2ControlInfo class is a specialisation of the ControlInfo for V4L2 * controls. It offers a convenience constructor from a struct - * v4l2_query_ext_ctrl, and is otherwise equivalent to the ControlRange class. + * v4l2_query_ext_ctrl, and is otherwise equivalent to the ControlInfo class. */ /** - * \brief Construct a V4L2ControlRange from a struct v4l2_query_ext_ctrl + * \brief Construct a V4L2ControlInfo from a struct v4l2_query_ext_ctrl * \param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel */ -V4L2ControlRange::V4L2ControlRange(const struct v4l2_query_ext_ctrl &ctrl) +V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) { switch (ctrl.type) { case V4L2_CTRL_TYPE_BOOLEAN: - ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum), - static_cast(ctrl.default_value))); + ControlInfo::operator=(ControlInfo(static_cast(ctrl.minimum), + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; case V4L2_CTRL_TYPE_INTEGER64: - ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum), - static_cast(ctrl.default_value))); + ControlInfo::operator=(ControlInfo(static_cast(ctrl.minimum), + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; default: - ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum), - static_cast(ctrl.default_value))); + ControlInfo::operator=(ControlInfo(static_cast(ctrl.minimum), + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; } } diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 1698d2451449..98639bd0f07f 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -381,7 +381,7 @@ void V4L2Device::listControls() } controlIds_.emplace_back(std::make_unique(ctrl)); - ctrls.emplace(controlIds_.back().get(), V4L2ControlRange(ctrl)); + ctrls.emplace(controlIds_.back().get(), V4L2ControlInfo(ctrl)); } controls_ = std::move(ctrls); diff --git a/test/controls/control_range.cpp b/test/controls/control_info.cpp similarity index 83% rename from test/controls/control_range.cpp rename to test/controls/control_info.cpp index 06ec3506ee62..1e05e13129ca 100644 --- a/test/controls/control_range.cpp +++ b/test/controls/control_info.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * control_range.cpp - ControlRange tests + * control_info.cpp - ControlInfo tests */ #include @@ -15,7 +15,7 @@ using namespace std; using namespace libcamera; -class ControlRangeTest : public Test +class ControlInfoTest : public Test { protected: int run() @@ -24,7 +24,7 @@ protected: * Test information retrieval from a range with no minimum and * maximum. */ - ControlRange brightness; + ControlInfo brightness; if (brightness.min().get() != 0 || brightness.max().get() != 0) { @@ -36,7 +36,7 @@ protected: * Test information retrieval from a control with a minimum and * a maximum value. */ - ControlRange contrast(10, 200); + ControlInfo contrast(10, 200); if (contrast.min().get() != 10 || contrast.max().get() != 200) { @@ -48,4 +48,4 @@ protected: } }; -TEST_REGISTER(ControlRangeTest) +TEST_REGISTER(ControlInfoTest) diff --git a/test/controls/meson.build b/test/controls/meson.build index 16a7f33fdcc6..7fff2413007e 100644 --- a/test/controls/meson.build +++ b/test/controls/meson.build @@ -1,7 +1,7 @@ control_tests = [ + [ 'control_info', 'control_info.cpp' ], [ 'control_info_map', 'control_info_map.cpp' ], [ 'control_list', 'control_list.cpp' ], - [ 'control_range', 'control_range.cpp' ], [ 'control_value', 'control_value.cpp' ], ] diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp index 68e0512a04ca..11d0f0f30031 100644 --- a/test/serialization/serialization_test.cpp +++ b/test/serialization/serialization_test.cpp @@ -22,7 +22,7 @@ using namespace libcamera; bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs) { - std::map rlhs; + std::map rlhs; std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), [](const ControlInfoMap::value_type &v) -> decltype(rlhs)::value_type @@ -30,7 +30,7 @@ bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap & return { v.first->id(), v.second }; }); - std::map rrhs; + std::map rrhs; std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), [](const ControlInfoMap::value_type &v) -> decltype(rrhs)::value_type diff --git a/test/v4l2_videodevice/controls.cpp b/test/v4l2_videodevice/controls.cpp index 1b71bf0633b4..478de3707a3c 100644 --- a/test/v4l2_videodevice/controls.cpp +++ b/test/v4l2_videodevice/controls.cpp @@ -41,9 +41,9 @@ protected: return TestFail; } - const ControlRange &brightness = infoMap.find(V4L2_CID_BRIGHTNESS)->second; - const ControlRange &contrast = infoMap.find(V4L2_CID_CONTRAST)->second; - const ControlRange &saturation = infoMap.find(V4L2_CID_SATURATION)->second; + const ControlInfo &brightness = infoMap.find(V4L2_CID_BRIGHTNESS)->second; + const ControlInfo &contrast = infoMap.find(V4L2_CID_CONTRAST)->second; + const ControlInfo &saturation = infoMap.find(V4L2_CID_SATURATION)->second; /* Test getting controls. */ ControlList ctrls(infoMap); From patchwork Mon Mar 9 16:24:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3068 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A27262938 for ; Mon, 9 Mar 2020 17:21:29 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id E01DE60008 for ; Mon, 9 Mar 2020 16:21:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:06 +0100 Message-Id: <20200309162414.720306-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/11] libcamera: controls: Add support for string controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:29 -0000 From: Laurent Pinchart 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 | 35 ++++++++++++++++++++++++---- src/libcamera/gen-controls.py | 18 +++++++------- 4 files changed, 87 insertions(+), 18 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 9c6cbffb88b5..5cf6280e612b 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 eef875f4d96c..808419f246c0 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 53649fe897db..68d040db4daa 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 */ @@ -74,8 +75,8 @@ static constexpr size_t ControlValueSize[] = { * The control stores a 32-bit integer value * \var ControlTypeInteger64 * 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 +165,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 +194,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 +229,7 @@ std::string ControlValue::toString() const break; } case ControlTypeNone: + case ControlTypeString: break; } @@ -439,12 +447,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 +671,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 ff8bda6b16c1..87c3d52ada6d 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, From patchwork Mon Mar 9 16:24:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3069 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 975DB62938 for ; Mon, 9 Mar 2020 17:21:29 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 5595060008 for ; Mon, 9 Mar 2020 16:21:29 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:07 +0100 Message-Id: <20200309162414.720306-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/11] test: controls: control_value: Test string control type X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:31 -0000 From: Laurent Pinchart Add test cases for the string control type. As strings are implemented as char arrays, arrays of strings are not supported. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- test/controls/control_value.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/controls/control_value.cpp b/test/controls/control_value.cpp index a7ebf60f6a6a..ad8e05d0b1a9 100644 --- a/test/controls/control_value.cpp +++ b/test/controls/control_value.cpp @@ -235,6 +235,28 @@ protected: return TestFail; } + /* + * String type. + */ + std::string string{ "libcamera" }; + value.set(string); + if (value.isNone() || !value.isArray() || + value.type() != ControlTypeString || + value.numElements() != string.size()) { + cerr << "Control type mismatch after setting to string" << endl; + return TestFail; + } + + if (value.get() != string) { + cerr << "Control value mismatch after setting to string" << endl; + return TestFail; + } + + if (value.toString() != string) { + cerr << "Control string mismatch after setting to string" << endl; + return TestFail; + } + return TestPass; } }; From patchwork Mon Mar 9 16:24:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3070 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 14BEB6292C for ; Mon, 9 Mar 2020 17:21:30 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id BB22460019 for ; Mon, 9 Mar 2020 16:21:29 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:08 +0100 Message-Id: <20200309162414.720306-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/11] libcamera: v4l2_controls: Fix usage of strerror() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:32 -0000 On failure, the return code from V4L2Device::ioctl() is the negative error code set by the failed ::ioctl() system call. When the return code of V4L2Device::ioctl() is provided to strerror() it has to be negated again to obtain the positive error code. Fix a few wrong usages of the return code which provided to the strerror() function a negative error code. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/v4l2_device.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 98639bd0f07f..179476e9afad 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -201,13 +201,13 @@ int V4L2Device::getControls(ControlList *ctrls) /* Generic validation error. */ if (errorIdx == 0 || errorIdx >= count) { LOG(V4L2, Error) << "Unable to read controls: " - << strerror(ret); + << strerror(-ret); return -EINVAL; } /* A specific control failed. */ LOG(V4L2, Error) << "Unable to read control " << errorIdx - << ": " << strerror(ret); + << ": " << strerror(-ret); count = errorIdx - 1; ret = errorIdx; } @@ -291,13 +291,13 @@ int V4L2Device::setControls(ControlList *ctrls) /* Generic validation error. */ if (errorIdx == 0 || errorIdx >= count) { LOG(V4L2, Error) << "Unable to set controls: " - << strerror(ret); + << strerror(-ret); return -EINVAL; } /* A specific control failed. */ LOG(V4L2, Error) << "Unable to set control " << errorIdx - << ": " << strerror(ret); + << ": " << strerror(-ret); count = errorIdx - 1; ret = errorIdx; } From patchwork Mon Mar 9 16:24:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3071 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6B4026293C for ; Mon, 9 Mar 2020 17:21:30 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 38EC360019 for ; Mon, 9 Mar 2020 16:21:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:09 +0100 Message-Id: <20200309162414.720306-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/11] libcamera: v4l2_controls: Cache query control information X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:32 -0000 Cache the V4L2 control info retrieved with VIDIOC_QUERY_EXT_CTRL at control listing time for later use. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/include/v4l2_device.h | 1 + src/libcamera/v4l2_device.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 6bfddefe336c..e1fd048cc85a 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -48,6 +48,7 @@ private: const struct v4l2_ext_control *v4l2Ctrls, unsigned int count); + std::map ctrlsInfo_; std::vector> controlIds_; ControlInfoMap controls_; std::string deviceNode_; diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 179476e9afad..65e97f92b01f 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -382,6 +382,7 @@ void V4L2Device::listControls() controlIds_.emplace_back(std::make_unique(ctrl)); ctrls.emplace(controlIds_.back().get(), V4L2ControlInfo(ctrl)); + ctrlsInfo_[ctrl.id] = ctrl; } controls_ = std::move(ctrls); From patchwork Mon Mar 9 16:24:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3073 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C71C862923 for ; Mon, 9 Mar 2020 17:21:30 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 90E4F6001C for ; Mon, 9 Mar 2020 16:21:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:10 +0100 Message-Id: <20200309162414.720306-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/11] libcamera: v4l2_device: Support writing array U8 controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:32 -0000 Add support to write array controls of type V4L2_CTRL_TYPE_U8. Signed-off-by: Jacopo Mondi --- src/libcamera/v4l2_device.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 65e97f92b01f..950e6286b84d 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -267,11 +267,25 @@ int V4L2Device::setControls(ControlList *ctrls) case ControlTypeInteger64: v4l2Ctrls[i].value64 = value.get(); break; + case ControlTypeByte: { + if (!value.isArray()) + /* + * \todo This happens if a V4L2_CTRL_TYPE_U8 + * control is set with a non-array ControlValue. + * + * Should we fail loudly here ? + */ + break; + + auto values = value.get>(); + v4l2Ctrls[i].p_u8 = const_cast(values.data()); + v4l2Ctrls[i].size = values.size_bytes(); + + break; + } + default: - /* - * \todo To be changed when support for string and - * compound controls will be added. - */ + /* \todo To be changed to support strings. */ v4l2Ctrls[i].value = value.get(); break; } @@ -413,6 +427,16 @@ void V4L2Device::updateControls(ControlList *ctrls, case ControlTypeInteger64: value.set(v4l2Ctrl->value64); break; + + case ControlTypeByte: { + std::vector data = { + v4l2Ctrl->p_u8, v4l2Ctrl->p_u8 + v4l2Ctrl->size + }; + Span values(data); + value.set>(values); + break; + } + default: /* * \todo To be changed when support for string and From patchwork Mon Mar 9 16:24:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3072 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2338362928 for ; Mon, 9 Mar 2020 17:21:31 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id E4C7D60016 for ; Mon, 9 Mar 2020 16:21:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:11 +0100 Message-Id: <20200309162414.720306-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/11] licamera: v4l2_device: Support reading U8 array controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:32 -0000 Add support to retrieve the value of array controls of type V4L2_CTRL_TYPE_U8. Signed-off-by: Jacopo Mondi --- src/libcamera/v4l2_device.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 950e6286b84d..464df6a1fe18 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -185,6 +185,22 @@ int V4L2Device::getControls(ControlList *ctrls) return -EINVAL; } + const struct v4l2_query_ext_ctrl &info = ctrlsInfo_[id]; + if (info.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { + if (info.type != V4L2_CTRL_TYPE_U8) { + /* + * \todo Fail loudly to notify support for + * other array control types is not implemented. + */ + LOG(V4L2, Error) << "Unsupported type"; + return -EINVAL; + } + + size_t sizeBytes = info.elems * info.elem_size; + v4l2Ctrls[i].p_u8 = new uint8_t[sizeBytes]; + v4l2Ctrls[i].size = sizeBytes; + } + v4l2Ctrls[i].id = id; i++; } @@ -214,6 +230,16 @@ int V4L2Device::getControls(ControlList *ctrls) updateControls(ctrls, v4l2Ctrls, count); + /* Release memory reserved for array controls. */ + for (unsigned int i = 0; i < count; i++) { + unsigned int id = v4l2Ctrls[i].id; + const struct v4l2_query_ext_ctrl &info = ctrlsInfo_[id]; + + /* \todo Adjust to support more array control types. */ + if (info.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) + delete[] v4l2Ctrls[i].p_u8; + } + return ret; } From patchwork Mon Mar 9 16:24:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3074 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 88C7E62930 for ; Mon, 9 Mar 2020 17:21:31 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 4313760008 for ; Mon, 9 Mar 2020 16:21:31 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:12 +0100 Message-Id: <20200309162414.720306-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/11] libcamera: v4l2_controls: Support U8 array controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:32 -0000 Add support for array controls of type V4L2_CTRL_TYPE_U8. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/v4l2_controls.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 4861f9778df3..8e2415f2a6df 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -60,6 +60,9 @@ std::string v4l2_ctrl_name(const struct v4l2_query_ext_ctrl &ctrl) ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl) { switch (ctrl.type) { + case V4L2_CTRL_TYPE_U8: + return ControlTypeByte; + case V4L2_CTRL_TYPE_BOOLEAN: return ControlTypeBool; @@ -119,6 +122,12 @@ V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl) V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) { switch (ctrl.type) { + case V4L2_CTRL_TYPE_U8: + ControlInfo::operator=(ControlInfo(static_cast(ctrl.minimum), + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); + break; + case V4L2_CTRL_TYPE_BOOLEAN: ControlInfo::operator=(ControlInfo(static_cast(ctrl.minimum), static_cast(ctrl.maximum), From patchwork Mon Mar 9 16:24:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3075 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 00B9362938 for ; Mon, 9 Mar 2020 17:21:32 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id B7E4C60008 for ; Mon, 9 Mar 2020 16:21:31 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:13 +0100 Message-Id: <20200309162414.720306-11-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/11] libcamera: v4l2_device: Enable enumeration of U8 controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:33 -0000 Enable the enumeration of V4L2 array controls with V4L2_CTRL_TYPE_U8 type. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/v4l2_device.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 464df6a1fe18..a36c121aa62a 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -388,7 +388,8 @@ void V4L2Device::listControls() /* \todo Add support for menu and compound controls. */ while (1) { - ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; + ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | + V4L2_CTRL_FLAG_NEXT_COMPOUND; if (ioctl(VIDIOC_QUERY_EXT_CTRL, &ctrl)) break; @@ -396,13 +397,6 @@ void V4L2Device::listControls() ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; - if (ctrl.elems != 1 || ctrl.nr_of_dims) { - LOG(V4L2, Debug) - << "Array control " << utils::hex(ctrl.id) - << " not supported"; - continue; - } - switch (ctrl.type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: @@ -411,8 +405,9 @@ void V4L2Device::listControls() case V4L2_CTRL_TYPE_INTEGER64: case V4L2_CTRL_TYPE_BITMASK: case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_U8: break; - /* \todo Support compound controls. */ + /* \todo Support other control types. */ default: LOG(V4L2, Debug) << "Control " << utils::hex(ctrl.id) From patchwork Mon Mar 9 16:24:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3076 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8091C62940 for ; Mon, 9 Mar 2020 17:21:32 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 2D25E60015 for ; Mon, 9 Mar 2020 16:21:31 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 17:24:14 +0100 Message-Id: <20200309162414.720306-12-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309162414.720306-1-jacopo@jmondi.org> References: <20200309162414.720306-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 11/11] test: v4l2_videodevice: Test U8 array controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Mar 2020 16:21:33 -0000 Test V4L2 array control using vivid control VIVID_CID_U8_4D_ARRAY. Signed-off-by: Jacopo Mondi --- test/v4l2_videodevice/controls.cpp | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/test/v4l2_videodevice/controls.cpp b/test/v4l2_videodevice/controls.cpp index 478de3707a3c..e2601b7594bb 100644 --- a/test/v4l2_videodevice/controls.cpp +++ b/test/v4l2_videodevice/controls.cpp @@ -5,6 +5,7 @@ * controls.cpp - V4L2 device controls handling test */ +#include #include #include @@ -12,6 +13,13 @@ #include "v4l2_videodevice_test.h" +/* These come from the vivid driver */ +#define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) +#define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10) + +/* Helper for VIVID_CID_U8_4D_ARRAY control array size: not from kernel. */ +#define VIVID_CID_U8_ARRAY_SIZE (2 * 3 * 4 * 5) + using namespace std; using namespace libcamera; @@ -36,7 +44,8 @@ protected: if (infoMap.find(V4L2_CID_BRIGHTNESS) == infoMap.end() || infoMap.find(V4L2_CID_CONTRAST) == infoMap.end() || - infoMap.find(V4L2_CID_SATURATION) == infoMap.end()) { + infoMap.find(V4L2_CID_SATURATION) == infoMap.end() || + infoMap.find(VIVID_CID_U8_4D_ARRAY) == infoMap.end()) { cerr << "Missing controls" << endl; return TestFail; } @@ -44,6 +53,7 @@ protected: const ControlInfo &brightness = infoMap.find(V4L2_CID_BRIGHTNESS)->second; const ControlInfo &contrast = infoMap.find(V4L2_CID_CONTRAST)->second; const ControlInfo &saturation = infoMap.find(V4L2_CID_SATURATION)->second; + const ControlInfo &u8 = infoMap.find(VIVID_CID_U8_4D_ARRAY)->second; /* Test getting controls. */ ControlList ctrls(infoMap); @@ -51,6 +61,10 @@ protected: ctrls.set(V4L2_CID_CONTRAST, -1); ctrls.set(V4L2_CID_SATURATION, -1); + std::array u8Values; + Span u8Span(u8Values); + ctrls.set(VIVID_CID_U8_4D_ARRAY, u8Span); + int ret = capture_->getControls(&ctrls); if (ret) { cerr << "Failed to get controls" << endl; @@ -64,11 +78,26 @@ protected: return TestFail; } + u8Span = ctrls.get(VIVID_CID_U8_4D_ARRAY).get>(); + for (unsigned int i = 0; i < VIVID_CID_U8_ARRAY_SIZE; ++i) { + if (u8Span[i] != 0) + continue; + + cerr << "Incorrect value for retrieved array control" + << endl; + return TestFail; + } + /* Test setting controls. */ ctrls.set(V4L2_CID_BRIGHTNESS, brightness.min()); ctrls.set(V4L2_CID_CONTRAST, contrast.max()); ctrls.set(V4L2_CID_SATURATION, saturation.min()); + for (unsigned int i = 0; i < VIVID_CID_U8_ARRAY_SIZE; ++i) + u8Values[i] = u8.min().get(); + u8Span = u8Values; + ctrls.set(VIVID_CID_U8_4D_ARRAY, u8Span); + ret = capture_->setControls(&ctrls); if (ret) { cerr << "Failed to set controls" << endl;