libcamera: v4l2_device: Add method to retrieve all supported controls

Add a new controls() method to the V4L2Device class to retrieve the map
of all supported controls. This is needed in order to dynamically query
the supported controls, for instance for drivers that support different
sets of controls depending on the device model.

To make the API easier to use, create a type alias for the control ID to
ControlInfo and use it.

Remove the getControlInfo() method that is not used externally, as it
can now be replaced by accessing the full list of controls.

Update the CameraSensor API accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Laurent Pinchart 2019-06-30 15:24:08 +03:00
parent bd0245a0dc
commit a110cc94ab
6 changed files with 28 additions and 32 deletions

View file

@ -248,14 +248,12 @@ int CameraSensor::setFormat(V4L2SubdeviceFormat *format)
} }
/** /**
* \brief Retrieve information about a control * \brief Retrieve the supported V4L2 controls and their information
* \param[in] id The control ID * \return A map of the V4L2 controls supported by the sensor
* \return A pointer to the V4L2ControlInfo for control \a id, or nullptr
* if the sensor doesn't have such a control
*/ */
const V4L2ControlInfo *CameraSensor::getControlInfo(unsigned int id) const const V4L2ControlInfoMap &CameraSensor::controls() const
{ {
return subdev_->getControlInfo(id); return subdev_->controls();
} }
/** /**

View file

@ -13,12 +13,11 @@
#include <libcamera/geometry.h> #include <libcamera/geometry.h>
#include "log.h" #include "log.h"
#include "v4l2_controls.h"
namespace libcamera { namespace libcamera {
class MediaEntity; class MediaEntity;
class V4L2ControlInfo;
class V4L2ControlList;
class V4L2Subdevice; class V4L2Subdevice;
struct V4L2SubdeviceFormat; struct V4L2SubdeviceFormat;
@ -43,7 +42,7 @@ public:
const Size &size) const; const Size &size) const;
int setFormat(V4L2SubdeviceFormat *format); int setFormat(V4L2SubdeviceFormat *format);
const V4L2ControlInfo *getControlInfo(unsigned int id) const; const V4L2ControlInfoMap &controls() const;
int getControls(V4L2ControlList *ctrls); int getControls(V4L2ControlList *ctrls);
int setControls(V4L2ControlList *ctrls); int setControls(V4L2ControlList *ctrls);

View file

@ -8,11 +8,11 @@
#ifndef __LIBCAMERA_V4L2_CONTROLS_H__ #ifndef __LIBCAMERA_V4L2_CONTROLS_H__
#define __LIBCAMERA_V4L2_CONTROLS_H__ #define __LIBCAMERA_V4L2_CONTROLS_H__
#include <map>
#include <stdint.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h>
#include <linux/v4l2-controls.h> #include <linux/v4l2-controls.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
@ -41,6 +41,8 @@ private:
int64_t max_; int64_t max_;
}; };
using V4L2ControlInfoMap = std::map<unsigned int, V4L2ControlInfo>;
class V4L2Control class V4L2Control
{ {
public: public:

View file

@ -13,19 +13,18 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include "log.h" #include "log.h"
#include "v4l2_controls.h"
namespace libcamera { namespace libcamera {
class V4L2ControlInfo;
class V4L2ControlList;
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 V4L2ControlInfoMap &controls() const { return controls_; }
int getControls(V4L2ControlList *ctrls); int getControls(V4L2ControlList *ctrls);
int setControls(V4L2ControlList *ctrls); int setControls(V4L2ControlList *ctrls);
@ -48,7 +47,7 @@ private:
const struct v4l2_ext_control *v4l2Ctrls, const struct v4l2_ext_control *v4l2Ctrls,
unsigned int count); unsigned int count);
std::map<unsigned int, V4L2ControlInfo> controls_; V4L2ControlInfoMap controls_;
std::string deviceNode_; std::string deviceNode_;
int fd_; int fd_;
}; };

View file

@ -114,6 +114,11 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl)
* \return The V4L2 control maximum value * \return The V4L2 control maximum value
*/ */
/**
* \typedef V4L2ControlInfoMap
* \brief A map of control ID to V4L2ControlInfo
*/
/** /**
* \class V4L2Control * \class V4L2Control
* \brief A V4L2 control value * \brief A V4L2 control value

View file

@ -111,19 +111,10 @@ void V4L2Device::close()
*/ */
/** /**
* \brief Retrieve information about a control * \fn V4L2Device::controls()
* \param[in] id The control ID * \brief Retrieve the supported V4L2 controls and their information
* \return A pointer to the V4L2ControlInfo for control \a id, or nullptr * \return A map of the V4L2 controls supported by the device
* 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 Read controls from the device * \brief Read controls from the device
@ -158,13 +149,14 @@ int V4L2Device::getControls(V4L2ControlList *ctrls)
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
const V4L2Control *ctrl = ctrls->getByIndex(i); const V4L2Control *ctrl = ctrls->getByIndex(i);
const V4L2ControlInfo *info = getControlInfo(ctrl->id()); const auto iter = controls_.find(ctrl->id());
if (!info) { if (iter == controls_.end()) {
LOG(V4L2, Error) LOG(V4L2, Error)
<< "Control '" << ctrl->id() << "' not found"; << "Control '" << ctrl->id() << "' not found";
return -EINVAL; return -EINVAL;
} }
const V4L2ControlInfo *info = &iter->second;
controlInfo[i] = info; controlInfo[i] = info;
v4l2Ctrls[i].id = info->id(); v4l2Ctrls[i].id = info->id();
} }
@ -232,13 +224,14 @@ int V4L2Device::setControls(V4L2ControlList *ctrls)
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
const V4L2Control *ctrl = ctrls->getByIndex(i); const V4L2Control *ctrl = ctrls->getByIndex(i);
const V4L2ControlInfo *info = getControlInfo(ctrl->id()); const auto iter = controls_.find(ctrl->id());
if (!info) { if (iter == controls_.end()) {
LOG(V4L2, Error) LOG(V4L2, Error)
<< "Control '" << ctrl->id() << "' not found"; << "Control '" << ctrl->id() << "' not found";
return -EINVAL; return -EINVAL;
} }
const V4L2ControlInfo *info = &iter->second;
controlInfo[i] = info; controlInfo[i] = info;
v4l2Ctrls[i].id = info->id(); v4l2Ctrls[i].id = info->id();