Show a patch.

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

{
    "id": 25345,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/25345/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/25345/",
    "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": "<20251203-rzv2h-pre-v3-2-1493e0638626@ideasonboard.com>",
    "date": "2025-12-03T09:14:22",
    "name": "[v3,2/4] libcamera: device_enumerator: Support regex to match entity names",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "751d49990050ab0dd1299729e4057a2bfdbfdcf8",
    "submitter": {
        "id": 143,
        "url": "https://patchwork.libcamera.org/api/1.1/people/143/?format=api",
        "name": "Jacopo Mondi",
        "email": "jacopo.mondi@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/25345/mbox/",
    "series": [
        {
            "id": 5634,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5634/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5634",
            "date": "2025-12-03T09:14:20",
            "name": "Use regular expressions for entity name matching",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/5634/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/25345/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/25345/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 E0948BD80A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  3 Dec 2025 09:14:47 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F1EC660D39;\n\tWed,  3 Dec 2025 10:14:45 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6C0A6606A0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  3 Dec 2025 10:14:42 +0100 (CET)",
            "from [192.168.1.104] (net-93-65-100-155.cust.vodafonedsl.it\n\t[93.65.100.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 6F8431574;\n\tWed,  3 Dec 2025 10:12:27 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"W1rTEZaN\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1764753147;\n\tbh=ga6BwroBLPac8/Chk0wzAVk1un0uWO+DSXQvAFxHmhU=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=W1rTEZaNr9ngA7WErodwJLy+vWa4dgCVJfvxV8zqAerS2PKKSv5abOBipo7svJjcn\n\tgUWdO/tMQSS0u5khy2J/Bij/mLoy3ZElpzhlyuNfQDZ2DVa4wQ6Xe59c/plg8bNkLE\n\tlH5IFA6dh2ldhdPhQLkyQBaa1D+sIGGSNtw0hRQE=",
        "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "Date": "Wed, 03 Dec 2025 10:14:22 +0100",
        "Subject": "[PATCH v3 2/4] libcamera: device_enumerator: Support regex to\n\tmatch entity names",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20251203-rzv2h-pre-v3-2-1493e0638626@ideasonboard.com>",
        "References": "<20251203-rzv2h-pre-v3-0-1493e0638626@ideasonboard.com>",
        "In-Reply-To": "<20251203-rzv2h-pre-v3-0-1493e0638626@ideasonboard.com>",
        "To": "Daniel Scally <dan.scally@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org",
        "Cc": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "X-Mailer": "b4 0.14.2",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=5163;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=PboEjt+8hFEbpw7D3On0uCQE59Q+aRwMemUVw2PRQ5g=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpL/+AW0MuITsvieOHMSpOS7jxh5H/f6T7JJLGF\n\tKtBEusw4kiJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaS//gAAKCRByNAaPFqFW\n\tPOZVD/95OLrShplfrDQBdkqUHXvglekOIDpt6L41183Pn07KmLQyMDkQ5dnN0oA/aDhdb8wNByU\n\tuDWre5qRvFqFBImPbgotnvu7YUcZY6wMtM2bKK3qNOGXrZv07KYZre/nlYgv6PVPOYpku/tD7Wc\n\tWG+imOY9HqOXvN1jqNLYHNjQPld1qjFvqXMHXN6KuV9UeIUtLmoZtCvkoIhJwvZ+bkCLzU7Nkza\n\tpuZLdmTTH1Mh1dyZgZ2pGL6xIQj5UBSfL/ElE216u6iewdi6ocSvFzXq7w9abhMC4sdS7mImDFb\n\t0gQmPkn5NLsSYXrl7rgrpaGB+Pe2BkMAw6nBQj2+s4ahAY9t2YIXyoGGQccmWmkc+Sg8LWCG/cv\n\tcgPgVJPid1R8DGpvoQyAtprRQ3x3HaiyUY44y3UWm+2vQ8ZQ6rlVocO6v1l6tcBGX6Bzvev8Vri\n\twDiUVLm9/L0OmH9W0J9OR74DwbDCLmY6eP1u4vABiMGNpUsnk10AKyCKdtgQpOonS5m3lW8JgA1\n\t1tOcVTU3fjJKXIOg/voQoe4vGLooaPrUZ44M/8Lvizbfg2K2urix6Pp/ubW+sdUdZhWjhX5czWx\n\t6pg1VVpE4lhfC+lPLgbXatxTH05/JO/SuD1VAIPJUIa+sVuzx9nUbeDMgqrbqYh6iNUG5mlaZGb\n\tpxlbLmdotMdg3ZA==",
        "X-Developer-Key": "i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B",
        "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": "From: Daniel Scally <dan.scally@ideasonboard.com>\n\nSome entities in a media graph have names that might differ from\nimplementation to implementation; for example the Camera Receiver\nUnit and CSI-2 receiver on the RZ/V2H(P) SoC have entities with names\nthat include their address, in the form \"csi-16000400.csi2\". Passing\nthat entity name to DeviceMatch is too inflexible given it would only\nwork if that specific CSI-2 receiver were the one being used.\n\nAdd an overload for DeviceMatch::add() such that users can pass in a\nstd::regex instead of a string. Update DeviceMatch::match() to check\nfor entities that are matched by the regular expressions added with\nthe new overload after checking for any exact matches from the vector\nof strings. This allows us to use regex to match on patterns like\n\"csi-[0-9a-f]{8}.csi2\".\n\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\n---\nChanges in v3:\n- As suggested by Barnabas accept an std::regex in add() instead of a\n  reference and move it into the entityRegexs_ vector\n\n- Exit early in DeviceMatch::match()\n\n\tfor (const MediaEntity *entity : device->entities()) {\n\t\tif (!std::regex_search(entity->name(), nameRegex))\n\t\t\tcontinue;\n\n\t\tif (found) {\n\n\t\t}\n\t}\n\n  Compared to\n\n\tfor (const MediaEntity *entity : device->entities()) {\n\t\tif (std::regex_search(entity->name(), nameRegex)) {\n\t\t\tif (found) {\n\n\t\t\t}\n\t\t}\n\t}\n\n- Invert the error logic when deviceNode is empty\n\n\tif (entity->deviceNode().empty()) {\n\t\tLOG(DeviceEnumerator, Debug)\n\t\t\t<< \"Skip \" << entity->name()\n\t\t\t<< \": no device node\";\n\t\tcontinue;\n\t}\n\n\tfound = true;\n\n  Compared to\n\n\tif (!entity->deviceNode().empty()) {\n\t\tfound = true;\n\t} else {\n\t\t LOG(DeviceEnumerator, Debug)\n\t\t\t<< \"Skip \" << entity->name()\n\t\t\t<< \": no device node\";\n\t}\n\nChanges in v2:\n\n    - Instead of replacing the existing ::add() function and\n      matching process with regex, add an overload for ::add()\n      that takes a regex and incorporate that into ::match()\n      alongside the existing functionality.\n---\n include/libcamera/internal/device_enumerator.h |  3 ++\n src/libcamera/device_enumerator.cpp            | 39 +++++++++++++++++++++++++-\n 2 files changed, 41 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h\nindex db3532a9887af913ceee20cbba3f945e56e7b61d..fa8806b0c2a47ab89fdc74fe01ef77bf2e68abb1 100644\n--- a/include/libcamera/internal/device_enumerator.h\n+++ b/include/libcamera/internal/device_enumerator.h\n@@ -11,6 +11,7 @@\n #include <string>\n #include <vector>\n \n+#include <libcamera/base/regex.h>\n #include <libcamera/base/signal.h>\n \n namespace libcamera {\n@@ -23,12 +24,14 @@ public:\n \tDeviceMatch(const std::string &driver);\n \n \tvoid add(const std::string &entity);\n+\tvoid add(const std::regex entity);\n \n \tbool match(const MediaDevice *device) const;\n \n private:\n \tstd::string driver_;\n \tstd::vector<std::string> entities_;\n+\tstd::vector<std::regex> entityRegexs_;\n };\n \n class DeviceEnumerator\ndiff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp\nindex ae17862f676310ef568e5331106ed661e84b5130..2911d5f0385f9765a2eafce2085d1fd627d94b95 100644\n--- a/src/libcamera/device_enumerator.cpp\n+++ b/src/libcamera/device_enumerator.cpp\n@@ -53,7 +53,8 @@ LOG_DEFINE_CATEGORY(DeviceEnumerator)\n  *\n  * A DeviceMatch is created with a specific Linux device driver in mind,\n  * therefore the name of the driver is a required property. One or more Entity\n- * names can be added as match criteria.\n+ * names (or regular expressions designed to match an entity name) can be added\n+ * as match criteria.\n  *\n  * Pipeline handlers are recommended to add entities to DeviceMatch as\n  * appropriate to ensure that the media device they need can be uniquely\n@@ -81,6 +82,15 @@ void DeviceMatch::add(const std::string &entity)\n \tentities_.push_back(entity);\n }\n \n+/**\n+ * \\brief Add a regex to match a media entity name to the search pattern\n+ * \\param[in] entity The regex intended to match to an entity in the media graph\n+ */\n+void DeviceMatch::add(const std::regex entity)\n+{\n+\tentityRegexs_.push_back(std::move(entity));\n+}\n+\n /**\n  * \\brief Compare a search pattern with a media device\n  * \\param[in] device The media device\n@@ -116,6 +126,33 @@ bool DeviceMatch::match(const MediaDevice *device) const\n \t\t\treturn false;\n \t}\n \n+\tfor (const std::regex &nameRegex : entityRegexs_) {\n+\t\tbool found = false;\n+\n+\t\tfor (const MediaEntity *entity : device->entities()) {\n+\t\t\tif (!std::regex_search(entity->name(), nameRegex))\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (found) {\n+\t\t\t\tLOG(DeviceEnumerator, Error)\n+\t\t\t\t\t<< \"Multiple entities match regex\";\n+\t\t\t\treturn false;\n+\t\t\t}\n+\n+\t\t\tif (entity->deviceNode().empty()) {\n+\t\t\t\tLOG(DeviceEnumerator, Debug)\n+\t\t\t\t\t<< \"Skip \" << entity->name()\n+\t\t\t\t\t<< \": no device node\";\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tfound = true;\n+\t\t}\n+\n+\t\tif (!found)\n+\t\t\treturn false;\n+\t}\n+\n \treturn true;\n }\n \n",
    "prefixes": [
        "v3",
        "2/4"
    ]
}