Source files in libcamera start by a comment block header, which includes the file name and a one-line description of the file contents. While the latter is useful to get a quick overview of the file contents at a glance, the former is mostly a source of inconvenience. The name in the comments can easily get out of sync with the file name when files are renamed, and copy & paste during development have often lead to incorrect names being used to start with. Readers of the source code are expected to know which file they're looking it. Drop the file name from the header comment block. The change was generated with the following script: ---------------------------------------- dirs="include/libcamera src test utils" declare -rA patterns=( ['c']=' \* ' ['cpp']=' \* ' ['h']=' \* ' ['py']='# ' ['sh']='# ' ) for ext in ${!patterns[@]} ; do files=$(for dir in $dirs ; do find $dir -name "*.${ext}" ; done) pattern=${patterns[${ext}]} for file in $files ; do name=$(basename ${file}) sed -i "s/^\(${pattern}\)${name} - /\1/" "$file" done done ---------------------------------------- This misses several files that are out of sync with the comment block header. Those will be addressed separately and manually. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
208 lines
4.8 KiB
C++
208 lines
4.8 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2021, Google Inc.
|
|
*
|
|
* Camera HAL configuration file manager
|
|
*/
|
|
#include "camera_hal_config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
|
|
#include <libcamera/base/file.h>
|
|
#include <libcamera/base/log.h>
|
|
|
|
#include "libcamera/internal/yaml_parser.h"
|
|
|
|
#include <hardware/camera3.h>
|
|
|
|
using namespace libcamera;
|
|
|
|
LOG_DEFINE_CATEGORY(HALConfig)
|
|
|
|
class CameraHalConfig::Private : public Extensible::Private
|
|
{
|
|
LIBCAMERA_DECLARE_PUBLIC(CameraHalConfig)
|
|
|
|
public:
|
|
Private();
|
|
|
|
int parseConfigFile(File &file, std::map<std::string, CameraConfigData> *cameras);
|
|
|
|
private:
|
|
int parseCameraConfigData(const std::string &cameraId, const YamlObject &);
|
|
int parseLocation(const YamlObject &, CameraConfigData &cameraConfigData);
|
|
int parseRotation(const YamlObject &, CameraConfigData &cameraConfigData);
|
|
|
|
std::map<std::string, CameraConfigData> *cameras_;
|
|
};
|
|
|
|
CameraHalConfig::Private::Private()
|
|
{
|
|
}
|
|
|
|
int CameraHalConfig::Private::parseConfigFile(File &file,
|
|
std::map<std::string, CameraConfigData> *cameras)
|
|
{
|
|
/*
|
|
* Parse the HAL properties.
|
|
*
|
|
* Each camera properties block is a list of properties associated
|
|
* with the ID (as assembled by CameraSensor::generateId()) of the
|
|
* camera they refer to.
|
|
*
|
|
* cameras:
|
|
* "camera0 id":
|
|
* location: value
|
|
* rotation: value
|
|
* ...
|
|
*
|
|
* "camera1 id":
|
|
* location: value
|
|
* rotation: value
|
|
* ...
|
|
*/
|
|
|
|
cameras_ = cameras;
|
|
|
|
std::unique_ptr<YamlObject> root = YamlParser::parse(file);
|
|
if (!root)
|
|
return -EINVAL;
|
|
|
|
if (!root->isDictionary())
|
|
return -EINVAL;
|
|
|
|
/* Parse property "cameras" */
|
|
if (!root->contains("cameras"))
|
|
return -EINVAL;
|
|
|
|
const YamlObject &yamlObjectCameras = (*root)["cameras"];
|
|
|
|
if (!yamlObjectCameras.isDictionary())
|
|
return -EINVAL;
|
|
|
|
for (const auto &[cameraId, configData] : yamlObjectCameras.asDict()) {
|
|
if (parseCameraConfigData(cameraId, configData))
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraHalConfig::Private::parseCameraConfigData(const std::string &cameraId,
|
|
const YamlObject &cameraObject)
|
|
|
|
{
|
|
if (!cameraObject.isDictionary())
|
|
return -EINVAL;
|
|
|
|
CameraConfigData &cameraConfigData = (*cameras_)[cameraId];
|
|
|
|
/* Parse property "location" */
|
|
if (parseLocation(cameraObject, cameraConfigData))
|
|
return -EINVAL;
|
|
|
|
/* Parse property "rotation" */
|
|
if (parseRotation(cameraObject, cameraConfigData))
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraHalConfig::Private::parseLocation(const YamlObject &cameraObject,
|
|
CameraConfigData &cameraConfigData)
|
|
{
|
|
if (!cameraObject.contains("location"))
|
|
return -EINVAL;
|
|
|
|
std::string location = cameraObject["location"].get<std::string>("");
|
|
|
|
if (location == "front")
|
|
cameraConfigData.facing = CAMERA_FACING_FRONT;
|
|
else if (location == "back")
|
|
cameraConfigData.facing = CAMERA_FACING_BACK;
|
|
else
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraHalConfig::Private::parseRotation(const YamlObject &cameraObject,
|
|
CameraConfigData &cameraConfigData)
|
|
{
|
|
if (!cameraObject.contains("rotation"))
|
|
return -EINVAL;
|
|
|
|
int32_t rotation = cameraObject["rotation"].get<int32_t>(-1);
|
|
|
|
if (rotation < 0 || rotation >= 360) {
|
|
LOG(HALConfig, Error)
|
|
<< "Unknown rotation: " << rotation;
|
|
return -EINVAL;
|
|
}
|
|
|
|
cameraConfigData.rotation = rotation;
|
|
return 0;
|
|
}
|
|
|
|
CameraHalConfig::CameraHalConfig()
|
|
: Extensible(std::make_unique<Private>()), exists_(false), valid_(false)
|
|
{
|
|
parseConfigurationFile();
|
|
}
|
|
|
|
/*
|
|
* Open the HAL configuration file and validate its content.
|
|
* Return 0 on success, a negative error code otherwise
|
|
* retval -ENOENT The configuration file is not available
|
|
* retval -EINVAL The configuration file is available but not valid
|
|
*/
|
|
int CameraHalConfig::parseConfigurationFile()
|
|
{
|
|
std::string filePath = LIBCAMERA_SYSCONF_DIR "/camera_hal.yaml";
|
|
|
|
File file(filePath);
|
|
if (!file.exists()) {
|
|
LOG(HALConfig, Debug)
|
|
<< "Configuration file: \"" << filePath << "\" not found";
|
|
return -ENOENT;
|
|
}
|
|
|
|
if (!file.open(File::OpenModeFlag::ReadOnly)) {
|
|
int ret = file.error();
|
|
LOG(HALConfig, Error) << "Failed to open configuration file "
|
|
<< filePath << ": " << strerror(-ret);
|
|
return ret;
|
|
}
|
|
|
|
exists_ = true;
|
|
|
|
int ret = _d()->parseConfigFile(file, &cameras_);
|
|
if (ret)
|
|
return -EINVAL;
|
|
|
|
valid_ = true;
|
|
|
|
for (const auto &c : cameras_) {
|
|
const std::string &cameraId = c.first;
|
|
const CameraConfigData &camera = c.second;
|
|
LOG(HALConfig, Debug) << "'" << cameraId << "' "
|
|
<< "(" << camera.facing << ")["
|
|
<< camera.rotation << "]";
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const CameraConfigData *CameraHalConfig::cameraConfigData(const std::string &cameraId) const
|
|
{
|
|
const auto &it = cameras_.find(cameraId);
|
|
if (it == cameras_.end()) {
|
|
LOG(HALConfig, Error)
|
|
<< "Camera '" << cameraId
|
|
<< "' not described in the HAL configuration file";
|
|
return nullptr;
|
|
}
|
|
|
|
return &it->second;
|
|
}
|