From patchwork Thu Mar 2 00:54:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sophie Friedrich X-Patchwork-Id: 18329 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A9E03C3261 for ; Thu, 2 Mar 2023 09:29:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9BEE2626C8; Thu, 2 Mar 2023 10:29:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1677749396; bh=9U6iY4+Q2s1En2SBDBaj6yQqUpGudxyqScncLVANyKo=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Jnml9E2h3EAPyUoRvU7nUQWSkpLAOSL9UUaIl9H6jko4ySKTAA3CEzqMnfQ7/K5Kd Ocx1rA9jT1IcOeLsCZWR8/JVQ2anJjDeqsfoCvhIPpHr0/BnKLXQLkH55sHe0SSADX iIahjbq6Jrq8dwgjKkH0afrWzB5wD7o8LKU84kMvW66IBrxerku9olrXDu2sbe3ZVR HgMX9XFbphgaFWqNf5O4RIXxwmP9niK55uYnVc2nX5tLKXLLQP/owkIB8p7If1xYn0 tir5TVHNvXOdhe8IUJM8WWQRMzUMLtt2SkoXAV2xcSQkLHeGZHyqutU5CYd7G0ghye IEfpZcg6X0PBg== Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8A0606266A for ; Thu, 2 Mar 2023 01:54:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=flowerpot.me header.i=@flowerpot.me header.b="F6Y96M+3"; dkim-atps=neutral Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4PRt0h1Tdwz9sdv; Thu, 2 Mar 2023 01:54:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flowerpot.me; s=MBO0001; t=1677718468; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a1iL2p36+0aqfwJleMxVyqBAc3Z4KQrI57d9DUmusgI=; b=F6Y96M+3GiP0AseEaALqM/ys2pYXlnX7fkoNyNeivdw6ttIHzx2PWqlrEUf/EJh0/PljaL tRt2bEGim/fObCGuJLmSi63NAiTVIodTinys0Yd477MvilEfVUvE0mOhAx7f8+5DD8XOUc FO4pCVNorEt4O9cAiPUjAJwhNQ/w+ZlfwgilgdxtNOa+kxSxLFmv8atvYiSnnzzXKWxmfR VquaZVRLHuqkLCiZxnT15wDHGtBIB8sfbsz7Ni3xDaMDt/4himMHUJEKunwJ3Iiqt4hLYY tTvvJaC6zfRHoHayqBsg8ADjEFJzKJ1f1RPo41O5GXK/iZ8G3zQ3Dxm+CeBOdA== To: libcamera-devel@lists.libcamera.org Date: Thu, 2 Mar 2023 01:54:15 +0100 Message-Id: <20230302005415.1789544-2-dev@flowerpot.me> In-Reply-To: <20230302005415.1789544-1-dev@flowerpot.me> References: <20230302005415.1789544-1-dev@flowerpot.me> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4PRt0h1Tdwz9sdv X-Mailman-Approved-At: Thu, 02 Mar 2023 10:29:54 +0100 Subject: [libcamera-devel] [PATCH 1/1] libcamera: enumeration: Generalize DeviceMatch 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-Patchwork-Original-From: Sophie Friedrich via libcamera-devel From: Sophie Friedrich Reply-To: Sophie Friedrich Cc: Sophie Friedrich Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Currently `DeviceMatch` is very specialized to handle `MediaDevice`s, which has strong dependencies to V4L2 internals. This patch enables `DeviceMatch` to match using key/value pairs instead of a simple list of strings and introduces a `DeviceMatchEntityInterface` to abstract away the likes of `MediaEntity` in order to search for a device. Signed-off-by: Sophie Friedrich --- .../libcamera/internal/device_enumerator.h | 16 +-- include/libcamera/internal/device_match.h | 46 +++++++ include/libcamera/internal/media_device.h | 1 + include/libcamera/internal/media_object.h | 7 +- include/libcamera/internal/meson.build | 1 + src/libcamera/device_enumerator.cpp | 73 ---------- src/libcamera/device_match.cpp | 126 ++++++++++++++++++ src/libcamera/meson.build | 1 + 8 files changed, 183 insertions(+), 88 deletions(-) create mode 100644 include/libcamera/internal/device_match.h create mode 100644 src/libcamera/device_match.cpp diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h index 72ec9a60..259a9e46 100644 --- a/include/libcamera/internal/device_enumerator.h +++ b/include/libcamera/internal/device_enumerator.h @@ -13,24 +13,12 @@ #include +#include "libcamera/internal/device_match.h" + namespace libcamera { class MediaDevice; -class DeviceMatch -{ -public: - DeviceMatch(const std::string &driver); - - void add(const std::string &entity); - - bool match(const MediaDevice *device) const; - -private: - std::string driver_; - std::vector entities_; -}; - class DeviceEnumerator { public: diff --git a/include/libcamera/internal/device_match.h b/include/libcamera/internal/device_match.h new file mode 100644 index 00000000..e4563d3c --- /dev/null +++ b/include/libcamera/internal/device_match.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Sophie Friedrich + * + * device_match.h - API to match devices + */ + +#pragma once + +#include +#include + +#include + + +namespace libcamera { + +class MediaDevice; + +class DeviceMatchEntityInterface +{ +public: + virtual const std::string &match_key() const = 0; + virtual const std::string &match_value() const = 0; + virtual ~DeviceMatchEntityInterface() = default; + + static const std::string MATCH_ALL_KEY; +}; + +class DeviceMatch +{ +public: + DeviceMatch(const std::string &driver); + + void add(const std::string &entity); + void add(const std::string &key, const std::string &value); + + bool match(const MediaDevice *device) const; + +private: + std::string driver_; + std::vector> map_; +}; + + +} \ No newline at end of file diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h index eb8cfde4..b10bb2eb 100644 --- a/include/libcamera/internal/media_device.h +++ b/include/libcamera/internal/media_device.h @@ -19,6 +19,7 @@ #include #include "libcamera/internal/media_object.h" +#include "libcamera/internal/device_match.h" namespace libcamera { diff --git a/include/libcamera/internal/media_object.h b/include/libcamera/internal/media_object.h index b1572968..d07ed698 100644 --- a/include/libcamera/internal/media_object.h +++ b/include/libcamera/internal/media_object.h @@ -14,6 +14,8 @@ #include +#include "libcamera/internal/device_match.h" + namespace libcamera { class MediaDevice; @@ -85,7 +87,7 @@ private: std::vector links_; }; -class MediaEntity : public MediaObject +class MediaEntity : public MediaObject, public DeviceMatchEntityInterface { public: enum class Type { @@ -111,6 +113,9 @@ public: int setDeviceNode(const std::string &deviceNode); + const std::string &match_key() const{ return DeviceMatchEntityInterface::MATCH_ALL_KEY; } + const std::string &match_value() const { return name_; } + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(MediaEntity) diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index d7508805..1e3c15ed 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -21,6 +21,7 @@ libcamera_internal_headers = files([ 'control_validator.h', 'converter.h', 'delayed_controls.h', + 'device_match.h', 'device_enumerator.h', 'device_enumerator_sysfs.h', 'device_enumerator_udev.h', diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index f2e055de..49afd783 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -40,79 +40,6 @@ namespace libcamera { LOG_DEFINE_CATEGORY(DeviceEnumerator) -/** - * \class DeviceMatch - * \brief Description of a media device search pattern - * - * The DeviceMatch class describes a media device using properties from the - * Media Controller struct media_device_info, entity names in the media graph - * or other properties that can be used to identify a media device. - * - * The description is meant to be filled by pipeline managers and passed to a - * device enumerator to find matching media devices. - * - * A DeviceMatch is created with a specific Linux device driver in mind, - * therefore the name of the driver is a required property. One or more Entity - * names can be added as match criteria. - * - * Pipeline handlers are recommended to add entities to DeviceMatch as - * appropriare to ensure that the media device they need can be uniquely - * identified. This is useful when the corresponding kernel driver can produce - * different graphs, for instance as a result of different driver versions or - * hardware configurations, and not all those graphs are suitable for a pipeline - * handler. - */ - -/** - * \brief Construct a media device search pattern - * \param[in] driver The Linux device driver name that created the media device - */ -DeviceMatch::DeviceMatch(const std::string &driver) - : driver_(driver) -{ -} - -/** - * \brief Add a media entity name to the search pattern - * \param[in] entity The name of the entity in the media graph - */ -void DeviceMatch::add(const std::string &entity) -{ - entities_.push_back(entity); -} - -/** - * \brief Compare a search pattern with a media device - * \param[in] device The media device - * - * Matching is performed on the Linux device driver name and entity names from - * the media graph. A match is found if both the driver name matches and the - * media device contains all the entities listed in the search pattern. - * - * \return true if the media device matches the search pattern, false otherwise - */ -bool DeviceMatch::match(const MediaDevice *device) const -{ - if (driver_ != device->driver()) - return false; - - for (const std::string &name : entities_) { - bool found = false; - - for (const MediaEntity *entity : device->entities()) { - if (name == entity->name()) { - found = true; - break; - } - } - - if (!found) - return false; - } - - return true; -} - /** * \class DeviceEnumerator * \brief Enumerate, store and search media devices diff --git a/src/libcamera/device_match.cpp b/src/libcamera/device_match.cpp new file mode 100644 index 00000000..0c205f93 --- /dev/null +++ b/src/libcamera/device_match.cpp @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Sophie Friedrich + * + * device_match.cpp - API to match devices + */ + +#include "libcamera/internal/device_match.h" + +#include + +#include + +#include "libcamera/internal/media_device.h" + +/** + * \file device_match.h + * \brief Matching of media devices + * + * Pipelines find compatible devices by matching against known strings or + * key/value pairs during device enumeration. MediaDevice are responsible for + * finding these entities during their population phase. + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(DeviceMatch) + +/** + * \interface DeviceMatchInterface + * \brief Interface which enables matching using DeviceMatch + * + * + * + */ +const std::string DeviceMatchEntityInterface::MATCH_ALL_KEY = "*"; + +/** + * \class DeviceMatch + * \brief Description of a media device search pattern + * + * The DeviceMatch class describes a media device using properties from the + * Media Controller struct media_device_info, entity names in the media graph + * or other properties that can be used to identify a media device. + * + * The description is meant to be filled by pipeline managers and passed to a + * device enumerator to find matching media devices. + * + * A DeviceMatch is created with a specific Linux device driver in mind, + * therefore the name of the driver is a required property. One or more Entity + * names can be added as match criteria. + * + * Pipeline handlers are recommended to add entities to DeviceMatch as + * appropriare to ensure that the media device they need can be uniquely + * identified. This is useful when the corresponding kernel driver can produce + * different graphs, for instance as a result of different driver versions or + * hardware configurations, and not all those graphs are suitable for a pipeline + * handler. + */ + +/** + * \brief Construct a media device search pattern + * \param[in] driver The Linux device driver name that created the media device + */ +DeviceMatch::DeviceMatch(const std::string &driver) + : driver_(driver) +{ +} + +/** + * \brief Add a media entity name to the search pattern + * \param[in] entity The name of the entity in the media graph + */ +void DeviceMatch::add(const std::string &entity) +{ + add(DeviceMatchEntityInterface::MATCH_ALL_KEY, entity); +} + +/** + * \brief Add key / value pair to search pattern + * \param[in] key The key the value is associated to + * \param[in] value The value that should be searched for + * + * There is no uniqueness enforced to key/value. Mentioning a certain + * key multiple times (in best case with different values) allows matching + * multiple properties on the same key. + */ +void DeviceMatch::add(const std::string &key, const std::string &value) +{ + map_.push_back(std::pair(key, value)); +} + +/** + * \brief Compare a search pattern with a media device + * \param[in] device The media device + * + * Matching is performed on the Linux device driver name and entity names from + * the media graph. A match is found if both the driver name matches and the + * media device contains all the entities listed in the search pattern. + * + * \return true if the media device matches the search pattern, false otherwise + */ +bool DeviceMatch::match(const MediaDevice *device) const +{ + if (driver_ != device->driver()) + return false; + + for (const std::pair &item : map_) { + bool found = false; + + for (const DeviceMatchEntityInterface *entity : device->entities()) { + if (item.first == entity->match_key() && + item.second == entity->match_value()) { + found = true; + break; + } + } + + if (!found) + return false; + } + + return true; +} + +} \ No newline at end of file diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 9869bfe7..445eb8e9 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -15,6 +15,7 @@ libcamera_sources = files([ 'control_validator.cpp', 'converter.cpp', 'delayed_controls.cpp', + 'device_match.cpp', 'device_enumerator.cpp', 'device_enumerator_sysfs.cpp', 'fence.cpp',