From patchwork Thu Jan 3 17:38:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 145 Return-Path: Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8D4EA60B13 for ; Thu, 3 Jan 2019 18:39:02 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 265C9FF808; Thu, 3 Jan 2019 17:39:01 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 3 Jan 2019 18:38:55 +0100 Message-Id: <20190103173859.22624-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190103173859.22624-1-jacopo@jmondi.org> References: <20190103173859.22624-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/5] libcamera: Add pointer to MediaDevice to MediaObject 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: Thu, 03 Jan 2019 17:39:02 -0000 Add a MediaDevice member field to the MediaObject class hierarcy. Each media object now has a reference to the media device it belongs to, and which it has been created by. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- src/libcamera/include/media_object.h | 10 ++++++---- src/libcamera/media_device.cpp | 8 ++++---- src/libcamera/media_object.cpp | 30 +++++++++++++++++++--------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/libcamera/include/media_object.h b/src/libcamera/include/media_object.h index 950a332..0f0bb29 100644 --- a/src/libcamera/include/media_object.h +++ b/src/libcamera/include/media_object.h @@ -26,10 +26,12 @@ public: protected: friend class MediaDevice; - MediaObject(unsigned int id) : id_(id) { } + MediaObject(MediaDevice *media, unsigned int id) : + id_(id), media_(media) { } virtual ~MediaObject() { } unsigned int id_; + MediaDevice *media_; }; class MediaLink : public MediaObject @@ -42,7 +44,7 @@ public: private: friend class MediaDevice; - MediaLink(const struct media_v2_link *link, + MediaLink(MediaDevice *media, const struct media_v2_link *link, MediaPad *source, MediaPad *sink); MediaLink(const MediaLink &) = delete; ~MediaLink() { } @@ -65,7 +67,7 @@ public: private: friend class MediaDevice; - MediaPad(const struct media_v2_pad *pad, MediaEntity *entity); + MediaPad(MediaDevice *media, const struct media_v2_pad *pad, MediaEntity *entity); MediaPad(const MediaPad &) = delete; ~MediaPad(); @@ -93,7 +95,7 @@ public: private: friend class MediaDevice; - MediaEntity(const struct media_v2_entity *entity, + MediaEntity(MediaDevice *media, const struct media_v2_entity *entity, unsigned int major = 0, unsigned int minor = 0); MediaEntity(const MediaEntity &) = delete; ~MediaEntity(); diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index cf4ff90..2f9490c 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -430,11 +430,11 @@ bool MediaDevice::populateEntities(const struct media_v2_topology &topology) MediaEntity *entity; if (iface) - entity = new MediaEntity(&mediaEntities[i], + entity = new MediaEntity(this, &mediaEntities[i], iface->devnode.major, iface->devnode.minor); else - entity = new MediaEntity(&mediaEntities[i]); + entity = new MediaEntity(this, &mediaEntities[i]); if (!addObject(entity)) { delete entity; @@ -464,7 +464,7 @@ bool MediaDevice::populatePads(const struct media_v2_topology &topology) return false; } - MediaPad *pad = new MediaPad(&mediaPads[i], mediaEntity); + MediaPad *pad = new MediaPad(this, &mediaPads[i], mediaEntity); if (!addObject(pad)) { delete pad; return false; @@ -509,7 +509,7 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology) return false; } - MediaLink *link = new MediaLink(&mediaLinks[i], source, sink); + MediaLink *link = new MediaLink(this, &mediaLinks[i], source, sink); if (!addObject(link)) { delete link; return false; diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp index 581e1c0..f1535e6 100644 --- a/src/libcamera/media_object.cpp +++ b/src/libcamera/media_object.cpp @@ -44,14 +44,16 @@ namespace libcamera { * * MediaObject is an abstract base class for all media objects in the media * graph. Every media graph object is identified by an id unique in the media - * device context, and this base class provides that. + * device context, and this base class provides both of them. * * \sa MediaEntity, MediaPad, MediaLink */ /** * \fn MediaObject::MediaObject() - * \brief Construct a MediaObject with \a id + * \brief Construct a MediaObject with \a id, globally unique in the MediaDevice + * \a media + * \param media The media device this object belongs to * \param id The media object id * * The caller shall ensure unicity of the object id in the media device context. @@ -69,6 +71,11 @@ namespace libcamera { * \brief The media object id */ +/** + * \var MediaObject::media_ + * \brief The media device that constructed this object + */ + /** * \class MediaLink * \brief The MediaLink represents a link between two pads in the media graph. @@ -82,13 +89,14 @@ namespace libcamera { /** * \brief Construct a MediaLink + * \param media The media device this entity belongs to * \param link The media link kernel data * \param source The source pad at the origin of the link * \param sink The sink pad at the destination of the link */ -MediaLink::MediaLink(const struct media_v2_link *link, MediaPad *source, - MediaPad *sink) - : MediaObject(link->id), source_(source), +MediaLink::MediaLink(MediaDevice *media, const struct media_v2_link *link, + MediaPad *source, MediaPad *sink) + : MediaObject(media, link->id), source_(source), sink_(sink), flags_(link->flags) { } @@ -135,11 +143,13 @@ MediaLink::MediaLink(const struct media_v2_link *link, MediaPad *source, /** * \brief Construct a MediaPad + * \param media The media device this entity belongs to * \param pad The media pad kernel data * \param entity The entity the pad belongs to */ -MediaPad::MediaPad(const struct media_v2_pad *pad, MediaEntity *entity) - : MediaObject(pad->id), index_(pad->index), entity_(entity), +MediaPad::MediaPad(MediaDevice *media, const struct media_v2_pad *pad, + MediaEntity *entity) + : MediaObject(media, pad->id), index_(pad->index), entity_(entity), flags_(pad->flags) { } @@ -283,13 +293,15 @@ int MediaEntity::setDeviceNode(const std::string &devnode) /** * \brief Construct a MediaEntity + * \param media The media device this entity belongs to * \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, +MediaEntity::MediaEntity(MediaDevice *media, + const struct media_v2_entity *entity, unsigned int major, unsigned int minor) - : MediaObject(entity->id), name_(entity->name), + : MediaObject(media, entity->id), name_(entity->name), major_(major), minor_(minor) { } From patchwork Thu Jan 3 17:38:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 146 Return-Path: Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 22A5B60B13 for ; Thu, 3 Jan 2019 18:39:03 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id B3A2DFF804; Thu, 3 Jan 2019 17:39:02 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 3 Jan 2019 18:38:56 +0100 Message-Id: <20190103173859.22624-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190103173859.22624-1-jacopo@jmondi.org> References: <20190103173859.22624-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/5] libcamera: media_device: Add function to get a MediaLink 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: Thu, 03 Jan 2019 17:39:03 -0000 Add three overloaded functions 'link()' to retrieve a link between two pads. Each overloaded implementation exposes a different method to identify the source and sink entities. Signed-off-by: Jacopo Mondi --- src/libcamera/include/media_device.h | 6 ++ src/libcamera/media_device.cpp | 119 +++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h index 9f45fc7..3228ad5 100644 --- a/src/libcamera/include/media_device.h +++ b/src/libcamera/include/media_device.h @@ -40,6 +40,12 @@ public: const std::vector &entities() const { return entities_; } MediaEntity *getEntityByName(const std::string &name) const; + MediaLink *link(const std::string sourceName, unsigned int sourceIdx, + const std::string sinkName, unsigned int sinkIdx) const; + MediaLink *link(const MediaEntity *source, unsigned int sourceIdx, + const MediaEntity *sink, unsigned int sinkIdx) const; + MediaLink *link(const MediaPad *source, const MediaPad *sink) const; + private: std::string driver_; std::string devnode_; diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index 2f9490c..6892300 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -306,6 +306,125 @@ MediaEntity *MediaDevice::getEntityByName(const std::string &name) const return nullptr; } +/** + * \brief Return the MediaLink that connects two entities identified by name + * \param sourceName The source entity name + * \param sourceIdx The index of the source pad + * \param sinkName The sink entity name + * \param sinkIdx The index of the sink pad + * + * Find link that connects the pads at index \a sourceIdx of the source + * entity with name \a sourceName, to the pad at index \a sinkIdx of the + * sink entity with name \a sinkName, if any. + * + * \sa MediaDevice::link(const MediaEntity *source, unsigned int sourceIdx, const MediaEntity *sink, unsigned int sinkIdx) const + * \sa MediaDevice::link(const MediaPad *source, const MediaPad *sink) const + * + * \return The link that connects the two entities, nullptr otherwise + */ +MediaLink *MediaDevice::link(const std::string sourceName, unsigned int sourceIdx, + const std::string sinkName, unsigned int sinkIdx) const +{ + const MediaEntity *source = getEntityByName(sourceName); + if (!source) { + LOG(Error) << "Failed to find entity with name: " + << sourceName << "\n"; + return nullptr; + } + + const MediaPad *sourcePad = source->getPadByIndex(sourceIdx); + if (!sourcePad) { + LOG(Error) << "Entity \"" << sourceName << "\" " + << "has no pad at index " << sourceIdx << "\n"; + return nullptr; + } + + const MediaEntity *sink = getEntityByName(sinkName); + if (!sink) { + LOG(Error) << "Failed to find entity with name: " + << sinkName << "\n"; + return nullptr; + } + + const MediaPad *sinkPad = sink->getPadByIndex(sinkIdx); + if (!sinkPad) { + LOG(Error) << "Entity \"" << sinkName << "\" " + << "has no pad at index " << sinkIdx << "\n"; + return nullptr; + } + + return link(sourcePad, sinkPad); +} + +/** + * \brief Return the MediaLink that connects two entities + * \param source The source entity + * \param sourceIdx The index of the source pad + * \param sink The sink entity + * \param sinkIdx The index of the sink pad + * + * Find link that connects the pads at index \a sourceIdx of the source + * entity \a source, to the pad at index \a sinkIdx of the sink entity \a + * sink, if any. + * + * \sa MediaDevice::link(const std::string sourceName, unsigned int sourceIdx, const std::string sinkName, unsigned int sinkIdx) const + * \sa MediaDevice::link(const MediaPad *source, const MediaPad *sink) const + * + * \return The link that connects the two entities, nullptr otherwise + */ +MediaLink *MediaDevice::link(const MediaEntity *source, unsigned int sourceIdx, + const MediaEntity *sink, unsigned int sinkIdx) const +{ + + const MediaPad *sourcePad = source->getPadByIndex(sourceIdx); + if (!sourcePad) { + LOG(Error) << "Entity \"" << source->name() << "\" " + << "has no pad at index " << sourceIdx << "\n"; + return nullptr; + } + + const MediaPad *sinkPad = sink->getPadByIndex(sinkIdx); + if (!sinkPad) { + LOG(Error) << "Entity \"" << sink->name() << "\" " + << "has no pad at index " << sinkIdx << "\n"; + return nullptr; + } + + return link(sourcePad, sinkPad); +} + +/** + * \brief Return the MediaLink that connects two pads + * \param source The source pad + * \param sink The sink pad + * + * \sa MediaDevice::link(const std::string sourceName, unsigned int sourceIdx, const std::string sinkName, unsigned int sinkIdx) const + * \sa MediaDevice::link(const MediaEntity *source, unsigned int sourceIdx, const MediaEntity *sink, unsigned int sinkIdx) const + * + * \return The link that connects the two pads, nullptr otherwise + */ +MediaLink *MediaDevice::link(const MediaPad *source, const MediaPad *sink) const +{ + if (!source || !sink) + return nullptr; + + /* + * Now that we have made sure all instances are valid, compare + * their ids to find a matching link. + */ + for (MediaLink *link : source->links()) { + if (link->sink()->id() != sink->id()) + continue; + + if (link->sink()->entity()->id() != sink->entity()->id()) + continue; + + return link; + } + + return nullptr; +} + /** * \var MediaDevice::objects_ * \brief Global map of media objects (entities, pads, links) keyed by their From patchwork Thu Jan 3 17:38:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 147 Return-Path: Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AE50960B2D for ; Thu, 3 Jan 2019 18:39:03 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 4B39FFF804; Thu, 3 Jan 2019 17:39:03 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 3 Jan 2019 18:38:57 +0100 Message-Id: <20190103173859.22624-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190103173859.22624-1-jacopo@jmondi.org> References: <20190103173859.22624-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/5] libcamera: Add MediaLink link setup function 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: Thu, 03 Jan 2019 17:39:04 -0000 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 setup() function itself. Signed-off-by: Jacopo Mondi --- src/libcamera/include/media_device.h | 8 ++++++ src/libcamera/include/media_object.h | 1 + src/libcamera/media_device.cpp | 30 +++++++++++++++++++++ src/libcamera/media_object.cpp | 40 ++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h index 3228ad5..d019639 100644 --- a/src/libcamera/include/media_device.h +++ b/src/libcamera/include/media_device.h @@ -65,6 +65,14 @@ 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); + + /* + * The MediaLink enable method needs to access the private + * setLink() function. + */ + friend int MediaLink::enable(bool enable); + int setLink(const MediaPad *source, const MediaPad *sink, + unsigned int flags); }; } /* namespace libcamera */ diff --git a/src/libcamera/include/media_object.h b/src/libcamera/include/media_object.h index 0f0bb29..e00c639 100644 --- a/src/libcamera/include/media_object.h +++ b/src/libcamera/include/media_object.h @@ -40,6 +40,7 @@ public: MediaPad *source() const { return source_; } MediaPad *sink() const { return sink_; } unsigned int flags() const { return flags_; } + int enable(bool enable); private: friend class MediaDevice; diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index 6892300..b86d0c4 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -641,4 +641,34 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology) return true; } +int MediaDevice::setLink(const MediaPad *source, const MediaPad *sink, + unsigned int flags) +{ + struct media_link_desc linkDesc = { }; + + 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) << "\n"; + 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 f1535e6..1ee8823 100644 --- a/src/libcamera/media_object.cpp +++ b/src/libcamera/media_object.cpp @@ -16,6 +16,7 @@ #include "log.h" #include "media_object.h" +#include "media_device.h" /** * \file media_object.h @@ -87,6 +88,45 @@ namespace libcamera { * Each link is referenced in the link array of both of the pads it connect. */ +/** + * \brief Set a link state to enabled or disabled + * \param enable The enable flag, true enables the link, false disables 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. Caller should inspect the link flags before trying to + * disable an immutable link. + * + * Enabling a link establishes a data connection between two pads, while + * disabling it interrupts such a connections. + * + * \return 0 for success, negative error code otherwise + */ +int MediaLink::enable(bool enable) +{ + unsigned int flags = enable ? MEDIA_LNK_FL_ENABLED : 0; + + if ((flags_ & MEDIA_LNK_FL_IMMUTABLE) && !enable) { + LOG(Error) << "Immutable links cannot be disabled"; + return -EINVAL; + } + + /* Do not try to enable an already enabled link. */ + if ((flags_ & MEDIA_LNK_FL_ENABLED) && enable) + return 0; + + int ret = media_->setLink(source_, sink_, flags); + if (ret) + return ret; + + /* Only update flags if 'setLink()' didn't fail. */ + flags_ = flags; + + return 0; +} + /** * \brief Construct a MediaLink * \param media The media device this entity belongs to From patchwork Thu Jan 3 17:38:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 148 Return-Path: Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 436E060B2D for ; Thu, 3 Jan 2019 18:39:04 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id D5F3AFF807; Thu, 3 Jan 2019 17:39:03 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 3 Jan 2019 18:38:58 +0100 Message-Id: <20190103173859.22624-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190103173859.22624-1-jacopo@jmondi.org> References: <20190103173859.22624-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/5] libcamera: Document private members 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: Thu, 03 Jan 2019 17:39:04 -0000 The newly added MediaDevice::setLink() function is defined as private, but it is worth being documented, as it is called from the friend method MediaLink::setup(). In the library code base, several private methods and fields are documented, but do not show up in the generated documentation output. Change doxygen settings to output processed documentation for the private fields and methods, when proper doxygen comments are applied to them (and do not complain if private members are not documented at all). Signed-off-by: Jacopo Mondi --- Documentation/Doxyfile.in | 4 ++-- src/libcamera/media_device.cpp | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index b1a70d3..16dcccd 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -442,7 +442,7 @@ EXTRACT_ALL = NO # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. @@ -487,7 +487,7 @@ EXTRACT_ANON_NSPACES = NO # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. -HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index b86d0c4..48aa805 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -641,6 +641,28 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology) return true; } +/** + * \brief Apply \a flags to a link between two pads + * \param source The source pad + * \param sink The sink pad + * \param flags The link flags + * + * Implements 'raw' link handling, as this functions applies \a flags, + * (whose only accepted values are the ones defined by the Media Controller + * APIs in MEDIA_LNK_FL_* macros) to a link between two pads. No correctness + * checks on the link existence and validity of \a flags is performed. The + * function assumes the \a source and \a sink pads are connected, and the + * supplied \a flags applies to the link (ie. immutable links cannot be + * disabled). + * + * This function wraps the raw MEDIA_IOC_SETUP_LINK ioctl, and shouldn't be + * called directly by any other class or method but the + * MediaLink::setup(bool enable) one, declared as friend for this reason. + * + * \sa MediaLink::setup(bool enable) + * + * \return 0 for success, negative error number otherwise + */ int MediaDevice::setLink(const MediaPad *source, const MediaPad *sink, unsigned int flags) { From patchwork Thu Jan 3 17:38:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 149 Return-Path: Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D16D160B3D for ; Thu, 3 Jan 2019 18:39:04 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 67C0DFF804; Thu, 3 Jan 2019 17:39:04 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 3 Jan 2019 18:38:59 +0100 Message-Id: <20190103173859.22624-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190103173859.22624-1-jacopo@jmondi.org> References: <20190103173859.22624-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/5] test: MediaDevice: Add link exercize test 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: Thu, 03 Jan 2019 17:39:05 -0000 Add test function to exercize the link handling abilities of the media device. Signed-off-by: Jacopo Mondi --- test/media_device/media_device_test.cpp | 101 ++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/test/media_device/media_device_test.cpp b/test/media_device/media_device_test.cpp index c482b2e..99da3a6 100644 --- a/test/media_device/media_device_test.cpp +++ b/test/media_device/media_device_test.cpp @@ -42,8 +42,104 @@ private: void printMediaGraph(const MediaDevice &media, ostream &os); void printLinkFlags(const MediaLink *link, ostream &os); void printNode(const MediaPad *pad, ostream &os); + + int exercizeLinks(const MediaDevice &media); + int testLink(const MediaDevice &media, MediaLink *link); }; +int MediaDeviceTest::testLink(const MediaDevice &media, MediaLink *link) +{ + MediaPad *sourcePad = link->source(); + MediaEntity *source = sourcePad->entity(); + MediaPad *sinkPad = link->sink(); + MediaEntity *sink = sinkPad->entity(); + + cerr << "Test link handling interface on link: " + << source->name() << ":" << sourcePad->index() + << " -> " << sink->name() << ":" << sinkPad->index() << "\n"; + + /* Test the link() functions to be consistent. */ + MediaLink *alink = media.link(source->name(), sourcePad->index(), + sink->name(), sinkPad->index()); + if (link != alink) + return -EINVAL; + + alink = media.link(source, sourcePad->index(), + sink, sinkPad->index()); + if (link != alink) + return -EINVAL; + + alink = media.link(sourcePad, sinkPad); + if (link != alink) + return -EINVAL; + + /* Fine, we get consisten results... now try to manipulate the link. */ + int ret = link->enable(true); + if (ret) + return ret; + + ret = link->enable(false); + if (ret) { + if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) + return ret; + } + + return 0; + +} + +/* + * Exercize the link handling interface. + * Try to get existing and non-existing links, and try to enable + * disable link. + * + * WARNING: this test will change the link between pads on the media + * device it runs on, potentially modying the behavior of the system + * where the test is run on. + */ +int MediaDeviceTest::exercizeLinks(const MediaDevice &media) +{ + auto entities = media.entities(); + + /* First of all, reset all links in the media graph. */ + for (MediaEntity *ent : entities) { + cerr << "Disable all links in entity: " << ent->name() << "\n"; + + for (MediaPad *pad : ent->pads()) { + if (pad->flags() & MEDIA_PAD_FL_SINK) + continue; + + for (MediaLink *link : pad->links()) { + int ret = link->enable(false); + if (ret) { + if (!(link->flags() & + MEDIA_LNK_FL_IMMUTABLE)) + return ret; + } + } + } + } + + + /* + * Exercize the link handling interface. + */ + for (MediaEntity *ent : entities) { + for (MediaPad *pad : ent->pads()) { + if (pad->flags() & MEDIA_PAD_FL_SINK) + continue; + + for (MediaLink *link : pad->links()) { + int ret = testLink(media, link); + if (ret) + return ret; + } + } + } + + return 0; +} + void MediaDeviceTest::printNode(const MediaPad *pad, ostream &os) { const MediaEntity *entity = pad->entity(); @@ -136,6 +232,11 @@ int MediaDeviceTest::testMediaDevice(const string devnode) /* Run tests in sequence. */ printMediaGraph(dev, cerr); + + ret = exercizeLinks(dev); + if (ret) + return ret; + /* TODO: add more tests here. */ dev.close();