[v2,2/4] libcamera: device_enumerator: Support regex to match entity names
diff mbox series

Message ID 20250717124853.2317191-3-dan.scally@ideasonboard.com
State New
Headers show
Series
  • Use regular expressions for entity name matching
Related show

Commit Message

Daniel Scally July 17, 2025, 12:48 p.m. UTC
Some entities in a media graph have names that might differ from
implementation to implementation; for example the Camera Receiver
Unit and CSI-2 receiver on the KakiP board have entities with names
that include their address, in the form "csi-16000400.csi2". Passing
that entity name to DeviceMatch is too inflexible given it would only
work if that specific CSI-2 receiver were the one being used.

Add an overload for DeviceMatch::add() such that users can pass in a
std::regex instead of a string. Update DeviceMatch::match() to check
for entities that are matched by the regular expressions added with
the new overload after checking for any exact matches from the vector
of strings. This allows us to use regex to match on patterns like
"csi-[0-9a-f]{8}.csi2".

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
---
Changes in v2:

	- Instead of replacing the existing ::add() function and
	matching process with regex, add an overload for ::add()
	that takes a regex and incorporate that into ::match()
	alongside the existing functionality.

 .../libcamera/internal/device_enumerator.h    |  4 +-
 src/libcamera/device_enumerator.cpp           | 37 ++++++++++++++++++-
 2 files changed, 39 insertions(+), 2 deletions(-)

Comments

Barnabás Pőcze July 17, 2025, 3:46 p.m. UTC | #1
Hi

