summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/include/media_device.h2
-rw-r--r--src/libcamera/include/media_object.h9
-rw-r--r--src/libcamera/media_device.cpp61
-rw-r--r--src/libcamera/media_object.cpp45
4 files changed, 111 insertions, 6 deletions
diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h
index 3fcdb4b4..8d491a87 100644
--- a/src/libcamera/include/media_device.h
+++ b/src/libcamera/include/media_device.h
@@ -54,6 +54,8 @@ private:
std::vector<MediaEntity *> 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 65b55085..950a3328 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<MediaPad *> &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<MediaPad *> pads_;
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;
diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp
index b64dcc3c..581e1c08 100644
--- a/src/libcamera/media_object.cpp
+++ b/src/libcamera/media_object.cpp
@@ -6,9 +6,8 @@
*/
#include <errno.h>
-#include <fcntl.h>
#include <string.h>
-#include <sys/stat.h>
+#include <unistd.h>
#include <string>
#include <vector>
@@ -213,6 +212,20 @@ void MediaPad::addLink(MediaLink *link)
*/
/**
+ * \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
* \return The list of the entity's pads
@@ -249,11 +262,35 @@ const MediaPad *MediaEntity::getPadById(unsigned int id) const
}
/**
+ * \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)
{
}