Show a patch.

GET /api/1.1/patches/23934/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 23934,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/23934/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/23934/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/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": "<20250724103834.54611-6-mzamazal@redhat.com>",
    "date": "2025-07-24T10:38:25",
    "name": "[v15,05/12] config: Look up IPA configurables in configuration file",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "f568116e116b25dadea316973d6b257191cb1552",
    "submitter": {
        "id": 177,
        "url": "https://patchwork.libcamera.org/api/1.1/people/177/?format=api",
        "name": "Milan Zamazal",
        "email": "mzamazal@redhat.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/23934/mbox/",
    "series": [
        {
            "id": 5320,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5320/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5320",
            "date": "2025-07-24T10:38:20",
            "name": "Add global configuration file",
            "version": 15,
            "mbox": "https://patchwork.libcamera.org/series/5320/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/23934/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/23934/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 11A42BDCC1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 24 Jul 2025 10:39:14 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AF2E1690F6;\n\tThu, 24 Jul 2025 12:39:13 +0200 (CEST)",
            "from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A3194690DA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 24 Jul 2025 12:39:10 +0200 (CEST)",
            "from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n\t(ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63])\n\tby relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n\tcipher=TLS_AES_256_GCM_SHA384) id us-mta-664-5gM-7MWOM06vyPB5b3IBwA-1;\n\tThu, 24 Jul 2025 06:39:05 -0400",
            "from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.17])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (2048 bits)\n\tserver-digest SHA256) (No client certificate requested)\n\tby mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id AE19B19560B4; Thu, 24 Jul 2025 10:39:01 +0000 (UTC)",
            "from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.255])\n\tby mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id B521E195608D; Thu, 24 Jul 2025 10:38:59 +0000 (UTC)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"VFBWkuz/\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1753353549;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tcontent-transfer-encoding:content-transfer-encoding:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=amtUO3i0DcCI7qpxVj8ejA8x6/ITyfYqV/TmG5CC3rA=;\n\tb=VFBWkuz/mn2xr4hGHVOl4CGkR4f7cwgPbAS/hFmfcrN3w1iQGUqNgQMlsHfVRMHXdrjwnB\n\ttngxgk2OG5wSQq3R4nmnX5+hQ6xTEpKrl4B6btOJPSQIT8gFnV4u4qsNbgmoCFSI8ek0RD\n\tQXrzD6wm1Sf+C3sVBHvGPdG5/v5rhWo=",
        "X-MC-Unique": "5gM-7MWOM06vyPB5b3IBwA-1",
        "X-Mimecast-MFC-AGG-ID": "5gM-7MWOM06vyPB5b3IBwA_1753353544",
        "From": "Milan Zamazal <mzamazal@redhat.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Milan Zamazal <mzamazal@redhat.com>, Kieran Bingham\n\t<kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?=\n\t<barnabas.pocze@ideasonboard.com>, Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>",
        "Subject": "[PATCH v15 05/12] config: Look up IPA configurables in configuration\n\tfile",
        "Date": "Thu, 24 Jul 2025 12:38:25 +0200",
        "Message-ID": "<20250724103834.54611-6-mzamazal@redhat.com>",
        "In-Reply-To": "<20250724103834.54611-1-mzamazal@redhat.com>",
        "References": "<20250724103834.54611-1-mzamazal@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.17",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "uSPnKgF54bP2HYjfcU72rcdm6eJX9jemGEwru7wNYlw_1753353544",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "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>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "This patch adds configuration options for environment variables used in\nthe IPA proxy.  Two utility functions configuration retrieval functions\nare added, to retrieve lists of values.\n\nThe configuration snippet:\n\n  configuration:\n    ipa:\n      config_paths:\n      - config path 1\n      - config path 2\n      - ...\n      module_paths:\n      - module path 1\n      - module path 2\n      - ...\n      proxy_paths:\n      - proxy path 1\n      - proxy path 2\n      - ...\n      force_isolation: BOOL\n\nLIBCAMERA_<IPA_NAME>_TUNING_FILE remains configurable only via the\nenvironment variable; this is supposed to be used only for testing and\ndebugging and it's not clear what to do about IPA names like \"rpi/vc4\"\nand \"rpi/pisp\" exactly.\n\nThere are two ways to pass the configuration to the places where it is\nneeded: Either to pass it as an argument to the method calls that need\nit, or to pass it to the class constructors and extract the needed\nconfiguration from there.  This patch uses the second method as it is\nless polluting the code.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n .../libcamera/internal/global_configuration.h | 21 +++++++-\n include/libcamera/internal/ipa_manager.h      |  7 ++-\n include/libcamera/internal/ipa_proxy.h        |  8 ++-\n src/libcamera/camera_manager.cpp              |  2 +-\n src/libcamera/global_configuration.cpp        | 47 +++++++++++++++--\n src/libcamera/ipa_manager.cpp                 | 39 ++++++++------\n src/libcamera/ipa_proxy.cpp                   | 51 +++++++++----------\n .../module_ipa_proxy.cpp.tmpl                 |  4 +-\n .../module_ipa_proxy.h.tmpl                   |  2 +-\n 9 files changed, 128 insertions(+), 53 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h\nindex 78bebff9f..3b500ee29 100644\n--- a/include/libcamera/internal/global_configuration.h\n+++ b/include/libcamera/internal/global_configuration.h\n@@ -12,6 +12,8 @@\n #include <string>\n #include <string_view>\n \n+#include <libcamera/base/utils.h>\n+\n #include \"libcamera/internal/yaml_parser.h\"\n \n namespace libcamera {\n@@ -25,11 +27,28 @@ public:\n \n \tunsigned int version() const;\n \tConfiguration configuration() const;\n-\tstd::optional<std::string> option(\n+\n+\ttemplate<typename T>\n+\tstd::optional<T> option(\n+\t\tconst std::initializer_list<std::string_view> confPath) const\n+\t{\n+\t\tconst YamlObject *c = &configuration();\n+\t\tfor (auto part : confPath) {\n+\t\t\tc = &(*c)[part];\n+\t\t\tif (!*c)\n+\t\t\t\treturn {};\n+\t\t}\n+\t\treturn c->get<T>();\n+\t}\n+\n+\tstd::optional<std::vector<std::string>> listOption(\n \t\tconst std::initializer_list<std::string_view> confPath) const;\n \tstd::optional<std::string> envOption(\n \t\tconst char *const envVariable,\n \t\tconst std::initializer_list<std::string_view> confPath) const;\n+\tstd::optional<std::vector<std::string>> envListOption(\n+\t\tconst char *const envVariable,\n+\t\tconst std::initializer_list<std::string_view> confPath) const;\n \n private:\n \tbool loadFile(const std::filesystem::path &fileName);\ndiff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h\nindex a0d448cf9..b0b44c74a 100644\n--- a/include/libcamera/internal/ipa_manager.h\n+++ b/include/libcamera/internal/ipa_manager.h\n@@ -17,6 +17,7 @@\n #include <libcamera/ipa/ipa_module_info.h>\n \n #include \"libcamera/internal/camera_manager.h\"\n+#include \"libcamera/internal/global_configuration.h\"\n #include \"libcamera/internal/ipa_module.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n #include \"libcamera/internal/pub_key.h\"\n@@ -28,7 +29,7 @@ LOG_DECLARE_CATEGORY(IPAManager)\n class IPAManager\n {\n public:\n-\tIPAManager();\n+\tIPAManager(const GlobalConfiguration &configuration);\n \t~IPAManager();\n \n \ttemplate<typename T>\n@@ -42,7 +43,8 @@ public:\n \t\tif (!m)\n \t\t\treturn nullptr;\n \n-\t\tstd::unique_ptr<T> proxy = std::make_unique<T>(m, !self->isSignatureValid(m));\n+\t\tconst GlobalConfiguration &configuration = cm->_d()->configuration();\n+\t\tstd::unique_ptr<T> proxy = std::make_unique<T>(m, !self->isSignatureValid(m), configuration);\n \t\tif (!proxy->isValid()) {\n \t\t\tLOG(IPAManager, Error) << \"Failed to load proxy\";\n \t\t\treturn nullptr;\n@@ -73,6 +75,7 @@ private:\n #if HAVE_IPA_PUBKEY\n \tstatic const uint8_t publicKeyData_[];\n \tstatic const PubKey pubKey_;\n+\tbool forceIsolation_;\n #endif\n };\n \ndiff --git a/include/libcamera/internal/ipa_proxy.h b/include/libcamera/internal/ipa_proxy.h\nindex 983bcc5fa..f1865d67e 100644\n--- a/include/libcamera/internal/ipa_proxy.h\n+++ b/include/libcamera/internal/ipa_proxy.h\n@@ -7,10 +7,14 @@\n \n #pragma once\n \n+#include <optional>\n #include <string>\n+#include <vector>\n \n #include <libcamera/ipa/ipa_interface.h>\n \n+#include \"libcamera/internal/global_configuration.h\"\n+\n namespace libcamera {\n \n class IPAModule;\n@@ -24,7 +28,7 @@ public:\n \t\tProxyRunning,\n \t};\n \n-\tIPAProxy(IPAModule *ipam);\n+\tIPAProxy(IPAModule *ipam, const GlobalConfiguration &configuration);\n \t~IPAProxy();\n \n \tbool isValid() const { return valid_; }\n@@ -40,6 +44,8 @@ protected:\n \n private:\n \tIPAModule *ipam_;\n+\tstd::vector<std::string> configPaths_;\n+\tstd::vector<std::string> execPaths_;\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\nindex dca3d9a83..64df62444 100644\n--- a/src/libcamera/camera_manager.cpp\n+++ b/src/libcamera/camera_manager.cpp\n@@ -41,7 +41,7 @@ LOG_DEFINE_CATEGORY(Camera)\n CameraManager::Private::Private()\n \t: initialized_(false)\n {\n-\tipaManager_ = std::make_unique<IPAManager>();\n+\tipaManager_ = std::make_unique<IPAManager>(this->configuration());\n }\n \n int CameraManager::Private::start()\ndiff --git a/src/libcamera/global_configuration.cpp b/src/libcamera/global_configuration.cpp\nindex 5be0f0701..1371392c5 100644\n--- a/src/libcamera/global_configuration.cpp\n+++ b/src/libcamera/global_configuration.cpp\n@@ -9,9 +9,11 @@\n \n #include <filesystem>\n #include <memory>\n+#include <optional>\n #include <string>\n #include <string_view>\n #include <sys/types.h>\n+#include <vector>\n \n #include <libcamera/base/file.h>\n #include <libcamera/base/log.h>\n@@ -114,13 +116,22 @@ GlobalConfiguration::GlobalConfiguration()\n  */\n \n /**\n+ * \\fn std::optional<T> GlobalConfiguration::option(const std::initializer_list<std::string_view> &confPath) const\n  * \\brief Return value of the configuration option identified by \\a confPath\n  * \\param[in] confPath Sequence of the YAML section names (excluding\n  * `configuration') leading to the requested option\n  * \\return A value if an item corresponding to \\a confPath exists in the\n  * configuration file, no value otherwise\n  */\n-std::optional<std::string> GlobalConfiguration::option(\n+\n+/**\n+ * \\brief Return values of the configuration option identified by \\a confPath\n+ * \\tparam T The type of the retrieved configuration value\n+ * \\param[in] confPath Sequence of the YAML section names (excluding\n+ * `configuration') leading to the requested list option, separated by dots\n+ * \\return A vector of strings or no value if not found\n+ */\n+std::optional<std::vector<std::string>> GlobalConfiguration::listOption(\n \tconst std::initializer_list<std::string_view> confPath) const\n {\n \tconst YamlObject *c = &configuration();\n@@ -129,7 +140,7 @@ std::optional<std::string> GlobalConfiguration::option(\n \t\tif (!*c)\n \t\t\treturn {};\n \t}\n-\treturn c->get<std::string>();\n+\treturn c->getList<std::string>();\n }\n \n /**\n@@ -156,7 +167,37 @@ std::optional<std::string> GlobalConfiguration::envOption(\n \tconst char *envValue = utils::secure_getenv(envVariable);\n \tif (envValue)\n \t\treturn std::optional{ std::string{ envValue } };\n-\treturn option(confPath);\n+\treturn option<std::string>(confPath);\n+}\n+\n+/**\n+ * \\brief Return values of the configuration option from a file or environment\n+ * \\param[in] envVariable Environment variable to get the value from\n+ * \\param[in] confPath The same as in GlobalConfiguration::option\n+ *\n+ * This helper looks first at the given environment variable and if it is\n+ * defined (even if it is empty) then it splits its value by semicolons and\n+ * returns the resulting list of strings. Otherwise it looks for \\a confPath the\n+ * same way as in GlobalConfiguration::option, value of which must be a list of\n+ * strings.\n+ *\n+ * \\note Support for using environment variables to configure libcamera behavior\n+ * is provided here mostly for backward compatibility reasons. Introducing new\n+ * configuration environment variables is discouraged.\n+ *\n+ * \\return A vector of strings retrieved from the given environment option or\n+ * configuration file or no value if not found; the vector may be empty\n+ */\n+std::optional<std::vector<std::string>> GlobalConfiguration::envListOption(\n+\tconst char *const envVariable,\n+\tconst std::initializer_list<std::string_view> confPath) const\n+{\n+\tconst char *envValue = utils::secure_getenv(envVariable);\n+\tif (envValue) {\n+\t\tauto items = utils::split(envValue, \":\");\n+\t\treturn std::vector<std::string>(items.begin(), items.end());\n+\t}\n+\treturn listOption(confPath);\n }\n \n /**\ndiff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp\nindex 830750dcc..000d56efa 100644\n--- a/src/libcamera/ipa_manager.cpp\n+++ b/src/libcamera/ipa_manager.cpp\n@@ -9,13 +9,17 @@\n \n #include <algorithm>\n #include <dirent.h>\n+#include <numeric>\n #include <string.h>\n+#include <string>\n #include <sys/types.h>\n+#include <vector>\n \n #include <libcamera/base/file.h>\n #include <libcamera/base/log.h>\n #include <libcamera/base/utils.h>\n \n+#include \"libcamera/internal/global_configuration.h\"\n #include \"libcamera/internal/ipa_module.h\"\n #include \"libcamera/internal/ipa_proxy.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n@@ -101,30 +105,36 @@ LOG_DEFINE_CATEGORY(IPAManager)\n  * The IPAManager class is meant to only be instantiated once, by the\n  * CameraManager.\n  */\n-IPAManager::IPAManager()\n+IPAManager::IPAManager(const GlobalConfiguration &configuration)\n {\n #if HAVE_IPA_PUBKEY\n \tif (!pubKey_.isValid())\n \t\tLOG(IPAManager, Warning) << \"Public key not valid\";\n+\n+\tchar *force = utils::secure_getenv(\"LIBCAMERA_IPA_FORCE_ISOLATION\");\n+\tforceIsolation_ = (force && force[0] != '\\0') ||\n+\t\t\t  (!force && configuration.option<bool>({ \"ipa\", \"force_isolation\" })\n+\t\t\t\t\t     .value_or(false));\n #endif\n \n \tunsigned int ipaCount = 0;\n \n \t/* User-specified paths take precedence. */\n-\tconst char *modulePaths = utils::secure_getenv(\"LIBCAMERA_IPA_MODULE_PATH\");\n-\tif (modulePaths) {\n-\t\tfor (const auto &dir : utils::split(modulePaths, \":\")) {\n-\t\t\tif (dir.empty())\n-\t\t\t\tcontinue;\n-\n-\t\t\tipaCount += addDir(dir.c_str());\n-\t\t}\n+\tconst auto modulePaths =\n+\t\tconfiguration.envListOption(\n+\t\t\t\"LIBCAMERA_IPA_MODULE_PATH\", { \"ipa\", \"module_paths\" });\n+\tfor (const auto &dir : modulePaths.value_or(std::vector<std::string>())) {\n+\t\tif (dir.empty())\n+\t\t\tcontinue;\n \n-\t\tif (!ipaCount)\n-\t\t\tLOG(IPAManager, Warning)\n-\t\t\t\t<< \"No IPA found in '\" << modulePaths << \"'\";\n+\t\tipaCount += addDir(dir.c_str());\n \t}\n \n+\tif (!ipaCount)\n+\t\tLOG(IPAManager, Warning) << \"No IPA found in '\"\n+\t\t\t\t\t << utils::join(modulePaths.value_or(std::vector<std::string>()), \":\")\n+\t\t\t\t\t << \"'\";\n+\n \t/*\n \t * When libcamera is used before it is installed, load IPAs from the\n \t * same build directory as the libcamera library itself.\n@@ -279,11 +289,10 @@ IPAModule *IPAManager::module(PipelineHandler *pipe, uint32_t minVersion,\n bool IPAManager::isSignatureValid([[maybe_unused]] IPAModule *ipa) const\n {\n #if HAVE_IPA_PUBKEY\n-\tchar *force = utils::secure_getenv(\"LIBCAMERA_IPA_FORCE_ISOLATION\");\n-\tif (force && force[0] != '\\0') {\n+\tif (forceIsolation_) {\n \t\tLOG(IPAManager, Debug)\n \t\t\t<< \"Isolation of IPA module \" << ipa->path()\n-\t\t\t<< \" forced through environment variable\";\n+\t\t\t<< \" forced through configuration\";\n \t\treturn false;\n \t}\n \ndiff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp\nindex 9907b9615..b845e9086 100644\n--- a/src/libcamera/ipa_proxy.cpp\n+++ b/src/libcamera/ipa_proxy.cpp\n@@ -7,13 +7,16 @@\n \n #include \"libcamera/internal/ipa_proxy.h\"\n \n+#include <string>\n #include <sys/stat.h>\n #include <sys/types.h>\n #include <unistd.h>\n+#include <vector>\n \n #include <libcamera/base/log.h>\n #include <libcamera/base/utils.h>\n \n+#include \"libcamera/internal/global_configuration.h\"\n #include \"libcamera/internal/ipa_module.h\"\n \n /**\n@@ -48,9 +51,12 @@ LOG_DEFINE_CATEGORY(IPAProxy)\n /**\n  * \\brief Construct an IPAProxy instance\n  * \\param[in] ipam The IPA module\n+ * \\param[in] configuration The global configuration\n  */\n-IPAProxy::IPAProxy(IPAModule *ipam)\n-\t: valid_(false), state_(ProxyStopped), ipam_(ipam)\n+IPAProxy::IPAProxy(IPAModule *ipam, const GlobalConfiguration &configuration)\n+\t: valid_(false), state_(ProxyStopped), ipam_(ipam),\n+\t  configPaths_(configuration.envListOption(\"LIBCAMERA_IPA_CONFIG_PATH\", { \"ipa\", \"config_paths\" }).value_or(std::vector<std::string>())),\n+\t  execPaths_(configuration.envListOption(\"LIBCAMERA_IPA_PROXY_PATH\", { \"ipa\", \"proxy_paths\" }).value_or(std::vector<std::string>()))\n {\n }\n \n@@ -122,20 +128,15 @@ std::string IPAProxy::configurationFile(const std::string &name,\n \tint ret;\n \n \t/*\n-\t * Check the directory pointed to by the IPA config path environment\n-\t * variable next.\n+\t * Check the directory pointed to by the IPA config path next.\n \t */\n-\tconst char *confPaths = utils::secure_getenv(\"LIBCAMERA_IPA_CONFIG_PATH\");\n-\tif (confPaths) {\n-\t\tfor (const auto &dir : utils::split(confPaths, \":\")) {\n-\t\t\tif (dir.empty())\n-\t\t\t\tcontinue;\n-\n-\t\t\tstd::string confPath = dir + \"/\" + ipaName + \"/\" + name;\n-\t\t\tret = stat(confPath.c_str(), &statbuf);\n-\t\t\tif (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)\n-\t\t\t\treturn confPath;\n-\t\t}\n+\tfor (const auto &dir : configPaths_) {\n+\t\tif (dir.empty())\n+\t\t\tcontinue;\n+\t\tstd::string confPath = dir + \"/\" + ipaName + \"/\" + name;\n+\t\tret = stat(confPath.c_str(), &statbuf);\n+\t\tif (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)\n+\t\t\treturn confPath;\n \t}\n \n \tstd::string root = utils::libcameraSourcePath();\n@@ -199,18 +200,14 @@ std::string IPAProxy::resolvePath(const std::string &file) const\n {\n \tstd::string proxyFile = \"/\" + file;\n \n-\t/* Check env variable first. */\n-\tconst char *execPaths = utils::secure_getenv(\"LIBCAMERA_IPA_PROXY_PATH\");\n-\tif (execPaths) {\n-\t\tfor (const auto &dir : utils::split(execPaths, \":\")) {\n-\t\t\tif (dir.empty())\n-\t\t\t\tcontinue;\n-\n-\t\t\tstd::string proxyPath = dir;\n-\t\t\tproxyPath += proxyFile;\n-\t\t\tif (!access(proxyPath.c_str(), X_OK))\n-\t\t\t\treturn proxyPath;\n-\t\t}\n+\t/* Check the configuration first. */\n+\tfor (const auto &dir : execPaths_) {\n+\t\tif (dir.empty())\n+\t\t\tcontinue;\n+\n+\t\tstd::string proxyPath = dir + proxyFile;\n+\t\tif (!access(proxyPath.c_str(), X_OK))\n+\t\t\treturn proxyPath;\n \t}\n \n \t/*\ndiff --git a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\nindex 9a3aadbd2..0f87e7976 100644\n--- a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n+++ b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl\n@@ -45,8 +45,8 @@ namespace {{ns}} {\n {% endfor %}\n {%- endif %}\n \n-{{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate)\n-\t: IPAProxy(ipam), isolate_(isolate),\n+{{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate, const GlobalConfiguration &configuration)\n+\t: IPAProxy(ipam, configuration), isolate_(isolate),\n \t  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)\n {\n \tLOG(IPAProxy, Debug)\ndiff --git a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl\nindex a0312a7c1..057c3ab03 100644\n--- a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl\n+++ b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl\n@@ -37,7 +37,7 @@ namespace {{ns}} {\n class {{proxy_name}} : public IPAProxy, public {{interface_name}}, public Object\n {\n public:\n-\t{{proxy_name}}(IPAModule *ipam, bool isolate);\n+\t{{proxy_name}}(IPAModule *ipam, bool isolate, const GlobalConfiguration &configuration);\n \t~{{proxy_name}}();\n \n {% for method in interface_main.methods %}\n",
    "prefixes": [
        "v15",
        "05/12"
    ]
}