[libcamera-devel,2/5] libcamera: media_device: Handle ancillary links in populateLinks()
diff mbox series

Message ID 20211126003118.42356-3-djrscally@gmail.com
State Superseded
Headers show
Series
  • Enumerate CameraLens by following sensor's ancillary links
Related show

Commit Message

Daniel Scally Nov. 26, 2021, 12:31 a.m. UTC
The populateLinks() function can't currently handle ancillary links
which causes an error to be thrown in process() when the MediaObject
cannot be cast to a MediaPad.

Add explicit handling for the different link types, creating either
pad-2-pad or entity-2-entity versions of a MediaLink based on the
link type in the link's flags.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
 include/linux/media.h          |  1 +
 src/libcamera/media_device.cpp | 52 ++++++++++++++++++++++++----------
 2 files changed, 38 insertions(+), 15 deletions(-)

Patch
diff mbox series

diff --git a/include/linux/media.h b/include/linux/media.h
index 17432318..e3123d1a 100644
--- a/include/linux/media.h
+++ b/include/linux/media.h
@@ -222,6 +222,7 @@  struct media_pad_desc {
 #define MEDIA_LNK_FL_LINK_TYPE			(0xf << 28)
 #  define MEDIA_LNK_FL_DATA_LINK		(0 << 28)
 #  define MEDIA_LNK_FL_INTERFACE_LINK		(1 << 28)
+#  define MEDIA_LNK_FL_ANCILLARY_LINK		(2 << 28)
 
 struct media_link_desc {
 	struct media_pad_desc source;
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index aa93da75..8133c534 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -699,45 +699,67 @@  bool MediaDevice::populateLinks(const struct media_v2_topology &topology)
 {
 	struct media_v2_link *mediaLinks = reinterpret_cast<struct media_v2_link *>
 					   (topology.ptr_links);
+	unsigned int link_type;
+	MediaLink *link;
 
 	for (unsigned int i = 0; i < topology.num_links; ++i) {
 		/*
 		 * Skip links between entities and interfaces: we only care
-		 * about pad-2-pad links here.
+		 * about pad-2-pad and entity-2-entity links here.
 		 */
 		if ((mediaLinks[i].flags & MEDIA_LNK_FL_LINK_TYPE) ==
 		    MEDIA_LNK_FL_INTERFACE_LINK)
 			continue;
 
-		/* Store references to source and sink pads in the link. */
+		/* Store references to source and sink objects in the link. */
 		unsigned int source_id = mediaLinks[i].source_id;
-		MediaPad *source = dynamic_cast<MediaPad *>
-				   (object(source_id));
+		MediaObject *source = object(source_id);
 		if (!source) {
 			LOG(MediaDevice, Error)
-				<< "Failed to find pad with id: "
+				<< "Failed to find MediaObject with id: "
 				<< source_id;
 			return false;
 		}
 
 		unsigned int sink_id = mediaLinks[i].sink_id;
-		MediaPad *sink = dynamic_cast<MediaPad *>
-				 (object(sink_id));
+		MediaObject *sink = object(sink_id);
 		if (!sink) {
 			LOG(MediaDevice, Error)
-				<< "Failed to find pad with id: "
+				<< "Failed to find MediaObject with id: "
 				<< sink_id;
 			return false;
 		}
 
-		MediaLink *link = new MediaLink(&mediaLinks[i], source, sink);
-		if (!addObject(link)) {
-			delete link;
-			return false;
-		}
+		link_type = mediaLinks[i].flags & MEDIA_LNK_FL_LINK_TYPE;
+
+		switch (link_type) {
+		case MEDIA_LNK_FL_DATA_LINK:
+			link = new MediaLink(&mediaLinks[i],
+					     dynamic_cast<MediaPad *>(source),
+					     dynamic_cast<MediaPad *>(sink));
+			if (!addObject(link)) {
+				delete link;
+				return false;
+			}
+
+			link->source()->addLink(link);
+			link->sink()->addLink(link);
 
-		source->addLink(link);
-		sink->addLink(link);
+			break;
+		case MEDIA_LNK_FL_ANCILLARY_LINK:
+			link = new MediaLink(&mediaLinks[i],
+					     dynamic_cast<MediaEntity *>(source),
+					     dynamic_cast<MediaEntity *>(sink));
+			if (!addObject(link)) {
+				delete link;
+				return false;
+			}
+
+			link->primary()->addLink(link);
+			link->ancillary()->addLink(link);
+
+			break;
+		}
 	}
 
 	return true;