[libcamera-devel,RFC,1/5] libcamera: Add control handling

Message ID 20190606205654.9311-2-kieran.bingham@ideasonboard.com
State Superseded
Headers show
Series
  • Libcamera Controls
Related show

Commit Message

Kieran Bingham June 6, 2019, 8:56 p.m. UTC
---
 include/libcamera/controls.h  | 106 ++++++++++++
 include/libcamera/meson.build |   1 +
 src/libcamera/controls.cpp    | 310 ++++++++++++++++++++++++++++++++++
 src/libcamera/meson.build     |   1 +
 4 files changed, 418 insertions(+)
 create mode 100644 include/libcamera/controls.h
 create mode 100644 src/libcamera/controls.cpp

Patch

diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
new file mode 100644
index 000000000000..0b751aa7a9d2
--- /dev/null
+++ b/include/libcamera/controls.h
@@ -0,0 +1,106 @@ 
+/* 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 <map>
+#include <set>
+
+namespace libcamera {
+
+enum ControlId : uint32_t {
+	/* IPA Controls */
+	IpaAwbEnable,
+
+	/* Manual Controls */
+	ManualBrightness,
+	ManualExposure,
+	ManualGain,
+};
+
+enum ControlType : uint32_t {
+	ControlBool,
+	ControlInteger,
+	ControlString,
+};
+
+enum ControlAction : uint8_t {
+	ControlWrite = 1,
+	ControlRead = 2,
+	ControlWriteRead = 3,
+};
+
+class ControlValue
+{
+public:
+	ControlValue(enum ControlType type);
+	ControlValue(bool value);
+	ControlValue(int value);
+	ControlValue(const char *value);
+	ControlValue(const std::string &value);
+
+	ControlType type() const { return type_; };
+
+	bool isRead() const { return action_ == ControlRead ||
+				     action_ == ControlWriteRead; };
+	bool isWrite() const { return action_ == ControlWrite ||
+				      action_ == ControlWriteRead; };
+
+	void set(bool value);
+	void set(int value);
+	void set(unsigned int value);
+
+	void set(const char *value);
+	void set(const std::string &value);
+
+	bool getBool() const;
+	int getInt() const;
+	std::string getString() const;
+
+	std::string toString() const;
+
+private:
+	ControlType type_;
+	ControlAction action_;
+
+	union {
+		bool bool_;
+		int integer_;
+	};
+	std::string string_;
+};
+
+std::ostream &operator<<(std::ostream &stream, const ControlValue &value);
+
+class Control
+{
+public:
+	/* Create a Read control */
+	Control(ControlId id);
+
+	/* Create a Write control */
+	Control(ControlId id, bool value);
+	Control(ControlId id, int value);
+
+	ControlId id() const { return id_; };
+	ControlValue &value() { return value_; };
+
+	std::string toString() const;
+
+	/* Overloaded for std::set usage */
+	bool operator<(const Control &rhs) const { return id_ < rhs.id_; };
+
+private:
+	ControlId id_;
+	ControlValue value_;
+};
+
+std::ostream &operator<<(std::ostream &stream, const Control &control);
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_CONTROLS_H__ */
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index 1fcf6b509a1e..6a69db60b3c9 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -1,5 +1,6 @@ 
 libcamera_api = files([
     'buffer.h',
+    'controls.h',
     'camera.h',
     'camera_manager.h',
     'event_dispatcher.h',
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
new file mode 100644
index 000000000000..bef0ddcc89a3
--- /dev/null
+++ b/src/libcamera/controls.cpp
@@ -0,0 +1,310 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * controls.cpp - Control handling
+ */
+
+#include <map>
+#include <string>
+
+#include <libcamera/controls.h>
+
+#include "log.h"
+
+/**
+ * \file controls.h
+ * \brief Describes all controls supported by a camera
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(ControlId)
+
+/**
+ * \enum Controls
+ * Control Identifiers
+ * \var IpaAwbEnable
+ * bool: Enables or disables the AWB
+ * \var ManualExposure
+ * Manually control the exposure time in milli-seconds
+ * \var ManualGain
+ * Controls the value of the manual gain setting
+ */
+
+/**
+ * \enum ControlType
+ * Determines the type of value represented by a \a ControlValue
+ * \var ControlBool
+ * Identifies controls storing a boolean value
+ * \var ControlInteger
+ * Identifies controls storing an integer value
+ * \var ControlString
+ * Identifies controls storing a string value.
+ */
+
+/**
+ * \enum ControlAction
+ * Declare the intent of the ControlValue.
+ * \var ControlNoop
+ * The ControlValue has not been given an action to perform. It can exist as
+ * part of the request, but will not be acted upon by the device.
+ * \var ControlWrite
+ * The ControlValue is to be given and set at the camera
+ * \var ControlRead
+ * The ControlValue is to be read from the camera
+ * \var ControlWriteRead
+ * The ControlValue should be written to the camera and read before request
+ * completion
+ */
+
+/*
+ * Two sets of tables are generated for the control definitions.
+ *
+ * An enum to declare the ID (in controls.h), and a type to establish its
+ * representation.
+ *
+ * Todo: Automate the generation of both tables from a single input table.
+ */
+struct ControlIdentifier {
+	ControlId id;
+	const char *name;
+	ControlType type;
+} static const ControlTypes[] = {
+#define CONTROL_TYPE(_id, _type) { _id, #_id, _type }
+
+	CONTROL_TYPE(IpaAwbEnable,		ControlBool),
+	CONTROL_TYPE(ManualBrightness,		ControlInteger),
+	CONTROL_TYPE(ManualExposure,		ControlInteger),
+	CONTROL_TYPE(ManualGain,		ControlInteger),
+
+#undef CONTROL_TYPE
+};
+
+static struct ControlIdentifier FindControlType(ControlId id)
+{
+	for (auto ident : ControlTypes) {
+		if (ident.id == id)
+			return ident;
+	}
+
+	LOG(ControlId, Fatal) << "Failed to find a ControlType.";
+
+	/* Unreachable. */
+	return {};
+}
+
+static ControlType GetControlType(ControlId id)
+{
+	return FindControlType(id).type;
+}
+
+static std::string ControlIDName(ControlId id)
+{
+	return FindControlType(id).name;
+}
+
+/**
+ * \brief Construct a ControlValue of a given type without initialising a value
+ * \param[in] type The type of ControlValue to be read
+ */
+ControlValue::ControlValue(ControlType type)
+	: type_(type), action_(ControlRead)
+{
+}
+
+/**
+ * \brief Construct a Boolean Control Value
+ * \param[in] value Boolean value to store
+ */
+ControlValue::ControlValue(bool value)
+	: type_(ControlBool), action_(ControlWrite), bool_(value)
+{
+}
+
+/**
+ * \brief Construct an integer Control Value
+ * \param[in] value Integer value to store
+ */
+ControlValue::ControlValue(int value)
+	: type_(ControlInteger), action_(ControlWrite), integer_(value)
+{
+}
+
+/**
+ * \brief Construct a string Control Value
+ * \param[in] value String representation to store
+ */
+ControlValue::ControlValue(const char *value)
+	: type_(ControlString), action_(ControlWrite), string_(value)
+{
+}
+
+/**
+ * \brief Construct a string Control Value
+ * \param[in] value String representation to store
+ */
+ControlValue::ControlValue(const std::string &value)
+	: type_(ControlString), action_(ControlWrite), string_(value)
+{
+}
+
+/**
+ * \brief Set the Control value with a boolean
+ * \param[in] value Boolean value to store
+ */
+void ControlValue::set(bool value)
+{
+	ASSERT(type_ == ControlBool);
+
+	bool_ = value;
+}
+
+/**
+ * \brief Set the Control value with an integer
+ * \param[in] value Integer value to store
+ */
+void ControlValue::set(int value)
+{
+	ASSERT(type_ == ControlInteger);
+
+	integer_ = value;
+}
+
+/**
+ * \brief Set the Control value with a string representation
+ * \param[in] value String value to store
+ */
+void ControlValue::set(const char *value)
+{
+	ASSERT(type_ == ControlString);
+
+	string_ = value;
+}
+
+/**
+ * \brief Set the Control value with a string representation
+ * \param[in] value String value to store
+ */
+void ControlValue::set(const std::string &value)
+{
+	ASSERT(type_ == ControlString);
+
+	string_ = value;
+}
+
+/**
+ * \brief Get the Control value.
+ *
+ * The ControlValue type must be Boolean.
+ */
+bool ControlValue::getBool() const
+{
+	ASSERT(type_ == ControlBool);
+
+	return bool_;
+}
+
+/**
+ * \brief Get the Control value.
+ *
+ * The ControlValue type must be Integer.
+ */
+int ControlValue::getInt() const
+{
+	ASSERT(type_ == ControlInteger);
+
+	return integer_;
+}
+
+/**
+ * \brief Get the Control value.
+ *
+ * The ControlValue type must be String.
+ */
+std::string ControlValue::getString() const
+{
+	ASSERT(type_ == ControlString);
+
+	return string_;
+}
+
+/**
+ * \brief Prepare a string representation of the ControlValue
+ */
+std::string ControlValue::toString() const
+{
+	switch (type_) {
+	case ControlBool:
+		return bool_ ? "True" : "False";
+	case ControlInteger:
+		return std::to_string(integer_);
+	case ControlString:
+		return string_;
+	}
+
+	/* Unreachable */
+	return "<ControlType Error>";
+}
+
+std::ostream &operator<<(std::ostream &stream, const ControlValue &value)
+{
+	return stream << value.toString();
+}
+
+
+/**
+ * \brief Create a new empty control
+ * \param[in] id ID of the new control
+ *
+ * The control is constructed, and the type determined by the \a ControlId.
+ */
+Control::Control(ControlId id)
+	: id_(id), value_(GetControlType(id))
+{
+}
+
+/**
+ * \brief Create a new control
+ * \param[in] id ID of the new control
+ * \param[in] value Boolean value to apply to the new control
+ *
+ * The control is constructed, and the type determined by the \a ControlId.
+ */
+Control::Control(ControlId id, bool value)
+	: id_(id), value_(value)
+{
+	ASSERT(GetControlType(id) == ControlBool);
+}
+
+/**
+ * \brief Create a new control
+ * \param[in] id ID of the new control
+ * \param[in] value Integer value to apply to the new control
+ *
+ * The control is constructed, and the type determined by the \a ControlId.
+ */
+Control::Control(ControlId id, int value)
+	: id_(id), value_(value)
+{
+	ASSERT(GetControlType(id) == ControlInteger);
+}
+
+/**
+ * \brief Prepare a string representation of the Control
+ */
+std::string Control::toString() const
+{
+	std::stringstream ss;
+
+	ss << "Control: " << ControlIDName(id_) << " : " << value_;
+
+	return ss.str();
+}
+
+std::ostream &operator<<(std::ostream &stream, const Control &control)
+{
+	return stream << control.toString();
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index fa1fbcb5faf5..7c67fdf3691a 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',