From patchwork Wed Jan 2 00:49:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 128 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7B3C560B30 for ; Wed, 2 Jan 2019 01:48:08 +0100 (CET) Received: from avalon.bb.dnainternet.fi (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 07C5C537 for ; Wed, 2 Jan 2019 01:48:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1546390088; bh=e8hkoztoWKXaxDWSisshkyI0Or3dA00sgdccn5X+DtE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=KDx7UfVak1W3RasTW97mcExM8rMDWRMy6qd9uilkLgmu4l+QI/4emlenwOcQu5li7 CjMpnBHdk5ev2HvLwW+4XZ3PjWlYNqYuE8G866rvs7+8ebb3w/3RVglJyoBu5fL7Rw ZAnGNLtRmcWAsnlRKZf0VPQ/Cm9iexy57v9fWuGw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Wed, 2 Jan 2019 02:49:02 +0200 Message-Id: <20190102004903.24190-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190102004903.24190-1-laurent.pinchart@ideasonboard.com> References: <20190102004903.24190-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/3] libcamera: MediaDevice: Create entities with major and minor numbers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Jan 2019 00:48:08 -0000 From: Jacopo Mondi 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 Signed-off-by: Laurent Pinchart --- 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 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 &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 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 + (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(-1)) + return nullptr; + + struct media_v2_interface *ifaces = reinterpret_cast + (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; + } + + 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 -#include #include -#include +#include #include #include @@ -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) { }