From patchwork Mon Oct 7 22:46:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2129 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B5E2961966 for ; Tue, 8 Oct 2019 00:46:51 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D44FEB2E for ; Tue, 8 Oct 2019 00:46:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488411; bh=IxLRHr79EuWaBR9GOp4FgtsR3K5J2Sj37RJ+4GRv4Is=; h=From:To:Subject:Date:In-Reply-To:References:From; b=mHJdgOBvmY6tHmn68B0T2UrBgtU2ZH684A4nqyL1lKaFzOrAPWLKCpE+sb/tSuSl1 02Zv0KIzXHyxI5cbpYWJG6VZiKLPg2qDAOhyCStkgxk37SJoexyH1frwyl1TlRG7b7 PjvOTcKZPummzGFtYSk9BzC91jFPFtp2XYnj+S8o= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:34 +0300 Message-Id: <20191007224642.6597-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/9] libcamera: control_ids: Generate map of all supported 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, 07 Oct 2019 22:46:51 -0000 In order to deserialise a ControlList, we will need to lookup ControlId instances based on their numerical ID. Generate a global map from the controls definitions to support such a lookup. Signed-off-by: Laurent Pinchart --- include/libcamera/control_ids.h.in | 3 +++ src/libcamera/control_ids.cpp.in | 7 +++++++ src/libcamera/gen-controls.py | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index 1d0bc791e559..30b2bae8a9ae 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -10,6 +10,7 @@ #ifndef __LIBCAMERA_CONTROL_IDS_H__ #define __LIBCAMERA_CONTROL_IDS_H__ +#include #include #include @@ -24,6 +25,8 @@ ${ids} ${controls} +extern const std::map controls; + } /* namespace controls */ } /* namespace libcamera */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index f699ac9eea54..f0656d3147b1 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -20,6 +20,13 @@ namespace controls { ${controls} +/** + * \brief List of all supported libcamera controls + */ +extern const std::map controls { +${controls_map} +}; + } /* namespace controls */ } /* namespace libcamera */ diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py index 0899e40b4080..0c4bd79eee5b 100755 --- a/src/libcamera/gen-controls.py +++ b/src/libcamera/gen-controls.py @@ -23,6 +23,7 @@ ${description} extern const Control<${type}> ${name}(${id_name}, "${name}");''') ctrls = [] + ctrls_map = [] for ctrl in controls: name, ctrl = ctrl.popitem() @@ -40,8 +41,12 @@ extern const Control<${type}> ${name}(${id_name}, "${name}");''') } ctrls.append(template.substitute(info)) + ctrls_map.append('\t{ ' + id_name + ', &' + name + ' },') - return {'controls': '\n\n'.join(ctrls)} + return { + 'controls': '\n\n'.join(ctrls), + 'controls_map': '\n'.join(ctrls_map), + } def generate_h(controls): From patchwork Mon Oct 7 22:46:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2130 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B764560E1F for ; Tue, 8 Oct 2019 00:46:52 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D8A8AB2D for ; Tue, 8 Oct 2019 00:46:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488412; bh=l7hpykS7uvEgF6n4GRYEzSmexVZKkNXXwkjQMQ9sanY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=fqx2TNzQJwROO85aGJHCNvRVDfGp2CDQR46+9xDDgbTQbtNS/Amv7goupFnUe/ftU IogNbMg4bVIKk4xL4XBnMey4TLa0DausB70sYEUfyWJgcOf8AGpnP/73+ANosTfqx5 FUwo1oJ5k3xMxGmCJQXRXlojKLDp/VX1mZ+NzMaU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:35 +0300 Message-Id: <20191007224642.6597-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/9] libcamera: controls: Support getting and setting controls by ControlId 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, 07 Oct 2019 22:46:53 -0000 The ControlList class has template get() and set() methods to get and set control values. The methods require a reference to a Control instance, which is only available when calling them with a hardcoded control. In order to support serialisation and deserialisation of ControlList, we need a way to get and set control values based on a ControlId. Add new get() and set() overload methods to do so. Signed-off-by: Laurent Pinchart --- include/libcamera/controls.h | 3 +++ src/libcamera/controls.cpp | 46 ++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 90426753f40f..49ff1a6f747f 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -156,6 +156,9 @@ public: val->set(value); } + const ControlValue &get(const ControlId &id) const; + void set(const ControlId &id, const ControlValue &value); + private: const ControlValue *find(const ControlId &id) const; ControlValue *find(const ControlId &id); diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index f3260edce0bc..f862a09adef9 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -445,7 +445,7 @@ bool ControlList::contains(const ControlId &id) const */ /** - * \fn template const T &ControlList::get() const + * \fn template const T &ControlList::get(const Control &ctrl) const * \brief Get the value of a control * \param[in] ctrl The control * @@ -460,7 +460,7 @@ bool ControlList::contains(const ControlId &id) const */ /** - * \fn template void ControlList::set() + * \fn template void ControlList::set(const Control< T > &ctrl, const T &value) * \brief Set the control value to \a value * \param[in] ctrl The control * \param[in] value The control value @@ -473,6 +473,48 @@ bool ControlList::contains(const ControlId &id) const * camera that the list refers to. */ +/** + * \brief Get the value of control \a id + * \param[in] id The control ID + * + * The behaviour is undefined if the control \a id is not present in the list. + * Use ControlList::contains() to test for the presence of a control in the + * list before retrieving its value. + * + * \return The control value + */ +const ControlValue &ControlList::get(const ControlId &id) const +{ + const ControlValue *val = find(id); + if (!val) { + static ControlValue zero; + return zero; + } + + return *val; +} + +/** + * \brief Set the value of control \a id to \a value + * \param[in] id The control ID + * \param[in] value The control value + * + * This method sets the value of a control in the control list. If the control + * is already present in the list, its value is updated, otherwise it is added + * to the list. + * + * The behaviour is undefined if the control \a ctrl is not supported by the + * camera that the list refers to. + */ +void ControlList::set(const ControlId &id, const ControlValue &value) +{ + ControlValue *val = find(id); + if (!val) + return; + + *val = value; +} + const ControlValue *ControlList::find(const ControlId &id) const { const auto iter = controls_.find(&id); From patchwork Mon Oct 7 22:46:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2131 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D38B76196D for ; Tue, 8 Oct 2019 00:46:53 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DD8CDB2D for ; Tue, 8 Oct 2019 00:46:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488413; bh=Or7twWIOEHG3Sh66YjvPhV7jDAQxmDeF4WX3kjWOeBQ=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Q5pTExUdclVbmBhpwDorEfH+Db3swQRm6UexUvSbhOfy9wDh9Q7NWOUByer4HnSJ+ BjlRcxuzy0vgZSvAa0mPCWNRbpFHtyr+ZdiKziejrM39wg1xTHl4JuIUJUPASO20u1 D2qSPdB5HovAIi/3encaTisiBO8dbQwfB1fi4zwM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:36 +0300 Message-Id: <20191007224642.6597-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/9] libcamera: controls: Store control name in ControlId 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, 07 Oct 2019 22:46:54 -0000 The ControlId class stores a pointer to the control name. This works fine for statically-defined controls, but requires code that allocates controls dynamically (for instance based on control discovery on a V4L2 device) to keep a list of control names in separate storage. To ease usage of dynamically allocated controls, store a copy of the control name string in the ControlId class. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/controls.h | 6 +++--- src/libcamera/controls.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 49ff1a6f747f..a5a6a135ec16 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -54,11 +54,11 @@ class ControlId { public: unsigned int id() const { return id_; } - const char *name() const { return name_; } + const std::string &name() const { return name_; } ControlType type() const { return type_; } protected: - ControlId(unsigned int id, const char *name, ControlType type) + ControlId(unsigned int id, const std::string &name, ControlType type) : id_(id), name_(name), type_(type) { } @@ -68,7 +68,7 @@ private: ControlId &operator=(const ControlId &) = delete; unsigned int id_; - const char *name_; + std::string name_; ControlType type_; }; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index f862a09adef9..e528dd80a2a7 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -205,7 +205,7 @@ std::string ControlValue::toString() const */ /** - * \fn ControlId::ControlId(unsigned int id, const char *name, ControlType type) + * \fn ControlId::ControlId(unsigned int id, const std::string &name, ControlType type) * \brief Construct a ControlId instance * \param[in] id The control numerical ID * \param[in] name The control name From patchwork Mon Oct 7 22:46:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2132 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B97B561974 for ; Tue, 8 Oct 2019 00:46:54 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E33C3B2E for ; Tue, 8 Oct 2019 00:46:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488414; bh=eGDT+p+P9eWFHXkhfzy2lRVTXwioER1osC4I4X7MPno=; h=From:To:Subject:Date:In-Reply-To:References:From; b=DHRnc7pAW25Wlz3CuQBVTSLknOclkgbfJNP+jYebBvUp51GD3xBfMf1WRXRQDD1Q5 d/lUJwGCNGBUqGehQcGn190oSjcnxRg0dRDwDNoYFtpYYeQBJDPb8woX8wIjapYnGy 2yDhHxLTMWhv3DolFqTPtiNpdEuIq9CKg3BFxKws= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:37 +0300 Message-Id: <20191007224642.6597-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/9] libcamera: controls: Make ControlList::find() protected 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, 07 Oct 2019 22:46:55 -0000 To prepare for Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/controls.h | 3 ++- src/libcamera/controls.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index a5a6a135ec16..fc33f0762138 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -159,10 +159,11 @@ public: const ControlValue &get(const ControlId &id) const; void set(const ControlId &id, const ControlValue &value); -private: +protected: const ControlValue *find(const ControlId &id) const; ControlValue *find(const ControlId &id); +private: ControlValidator *validator_; ControlListMap controls_; }; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index e528dd80a2a7..afea09d6d7d7 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -515,6 +515,13 @@ void ControlList::set(const ControlId &id, const ControlValue &value) *val = value; } +/** + * \brief Find a control in the list + * \param[in] id The control ID + * + * \return The control value for the control \a id, or nullptr if no such + * control exists in the list + */ const ControlValue *ControlList::find(const ControlId &id) const { const auto iter = controls_.find(&id); @@ -528,6 +535,13 @@ const ControlValue *ControlList::find(const ControlId &id) const return &iter->second; } +/** + * \brief Find a control in the list + * \param[in] id The control ID + * + * \return The control value for the control \a id, or nullptr if no such + * control exists in the list + */ ControlValue *ControlList::find(const ControlId &id) { if (validator_ && !validator_->validate(id)) { From patchwork Mon Oct 7 22:46:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2133 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C4D176196D for ; Tue, 8 Oct 2019 00:46:55 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E91F2B2D for ; Tue, 8 Oct 2019 00:46:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488415; bh=GvIit0LxIGNZjzEkjapDquTGQEpfBw0NxtjXXLA+hFY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=pSQ+wzfBsBXRR+iTPCBerDupZLJtsHbOojGqx56e447JELFNUF1SLH5NMj4EzMFLL j1Q1lleYm39mSW4SNVp+5ekrXWulDzAMSoCPsyT89pfmQRS38Mod61avANr2ynCLQN mL+ITwVOCHBAq5omFaY6t9xnQCZX/hWtorCRaeqQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:38 +0300 Message-Id: <20191007224642.6597-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/9] libcamera: v4l2_device: Avoid copy of V4L2ControlInfo 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, 07 Oct 2019 22:46:56 -0000 The V4L2Device::listControls() method creates an instance of V4L2ControlInfo and then inserts it in the device's list of controls. The insertion uses std::map::emplace(), but passes the V4L2ControlInfo, resulting in a copy being performed (using the copy constructor of V4L2ControlInfo). Optimise this by really constructing the V4L2ControlInfo emplace. The use of std::piecewise_construct is required for gcc-5 that seems to have trouble with std::map::emplace() on non-copyable values in this case. Signed-off-by: Laurent Pinchart --- src/libcamera/v4l2_device.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index fd4b9c6d5c62..3bd82ff23212 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -352,8 +352,7 @@ void V4L2Device::listControls() ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; - V4L2ControlInfo info(ctrl); - switch (info.type()) { + switch (ctrl.type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: @@ -364,12 +363,14 @@ void V4L2Device::listControls() break; /* \todo Support compound controls. */ default: - LOG(V4L2, Debug) << "Control type '" << info.type() + LOG(V4L2, Debug) << "Control type '" << ctrl.type << "' not supported"; continue; } - controls_.emplace(ctrl.id, info); + controls_.emplace(std::piecewise_construct, + std::forward_as_tuple(ctrl.id), + std::forward_as_tuple(ctrl)); } } From patchwork Mon Oct 7 22:46:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2134 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FCC961974 for ; Tue, 8 Oct 2019 00:46:56 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EF0A1B2D for ; Tue, 8 Oct 2019 00:46:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488416; bh=DqeXG14ytkkFz0F+Phy0EQ9TMq5xHDAFzIPV+bH9CiI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=tQz1S00RYC1UVeNGLXF7libtAyUAZE0oGnOc/LlQl8UkRacV716DeC87ZGa8d2h5o nBckGlugeGKpOcG2oLD6sbCjlabYJ6Ll2OD0SXdS6PBhZZMLplKRnn2lbEEKRBiQfX 2Xh6x7J3bl4xRnjAqLYnF/KKxHv1UdNj2H0DC2yU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:39 +0300 Message-Id: <20191007224642.6597-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 6/9] libcamera: v4l2_controls: Add V4L2ControlId 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, 07 Oct 2019 22:46:56 -0000 Add a V4L2 specialisation of the ControlId class, in order to construct a ControlId from a v4l2_query_ext_ctrl. This is needed in order to use ControlList for V4L2 controls. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/include/v4l2_controls.h | 12 +++-- src/libcamera/v4l2_controls.cpp | 67 +++++++++++++++++++++++---- src/libcamera/v4l2_device.cpp | 4 +- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index b39370b2e90e..71ce377fe4c5 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -20,23 +20,27 @@ namespace libcamera { +class V4L2ControlId : public ControlId +{ +public: + V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl); +}; + class V4L2ControlInfo { public: V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl); - unsigned int id() const { return id_; } + const ControlId &id() const { return id_; } unsigned int type() const { return type_; } size_t size() const { return size_; } - const std::string &name() const { return name_; } const ControlRange &range() const { return range_; } private: - unsigned int id_; + V4L2ControlId id_; unsigned int type_; size_t size_; - std::string name_; ControlRange range_; }; diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 6f5f1578b139..a630a2583d33 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -7,6 +7,8 @@ #include "v4l2_controls.h" +#include + /** * \file v4l2_controls.h * \brief Support for V4L2 Controls using the V4L2 Extended Controls APIs @@ -47,6 +49,60 @@ namespace libcamera { +namespace { + +std::string v4l2_ctrl_name(const struct v4l2_query_ext_ctrl &ctrl) +{ + size_t len = strnlen(ctrl.name, sizeof(ctrl.name)); + return std::string(static_cast(ctrl.name), len); +} + +ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl) +{ + switch (ctrl.type) { + case V4L2_CTRL_TYPE_BOOLEAN: + return ControlTypeBool; + + case V4L2_CTRL_TYPE_INTEGER: + return ControlTypeInteger32; + + case V4L2_CTRL_TYPE_INTEGER64: + return ControlTypeInteger64; + + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BUTTON: + case V4L2_CTRL_TYPE_BITMASK: + case V4L2_CTRL_TYPE_INTEGER_MENU: + /* + * More precise types may be needed, for now use a 32-bit + * integer type. + */ + return ControlTypeInteger32; + + default: + return ControlTypeNone; + } +} + +} /* namespace */ + +/** + * \class V4L2ControlId + * \brief V4L2 control static metadata + * + * The V4L2ControlId class is a specialisation of the ControlId for V4L2 + * controls. + */ + +/** + * \brief Construct a V4L2ControlId from a struct v4l2_query_ext_ctrl + * \param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel + */ +V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl) + : ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl)) +{ +} + /** * \class V4L2ControlInfo * \brief Information on a V4L2 control @@ -66,13 +122,12 @@ namespace libcamera { /** * \brief Construct a V4L2ControlInfo from a struct v4l2_query_ext_ctrl - * \param ctrl The struct v4l2_query_ext_ctrl as returned by the kernel + * \param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel */ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) + : id_(ctrl) { - id_ = ctrl.id; type_ = ctrl.type; - name_ = static_cast(ctrl.name); size_ = ctrl.elem_size * ctrl.elems; if (ctrl.type == V4L2_CTRL_TYPE_INTEGER64) @@ -101,12 +156,6 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) * \return The V4L2 control value data size */ -/** - * \fn V4L2ControlInfo::name() - * \brief Retrieve the control user readable name - * \return The V4L2 control user readable name - */ - /** * \fn V4L2ControlInfo::range() * \brief Retrieve the control value range diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 3bd82ff23212..466c3d41f6e3 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -184,7 +184,7 @@ int V4L2Device::getControls(V4L2ControlList *ctrls) const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = info->id(); + v4l2Ctrls[i].id = ctrl->id(); } struct v4l2_ext_controls v4l2ExtCtrls = {}; @@ -259,7 +259,7 @@ int V4L2Device::setControls(V4L2ControlList *ctrls) const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = info->id(); + v4l2Ctrls[i].id = ctrl->id(); /* Set the v4l2_ext_control value for the write operation. */ switch (info->type()) { From patchwork Mon Oct 7 22:46:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2135 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8B7656197C for ; Tue, 8 Oct 2019 00:46:57 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C2CB6B2D for ; Tue, 8 Oct 2019 00:46:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488417; bh=Y1es+fK69192VYzSD/a+Pax3URLNrXz6dXh7MAsJeOY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Fax9S+0SQjr4F+1A9QSPMjDMn2orkOWW5tFAbJkIpNM8gshExJ1jaMjAvkWSje8PS usR2x+xlnEkfBdnMAc/0Toix6uP65JrucHXPCRnrSBu/mPspOHR0aKciMPhMSPDOJF avJ3vbvS76yRPqXFUx01nR7laMmUwwH9ZR+dUqbo= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:40 +0300 Message-Id: <20191007224642.6597-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 7/9] libcamera: v4l2_device: Replace V4L2ControlList with ControlList 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, 07 Oct 2019 22:46:57 -0000 The V4L2Device class uses V4L2ControlList as a controls container for the getControls() and setControls() operations. Having a distinct container from ControlList will make the IPA API more complex, especially when dealing with serialisation and deserialisation, as it will need to explicitly support transporting both types of lists. To simplify the IPA API, replace usage of V4L2ControlList with ControlList in the V4L2Device (and thus CameraSensor) API. ControlList however doesn't support accessing controls by numerical ID, which is a common use case for V4L2 controls in pipeline handlers. To avoid requiring each pipeline handler to map numerical IDs to ControlId instances, turn the existing V4L2ControlList class into a helper derived from ControlList. This allows easy building of a ControlList for a V4L2 device in pipeline handlers, while generalising the use of ControlList everywhere else. Signed-off-by: Laurent Pinchart --- src/libcamera/camera_sensor.cpp | 4 +- src/libcamera/include/camera_sensor.h | 5 +- src/libcamera/include/v4l2_controls.h | 41 +---- src/libcamera/include/v4l2_device.h | 8 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 9 +- src/libcamera/pipeline/uvcvideo.cpp | 24 ++- src/libcamera/pipeline/vimc.cpp | 25 ++- src/libcamera/v4l2_controls.cpp | 216 +++++++------------------- src/libcamera/v4l2_device.cpp | 50 +++--- 9 files changed, 128 insertions(+), 254 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index a7670b449b31..9e8b44a23850 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -279,7 +279,7 @@ const V4L2ControlInfoMap &CameraSensor::controls() const * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int CameraSensor::getControls(V4L2ControlList *ctrls) +int CameraSensor::getControls(ControlList *ctrls) { return subdev_->getControls(ctrls); } @@ -309,7 +309,7 @@ int CameraSensor::getControls(V4L2ControlList *ctrls) * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int CameraSensor::setControls(V4L2ControlList *ctrls) +int CameraSensor::setControls(ControlList *ctrls) { return subdev_->setControls(ctrls); } diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index fe033fb374c1..5ad829232f26 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -17,6 +17,7 @@ namespace libcamera { +class ControlList; class MediaEntity; class V4L2Subdevice; @@ -43,8 +44,8 @@ public: int setFormat(V4L2SubdeviceFormat *format); const V4L2ControlInfoMap &controls() const; - int getControls(V4L2ControlList *ctrls); - int setControls(V4L2ControlList *ctrls); + int getControls(ControlList *ctrls); + int setControls(ControlList *ctrls); protected: std::string logPrefix() const; diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index 71ce377fe4c5..1d85ecf9864a 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -47,45 +46,17 @@ private: using V4L2ControlInfoMap = std::map; -class V4L2Control +class V4L2ControlList : public ControlList { public: - V4L2Control(unsigned int id, const ControlValue &value = ControlValue()) - : id_(id), value_(value) - { - } + V4L2ControlList(const V4L2ControlInfoMap &controls); - unsigned int id() const { return id_; } - const ControlValue &value() const { return value_; } - ControlValue &value() { return value_; } + bool contains(unsigned int id) const; + const ControlValue &get(unsigned int id) const; + void set(unsigned int id, const ControlValue &value); private: - unsigned int id_; - ControlValue value_; -}; - -class V4L2ControlList -{ -public: - using iterator = std::vector::iterator; - using const_iterator = std::vector::const_iterator; - - iterator begin() { return controls_.begin(); } - const_iterator begin() const { return controls_.begin(); } - iterator end() { return controls_.end(); } - const_iterator end() const { return controls_.end(); } - - bool empty() const { return controls_.empty(); } - std::size_t size() const { return controls_.size(); } - - void clear() { controls_.clear(); } - void add(unsigned int id, int64_t value = 0); - - V4L2Control *getByIndex(unsigned int index); - V4L2Control *operator[](unsigned int id); - -private: - std::vector controls_; + const V4L2ControlInfoMap &controls_; }; } /* namespace libcamera */ diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 75a52c33d821..0375d3a1cb82 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -17,6 +17,8 @@ namespace libcamera { +class ControlList; + class V4L2Device : protected Loggable { public: @@ -25,8 +27,8 @@ public: const V4L2ControlInfoMap &controls() const { return controls_; } - int getControls(V4L2ControlList *ctrls); - int setControls(V4L2ControlList *ctrls); + int getControls(ControlList *ctrls); + int setControls(ControlList *ctrls); const std::string &deviceNode() const { return deviceNode_; } @@ -43,7 +45,7 @@ protected: private: void listControls(); - void updateControls(V4L2ControlList *ctrls, + void updateControls(ControlList *ctrls, const V4L2ControlInfo **controlInfo, const struct v4l2_ext_control *v4l2Ctrls, unsigned int count); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 827906d5cd2e..9776b36b88cd 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -199,6 +199,7 @@ class PipelineHandlerIPU3 : public PipelineHandler { public: static constexpr unsigned int V4L2_CID_IPU3_PIPE_MODE = 0x009819c1; + enum IPU3PipeModes { IPU3PipeModeVideo = 0, IPU3PipeModeStillCapture = 1, @@ -603,10 +604,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) return ret; /* Apply the "pipe_mode" control to the ImgU subdevice. */ - V4L2ControlList ctrls; - ctrls.add(V4L2_CID_IPU3_PIPE_MODE, vfStream->active_ ? - IPU3PipeModeVideo : - IPU3PipeModeStillCapture); + V4L2ControlList ctrls(imgu->imgu_->controls()); + ctrls.set(V4L2_CID_IPU3_PIPE_MODE, + static_cast(vfStream->active_ ? IPU3PipeModeVideo : + IPU3PipeModeStillCapture)); ret = imgu->imgu_->setControls(&ctrls); if (ret) { LOG(IPU3, Error) << "Unable to set pipe_mode control"; diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 88f7fb9bc568..467bd9a9eaff 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -228,31 +228,30 @@ void PipelineHandlerUVC::stop(Camera *camera) int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request) { - V4L2ControlList controls; + V4L2ControlList controls(data->video_->controls()); for (auto it : request->controls()) { const ControlId &id = *it.first; ControlValue &value = it.second; if (id == controls::Brightness) { - controls.add(V4L2_CID_BRIGHTNESS, value.get()); + controls.set(V4L2_CID_BRIGHTNESS, value); } else if (id == controls::Contrast) { - controls.add(V4L2_CID_CONTRAST, value.get()); + controls.set(V4L2_CID_CONTRAST, value); } else if (id == controls::Saturation) { - controls.add(V4L2_CID_SATURATION, value.get()); + controls.set(V4L2_CID_SATURATION, value); } else if (id == controls::ManualExposure) { - controls.add(V4L2_CID_EXPOSURE_AUTO, 1); - controls.add(V4L2_CID_EXPOSURE_ABSOLUTE, value.get()); + controls.set(V4L2_CID_EXPOSURE_AUTO, 1); + controls.set(V4L2_CID_EXPOSURE_ABSOLUTE, value); } else if (id == controls::ManualGain) { - controls.add(V4L2_CID_GAIN, value.get()); + controls.set(V4L2_CID_GAIN, value); } } - for (const V4L2Control &ctrl : controls) + for (const auto &ctrl : controls) LOG(UVC, Debug) - << "Setting control 0x" - << std::hex << std::setw(8) << ctrl.id() << std::dec - << " to " << ctrl.value().toString(); + << "Setting control " << ctrl.first->name() + << " to " << ctrl.second.toString(); int ret = data->video_->setControls(&controls); if (ret) { @@ -338,11 +337,10 @@ int UVCCameraData::init(MediaEntity *entity) /* Initialise the supported controls. */ const V4L2ControlInfoMap &controls = video_->controls(); for (const auto &ctrl : controls) { - unsigned int v4l2Id = ctrl.first; const V4L2ControlInfo &info = ctrl.second; const ControlId *id; - switch (v4l2Id) { + switch (info.id().id()) { case V4L2_CID_BRIGHTNESS: id = &controls::Brightness; break; diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 26477dccbb8f..600a1154c75e 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -281,26 +281,24 @@ void PipelineHandlerVimc::stop(Camera *camera) int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) { - V4L2ControlList controls; + V4L2ControlList controls(data->sensor_->controls()); for (auto it : request->controls()) { const ControlId &id = *it.first; ControlValue &value = it.second; - if (id == controls::Brightness) { - controls.add(V4L2_CID_BRIGHTNESS, value.get()); - } else if (id == controls::Contrast) { - controls.add(V4L2_CID_CONTRAST, value.get()); - } else if (id == controls::Saturation) { - controls.add(V4L2_CID_SATURATION, value.get()); - } + if (id == controls::Brightness) + controls.set(V4L2_CID_BRIGHTNESS, value); + else if (id == controls::Contrast) + controls.set(V4L2_CID_CONTRAST, value); + else if (id == controls::Saturation) + controls.set(V4L2_CID_SATURATION, value); } - for (const V4L2Control &ctrl : controls) + for (const auto &ctrl : controls) LOG(VIMC, Debug) - << "Setting control 0x" - << std::hex << std::setw(8) << ctrl.id() << std::dec - << " to " << ctrl.value().toString(); + << "Setting control " << ctrl.first->name() + << " to " << ctrl.second.toString(); int ret = data->sensor_->setControls(&controls); if (ret) { @@ -417,11 +415,10 @@ int VimcCameraData::init(MediaDevice *media) /* Initialise the supported controls. */ const V4L2ControlInfoMap &controls = sensor_->controls(); for (const auto &ctrl : controls) { - unsigned int v4l2Id = ctrl.first; const V4L2ControlInfo &info = ctrl.second; const ControlId *id; - switch (v4l2Id) { + switch (info.id().id()) { case V4L2_CID_BRIGHTNESS: id = &controls::Brightness; break; diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index a630a2583d33..98b2b3fe9d0a 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -167,191 +167,83 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) * \brief A map of control ID to V4L2ControlInfo */ -/** - * \class V4L2Control - * \brief A V4L2 control value - * - * The V4L2Control class represent the value of a V4L2 control. The class - * stores values that have been read from or will be applied to a V4L2 device. - * - * The value stored in the class instances does not reflect what is actually - * applied to the hardware but is a pure software cache optionally initialized - * at control creation time and modified by a control read or write operation. - * - * The write and read controls the V4L2Control class instances are not meant - * to be directly used but are instead intended to be grouped in - * V4L2ControlList instances, which are then passed as parameters to - * V4L2Device::setControls() and V4L2Device::getControls() operations. - */ - -/** - * \fn V4L2Control::V4L2Control - * \brief Construct a V4L2 control with \a id and \a value - * \param id The V4L2 control ID - * \param value The control value - */ - -/** - * \fn V4L2Control::value() const - * \brief Retrieve the value of the control - * - * This method is a const version of V4L2Control::value(), returning a const - * reference to the value. - * - * \return The V4L2 control value - */ - -/** - * \fn V4L2Control::value() - * \brief Retrieve the value of the control - * - * This method returns the cached control value, initially set by - * V4L2ControlList::add() and then updated when the controls are read or - * written with V4L2Device::getControls() and V4L2Device::setControls(). - * - * \return The V4L2 control value - */ - -/** - * \fn V4L2Control::id() - * \brief Retrieve the control ID this instance refers to - * \return The V4L2Control ID - */ - /** * \class V4L2ControlList - * \brief Container of V4L2Control instances + * \brief A list of controls for a V4L2 device * - * The V4L2ControlList class works as a container for a list of V4L2Control - * instances. The class provides operations to add a new control to the list, - * get back a control value, and reset the list of controls it contains. + * This class specialises the ControList class for use with V4L2 devices. It + * offers a convenience API to access controls by numerical ID instead of + * ControlId. * - * In order to set and get controls, user of the libcamera V4L2 control - * framework should operate on instances of the V4L2ControlList class, and use - * them as argument for the V4L2Device::setControls() and - * V4L2Device::getControls() operations, which write and read a list of - * controls to or from a V4L2 device (a video device or a subdevice). - * - * Controls are added to a V4L2ControlList instance with the add() method, with - * or without a value. - * - * To write controls to a device, the controls of interest shall be added with - * an initial value by calling V4L2ControlList::add(unsigned int id, int64_t - * value) to prepare for a write operation. Once the values of all controls of - * interest have been added, the V4L2ControlList instance is passed to the - * V4L2Device::setControls(), which sets the controls on the device. - * - * To read controls from a device, the desired controls are added with - * V4L2ControlList::add(unsigned int id) to prepare for a read operation. The - * V4L2ControlList instance is then passed to V4L2Device::getControls(), which - * reads the controls from the device and updates the values stored in - * V4L2ControlList. - * - * V4L2ControlList instances can be reset to remove all controls they contain - * and prepare to be re-used for a new control write/read sequence. - */ - -/** - * \typedef V4L2ControlList::iterator - * \brief Iterator on the V4L2 controls contained in the instance - */ - -/** - * \typedef V4L2ControlList::const_iterator - * \brief Const iterator on the V4L2 controls contained in the instance + * V4L2ControlList should as much as possible not be used in place of + * ControlList in APIs, and be used instead solely for the purpose of easily + * constructing a ControlList of V4L2 controls for a device. */ /** - * \fn iterator V4L2ControlList::begin() - * \brief Retrieve an iterator to the first V4L2Control in the instance - * \return An iterator to the first V4L2 control + * \brief Construct a V4L2ControlList associated with a V4L2 device + * \param[in] controls The V4L2 device control info map */ - -/** - * \fn const_iterator V4L2ControlList::begin() const - * \brief Retrieve a constant iterator to the first V4L2Control in the instance - * \return A constant iterator to the first V4L2 control - */ - -/** - * \fn iterator V4L2ControlList::end() - * \brief Retrieve an iterator pointing to the past-the-end V4L2Control in the - * instance - * \return An iterator to the element following the last V4L2 control in the - * instance - */ - -/** - * \fn const_iterator V4L2ControlList::end() const - * \brief Retrieve a constant iterator pointing to the past-the-end V4L2Control - * in the instance - * \return A constant iterator to the element following the last V4L2 control - * in the instance - */ - -/** - * \fn V4L2ControlList::empty() - * \brief Verify if the instance does not contain any control - * \return True if the instance does not contain any control, false otherwise - */ - -/** - * \fn V4L2ControlList::size() - * \brief Retrieve the number on controls in the instance - * \return The number of V4L2Control stored in the instance - */ - -/** - * \fn V4L2ControlList::clear() - * \brief Remove all controls in the instance - */ - -/** - * \brief Add control with \a id and optional \a value to the instance - * \param id The V4L2 control ID (V4L2_CID_*) - * \param value The V4L2 control value - * - * This method adds a new V4L2 control to the V4L2ControlList. The newly - * inserted control shall not already be present in the control lists, otherwise - * this method, and further use of the control list lead to undefined behaviour. - */ -void V4L2ControlList::add(unsigned int id, int64_t value) +V4L2ControlList::V4L2ControlList(const V4L2ControlInfoMap &controls) + : ControlList(nullptr), controls_(controls) { - controls_.emplace_back(id, value); } /** - * \brief Retrieve the control at \a index - * \param[in] index The control index - * - * Controls are stored in a V4L2ControlList in order of insertion and this - * method retrieves the control at \a index. + * \brief Check if the list contains a control with the specified \a id + * \param[in] id The control ID * - * \return A pointer to the V4L2Control at \a index or nullptr if the - * index is larger than the number of controls + * \return True if the list contains a matching control, false otherwise */ -V4L2Control *V4L2ControlList::getByIndex(unsigned int index) +bool V4L2ControlList::contains(unsigned int id) const { - if (index >= controls_.size()) - return nullptr; + auto ctrl = controls_.find(id); + if (ctrl == controls_.end()) + return false; - return &controls_[index]; + return ControlList::contains(ctrl->second.id()); } /** - * \brief Retrieve the control with \a id - * \param[in] id The V4L2 control ID (V4L2_CID_xx) - * \return A pointer to the V4L2Control with \a id or nullptr if the - * control ID is not part of this instance. + * \brief Get the value of control \a id + * \param[in] id The control ID + * + * The behaviour is undefined if the control \a id is not present in the list. + * Use v4L2ControlList::contains() to test for the presence of a control in the + * list before retrieving its value. + * + * \return The control value */ -V4L2Control *V4L2ControlList::operator[](unsigned int id) +const ControlValue &V4L2ControlList::get(unsigned int id) const { - for (V4L2Control &ctrl : controls_) { - if (ctrl.id() == id) - return &ctrl; + auto ctrl = controls_.find(id); + if (ctrl == controls_.end()) { + static ControlValue zero; + return zero; } - return nullptr; + return ControlList::get(ctrl->second.id()); +} + +/** + * \brief Set the value of control \a id to \a value + * \param[in] id The control ID + * \param[in] value The control value + * + * This method sets the value of a control in the control list. If the control + * is already present in the list, its value is updated, otherwise it is added + * to the list. + * + * The behaviour is undefined if the control \a ctrl is not supported by the + * V4L2 device that the list refers to. + */ +void V4L2ControlList::set(unsigned int id, const ControlValue &value) +{ + auto ctrl = controls_.find(id); + if (ctrl == controls_.end()) + return; + + ControlList::set(ctrl->second.id(), value); } } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 466c3d41f6e3..50616571dcef 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "log.h" #include "v4l2_controls.h" @@ -163,7 +165,7 @@ void V4L2Device::close() * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int V4L2Device::getControls(V4L2ControlList *ctrls) +int V4L2Device::getControls(ControlList *ctrls) { unsigned int count = ctrls->size(); if (count == 0) @@ -173,18 +175,21 @@ int V4L2Device::getControls(V4L2ControlList *ctrls) struct v4l2_ext_control v4l2Ctrls[count]; memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); - for (unsigned int i = 0; i < count; ++i) { - const V4L2Control *ctrl = ctrls->getByIndex(i); - const auto iter = controls_.find(ctrl->id()); + unsigned int i = 0; + for (const auto &ctrl : *ctrls) { + const ControlId *id = ctrl.first; + const auto iter = controls_.find(id->id()); if (iter == controls_.end()) { LOG(V4L2, Error) - << "Control '" << ctrl->id() << "' not found"; + << "Control '" << id->name() << "' not found"; return -EINVAL; } const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = ctrl->id(); + v4l2Ctrls[i].id = id->id(); + + i++; } struct v4l2_ext_controls v4l2ExtCtrls = {}; @@ -238,7 +243,7 @@ int V4L2Device::getControls(V4L2ControlList *ctrls) * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int V4L2Device::setControls(V4L2ControlList *ctrls) +int V4L2Device::setControls(ControlList *ctrls) { unsigned int count = ctrls->size(); if (count == 0) @@ -248,32 +253,36 @@ int V4L2Device::setControls(V4L2ControlList *ctrls) struct v4l2_ext_control v4l2Ctrls[count]; memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); - for (unsigned int i = 0; i < count; ++i) { - const V4L2Control *ctrl = ctrls->getByIndex(i); - const auto iter = controls_.find(ctrl->id()); + unsigned int i = 0; + for (const auto &ctrl : *ctrls) { + const ControlId *id = ctrl.first; + const auto iter = controls_.find(id->id()); if (iter == controls_.end()) { LOG(V4L2, Error) - << "Control '" << ctrl->id() << "' not found"; + << "Control '" << id->name() << "' not found"; return -EINVAL; } const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = ctrl->id(); + v4l2Ctrls[i].id = id->id(); /* Set the v4l2_ext_control value for the write operation. */ + const ControlValue &value = ctrl.second; switch (info->type()) { case V4L2_CTRL_TYPE_INTEGER64: - v4l2Ctrls[i].value64 = ctrl->value().get(); + v4l2Ctrls[i].value64 = value.get(); break; default: /* * \todo To be changed when support for string and * compound controls will be added. */ - v4l2Ctrls[i].value = ctrl->value().get(); + v4l2Ctrls[i].value64 = value.get(); break; } + + i++; } struct v4l2_ext_controls v4l2ExtCtrls = {}; @@ -382,28 +391,31 @@ void V4L2Device::listControls() * \param[in] v4l2Ctrls List of V4L2 extended controls as returned by the driver * \param[in] count The number of controls to update */ -void V4L2Device::updateControls(V4L2ControlList *ctrls, +void V4L2Device::updateControls(ControlList *ctrls, const V4L2ControlInfo **controlInfo, const struct v4l2_ext_control *v4l2Ctrls, unsigned int count) { - for (unsigned int i = 0; i < count; ++i) { + unsigned int i = 0; + for (auto &ctrl : *ctrls) { const struct v4l2_ext_control *v4l2Ctrl = &v4l2Ctrls[i]; const V4L2ControlInfo *info = controlInfo[i]; - V4L2Control *ctrl = ctrls->getByIndex(i); + ControlValue &value = ctrl.second; switch (info->type()) { case V4L2_CTRL_TYPE_INTEGER64: - ctrl->value().set(v4l2Ctrl->value64); + value.set(v4l2Ctrl->value64); break; default: /* * \todo To be changed when support for string and * compound controls will be added. */ - ctrl->value().set(v4l2Ctrl->value); + value.set(v4l2Ctrl->value); break; } + + i++; } } From patchwork Mon Oct 7 22:46:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2136 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 929826197A for ; Tue, 8 Oct 2019 00:46:58 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B1FB7B2D for ; Tue, 8 Oct 2019 00:46:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488418; bh=qp6YVjF2+RZfNWa91P1S76as2yhZ8jHLX2J/NfMV4uY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=CkQ59IklX74ECkJGqYA3msc8qSewm3p6bfggbkELUJjO52nX6+6+otTpr+/rvk8dH 4woeYXgRr31SV89k0hzYHSv78GSYLZ01+mT4cCzTgMGp09OobKyJ/ZuuEaKh3SMmW5 5XZiDRpwj4sPYFdg+YUU/TeSJyUy5Wg3IIPp9EQ4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:41 +0300 Message-Id: <20191007224642.6597-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 8/9] libcamera: v4l2_controls: Remove V4L2ControlInfo type field 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, 07 Oct 2019 22:46:58 -0000 The V4L2ControlInfo type field stores the V4L2 control type. It partly duplicates the V4L2ControlInfo id().type() that stores the corresponding libcamera control type. The two fields are not strictly identical, but having two types doesn't provide us with any extra value. As this is confusing, remove the V4L2ControlInfo type field. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/include/v4l2_controls.h | 2 -- src/libcamera/v4l2_controls.cpp | 7 ------- src/libcamera/v4l2_device.cpp | 10 +++++----- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index 1d85ecf9864a..133ab9ec208b 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -31,14 +31,12 @@ public: V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl); const ControlId &id() const { return id_; } - unsigned int type() const { return type_; } size_t size() const { return size_; } const ControlRange &range() const { return range_; } private: V4L2ControlId id_; - unsigned int type_; size_t size_; ControlRange range_; diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 98b2b3fe9d0a..d3f94709e821 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -127,7 +127,6 @@ V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl) V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) : id_(ctrl) { - type_ = ctrl.type; size_ = ctrl.elem_size * ctrl.elems; if (ctrl.type == V4L2_CTRL_TYPE_INTEGER64) @@ -144,12 +143,6 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) * \return The V4L2 control ID */ -/** - * \fn V4L2ControlInfo::type() - * \brief Retrieve the control type as defined by V4L2_CTRL_TYPE_* - * \return The V4L2 control type - */ - /** * \fn V4L2ControlInfo::size() * \brief Retrieve the control value data size (in bytes) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 50616571dcef..b64e5068a671 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -269,8 +269,8 @@ int V4L2Device::setControls(ControlList *ctrls) /* Set the v4l2_ext_control value for the write operation. */ const ControlValue &value = ctrl.second; - switch (info->type()) { - case V4L2_CTRL_TYPE_INTEGER64: + switch (info->id().type()) { + case ControlTypeInteger64: v4l2Ctrls[i].value64 = value.get(); break; default: @@ -278,7 +278,7 @@ int V4L2Device::setControls(ControlList *ctrls) * \todo To be changed when support for string and * compound controls will be added. */ - v4l2Ctrls[i].value64 = value.get(); + v4l2Ctrls[i].value = value.get(); break; } @@ -402,8 +402,8 @@ void V4L2Device::updateControls(ControlList *ctrls, const V4L2ControlInfo *info = controlInfo[i]; ControlValue &value = ctrl.second; - switch (info->type()) { - case V4L2_CTRL_TYPE_INTEGER64: + switch (info->id().type()) { + case ControlTypeInteger64: value.set(v4l2Ctrl->value64); break; default: From patchwork Mon Oct 7 22:46:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2137 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 951E36197A for ; Tue, 8 Oct 2019 00:46:59 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable118.64-20-96.mc.videotron.ca [96.20.64.118]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CEE59B2D for ; Tue, 8 Oct 2019 00:46:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570488419; bh=bLkfjQh9qvSAmLcrRWH0Cq5MipYCnwfXqr0Dg5tI6cU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=IGQZIKopdc7LmCLazWjeZ2fpVuip6VGAZjsnpzb37jcxbdo2k9Ho2l+OxkAyyGDQv eftHuP/xgoweq/EGh6ud2jSTgBrJeVjGd/DDARGT4OX+0X01dRszqpjUIEvuL5HEhT IPBGiUKY+O8By9qdTMguJzrZINHJ981fvQMELCho= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Oct 2019 01:46:42 +0300 Message-Id: <20191007224642.6597-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> References: <20191007224642.6597-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 9/9] libcamera: v4l2_controls: Add control validator 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, 07 Oct 2019 22:47:00 -0000 Add a ControlValidator specialisation that validates controls based on a V4L2 device. Signed-off-by: Laurent Pinchart --- src/libcamera/include/v4l2_controls.h | 14 ++++++++++++ src/libcamera/v4l2_controls.cpp | 33 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index 133ab9ec208b..5fd92e3ac4e5 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -17,6 +17,8 @@ #include +#include "control_validator.h" + namespace libcamera { class V4L2ControlId : public ControlId @@ -57,6 +59,18 @@ private: const V4L2ControlInfoMap &controls_; }; +class V4L2ControlValidator final : public ControlValidator +{ +public: + V4L2ControlValidator(V4L2Device *device); + + const std::string &name() const override; + bool validate(const ControlId &id) const override; + +private: + V4L2Device *dev_; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_V4L2_CONTROLS_H__ */ diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index d3f94709e821..498567ee0bf0 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -239,4 +239,37 @@ void V4L2ControlList::set(unsigned int id, const ControlValue &value) ControlList::set(ctrl->second.id(), value); } +/** + * \class V4L2ControlValidator + * \brief A control validator for V4L2Devoe instances + * + * This ControlValidator specialisation validates that controls exist in the + * V4L2Device associated with the validator. + */ + +/** + * \brief Construst a V4L2ControlValidator for the V4L2 \a device + * \param[in] device The V4L2 device + */ +V4L2ControlValidator::V4L2ControlValidator(V4L2Device *device) + : dev_(device) +{ +} + +const std::string &V4L2ControlValidator::name() const +{ + return dev_->deviceNode(); +} + +/** + * \brief Validate a control + * \param[in] id The control ID + * \return True if the control is valid, false otherwise + */ +bool V4L2ControlValidator::validate(const ControlId &id) const +{ + const V4L2ControlInfoMap &controls = dev_->controls(); + return controls.find(id.id()) != controls.end(); +} + } /* namespace libcamera */