[libcamera-devel] [PATCH 1/1] libcamera: enumeration: Generalize DeviceMatch
Sophie Friedrich
dev at flowerpot.me
Thu Mar 2 01:54:15 CET 2023
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 <dev at flowerpot.me>
---
.../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 <libcamera/base/signal.h>
+#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<std::string> 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 <string>
+#include <vector>
+
+#include <libcamera/base/class.h>
+
+
+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<std::pair<std::string, std::string>> 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 <libcamera/base/unique_fd.h>
#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 <libcamera/base/class.h>
+#include "libcamera/internal/device_match.h"
+
namespace libcamera {
class MediaDevice;
@@ -85,7 +87,7 @@ private:
std::vector<MediaLink *> 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 <string.h>
+
+#include <libcamera/base/log.h>
+
+#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<std::string, std::string> &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',
--
2.34.1
More information about the libcamera-devel
mailing list