2025. 07. 17. 14:48 keltezéssel, Daniel Scally írta:
> Some entities in a media graph have names that might differ from
> implementation to implementation; for example the Camera Receiver
> Unit and CSI-2 receiver on the KakiP board have entities with names
> that include their address, in the form "csi-16000400.csi2". Passing
> that entity name to DeviceMatch is too inflexible given it would only
> work if that specific CSI-2 receiver were the one being used.
> 
> Add an overload for DeviceMatch::add() such that users can pass in a
> std::regex instead of a string. Update DeviceMatch::match() to check
> for entities that are matched by the regular expressions added with
> the new overload after checking for any exact matches from the vector
> of strings. This allows us to use regex to match on patterns like
> "csi-[0-9a-f]{8}.csi2".
> 
> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> ---
> Changes in v2:
> 
> 	- Instead of replacing the existing ::add() function and
> 	matching process with regex, add an overload for ::add()
> 	that takes a regex and incorporate that into ::match()
> 	alongside the existing functionality.
> 
>   .../libcamera/internal/device_enumerator.h    |  4 +-
>   src/libcamera/device_enumerator.cpp           | 37 ++++++++++++++++++-
>   2 files changed, 39 insertions(+), 2 deletions(-)
> 
> diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h
> index db3532a9..4e55e172 100644
> --- a/include/libcamera/internal/device_enumerator.h
> +++ b/include/libcamera/internal/device_enumerator.h
> @@ -11,6 +11,7 @@
>   #include <string>
>   #include <vector>
>   
> +#include <libcamera/base/regex.h>
>   #include <libcamera/base/signal.h>
>   
>   namespace libcamera {
> @@ -23,12 +24,13 @@ public:
>   	DeviceMatch(const std::string &driver);
>   
>   	void add(const std::string &entity);
> -
> +	void add(const std::regex &entity);
>   	bool match(const MediaDevice *device) const;
>   
>   private:
>   	std::string driver_;
>   	std::vector<std::string> entities_;
> +	std::vector<std::regex> entityRegexs_;
>   };
>   
>   class DeviceEnumerator
> diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
> index ae17862f..191758ca 100644
> --- a/src/libcamera/device_enumerator.cpp
> +++ b/src/libcamera/device_enumerator.cpp
> @@ -53,7 +53,8 @@ LOG_DEFINE_CATEGORY(DeviceEnumerator)
>    *
>    * 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.
> + * names (or regular expressions designed to match an entity name) can be added
> + * as match criteria.
>    *
>    * Pipeline handlers are recommended to add entities to DeviceMatch as
>    * appropriate to ensure that the media device they need can be uniquely
> @@ -81,6 +82,15 @@ void DeviceMatch::add(const std::string &entity)
>   	entities_.push_back(entity);
>   }
>   
> +/**
> + * \brief Add a regex to match a media entity name to the search pattern
> + * \param[in] entity The regex intended to match to an entity in the media graph
> + */
> +void DeviceMatch::add(const std::regex &entity)
> +{
> +	entityRegexs_.push_back(entity);

void DeviceMatch::add(std::regex entity)
{
     entityRegexs_.push_back(std::move(entity));


> +}
> +
>   /**
>    * \brief Compare a search pattern with a media device
>    * \param[in] device The media device
> @@ -116,6 +126,31 @@ bool DeviceMatch::match(const MediaDevice *device) const
>   			return false;
>   	}
>   
> +	for (const std::regex &nameRegex : entityRegexs_) {
> +		bool found = false;
> +
> +		for (const MediaEntity *entity : device->entities()) {
> +			if (std::regex_search(entity->name(), nameRegex)) {

Why not `regex_match()`? I feel like maybe the whole name should be matched
by default? I believe it would make sense from a consistency point of view
since `entities_` only allows full matches.


> +				if (found) {
> +					LOG(DeviceEnumerator, Error)
> +						<< "Multiple entities match regex";

I suppose another concern could be if multiple regex patterns match the same
entity. Although that is probably the smaller issue out of the two.


Regards,
Barnabás Pőcze


> +					return false;
> +				}
> +
> +				if (!entity->deviceNode().empty()) {
> +					found = true;
> +				} else {
> +					LOG(DeviceEnumerator, Debug)
> +						<< "Skip " << entity->name()
> +						<< ": no device node";
> +				}
> +			}
> +		}
> +
> +		if (!found)
> +			return false;
> +	}
> +
>   	return true;
>   }
>

Patch
diff mbox series

diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h
index db3532a9..4e55e172 100644
--- a/include/libcamera/internal/device_enumerator.h
+++ b/include/libcamera/internal/device_enumerator.h
@@ -11,6 +11,7 @@ 
 #include <string>
 #include <vector>
 
+#include <libcamera/base/regex.h>
 #include <libcamera/base/signal.h>
 
 namespace libcamera {
@@ -23,12 +24,13 @@  public:
 	DeviceMatch(const std::string &driver);
 
 	void add(const std::string &entity);
-
+	void add(const std::regex &entity);
 	bool match(const MediaDevice *device) const;
 
 private:
 	std::string driver_;
 	std::vector<std::string> entities_;
+	std::vector<std::regex> entityRegexs_;
 };
 
 class DeviceEnumerator
diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
index ae17862f..191758ca 100644
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -53,7 +53,8 @@  LOG_DEFINE_CATEGORY(DeviceEnumerator)
  *
  * 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.
+ * names (or regular expressions designed to match an entity name) can be added
+ * as match criteria.
  *
  * Pipeline handlers are recommended to add entities to DeviceMatch as
  * appropriate to ensure that the media device they need can be uniquely
@@ -81,6 +82,15 @@  void DeviceMatch::add(const std::string &entity)
 	entities_.push_back(entity);
 }
 
+/**
+ * \brief Add a regex to match a media entity name to the search pattern
+ * \param[in] entity The regex intended to match to an entity in the media graph
+ */
+void DeviceMatch::add(const std::regex &entity)
+{
+	entityRegexs_.push_back(entity);
+}
+
 /**
  * \brief Compare a search pattern with a media device
  * \param[in] device The media device
@@ -116,6 +126,31 @@  bool DeviceMatch::match(const MediaDevice *device) const
 			return false;
 	}
 
+	for (const std::regex &nameRegex : entityRegexs_) {
+		bool found = false;
+
+		for (const MediaEntity *entity : device->entities()) {
+			if (std::regex_search(entity->name(), nameRegex)) {
+				if (found) {
+					LOG(DeviceEnumerator, Error)
+						<< "Multiple entities match regex";
+					return false;
+				}
+
+				if (!entity->deviceNode().empty()) {
+					found = true;
+				} else {
+					LOG(DeviceEnumerator, Debug)
+						<< "Skip " << entity->name()
+						<< ": no device node";
+				}
+			}
+		}
+
+		if (!found)
+			return false;
+	}
+
 	return true;
 }