summaryrefslogtreecommitdiff
path: root/.clang-format
blob: 5b8857dae924cf5e21fe5fb459097ee17603fcbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# SPDX-License-Identifier: GPL-2.0-only
#
# clang-format configuration file. Intended for clang-format >= 7.
#
# For more information, see:
#
#   Documentation/process/clang-format.rst
#   https://clang.llvm.org/docs/ClangFormat.html
#   https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
Language: Cpp
AccessModifierOffset: -8
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterClass: true
  AfterControlStatement: false
  AfterEnum: false
  AfterFunction: true
  AfterNamespace: false
  AfterObjCDeclaration: false
  AfterStruct: false
  AfterUnion: false
  AfterExternBlock: false
  BeforeCatch: false
  BeforeElse: false
  IndentBraces: false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
  - 'udev_list_entry_foreach'
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
  # Headers matching the name of the component are matched automatically.
  # Priority 1
  # Other library headers (explicit overrides to match before system headers)
  - Regex:           '(<jpeglib.h>|<libudev.h>|<tiffio.h>|<xf86drm.h>|<xf86drmMode.h>|<yaml.h>)'
    Priority:        9
  # Qt includes (match before C++ standard library)
  - Regex:           '<Q([A-Za-z0-9\-_])+>'
    Priority:        9
  # Headers in <> with an extension. (+system libraries)
  - Regex:           '<([A-Za-z0-9\-_])+\.h>'
    Priority:        2
  # System headers 
  - Regex:           '<sys/.*>'
    Priority:        2
  # C++ standard library includes (no extension)
  - Regex:           '<([A-Za-z0-9\-_/])+>'
    Priority:        2
  # Linux headers, as a second group/subset of system headers
  - Regex:           '<linux/.*>'
    Priority:        3
  # Headers for libcamera Base support
  - Regex:           '<libcamera/base/private.h>'
    Priority:        4
  - Regex:           '<libcamera/base/.*\.h>'
    Priority:        5
  # Public API Headers for libcamera, which are not in a subdir (i.e. ipa/,internal/)
  - Regex:           '<libcamera/([A-Za-z0-9\-_])+.h>'
    Priority:        6
  # IPA Interfaces
  - Regex:           '<libcamera/ipa/.*\.h>'
    Priority:        7
  # libcamera Internal headers in ""  
  - Regex:           '"libcamera/internal/.*\.h"'
    Priority:        8
  # Other libraries headers with one group per library (.h or .hpp)
  - Regex:           '<.*/.*\.hp*>'
    Priority:        9
  # local modular includes "path/file.h" (.h or .hpp)
  - Regex:           '"(.*/)+.*\.hp*"'
    Priority:        10
  # Other local headers "file.h" with extension (.h or .hpp)
  - Regex:           '".*.hp*"'
    Priority:        11
  # Any unmatched line, separated from the last group
  - Regex:	     '"*"'
    Priority:        100

IncludeIsMainRegex: '(_test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true

# Taken from git's rules
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60

PointerAlignment: Right
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Always
...
30'>330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2021, Google Inc.
 *
 * camera_hal_config.cpp - Camera HAL configuration file manager
 */
#include "camera_hal_config.h"

#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 8
#include <experimental/filesystem>
namespace std {
namespace filesystem = std::experimental::filesystem;
}
#else
#include <filesystem>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <yaml.h>

#include <hardware/camera3.h>

#include <libcamera/base/log.h>

using namespace libcamera;

LOG_DEFINE_CATEGORY(HALConfig)

class CameraHalConfig::Private : public Extensible::Private
{
	LIBCAMERA_DECLARE_PUBLIC(CameraHalConfig)

public:
	Private();

	int parseConfigFile(FILE *fh, std::map<std::string, CameraConfigData> *cameras);

private:
	std::string parseValue();
	std::string parseKey();
	int parseValueBlock();
	int parseCameraLocation(CameraConfigData *cameraConfigData,
				const std::string &location);
	int parseCameraConfigData(const std::string &cameraId);
	int parseCameras();
	int parseEntry();

	yaml_parser_t parser_;
	std::map<std::string, CameraConfigData> *cameras_;
};

CameraHalConfig::Private::Private()
{
}

std::string CameraHalConfig::Private::parseValue()
{
	yaml_token_t token;

	/* Make sure the token type is a value and get its content. */
	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_VALUE_TOKEN) {
		yaml_token_delete(&token);
		return "";
	}
	yaml_token_delete(&token);

	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_SCALAR_TOKEN) {
		yaml_token_delete(&token);
		return "";
	}

	std::string value(reinterpret_cast<char *>(token.data.scalar.value),
			  token.data.scalar.length);
	yaml_token_delete(&token);

	return value;
}

std::string CameraHalConfig::Private::parseKey()
{
	yaml_token_t token;

	/* Make sure the token type is a key and get its value. */
	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_SCALAR_TOKEN) {
		yaml_token_delete(&token);
		return "";
	}

	std::string value(reinterpret_cast<char *>(token.data.scalar.value),
			  token.data.scalar.length);
	yaml_token_delete(&token);

	return value;
}

int CameraHalConfig::Private::parseValueBlock()
{
	yaml_token_t token;

	/* Make sure the next token are VALUE and BLOCK_MAPPING_START. */
	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_VALUE_TOKEN) {
		yaml_token_delete(&token);
		return -EINVAL;
	}
	yaml_token_delete(&token);

	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_BLOCK_MAPPING_START_TOKEN) {
		yaml_token_delete(&token);
		return -EINVAL;
	}
	yaml_token_delete(&token);

	return 0;
}

