@@ -94,14 +94,16 @@ private:
class ControlId
{
public:
- ControlId(unsigned int id, const std::string &name, ControlType type)
- : id_(id), name_(name), type_(type)
+ ControlId(unsigned int id, const std::string &name, ControlType type,
+ bool isCompound)
+ : id_(id), name_(name), type_(type), isCompound_(isCompound)
{
}
unsigned int id() const { return id_; }
const std::string &name() const { return name_; }
ControlType type() const { return type_; }
+ bool isCompound() const { return isCompound_; }
private:
ControlId &operator=(const ControlId &) = delete;
@@ -110,6 +112,7 @@ private:
unsigned int id_;
std::string name_;
ControlType type_;
+ bool isCompound_;
};
static inline bool operator==(unsigned int lhs, const ControlId &rhs)
@@ -138,7 +141,7 @@ class Control : public ControlId
public:
using type = T;
- Control(unsigned int id, const char *name);
+ Control(unsigned int id, const char *name, bool isCompound = false);
private:
Control(const Control &) = delete;
@@ -272,6 +275,9 @@ public:
template<typename T>
void set(const Control<T> &ctrl, const Span<T> &values)
{
+ if (!ctrl.isCompound())
+ return;
+
ControlValue *val = find(ctrl.id());
if (!val)
return;
@@ -51,7 +51,8 @@ controls:
description: Specify a fixed gain parameter
- CompoundControl:
- type: int8_t
+ type: int32_t
description: A fictional compound control
+ compound: true
...
@@ -415,8 +415,10 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
/**
* \todo Find a way to preserve the control name for debugging
* purpose.
+ *
+ * FIXME: set isCompound to false unconditionally
*/
- controlIds_.emplace_back(utils::make_unique<ControlId>(entry.id, "", type));
+ controlIds_.emplace_back(utils::make_unique<ControlId>(entry.id, "", type, false));
if (entry.offset != values.offset()) {
LOG(Serializer, Error)
@@ -581,38 +581,38 @@ bool ControlValue::operator==(const ControlValue &other) const
#ifndef __DOXYGEN__
template<>
-Control<void>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeNone)
+Control<void>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeNone, isCompound)
{
}
template<>
-Control<bool>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeBool)
+Control<bool>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeBool, isCompound)
{
}
template<>
-Control<int8_t>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeInteger8)
+Control<int8_t>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeInteger8, isCompound)
{
}
template<>
-Control<int32_t>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeInteger32)
+Control<int32_t>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeInteger32, isCompound)
{
}
template<>
-Control<int64_t>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeInteger64)
+Control<int64_t>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeInteger64, isCompound)
{
}
template<>
-Control<float>::Control(unsigned int id, const char *name)
- : ControlId(id, name, ControlTypeFloat)
+Control<float>::Control(unsigned int id, const char *name, bool isCompound)
+ : ControlId(id, name, ControlTypeFloat, isCompound)
{
}
#endif /* __DOXYGEN__ */
@@ -26,6 +26,7 @@ ${description}\n *\n''')
${description}
*/''')
def_template = string.Template('extern const Control<${type}> ${name}(${id_name}, "${name}");')
+ def_compound_template = string.Template('extern const Control<${type}> ${name}(${id_name}, "${name}", true);')
ctrls_doc = []
ctrls_def = []
@@ -67,8 +68,17 @@ ${description}
except KeyError:
pass
+ try:
+ compound = ctrl['compound']
+ isCompound = True
+ except KeyError:
+ isCompound = False
+
ctrls_doc.append(doc_template.substitute(info))
- ctrls_def.append(def_template.substitute(info))
+ if isCompound:
+ ctrls_def.append(def_compound_template.substitute(info))
+ else:
+ ctrls_def.append(def_template.substitute(info))
ctrls_map.append('\t{ ' + id_name + ', &' + name + ' },')
return {
@@ -97,9 +97,11 @@ ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl)
/**
* \brief Construct a V4L2ControlId from a struct v4l2_query_ext_ctrl
* \param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel
+ *
+ * FIXME: set isCompound to false unconditionally
*/
V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl)
- : ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl))
+ : ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl), false)
{
}
@@ -53,40 +53,52 @@ protected:
cout << span[0] << endl;
/*
- * Compound Controls
- *
- * As of now, all Controls are now 'compounds' when set with a
- * Span<> of values.
- *
- * We need to define how to establish that a Control is actually
- * a compound or supports a single value.
+ * Compound Controls: can be set with a span of values
*/
- list.set(controls::Brightness, {0, 125, 255});
- Span<int32_t> iSpan = list.get(controls::Brightness);
+ list.set(controls::CompoundControl, { 0, 125, 253 });
+ Span<int32_t> iSpan = list.get(controls::CompoundControl);
cout << iSpan.size() << endl;
for (uint32_t i : iSpan)
cout << i << endl;
/*
- * But they can still be accessed and operated with a single
- * value.
+ * But they can still be accessed and operated as a single
+ * value control.
*/
- list.set(controls::Brightness, 112);
- cout << list.get(controls::Brightness) << endl;
+ list.set(controls::CompoundControl, 112);
+ cout << list.get(controls::CompoundControl) << endl;
/*
* Or set with a Span and accessed by value. The first item
- * is returned.
+ * is returned in this case.
*/
- list.set(controls::Brightness, {50, 125});
- cout << list.get(controls::Brightness) << endl;
+ list.set(controls::CompoundControl, { 50, 125 });
+ cout << list.get(controls::CompoundControl) << endl;
/* The other way around works as well. */
- list.set(controls::Brightness, 133);
- Span<int32_t> s = list.get(controls::Brightness);
+ list.set(controls::CompoundControl, 133);
+ Span<int32_t> s = list.get(controls::CompoundControl);
cout << s << endl;
+ /*
+ * Try to set a non-compound control with a span<> and make
+ * sure it fails.
+ */
+ list.set(controls::Brightness, 55);
+ uint32_t brightness = list.get(controls::Brightness);
+ if (brightness != 55) {
+ cerr << "Failed to set non-compound control" << endl;
+ return TestFail;
+ }
+
+ list.set(controls::Brightness, { 45, 30 });
+ brightness = list.get(controls::Brightness);
+ if (brightness != 55) {
+ cerr << "non-compound control set with span<>" << endl;
+ return TestFail;
+ }
+
return TestPass;
}
};
Add 'isCompound' flag to the control framework. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> --- include/libcamera/controls.h | 12 +++++-- src/libcamera/control_ids.yaml | 3 +- src/libcamera/control_serializer.cpp | 4 ++- src/libcamera/controls.cpp | 24 +++++++------- src/libcamera/gen-controls.py | 12 ++++++- src/libcamera/v4l2_controls.cpp | 4 ++- test/controls/compound_controls.cpp | 48 +++++++++++++++++----------- 7 files changed, 70 insertions(+), 37 deletions(-)