@@ -47,9 +47,13 @@ private:
static void store(const ControlValue &value, ByteStreamBuffer &buffer);
static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
+ void populateControlValueEntry(struct ipa_control_value_entry &entry,
+ const ControlValue &value,
+ uint32_t offset);
+
ControlValue loadControlValue(ByteStreamBuffer &buffer,
- bool isArray = false, unsigned int count = 1);
- ControlInfo loadControlInfo(ByteStreamBuffer &buffer);
+ ControlType type,
+ bool isArray, unsigned int count);
unsigned int serial_;
unsigned int serialSeed_;
@@ -15,7 +15,7 @@ namespace libcamera {
extern "C" {
#endif
-#define IPA_CONTROLS_FORMAT_VERSION 1
+#define IPA_CONTROLS_FORMAT_VERSION 2
enum ipa_controls_id_map_type {
IPA_CONTROL_ID_MAP_CONTROLS,
@@ -34,20 +34,26 @@ struct ipa_controls_header {
};
struct ipa_control_value_entry {
- uint32_t id;
uint8_t type;
uint8_t is_array;
uint16_t count;
uint32_t offset;
- uint32_t padding[1];
+ uint32_t reserved[2];
+};
+
+struct ipa_control_list_entry {
+ uint32_t id;
+ struct ipa_control_value_entry value;
};
struct ipa_control_info_entry {
uint32_t id;
uint32_t type;
- uint32_t offset;
uint8_t direction;
- uint8_t padding[3];
+ uint8_t padding[7];
+ struct ipa_control_value_entry min;
+ struct ipa_control_value_entry max;
+ struct ipa_control_value_entry def;
};
#ifdef __cplusplus
@@ -144,7 +144,7 @@ void ControlSerializer::reset()
size_t ControlSerializer::binarySize(const ControlValue &value)
{
- return sizeof(ControlType) + value.data().size_bytes();
+ return value.data().size_bytes();
}
size_t ControlSerializer::binarySize(const ControlInfo &info)
@@ -164,7 +164,8 @@ size_t ControlSerializer::binarySize(const ControlInfo &info)
size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
{
size_t size = sizeof(struct ipa_controls_header)
- + infoMap.size() * sizeof(struct ipa_control_info_entry);
+ + infoMap.size() * (sizeof(struct ipa_control_info_entry) +
+ 3 * sizeof(struct ipa_control_value_entry));
for (const auto &ctrl : infoMap)
size += binarySize(ctrl.second);
@@ -184,7 +185,7 @@ size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
size_t ControlSerializer::binarySize(const ControlList &list)
{
size_t size = sizeof(struct ipa_controls_header)
- + list.size() * sizeof(struct ipa_control_value_entry);
+ + list.size() * sizeof(struct ipa_control_list_entry);
for (const auto &ctrl : list)
size += binarySize(ctrl.second);
@@ -195,16 +196,17 @@ size_t ControlSerializer::binarySize(const ControlList &list)
void ControlSerializer::store(const ControlValue &value,
ByteStreamBuffer &buffer)
{
- const ControlType type = value.type();
- buffer.write(&type);
buffer.write(value.data());
}
-void ControlSerializer::store(const ControlInfo &info, ByteStreamBuffer &buffer)
+void ControlSerializer::populateControlValueEntry(struct ipa_control_value_entry &entry,
+ const ControlValue &value,
+ uint32_t offset)
{
- store(info.min(), buffer);
- store(info.max(), buffer);
- store(info.def(), buffer);
+ entry.type = value.type();
+ entry.is_array = value.isArray();
+ entry.count = value.numElements();
+ entry.offset = offset;
}
/**
@@ -232,7 +234,8 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
/* Compute entries and data required sizes. */
size_t entriesSize = infoMap.size()
- * sizeof(struct ipa_control_info_entry);
+ * (sizeof(struct ipa_control_info_entry) +
+ 3 * sizeof(struct ipa_control_value_entry));
size_t valuesSize = 0;
for (const auto &ctrl : infoMap)
valuesSize += binarySize(ctrl.second);
@@ -280,11 +283,18 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
struct ipa_control_info_entry entry;
entry.id = id->id();
entry.type = id->type();
- entry.offset = values.offset();
entry.direction = static_cast<ControlId::DirectionFlags::Type>(id->direction());
- entries.write(&entry);
- store(info, values);
+ populateControlValueEntry(entry.min, info.min(), values.offset());
+ store(info.min(), values);
+
+ populateControlValueEntry(entry.max, info.max(), values.offset());
+ store(info.max(), values);
+
+ populateControlValueEntry(entry.def, info.def(), values.offset());
+ store(info.def(), values);
+
+ entries.write(&entry);
}
if (buffer.overflow())
@@ -341,7 +351,7 @@ int ControlSerializer::serialize(const ControlList &list,
else
idMapType = IPA_CONTROL_ID_MAP_V4L2;
- size_t entriesSize = list.size() * sizeof(struct ipa_control_value_entry);
+ size_t entriesSize = list.size() * sizeof(struct ipa_control_list_entry);
size_t valuesSize = 0;
for (const auto &ctrl : list)
valuesSize += binarySize(ctrl.second);
@@ -365,12 +375,9 @@ int ControlSerializer::serialize(const ControlList &list,
unsigned int id = ctrl.first;
const ControlValue &value = ctrl.second;
- struct ipa_control_value_entry entry;
+ struct ipa_control_list_entry entry;
entry.id = id;
- entry.type = value.type();
- entry.is_array = value.isArray();
- entry.count = value.numElements();
- entry.offset = values.offset();
+ populateControlValueEntry(entry.value, value, values.offset());
entries.write(&entry);
store(value, values);
@@ -383,12 +390,10 @@ int ControlSerializer::serialize(const ControlList &list,
}
ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
+ ControlType type,
bool isArray,
unsigned int count)
{
- ControlType type;
- buffer.read(&type);
-
ControlValue value;
value.reserve(type, isArray, count);
@@ -397,15 +402,6 @@ ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
return value;
}
-ControlInfo ControlSerializer::loadControlInfo(ByteStreamBuffer &b)
-{
- ControlValue min = loadControlValue(b);
- ControlValue max = loadControlValue(b);
- ControlValue def = loadControlValue(b);
-
- return ControlInfo(min, max, def);
-}
-
/**
* \fn template<typename T> T ControlSerializer::deserialize(ByteStreamBuffer &buffer)
* \brief Deserialize an object from a binary buffer
@@ -483,8 +479,7 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
ControlInfoMap::Map ctrls;
for (unsigned int i = 0; i < hdr->entries; ++i) {
- const struct ipa_control_info_entry *entry =
- entries.read<decltype(*entry)>();
+ const auto *entry = entries.read<const ipa_control_info_entry>();
if (!entry) {
LOG(Serializer, Error) << "Out of data";
return {};
@@ -511,15 +506,43 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
const ControlId *controlId = idMap->at(entry->id);
ASSERT(controlId);
- if (entry->offset != values.offset()) {
+ const ipa_control_value_entry &min_entry = entry->min;
+ const ipa_control_value_entry &max_entry = entry->max;
+ const ipa_control_value_entry &def_entry = entry->def;
+
+ if (min_entry.offset != values.offset()) {
LOG(Serializer, Error)
- << "Bad data, entry offset mismatch (entry "
+ << "Bad data, entry offset mismatch (min entry "
<< i << ")";
return {};
}
+ ControlValue min =
+ loadControlValue(values, static_cast<ControlType>(min_entry.type),
+ min_entry.is_array, min_entry.count);
+
+ if (max_entry.offset != values.offset()) {
+ LOG(Serializer, Error)
+ << "Bad data, entry offset mismatch (max entry "
+ << i << ")";
+ return {};
+ }
+ ControlValue max =
+ loadControlValue(values, static_cast<ControlType>(max_entry.type),
+ max_entry.is_array, max_entry.count);
+
+ if (def_entry.offset != values.offset()) {
+ LOG(Serializer, Error)
+ << "Bad data, entry offset mismatch (def entry "
+ << i << ")";
+ return {};
+ }
+ ControlValue def =
+ loadControlValue(values, static_cast<ControlType>(def_entry.type),
+ def_entry.is_array, def_entry.count);
+
/* Create and store the ControlInfo. */
- ctrls.emplace(controlId, loadControlInfo(values));
+ ctrls.emplace(controlId, ControlInfo(min, max, def));
}
/*
@@ -618,12 +641,12 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
ControlList ctrls(*idMap);
for (unsigned int i = 0; i < hdr->entries; ++i) {
- const struct ipa_control_value_entry *entry =
- entries.read<decltype(*entry)>();
- if (!entry) {
+ auto *list_entry = entries.read<const ipa_control_list_entry>();
+ if (!list_entry) {
LOG(Serializer, Error) << "Out of data";
return {};
}
+ const ipa_control_value_entry *entry = &list_entry->value;
if (entry->offset != values.offset()) {
LOG(Serializer, Error)
@@ -632,8 +655,9 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
return {};
}
- ctrls.set(entry->id,
- loadControlValue(values, entry->is_array, entry->count));
+ ctrls.set(list_entry->id,
+ loadControlValue(values, static_cast<ControlType>(entry->type),
+ entry->is_array, entry->count));
}
return ctrls;
@@ -26,28 +26,28 @@
* The following diagram describes the layout of the ControlList packet.
*
* ~~~~
- * +-------------------------+ . .
- * Header / | ipa_controls_header | | |
- * | | | | |
- * \ | | | |
- * +-------------------------+ | |
- * / | ipa_control_value_entry | | hdr.data_offset |
- * | | #0 | | |
- * Control | +-------------------------+ | |
- * value | | ... | | |
- * entries | +-------------------------+ | |
- * | | ipa_control_value_entry | | hdr.size |
- * \ | #hdr.entries - 1 | | |
- * +-------------------------+ | |
- * | empty space (optional) | | |
- * +-------------------------+ <--´ . |
- * / | ... | | entry[n].offset |
- * Data | | ... | | |
- * section | | value data for entry #n | <-----´ |
- * \ | ... | |
- * +-------------------------+ |
- * | empty space (optional) | |
- * +-------------------------+ <-------------------------´
+ * +-------------------------+ . .
+ * Header / | ipa_controls_header | | |
+ * | | | | |
+ * \ | | | |
+ * +-------------------------+ | |
+ * / | ipa_control_list_entry | | hdr.data_offset |
+ * | | #0 | | |
+ * Control | +-------------------------+ | |
+ * value | | ... | | |
+ * entries | +-------------------------+ | |
+ * | | ipa_control_list_entry | | hdr.size |
+ * \ | #hdr.entries - 1 | | |
+ * +-------------------------+ | |
+ * | empty space (optional) | | |
+ * +-------------------------+ <--´ . |
+ * / | ... | | entry[n].value.offset |
+ * Data | | ... | | |
+ * section | | value data for entry #n | <-----´ |
+ * \ | ... | |
+ * +-------------------------+ |
+ * | empty space (optional) | |
+ * +-------------------------+ <-----------------------------´
* ~~~~
*
* The packet header contains the size of the packet, the number of entries, and
@@ -56,12 +56,14 @@
* offset ipa_controls_header::data_offset from the beginning of the packet, and
* shall be aligned to a multiple of 8 bytes.
*
- * Entries are described by the ipa_control_value_entry structure. They contain
- * the numerical ID of the control, its type, and the number of control values.
+ * Entries are described by the ipa_control_list_entry structure. They contain
+ * the numerical ID of the control and an ipa_control_value_entry structure,
+ * which contains the type and the number of control values.
*
- * The control values are stored in the data section in the platform's native
- * format. The ipa_control_value_entry::offset field stores the offset from the
- * beginning of the data section to the values.
+ * The control values are stored (as ipa_control_list_entry) in the data
+ * section in the platform's native format. The ipa_control_value_entry::offset
+ * field stores the offset from the beginning of the data section to the
+ * values.
*
* All control values in the data section shall be stored in the same order as
* the respective control entries, shall be aligned to a multiple of 8 bytes,
@@ -74,59 +76,65 @@
* The following diagram describes the layout of the ControlInfoMap packet.
*
* ~~~~
- * +-------------------------+ . .
- * Header / | ipa_controls_header | | |
- * | | | | |
- * \ | | | |
- * +-------------------------+ | |
- * / | ipa_control_info_entry | | hdr.data_offset |
- * | | #0 | | |
- * Control | +-------------------------+ | |
- * info | | ... | | |
- * entries | +-------------------------+ | |
- * | | ipa_control_info_entry | | hdr.size |
- * \ | #hdr.entries - 1 | | |
- * +-------------------------+ | |
- * | empty space (optional) | | |
- * +-------------------------+ <--´ . |
- * / | ... | | entry[n].offset |
- * Data | | ... | | |
- * section | | info data for entry #n | <-----´ |
- * \ | ... | |
- * +-------------------------+ |
- * | empty space (optional) | |
- * +-------------------------+ <-------------------------´
+ * +------------------------------+ . .
+ * Header / | ipa_controls_header | | |
+ * | | | | |
+ * \ | | | |
+ * +------------------------------+ | |
+ * / | ipa_control_info_entry | | hdr.data_offset |
+ * | | #0 | | |
+ * Control | +------------------------------+ | |
+ * info | | ... | | |
+ * entries | +------------------------------+ | |
+ * | | ipa_control_info_entry | | |
+ * \ | #hdr.entries - 1 | | |
+ * +------------------------------+ | |
+ * | empty space (optional) | | |
+ * +------------------------------+ <--´ . . . |
+ * / | ... | | entry[n].min.offset |
+ * | | ... | | | | |
+ * Data | | ... | | | entry[n].max.offset |
+ * section | | min value data for entry #n | <-----´ | | |
+ * | | max value data for entry #n | <-------´ | entry[n].def.offset |
+ * | | def value data for entry #n | <---------´ |
+ * | | ... | |
+ * \ | ... | |
+ * +------------------------------+ |
+ * | empty space (optional) | |
+ * +------------------------------+ <-------------------------------´
* ~~~~
*
* The packet header is identical to the ControlList packet header.
*
* Entries are described by the ipa_control_info_entry structure. They contain
- * the numerical ID and type of the control. The control info data is stored
- * in the data section as described by the following diagram.
+ * the numerical ID, direction (in/out) of the control, and three
+ * ipa_control_value_entry structures for the min, max, and def ControlValues
+ * that make up the ControlInfo.
*
- * ~~~~
- * +-------------------------+ .
- * / | ... | | entry[n].offset
- * | +-------------------------+ <-----´
- * | | minimum value (#n) | \
- * Data | +-------------------------+ |
- * section | | maximum value (#n) | | Entry #n
- * | +-------------------------+ |
- * | | default value (#n) | /
- * | +-------------------------+
- * \ | ... |
- * +-------------------------+
- * ~~~~
+ * The control info has no associated data in the data section;
+ * instead the three control values for min, max, and def are stored in the data section
+ *
+ *
+ * The control values are stored (as ipa_control_list_entry) in the data
+ * section in the platform's native format. The ipa_control_value_entry::offset
+ * field stores the offset from the beginning of the data section to the
+ * values.
*
- * The minimum, maximum and default values are stored in the platform's native
- * data format. The ipa_control_info_entry::offset field stores the offset from
- * the beginning of the data section to the info data.
+ * ipa_control_value_entry structures contain the relevant
+ * ControlValue information for the ControlInfo's min, max, and def
+ * respectively, and their associated data is stored in the data section.
*
- * Info data in the data section shall be stored in the same order as the
- * entries array, shall be aligned to a multiple of 8 bytes, and shall be
- * contiguous in memory.
+ * The control info has no associated data in the data section. Instead the
+ * minimum, maximum, and default control values of the control info are stored
+ * n the data section in the platform's native data format. The
+ * ipa_control_value_entry::offset field stores the offset from the beginning
+ * of the data section to the control value data.
*
- * As for the ControlList packet, empty spaces may be present between the end of
+ * All control values in the data section shall be stored in the same order as
+ * the respective control info entries, in the order of min, max, def, and shall be
+ * aligned to a multiple of 8 bytes, and shall be contiguous in memory.
+ *
+ * As with the ControlList packet, empty spaces may be present between the end of
* the entries array and the data section, and after the data section. They
* shall be ignored when parsing the packet.
*/
@@ -192,8 +200,6 @@ static_assert(sizeof(ipa_controls_header) == 32,
/**
* \struct ipa_control_value_entry
* \brief Description of a serialized ControlValue entry
- * \var ipa_control_value_entry::id
- * The numerical ID of the control
* \var ipa_control_value_entry::type
* The type of the control (defined by enum ControlType)
* \var ipa_control_value_entry::is_array
@@ -203,13 +209,25 @@ static_assert(sizeof(ipa_controls_header) == 32,
* \var ipa_control_value_entry::offset
* The offset in bytes from the beginning of the data section to the control
* value data (shall be a multiple of 8 bytes).
- * \var ipa_control_value_entry::padding
- * Padding bytes (shall be set to 0)
+ * \var ipa_control_value_entry::reserved
+ * Reserved for future extensions
*/
static_assert(sizeof(ipa_control_value_entry) == 16,
"Invalid ABI size change for struct ipa_control_value_entry");
+/**
+ * \struct ipa_control_list_entry
+ * \brief Description of a serialized ControlList entry
+ * \var ipa_control_list_entry::id
+ * The numerical ID of the control
+ * \var ipa_control_list_entry::value
+ * The description of the serialized ControlValue
+ */
+
+static_assert(sizeof(ipa_control_list_entry) == 20,
+ "Invalid ABI size change for struct ipa_control_list_entry");
+
/**
* \struct ipa_control_info_entry
* \brief Description of a serialized ControlInfo entry
@@ -217,8 +235,6 @@ static_assert(sizeof(ipa_control_value_entry) == 16,
* The numerical ID of the control
* \var ipa_control_info_entry::type
* The type of the control (defined by enum ControlType)
- * \var ipa_control_info_entry::offset
- * The offset in bytes from the beginning of the data section to the control
* info data (shall be a multiple of 8 bytes)
* \var ipa_control_info_entry::direction
* The directions in which the control is allowed to be sent. This is a flags
@@ -226,9 +242,15 @@ static_assert(sizeof(ipa_control_value_entry) == 16,
* metadata). \sa ControlId::Direction
* \var ipa_control_info_entry::padding
* Padding bytes (shall be set to 0)
+ * \var ipa_control_info_entry::min
+ * The description of the serialized ControlValue (min)
+ * \var ipa_control_info_entry::max
+ * The description of the serialized ControlValue (max)
+ * \var ipa_control_info_entry::def
+ * The description of the serialized ControlValue (def)
*/
-static_assert(sizeof(ipa_control_info_entry) == 16,
+static_assert(sizeof(ipa_control_info_entry) == 64,
"Invalid ABI size change for struct ipa_control_info_entry");
} /* namespace libcamera */