libcamera: v4l2_device: Use UniqueFD for a file descriptor

Manages a file descriptor owned by V4L2Device for a v4l2 device node
by UniqueFD.

Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Hirokazu Honda 2021-06-10 16:50:23 +09:00 committed by Laurent Pinchart
parent 91dcd719d7
commit cfe4f9622e
3 changed files with 21 additions and 27 deletions

View file

@ -16,6 +16,7 @@
#include <libcamera/base/log.h> #include <libcamera/base/log.h>
#include <libcamera/base/signal.h> #include <libcamera/base/signal.h>
#include <libcamera/base/span.h> #include <libcamera/base/span.h>
#include <libcamera/base/unique_fd.h>
#include <libcamera/controls.h> #include <libcamera/controls.h>
@ -27,7 +28,7 @@ class V4L2Device : protected Loggable
{ {
public: public:
void close(); void close();
bool isOpen() const { return fd_ != -1; } bool isOpen() const { return fd_.isValid(); }
const ControlInfoMap &controls() const { return controls_; } const ControlInfoMap &controls() const { return controls_; }
@ -49,11 +50,11 @@ protected:
~V4L2Device(); ~V4L2Device();
int open(unsigned int flags); int open(unsigned int flags);
int setFd(int fd); int setFd(UniqueFD fd);
int ioctl(unsigned long request, void *argp); int ioctl(unsigned long request, void *argp);
int fd() const { return fd_; } int fd() const { return fd_.get(); }
private: private:
static ControlType v4l2CtrlType(uint32_t ctrlType); static ControlType v4l2CtrlType(uint32_t ctrlType);
@ -72,7 +73,7 @@ private:
ControlIdMap controlIdMap_; ControlIdMap controlIdMap_;
ControlInfoMap controls_; ControlInfoMap controls_;
std::string deviceNode_; std::string deviceNode_;
int fd_; UniqueFD fd_;
EventNotifier *fdEventNotifier_; EventNotifier *fdEventNotifier_;
bool frameStartEnabled_; bool frameStartEnabled_;

View file

@ -53,7 +53,7 @@ LOG_DEFINE_CATEGORY(V4L2)
* at open() time, and the \a logTag to prefix log messages with. * at open() time, and the \a logTag to prefix log messages with.
*/ */
V4L2Device::V4L2Device(const std::string &deviceNode) V4L2Device::V4L2Device(const std::string &deviceNode)
: deviceNode_(deviceNode), fd_(-1), fdEventNotifier_(nullptr), : deviceNode_(deviceNode), fdEventNotifier_(nullptr),
frameStartEnabled_(false) frameStartEnabled_(false)
{ {
} }
@ -81,15 +81,15 @@ int V4L2Device::open(unsigned int flags)
return -EBUSY; return -EBUSY;
} }
int ret = syscall(SYS_openat, AT_FDCWD, deviceNode_.c_str(), flags); UniqueFD fd(syscall(SYS_openat, AT_FDCWD, deviceNode_.c_str(), flags));
if (ret < 0) { if (!fd.isValid()) {
ret = -errno; int ret = -errno;
LOG(V4L2, Error) << "Failed to open V4L2 device: " LOG(V4L2, Error) << "Failed to open V4L2 device: "
<< strerror(-ret); << strerror(-ret);
return ret; return ret;
} }
setFd(ret); setFd(std::move(fd));
listControls(); listControls();
@ -112,14 +112,14 @@ int V4L2Device::open(unsigned int flags)
* *
* \return 0 on success or a negative error code otherwise * \return 0 on success or a negative error code otherwise
*/ */
int V4L2Device::setFd(int fd) int V4L2Device::setFd(UniqueFD fd)
{ {
if (isOpen()) if (isOpen())
return -EBUSY; return -EBUSY;
fd_ = fd; fd_ = std::move(fd);
fdEventNotifier_ = new EventNotifier(fd_, EventNotifier::Exception); fdEventNotifier_ = new EventNotifier(fd_.get(), EventNotifier::Exception);
fdEventNotifier_->activated.connect(this, &V4L2Device::eventAvailable); fdEventNotifier_->activated.connect(this, &V4L2Device::eventAvailable);
fdEventNotifier_->setEnabled(false); fdEventNotifier_->setEnabled(false);
@ -138,10 +138,7 @@ void V4L2Device::close()
delete fdEventNotifier_; delete fdEventNotifier_;
if (::close(fd_) < 0) fd_.reset();
LOG(V4L2, Error) << "Failed to close V4L2 device: "
<< strerror(errno);
fd_ = -1;
} }
/** /**
@ -440,7 +437,7 @@ int V4L2Device::ioctl(unsigned long request, void *argp)
* Printing out an error message is usually better performed * Printing out an error message is usually better performed
* in the caller, which can provide more context. * in the caller, which can provide more context.
*/ */
if (::ioctl(fd_, request, argp) < 0) if (::ioctl(fd_.get(), request, argp) < 0)
return -errno; return -errno;
return 0; return 0;

View file

@ -24,6 +24,7 @@
#include <libcamera/base/event_notifier.h> #include <libcamera/base/event_notifier.h>
#include <libcamera/base/file_descriptor.h> #include <libcamera/base/file_descriptor.h>
#include <libcamera/base/log.h> #include <libcamera/base/log.h>
#include <libcamera/base/unique_fd.h>
#include <libcamera/base/utils.h> #include <libcamera/base/utils.h>
#include "libcamera/internal/formats.h" #include "libcamera/internal/formats.h"
@ -620,22 +621,17 @@ int V4L2VideoDevice::open()
*/ */
int V4L2VideoDevice::open(int handle, enum v4l2_buf_type type) int V4L2VideoDevice::open(int handle, enum v4l2_buf_type type)
{ {
int ret; UniqueFD newFd(dup(handle));
int newFd; if (!newFd.isValid()) {
newFd = dup(handle);
if (newFd < 0) {
ret = -errno;
LOG(V4L2, Error) << "Failed to duplicate file handle: " LOG(V4L2, Error) << "Failed to duplicate file handle: "
<< strerror(-ret); << strerror(errno);
return ret; return -errno;
} }
ret = V4L2Device::setFd(newFd); int ret = V4L2Device::setFd(std::move(newFd));
if (ret < 0) { if (ret < 0) {
LOG(V4L2, Error) << "Failed to set file handle: " LOG(V4L2, Error) << "Failed to set file handle: "
<< strerror(-ret); << strerror(-ret);
::close(newFd);
return ret; return ret;
} }