[libcamera-devel] [PATCH 2/3] libcamera: MediaDevice: Create entities with major and minor numbers

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Jan 2 02:06:05 CET 2019


On Wednesday, 2 January 2019 02:49:02 EET Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo at jmondi.org>
> 
> Extend the MediaEntity object with device node major and minor numbers,
> and retrieve them from the media graph using interfaces. They will be
> used by the DeviceEnumerator to retrieve the devnode path.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  src/libcamera/include/media_device.h |  2 +
>  src/libcamera/include/media_object.h |  9 +++-
>  src/libcamera/media_device.cpp       | 65 +++++++++++++++++++++++++++-
>  src/libcamera/media_object.cpp       | 46 ++++++++++++++++++--
>  4 files changed, 116 insertions(+), 6 deletions(-)
> 
> diff --git a/src/libcamera/include/media_device.h
> b/src/libcamera/include/media_device.h index 3fcdb4b4d5f8..8d491a87867c
> 100644
> --- a/src/libcamera/include/media_device.h
> +++ b/src/libcamera/include/media_device.h
> @@ -54,6 +54,8 @@ private:
> 
>  	std::vector<MediaEntity *> entities_;
> 
> +	struct media_v2_interface *findInterface(const struct media_v2_topology
> &topology, +						 unsigned int entityId);
>  	bool populateEntities(const struct media_v2_topology &topology);
>  	bool populatePads(const struct media_v2_topology &topology);
>  	bool populateLinks(const struct media_v2_topology &topology);
> diff --git a/src/libcamera/include/media_object.h
> b/src/libcamera/include/media_object.h index 65b55085a3b0..950a33286690
> 100644
> --- a/src/libcamera/include/media_object.h
> +++ b/src/libcamera/include/media_object.h
> @@ -80,21 +80,28 @@ class MediaEntity : public MediaObject
>  {
>  public:
>  	const std::string &name() const { return name_; }
> +	unsigned int major() const { return major_; }
> +	unsigned int minor() const { return minor_; }
> 
>  	const std::vector<MediaPad *> &pads() const { return pads_; }
> 
>  	const MediaPad *getPadByIndex(unsigned int index) const;
>  	const MediaPad *getPadById(unsigned int id) const;
> 
> +	int setDeviceNode(const std::string &devnode);
> +
>  private:
>  	friend class MediaDevice;
> 
> -	MediaEntity(const struct media_v2_entity *entity);
> +	MediaEntity(const struct media_v2_entity *entity,
> +		    unsigned int major = 0, unsigned int minor = 0);
>  	MediaEntity(const MediaEntity &) = delete;
>  	~MediaEntity();
> 
>  	std::string name_;
>  	std::string devnode_;
> +	unsigned int major_;
> +	unsigned int minor_;
> 
>  	std::vector<MediaPad *> pads_;
> 
> diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
> index 605e504be124..70b3fff3f492 100644
> --- a/src/libcamera/media_device.cpp
> +++ b/src/libcamera/media_device.cpp
> @@ -208,6 +208,7 @@ int MediaDevice::populate()
>  	struct media_v2_entity *ents = nullptr;
>  	struct media_v2_link *links = nullptr;
>  	struct media_v2_pad *pads = nullptr;
> +	struct media_v2_interface *interfaces = nullptr;
>  	__u64 version = -1;
>  	int ret;
> 
> @@ -221,6 +222,7 @@ int MediaDevice::populate()
>  		topology.ptr_entities = reinterpret_cast<__u64>(ents);
>  		topology.ptr_links = reinterpret_cast<__u64>(links);
>  		topology.ptr_pads = reinterpret_cast<__u64>(pads);
> +		topology.ptr_interfaces = reinterpret_cast<__u64>(interfaces);
> 
>  		ret = ioctl(fd_, MEDIA_IOC_G_TOPOLOGY, &topology);
>  		if (ret < 0) {
> @@ -236,10 +238,12 @@ int MediaDevice::populate()
>  		delete[] links;
>  		delete[] ents;
>  		delete[] pads;
> +		delete[] interfaces;
> 
>  		ents = new media_v2_entity[topology.num_entities];
>  		links = new media_v2_link[topology.num_links];
>  		pads = new media_v2_pad[topology.num_pads];
> +		interfaces = new media_v2_interface[topology.num_interfaces];
> 
>  		version = topology.topology_version;
>  	}
> @@ -253,6 +257,7 @@ int MediaDevice::populate()
>  	delete[] links;
>  	delete[] ents;
>  	delete[] pads;
> +	delete[] interfaces;
> 
>  	if (!valid_) {
>  		clear();
> @@ -367,6 +372,45 @@ void MediaDevice::clear()
>   * \brief Global list of media entities in the media graph
>   */
> 
> +/**
> + * \brief Find the interface associated with an entity
> + * \param topology The media topology as returned by MEDIA_IOC_G_TOPOLOGY
> + * \param entityId The entity id
> + * \return A pointer to the interface if found, or nullptr otherwise
> + */
> +struct media_v2_interface *MediaDevice::findInterface(const struct
> media_v2_topology &topology, +			       unsigned int entityId)
> +{
> +	struct media_v2_link *links = reinterpret_cast<struct media_v2_link *>
> +						(topology.ptr_links);
> +	unsigned int ifaceId = -1;
> +
> +	for (unsigned int i = 0; i < topology.num_links; ++i) {
> +		/* Search for the interface to entity link. */
> +		if (links[i].sink_id != entityId)
> +			continue;
> +
> +		if ((links[i].flags & MEDIA_LNK_FL_LINK_TYPE) !=
> +		    MEDIA_LNK_FL_INTERFACE_LINK)
> +			continue;
> +
> +		ifaceId = links[i].source_id;
> +	}
> +
> +	if (ifaceId == static_cast<unsigned int>(-1))
> +		return nullptr;
> +
> +	struct media_v2_interface *ifaces = reinterpret_cast<struct
> media_v2_interface *> +						(topology.ptr_interfaces);
> +
> +	for (unsigned int i = 0; i < topology.num_interfaces; ++i) {
> +		if (ifaces[i].id == ifaceId)
> +			return &ifaces[i];
> +	}
> +
> +	return nullptr;
> +}
> +
>  /*
>   * For each entity in the media graph create a MediaEntity and store a
>   * reference in the media device objects map and entities list.
> @@ -377,7 +421,26 @@ bool MediaDevice::populateEntities(const struct
> media_v2_topology &topology) (topology.ptr_entities);
> 
>  	for (unsigned int i = 0; i < topology.num_entities; ++i) {
> -		MediaEntity *entity = new MediaEntity(&mediaEntities[i]);
> +		/*
> +		 * Find the interface linked to this entity to get the device
> +		 * node major and minor numbers.
> +		 */
> +		struct media_v2_interface *iface =
> +			findInterface(topology, mediaEntities[i].id);
> +		if (!iface) {
> +			LOG(Error) << "Failed to find interface link for "
> +				   << "entity with id: " << mediaEntities[i].id;
> +			return false;
> +		}

The above five lines should be dropped. So much for testing patches after 
sending them out :-S

> +
> +		MediaEntity *entity;
> +		if (iface)
> +			entity = new MediaEntity(&mediaEntities[i],
> +						 iface->devnode.major,
> +						 iface->devnode.minor);
> +		else
> +			entity = new MediaEntity(&mediaEntities[i]);
> +
>  		if (!addObject(entity)) {
>  			delete entity;
>  			return false;
> diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp
> index b64dcc3c8fb4..69e5cc74264d 100644
> --- a/src/libcamera/media_object.cpp
> +++ b/src/libcamera/media_object.cpp
> @@ -6,9 +6,8 @@
>   */
> 
>  #include <errno.h>
> -#include <fcntl.h>
>  #include <string.h>
> -#include <sys/stat.h>
> +#include <unistd.h>
> 
>  #include <string>
>  #include <vector>
> @@ -212,6 +211,20 @@ void MediaPad::addLink(MediaLink *link)
>   * \return The entity name
>   */
> 
> +/**
> + * \fn MediaEntity::major()
> + * \brief Retrieve the major number of the interface associated with the
> entity + * \return The interface major number, or 0 if the entity isn't
> associated with + * an interface
> + */
> +
> +/**
> + * \fn MediaEntity::minor()
> + * \brief Retrieve the minor number of the interface associated with the
> entity + * \return The interface minor number, or 0 if the entity isn't
> associated with + * an interface
> + */
> +
>  /**
>   * \fn MediaEntity::pads()
>   * \brief Retrieve all pads of the entity
> @@ -238,6 +251,7 @@ const MediaPad *MediaEntity::getPadByIndex(unsigned int
> index) const * \param id The pad id
>   * \return The pad identified by \a id, or nullptr if no such pad exist
>   */
> +
>  const MediaPad *MediaEntity::getPadById(unsigned int id) const
>  {
>  	for (MediaPad *p : pads_) {
> @@ -248,12 +262,36 @@ const MediaPad *MediaEntity::getPadById(unsigned int
> id) const return nullptr;
>  }
> 
> +/**
> + * \brief Set the path to the device node for the associated interface
> + * \param devnode The interface device node path associated with this
> entity + * \return 0 on success, or a negative error code if the device
> node can't be + * accessed
> + */
> +int MediaEntity::setDeviceNode(const std::string &devnode)
> +{
> +	/* Make sure the device node can be accessed. */
> +	int ret = ::access(devnode.c_str(), R_OK | W_OK);
> +	if (ret < 0) {
> +		ret = -errno;
> +		LOG(Error) << "Device node " << devnode << " can't be accessed: "
> +			   << strerror(-ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * \brief Construct a MediaEntity
>   * \param entity The media entity kernel data
> + * \param major The major number of the entity associated interface
> + * \param minor The minor number of the entity associated interface
>   */
> -MediaEntity::MediaEntity(const struct media_v2_entity *entity)
> -	: MediaObject(entity->id), name_(entity->name)
> +MediaEntity::MediaEntity(const struct media_v2_entity *entity,
> +			 unsigned int major, unsigned int minor)
> +	: MediaObject(entity->id), name_(entity->name),
> +	  major_(major), minor_(minor)
>  {
>  }

-- 
Regards,

Laurent Pinchart





More information about the libcamera-devel mailing list