[libcamera-devel] [PATCH v4 03/13] libcamera: controls: Introduce control-related data types

Niklas Söderlund niklas.soderlund at ragnatech.se
Tue Jul 2 01:59:03 CEST 2019


Hi Kieran,

Thanks for your work.

On 2019-07-01 23:14:54 +0300, Laurent Pinchart wrote:
> From: Kieran Bingham <kieran.bingham at ideasonboard.com>
> 
> Add a set of data types to support controls:
> 
> - ControlValue stores a control type and value in a generic way
> - ControlId enumerates all the control identifiers
> - ControlIdentifier declares the types of a control and map their names
> - ControlInfo stores runtime information for controls
> - ControlList contains a set of control info and value pairs
> 
> The control definitions map is generated from the controls documentation
> to ensure that the two will always be synchronised.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

I tested the awk script, it works but my awk is too week to properly 
review it. So I will blindly trust you on that no backdoors exists in it 
(much the same way I would review perl...) ;-P

Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>

> ---
> Changes since v3:
> 
> - Typo fixes
> - Optimized the contains() implementation
> - Various documentation updates
> 
> Changes since v2:
> 
> - Squashed "Provide ControlValue class"
> - Renamed Value to ControlValue
> - Removed operator<<()
> - Added control table generation
> - Moved control definitions to control_definitions.h
> - Renamed ControlTypes to controlTypes and make it const
> - Moved the initial controls list to a separate patch
> - Renamed control_definitions.h to control_ids.h and
>   control_definitions.cpp to control_types.cpp to match the contained
>   enum and variable name respectively
> - Indexed ControlList by ControlInfo pointer instead of value
> - Replaced ControlInfoHash with std::hash specialisation
> - Added automatic conversion between 32- and 64-bit integer values
> 
> The automatic conversion between integer types was prompted by an
> assertion failure due to the use of getInt() on the min() and max()
> value of an Integer control. The min and max ControlValue instances are
> create as Integer64, due to the V4L2ControlInfo class returning the
> range as int64_t. This may need to be reworked.
> ---
>  Documentation/Doxyfile.in       |   3 +-
>  include/libcamera/control_ids.h |  35 +++
>  include/libcamera/controls.h    | 134 ++++++++++
>  include/libcamera/meson.build   |   2 +
>  src/libcamera/controls.cpp      | 451 ++++++++++++++++++++++++++++++++
>  src/libcamera/gen-controls.awk  | 106 ++++++++
>  src/libcamera/meson.build       |  11 +
>  7 files changed, 741 insertions(+), 1 deletion(-)
>  create mode 100644 include/libcamera/control_ids.h
>  create mode 100644 include/libcamera/controls.h
>  create mode 100644 src/libcamera/controls.cpp
>  create mode 100755 src/libcamera/gen-controls.awk
> 
> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
> index c58631200dd5..9ca32241b895 100644
> --- a/Documentation/Doxyfile.in
> +++ b/Documentation/Doxyfile.in
> @@ -868,7 +868,8 @@ EXCLUDE_SYMBOLS        = libcamera::SignalBase \
>                           libcamera::SlotArgs \
>                           libcamera::SlotBase \
>                           libcamera::SlotMember \
> -                         libcamera::SlotStatic
> +                         libcamera::SlotStatic \
> +                         std::*
>  
>  # The EXAMPLE_PATH tag can be used to specify one or more files or directories
>  # that contain example code fragments that are included (see the \include
> diff --git a/include/libcamera/control_ids.h b/include/libcamera/control_ids.h
> new file mode 100644
> index 000000000000..d0e700da9844
> --- /dev/null
> +++ b/include/libcamera/control_ids.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * control_ids.h : Control ID list
> + */
> +
> +#ifndef __LIBCAMERA_CONTROL_IDS_H__
> +#define __LIBCAMERA_CONTROL_IDS_H__
> +
> +#include <functional>
> +
> +namespace libcamera {
> +
> +enum ControlId {
> +};
> +
> +} /* namespace libcamera */
> +
> +namespace std {
> +
> +template<>
> +struct hash<libcamera::ControlId> {
> +	using argument_type = libcamera::ControlId;
> +	using result_type = std::size_t;
> +
> +	result_type operator()(const argument_type &key) const noexcept
> +	{
> +		return std::hash<std::underlying_type<argument_type>::type>()(key);
> +	}
> +};
> +
> +} /* namespace std */
> +
> +#endif // __LIBCAMERA_CONTROL_IDS_H__
> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
> new file mode 100644
> index 000000000000..2206155909ca
> --- /dev/null
> +++ b/include/libcamera/controls.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * controls.h - Control handling
> + */
> +
> +#ifndef __LIBCAMERA_CONTROLS_H__
> +#define __LIBCAMERA_CONTROLS_H__
> +
> +#include <stdint.h>
> +#include <string>
> +#include <unordered_map>
> +
> +#include <libcamera/control_ids.h>
> +
> +namespace libcamera {
> +
> +class Camera;
> +
> +enum ControlValueType {
> +	ControlValueNone,
> +	ControlValueBool,
> +	ControlValueInteger,
> +	ControlValueInteger64,
> +};
> +
> +class ControlValue
> +{
> +public:
> +	ControlValue();
> +	ControlValue(bool value);
> +	ControlValue(int value);
> +	ControlValue(int64_t value);
> +
> +	ControlValueType type() const { return type_; };
> +	bool isNone() const { return type_ == ControlValueNone; };
> +
> +	void set(bool value);
> +	void set(int value);
> +	void set(int64_t value);
> +
> +	bool getBool() const;
> +	int getInt() const;
> +	int64_t getInt64() const;
> +
> +	std::string toString() const;
> +
> +private:
> +	ControlValueType type_;
> +
> +	union {
> +		bool bool_;
> +		int integer_;
> +		int64_t integer64_;
> +	};
> +};
> +
> +struct ControlIdentifier {
> +	ControlId id;
> +	const char *name;
> +	ControlValueType type;
> +};
> +
> +class ControlInfo
> +{
> +public:
> +	explicit ControlInfo(ControlId id, const ControlValue &min = 0,
> +			     const ControlValue &max = 0);
> +
> +	ControlId id() const { return ident_->id; }
> +	const char *name() const { return ident_->name; }
> +	ControlValueType type() const { return ident_->type; }
> +
> +	const ControlValue &min() const { return min_; }
> +	const ControlValue &max() const { return max_; }
> +
> +	std::string toString() const;
> +
> +private:
> +	const struct ControlIdentifier *ident_;
> +	ControlValue min_;
> +	ControlValue max_;
> +};
> +
> +bool operator==(const ControlInfo &lhs, const ControlInfo &rhs);
> +bool operator==(const ControlId &lhs, const ControlInfo &rhs);
> +bool operator==(const ControlInfo &lhs, const ControlId &rhs);
> +static inline bool operator!=(const ControlInfo &lhs, const ControlInfo &rhs)
> +{
> +	return !(lhs == rhs);
> +}
> +static inline bool operator!=(const ControlId &lhs, const ControlInfo &rhs)
> +{
> +	return !(lhs == rhs);
> +}
> +static inline bool operator!=(const ControlInfo &lhs, const ControlId &rhs)
> +{
> +	return !(lhs == rhs);
> +}
> +
> +class ControlList
> +{
> +private:
> +	using ControlListMap = std::unordered_map<const ControlInfo *, ControlValue>;
> +
> +public:
> +	ControlList(Camera *camera);
> +
> +	using iterator = ControlListMap::iterator;
> +	using const_iterator = ControlListMap::const_iterator;
> +
> +	iterator begin() { return controls_.begin(); }
> +	iterator end() { return controls_.end(); }
> +	const_iterator begin() const { return controls_.begin(); }
> +	const_iterator end() const { return controls_.end(); }
> +
> +	bool contains(const ControlInfo *info) const;
> +	bool empty() const { return controls_.empty(); }
> +	std::size_t size() const { return controls_.size(); }
> +	void clear() { controls_.clear(); }
> +
> +	ControlValue &operator[](const ControlInfo *info) { return controls_[info]; }
> +
> +	void update(const ControlList &list);
> +
> +private:
> +	Camera *camera_;
> +	ControlListMap controls_;
> +};
> +
> +} /* namespace libcamera */
> +
> +#endif /* __LIBCAMERA_CONTROLS_H__ */
> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
> index 15484724df01..3067120a1598 100644
> --- a/include/libcamera/meson.build
> +++ b/include/libcamera/meson.build
> @@ -2,6 +2,8 @@ libcamera_api = files([
>      'buffer.h',
>      'camera.h',
>      'camera_manager.h',
> +    'control_ids.h',
> +    'controls.h',
>      'event_dispatcher.h',
>      'event_notifier.h',
>      'geometry.h',
> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
> new file mode 100644
> index 000000000000..7fac1169cbfd
> --- /dev/null
> +++ b/src/libcamera/controls.cpp
> @@ -0,0 +1,451 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * controls.cpp - Control handling
> + */
> +
> +#include <libcamera/controls.h>
> +
> +#include <sstream>
> +#include <string>
> +
> +#include "log.h"
> +#include "utils.h"
> +
> +/**
> + * \file controls.h
> + * \brief Describes control framework and controls supported by a camera
> + */
> +
> +namespace libcamera {
> +
> +LOG_DEFINE_CATEGORY(Controls)
> +
> +/**
> + * \enum ControlValueType
> + * \brief Define the data type of value represented by a ControlValue
> + * \var ControlValueNone
> + * Identifies an unset control value
> + * \var ControlValueBool
> + * Identifies controls storing a boolean value
> + * \var ControlValueInteger
> + * Identifies controls storing an integer value
> + * \var ControlValueInteger64
> + * Identifies controls storing a 64-bit integer value
> + */
> +
> +/**
> + * \class ControlValue
> + * \brief Abstract type representing the value of a control
> + */
> +
> +/**
> + * \brief Construct an empty ControlValue.
> + */
> +ControlValue::ControlValue()
> +	: type_(ControlValueNone)
> +{
> +}
> +
> +/**
> + * \brief Construct a Boolean ControlValue
> + * \param[in] value Boolean value to store
> + */
> +ControlValue::ControlValue(bool value)
> +	: type_(ControlValueBool), bool_(value)
> +{
> +}
> +
> +/**
> + * \brief Construct an integer ControlValue
> + * \param[in] value Integer value to store
> + */
> +ControlValue::ControlValue(int value)
> +	: type_(ControlValueInteger), integer_(value)
> +{
> +}
> +
> +/**
> + * \brief Construct a 64 bit integer ControlValue
> + * \param[in] value Integer value to store
> + */
> +ControlValue::ControlValue(int64_t value)
> +	: type_(ControlValueInteger64), integer64_(value)
> +{
> +}
> +
> +/**
> + * \fn ControlValue::type()
> + * \brief Retrieve the data type of the value
> + * \return The value data type
> + */
> +
> +/**
> + * \fn ControlValue::isNone()
> + * \brief Determine if the value is not initialised
> + * \return True if the value type is ControlValueNone, false otherwise
> + */
> +
> +/**
> + * \brief Set the value with a boolean
> + * \param[in] value Boolean value to store
> + */
> +void ControlValue::set(bool value)
> +{
> +	type_ = ControlValueBool;
> +	bool_ = value;
> +}
> +
> +/**
> + * \brief Set the value with an integer
> + * \param[in] value Integer value to store
> + */
> +void ControlValue::set(int value)
> +{
> +	type_ = ControlValueInteger;
> +	integer_ = value;
> +}
> +
> +/**
> + * \brief Set the value with a 64 bit integer
> + * \param[in] value 64 bit integer value to store
> + */
> +void ControlValue::set(int64_t value)
> +{
> +	type_ = ControlValueInteger64;
> +	integer64_ = value;
> +}
> +
> +/**
> + * \brief Get the boolean value
> + *
> + * The value type must be Boolean.
> + *
> + * \return The boolean value
> + */
> +bool ControlValue::getBool() const
> +{
> +	ASSERT(type_ == ControlValueBool);
> +
> +	return bool_;
> +}
> +
> +/**
> + * \brief Get the integer value
> + *
> + * The value type must be Integer or Integer64.
> + *
> + * \return The integer value
> + */
> +int ControlValue::getInt() const
> +{
> +	ASSERT(type_ == ControlValueInteger || type_ == ControlValueInteger64);
> +
> +	return integer_;
> +}
> +
> +/**
> + * \brief Get the 64-bit integer value
> + *
> + * The value type must be Integer or Integer64.
> + *
> + * \return The 64-bit integer value
> + */
> +int64_t ControlValue::getInt64() const
> +{
> +	ASSERT(type_ == ControlValueInteger || type_ == ControlValueInteger64);
> +
> +	return integer64_;
> +}
> +
> +/**
> + * \brief Assemble and return a string describing the value
> + * \return A string describing the ControlValue
> + */
> +std::string ControlValue::toString() const
> +{
> +	switch (type_) {
> +	case ControlValueNone:
> +		return "<None>";
> +	case ControlValueBool:
> +		return bool_ ? "True" : "False";
> +	case ControlValueInteger:
> +		return std::to_string(integer_);
> +	case ControlValueInteger64:
> +		return std::to_string(integer64_);
> +	}
> +
> +	return "<ValueType Error>";
> +}
> +
> +/**
> + * \enum ControlId
> + * \brief Numerical control ID
> + */
> +
> +/**
> + * \struct ControlIdentifier
> + * \brief Describe a ControlId with control specific constant meta-data
> + *
> + * Defines a Control with a unique ID, a name, and a type.
> + * This structure is used as static part of the auto-generated control
> + * definitions, which are generated from the ControlId documentation.
> + *
> + * \var ControlIdentifier::id
> + * The unique ID for a control
> + * \var ControlIdentifier::name
> + * The string representation of the control
> + * \var ControlIdentifier::type
> + * The ValueType required to represent the control value
> + */
> +
> +/*
> + * The controlTypes are automatically generated to produce a control_types.cpp
> + * output. This file is not for public use, and so no suitable header exists
> + * for this sole usage of the controlTypes reference. As such the extern is
> + * only defined here for use during the ControlInfo constructor and should not
> + * be referenced directly elsewhere.
> + */
> +extern const std::unordered_map<ControlId, ControlIdentifier> controlTypes;
> +
> +/**
> + * \class ControlInfo
> + * \brief Describe the information and capabilities of a Control
> + *
> + * The ControlInfo represents control specific meta-data which is constant on a
> + * per camera basis. ControlInfo classes are constructed by pipeline handlers
> + * to expose the controls they support and the metadata needed to utilise those
> + * controls.
> + */
> +
> +/**
> + * \brief Construct a ControlInfo with minimum and maximum range parameters
> + * \param[in] id The control ID
> + * \param[in] min The control minimum value
> + * \param[in] max The control maximum value
> + */
> +ControlInfo::ControlInfo(ControlId id, const ControlValue &min,
> +			 const ControlValue &max)
> +	: min_(min), max_(max)
> +{
> +	auto iter = controlTypes.find(id);
> +	if (iter == controlTypes.end()) {
> +		LOG(Controls, Fatal) << "Attempt to create invalid ControlInfo";
> +		return;
> +	}
> +
> +	ident_ = &iter->second;
> +}
> +
> +/**
> + * \fn ControlInfo::id()
> + * \brief Retrieve the control ID
> + * \return The control ID
> + */
> +
> +/**
> + * \fn ControlInfo::name()
> + * \brief Retrieve the control name string
> + * \return The control name string
> + */
> +
> +/**
> + * \fn ControlInfo::type()
> + * \brief Retrieve the control data type
> + * \return The control data type
> + */
> +
> +/**
> + * \fn ControlInfo::min()
> + * \brief Retrieve the minimum value of the control
> + * \return A ControlValue with the minimum value for the control
> + */
> +
> +/**
> + * \fn ControlInfo::max()
> + * \brief Retrieve the maximum value of the control
> + * \return A ControlValue with the maximum value for the control
> + */
> +
> +/**
> + * \brief Provide a string representation of the ControlInfo
> + */
> +std::string ControlInfo::toString() const
> +{
> +	std::stringstream ss;
> +
> +	ss << name() << "[" << min_.toString() << ".." << max_.toString() << "]";
> +
> +	return ss.str();
> +}
> +
> +/**
> + * \brief Compare control information for equality
> + * \param[in] lhs Left-hand side control information
> + * \param[in] rhs Right-hand side control information
> + *
> + * Control information is compared based on the ID only, as a camera may not
> + * have two separate controls with the same ID.
> + *
> + * \return True if \a lhs and \a rhs are equal, false otherwise
> + */
> +bool operator==(const ControlInfo &lhs, const ControlInfo &rhs)
> +{
> +	return lhs.id() == rhs.id();
> +}
> +
> +/**
> + * \brief Compare control ID and information for equality
> + * \param[in] lhs Left-hand side control identifier
> + * \param[in] rhs Right-hand side control information
> + *
> + * Control information is compared based on the ID only, as a camera may not
> + * have two separate controls with the same ID.
> + *
> + * \return True if \a lhs and \a rhs are equal, false otherwise
> + */
> +bool operator==(const ControlId &lhs, const ControlInfo &rhs)
> +{
> +	return lhs == rhs.id();
> +}
> +
> +/**
> + * \brief Compare control information and ID for equality
> + * \param[in] lhs Left-hand side control information
> + * \param[in] rhs Right-hand side control identifier
> + *
> + * Control information is compared based on the ID only, as a camera may not
> + * have two separate controls with the same ID.
> + *
> + * \return True if \a lhs and \a rhs are equal, false otherwise
> + */
> +bool operator==(const ControlInfo &lhs, const ControlId &rhs)
> +{
> +	return lhs.id() == rhs;
> +}
> +
> +/**
> + * \class ControlList
> + * \brief Associate a list of ControlId with their values for a camera
> + *
> + * A ControlList wraps a map of ControlId to ControlValue and provide
> + * additional validation against the control information exposed by a Camera.
> + *
> + * A list is only valid for as long as the camera it refers to is valid. After
> + * that calling any method of the ControlList class other than its destructor
> + * will cause undefined behaviour.
> + */
> +
> +/**
> + * \brief Construct a ControlList with a reference to the Camera it applies on
> + * \param[in] camera The camera
> + */
> +ControlList::ControlList(Camera *camera)
> +	: camera_(camera)
> +{
> +}
> +
> +/**
> + * \typedef ControlList::iterator
> + * \brief Iterator for the controls contained within the list
> + */
> +
> +/**
> + * \typedef ControlList::const_iterator
> + * \brief Const iterator for the controls contained within the list
> + */
> +
> +/**
> + * \fn iterator ControlList::begin()
> + * \brief Retrieve an iterator to the first Control in the list
> + * \return An iterator to the first Control in the list
> + */
> +
> +/**
> + * \fn const_iterator ControlList::begin() const
> + * \brief Retrieve a const_iterator to the first Control in the list
> + * \return A const_iterator to the first Control in the list
> + */
> +
> +/**
> + * \fn iterator ControlList::end()
> + * \brief Retrieve an iterator pointing to the past-the-end control in the list
> + * \return An iterator to the element following the last control in the list
> + */
> +
> +/**
> + * \fn const_iterator ControlList::end() const
> + * \brief Retrieve a const iterator pointing to the past-the-end control in the
> + * list
> + * \return A const iterator to the element following the last control in the
> + * list
> + */
> +
> +/**
> + * \brief Check if the list contains a control with the specified \a info
> + * \param[in] info The control info
> + * \return True if the list contains a matching control, false otherwise
> + */
> +bool ControlList::contains(const ControlInfo *info) const
> +{
> +	return controls_.find(info) != controls_.end();
> +}
> +
> +/**
> + * \fn ControlList::empty()
> + * \brief Identify if the list is empty
> + * \return True if the list does not contain any control, false otherwise
> + */
> +
> +/**
> + * \fn ControlList::size()
> + * \brief Retrieve the number of controls in the list
> + * \return The number of Control entries stored in the list
> + */
> +
> +/**
> + * \fn ControlList::clear()
> + * \brief Removes all controls from the list
> + */
> +
> +/**
> + * \fn ControlList::operator[](const ControlInfo *info)
> + * \brief Access or insert the control specified by \a info
> + * \param[in] info The control info
> + *
> + * This method returns a reference to the control identified by \a info,
> + * inserting it in the list if the info is not already present.
> + *
> + * \return A reference to the value of the control identified by \a info
> + */
> +
> +/**
> + * \brief Update the list with a union of itself and \a other
> + * \param other The other list
> + *
> + * Update the control list to include all values from the \a other list.
> + * Elements in the list whose control IDs are contained in \a other are updated
> + * with the value from \a other. Elements in the \a other list that have no
> + * corresponding element in the list are added to the list with their value.
> + *
> + * The behaviour is undefined if the two lists refer to different Camera
> + * instances.
> + */
> +void ControlList::update(const ControlList &other)
> +{
> +	if (other.camera_ != camera_) {
> +		LOG(Controls, Error)
> +			<< "Can't update ControlList from a different camera";
> +		return;
> +	}
> +
> +	for (auto it : other) {
> +		const ControlInfo *info = it.first;
> +		const ControlValue &value = it.second;
> +
> +		controls_[info] = value;
> +	}
> +}
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/gen-controls.awk b/src/libcamera/gen-controls.awk
> new file mode 100755
> index 000000000000..f3d068123012
> --- /dev/null
> +++ b/src/libcamera/gen-controls.awk
> @@ -0,0 +1,106 @@
> +#!/usr/bin/awk -f
> +
> +# SPDX-License-Identifier: LGPL-2.1-or-later
> +
> +# Controls are documented using Doxygen in the main controls.cpp source.
> +#
> +# Generate control tables directly from the documentation, creating enumerations
> +# to support the IDs and static type information regarding each control.
> +
> +BEGIN {
> +	id=0
> +	input=ARGV[1]
> +	mode=ARGV[2]
> +	output=ARGV[3]
> +}
> +
> +# Detect Doxygen style comment blocks and ignore other lines
> +/^\/\*\*$/ { in_doxygen=1; first_line=1; next }
> +// { if (!in_doxygen) next }
> +
> +# Entry point for the Control Documentation
> +/ * \\enum ControlId$/ { in_controls=1; first_line=0; next }
> +// { if (!in_controls) next }
> +
> +# Extract control information
> +/ \* \\var/ { names[++id]=$3; first_line=0; next }
> +/ \* ControlType:/ { types[id] = $3 }
> +
> +# End of comment blocks
> +/^ \*\// { in_doxygen=0 }
> +
> +# Identify the end of controls
> +/^ \* \\/ { if (first_line) exit }
> +// { first_line=0 }
> +
> +################################
> +# Support output file generation
> +
> +function basename(file) {
> +	sub(".*/", "", file)
> +	return file
> +}
> +
> +function Header(file, description) {
> +	print "/* SPDX-License-Identifier: LGPL-2.1-or-later */" > file
> +	print "/*" > file
> +	print " * Copyright (C) 2019, Google Inc." > file
> +	print " *" > file
> +	print " * " basename(file) " - " description > file
> +	print " *" > file
> +	print " * This file is auto-generated. Do not edit." > file
> +	print " */" > file
> +	print "" > file
> +}
> +
> +function EnterNameSpace(file) {
> +	print "namespace libcamera {" > file
> +	print "" > file
> +}
> +
> +function ExitNameSpace(file) {
> +	print "" > file
> +	print "} /* namespace libcamera */" > file
> +}
> +
> +function GenerateHeader(file) {
> +	Header(file, "Control ID list")
> +
> +	print "#ifndef __LIBCAMERA_CONTROL_IDS_H__" > file
> +	print "#define __LIBCAMERA_CONTROL_IDS_H__" > file
> +	print "" > file
> +
> +	EnterNameSpace(file)
> +	print "enum ControlId {" > file
> +	for (i=1; i <= id; ++i) {
> +		printf "\t%s,\n", names[i] > file
> +	}
> +	print "};" > file
> +	ExitNameSpace(file)
> +
> +	print "" > file
> +	print "#endif // __LIBCAMERA_CONTROL_IDS_H__" > file
> +}
> +
> +function GenerateTable(file) {
> +	Header(file, "Control types")
> +	print "#include <libcamera/controls.h>" > file
> +	print "" > file
> +
> +	EnterNameSpace(file)
> +
> +	print "extern const std::unordered_map<ControlId, ControlIdentifier>" > file
> +	print "controlTypes {" > file
> +	for (i=1; i <= id; ++i) {
> +		printf "\t{ %s, { %s, \"%s\", ControlValue%s } },\n", names[i], names[i], names[i], types[i] > file
> +	}
> +	print "};" > file
> +	ExitNameSpace(file)
> +}
> +
> +END {
> +	if (mode == "--header")
> +		GenerateHeader(output)
> +	else
> +		GenerateTable(output)
> +}
> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> index 985aa7e8ab0e..b1ee92735e41 100644
> --- a/src/libcamera/meson.build
> +++ b/src/libcamera/meson.build
> @@ -3,6 +3,7 @@ libcamera_sources = files([
>      'camera.cpp',
>      'camera_manager.cpp',
>      'camera_sensor.cpp',
> +    'controls.cpp',
>      'device_enumerator.cpp',
>      'device_enumerator_sysfs.cpp',
>      'event_dispatcher.cpp',
> @@ -66,6 +67,16 @@ if libudev.found()
>      ])
>  endif
>  
> +gen_controls = files('gen-controls.awk')
> +
> +control_types_cpp = custom_target('control_types_cpp',
> +                                  input : files('controls.cpp'),
> +                                  output : 'control_types.cpp',
> +                                  depend_files : gen_controls,
> +                                  command : [gen_controls, '@INPUT@', '--code', '@OUTPUT@'])
> +
> +libcamera_sources += control_types_cpp
> +
>  libcamera_deps = [
>      cc.find_library('dl'),
>      libudev,
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

-- 
Regards,
Niklas Söderlund


More information about the libcamera-devel mailing list