From patchwork Mon Jun 10 16:40:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1384 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7F35D635E9 for ; Mon, 10 Jun 2019 18:39:47 +0200 (CEST) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id DE2DA24000B; Mon, 10 Jun 2019 16:39:46 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 10 Jun 2019 18:40:49 +0200 Message-Id: <20190610164052.30741-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190610164052.30741-1-jacopo@jmondi.org> References: <20190610164052.30741-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/6] libcamera: Add V4L2Controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Jun 2019 16:39:48 -0000 Add Libcamera V4L2 control support, implemented using the V4L2 Extended Control APIs. This patch defines the types used to define and manage controls. Signed-off-by: Jacopo Mondi --- src/libcamera/include/v4l2_controls.h | 210 +++++++++ src/libcamera/meson.build | 1 + src/libcamera/v4l2_controls.cpp | 632 ++++++++++++++++++++++++++ 3 files changed, 843 insertions(+) create mode 100644 src/libcamera/include/v4l2_controls.h create mode 100644 src/libcamera/v4l2_controls.cpp diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h new file mode 100644 index 000000000000..bca5ccc29de3 --- /dev/null +++ b/src/libcamera/include/v4l2_controls.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_controls.h - V4L2 Extended Control Support + */ + +#ifndef __LIBCAMERA_V4L2_CONTROLS_H__ +#define __LIBCAMERA_V4L2_CONTROLS_H__ + +#include +#include +#include + +#include + +#include +#include + +namespace libcamera { + +class V4L2Control +{ +public: + virtual ~V4L2Control() + { + } + + unsigned int id() { return id_; } + unsigned int size() { return size_; } + enum v4l2_ctrl_type type() const { return type_; } + +protected: + V4L2Control(unsigned int id, unsigned int size, + enum v4l2_ctrl_type type) + : id_(id), size_(size), type_(type) + { + } + +private: + unsigned int id_; + unsigned int size_; + enum v4l2_ctrl_type type_; +}; + +template +class V4L2ControlValue : public V4L2Control +{ +public: + T value() const { return value_; } + T *mem() const { return mem_; } + +protected: + V4L2ControlValue(unsigned int id, unsigned int size, + enum v4l2_ctrl_type type, T value) + : V4L2Control(id, size, type) + { + value_ = value; + mem_ = nullptr; + } + + V4L2ControlValue(unsigned int id, unsigned int size, + enum v4l2_ctrl_type type, T *value) + : V4L2Control(id, size, type) + { + value_ = 0; + mem_ = static_cast(new T[size]); + memcpy(mem_, value, size); + } + + ~V4L2ControlValue() + { + delete[] mem_; + } + +private: + T value_; + T *mem_; +}; + +class V4L2IntControl : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2IntControl(unsigned int id, int32_t value) + : V4L2ControlValue(id, sizeof(int32_t), + V4L2_CTRL_TYPE_INTEGER, value) + { + } +}; + +class V4L2Int64Control : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2Int64Control(unsigned int id, int64_t value) + : V4L2ControlValue(id, sizeof(int64_t), + V4L2_CTRL_TYPE_INTEGER64, value) + { + } +}; + +class V4L2BoolControl : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2BoolControl(unsigned int id, bool value) + : V4L2ControlValue(id, sizeof(bool), + V4L2_CTRL_TYPE_BOOLEAN, value) + { + } +}; + +class V4L2StringControl : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2StringControl(unsigned int id, std::string value) + : V4L2ControlValue(id, value.length(), + V4L2_CTRL_TYPE_STRING, value) + { + } +}; + +class V4L2U8Control : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2U8Control(unsigned int id, unsigned int size, uint8_t *mem) + : V4L2ControlValue(id, size, V4L2_CTRL_TYPE_U8, mem) + { + } +}; + +class V4L2U16Control : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2U16Control(unsigned int id, unsigned int size, uint16_t *mem) + : V4L2ControlValue(id, size, V4L2_CTRL_TYPE_U16, mem) + { + } +}; + +class V4L2U32Control : public V4L2ControlValue +{ +private: + friend class V4L2Controls; + + V4L2U32Control(unsigned int id, unsigned int size, uint32_t *mem) + : V4L2ControlValue(id, size, V4L2_CTRL_TYPE_U32, mem) + { + } +}; + +class V4L2Controls { +public: + ~V4L2Controls() + { + clear(); + } + + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + + iterator begin() { return controls_.begin(); } + const_iterator begin() const { return controls_.begin(); } + iterator end() { return controls_.end(); } + const_iterator end() const { return controls_.end(); } + + size_t size() { return controls_.size(); } + void clear(); + + V4L2Control *operator[](unsigned int index) const + { + return controls_[index]; + } + + bool empty() const { return controls_.size() == 0; } + + void set(unsigned int id, unsigned int value); + void set(unsigned int id, int32_t value); + void set(unsigned int id, int64_t value); + void set(unsigned int id, bool value); + void set(unsigned int id, std::string value); + void set(unsigned int id, size_t size, uint8_t *value); + void set(unsigned int id, size_t size, uint16_t *value); + void set(unsigned int id, size_t size, uint32_t *value); + + int32_t getInt(unsigned int id); + int64_t getInt64(unsigned int id); + bool getBool(unsigned int id); + std::string getString(unsigned int id); + uint8_t *getU8(unsigned int id); + uint16_t *getU16(unsigned int id); + uint32_t *getU32(unsigned int id); + +private: + std::vector controls_; +}; + +}; /* namespace libcamera */ + +#endif /* __LIBCAMERA_V4L2_CONTROLS_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 6d858a22531e..fa1fbcb5faf5 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -22,6 +22,7 @@ libcamera_sources = files([ 'timer.cpp', 'utils.cpp', 'v4l2_base.cpp', + 'v4l2_controls.cpp', 'v4l2_device.cpp', 'v4l2_subdevice.cpp', ]) diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp new file mode 100644 index 000000000000..bd68d07f37bf --- /dev/null +++ b/src/libcamera/v4l2_controls.cpp @@ -0,0 +1,632 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_controls.cpp - V4L2 Extended Control Support + */ + +#include "v4l2_controls.h" + +/** + * \file v4l2_controls.h + * \brief Support for V4L2 Controls using the V4L2 Extended Controls APIs. + * + * The V4L2 defined "Control API" allows application to inspect and modify set + * of configurable parameters on the video device or subdevice of interest. The + * nature of the parameters an application could modify using the control + * framework depends on what the driver implements support for, and on the + * characteristics of the underlying hardware platform. Generally controls are + * used to modify user visible settings, such as the image brightness and + * exposure time, or non-standard parameters which cannot be controlled through + * the V4L2 format negotiation API. + * + * Controls are identified by a numerical id, defined by the V4L2 kernel headers + * and have an associated type and class. Each control has a 'value', which is + * the data that can be modified with a 'V4L2Base::setControl()' operation call + * or retrieved with a 'V4L2Base::getControl()' one. + * + * A control class defines the control purpose while its type (along with the + * control's flags) defines the type of the control's value content. Controls + * might transport a single data value stored in variable inside the control, or + * they might as well deal with more complex data types, such as arrays of + * matrices, stored in a contiguous memory locations associated with the control + * and called 'the payload'. The content have to be opportunely copied into the + * application memory when retrieving a control's value and provided to the V4L2 + * device when setting it. + * + * Libcamera supports control using the V4L2 'Extended Control' framework, which + * allows easier handling of controls with payloads of arbitrary sizes. + * + * The Libcamera V4L2 Controls framework operates on lists of controls, wrapped + * by the V4L2Controls class, to match the V4L2 extended controls framework. + * The interface to set and get control is implemented by the V4L2Base class, + * while this file only provides the data type definitions. + * + * The Libcamera V4L2 control framework define a base class + * V4L2Control that contains the fields common to all controls, regardless of + * their type, such as the control's id, its type and the expected control's + * value data size. The V4L2Control class is not meant to be instantiated + * directly, but is instead used as placeholder to store controls inside the + * publicly constructible V4L2Controls class. + * + * A parametric derived class V4L2ControlValue stores the control's value and + * provide accessors to the data values for controls with no payload, or to the + * memory area that contains the control's data payload. These classes are not + * intended to be directly used and cannot be constructed, but are used instead + * to define specialized derived classes which provide accessors to the + * control's data values. + * + * In order to set and get controls, user of the Libcamera V4L2 control + * framework should operate on instances of the V4L2Controls class, iterating + * on the V4L2Controls it contains, and use the V4L2Controls::set() and + * V4L2Controls::get() methods to set or access the control's data + * content. + * + * \todo Support setting controls with data payload. + */ + +namespace libcamera { + +/** + * \class V4L2Control + * \brief Base class for V4L2 Controls + * + * The V4L2Control base class is the base class that contains the fields common + * to all controls (id, type and size). + * + * This class is not meant to be instantiated directly, but is instead used as a + * place holder to store controls in arrays or other containers. User of the + * libcamera V4L2 control framework should access the controls content by + * using accessors provided by the V4L2Controls class. + */ + +/** + * \fn V4L2Control::V4L2Control + * \brief Construct a V4L2Control instance + * \param id The control's id + * \param size The control's data size + * \param type The control's type + */ + +/** + * \fn V4L2Control::id() + * \brief Retrieve the control's id + * + * Retrieve the control's numerical id value as defined by the V4L2 + * specification. + * + * \return The control's id + */ + +/** + * \fn V4L2Control::size() + * \brief Retrieve the control's data value size in bytes + * + * \todo Better define the value of size() for controls with payload data. + * + * \return The control's size + */ + +/** + * \fn V4L2Control::type() + * \brief Retrieve the control's type + * + * Retrieve the control's type as defined by the V4L2 specification. + * + * \return The control's type + */ + +/** + * \class V4L2ControlValue + * \brief Template base class that represent values of a V4L2 control + * + * The V4L2ControlValue template base class represents a V4L2 control with + * its different value types. + * + * It provides two operations to access the control's value or the pointer + * to the memory location that contains to the control's value data payload. + */ + +/** + * \fn V4L2ControlValue::V4L2ControlValue(unsigned int id, unsigned int size, enum v4l2_ctrl_type type, T value) + * \brief Contruct a V4L2ControlValue with a parametric value + * \param id The control's id + * \param size The control's size + * \param type The control's type + * \param value The control's value + */ + +/** + * \fn V4L2ControlValue::V4L2ControlValue(unsigned int id, unsigned int size, enum v4l2_ctrl_type type, T* value) + * \brief Contruct a V4L2ControlValue with a pointer to a data payload + * \param id The control's id + * \param size The control's size + * \param type The control's type + * \param value The pointer to the control's data payload + */ + +/** + * \fn V4L2ControlValue::~V4L2ControlValue + * \brief Release the memory reserved for the control's data payload, if any + */ + +/** + * \fn V4L2ControlValue::value() + * \brief Retrieve the control's value + * + * Retrieve the control's value. Valid only for controls with no payload. + */ + +/** + * \fn V4L2ControlValue::mem() + * \brief Retrieve a pointer to the memory location of the control's data + * + * Retrieve a pointer to the memory location that contains the control's data + * payload. Valid only for controls with data payload. + */ + +/** + * \class V4L2IntControl + * \brief Specialized V4L2Control class that handles controls of + * V4L2_CTRL_TYPE_INTEGER type. + * + * Access to the control's data value by using the value() operation is + * restricted to the proxy V4L2Controls class. + */ + +/** + * \fn V4L2IntControl::V4L2IntControl() + * \brief Construct a V4L2Control that contains an int value + * \param id The control's id + * \param value The control's value + */ + +/** + * \class V4L2Int64Control + * \brief Specialized V4L2Control class that handles controls of + * V4L2_CTRL_TYPE_INTEGER64 type. + * + * Access to the control's data value by using the value() operation is + * restricted to the proxy V4L2Controls class. + */ + +/** + * \fn V4L2Int64Control::V4L2Int64Control() + * \brief Construct a V4L2Control that contains an int64 value + * \param id The control's id + * \param value The control's value + */ + +/** + * \class V4L2BoolControl + * \brief Specialized V4L2Control class that handles controls of + * V4L2_CTRL_TYPE_BOOLEAN type. + * + * + * Access to the control's data value by using the value() operation is + * restricted to the proxy V4L2Controls class. + */ + +/** + * \fn V4L2BoolControl::V4L2BoolControl() + * \brief Construct a V4L2Control that contains a boolean value + * \param id The control's id + * \param value The control's value + */ + +/** + * \class V4L2StringControl + * \brief Specialized V4L2Control class that handles controls of + * V4L2_CTRL_TYPE_STRING type. + * + * Access to the control's data value by using the value() operation is + * restricted to the proxy V4L2Controls class. + */ + +/** + * \fn V4L2StringControl::V4L2StringControl() + * \brief Construct a V4L2Control that contains a string value + * \param id The control's id + * \param value The control's value + */ + +/** + * \class V4L2U8Control + * \brief Specialized V4L2Control class that handles controls with payload of + * V4L2_CTRL_TYPE_U8 type. + * + * Access to the control's mem() operation is reserved to the V4L2Controls + * proxy class. The size of the payload data can be retrieved with the size() + * operation. + */ + +/** + * \fn V4L2U8Control::V4L2U8Control() + * \brief Construct a V4L2Control with payload of uin8_t data + * \param id The control's id + * \param size The size in bytes of the payload content + * \param mem Pointer to the memory location of the payload content + * + * Memory is reserved in the newly created instance to hold the data payload + * and the data content is copied there. The reserved memory is then freed when + * the Control is destroyed. The memory where the control's payload was copied + * from should be released by the caller. + */ + +/** + * \class V4L2U16Control + * \brief Specialized V4L2Control class that handles controls with payload of + * V4L2_CTRL_TYPE_U16 type. + * + * Access to the control's mem() operation is reserved to the V4L2Controls + * proxy class. The size of the payload data can be retrieved with the size() + * operation. + */ + +/** + * \fn V4L2U16Control::V4L2U16Control(unsigned int id, unsigned int size, uint16_t *mem) + * \brief Construct a V4L2Control with payload of uin16_t data + * \param id The control's id + * \param size The size in bytes of the payload content + * \param mem Pointer to the memory location of the payload content + * + * Memory is reserved in the newly created instance to hold the data payload + * and the data content is copied there. The reserved memory is then freed when + * the Control is destroyed. The memory where the control's payload was copied + * from should be released by the caller. + */ + +/** + * \class V4L2U32Control + * \brief Specialized V4L2Control class that handles controls with payload of + * V4L2_CTRL_TYPE_U32 type. + * + * Access to the control's mem() operation is reserved to the V4L2Controls + * proxy class. The size of the payload data can be retrieved with the size() + * operation. + */ + +/** + * \fn V4L2U32Control::V4L2U32Control(unsigned int id, unsigned int size, uint32_t *mem) + * \brief Construct a V4L2Control with payload of uin32_t data + * \param id The control's id + * \param size The size in bytes of the payload content + * \param mem Pointer to the memory location of the payload content + * + * Memory is reserved in the newly created instance to hold the data payload + * and the data content is copied there. The reserved memory is then freed when + * the Control is destroyed. The memory where the control's payload was copied + * from should be released by the caller. + */ + +/** + * \class V4L2Controls + * \brief Wraps a list of V4L2Control and provide accessors to each control's + * data + * + * The V4L2Controls class works as a wrapper for a list of V4L2Control + * instances. The class provides operations to add a new control (set()) and + * to get back it's content. + * + * User of the Libcamera V4L2 control framework which want to set controls on + * a video device or subdevice should create instances of the V4L2Controls + * class and start filling it with control values. Once ready the instance + * should be passed to the V4L2Base::setControls() operation, that applies the + * control values to the underlying hardware. + * + * When reading control, a V4L2Controls instance is passed to the + * V4L2Base::getControls() operation, along with a list of control IDs, and it + * filled by the V4L2Base operation with V4L2Control instances, the user can + * access by ID using on the provided V4L2Controls::get() operations. + */ + +/** + * \fn V4L2Controls::~V4L2Controls() + * \brief Destroy all V4L2Control stored in the instance + * + * \sa V4L2Controls::clear() + */ + +/** + * \typedef V4L2Controls::iterator + * \brief Iterator on the V4L2 controls contained in the V4L2Controls + */ + +/** + * \typedef CameraConfiguration::const_iterator + * \brief Const iterator on the V4L2 controls contained in the V4L2Controls + */ + +/** + * \fn V4L2Controls::begin + * \brief Retrieve an iterator to the first V4L2Control in the sequence + * \return An iterator to the first V4L2 control + */ + +/** + * \fn iterator V4L2Controls::begin() + * \brief Retrieve an iterator to the first V4L2Control in the sequence + * \return An iterator to the first V4L2 control + */ + +/** + * \fn const_iterator V4L2Controls::begin() const + * \brief Retrieve a constant iterator to the first V4L2Control in the sequence + * \return A constant iterator to the first V4L2 control + */ + +/** + * \fn iterator V4L2Controls::end() + * \brief Retrieve an iterator pointing to the past-the-end V4L2Control in the + * sequence + * \return An iterator to the element following the last V4L2 control in the + * sequence + */ + +/** + * \fn const_iterator V4L2Controls::end() const + * \brief Retrieve a constant iterator pointing to the past-the-end V4L2Control + * in the sequence + * \return A constant iterator to the element following the last V4L2 control + * in the sequence + */ + +/** + * \fn V4L2Controls::size() + * \brief Retrieve the number on stored controls + * \return The number of V4L2Control stored in the instance + */ + +/** + * \brief Destroy each control stored in the instance + * + * Destroy all the V4L2Control instances stored in this V4L2Controls instance. + * Reset the instance size to 0, and release all memory reserved by each + * control. + */ +void V4L2Controls::clear() +{ + for (unsigned int i = 0; i < controls_.size(); ++i) + delete controls_[i]; + + controls_.clear(); +} + +/** + * \fn V4L2Controls::operator[] + * \brief Access the control at index \a index + * \param index The index to access + */ + +/** + * \fn V4L2Controls::empty() + * \brief Retrieve if the instance is empty + * \return True if the instance does not contain any control, false otherwise + */ + +/** + * \brief Store a new control with integer value + * \param id The control's id + * \param value The control's value + */ +void V4L2Controls::set(unsigned int id, unsigned int value) +{ + set(id, static_cast(value)); +} + +/** + * \brief Store a new control with integer value + * \param id The control's id + * \param value The control's value + */ +void V4L2Controls::set(unsigned int id, int32_t value) +{ + V4L2IntControl *c = new V4L2IntControl(id, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with 64-bit integer value + * \param id The control's id + * \param value The control's value + */ +void V4L2Controls::set(unsigned int id, int64_t value) +{ + V4L2Int64Control *c = new V4L2Int64Control(id, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with boolean value + * \param id The control's id + * \param value The control's value + */ +void V4L2Controls::set(unsigned int id, bool value) +{ + V4L2BoolControl *c = new V4L2BoolControl(id, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with string value + * \param id The control's id + * \param value The control's value + */ +void V4L2Controls::set(unsigned int id, std::string value) +{ + V4L2StringControl *c = new V4L2StringControl(id, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with pointer to payload + * \param id The control's id + * \param size The payload size + * \param value The pointer to the data payload + */ +void V4L2Controls::set(unsigned int id, size_t size, uint8_t *value) +{ + V4L2U8Control *c = new V4L2U8Control(id, size, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with pointer to payload + * \param id The control's id + * \param size The payload size + * \param value The pointer to the data payload + */ +void V4L2Controls::set(unsigned int id, size_t size, uint16_t *value) +{ + V4L2U16Control *c = new V4L2U16Control(id, size, value); + controls_.push_back(c); +} + +/** + * \brief Store a new control with pointer to payload + * \param id The control's id + * \param size The payload size + * \param value The pointer to the data payload + */ +void V4L2Controls::set(unsigned int id, size_t size, uint32_t *value) +{ + V4L2U32Control *c = new V4L2U32Control(id, size, value); + controls_.push_back(c); + +} + +/** + * \brief Retrieve the control's integer value + * \param id The control's id + * \return The value of control with \a id, a negative error code if the control + * does not exist in the instance + */ +int32_t V4L2Controls::getInt(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2IntControl *ic = static_cast(c); + return ic->value(); + } + + return -EINVAL; +} + +/** + * \brief Retrieve the control's 64-bit integer value + * \param id The control's id + * \return The value of control with \a id, a negative error code if the control + * does not exist in the instance + */ +int64_t V4L2Controls::getInt64(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2Int64Control *ic = static_cast(c); + return ic->value(); + } + + return -EINVAL; +} + +/** + * \brief Retrieve the control's boolean value + * \param id The control's id + * \return The value of control with \a id, false if the control does not exist + * in the instance + */ +bool V4L2Controls::getBool(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2BoolControl *ic = static_cast(c); + return ic->value(); + } + + return false; +} + +/** + * \brief Retrieve the control's string value + * \param id The control's id + * \return The value of control with \a id, an empty string if the control + * does not exist in the instance + */ +std::string V4L2Controls::getString(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2StringControl *ic = static_cast(c); + return ic->value(); + } + + return ""; +} + +/** + * \brief Retrieve a pointer to the control's payload + * \param id The control's id + * \return A pointer to the control's payload, nullptr if the control + * does not exist in the instance + */ +uint8_t *V4L2Controls::getU8(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2U8Control *ic = static_cast(c); + return ic->mem(); + } + + return nullptr; + +} + +/** + * \brief Retrieve a pointer to the control's payload + * \param id The control's id + * \return A pointer to the control's payload, nullptr if the control + * does not exist in the instance + */ +uint16_t *V4L2Controls::getU16(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2U16Control *ic = static_cast(c); + return ic->mem(); + } + + return nullptr; +} + +/** + * \brief Retrieve a pointer to the control's payload + * \param id The control's id + * \return A pointer to the control's payload, nullptr if the control + * does not exist in the instance + */ +uint32_t *V4L2Controls::getU32(unsigned int id) +{ + for (V4L2Control *c : controls_) { + if (c->id() != id) + continue; + + V4L2U32Control *ic = static_cast(c); + return ic->mem(); + } + + return nullptr; +} + +}; /* namespace libcamera */