From patchwork Sat Dec 29 03:28:44 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: 96 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A4F4060B31 for ; Sat, 29 Dec 2018 04:29:52 +0100 (CET) X-Halon-ID: f94473f9-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id f94473f9-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:39 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:44 +0100 Message-Id: <20181229032855.26249-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 01/12] libcamera: Add Camera 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, 29 Dec 2018 03:29:53 -0000 Provide a Camera class which represents our main interface to handling camera devices. This is a rework of Kieran's initial proposal and Laurent's documentation of the file changed to fit the device enumerators needs. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- * Changes v1 - Fix missing /* namespace libcamera */ comment, thanks Jacopo. - Removed Debug messages from Camera class constructor and destructor. - Reworded documentation for Camera::get() and Camera::put(), thanks Laurent. --- include/libcamera/camera.h | 31 ++++++++++++ include/libcamera/libcamera.h | 2 + include/libcamera/meson.build | 1 + src/libcamera/camera.cpp | 89 +++++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 5 files changed, 124 insertions(+) create mode 100644 include/libcamera/camera.h create mode 100644 src/libcamera/camera.cpp diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h new file mode 100644 index 0000000000000000..9a7579d61fa331ee --- /dev/null +++ b/include/libcamera/camera.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * camera.h - Camera object interface + */ +#ifndef __LIBCAMERA_CAMERA_H__ +#define __LIBCAMERA_CAMERA_H__ + +#include + +namespace libcamera { + +class Camera +{ +public: + Camera(const std::string &name); + + const std::string &name() const; + void get(); + void put(); + +private: + virtual ~Camera() { }; + int ref_; + std::string name_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_CAMERA_H__ */ diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h index 790771b61e41e123..44c094d92feed5ba 100644 --- a/include/libcamera/libcamera.h +++ b/include/libcamera/libcamera.h @@ -7,6 +7,8 @@ #ifndef __LIBCAMERA_LIBCAMERA_H__ #define __LIBCAMERA_LIBCAMERA_H__ +#include + namespace libcamera { class libcamera diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 8c82675a25d29913..9b266ad926681db9 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_api = files([ + 'camera.h', 'libcamera.h', ]) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp new file mode 100644 index 0000000000000000..6da2b20137d45da2 --- /dev/null +++ b/src/libcamera/camera.cpp @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * camera.cpp - Camera device + */ + +#include + +#include "log.h" + +/** + * \file camera.h + * \brief Camera device handling + * + * At the core of libcamera is the camera device, combining one image source + * with processing hardware able to provide one or multiple image streams. The + * Camera class represents a camera device. + * + * A camera device contains a single image source, and separate camera device + * instances relate to different image sources. For instance, a phone containing + * front and back image sensors will be modelled with two camera devices, one + * for each sensor. When multiple streams can be produced from the same image + * source, all those streams are guaranteed to be part of the same camera + * device. + * + * While not sharing image sources, separate camera devices can share other + * system resources, such as an ISP. For this reason camera device instances may + * not be fully independent, in which case usage restrictions may apply. For + * instance, a phone with a front and a back camera device may not allow usage + * of the two devices simultaneously. + */ + +namespace libcamera { + +/** + * \class Camera + * \brief Camera device + * + * The Camera class models a camera capable of producing one or more image + * streams from a single image source. It provides the main interface to + * configuring and controlling the device, and capturing image streams. It is + * the central object exposed by libcamera. + */ + +/** + * \brief Construct a named camera device + * + * \param[in] name The name to set on the camera device + * + * The caller is responsible for guaranteeing unicity of the camera + * device name. + */ +Camera::Camera(const std::string &name) + : ref_(1), name_(name) +{ +} + +/** + * \brief Retrieve the name of the camera + * + * \return Name of the camera device + */ +const std::string &Camera::name() const +{ + return name_; +} + +/** + * \brief Acquire a reference to the camera + */ +void Camera::get() +{ + ref_++; +} + +/** + * \brief Release a reference to the camera + * + * When the last reference is released the camera device is deleted. Callers + * shall not access the camera device after calling this function. + */ +void Camera::put() +{ + if (--ref_ == 0) + delete this; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index f632eb5dd7791ad2..46591069aa5f8beb 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_sources = files([ + 'camera.cpp', 'log.cpp', 'main.cpp', ]) From patchwork Sat Dec 29 03:28:45 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: 97 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3125660B32 for ; Sat, 29 Dec 2018 04:29:53 +0100 (CET) X-Halon-ID: f9bd5251-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id f9bd5251-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:40 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:45 +0100 Message-Id: <20181229032855.26249-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 02/12] libcamera: add dependency on libudev 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, 29 Dec 2018 03:29:53 -0000 The device enumeration will depend on libudev, add the dependency to the build system. This should be turned into a optional dependency once a device enumerator not using udev is supported. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- src/libcamera/meson.build | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 46591069aa5f8beb..52b556a8ed4050cb 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -16,7 +16,10 @@ includes = [ libcamera_internal_includes, ] +libudev = dependency('libudev') + libcamera = shared_library('camera', libcamera_sources, install : true, - include_directories : includes) + include_directories : includes, + dependencies : libudev) From patchwork Sat Dec 29 03:28:46 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: 98 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 844F760B36 for ; Sat, 29 Dec 2018 04:29:53 +0100 (CET) X-Halon-ID: fa0c59bc-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fa0c59bc-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:41 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:46 +0100 Message-Id: <20181229032855.26249-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/12] libcamera: device_enumerator: add DeviceInfo 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, 29 Dec 2018 03:29:54 -0000 Provide a DeviceInfo class which holds all information from the initial enumeration of a media device. Not all information available at a media device is stored, only the information needed for a pipeline handler to find a specific device. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- * Changes since v1 - s/do/does in DeviceInfo::lookup(). - Fix typo in include guard. --- src/libcamera/device_enumerator.cpp | 78 +++++++++++++++++++++++ src/libcamera/include/device_enumerator.h | 44 +++++++++++++ src/libcamera/meson.build | 2 + 3 files changed, 124 insertions(+) create mode 100644 src/libcamera/device_enumerator.cpp create mode 100644 src/libcamera/include/device_enumerator.h diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp new file mode 100644 index 0000000000000000..83dcda9403526010 --- /dev/null +++ b/src/libcamera/device_enumerator.cpp @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * device_enumerator.cpp - Enumeration and matching + */ + +#include "device_enumerator.h" +#include "log.h" + +namespace libcamera { + +/* ----------------------------------------------------------------------------- + * DeviceInfo + */ + +DeviceInfo::DeviceInfo(const std::string &devnode, const struct media_device_info &info, + const std::map &entities) + : acquired_(false), devnode_(devnode), info_(info), entities_(entities) +{ + for (const auto &entity : entities_) + LOG(Info) << "Device: " << devnode_ << " Entity: '" << entity.first << "' -> " << entity.second; +} + +int DeviceInfo::acquire() +{ + if (acquired_) + return -EBUSY; + + acquired_ = true; + + return 0; +} + +void DeviceInfo::release() +{ + acquired_ = false; +} + +bool DeviceInfo::busy() const +{ + return acquired_; +} + +const std::string &DeviceInfo::devnode() const +{ + return devnode_; +} + +const struct media_device_info &DeviceInfo::info() const +{ + return info_; +} + +std::vector DeviceInfo::entities() const +{ + std::vector entities; + + for (const auto &entity : entities_) + entities.push_back(entity.first); + + return entities; +} + +int DeviceInfo::lookup(const std::string &name, std::string &devnode) const +{ + auto it = entities_.find(name); + + if (it == entities_.end()) { + LOG(Error) << "Trying to lookup entity '" << name << "' which does not exist"; + return -ENODEV; + } + + devnode = it->second; + return 0; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h new file mode 100644 index 0000000000000000..ac40bafc5169c7c7 --- /dev/null +++ b/src/libcamera/include/device_enumerator.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * device_enumerator.h - API to enumerate and find media devices + */ +#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_H__ +#define __LIBCAMERA_DEVICE_ENUMERATOR_H__ + +#include +#include +#include + +#include + +namespace libcamera { + +class DeviceInfo +{ +public: + DeviceInfo(const std::string &devnode, const struct media_device_info &info, + const std::map &entities); + + int acquire(); + void release(); + bool busy() const; + + const std::string &devnode() const; + const struct media_device_info &info() const; + std::vector entities() const; + + int lookup(const std::string &name, std::string &devnode) const; + +private: + bool acquired_; + + std::string devnode_; + struct media_device_info info_; + std::map entities_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 52b556a8ed4050cb..581da1aa78ebb3ba 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -1,10 +1,12 @@ libcamera_sources = files([ 'camera.cpp', + 'device_enumerator.cpp', 'log.cpp', 'main.cpp', ]) libcamera_headers = files([ + 'include/device_enumerator.h', 'include/log.h', 'include/utils.h', ]) From patchwork Sat Dec 29 03:28:47 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: 99 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1204560B36 for ; Sat, 29 Dec 2018 04:29:54 +0100 (CET) X-Halon-ID: fa85b787-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fa85b787-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:41 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:47 +0100 Message-Id: <20181229032855.26249-5-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 04/12] libcamera: device_enumerator: add DeviceMatch 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, 29 Dec 2018 03:29:54 -0000 Provide a DeviceMatch class which represents all properties of a media device a pipeline hander can specify when searching for a device to use in its pipeline. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- * Changes since v1 - Remove unneeded std::string(entity) in DeviceMatch::add(). - Inline matchInfo() and matchEntities() into the only caller, DeviceMatch::match. --- src/libcamera/device_enumerator.cpp | 36 +++++++++++++++++++++++ src/libcamera/include/device_enumerator.h | 14 +++++++++ 2 files changed, 50 insertions(+) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 83dcda9403526010..61b32bb921581f49 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -75,4 +75,40 @@ int DeviceInfo::lookup(const std::string &name, std::string &devnode) const return 0; } +/* ----------------------------------------------------------------------------- + * DeviceMatch + */ + +DeviceMatch::DeviceMatch(const std::string &driver) + : driver_(driver) +{ +} + +void DeviceMatch::add(const std::string &entity) +{ + entities_.push_back(entity); +} + +bool DeviceMatch::match(const DeviceInfo *info) const +{ + if (driver_ != info->info().driver) + return false; + + for (const std::string &name : entities_) { + bool found = false; + + for (const std::string &entity : info->entities()) { + if (name == entity) { + found = true; + break; + } + } + + if (!found) + return false; + } + + return true; +} + } /* namespace libcamera */ diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h index ac40bafc5169c7c7..ed1e986ff45f95f5 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -39,6 +39,20 @@ private: std::map entities_; }; +class DeviceMatch +{ +public: + DeviceMatch(const std::string &driver); + + void add(const std::string &entity); + + bool match(const DeviceInfo *info) const; + +private: + std::string driver_; + std::vector entities_; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */ From patchwork Sat Dec 29 03:28:48 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: 101 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9371160B36 for ; Sat, 29 Dec 2018 04:29:55 +0100 (CET) X-Halon-ID: fadaa1e5-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fadaa1e5-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:42 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:48 +0100 Message-Id: <20181229032855.26249-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/12] libcamera: device_enumerator: 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, 29 Dec 2018 03:29:56 -0000 Provide a DeviceEnumerator base class which enumerates all media devices in the system and information about them, resolving Media Controller data structures to paths and a method to search in all the enumerated information. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- * Changes since v1 - Add strerror() logging if open() or ioctl() fails. - Use reinterpret_cast. - s/NULL/nullptr. - Break some lines to better fit 80 character lines. --- src/libcamera/device_enumerator.cpp | 155 ++++++++++++++++++++++ src/libcamera/include/device_enumerator.h | 22 +++ 2 files changed, 177 insertions(+) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 61b32bb921581f49..df9e89a1afeecda1 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -5,6 +5,12 @@ * device_enumerator.cpp - Enumeration and matching */ +#include +#include +#include +#include +#include + #include "device_enumerator.h" #include "log.h" @@ -111,4 +117,153 @@ bool DeviceMatch::match(const DeviceInfo *info) 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) { + ret = -errno; + LOG(Info) << "Unable to open " << devnode << + " (" << strerror(-ret) << "), skipping"; + return ret; + } + + 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) { + ret = -errno; + LOG(Info) << "Unable to read device info " << + " (" << strerror(-ret) << "), skipping"; + return ret; + } + + return 0; +} + +int DeviceEnumerator::readTopology(int fd, std::map &entities) +{ + struct media_v2_topology topology; + struct media_v2_entity *ents = nullptr; + struct media_v2_interface *ifaces = nullptr; + struct media_v2_link *links = nullptr; + 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 = reinterpret_cast<__u64>(ents); + topology.ptr_interfaces = reinterpret_cast<__u64>(ifaces); + topology.ptr_links = reinterpret_cast<__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; + + devnode = lookupDevnode(ifaces[iface_id].devnode.major, + ifaces[iface_id].devnode.minor); + if (devnode == "") + break; + + entities[ents[ent_id].name] = devnode; + } +done: + delete[] links; + delete[] ifaces; + delete[] ents; + + return ret; +} + +DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const +{ + DeviceInfo *info = nullptr; + + 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/device_enumerator.h b/src/libcamera/include/device_enumerator.h index ed1e986ff45f95f5..1f8cef3311012308 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -53,6 +53,28 @@ private: std::vector entities_; }; +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 std::string lookupDevnode(int major, int minor) = 0; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */ From patchwork Sat Dec 29 03:28:49 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: 100 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8B19860B33 for ; Sat, 29 Dec 2018 04:29:55 +0100 (CET) X-Halon-ID: fb5a72bb-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fb5a72bb-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:43 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:49 +0100 Message-Id: <20181229032855.26249-7-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 06/12] libcamera: device_enumerator: add DeviceEnumeratorUdev 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, 29 Dec 2018 03:29:56 -0000 Provide a DeviceEnumeratorUdev class which is a specialization of DeviceEnumerator which uses udev to enumerate information in the system. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- * Changes since v1 - s/NULL/nullptr/ - s/foo == NULL/!foo/ - Break log messages to not exceed 80 chars. - Return a std::string from lookupDevnode(). --- src/libcamera/device_enumerator.cpp | 98 +++++++++++++++++++++++ src/libcamera/include/device_enumerator.h | 15 ++++ 2 files changed, 113 insertions(+) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index df9e89a1afeecda1..3cafd0d3703dac99 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -266,4 +266,102 @@ DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const return info; } +/* ----------------------------------------------------------------------------- + * Enumerator Udev + */ + +DeviceEnumeratorUdev::DeviceEnumeratorUdev() + : udev_(nullptr) +{ +} + +DeviceEnumeratorUdev::~DeviceEnumeratorUdev() +{ + if (udev_) + udev_unref(udev_); +} + +int DeviceEnumeratorUdev::init() +{ + if (udev_) + return -EBUSY; + + udev_ = udev_new(); + if (!udev_) + return -ENODEV; + + return 0; +} + +int DeviceEnumeratorUdev::enumerate() +{ + struct udev_enumerate *udev_enum = nullptr; + struct udev_list_entry *ents, *ent; + int ret; + + udev_enum = udev_enumerate_new(udev_); + if (!udev_enum) + return -ENOMEM; + + ret = udev_enumerate_add_match_subsystem(udev_enum, "media"); + if (ret < 0) + goto done; + + ret = udev_enumerate_scan_devices(udev_enum); + if (ret < 0) + goto done; + + ents = udev_enumerate_get_list_entry(udev_enum); + if (!ents) + goto done; + + udev_list_entry_foreach(ent, ents) { + struct udev_device *dev; + const char *devnode; + const char *syspath = udev_list_entry_get_name(ent); + + dev = udev_device_new_from_syspath(udev_, syspath); + if (!dev) { + LOG(Error) << "Failed to get device for '" << + syspath << "', skipping"; + continue; + } + + devnode = udev_device_get_devnode(dev); + if (!devnode) { + udev_device_unref(dev); + ret = -ENODEV; + goto done; + } + + addDevice(devnode); + + udev_device_unref(dev); + } +done: + udev_enumerate_unref(udev_enum); + return ret >= 0 ? 0 : ret; +} + +std::string DeviceEnumeratorUdev::lookupDevnode(int major, int minor) +{ + struct udev_device *device; + const char *name; + dev_t devnum; + std::string devnode(""); + + devnum = makedev(major, minor); + device = udev_device_new_from_devnum(udev_, 'c', devnum); + if (!device) + return ""; + + name = udev_device_get_devnode(device); + if (name) + devnode = name; + + udev_device_unref(device); + + return devnode; +} + } /* namespace libcamera */ diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h index 1f8cef3311012308..5348e6cf583dbd15 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -75,6 +75,21 @@ private: virtual std::string lookupDevnode(int major, int minor) = 0; }; +class DeviceEnumeratorUdev: public DeviceEnumerator +{ +public: + DeviceEnumeratorUdev(); + ~DeviceEnumeratorUdev(); + + int init() final; + int enumerate() final; + +private: + struct udev *udev_; + + std::string lookupDevnode(int major, int minor) final; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */ From patchwork Sat Dec 29 03:28:50 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: 102 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1ECDB60B31 for ; Sat, 29 Dec 2018 04:29:56 +0100 (CET) X-Halon-ID: fbb49f4a-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fbb49f4a-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:43 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:50 +0100 Message-Id: <20181229032855.26249-8-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 07/12] libcamera: device_enumerator: add factory for DeviceEnumerators 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, 29 Dec 2018 03:29:56 -0000 Provide a factory for DeviceEnumerator objects. Depending on which libraries are available there will be different ways to enumerate information in the system. This factory hides this from the rest of the library. Currently udev enumeration is the only supported implementation, a sysfs implementation is another method that surely will be added in the future. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- src/libcamera/device_enumerator.cpp | 19 +++++++++++++++++++ src/libcamera/include/device_enumerator.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 3cafd0d3703dac99..26a3e68fcf39e43a 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -121,6 +121,25 @@ bool DeviceMatch::match(const DeviceInfo *info) const * Enumerator Base */ +DeviceEnumerator *DeviceEnumerator::create() +{ + DeviceEnumerator *enumerator; + + /* TODO: add compile time checks to only try udev enumerator if libudev is available */ + enumerator = new DeviceEnumeratorUdev(); + if (!enumerator->init()) + return enumerator; + + /* + * NOTE: Either udev is not available or initialization of it + * failed, use/fallback on sysfs enumerator + */ + + /* TODO: add a sysfs based enumerator */ + + return nullptr; +} + DeviceEnumerator::~DeviceEnumerator() { for (DeviceInfo *dev : devices_) { diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h index 5348e6cf583dbd15..24bca0e3fc32c377 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -56,6 +56,8 @@ private: class DeviceEnumerator { public: + static DeviceEnumerator *create(); + virtual ~DeviceEnumerator(); virtual int init() = 0; From patchwork Sat Dec 29 03:28:51 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: 104 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A3CE60B4A for ; Sat, 29 Dec 2018 04:29:58 +0100 (CET) X-Halon-ID: fc0cb492-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fc0cb492-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:44 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:51 +0100 Message-Id: <20181229032855.26249-9-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 08/12] libcamera: device_enumerator: 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, 29 Dec 2018 03:29:58 -0000 Document the intended use-case of the different elements of the device enumerator. Signed-off-by: Niklas Söderlund --- src/libcamera/device_enumerator.cpp | 224 +++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 8 deletions(-) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 26a3e68fcf39e43a..7608087b282339f8 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -14,12 +14,55 @@ #include "device_enumerator.h" #include "log.h" +/** + * \file device_enumerator.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) @@ -28,6 +71,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_) @@ -38,26 +90,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; @@ -68,6 +147,17 @@ 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. + * + * \return 0 on success none zero otherwise + */ int DeviceInfo::lookup(const std::string &name, std::string &devnode) const { auto it = entities_.find(name); @@ -81,20 +171,49 @@ int DeviceInfo::lookup(const std::string &name, std::string &devnode) const return 0; } -/* ----------------------------------------------------------------------------- - * 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(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 { if (driver_ != info->info().driver) @@ -117,10 +236,30 @@ bool DeviceMatch::match(const DeviceInfo *info) 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; @@ -150,6 +289,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; @@ -180,6 +328,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; @@ -195,6 +353,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; @@ -268,6 +438,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, nullptr if no match is found + */ DeviceInfo *DeviceEnumerator::search(DeviceMatch &dm) const { DeviceInfo *info = nullptr; @@ -285,8 +467,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() @@ -300,6 +485,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_) @@ -312,6 +504,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 = nullptr; @@ -362,6 +562,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 device node path or empty string if lookup fails. + * + */ std::string DeviceEnumeratorUdev::lookupDevnode(int major, int minor) { struct udev_device *device; From patchwork Sat Dec 29 03:28:52 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: 103 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4970860B49 for ; Sat, 29 Dec 2018 04:29:58 +0100 (CET) X-Halon-ID: fcb5f40b-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fcb5f40b-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:45 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:52 +0100 Message-Id: <20181229032855.26249-10-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/12] libcamera: pipeline_handler: add PipelineHandler 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, 29 Dec 2018 03:29:58 -0000 Provide a PipelineHandler which represents a handler for one or more media devices and provider of one or more cameras. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- src/libcamera/include/pipeline_handler.h | 62 ++++++++++ src/libcamera/meson.build | 2 + src/libcamera/pipeline_handler.cpp | 138 +++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 src/libcamera/include/pipeline_handler.h create mode 100644 src/libcamera/pipeline_handler.cpp diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h new file mode 100644 index 0000000000000000..a7805a01e1c779bd --- /dev/null +++ b/src/libcamera/include/pipeline_handler.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * pipeline_handler.h - Pipeline handler infrastructure + */ +#ifndef __LIBCAMERA_PIPELINE_HANDLER_H__ +#define __LIBCAMERA_PIPELINE_HANDLER_H__ + +#include +#include +#include + +#include + +namespace libcamera { + +class DeviceEnumerator; +class PipelineHandlerFactory; + +class PipelineHandler +{ +public: + virtual ~PipelineHandler() { }; + + virtual bool match(DeviceEnumerator *enumerator) = 0; + + virtual unsigned int count() = 0; + virtual Camera *camera(unsigned int id) = 0; +}; + +class PipelineHandlerFactory +{ +public: + virtual ~PipelineHandlerFactory() { }; + + virtual PipelineHandler *create() = 0; + + static void registerType(const std::string &name, PipelineHandlerFactory *factory); + static PipelineHandler *create(const std::string &name, DeviceEnumerator *enumerator); + static void handlers(std::vector &handlers); + +private: + static std::map ®istry(); +}; + +#define REGISTER_PIPELINE_HANDLER(handler) \ + class handler##Factory : public PipelineHandlerFactory { \ + public: \ + handler##Factory() \ + { \ + PipelineHandlerFactory::registerType(#handler, this); \ + } \ + virtual PipelineHandler *create() { \ + return new handler(); \ + } \ + }; \ + static handler##Factory global_##handler##Factory; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_PIPELINE_HANDLER_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 581da1aa78ebb3ba..0db648dd3e37156e 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -3,11 +3,13 @@ libcamera_sources = files([ 'device_enumerator.cpp', 'log.cpp', 'main.cpp', + 'pipeline_handler.cpp', ]) libcamera_headers = files([ 'include/device_enumerator.h', 'include/log.h', + 'include/pipeline_handler.h', 'include/utils.h', ]) diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp new file mode 100644 index 0000000000000000..b6e28216a6636faf --- /dev/null +++ b/src/libcamera/pipeline_handler.cpp @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * pipeline_handler.cpp - Pipeline handler infrastructure + */ + +#include "device_enumerator.h" +#include "log.h" +#include "pipeline_handler.h" + +/** + * \file pipeline_handler.h + * \brief Create pipelines and cameras from one or more media device + * + * Each pipeline supported by libcamera needs to be backed by a pipeline + * handler implementation which describes the one or many media devices + * needed for a pipeline to function properly. + * + * The pipeline handler is responsible to find all media devices it requires + * to operate and once it retrieves them create all the camera devices + * it is able to support with the that set of devices. + * + * To make it a bit less bit complicated to write pipe line handlers a + * macro REGISTER_PIPELINE_HANDLER() is provided which allows a pipeline + * handler implementation to register itself with the library with ease. + */ + +namespace libcamera { + + +/** + * \class PipelineHandler + * \brief Find a set of media devices and provide cameras + * + * The responsibility of a PipelineHandler is to describe all media + * devices it would need in order to provide cameras to the system. + */ + +/** + * \class PipelineHandlerFactory + * \brief Keep a registry and create instances of available pipeline handlers + * + * The responsibility of the PipelineHandlerFactory is to keep a list + * of all pipelines in the system. Each pipeline handler should register + * it self with the factory using the REGISTER_PIPELINE_HANDLER() macro. + */ + +/** + * \brief Add a pipeline handler to the global list + * + * \param[in] name Name of the pipeline handler to add + * \param[in] factory Factory to use to construct the pipeline + * + * The caller is responsible to guarantee the uniqueness of the pipeline name. + */ +void PipelineHandlerFactory::registerType(const std::string &name, PipelineHandlerFactory *factory) +{ + std::map &factories = registry(); + + if (factories.count(name)) { + LOG(Error) << "Registering '" << name << "' pipeline twice"; + return; + } + + factories[name] = factory; +} + +/** + * \brief Create a new pipeline handler and try to match it + * + * \param[in] name Name of the pipeline handler to try + * \param[in] enumerator Numerator to to search for a match for the handler + * + * Search \a enumerator for a match for a pipeline handler named \a name. + * + * \return Pipeline handler if a match was found else nullptr + */ +PipelineHandler *PipelineHandlerFactory::create(const std::string &name, DeviceEnumerator *enumerator) +{ + std::map &factories = registry(); + + auto it = factories.find(name); + if (it == factories.end()) { + LOG(Error) << "Trying to create non-existing pipeline handler " << name; + return nullptr; + } + + PipelineHandler *pipe; + + pipe = it->second->create(); + + if (pipe->match(enumerator)) + return pipe; + + delete pipe; + return nullptr; +} + +/** + * \brief List all names of handlers from the global list + * + * \param[out] handlers Names of all handlers registered with the global list + */ +void PipelineHandlerFactory::handlers(std::vector &handlers) +{ + std::map &factories = registry(); + + for (auto const &handler : factories) + handlers.push_back(handler.first); +} + +/** + * \brief Static global list of pipeline handlers + * + * It might seem odd to hide the static map inside a function. + * This is needed to make sure the list is created before anyone + * tries to access it and creating problems at link time. + * + * \return Global list of pipeline handlers + */ +std::map &PipelineHandlerFactory::registry() +{ + static std::map factories; + return factories; +} + +/** + * \def REGISTER_PIPELINE_HANDLER + * \brief Register a pipeline handler with the global list + * + * \param[in] handler Class name of PipelineHandler subclass to register + * + * Register a specifc pipline handler with the global list and make it + * avaiable to try and match devices for libcamera. + */ + +} /* namespace libcamera */ From patchwork Sat Dec 29 03:28:53 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: 105 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DC2F760B47 for ; Sat, 29 Dec 2018 04:29:58 +0100 (CET) X-Halon-ID: fd397e64-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fd397e64-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:46 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:53 +0100 Message-Id: <20181229032855.26249-11-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 10/12] libcamera: camera_manager: add CameraManager 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, 29 Dec 2018 03:29:59 -0000 Provide a CameraManager class which will handle listing, instancing, destruction and lifetime management of cameras. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- include/libcamera/camera_manager.h | 38 +++++++ include/libcamera/libcamera.h | 1 + include/libcamera/meson.build | 1 + src/libcamera/camera_manager.cpp | 166 +++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 5 files changed, 207 insertions(+) create mode 100644 include/libcamera/camera_manager.h create mode 100644 src/libcamera/camera_manager.cpp diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h new file mode 100644 index 0000000000000000..9d032d71c4c0841a --- /dev/null +++ b/include/libcamera/camera_manager.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * camera_manager.h - Camera management + */ +#ifndef __LIBCAMERA_CAMERA_MANAGER_H__ +#define __LIBCAMERA_CAMERA_MANAGER_H__ + +#include +#include + +namespace libcamera { + +class Camera; +class DeviceEnumerator; +class PipelineHandler; + +class CameraManager +{ +public: + CameraManager(); + + int start(); + void stop(); + + std::vector list() const; + Camera *get(const std::string &name); + void put(Camera *camera); + +private: + DeviceEnumerator *enumerator_; + std::vector pipes_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_CAMERA_MANAGER_H__ */ diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h index 44c094d92feed5ba..32fb1ff741a7b97a 100644 --- a/include/libcamera/libcamera.h +++ b/include/libcamera/libcamera.h @@ -8,6 +8,7 @@ #define __LIBCAMERA_LIBCAMERA_H__ #include +#include namespace libcamera { diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 9b266ad926681db9..3e04557d66b1a8f4 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -1,5 +1,6 @@ libcamera_api = files([ 'camera.h', + 'camera_manager.h', 'libcamera.h', ]) diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp new file mode 100644 index 0000000000000000..1160381b72a08850 --- /dev/null +++ b/src/libcamera/camera_manager.cpp @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * camera_manager.h - Camera management + */ + +#include + +#include "device_enumerator.h" +#include "pipeline_handler.h" + +/** + * \file camera_manager.h + * \brief Manage all cameras handled by libcamera + * + * The responsibility of the camera manager is to control the lifetime + * management of objects provided by libcamera. + * + * When a user wish to interact with libcamera it creates and starts a + * CameraManager object. Once confirmed the camera manager is running + * the application can list all cameras detected by the library, get + * one or more of the cameras and interact with them. + * + * When the user is done with the camera it should be returned to the + * camera manager. Once all cameras are returned to the camera manager + * the user is free to stop the manager. + * + * \todo Add ability to add and remove media devices based on + * hot-(un)plug events coming from the device enumerator. + * + * \todo Add interface to register a notification callback to the user + * to be able to inform it new cameras have been hot-plugged or + * cameras have been removed due to hot-unplug. + */ + +namespace libcamera { + +CameraManager::CameraManager() + : enumerator_(nullptr) +{ +} + +/** + * \brief Start the camera manager + * + * Start the camera manager and enumerate all devices in the system. Once + * the start have been confirmed the user is free to list and otherwise + * interact with cameras in the system until either the camera manager + * is stopped or the camera is unplugged from the system. + * + * \return true on successful start false otherwise + */ +int CameraManager::start() +{ + std::vector handlers; + + if (enumerator_) + return -ENODEV; + + enumerator_ = DeviceEnumerator::create(); + + if (enumerator_->enumerate()) + return -ENODEV; + + /* + * TODO: Try to read handlers and order from configuration + * file and only fallback on all handlers if there is no + * configuration file. + */ + PipelineHandlerFactory::handlers(handlers); + + for (std::string const &handler : handlers) { + PipelineHandler *pipe; + + /* + * Try each pipeline handler until it exhaust + * all pipelines it can provide. + */ + do { + pipe = PipelineHandlerFactory::create(handler, enumerator_); + if (pipe) + pipes_.push_back(pipe); + } while (pipe); + } + + /* TODO: register hot-plug callback here */ + + return 0; +} + +/** + * \brief Stop the camera manager + * + * Before stopping the camera manger the caller is responsible for making + * sure all cameras provided by the manager are returned to the manager. + * + * After the manager has been stopped no resource provided by the camera + * manager should be consider valid or functional even if they for one + * reason or another have yet to be deleted. + */ +void CameraManager::stop() +{ + /* TODO: unregister hot-plug callback here */ + + for (PipelineHandler *pipe : pipes_) + delete pipe; + + pipes_.clear(); + + if (enumerator_) + delete enumerator_; + + enumerator_ = nullptr; +} + +/** + * \brief List all detected cameras + * + * Before calling this function the caller is responsible to make sure + * the camera manger is running. + * + * \return List of names for all detected cameras + */ +std::vector CameraManager::list() const +{ + std::vector list; + + for (PipelineHandler *pipe : pipes_) { + for (unsigned int i = 0; i < pipe->count(); i++) { + Camera *cam = pipe->camera(i); + list.push_back(cam->name()); + } + } + + return list; +} + +/** + * \brief Get a camera based on name + * + * \param[in] name Name of camera to get + * + * Before calling this function the caller is responsible to make sure + * the camera manger is running. A camera fetched this way should be + * release by the user with the put() method of the Camera object once + * it's done using the camera. + * + * \return Pointer to Camera object or nullptr if camera not found + */ +Camera *CameraManager::get(const std::string &name) +{ + for (PipelineHandler *pipe : pipes_) { + for (unsigned int i = 0; i < pipe->count(); i++) { + Camera *cam = pipe->camera(i); + if (cam->name() == name) { + cam->get(); + return cam; + } + } + } + + return nullptr; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 0db648dd3e37156e..a8cb3fdc22784334 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -1,5 +1,6 @@ libcamera_sources = files([ 'camera.cpp', + 'camera_manager.cpp', 'device_enumerator.cpp', 'log.cpp', 'main.cpp', From patchwork Sat Dec 29 03:28:54 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: 106 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E56260B53 for ; Sat, 29 Dec 2018 04:29:59 +0100 (CET) X-Halon-ID: fdb59afb-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fdb59afb-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:47 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:54 +0100 Message-Id: <20181229032855.26249-12-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 11/12] libcamera: pipeline: vimc: add pipeline handler for vimc 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, 29 Dec 2018 03:29:59 -0000 Provide a pipeline handler for the virtual vimc driver. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/meson.build | 2 + src/libcamera/pipeline/meson.build | 3 + src/libcamera/pipeline/vimc.cpp | 91 ++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/libcamera/pipeline/meson.build create mode 100644 src/libcamera/pipeline/vimc.cpp diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index a8cb3fdc22784334..ac5bba052d7f687b 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -21,6 +21,8 @@ includes = [ libcamera_internal_includes, ] +subdir('pipeline') + libudev = dependency('libudev') libcamera = shared_library('camera', diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build new file mode 100644 index 0000000000000000..615ecd20f1a21141 --- /dev/null +++ b/src/libcamera/pipeline/meson.build @@ -0,0 +1,3 @@ +libcamera_sources += files([ + 'vimc.cpp', +]) diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp new file mode 100644 index 0000000000000000..e0f70a78f7e88412 --- /dev/null +++ b/src/libcamera/pipeline/vimc.cpp @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * vimc.cpp - Pipeline handler for the vimc device + */ + +#include + +#include "device_enumerator.h" +#include "pipeline_handler.h" + +namespace libcamera { + +class PipeHandlerVimc : public PipelineHandler +{ +public: + PipeHandlerVimc(); + ~PipeHandlerVimc(); + + bool match(DeviceEnumerator *enumerator); + + unsigned int count(); + Camera *camera(unsigned int id); +private: + DeviceInfo *info_; + Camera *camera_; +}; + +PipeHandlerVimc::PipeHandlerVimc() + : info_(nullptr), camera_(nullptr) +{ +} + +PipeHandlerVimc::~PipeHandlerVimc() +{ + if (camera_) + camera_->put(); + + if (info_) + info_->release(); +} + +unsigned int PipeHandlerVimc::count() +{ + return 1; +} + +Camera *PipeHandlerVimc::camera(unsigned int id) +{ + if (id != 0) + return nullptr; + + return camera_; +} + +bool PipeHandlerVimc::match(DeviceEnumerator *enumerator) +{ + DeviceMatch dm("vimc"); + + dm.add("Raw Capture 0"); + dm.add("Raw Capture 1"); + dm.add("RGB/YUV Capture"); + dm.add("Sensor A"); + dm.add("Sensor B"); + dm.add("Debayer A"); + dm.add("Debayer B"); + dm.add("RGB/YUV Input"); + dm.add("Scaler"); + + info_ = enumerator->search(dm); + + if (!info_) + return false; + + info_->acquire(); + + /* NOTE: A more complete Camera implementation could + * be passed the DeviceInfo(s) it controls here or + * a reference to the PipelineHandler. Which method + * that is chosen will depend on how the Camera + * object is modeled. + */ + camera_ = new Camera("Dummy VIMC Camera"); + + return true; +} + +REGISTER_PIPELINE_HANDLER(PipeHandlerVimc); + +} /* namespace libcamera */ From patchwork Sat Dec 29 03:28:55 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: 107 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D2EF860B41 for ; Sat, 29 Dec 2018 04:29:59 +0100 (CET) X-Halon-ID: fe0d7c96-0b19-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id fe0d7c96-0b19-11e9-911a-0050569116f7; Sat, 29 Dec 2018 04:29:47 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 29 Dec 2018 04:28:55 +0100 Message-Id: <20181229032855.26249-13-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> References: <20181229032855.26249-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 12/12] tests: add test to list all cameras in the system 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, 29 Dec 2018 03:30:00 -0000 Add simple test which lists all cameras detected in the system. The test fails if no camera can be found. Signed-off-by: Niklas Söderlund --- test/list.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ test/meson.build | 5 +++++ 2 files changed, 59 insertions(+) create mode 100644 test/list.cpp diff --git a/test/list.cpp b/test/list.cpp new file mode 100644 index 0000000000000000..39b8a41d1fef892c --- /dev/null +++ b/test/list.cpp @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * list.cpp - camera list tests + */ + +#include + +#include + +#include "test.h" + +using namespace std; +using namespace libcamera; + +class ListTest : public Test +{ +protected: + int init() + { + cm = new CameraManager(); + if (!cm) + return -ENOMEM; + + cm->start(); + + return 0; + } + + int run() + { + unsigned int count = 0; + + for (auto name : cm->list()) { + cout << "- " << name << endl; + count++; + } + + return count ? 0 : -ENODEV; + } + + void cleanup() + { + cm->stop(); + + delete cm; + } + +private: + CameraManager *cm; +}; + +TEST_REGISTER(ListTest) diff --git a/test/meson.build b/test/meson.build index da0aea9678d127ce..a74629f89197ecea 100644 --- a/test/meson.build +++ b/test/meson.build @@ -8,4 +8,9 @@ test_init = executable('test_init', 'init.cpp', link_with : libcamera, include_directories : libcamera_includes) +list = executable('list', 'list.cpp', + link_with : [libcamera, libtest], + include_directories : libcamera_includes) + test('Initialisation test', test_init) +test('List Camera API tests', list)