From patchwork Sat Dec 22 23:00:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 81 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5B05960B2D for ; Sun, 23 Dec 2018 00:02:24 +0100 (CET) X-Halon-ID: 946979a7-063d-11e9-9adf-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.dyn.berto.se (unknown [217.31.177.236]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 946979a7-063d-11e9-9adf-005056917a89; Sun, 23 Dec 2018 00:01:57 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 23 Dec 2018 00:00:34 +0100 Message-Id: <20181222230041.29999-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181222230041.29999-1-niklas.soderlund@ragnatech.se> References: <20181222230041.29999-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/12] libcamera: deviceenumerator: add DeviceEnumerator class 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: Sat, 22 Dec 2018 23:02:24 -0000 Provide a DeviceEnumerator base class which enumerates all media devices in the system and information about them, resolving V4L2 data structures to paths and a method to search in all the enumerated information. Signed-off-by: Niklas Söderlund --- src/libcamera/deviceenumerator.cpp | 144 +++++++++++++++++++++++ src/libcamera/include/deviceenumerator.h | 22 ++++ 2 files changed, 166 insertions(+) diff --git a/src/libcamera/deviceenumerator.cpp b/src/libcamera/deviceenumerator.cpp index 17b6874d229c791c..b2f59017e94d14aa 100644 --- a/src/libcamera/deviceenumerator.cpp +++ b/src/libcamera/deviceenumerator.cpp @@ -5,6 +5,10 @@ * deviceenumerator.cpp - Enumeration and matching */ +#include +#include +#include + #include "deviceenumerator.h" #include "log.h" @@ -129,4 +133,144 @@ bool DeviceMatch::matchEntities(const std::vector &entities) const return true; } +/* ----------------------------------------------------------------------------- + * Enumerator Base + */ + +DeviceEnumerator::~DeviceEnumerator() +{ + for (DeviceInfo *dev : devices_) { + if (dev->busy()) + LOG(Error) << "Removing device info while still in use"; + + delete dev; + } +} + +int DeviceEnumerator::addDevice(const std::string &devnode) +{ + int fd, ret; + + struct media_device_info info = {}; + std::map entities; + + fd = open(devnode.c_str(), O_RDWR); + if (fd < 0) + return fd; + + ret = readInfo(fd, info); + if (ret) + goto out; + + ret = readTopology(fd, entities); + if (ret) + goto out; + + devices_.push_back(new DeviceInfo(devnode, info, entities)); +out: + close(fd); + + return ret; +} + +int DeviceEnumerator::readInfo(int fd, struct media_device_info &info) +{ + int ret; + + ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &info); + if (ret < 0) + return -errno; + + return 0; +} + +int DeviceEnumerator::readTopology(int fd, std::map &entities) +{ + struct media_v2_topology topology; + struct media_v2_entity *ents = NULL; + struct media_v2_interface *ifaces = NULL; + struct media_v2_link *links = NULL; + int ret; + + while (true) { + topology = {}; + + ret = ioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology); + if (ret < 0) + return -errno; + + __u64 version = topology.topology_version; + + ents = new media_v2_entity[topology.num_entities](); + ifaces = new media_v2_interface[topology.num_interfaces](); + links = new media_v2_link[topology.num_links](); + topology.ptr_entities = (__u64)ents; + topology.ptr_interfaces = (__u64)ifaces; + topology.ptr_links = (__u64)links; + + ret = ioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology); + if (ret < 0) { + ret = -errno; + goto done; + } + + if (version == topology.topology_version) + break; + + delete[] links; + delete[] ifaces; + delete[] ents; + } + + for (unsigned int link_id = 0; link_id < topology.num_links; link_id++) { + unsigned int iface_id, ent_id; + std::string devnode; + + if ((links[link_id].flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_INTERFACE_LINK) + continue; + + for (iface_id = 0; iface_id < topology.num_interfaces; iface_id++) + if (links[link_id].source_id == ifaces[iface_id].id) + break; + + for (ent_id = 0; ent_id < topology.num_entities; ent_id++) + if (links[link_id].sink_id == ents[ent_id].id) + break; + + if (ent_id >= topology.num_entities || iface_id >= topology.num_interfaces) + continue; + + ret = lookupDevnode(devnode, + ifaces[iface_id].devnode.major, + ifaces[iface_id].devnode.minor); + if (ret) + break; + + entities[ents[ent_id].name] = devnode; + } +done: + delete[] links; + delete[] ifaces; + delete[] ents; + + return ret; +} + +DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const +{ + DeviceInfo *info = NULL; + + for (DeviceInfo *dev : devices_) { + if (dev->busy()) + continue; + + if (dm.match(dev)) { + info = dev; + break; + } + } + + return info; +} + } /* namespace libcamera */ diff --git a/src/libcamera/include/deviceenumerator.h b/src/libcamera/include/deviceenumerator.h index fb412b8840cb2ffe..cbe17774edb7fcc5 100644 --- a/src/libcamera/include/deviceenumerator.h +++ b/src/libcamera/include/deviceenumerator.h @@ -56,6 +56,28 @@ private: bool matchEntities(const std::vector &entities) const; }; +class DeviceEnumerator +{ +public: + virtual ~DeviceEnumerator(); + + virtual int init() = 0; + virtual int enumerate() = 0; + + DeviceInfo *search(DeviceMatch &dm) const; + +protected: + int addDevice(const std::string &devnode); + +private: + std::vector devices_; + + int readInfo(int fd, struct media_device_info &info); + int readTopology(int fd, std::map &entities); + + virtual int lookupDevnode(std::string &devnode, int major, int minor) = 0; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_DEVICEENUMERATE_H__ */