From e4d2dcc54971bc877f0d12a3af964d410515a997 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 25 Jan 2019 23:35:23 +0200 Subject: libcamera: media_device: Fallback to legacy ioctls on older kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to kernel v4.19, the MEDIA_IOC_G_TOPOLOGY ioctl didn't expose entity flags. Fallback to calling MEDIA_IOC_ENUM_ENTITIES for each entity to retrieve the flags in that case. Fixes: 67d313240c9b ("libcamera: pipeline: uvcvideo: create a V4L2Device for the default video entity") Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- src/libcamera/include/media_device.h | 3 +++ src/libcamera/media_device.cpp | 41 +++++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h index 27a2b46a..9f038093 100644 --- a/src/libcamera/include/media_device.h +++ b/src/libcamera/include/media_device.h @@ -56,6 +56,8 @@ private: std::string driver_; std::string deviceNode_; std::string model_; + unsigned int version_; + int fd_; bool valid_; bool acquired_; @@ -72,6 +74,7 @@ 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); + void fixupEntityFlags(struct media_v2_entity *entity); friend int MediaLink::setEnabled(bool enable); int setupLink(const MediaLink *link, unsigned int flags); diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index be81bd8c..800ed330 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -167,6 +167,7 @@ int MediaDevice::open() driver_ = info.driver; model_ = info.model; + version_ = info.media_version; return 0; } @@ -553,20 +554,29 @@ bool MediaDevice::populateEntities(const struct media_v2_topology &topology) (topology.ptr_entities); for (unsigned int i = 0; i < topology.num_entities; ++i) { + struct media_v2_entity *ent = &mediaEntities[i]; + + /* + * The media_v2_entity structure was missing the flag field before + * v4.19. + */ + if (!MEDIA_V2_ENTITY_HAS_FLAGS(version_)) + fixupEntityFlags(ent); + /* * 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); + findInterface(topology, ent->id); MediaEntity *entity; if (iface) - entity = new MediaEntity(this, &mediaEntities[i], + entity = new MediaEntity(this, ent, iface->devnode.major, iface->devnode.minor); else - entity = new MediaEntity(this, &mediaEntities[i]); + entity = new MediaEntity(this, ent); if (!addObject(entity)) { delete entity; @@ -657,6 +667,31 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology) return true; } +/** + * \brief Fixup entity flags using the legacy API + * \param[in] entity The entity + * + * This function is used as a fallback to query entity flags using the legacy + * MEDIA_IOC_ENUM_ENTITIES ioctl when running on a kernel version that doesn't + * provide them through the MEDIA_IOC_G_TOPOLOGY ioctl. + */ +void MediaDevice::fixupEntityFlags(struct media_v2_entity *entity) +{ + struct media_entity_desc desc = {}; + desc.id = entity->id; + + int ret = ioctl(fd_, MEDIA_IOC_ENUM_ENTITIES, &desc); + if (ret < 0) { + ret = -errno; + LOG(MediaDevice, Debug) + << "Failed to retrieve information for entity " + << entity->id << ": " << strerror(-ret); + return; + } + + entity->flags = desc.flags; +} + /** * \brief Apply \a flags to a link between two pads * \param link The link to apply flags to -- cgit v1.2.1