libcamera: v4l2_device: List valid controls at open

Enumerate all the valid controls a device supports at open() time.
A control is valid only if its type is supported.

Store the control information in a map inside the device to save
querying the control when setting or getting its value from the device
and provide an operation to retrieve information by control ID.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Jacopo Mondi 2019-06-12 17:30:21 +02:00
parent bab8b01895
commit 030ce6491e
2 changed files with 65 additions and 0 deletions

View file

@ -7,18 +7,23 @@
#ifndef __LIBCAMERA_V4L2_DEVICE_H__ #ifndef __LIBCAMERA_V4L2_DEVICE_H__
#define __LIBCAMERA_V4L2_DEVICE_H__ #define __LIBCAMERA_V4L2_DEVICE_H__
#include <map>
#include <string> #include <string>
#include "log.h" #include "log.h"
namespace libcamera { namespace libcamera {
class V4L2ControlInfo;
class V4L2Device : protected Loggable class V4L2Device : protected Loggable
{ {
public: public:
void close(); void close();
bool isOpen() const { return fd_ != -1; } bool isOpen() const { return fd_ != -1; }
const V4L2ControlInfo *getControlInfo(unsigned int id) const;
const std::string &deviceNode() const { return deviceNode_; } const std::string &deviceNode() const { return deviceNode_; }
protected: protected:
@ -32,6 +37,9 @@ protected:
int fd() { return fd_; } int fd() { return fd_; }
private: private:
void listControls();
std::map<unsigned int, V4L2ControlInfo> controls_;
std::string deviceNode_; std::string deviceNode_;
int fd_; int fd_;
}; };

View file

@ -13,6 +13,7 @@
#include <unistd.h> #include <unistd.h>
#include "log.h" #include "log.h"
#include "v4l2_controls.h"
/** /**
* \file v4l2_device.h * \file v4l2_device.h
@ -82,6 +83,8 @@ int V4L2Device::open(unsigned int flags)
fd_ = ret; fd_ = ret;
listControls();
return 0; return 0;
} }
@ -107,6 +110,21 @@ void V4L2Device::close()
* \return True if the V4L2 device node is open, false otherwise * \return True if the V4L2 device node is open, false otherwise
*/ */
/**
* \brief Retrieve information about a control
* \param[in] id The control ID
* \return A pointer to the V4L2ControlInfo for control \a id, or nullptr
* if the device doesn't have such a control
*/
const V4L2ControlInfo *V4L2Device::getControlInfo(unsigned int id) const
{
auto it = controls_.find(id);
if (it == controls_.end())
return nullptr;
return &it->second;
}
/** /**
* \brief Perform an IOCTL system call on the device node * \brief Perform an IOCTL system call on the device node
* \param[in] request The IOCTL request code * \param[in] request The IOCTL request code
@ -137,4 +155,43 @@ int V4L2Device::ioctl(unsigned long request, void *argp)
* \return The V4L2 device file descriptor, -1 if the device node is not open * \return The V4L2 device file descriptor, -1 if the device node is not open
*/ */
/*
* \brief List and store information about all controls supported by the
* V4L2 device
*/
void V4L2Device::listControls()
{
struct v4l2_query_ext_ctrl ctrl = {};
/* \todo Add support for menu and compound controls. */
ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
while (ioctl(VIDIOC_QUERY_EXT_CTRL, &ctrl) == 0) {
if (ctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS ||
ctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
continue;
}
V4L2ControlInfo info(ctrl);
switch (info.type()) {
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_BUTTON:
case V4L2_CTRL_TYPE_INTEGER64:
case V4L2_CTRL_TYPE_BITMASK:
case V4L2_CTRL_TYPE_INTEGER_MENU:
break;
/* \todo Support compound controls. */
default:
LOG(V4L2, Error) << "Control type '" << info.type()
<< "' not supported";
continue;
}
controls_.emplace(ctrl.id, info);
ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
}
}
} /* namespace libcamera */ } /* namespace libcamera */