Patch Detail
Show a patch.
GET /api/patches/2423/?format=api
{ "id": 2423, "url": "https://patchwork.libcamera.org/api/patches/2423/?format=api", "web_url": "https://patchwork.libcamera.org/patch/2423/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20191211145327.58633-2-jacopo@jmondi.org>", "date": "2019-12-11T14:53:27", "name": "[libcamera-devel,RFC,2/2] controls: Define controls as compound", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "97056bfe4f7e845e5f89d290e7d2553fe1ead797", "submitter": { "id": 3, "url": "https://patchwork.libcamera.org/api/people/3/?format=api", "name": "Jacopo Mondi", "email": "jacopo@jmondi.org" }, "delegate": { "id": 15, "url": "https://patchwork.libcamera.org/api/users/15/?format=api", "username": "jmondi", "first_name": "Jacopo", "last_name": "Mondi", "email": "jacopo@jmondi.org" }, "mbox": "https://patchwork.libcamera.org/patch/2423/mbox/", "series": [ { "id": 587, "url": "https://patchwork.libcamera.org/api/series/587/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=587", "date": "2019-12-11T14:53:26", "name": "[libcamera-devel,RFC,1/2] WIP libcamera: controls: Support compound controls", "version": 1, "mbox": "https://patchwork.libcamera.org/series/587/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/2423/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/2423/checks/", "tags": {}, "headers": { "Return-Path": "<jacopo@jmondi.org>", "Received": [ "from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net\n\t[217.70.183.199])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D74A2600F5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 11 Dec 2019 15:51:19 +0100 (CET)", "from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 6DE0AFF80F;\n\tWed, 11 Dec 2019 14:51:19 +0000 (UTC)" ], "X-Originating-IP": "93.34.114.233", "From": "Jacopo Mondi <jacopo@jmondi.org>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 11 Dec 2019 15:53:27 +0100", "Message-Id": "<20191211145327.58633-2-jacopo@jmondi.org>", "X-Mailer": "git-send-email 2.24.0", "In-Reply-To": "<20191211145327.58633-1-jacopo@jmondi.org>", "References": "<20191211145327.58633-1-jacopo@jmondi.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [RFC 2/2] controls: Define controls as compound", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "X-List-Received-Date": "Wed, 11 Dec 2019 14:51:20 -0000" }, "content": "Add 'isCompound' flag to the control framework.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n include/libcamera/controls.h | 12 +++++--\n src/libcamera/control_ids.yaml | 3 +-\n src/libcamera/control_serializer.cpp | 4 ++-\n src/libcamera/controls.cpp | 24 +++++++-------\n src/libcamera/gen-controls.py | 12 ++++++-\n src/libcamera/v4l2_controls.cpp | 4 ++-\n test/controls/compound_controls.cpp | 48 +++++++++++++++++-----------\n 7 files changed, 70 insertions(+), 37 deletions(-)", "diff": "diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h\nindex b9f8d4db0bea..ddd641e01655 100644\n--- a/include/libcamera/controls.h\n+++ b/include/libcamera/controls.h\n@@ -94,14 +94,16 @@ private:\n class ControlId\n {\n public:\n-\tControlId(unsigned int id, const std::string &name, ControlType type)\n-\t\t: id_(id), name_(name), type_(type)\n+\tControlId(unsigned int id, const std::string &name, ControlType type,\n+\t\t bool isCompound)\n+\t\t: id_(id), name_(name), type_(type), isCompound_(isCompound)\n \t{\n \t}\n \n \tunsigned int id() const { return id_; }\n \tconst std::string &name() const { return name_; }\n \tControlType type() const { return type_; }\n+\tbool isCompound() const { return isCompound_; }\n \n private:\n \tControlId &operator=(const ControlId &) = delete;\n@@ -110,6 +112,7 @@ private:\n \tunsigned int id_;\n \tstd::string name_;\n \tControlType type_;\n+\tbool isCompound_;\n };\n \n static inline bool operator==(unsigned int lhs, const ControlId &rhs)\n@@ -138,7 +141,7 @@ class Control : public ControlId\n public:\n \tusing type = T;\n \n-\tControl(unsigned int id, const char *name);\n+\tControl(unsigned int id, const char *name, bool isCompound = false);\n \n private:\n \tControl(const Control &) = delete;\n@@ -272,6 +275,9 @@ public:\n \ttemplate<typename T>\n \tvoid set(const Control<T> &ctrl, const Span<T> &values)\n \t{\n+\t\tif (!ctrl.isCompound())\n+\t\t\treturn;\n+\n \t\tControlValue *val = find(ctrl.id());\n \t\tif (!val)\n \t\t\treturn;\ndiff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml\nindex b72e81dae060..1bdece651638 100644\n--- a/src/libcamera/control_ids.yaml\n+++ b/src/libcamera/control_ids.yaml\n@@ -51,7 +51,8 @@ controls:\n description: Specify a fixed gain parameter\n \n - CompoundControl:\n- type: int8_t\n+ type: int32_t\n description: A fictional compound control\n+ compound: true\n \n ...\ndiff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp\nindex 2140d3a5dd3f..82502285c5ca 100644\n--- a/src/libcamera/control_serializer.cpp\n+++ b/src/libcamera/control_serializer.cpp\n@@ -415,8 +415,10 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &\n \t\t/**\n \t\t * \\todo Find a way to preserve the control name for debugging\n \t\t * purpose.\n+\t\t *\n+\t\t * FIXME: set isCompound to false unconditionally\n \t\t */\n-\t\tcontrolIds_.emplace_back(utils::make_unique<ControlId>(entry.id, \"\", type));\n+\t\tcontrolIds_.emplace_back(utils::make_unique<ControlId>(entry.id, \"\", type, false));\n \n \t\tif (entry.offset != values.offset()) {\n \t\t\tLOG(Serializer, Error)\ndiff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp\nindex 64d99f7669b6..8fb0088150d0 100644\n--- a/src/libcamera/controls.cpp\n+++ b/src/libcamera/controls.cpp\n@@ -581,38 +581,38 @@ bool ControlValue::operator==(const ControlValue &other) const\n \n #ifndef __DOXYGEN__\n template<>\n-Control<void>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeNone)\n+Control<void>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeNone, isCompound)\n {\n }\n \n template<>\n-Control<bool>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeBool)\n+Control<bool>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeBool, isCompound)\n {\n }\n \n template<>\n-Control<int8_t>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeInteger8)\n+Control<int8_t>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeInteger8, isCompound)\n {\n }\n \n template<>\n-Control<int32_t>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeInteger32)\n+Control<int32_t>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeInteger32, isCompound)\n {\n }\n \n template<>\n-Control<int64_t>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeInteger64)\n+Control<int64_t>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeInteger64, isCompound)\n {\n }\n \n template<>\n-Control<float>::Control(unsigned int id, const char *name)\n-\t: ControlId(id, name, ControlTypeFloat)\n+Control<float>::Control(unsigned int id, const char *name, bool isCompound)\n+\t: ControlId(id, name, ControlTypeFloat, isCompound)\n {\n }\n #endif /* __DOXYGEN__ */\ndiff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py\nindex 4a1ee52cdb04..820b862dcf01 100755\n--- a/src/libcamera/gen-controls.py\n+++ b/src/libcamera/gen-controls.py\n@@ -26,6 +26,7 @@ ${description}\\n *\\n''')\n ${description}\n */''')\n def_template = string.Template('extern const Control<${type}> ${name}(${id_name}, \"${name}\");')\n+ def_compound_template = string.Template('extern const Control<${type}> ${name}(${id_name}, \"${name}\", true);')\n \n ctrls_doc = []\n ctrls_def = []\n@@ -67,8 +68,17 @@ ${description}\n except KeyError:\n pass\n \n+ try:\n+ compound = ctrl['compound']\n+ isCompound = True\n+ except KeyError:\n+ isCompound = False\n+\n ctrls_doc.append(doc_template.substitute(info))\n- ctrls_def.append(def_template.substitute(info))\n+ if isCompound:\n+ ctrls_def.append(def_compound_template.substitute(info))\n+ else:\n+ ctrls_def.append(def_template.substitute(info))\n ctrls_map.append('\\t{ ' + id_name + ', &' + name + ' },')\n \n return {\ndiff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp\nindex 7446c3880330..cd1b39a1a4b3 100644\n--- a/src/libcamera/v4l2_controls.cpp\n+++ b/src/libcamera/v4l2_controls.cpp\n@@ -97,9 +97,11 @@ ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl)\n /**\n * \\brief Construct a V4L2ControlId from a struct v4l2_query_ext_ctrl\n * \\param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel\n+ *\n+ * FIXME: set isCompound to false unconditionally\n */\n V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl)\n-\t: ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl))\n+\t: ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl), false)\n {\n }\n \ndiff --git a/test/controls/compound_controls.cpp b/test/controls/compound_controls.cpp\nindex de00573df141..0ca72f683d1f 100644\n--- a/test/controls/compound_controls.cpp\n+++ b/test/controls/compound_controls.cpp\n@@ -53,40 +53,52 @@ protected:\n \t\tcout << span[0] << endl;\n \n \t\t/*\n-\t\t * Compound Controls\n-\t\t *\n-\t\t * As of now, all Controls are now 'compounds' when set with a\n-\t\t * Span<> of values.\n-\t\t *\n-\t\t * We need to define how to establish that a Control is actually\n-\t\t * a compound or supports a single value.\n+\t\t * Compound Controls: can be set with a span of values\n \t\t */\n-\t\tlist.set(controls::Brightness, {0, 125, 255});\n-\t\tSpan<int32_t> iSpan = list.get(controls::Brightness);\n+\t\tlist.set(controls::CompoundControl, { 0, 125, 253 });\n+\t\tSpan<int32_t> iSpan = list.get(controls::CompoundControl);\n \n \t\tcout << iSpan.size() << endl;\n \t\tfor (uint32_t i : iSpan)\n \t\t\tcout << i << endl;\n \n \t\t/*\n-\t\t * But they can still be accessed and operated with a single\n-\t\t * value.\n+\t\t * But they can still be accessed and operated as a single\n+\t\t * value control.\n \t\t */\n-\t\tlist.set(controls::Brightness, 112);\n-\t\tcout << list.get(controls::Brightness) << endl;\n+\t\tlist.set(controls::CompoundControl, 112);\n+\t\tcout << list.get(controls::CompoundControl) << endl;\n \n \t\t/*\n \t\t * Or set with a Span and accessed by value. The first item\n-\t\t * is returned.\n+\t\t * is returned in this case.\n \t\t */\n-\t\tlist.set(controls::Brightness, {50, 125});\n-\t\tcout << list.get(controls::Brightness) << endl;\n+\t\tlist.set(controls::CompoundControl, { 50, 125 });\n+\t\tcout << list.get(controls::CompoundControl) << endl;\n \n \t\t/* The other way around works as well. */\n-\t\tlist.set(controls::Brightness, 133);\n-\t\tSpan<int32_t> s = list.get(controls::Brightness);\n+\t\tlist.set(controls::CompoundControl, 133);\n+\t\tSpan<int32_t> s = list.get(controls::CompoundControl);\n \t\tcout << s << endl;\n \n+\t\t/*\n+\t\t * Try to set a non-compound control with a span<> and make\n+\t\t * sure it fails.\n+\t\t */\n+\t\tlist.set(controls::Brightness, 55);\n+\t\tuint32_t brightness = list.get(controls::Brightness);\n+\t\tif (brightness != 55) {\n+\t\t\tcerr << \"Failed to set non-compound control\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tlist.set(controls::Brightness, { 45, 30 });\n+\t\tbrightness = list.get(controls::Brightness);\n+\t\tif (brightness != 55) {\n+\t\t\tcerr << \"non-compound control set with span<>\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n \t\treturn TestPass;\n \t}\n };\n", "prefixes": [ "libcamera-devel", "RFC", "2/2" ] }