diff options
-rw-r--r-- | src/libcamera/include/media_device.h | 4 | ||||
-rw-r--r-- | src/libcamera/include/media_object.h | 1 | ||||
-rw-r--r-- | src/libcamera/media_device.cpp | 75 | ||||
-rw-r--r-- | src/libcamera/media_object.cpp | 29 |
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 |