[libcamera-devel,08/12] libcamera: deviceenumerator: add documentation

Message ID 20181222230041.29999-9-niklas.soderlund@ragnatech.se
State Superseded
Headers show
Series
  • Add basic camera enumeration
Related show

Commit Message

Niklas Söderlund Dec. 22, 2018, 11 p.m. UTC
Document the intended use-case of the different elements of the device
enumerator.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/libcamera/deviceenumerator.cpp | 249 +++++++++++++++++++++++++++--
 1 file changed, 239 insertions(+), 10 deletions(-)

Patch

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<std::string, std::string> &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<std::string> DeviceInfo::entities() const
 {
 	std::vector<std::string> entities;
@@ -67,6 +146,19 @@  std::vector<std::string> 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<std::string> 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<std::string> &entities) const
 {
 	for (const std::string &name : entities_) {
@@ -134,10 +274,30 @@  bool DeviceMatch::matchEntities(const std::vector<std::string> &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<std::string, std::string> &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;