From e74f3eebb498634f438a005b2ad5b7f1778091e8 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 14 Dec 2018 13:49:20 +0000 Subject: libcamera: Add V4L2 Device object Provide a helper V4L2 device object capable of interacting with the V4L2 Linux Kernel APIs. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- src/libcamera/v4l2_device.cpp | 186 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/libcamera/v4l2_device.cpp (limited to 'src/libcamera/v4l2_device.cpp') diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp new file mode 100644 index 00000000..54b53de3 --- /dev/null +++ b/src/libcamera/v4l2_device.cpp @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_device.cpp - V4L2 Device + */ + +#include +#include +#include +#include +#include + +#include "log.h" +#include "v4l2_device.h" + +/** + * \file v4l2_device.h + * \brief V4L2 Device API + */ +namespace libcamera { + +/** + * \struct V4L2Capability + * \brief struct v4l2_capability object wrapper and helpers + * + * The V4L2Capability structure manages the information returned by the + * VIDIOC_QUERYCAP ioctl. + */ + +/** + * \fn const char *V4L2Capability::driver() + * \brief Retrieve the driver module name + * \return The string containing the name of the driver module + */ + +/** + * \fn const char *V4L2Capability::card() + * \brief Retrieve the device card name + * \return The string containing the device name + */ + +/** + * \fn const char *V4L2Capability::bus_info() + * \brief Retrieve the location of the device in the system + * \return The string containing the device location + */ + +/** + * \fn bool V4L2Capability::isCapture() + * \brief Identify if the device is capable of capturing video + * \return True if the device can capture video frames + */ + +/** + * \fn bool V4L2Capability::isOutput() + * \brief Identify if the device is capable of outputting video + * \return True if the device can output video frames + */ + +/** + * \fn bool V4L2Capability::hasStreaming() + * \brief Determine if the device can perform Streaming I/O + * \return True if the device provides Streaming I/O IOCTLs + */ + +/** + * \class V4L2Device + * \brief V4L2Device object and API + * + * The V4L2 Device API class models an instance of a V4L2 device node. + * It is constructed with the path to a V4L2 video device node. The device node + * is only opened upon a call to open() which must be checked for success. + * + * The device capabilities are validated when the device is opened and the + * device is rejected if it is not a suitable V4L2 capture or output device, or + * if the device does not support streaming I/O. + * + * No API call other than open(), isOpen() and close() shall be called on an + * unopened device instance. + * + * Upon destruction any device left open will be closed, and any resources + * released. + */ + +/** + * \brief Construct a V4L2Device + * \param devnode The file-system path to the video device node + */ +V4L2Device::V4L2Device(const std::string &devnode) + : devnode_(devnode), fd_(-1) +{ +} + +V4L2Device::~V4L2Device() +{ + close(); +} + +/** + * \brief Open a V4L2 device and query its capabilities + * \return 0 on success, or a negative error code otherwise + */ +int V4L2Device::open() +{ + int ret; + + if (isOpen()) { + LOG(Error) << "Device already open"; + return -EBUSY; + } + + ret = ::open(devnode_.c_str(), O_RDWR); + if (ret < 0) { + ret = -errno; + LOG(Error) << "Failed to open V4L2 device '" << devnode_ + << "': " << strerror(-ret); + return ret; + } + fd_ = ret; + + ret = ioctl(fd_, VIDIOC_QUERYCAP, &caps_); + if (ret < 0) { + ret = -errno; + LOG(Error) << "Failed to query device capabilities: " + << strerror(-ret); + return ret; + } + + LOG(Debug) << "Opened '" << devnode_ << "' " + << caps_.bus_info() << ": " << caps_.driver() + << ": " << caps_.card(); + + if (!caps_.isCapture() && !caps_.isOutput()) { + LOG(Debug) << "Device is not a supported type"; + return -EINVAL; + } + + if (!caps_.hasStreaming()) { + LOG(Error) << "Device does not support streaming I/O"; + return -EINVAL; + } + + return 0; +} + +/** + * \brief Check if device is successfully opened + * \return True if the device is open, false otherwise + */ +bool V4L2Device::isOpen() const +{ + return fd_ != -1; +} + +/** + * \brief Close the device, releasing any resources acquired by open() + */ +void V4L2Device::close() +{ + if (fd_ < 0) + return; + + ::close(fd_); + fd_ = -1; +} + +/** + * \fn const char *V4L2Device::driverName() + * \brief Retrieve the name of the V4L2 device driver + * \return The string containing the driver name + */ + +/** + * \fn const char *V4L2Device::deviceName() + * \brief Retrieve the name of the V4L2 device + * \return The string containing the device name + */ + +/** + * \fn const char *V4L2Device::busName() + * \brief Retrieve the location of the device in the system + * \return The string containing the device location + */ + +} /* namespace libcamera */ -- cgit v1.2.1