libcamera/utils/codegen/controls.py
Paul Elder 39fe4ad968 utils: codegen: controls.py: Parse direction information
In preparation for adding support for querying direction information
from controls, parse the direction information from control ID
definitions. This can later be plugged in directly to the IPA code
generators simply by using ctrl.direction.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
2024-12-18 17:26:52 +09:00

142 lines
4 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2019, Google Inc.
#
# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#
# Helper classes to handle source code generation for libcamera controls
class ControlEnum(object):
def __init__(self, data):
self.__data = data
@property
def description(self):
"""The enum description"""
return self.__data.get('description')
@property
def name(self):
"""The enum name"""
return self.__data.get('name')
@property
def value(self):
"""The enum value"""
return self.__data.get('value')
class Control(object):
def __init__(self, name, data, vendor, mode):
self.__name = name
self.__data = data
self.__enum_values = None
self.__size = None
self.__vendor = vendor
enum_values = data.get('enum')
if enum_values is not None:
self.__enum_values = [ControlEnum(enum) for enum in enum_values]
size = self.__data.get('size')
if size is not None:
if len(size) == 0:
raise RuntimeError(f'Control `{self.__name}` size must have at least one dimension')
# Compute the total number of elements in the array. If any of the
# array dimension is a string, the array is variable-sized.
num_elems = 1
for dim in size:
if type(dim) is str:
num_elems = 0
break
dim = int(dim)
if dim <= 0:
raise RuntimeError(f'Control `{self.__name}` size must have positive values only')
num_elems *= dim
self.__size = num_elems
if mode == 'properties':
self.__direction = 'out'
else:
direction = self.__data.get('direction')
if direction is None:
raise RuntimeError(f'Control `{self.__name}` missing required field `{direction}`')
if direction not in ['in', 'out', 'inout']:
raise RuntimeError(f'Control `{self.__name}` direction `{direction}` is invalid; must be one of `in`, `out`, or `inout`')
self.__direction = direction
@property
def description(self):
"""The control description"""
return self.__data.get('description')
@property
def enum_values(self):
"""The enum values, if the control is an enumeration"""
if self.__enum_values is None:
return
for enum in self.__enum_values:
yield enum
@property
def enum_values_count(self):
"""The number of enum values, if the control is an enumeration"""
if self.__enum_values is None:
return 0
return len(self.__enum_values)
@property
def is_enum(self):
"""Is the control an enumeration"""
return self.__enum_values is not None
@property
def vendor(self):
"""The vendor string, or None"""
return self.__vendor
@property
def name(self):
"""The control name (CamelCase)"""
return self.__name
@property
def type(self):
typ = self.__data.get('type')
size = self.__data.get('size')
if typ == 'string':
return 'std::string'
if self.__size is None:
return typ
if self.__size:
return f"Span<const {typ}, {self.__size}>"
else:
return f"Span<const {typ}>"
@property
def direction(self):
in_flag = 'ControlId::Direction::In'
out_flag = 'ControlId::Direction::Out'
if self.__direction == 'inout':
return f'{in_flag} | {out_flag}'
if self.__direction == 'in':
return in_flag
if self.__direction == 'out':
return out_flag
@property
def element_type(self):
return self.__data.get('type')
@property
def size(self):
return self.__size