[libcamera-devel] [PATCH v2 3/4] libcamera: Add link handling functions

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Jan 8 19:18:45 CET 2019


Hi Jacopo,

Thank you for the patch.

On Tuesday, 8 January 2019 19:04:06 EET Jacopo Mondi wrote:
> Add a function to the MediaLink class to set the state of a link to
> enabled or disabled. The function makes use of an internal MediaDevice
> method, which is defined private and only accessible by the MediaLink
> setEnable() function itself.
> 
> Also add to MediaDevice a function to reset all links registered in the
> media graph.

I would have split this to a separate patch, but it's not a big deal.

> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
> v1->v2:
> - Add resetLinks() function
> - s/enable()/setEnable()
> - s/setLink()/setupLink()
> - Pass MediaLink and not two MediaPads to MediaDevice::setupLink
> 
>  src/libcamera/include/media_device.h |  4 ++
>  src/libcamera/include/media_object.h |  1 +
>  src/libcamera/media_device.cpp       | 75 ++++++++++++++++++++++++++++
>  src/libcamera/media_object.cpp       | 29 +++++++++++
>  4 files changed, 109 insertions(+)
> 
> diff --git a/src/libcamera/include/media_device.h
> b/src/libcamera/include/media_device.h index 397d349..0f423aa 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 resetLinks();

I wonder if this should be called disableLinks() or disableAllLinks() to 
better reflect the purpose.

> 
>  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::setEnable(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 d92aab3..bb46fac 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 setEnable(bool enable);

s/setEnable/setEnabled/ ?

> 
>  private:
>  	friend class MediaDevice;
> diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
> index 7ce5c22..9900c3f 100644
> --- a/src/libcamera/media_device.cpp
> +++ b/src/libcamera/media_device.cpp
> @@ -385,6 +385,35 @@ MediaLink *MediaDevice::link(const MediaPad *source,
> const MediaPad *sink) return nullptr;
>  }
> 
> +/**
> + * \brief Reset all links in the media device

How about "Disable all links in the media device" ?

> + *
> + * Reset the media device links, clearing the MEDIA_LNK_FL_ENABLED flag
> + * on links which are not flagged as IMMUTABLE.

And updating this accordingly. The "reset" concept isn't clearly defined in 
the MC API, and why media-ctl implements it, I think stating the purpose more 
explicitly would be clearer.

> + * \return 0 for success, or a negative error code otherwise

s/for/on/

> + */
> +int MediaDevice::resetLinks()
> +{
> +	for (MediaEntity *entity : entities_) {
> +		for (MediaPad *pad : entity->pads()) {
> +			if (pad->flags() & MEDIA_PAD_FL_SINK)

I'd rather write this !(pad->flags() & MEDIA_PAD_FL_SOURCE) in case we later 
get pads that have neither flag set.

> +				continue;
> +
> +			for (MediaLink *link : pad->links()) {
> +				if (link->flags() & MEDIA_LNK_FL_IMMUTABLE)
> +					continue;
> +
> +				int ret = link->setEnable(false);
> +				if (ret)
> +					return ret;
> +			}
> +		}
> +	}

We don't need to do so in this patch, but do you think we should keep a list 
of links internally in MediaDevice for the purpose of iterating over them 
easily here ?

> +	return 0;
> +}
> +
>  /**
>   * \var MediaDevice::objects_
>   * \brief Global map of media objects (entities, pads, links) keyed by
> their @@ -601,4 +630,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 on

s/on/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)."

s/"//

> +*
> + * \sa MediaLink::setEnable(bool enable)
> + *
> + * \return 0 for success, or a negative error code otherwise

s/for/on/

> + */
> +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 612550d..c6cb02b 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"
> 
>  /**
> @@ -89,6 +90,34 @@ namespace libcamera {
>   * Each link is referenced in the link array of both of the pads it
> connect. */
> 
> +/**
> + * \brief Enable or disable a lik

s/lik/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.

s/link,/link/

> + * 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 such a connections.

s/connections/connection/

or possibly better

s/such a connections/that connection/

> + *
> + * \return 0 on success, or a negative error code otherwise
> + */
> +int MediaLink::setEnable(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

-- 
Regards,

Laurent Pinchart





More information about the libcamera-devel mailing list