diff options
-rw-r--r-- | src/libcamera/include/media_device.h | 3 | ||||
-rw-r--r-- | src/libcamera/media_device.cpp | 41 |
2 files changed, 41 insertions, 3 deletions
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; @@ -658,6 +668,31 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology) } /** + * \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 * \param flags The flags to apply to the link |