summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/include/media_device.h4
-rw-r--r--src/libcamera/include/media_object.h1
-rw-r--r--src/libcamera/media_device.cpp75
-rw-r--r--src/libcamera/media_object.cpp29
4 files changed, 109 insertions, 0 deletions
diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h
index 22c32b7e..a8dec0d3 100644
--- a/src/libcamera/include/media_device.h
+++ b/src/libcamera/include/media_device.h
@@ -45,6 +45,7 @@ public:
MediaLink *link(const MediaEntity *source, unsigned int sourceIdx,
const MediaEntity *sink, unsigned int sinkIdx);
MediaLink *link(const MediaPad *source, const MediaPad *sink);
+ int disableLinks();
private:
std::string driver_;
@@ -65,6 +66,9 @@ private:
bool populateEntities(const struct media_v2_topology &topology);
bool populatePads(const struct media_v2_topology &topology);
bool populateLinks(const struct media_v2_topology &topology);
+
+ friend int MediaLink::setEnabled(bool enable);
+ int setupLink(const MediaLink *link, unsigned int flags);
};
} /* namespace libcamera */
diff --git a/src/libcamera/include/media_object.h b/src/libcamera/include/media_object.h
index b2c3d8e9..7fc44415 100644
--- a/src/libcamera/include/media_object.h
+++ b/src/libcamera/include/media_object.h
@@ -41,6 +41,7 @@ public:
MediaPad *source() const { return source_; }
MediaPad *sink() const { return sink_; }
unsigned int flags() const { return flags_; }
+ int setEnabled(bool enable);
private:
friend class MediaDevice;
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index ca12caaa..0ee55060 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -387,6 +387,35 @@ MediaLink *MediaDevice::link(const MediaPad *source, const MediaPad *sink)
}
/**
+ * \brief Disable all links in the media device
+ *
+ * Disable all the media device links, clearing the MEDIA_LNK_FL_ENABLED flag
+ * on links which are not flagged as IMMUTABLE.
+ *
+ * \return 0 on success, or a negative error code otherwise
+ */
+int MediaDevice::disableLinks()
+{
+ for (MediaEntity *entity : entities_) {
+ for (MediaPad *pad : entity->pads()) {
+ if (!(pad->flags() & MEDIA_PAD_FL_SOURCE))
+ continue;
+
+ for (MediaLink *link : pad->links()) {
+ if (link->flags() & MEDIA_LNK_FL_IMMUTABLE)
+ continue;
+
+ int ret = link->setEnabled(false);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
* \var MediaDevice::objects_
* \brief Global map of media objects (entities, pads, links) keyed by their
* object id.
@@ -602,4 +631,50 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology)
return true;
}
+/**
+ * \brief Apply \a flags to a link between two pads
+ * \param link The link to apply flags to
+ * \param flags The flags to apply to the link
+ *
+ * This function applies the link \a flags (as defined by the MEDIA_LNK_FL_*
+ * macros from the Media Controller API) to the given \a link. It implements
+ * low-level link setup as it performs no checks on the validity of the \a
+ * flags, and assumes that the supplied \a flags are valid for the link (e.g.
+ * immutable links cannot be disabled).
+*
+ * \sa MediaLink::setEnabled(bool enable)
+ *
+ * \return 0 on success, or a negative error code otherwise
+ */
+int MediaDevice::setupLink(const MediaLink *link, unsigned int flags)
+{
+ struct media_link_desc linkDesc = { };
+ MediaPad *source = link->source();
+ MediaPad *sink = link->sink();
+
+ linkDesc.source.entity = source->entity()->id();
+ linkDesc.source.index = source->index();
+ linkDesc.source.flags = MEDIA_PAD_FL_SOURCE;
+
+ linkDesc.sink.entity = sink->entity()->id();
+ linkDesc.sink.index = sink->index();
+ linkDesc.sink.flags = MEDIA_PAD_FL_SINK;
+
+ linkDesc.flags = flags;
+
+ int ret = ioctl(fd_, MEDIA_IOC_SETUP_LINK, &linkDesc);
+ if (ret) {
+ ret = -errno;
+ LOG(Error) << "Failed to setup link: " << strerror(-ret);
+ return ret;
+ }
+
+ LOG(Debug) << source->entity()->name() << "["
+ << source->index() << "] -> "
+ << sink->entity()->name() << "["
+ << sink->index() << "]: " << flags;
+
+ return 0;
+}
+
} /* namespace libcamera */
diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp
index 4ff9620d..cb3af85e 100644
--- a/src/libcamera/media_object.cpp
+++ b/src/libcamera/media_object.cpp
@@ -15,6 +15,7 @@
#include <linux/media.h>
#include "log.h"
+#include "media_device.h"
#include "media_object.h"
/**
@@ -96,6 +97,34 @@ namespace libcamera {
*/
/**
+ * \brief Enable or disable a link
+ * \param enable True to enable the link, false to disable it
+ *
+ * Set the status of a link according to the value of \a enable.
+ * Links between two pads can be set to the enabled or disabled state freely,
+ * unless they're immutable links, whose status cannot be changed.
+ * Enabling an immutable link is not considered an error, while trying to
+ * disable it is.
+ *
+ * Enabling a link establishes a data connection between two pads, while
+ * disabling it interrupts that connection.
+ *
+ * \return 0 on success, or a negative error code otherwise
+ */
+int MediaLink::setEnabled(bool enable)
+{
+ unsigned int flags = enable ? MEDIA_LNK_FL_ENABLED : 0;
+
+ int ret = dev_->setupLink(this, flags);
+ if (ret)
+ return ret;
+
+ flags_ = flags;
+
+ return 0;
+}
+
+/**
* \brief Construct a MediaLink
* \param link The media link kernel data
* \param source The source pad at the origin of the link