int CameraHalConfig::Private::parseCameraLocation(CameraConfigData *cameraConfigData,
						  const std::string &location)
{
	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::parseCameraConfigData(const std::string &cameraId)
{
	int ret = parseValueBlock();
	if (ret)
		return ret;

	/*
	 * Parse the camera properties and store them in a cameraConfigData
	 * instance.
	 *
	 * Add a safety counter to make sure we don't loop indefinitely in case
	 * the configuration file is malformed.
	 */
	CameraConfigData cameraConfigData;
	unsigned int sentinel = 100;
	bool blockEnd = false;
	yaml_token_t token;

	do {
		yaml_parser_scan(&parser_, &token);
		switch (token.type) {
		case YAML_KEY_TOKEN: {
			yaml_token_delete(&token);

			/*
			 * Parse the camera property key and make sure it is
			 * valid.
			 */
			std::string key = parseKey();
			std::string value = parseValue();
			if (key.empty() || value.empty())
				return -EINVAL;

			if (key == "location") {
				ret = parseCameraLocation(&cameraConfigData, value);
				if (ret) {
					LOG(HALConfig, Error)
						<< "Unknown location: " << value;
					return -EINVAL;
				}
			} else if (key == "rotation") {
				ret = std::stoi(value);
				if (ret < 0 || ret >= 360) {
					LOG(HALConfig, Error)
						<< "Unknown rotation: " << value;
					return -EINVAL;
				}
				cameraConfigData.rotation = ret;
			} else {
				LOG(HALConfig, Error)
					<< "Unknown key: " << key;
				return -EINVAL;
			}
			break;
		}

		case YAML_BLOCK_END_TOKEN:
			blockEnd = true;
			[[fallthrough]];
		default:
			yaml_token_delete(&token);
			break;
		}

		--sentinel;
	} while (!blockEnd && sentinel);
	if (!sentinel)
		return -EINVAL;

	(*cameras_)[cameraId] = cameraConfigData;

	return 0;
}

int CameraHalConfig::Private::parseCameras()
{
	int ret = parseValueBlock();
	if (ret) {
		LOG(HALConfig, Error) << "Configuration file is not valid";
		return ret;
	}

	/*
	 * Parse the camera 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":
	 *     key: value
	 *     key: value
	 *     ...
	 *
	 *   "camera1 id":
	 *     key: value
	 *     key: value
	 *     ...
	 */
	bool blockEnd = false;
	yaml_token_t token;
	do {
		yaml_parser_scan(&parser_, &token);
		switch (token.type) {
		case YAML_KEY_TOKEN: {
			yaml_token_delete(&token);

			/* Parse the camera ID as key of the property list. */
			std::string cameraId = parseKey();
			if (cameraId.empty())
				return -EINVAL;

			ret = parseCameraConfigData(cameraId);
			if (ret)
				return -EINVAL;
			break;
		}
		case YAML_BLOCK_END_TOKEN:
			blockEnd = true;
			[[fallthrough]];
		default:
			yaml_token_delete(&token);
			break;
		}
	} while (!blockEnd);

	return 0;
}

int CameraHalConfig::Private::parseEntry()
{
	int ret = -EINVAL;

	/*
	 * Parse each key we find in the file.
	 *
	 * The 'cameras' keys maps to a list of (lists) of camera properties.
	 */

	std::string key = parseKey();
	if (key.empty())
		return ret;

	if (key == "cameras")
		ret = parseCameras();
	else
		LOG(HALConfig, Error) << "Unknown key: " << key;

	return ret;
}

int CameraHalConfig::Private::parseConfigFile(FILE *fh,
					      std::map<std::string, CameraConfigData> *cameras)
{
	cameras_ = cameras;

	int ret = yaml_parser_initialize(&parser_);
	if (!ret) {
		LOG(HALConfig, Error) << "Failed to initialize yaml parser";
		return -EINVAL;
	}
	yaml_parser_set_input_file(&parser_, fh);

	yaml_token_t token;
	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_STREAM_START_TOKEN) {
		LOG(HALConfig, Error) << "Configuration file is not valid";
		yaml_token_delete(&token);
		yaml_parser_delete(&parser_);
		return -EINVAL;
	}
	yaml_token_delete(&token);

	yaml_parser_scan(&parser_, &token);
	if (token.type != YAML_BLOCK_MAPPING_START_TOKEN) {
		LOG(HALConfig, Error) << "Configuration file is not valid";
		yaml_token_delete(&token);
		yaml_parser_delete(&parser_);
		return -EINVAL;
	}
	yaml_token_delete(&token);

	/* Parse the file and parse each single key one by one. */
	do {
		yaml_parser_scan(&parser_, &token);
		switch (token.type) {
		case YAML_KEY_TOKEN:
			yaml_token_delete(&token);
			ret = parseEntry();
			break;

		case YAML_STREAM_END_TOKEN:
			ret = -ENOENT;
			[[fallthrough]];
		default:
			yaml_token_delete(&token);
			break;
		}
	} while (ret >= 0);
	yaml_parser_delete(&parser_);

	if (ret && ret != -ENOENT)
		LOG(HALConfig, Error) << "Configuration file is not valid";

	return ret == -ENOENT ? 0 : ret;
}

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::filesystem::path filePath = LIBCAMERA_SYSCONF_DIR;
	filePath /= "camera_hal.yaml";
	if (!std::filesystem::is_regular_file(filePath)) {
		LOG(HALConfig, Debug)
			<< "Configuration file: \"" << filePath << "\" not found";
		return -ENOENT;
	}

	FILE *fh = fopen(filePath.c_str(), "r");
	if (!fh) {
		int ret = -errno;
		LOG(HALConfig, Error) << "Failed to open configuration file "
				      << filePath << ": " << strerror(-ret);
		return ret;
	}

	exists_ = true;

	int ret = _d()->parseConfigFile(fh, &cameras_);
	fclose(fh);
	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;
}