new file mode 100644
@@ -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__ */
@@ -1,5 +1,6 @@
libcamera_api = files([
'buffer.h',
+ 'controls.h',
'camera.h',
'camera_manager.h',
'event_dispatcher.h',
new file mode 100644
@@ -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 */
@@ -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',