From patchwork Sat Dec 22 23:00:37 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: 84 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8817E60B34 for ; Sun, 23 Dec 2018 00:02:30 +0100 (CET) X-Halon-ID: 97d4075f-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 97d4075f-063d-11e9-9adf-005056917a89; Sun, 23 Dec 2018 00:02:03 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 23 Dec 2018 00:00:37 +0100 Message-Id: <20181222230041.29999-9-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 08/12] libcamera: deviceenumerator: add documentation 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:30 -0000 Document the intended use-case of the different elements of the device enumerator. Signed-off-by: Niklas Söderlund --- src/libcamera/deviceenumerator.cpp | 249 +++++++++++++++++++++++++++-- 1 file changed, 239 insertions(+), 10 deletions(-) diff --git a/src/libcamera/deviceenumerator.cpp b/src/libcamera/deviceenumerator.cpp index 6d675fc78af8e586..fc43ecc7e2d07e05 100644 --- a/src/libcamera/deviceenumerator.cpp +++ b/src/libcamera/deviceenumerator.cpp @@ -13,12 +13,55 @@ #include "deviceenumerator.h" #include "log.h" +/** + * \file deviceenumerator.h + * \brief Enumerating and matching of media devices + * + * The purpose of device enumeration and matching is to find media + * devices in the system and map one or more media devices to a pipeline + * handler. During enumeration information about each media device is + * gathered, transformed and stored. + * + * The core of the enumeration is DeviceEnumerator which is responsible + * for all interactions with the operating system and the entry point + * for other parts of libcamera. + * + * The DeviceEnumerator can enumerate all or specific media devices in + * the system. When a new media device is added the enumerator gathers + * information about it and stores it in a DeviceInfo object. + * + * The last functionality provided is the ability to search among the + * enumerate media devices for one matching information known to the + * searcher. This is done by populating and passing a DeviceMatch object + * to the DeviceEnumerator. + * + * \todo Add sysfs based device enumerator + * \todo Add support for hot-plug and hot-unplug. + */ + namespace libcamera { -/* ----------------------------------------------------------------------------- - * DeviceInfo +/** + * \class DeviceInfo + * \brief Container of information for enumerated device + * + * The DeviceInfo class holds information about a media device. It provides + * methods to retrieve the information stored and to lookup entity names + * to device node paths. Furthermore it provides a scheme where a device + * can be acquired and released to indicate if the device is in use. + * + * \todo Look into the possibility to replace this with a more complete MediaDevice model. */ +/** + * \brief Construct a container of device information + * + * \param[in] devnode The path to the device node of the media device + * \param[in] info Information retrieved from MEDIA_IOC_DEVICE_INFO IOCTL + * \param[in] entities A map of media graph 'Entity name' -> 'devnode path' + * + * The caller is responsible to provide all information for the device. + */ DeviceInfo::DeviceInfo(const std::string &devnode, const struct media_device_info &info, const std::map &entities) : acquired_(false), devnode_(devnode), info_(info), entities_(entities) @@ -27,6 +70,15 @@ DeviceInfo::DeviceInfo(const std::string &devnode, const struct media_device_inf LOG(Info) << "Device: " << devnode_ << " Entity: '" << entity.first << "' -> " << entity.second; } +/** + * \brief Claim a device for exclusive use + * + * Once a device is successfully acquired the caller is responsible to + * release it once it is done wit it. + * + * \retval 0 Device claimed + * \retval -EBUSY Device already claimed by someone else + */ int DeviceInfo::acquire() { if (acquired_) @@ -37,26 +89,53 @@ int DeviceInfo::acquire() return 0; } +/** + * \brief Release a device from exclusive use + */ void DeviceInfo::release() { acquired_ = false; } +/** + * \brief Check if a device is in use + * + * \retval true Device is in use + * \retval false Device is free + */ bool DeviceInfo::busy() const { return acquired_; } +/** + * \brief Retrieve the devnode to the media device + * + * \return Path to the media device (example /dev/media0) + */ const std::string &DeviceInfo::devnode() const { return devnode_; } +/** + * \brief Retrieve the media device v4l2 information + * + * \return v4l2 specific information structure + */ const struct media_device_info &DeviceInfo::info() const { return info_; } +/** + * \brief List all entities of the device + * + * List all media entities names from the media graph which are known + * and to which this instance can lookup the device node path. + * + * \return List of strings + */ std::vector DeviceInfo::entities() const { std::vector entities; @@ -67,6 +146,19 @@ std::vector DeviceInfo::entities() const return entities; } +/** + * \brief Lookup a media entity name and retrieve its device node path + * + * \param[in] name Entity name to lookup + * \param[out] devnode Path to \a name devnode if lookup is successful + * + * The caller is responsible to check the return code of the function + * to determine if the entity name could be looked up. + * + * \retval true Successful - \a devnode contains valid data + * \retval false Fail - \a devnode contains invalid data + * + */ bool DeviceInfo::lookup(const std::string &name, std::string &devnode) const { auto it = entities_.find(name); @@ -80,20 +172,49 @@ bool DeviceInfo::lookup(const std::string &name, std::string &devnode) const return true; } -/* ----------------------------------------------------------------------------- - * DeviceMatch +/** + * \class DeviceMatch + * \brief Description of a media device search pattern + * + * The DeviceMatch class describes a media device using properties from + * the v4l2 struct media_device_info, entity names in the media graph or + * other properties which can be used to identify a media device. + * + * The description of a media device can then be passed to an enumerator + * to try and find a matching media device. */ +/** + * \brief Construct a media device search pattern + * + * \param[in] driver The Linux device driver name who created the media device + */ DeviceMatch::DeviceMatch(const std::string &driver) : driver_(driver) { } +/** + * \brief Add a media entity name to the search pattern + * + * \param[in] entity The name of the entity in the media graph + */ void DeviceMatch::add(const std::string &entity) { entities_.push_back(std::string(entity)); } +/** + * \brief Compare a search pattern with a media device + * + * \param[in] info Information about a enumerated media device + * + * Matching is performed on the Linux device driver name and entity names + * from the media graph. + * + * \retval true The device described in \a info matches search pattern + * \retval false The device described in \a info do not match search pattern + */ bool DeviceMatch::match(const DeviceInfo *info) const { std::vector entities; @@ -107,13 +228,32 @@ bool DeviceMatch::match(const DeviceInfo *info) const return true; } +/** + * \brief Compare a v4l2 struct media_device_info to search pattern + * + * \param[in] info Information about a enumerated media device + * + * Not all parameters of struct media_device_info is compared. + * + * \todo Allow for empty driver_ search pattern as a no-op + * \todo Add more optional matching pairs from struct media_device_info + * + * \retval true The device described in \a info matches search pattern + * \retval false The device described in \a info do not match search pattern + */ bool DeviceMatch::matchInfo(const struct media_device_info &info) const { - /* TODO: Add more optinal matching pairs from struct media_device_info */ - /* TODO: Allow for empty driver in DeviceMatch */ return driver_ == info.driver; } +/** + * \brief Compare media entities of media device with search pattern + * + * \param[in] info Information about a enumerated media device + * + * \retval true The device described in \a info matches search pattern + * \retval false The device described in \a info do not match search pattern + */ bool DeviceMatch::matchEntities(const std::vector &entities) const { for (const std::string &name : entities_) { @@ -134,10 +274,30 @@ bool DeviceMatch::matchEntities(const std::vector &entities) const return true; } -/* ----------------------------------------------------------------------------- - * Enumerator Base +/** + * \class DeviceEnumerator + * \brief Enumerate, interrogate, store and search media device information + * + * The DeviceEnumerator class is responsible for all interactions with + * the operation system when searching and interrogating media devices. + * + * It is possible to automatically search and add all media devices in + * the system or specify which media devices should be interrogated + * in order for a specialized application to open as few resources + * as possible to get hold of a specific camera. + * + * Once one or many media devices have been enumerated it is possible + * to search among them to try and find a matching device using a + * DeviceMatch object. + * */ +/** + * \brief Create a new device enumerator matching the systems capabilities + * + * Create a enumerator based on resource available to the system. Not all + * different enumerator types are guaranteed to support all features. + */ DeviceEnumerator *DeviceEnumerator::create() { DeviceEnumerator *enumerator; @@ -165,6 +325,15 @@ DeviceEnumerator::~DeviceEnumerator() } } +/** + * \brief Add a media device to the enumerator + * + * \param[in] devnode path to the media device to add + * + * Opens the media device and quires its topology and other information. + * + * \return 0 on success none zero otherwise + */ int DeviceEnumerator::addDevice(const std::string &devnode) { int fd, ret; @@ -191,6 +360,16 @@ out: return ret; } +/** + * \brief Fetch the MEDIA_IOC_DEVICE_INFO from media device + * + * \param[in] fd File pointer to media device + * \param[out] info Information retrieved from MEDIA_IOC_DEVICE_INFO IOCTL + * + * Opens the media device and quires its information. + * + * \return 0 on success none zero otherwise + */ int DeviceEnumerator::readInfo(int fd, struct media_device_info &info) { int ret; @@ -202,6 +381,18 @@ int DeviceEnumerator::readInfo(int fd, struct media_device_info &info) return 0; } +/** + * \brief Fetch the topology from media device + * + * \param[in] fd File pointer to media device + * \param[out] entities Map of entity names to device node paths + * + * The media graph is retrieved using MEDIA_IOC_G_TOPOLOGY and the + * result is transformed to a map where the entity name is the key + * and the filesystem path for that entity device node is the value. + * + * \return 0 on success none zero otherwise + */ int DeviceEnumerator::readTopology(int fd, std::map &entities) { struct media_v2_topology topology; @@ -274,6 +465,18 @@ done: return ret; } +/** + * \brief Search available media devices for a pattern match + * + * \param[in] dm search pattern + * + * Search the enumerated media devices who are not already in use + * for a match described in \a dm. If a match is found and the caller + * intends to use it the caller is responsible to mark the DeviceInfo + * object as in use and to release it when it's done with it. + * + * \return pointer to the matching DeviceInfo, NULL if no match is found + */ DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const { DeviceInfo *info = NULL; @@ -291,8 +494,11 @@ DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const return info; } -/* ----------------------------------------------------------------------------- - * Enumerator Udev +/** + * \class DeviceEnumeratorUdev + * \brief Udev implementation of device enumeration + * + * Implementation of system enumeration functions using libudev. */ DeviceEnumeratorUdev::DeviceEnumeratorUdev() @@ -306,6 +512,13 @@ DeviceEnumeratorUdev::~DeviceEnumeratorUdev() udev_unref(udev_); } +/** + * \brief Initialize the enumerator + * + * \retval 0 Initialized + * \retval -EBUSY Busy (already initialized) + * \retval -ENODEV Failed to talk to udev + */ int DeviceEnumeratorUdev::init() { if (udev_) @@ -318,6 +531,14 @@ int DeviceEnumeratorUdev::init() return 0; } +/** + * \brief Enumerate all media devices using udev + * + * Find, enumerate and add all media devices in the system to the + * enumerator. + * + * \return 0 on success none zero otherwise + */ int DeviceEnumeratorUdev::enumerate() { struct udev_enumerate *udev_enum = NULL; @@ -367,6 +588,14 @@ done: return ret >= 0 ? 0 : ret; } +/** + * \brief Lookup device node from device number using udev + * + * Translate a device number (major, minor) to a device node path. + * + * \return 0 on success none zero otherwise + * + */ int DeviceEnumeratorUdev::lookupDevnode(std::string &devnode, int major, int minor) { struct udev_device *device;