summaryrefslogtreecommitdiff
path: root/src/libcamera/media_device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/media_device.cpp')
-rw-r--r--src/libcamera/media_device.cpp61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index 73a866bb..4b135579 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,46 @@ 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;
+ break;
+ }
+
+ 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 +422,21 @@ 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);
+
+ 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;