summaryrefslogtreecommitdiff
path: root/src/libcamera/v4l2_device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/v4l2_device.cpp')
-rw-r--r--src/libcamera/v4l2_device.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
new file mode 100644
index 00000000..99621a72
--- /dev/null
+++ b/src/libcamera/v4l2_device.cpp
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * v4l2_device.cpp - Common base for V4L2 video devices and subdevices
+ */
+
+#include "v4l2_device.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "log.h"
+
+/**
+ * \file v4l2_device.h
+ * \brief Common base for V4L2 devices and subdevices
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(V4L2)
+
+/**
+ * \class V4L2Device
+ * \brief Base class for V4L2VideoDevice and V4L2Subdevice
+ *
+ * The V4L2Device class groups together the methods and fields common to
+ * both the V4L2VideoDevice and V4L2Subdevice classes, and provides a base
+ * class whith methods to open and close the device node associated with the
+ * device and to perform IOCTL system calls on it.
+ *
+ * The V4L2Device class cannot be instantiated directly, as its constructor
+ * is protected. Users should instead create instances of one the derived
+ * classes to model either a V4L2 video device or a V4L2 subdevice.
+ */
+
+/**
+ * \brief Construct a V4L2Device
+ * \param[in] deviceNode The device node filesystem path
+ *
+ * Initialize the file descriptor to -1 and store the \a deviceNode to be used
+ * at open() time, and the \a logTag to prefix log messages with.
+ */
+V4L2Device::V4L2Device(const std::string &deviceNode)
+ : deviceNode_(deviceNode), fd_(-1)
+{
+}
+
+/**
+ * \brief Destroy a V4L2Device
+ */
+V4L2Device::~V4L2Device()
+{
+}
+
+/**
+ * \brief Open a V4L2 device node
+ * \param[in] flags Access mode flags
+ *
+ * Open the device node path with the provided access mode \a flags and
+ * initialize the file descriptor, which was initially set to -1.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2Device::open(unsigned int flags)
+{
+ if (isOpen()) {
+ LOG(V4L2, Error) << "Device already open";
+ return -EBUSY;
+ }
+
+ int ret = ::open(deviceNode_.c_str(), flags);
+ if (ret < 0) {
+ ret = -errno;
+ LOG(V4L2, Error) << "Failed to open V4L2 device: "
+ << strerror(-ret);
+ return ret;
+ }
+
+ fd_ = ret;
+
+ return 0;
+}
+
+/**
+ * \brief Close the device node
+ *
+ * Reset the file descriptor to -1
+ */
+void V4L2Device::close()
+{
+ if (!isOpen())
+ return;
+
+ if (::close(fd_) < 0)
+ LOG(V4L2, Error) << "Failed to close V4L2 device: "
+ << strerror(errno);
+ fd_ = -1;
+}
+
+/**
+ * \fn V4L2Device::isOpen()
+ * \brief Check if the V4L2 device node is open
+ * \return True if the V4L2 device node is open, false otherwise
+ */
+
+/**
+ * \brief Perform an IOCTL system call on the device node
+ * \param[in] request The IOCTL request code
+ * \param[in] argp A pointer to the IOCTL argument
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2Device::ioctl(unsigned long request, void *argp)
+{
+ /*
+ * Printing out an error message is usually better performed
+ * in the caller, which can provide more context.
+ */
+ if (::ioctl(fd_, request, argp) < 0)
+ return -errno;
+
+ return 0;
+}
+
+/**
+ * \fn V4L2Device::deviceNode()
+ * \brief Retrieve the device node path
+ * \return The device node path
+ */
+
+/**
+ * \fn V4L2Device::fd()
+ * \brief Retrieve the V4L2 device file descriptor
+ * \return The V4L2 device file descriptor, -1 if the device node is not open
+ */
+
+} /* namespace libcamera */