new file mode 100644
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * control_info.cpp - Serialize and de-serialize a list of control info
+ */
+
+#include <iostream>
+
+#include <libcamera/camera.h>
+#include <libcamera/camera_manager.h>
+#include <libcamera/controls.h>
+
+#include "device_enumerator.h"
+#include "media_device.h"
+#include "serializer.h"
+#include "test.h"
+#include "v4l2_subdevice.h"
+
+#include "serialization_test.h"
+
+using namespace std;
+using namespace libcamera;
+
+class ControlInfoListSerializeTest : public SerializationTest
+{
+public:
+ ControlInfoListSerializeTest()
+ : SerializationTest()
+ {
+ }
+
+private:
+ void initValidationMatrix()
+ {
+ const V4L2ControlInfoMap &controls = sensor_->controls();
+
+ unsigned int i = 0;
+ for (const auto &ctrl : controls) {
+ unsigned int v4l2Id = ctrl.first;
+ const V4L2ControlInfo &info = ctrl.second;
+ ControlId id;
+
+ switch (v4l2Id) {
+ case V4L2_CID_BRIGHTNESS:
+ id = Brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ id = Contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ id = Saturation;
+ break;
+ default:
+ continue;
+ }
+
+ infoValidationMatrix[i][INFO_CTRL_ID] = id;
+ /* \todo Assume all controls have integers values. */
+ infoValidationMatrix[i][INFO_CTRL_MIN] = info.min().getInt();
+ infoValidationMatrix[i][INFO_CTRL_MAX] = info.max().getInt();
+ infoValidationMatrix[i][INFO_CTRL_FLAG] = 0;
+
+ numCtrls_++;
+ i++;
+ }
+ }
+
+ int init()
+ {
+ int ret = SerializationTest::init();
+ if (ret != TestPass)
+ return ret;
+
+ ret = initSubdevice();
+ if (ret < 0)
+ return ret;
+
+ initValidationMatrix();
+
+ return TestPass;
+ }
+
+ int run()
+ {
+ const ControlInfoMap &controls = camera_->controls();
+
+ std::unique_ptr<DataBlob> blob = controls.serialize();
+ if (!blob) {
+ cerr << "Failed to serialize the control info" << endl;
+ return TestFail;
+ }
+
+ int ret = validateInfoBlobSize(blob.get());
+ if (ret != TestPass)
+ return ret;
+
+ /* Validate each serialized info data. */
+ uint8_t *b = blob->data();
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (!validateInfoBlob(b))
+ return TestFail;
+
+ b += INFO_BLOB_SIZE;
+ }
+
+ /* De-serialize a control info list and re-validate it. */
+ ControlInfoMap newInfoMap;
+ newInfoMap.deserialize(blob->data(), blob->size());
+ for (auto it : newInfoMap) {
+ ControlId id = it.first;
+ ControlInfo &info = it.second;
+
+ if (!validateInfoValue(id, info))
+ return TestFail;
+ }
+
+ return TestPass;
+ }
+};
+
+TEST_REGISTER(ControlInfoListSerializeTest)
@@ -1,5 +1,6 @@
serialization_tests = [
[ 'control_list', 'control_list.cpp' ],
+ [ 'control_info_list', 'control_info_list.cpp' ],
]
foreach t : serialization_tests
@@ -187,3 +187,106 @@ bool SerializationTest::validateDataValue(unsigned int id, const DataValue &data
return true;
}
+
+int SerializationTest::validateInfoBlobSize(DataBlob *blob)
+{
+ size_t blobSize = blob->size();
+ if (blobSize % Serializer::BLOB_ALIGN_BYTES) {
+ cerr << "Serialized control info has incorrect alignement"
+ << endl;
+ return TestFail;
+ }
+
+ size_t expectedSize = INFO_BLOB_SIZE * numCtrls_;
+ if (blobSize != expectedSize) {
+ cerr << "Serialized info list has incorrect size: "
+ << " expected size " << expectedSize
+ << " got " << blobSize << endl;
+ return TestFail;
+ }
+
+ return TestPass;
+}
+
+bool SerializationTest::validateInfoBlob(uint8_t *info)
+{
+ uint32_t id = *(reinterpret_cast<uint32_t *>(info));
+ uint32_t size = *(reinterpret_cast<uint32_t *>(Serializer::INFO_BLOB_SIZE(info)));
+
+ /* Manually access min and max assuming they're 32-bits integers. */
+ uint32_t min = *(reinterpret_cast<uint32_t *>(info + 16));
+ uint32_t max = *(reinterpret_cast<uint32_t *>(info + 24));
+ bool found = false;
+
+ cout << "Testing serialized info: " << id << " - "
+ << size << " - " << min << " - " << max << endl;
+
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (infoValidationMatrix[i][INFO_CTRL_ID] != id)
+ continue;
+
+ found = true;
+
+ unsigned int *entry = infoValidationMatrix[i];
+ if (entry[INFO_CTRL_FLAG]) {
+ cerr << "The info with id " << id
+ << " has been serialized twice" << endl;
+ return false;
+ }
+ entry[INFO_CTRL_FLAG] = true;
+
+ if (entry[INFO_CTRL_MIN] != min ||
+ entry[INFO_CTRL_MAX] != max ||
+ size != INFO_BLOB_DATA_SIZE) {
+ cerr << "The info with id " << id
+ << " has been wrongly serialized" << endl;
+ return false;
+ }
+ }
+
+ if (!found) {
+ cerr << "Non-existing info with id " << id << endl;
+ return false;
+ }
+
+ cout << "Serialization of info: " << id << " = Success."
+ << endl;
+
+ return true;
+}
+
+bool SerializationTest::validateInfoValue(unsigned int id,
+ const DataInfo &info)
+{
+ bool found = false;
+ uint32_t min = info.min().getInt();
+ uint32_t max = info.max().getInt();
+
+ cout << "Testing de-serialized info: " << id
+ << " - " << min << " - " << max << endl;
+
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (infoValidationMatrix[i][INFO_CTRL_ID] != id)
+ continue;
+
+ found = true;
+
+ unsigned int *controlValidation = infoValidationMatrix[i];
+ if (controlValidation[INFO_CTRL_MIN] != min ||
+ controlValidation[INFO_CTRL_MAX] != max) {
+ cerr << "The info with id " << id
+ << " has been wrongly serialized" << endl;
+ return false;
+ }
+ }
+
+ if (!found) {
+ cerr << "Non-existing info with id " << id << endl;
+ return false;
+ }
+
+ cout << "De-serialization of info: " << id << " = Success."
+ << endl;
+
+ return true;
+}
@@ -45,6 +45,23 @@ protected:
static constexpr unsigned int VALUE_BLOB_DATA_SIZE = 8;
static constexpr unsigned int VALUE_BLOB_SIZE = 24;
+ /* Info validation matrix */
+ unsigned int infoValidationMatrix[CTRL_MAX][4];
+
+ /* Indices on the info validation matrix fields. */
+ static constexpr unsigned int INFO_CTRL_ID = 0;
+ static constexpr unsigned int INFO_CTRL_MIN = 1;
+ static constexpr unsigned int INFO_CTRL_MAX = 2;
+ static constexpr unsigned int INFO_CTRL_FLAG = 3;
+
+ /*
+ * Serialized info sizes.
+ * \todo Assume a serialized info is 32 bytes in total (header +
+ * DataInfo), as values are simple integers.
+ */
+ static constexpr unsigned int INFO_BLOB_DATA_SIZE = 16;
+ static constexpr unsigned int INFO_BLOB_SIZE = 32;
+
int init();
void cleanup();
@@ -54,6 +71,10 @@ protected:
bool validateValueBlob(uint8_t *dataBlob);
bool validateDataValue(unsigned int id, const DataValue &dataValue);
+ int validateInfoBlobSize(DataBlob *blob);
+ bool validateInfoBlob(uint8_t *infoBlob);
+ bool validateInfoValue(unsigned int id, const DataInfo &dataInfo);
+
std::unique_ptr<DeviceEnumerator> enumerator_;
std::shared_ptr<MediaDevice> media_;
std::shared_ptr<Camera> camera_;
Test the serialization procedure of a ControlInfoMap by manually unwrapping a serialized data blob containing control info and validate them against the sensor subdevice reported ones. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> --- test/serialization/control_info_list.cpp | 122 ++++++++++++++++++++++ test/serialization/meson.build | 1 + test/serialization/serialization_test.cpp | 103 ++++++++++++++++++ test/serialization/serialization_test.h | 21 ++++ 4 files changed, 247 insertions(+) create mode 100644 test/serialization/control_info_list.cpp