From patchwork Fri Nov 10 10:59:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19194 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D3AB0C3285 for ; Fri, 10 Nov 2023 11:00:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 51F60629C8; Fri, 10 Nov 2023 12:00:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1699614001; bh=dlfiNxQIcLROOxPnUDt9+UpfHMH7B8/7kT1KXwIba+0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=1DkthgIxL2GzZQE8irmaYNjRRI+XeKeAl1OmY8YteAgcqhFhquyFvCl4muv6caaox Kr7bmsnvN5f0gRpa4jqaS+7IIZU93S7eE3lEirbwkch4FJeI2BPfknyWrOAVbV2TWP iSaXoxROIbOLy5qgTjIrT+FlyNuAuKKeQ5UntEick0D1elYe2WX+pwNgAkM6zcc2cK kuvdpVosYBKaf0ksdYxtkh6UZab8ahEeikzk8R9mtfMGv8QosAOExRsmPvbowYn0ic br6cf3GS7nPxgsAHCbdBZECSmfvUd0HCi3NUMFgDWU/7mMyyPSCZj5Y4NWZhcl9zQ2 IaLzEJBHMbQIg== Received: from mail-lj1-x235.google.com (mail-lj1-x235.google.com [IPv6:2a00:1450:4864:20::235]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D35D6629BD for ; Fri, 10 Nov 2023 11:59:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="c6HfCTb3"; dkim-atps=neutral Received: by mail-lj1-x235.google.com with SMTP id 38308e7fff4ca-2c503dbe50dso25258391fa.1 for ; Fri, 10 Nov 2023 02:59:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1699613997; x=1700218797; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ng52OPkZn77AerY9h5LP2IbzTh0qdlf5lJORgUvbVBo=; b=c6HfCTb3zMSmhVh/izo7SpL1yz7TYprHN3nVsxlMR4XhOWI0DCR7xSdrDYOlBsYeil 7H1g1bXeYhmS/oOyvpauHccJbS6dHmZAUGsGoUh6tcm1t/qxB3P13Xs47Y69QNHqgbob RSuhm/DSuNlxCGdKHQTmqlfXBCHNKiHe8p28Y6fofZZdQve0Y2ZVCVGmmHb+eN+D+hIc nJHpqcRdm+fQIVLQnVFYblAHZISsTYyR7FQAXtFUJUcAGj1dGndXYTgC6eVHZtmaAVLa DOQohwKcv0g2xSaJn7qnUjAHbgHMgtrCoNH/Lg3x4uQvvhTWlF4ZFeBqlY23epSV/NOI UWyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699613997; x=1700218797; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ng52OPkZn77AerY9h5LP2IbzTh0qdlf5lJORgUvbVBo=; b=l2r9XXgA+gWWxdC5t8KXb0VJiGMytf4d3dRfx2b9ihmCJl26kgNosGvBhUIzAZpxSc G82Hanp99n/rGDCG36FjGKuMaFMM7VlHW2r9BR8O+r+ocfphKlCL5VYT5VrtiRV0U/0E o3V6l3jLaWCIqVl7EpKeB7xS0wn1G7+VpZUFNCTrJijmwvtOFKa4aKCKWrM6juZF8Vx8 Mqcy8rvvJemjraUB3PS6U67erkRNSfq/a7CGYbjy6U9gQo3tb/15659LLke0mxNWpQZD yCMg8EDTfvDLzS4Yn6OQBXGGjcLmVyNai1pcP9YsTeKk19FPl+iLCv6nqmWfu+M3koin cjJw== X-Gm-Message-State: AOJu0YwugqSGXryaHLjOw4H4VnzJYoIyQadpbghc4TE1pyVoizQujadO ihOFJLmBXRZeJ8tsMqlFVde5wuvQw4mA/KmVjUOKeg== X-Google-Smtp-Source: AGHT+IGEresNeNY3Wzi7hJF7Ngv6mvkNc10+EZ/c9mvMv/Rp9m6WvoSbHlJ5NjlnCzWfSv2TMPR6Hg== X-Received: by 2002:a2e:9185:0:b0:2c6:e5f8:451e with SMTP id f5-20020a2e9185000000b002c6e5f8451emr5966751ljg.5.1699613997342; Fri, 10 Nov 2023 02:59:57 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id r15-20020a05600c35cf00b0040531f5c51asm4883156wmq.5.2023.11.10.02.59.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Nov 2023 02:59:56 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 10 Nov 2023 10:59:58 +0000 Message-Id: <20231110110002.21381-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231110110002.21381-1-naush@raspberrypi.com> References: <20231110110002.21381-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 1/5] controls: Add vendor control/property support to generation scripts X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for vendor specific controls and properties to libcamera. The controls/properties are defined by a "vendor" tag in the YAML control description, for example: - RpiVendorControlExample: type: string vendor: rpi description: | Test for libcamera vendor specific controls. This will now generate a control id in the libcamera::controls::vendor::rpi namespace, ensuring no id conflict between different vendors, core or draft libcamera controls. Similarly, a ControlIdMap control is generated in the libcamera::controls::rpi namespace. A #define LIBCAMERA_RPI_VENDOR_CONTROLS is also generated to allow applications to conditionally compile code if the specific vendor controls are present. For the python bindings, the control is available with libcamera.controls.rpi.RpiVendorControlExample. The above controls example applies similarly to properties. A new --mode flag is added to gen-controls.py to specify the mode of operation, either 'controls' or 'properties' to allow the code generator to correctly set the #define string. Signed-off-by: Naushir Patuck --- include/libcamera/control_ids.h.in | 2 + include/libcamera/meson.build | 13 +- include/libcamera/property_ids.h.in | 2 + src/libcamera/control_ids.cpp.in | 6 + src/libcamera/meson.build | 5 +- src/libcamera/property_ids.cpp.in | 6 + src/py/libcamera/gen-py-controls.py | 16 +- src/py/libcamera/py_controls_generated.cpp.in | 3 + .../libcamera/py_properties_generated.cpp.in | 3 + utils/gen-controls.py | 144 ++++++++++++++---- 10 files changed, 162 insertions(+), 38 deletions(-) diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index 0718a8886f6c..c97b09a82450 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -32,6 +32,8 @@ ${draft_controls} } /* namespace draft */ +${vendor_controls} + } /* namespace controls */ } /* namespace libcamera */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index a24c50d66a82..f736cca07228 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -33,19 +33,20 @@ install_headers(libcamera_public_headers, libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir # control_ids.h and property_ids.h -control_source_files = [ - 'control_ids', - 'property_ids', -] +control_source_files = { + 'control_ids': 'controls', + 'property_ids': 'properties', +} control_headers = [] -foreach header : control_source_files +foreach header, mode : control_source_files input_files = files('../../src/libcamera/' + header +'.yaml', header + '.h.in') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@'], + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', + '--mode', mode], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in index ff0194083af0..47c5d6bf2e28 100644 --- a/include/libcamera/property_ids.h.in +++ b/include/libcamera/property_ids.h.in @@ -31,6 +31,8 @@ ${draft_controls} extern const ControlIdMap properties; +${vendor_controls} + } /* namespace properties */ } /* namespace libcamera */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index 5fb1c2c30558..d26eb930b30c 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -33,6 +33,8 @@ ${draft_controls_doc} } /* namespace draft */ +${vendor_controls_doc} + #ifndef __DOXYGEN__ /* * Keep the controls definitions hidden from doxygen as it incorrectly parses @@ -45,6 +47,8 @@ namespace draft { ${draft_controls_def} } /* namespace draft */ + +${vendor_controls_def} #endif /** @@ -57,6 +61,8 @@ extern const ControlIdMap controls { ${controls_map} }; +${vendor_controls_map} + } /* namespace controls */ } /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index d0e26f6b4141..e49bf850b355 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -127,12 +127,13 @@ endif control_sources = [] -foreach source : control_source_files +foreach source, mode : control_source_files input_files = files(source +'.yaml', source + '.cpp.in') control_sources += custom_target(source + '_cpp', input : input_files, output : source + '.cpp', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', + '--mode', mode]) endforeach libcamera_sources += control_sources diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in index f917e3349766..ddbe714c3f00 100644 --- a/src/libcamera/property_ids.cpp.in +++ b/src/libcamera/property_ids.cpp.in @@ -32,6 +32,8 @@ ${draft_controls_doc} } /* namespace draft */ +${vendor_controls_doc} + #ifndef __DOXYGEN__ /* * Keep the properties definitions hidden from doxygen as it incorrectly parses @@ -44,6 +46,8 @@ namespace draft { ${draft_controls_def} } /* namespace draft */ + +${vendor_controls_def} #endif /** @@ -53,6 +57,8 @@ extern const ControlIdMap properties { ${controls_map} }; +${vendor_controls_map} + } /* namespace properties */ } /* namespace libcamera */ diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index 9948c41e42b1..e89de674966a 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -24,12 +24,24 @@ def find_common_prefix(strings): def generate_py(controls, mode): out = '' + vendors_class_def = [] + vendor_defs = [] + vendors = [] for ctrl in controls: name, ctrl = ctrl.popitem() + vendor = ctrl.get('vendor') + if vendor and vendor not in vendors: + vendors_class_def.append('class Py{}Controls\n{{\n}};\n'.format(vendor)) + vendor_defs.append('\tauto {} = py::class_(controls, \"{}\");'.format(vendor, vendor, vendor)) + vendors.append(vendor) + if ctrl.get('draft'): ns = 'libcamera::{}::draft::'.format(mode) container = 'draft' + elif vendor: + ns = 'libcamera::{}::{}::'.format(mode, vendor) + container = vendor else: ns = 'libcamera::{}::'.format(mode) container = 'controls' @@ -62,7 +74,9 @@ def generate_py(controls, mode): out += '\t;\n\n' - return {'controls': out} + return {'controls': out, + 'vendors_class_def': '\n'.join(vendors_class_def), + 'vendors_defs': '\n'.join(vendor_defs)} def fill_template(template, data): diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in index 18fa57d948ea..ec4b55ef2011 100644 --- a/src/py/libcamera/py_controls_generated.cpp.in +++ b/src/py/libcamera/py_controls_generated.cpp.in @@ -21,10 +21,13 @@ class PyDraftControls { }; +${vendors_class_def} + void init_py_controls_generated(py::module& m) { auto controls = py::class_(m, "controls"); auto draft = py::class_(controls, "draft"); +${vendors_defs} ${controls} } diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in index e49b6e91bb83..87bc5e5d937e 100644 --- a/src/py/libcamera/py_properties_generated.cpp.in +++ b/src/py/libcamera/py_properties_generated.cpp.in @@ -21,10 +21,13 @@ class PyDraftProperties { }; +${vendors_class_def} + void init_py_properties_generated(py::module& m) { auto controls = py::class_(m, "properties"); auto draft = py::class_(controls, "draft"); +${vendors_defs} ${controls} } diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 1075ae302ce1..dd55753e792c 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -89,6 +89,11 @@ class Control(object): """Is the control a draft control""" return self.__data.get('draft') is not None + @property + def vendor(self): + """The vendor string, or None""" + return self.__data.get('vendor') if 'vendor' in self.__data else None + @property def name(self): """The control name (CamelCase)""" @@ -145,15 +150,22 @@ ${description} enum_values_start = string.Template('''extern const std::array ${name}Values = {''') enum_values_values = string.Template('''\tstatic_cast(${name}),''') - ctrls_doc = [] - ctrls_def = [] - draft_ctrls_doc = [] - draft_ctrls_def = [] - ctrls_map = [] + ctrls_doc = {} + ctrls_def = {} + ctrls_map = {} for ctrl in controls: id_name = snake_case(ctrl.name).upper() + vendor = ctrl.vendor + if vendor is None: + vendor = 'draft' if ctrl.is_draft else 'libcamera' + + if vendor not in ctrls_doc: + ctrls_doc[vendor] = [] + ctrls_def[vendor] = [] + ctrls_map[vendor] = [] + info = { 'name': ctrl.name, 'type': ctrl.type, @@ -161,11 +173,9 @@ ${description} 'id_name': id_name, } - target_doc = ctrls_doc - target_def = ctrls_def - if ctrl.is_draft: - target_doc = draft_ctrls_doc - target_def = draft_ctrls_def + target_doc = ctrls_doc[vendor] + target_def = ctrls_def[vendor] + target_ctrls_map = ctrls_map[vendor] if ctrl.is_enum: enum_doc = [] @@ -201,41 +211,90 @@ ${description} target_doc.append(doc_template.substitute(info)) target_def.append(def_template.substitute(info)) - ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + + vendor_ctrl_doc_sub = [] + vendor_ctrl_template = string.Template(''' +namespace ${vendor} { + +${vendor_controls_str} + +} /* namespace ${vendor} */''') + + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_doc_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n\n'.join(ctrls_doc[vendor])})) + + vendor_ctrl_def_sub = [] + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_def_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n'.join(ctrls_def[vendor])})) + + vendor_ctrl_map_sub = [] + vendor_ctrl_template = string.Template('''namespace ${vendor} { +/** + * \\brief List of all supported ${vendor} vendor controls + * + * Unless otherwise stated, all controls are bi-directional, i.e. they can be + * set through Request::controls() and returned out through Request::metadata(). + */ +extern const ControlIdMap controls { +${vendor_controls_map} +}; + +} /* namespace ${vendor} */ +''') + + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_map_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, + 'vendor_controls_map': '\n'.join(ctrls_map[vendor])})) return { - 'controls_doc': '\n\n'.join(ctrls_doc), - 'controls_def': '\n'.join(ctrls_def), - 'draft_controls_doc': '\n\n'.join(draft_ctrls_doc), - 'draft_controls_def': '\n\n'.join(draft_ctrls_def), - 'controls_map': '\n'.join(ctrls_map), + 'controls_doc': '\n\n'.join(ctrls_doc['libcamera']), + 'controls_def': '\n'.join(ctrls_def['libcamera']), + 'draft_controls_doc': '\n\n'.join(ctrls_doc['draft']), + 'draft_controls_def': '\n\n'.join(ctrls_def['draft']), + 'controls_map': '\n'.join(ctrls_map['libcamera'] + ctrls_map['draft']), + 'vendor_controls_doc': '\n'.join(vendor_ctrl_doc_sub), + 'vendor_controls_def': '\n'.join(vendor_ctrl_def_sub), + 'vendor_controls_map': '\n'.join(vendor_ctrl_map_sub), } -def generate_h(controls): +def generate_h(controls, mode): enum_template_start = string.Template('''enum ${name}Enum {''') enum_value_template = string.Template('''\t${name} = ${value},''') enum_values_template = string.Template('''extern const std::array ${name}Values;''') template = string.Template('''extern const Control<${type}> ${name};''') - ctrls = [] - draft_ctrls = [] - ids = [] - id_value = 1 + ctrls = {} + ids = {} + id_value = {} for ctrl in controls: id_name = snake_case(ctrl.name).upper() - ids.append('\t' + id_name + ' = ' + str(id_value) + ',') + vendor = ctrl.vendor + if vendor is None: + vendor = 'draft' if ctrl.is_draft else 'libcamera' + + if vendor not in ctrls: + ids[vendor] = [] + id_value[vendor] = 1 + ctrls[vendor] = [] + + # Core and draft controls use the same ID value + target_ids = ids['libcamera'] if vendor in ['libcamera', 'draft'] else ids[vendor] + target_ids.append('\t' + id_name + ' = ' + str(id_value[vendor]) + ',') info = { 'name': ctrl.name, 'type': ctrl.type, } - target_ctrls = ctrls + target_ctrls = ctrls['libcamera'] if ctrl.is_draft: - target_ctrls = draft_ctrls + target_ctrls = ctrls['draft'] + elif vendor != 'libcamera': + target_ctrls = ctrls[vendor] if ctrl.is_enum: target_ctrls.append(enum_template_start.substitute(info)) @@ -257,12 +316,37 @@ def generate_h(controls): target_ctrls.append(enum_values_template.substitute(values_info)) target_ctrls.append(template.substitute(info)) - id_value += 1 + id_value[vendor] += 1 + + vendor_template = string.Template(''' +namespace ${vendor} { + +#define LIBCAMERA_${vendor_def}_VENDOR_${mode} + +enum { +${vendor_enums} +}; + +extern const ControlIdMap controls; + +${vendor_controls} + +} /* namespace ${vendor} */ +''') + + vendor_sub = [] + for vendor in [v for v in ctrls.keys() if v not in ['libcamera', 'draft']]: + vendor_sub.append(vendor_template.substitute({'mode': mode.upper(), + 'vendor': vendor, + 'vendor_def': vendor.upper(), + 'vendor_enums': '\n'.join(ids[vendor]), + 'vendor_controls': '\n'.join(ctrls[vendor])})) return { - 'ids': '\n'.join(ids), - 'controls': '\n'.join(ctrls), - 'draft_controls': '\n'.join(draft_ctrls) + 'ids': '\n'.join(ids['libcamera']), + 'controls': '\n'.join(ctrls['libcamera']), + 'draft_controls': '\n'.join(ctrls['draft']), + 'vendor_controls': '\n'.join(vendor_sub) } @@ -284,6 +368,8 @@ def main(argv): help='Input file name.') parser.add_argument('template', type=str, help='Template file name.') + parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], + help='Mode of operation') args = parser.parse_args(argv[1:]) data = open(args.input, 'rb').read() @@ -293,7 +379,7 @@ def main(argv): if args.template.endswith('.cpp.in'): data = generate_cpp(controls) elif args.template.endswith('.h.in'): - data = generate_h(controls) + data = generate_h(controls, args.mode) else: raise RuntimeError('Unknown template type') From patchwork Fri Nov 10 10:59:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19195 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AAD85BDE6B for ; Fri, 10 Nov 2023 11:00:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A27A629AF; Fri, 10 Nov 2023 12:00:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1699614002; bh=FNFGzC5HF+ifNcYw5R4MlHlpFomJsHZkSQWiEXKPNHs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=dbALBVYY7o6X5wP8U78nBvgXJ5C6vfKbgP3yS2TfPm3pMWnmBGXWeebqJNYZD4EQc n+XDrfccizGcOft4QqO/1LwLOc/JrC1NcQH8ZdQGKQmZV4ZTo4bgQL7SaJbz92wrUC 0CTu6jYH3ynIPYKs37W9xXtG74c6z3IB+vc36o/ZuVg1YZXIZCMEnlcKbBMFF7nkbF lHJc6vZEp1cBF1MH2LCPHQ9cJQKpPrWHrpX+eBHEBym79CVuyfWT6lWyanXthLHjhj Tbhgqmt+YXEspNmLFMjdUgYXiuNT2H8wnF1g2YdE7UNV8mUfrB8caGVoslXx4ZyTww 8WKCNFw9KvpMg== Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 26FFB629C0 for ; Fri, 10 Nov 2023 11:59:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="k3ZCJqV8"; dkim-atps=neutral Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-408425c7c10so14343805e9.0 for ; Fri, 10 Nov 2023 02:59:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1699613998; x=1700218798; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7zG4YADsqfXxky8HV1UlKl3gSBl6yLhKvKdAQ0eg5Pw=; b=k3ZCJqV8fxEBn2f2uoU5LKnnra2Vcy8Mbg0Kq9LjrnybHdeDiQPwvc1vB+vpR0r5le uVHhpAERPrReFKwWuOEI51vseRjo22s1MhY7iyurjarswRU8lnbKmg+KT2ZR0Nn5bX4m xY4mIKN9Rq0d1N/IXhy4UnZ/zpKHDyHrsiXC4nLyUZ1luue+/4aeE64yt4KlT2B5OT7d /TPgFe36t23M5SUaFMoyuEAGfCtHWHK1+rBUx9/rxm3wGubxOSLS/Tdz3heUzbBtDMLN sckM78wWhJm+Gi7cr0LXgOMMrDApgLYXWmJeK5zHfDi2VPBkbuqTaAlt1WGGAUdI6ilp /fbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699613998; x=1700218798; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7zG4YADsqfXxky8HV1UlKl3gSBl6yLhKvKdAQ0eg5Pw=; b=Z3V57MDC8F/t2p2MFTHzafp5Cl+tv7a/l6cfc/FJ16a7fg9g/c+5E+SBgk27xWv2Qm 8SsXl9y7PVYm+T8znJUkuUZ/sC1baNOs7EJTXM3vt9OpSpLfHnDq9qjGbZTwYFhIIG+s MEL2fT3gKdL8MErKCvOtvMbxxWT3hYiYdsTOyI12bPyl0rOvTa6Fuv3z7VEdVMktwogV 5lCHrxqLMo1cZKzGn8XfAiKJxrHYElvRtDyrIQinPYjk+Ysrjnx4F69ZJIQuokOPRnnL 1vFJ9cXLaXPOWrCsEHBkAMp9R/+4x7kBos8ztXr/bWtPXIhzKWdHB59Ei9Vv4VxN7an/ wmBg== X-Gm-Message-State: AOJu0YwLtNLgjRmcT7xOko4qIoXVFY656k0Za8qv3Tgb2xgdnk0wknZt lTGFuiV6ZFyYase5qhTczcDcuWjkccyKWJe8s1sdTg== X-Google-Smtp-Source: AGHT+IF6x4PiKwj7/Lc97QqZzcw4eZ2WuYIzwRUFBNtysJsIMDgMNOIJfK0zIAOc8q5ZuSL/zRiG3A== X-Received: by 2002:a05:600c:4ed0:b0:40a:43d3:2348 with SMTP id g16-20020a05600c4ed000b0040a43d32348mr1630236wmq.35.1699613998115; Fri, 10 Nov 2023 02:59:58 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id r15-20020a05600c35cf00b0040531f5c51asm4883156wmq.5.2023.11.10.02.59.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Nov 2023 02:59:57 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 10 Nov 2023 10:59:59 +0000 Message-Id: <20231110110002.21381-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231110110002.21381-1-naush@raspberrypi.com> References: <20231110110002.21381-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 2/5] controls: build: Allow separate vendor control YAML files X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for using separate YAML files for vendor specific controls. This simplifies management of vendor control definitions and avoids possible merge conflicts when changing the control_ids.yaml file for core and draft controls. The mapping of vendor/pipeline handler to control file is done through the vendor_controls_mapping variable in include/libcamera/meson.build. The command line argument handling for the gen-py-controls.py and gen-controls.py have now changed to allow multiple input files to be provided. This means that all positional arguments have been replaced by non-positional equivalents. Add a new control_ids_rpi.yaml file to hold the Raspberry Pi specific vendor controls. This contains a single control PispConfigDumpFile that will be used in the Pi 5 pipeline handler as a trigger to dump the Backend configuration as a JSON file. Signed-off-by: Naushir Patuck --- include/libcamera/meson.build | 48 ++++++++++++++++++++++++++--- meson.build | 2 ++ src/libcamera/control_ids_rpi.yaml | 17 ++++++++++ src/libcamera/meson.build | 19 ++++++++++-- src/py/libcamera/gen-py-controls.py | 12 +++++--- src/py/libcamera/meson.build | 26 ++++++++++------ utils/gen-controls.py | 15 +++++---- 7 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 src/libcamera/control_ids_rpi.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index f736cca07228..f8af51174f08 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -32,21 +32,61 @@ install_headers(libcamera_public_headers, libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir -# control_ids.h and property_ids.h +# control_ids.h and property_ids.h and associated modes control_source_files = { 'control_ids': 'controls', 'property_ids': 'properties', } +vendor_mappings = { + # Mapping of vendor (pipeline handler) specific controls files + 'controls': + { + 'rpi/pisp': 'control_ids_rpi.yaml', + 'rpi/vc4': 'control_ids_rpi.yaml' + }, + # Mapping of vendor (pipeline handler) specific properties files + 'properties': + { + + } +} + control_headers = [] +vendor_ctrl_files = [] +vendor_prop_files = [] foreach header, mode : control_source_files - input_files = files('../../src/libcamera/' + header +'.yaml', header + '.h.in') + # Start by populating the vendor specific mappings into vendor_ctrl_files + # vendor_prop_files. These will be cached for later use. + vendor_files = [] + foreach pipeline, file : vendor_mappings[mode] + if pipeline not in pipelines + continue + endif + if file not in vendor_files + vendor_files += file + endif + endforeach + + if mode == 'controls' + vendor_ctrl_files = vendor_files + else + vendor_prop_files = vendor_files + endif + + input_files = files('../../src/libcamera/' + header +'.yaml') + + foreach file : vendor_files + input_files += files('../../src/libcamera/' + file) + endforeach + + template_file = files(header + '.h.in') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', - '--mode', mode], + command : [gen_controls, '-o', '@OUTPUT@', '-i', '@INPUT@', + '--mode', mode, '-t', template_file], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/meson.build b/meson.build index e9a1c7e360ce..1423abf16c77 100644 --- a/meson.build +++ b/meson.build @@ -267,6 +267,8 @@ py_mod.find_installation('python3', modules : py_modules) summary({ 'Enabled pipelines': pipelines, 'Enabled IPA modules': enabled_ipa_names, + 'Vendor controls': vendor_ctrl_files, + 'Vendor properties': vendor_prop_files, 'Hotplug support': libudev.found(), 'Tracing support': tracing_enabled, 'Android support': android_enabled, diff --git a/src/libcamera/control_ids_rpi.yaml b/src/libcamera/control_ids_rpi.yaml new file mode 100644 index 000000000000..239904a008a8 --- /dev/null +++ b/src/libcamera/control_ids_rpi.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2023, Raspberry Pi Ltd +# +%YAML 1.1 +--- +controls: + + - PispConfigDumpFile: + type: string + vendor: rpi + description: | + Triggers the Raspberry Pi PiSP pipeline handler to generate a JSON + formatted dump of the Backend configuration to the filename given by the + value of the control. + +... diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index e49bf850b355..8891052a3316 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -128,12 +128,25 @@ endif control_sources = [] foreach source, mode : control_source_files - input_files = files(source +'.yaml', source + '.cpp.in') + input_files = files(source +'.yaml') + + # Add the vendor specific files to the input. + if mode == 'controls' + vendor_files = vendor_ctrl_files + else + vendor_files = vendor_prop_files + endif + + foreach file : vendor_files + input_files += files(file) + endforeach + + template_file = files(source + '.cpp.in') control_sources += custom_target(source + '_cpp', input : input_files, output : source + '.cpp', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', - '--mode', mode]) + command : [gen_controls, '-o', '@OUTPUT@', '-i', '@INPUT@', + '--mode', mode, '-t', template_file]) endforeach libcamera_sources += control_sources diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index e89de674966a..a32ef09c2f48 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -91,9 +91,9 @@ def main(argv): parser = argparse.ArgumentParser() parser.add_argument('-o', dest='output', metavar='file', type=str, help='Output file name. Defaults to standard output if not specified.') - parser.add_argument('input', type=str, - help='Input file name.') - parser.add_argument('template', type=str, + parser.add_argument('-i', dest='inputs', type=str, nargs='+', required=True, + help='Input file name(s).') + parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') parser.add_argument('--mode', type=str, required=True, help='Mode is either "controls" or "properties"') @@ -103,8 +103,10 @@ def main(argv): print(f'Invalid mode option "{args.mode}"', file=sys.stderr) return -1 - data = open(args.input, 'rb').read() - controls = yaml.safe_load(data)['controls'] + controls = [] + for input in args.inputs: + data = open(input, 'rb').read() + controls += yaml.safe_load(data)['controls'] data = generate_py(controls, args.mode) diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index f58c7198ee9e..e4bc208b4ac1 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -28,29 +28,35 @@ pycamera_sources = files([ # Generate controls -gen_py_controls_input_files = files([ - '../../libcamera/control_ids.yaml', - 'py_controls_generated.cpp.in', -]) +gen_py_controls_input_files = files('../../libcamera/control_ids.yaml') + +foreach file : vendor_ctrl_files + gen_py_controls_input_files += files('../../libcamera/' + file) +endforeach gen_py_controls = files('gen-py-controls.py') +gen_py_controls_template = files('py_controls_generated.cpp.in') pycamera_sources += custom_target('py_gen_controls', input : gen_py_controls_input_files, output : ['py_controls_generated.cpp'], - command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@', '-i', '@INPUT@', + '-t', gen_py_controls_template]) # Generate properties -gen_py_property_enums_input_files = files([ - '../../libcamera/property_ids.yaml', - 'py_properties_generated.cpp.in', -]) +gen_py_property_enums_input_files = files('../../libcamera/property_ids.yaml') +gen_py_property_template = files('py_properties_generated.cpp.in') + +foreach file : vendor_prop_files + gen_py_property_enums_input_files += files('../../libcamera/' + file) +endforeach pycamera_sources += custom_target('py_gen_properties', input : gen_py_property_enums_input_files, output : ['py_properties_generated.cpp'], - command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@', '-i', '@INPUT@', + '-t', gen_py_property_template]) # Generate formats diff --git a/utils/gen-controls.py b/utils/gen-controls.py index dd55753e792c..3c490a562676 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -362,18 +362,21 @@ def main(argv): # Parse command line arguments parser = argparse.ArgumentParser() - parser.add_argument('-o', dest='output', metavar='file', type=str, + parser.add_argument('-o', dest='output', metavar='file', type=str, required=True, help='Output file name. Defaults to standard output if not specified.') - parser.add_argument('input', type=str, - help='Input file name.') - parser.add_argument('template', type=str, + parser.add_argument('-i', dest='inputs', type=str, nargs='+', required=True, + help='Input file name(s).') + parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], help='Mode of operation') args = parser.parse_args(argv[1:]) - data = open(args.input, 'rb').read() - controls = yaml.safe_load(data)['controls'] + controls = [] + for input in args.inputs: + data = open(input, 'rb').read() + controls = controls + yaml.safe_load(data)['controls'] + controls = [Control(*ctrl.popitem()) for ctrl in controls] if args.template.endswith('.cpp.in'): From patchwork Fri Nov 10 11:00:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19196 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id DE321C32B6 for ; Fri, 10 Nov 2023 11:00:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2D014629C5; Fri, 10 Nov 2023 12:00:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1699614003; bh=7XSFXx2DUl5h2GAm5SWiy58sKU3/VWKQHhEIIZzYr04=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Axx0yglJ2xwBXE8dk4QNbQgOub9/cek4lApBCiqPTj+LE37MABDFyL3rx2iFgd+Td LbfUwewEfc3NjY1pl2ByDdYonVDF5IzDEdf4pX1hVlPziz7vso7NTQIZ/N31EVxHvV 29Vmpx+gYnHTIGLb2x72jtsohFGCBQCxn/Ss+jU5JI8omq7njvCgnZVUqLeMhjD0+z wjjQusroayI2KnyifidgIxCoA3HiGXFXtrhGRBFx1UyLZV+JxYxwu0m6CyooHPwFdF LyqX5dlcvZlfOcbLC5od2ASrTeT6zUXtVhehzhKOqVZ55KjwhN9ZLz7Gwt/cDyf36p u+kVbA9p9al9g== Received: from mail-lj1-x235.google.com (mail-lj1-x235.google.com [IPv6:2a00:1450:4864:20::235]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9A37C629C4 for ; Fri, 10 Nov 2023 12:00:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="TNtpJ1Yz"; dkim-atps=neutral Received: by mail-lj1-x235.google.com with SMTP id 38308e7fff4ca-2c54c8934abso26177591fa.0 for ; Fri, 10 Nov 2023 03:00:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1699613999; x=1700218799; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KGVaaYbVeRRnBsWLiUTohKuu49hyzSLpVxoqEmiQ8Hs=; b=TNtpJ1YzKecoaUbFqqDG4mgF4Fwkb9x1GiJDc7Bqo83elN2xqMFTH9q/sI8qIPbLU5 8/jL111xuEtpEOMLNC3ZbaeIuGyNOgy4syRw0w43kKwI8Bd/St7Djw3AHYMUPPwNksxx G1PVcSKCkMpGqjo+em6O9KG0BIvUcbJvKF2LJyrAAx/gaMNW4I2a/W7oqKB1QwATdsFr AJGVZgU06gP1b/5ccoW8h9Ip2aY7rczrhKp5q5PB7iT+rOU7yi/kcTyNXo2kZgbnhiDI 208LNfM1L0Ggv3cVOTTtaJHjNbBRV8XU0xpD6Nm8rbAPX6/Wv0A+eae4gzyHfvyi7gFV k86g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699613999; x=1700218799; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KGVaaYbVeRRnBsWLiUTohKuu49hyzSLpVxoqEmiQ8Hs=; b=JTrJvqbbjPl7ARJ6w4SC0+Hc2B+/JiDv0ujl09foI2nVM8ESsJUI5Q4S1emSHyzVBe neSwnxjwI4LqTW3OlM3dOz0G8esWEExQl0zgCvQveA7uM44Y6d84YQF6R+AnL1DSGm50 Cnq+bbjdHDvvK4L+7efrEjhe4Qb4ps7qvs1c6jYAy69IREFm0f1gnwwtlgMB5WpqlVU7 PsjZTaLQlf7AeBuUdWkiyssYe8dlSgq/OqCmofFIi+6ui8AWSP/Hw7O8f25f1MLGu6n2 6tSpLjc2THXl4690DGoFSLxfRsH+mytDOBtpD4ANVyajLgzq1fmqWUOI1AeMYdjRO4Ap mvJw== X-Gm-Message-State: AOJu0YxBxzgT7fhX90bFLXkxbxa/DLg+yOvtjFg4j/hlTJGxfZDaYGSz R61CfToAcblUchzQ01Hp8ktIg5yX7InFKzc4v/4RyA== X-Google-Smtp-Source: AGHT+IGZb5FYW8VKLDntbYhyj0onM76iscKB7nYmnIkVYx/zbp6UZqdnU+bIvhRdmdHZXXpdX9MZTA== X-Received: by 2002:a2e:9410:0:b0:2c7:8fee:c295 with SMTP id i16-20020a2e9410000000b002c78feec295mr1994775ljh.42.1699613999342; Fri, 10 Nov 2023 02:59:59 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id r15-20020a05600c35cf00b0040531f5c51asm4883156wmq.5.2023.11.10.02.59.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Nov 2023 02:59:58 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 10 Nov 2023 11:00:00 +0000 Message-Id: <20231110110002.21381-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231110110002.21381-1-naush@raspberrypi.com> References: <20231110110002.21381-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 3/5] libcamera: control: Add vendor control id range reservation X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a new control_ranges.yaml file that is used to reserve control id ranges/offsets for libcamera and vendor specific controls. This file is used by the gen-controls.py script to generate control id values for each control. Draft controls now have a seprate range from core libcamera controls, breaking the existing numbering behaviour. Signed-off-by: Naushir Patuck --- include/libcamera/meson.build | 3 ++- src/libcamera/control_ranges.yaml | 17 +++++++++++++++++ utils/gen-controls.py | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 src/libcamera/control_ranges.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index f8af51174f08..98339b93777c 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -82,11 +82,12 @@ foreach header, mode : control_source_files endforeach template_file = files(header + '.h.in') + ranges_file = files('../../src/libcamera/control_ranges.yaml') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', command : [gen_controls, '-o', '@OUTPUT@', '-i', '@INPUT@', - '--mode', mode, '-t', template_file], + '--mode', mode, '-t', template_file, '-r', ranges_file], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/src/libcamera/control_ranges.yaml b/src/libcamera/control_ranges.yaml new file mode 100644 index 000000000000..e908a8a3a110 --- /dev/null +++ b/src/libcamera/control_ranges.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2023, Raspberry Pi Ltd +# +%YAML 1.1 +--- +# Specifies the control id ranges/offsets for core libcamera and vendor specific +# controls. +ranges: + # Core libcamera controls + libcamera: 0 + # Draft designated libcamera controls + draft: 1000 + # Raspberry Pi vendor controls + rpi: 2000 + +... diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 3c490a562676..a10b9fdc19ee 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -259,7 +259,7 @@ ${vendor_controls_map} } -def generate_h(controls, mode): +def generate_h(controls, mode, ranges): enum_template_start = string.Template('''enum ${name}Enum {''') enum_value_template = string.Template('''\t${name} = ${value},''') enum_values_template = string.Template('''extern const std::array ${name}Values;''') @@ -277,8 +277,10 @@ def generate_h(controls, mode): vendor = 'draft' if ctrl.is_draft else 'libcamera' if vendor not in ctrls: + if vendor not in ranges.keys(): + raise RuntimeError('Vendor range is not defined') + id_value[vendor] = ranges[vendor] + 1 ids[vendor] = [] - id_value[vendor] = 1 ctrls[vendor] = [] # Core and draft controls use the same ID value @@ -370,8 +372,15 @@ def main(argv): help='Template file name.') parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], help='Mode of operation') + parser.add_argument('-r', dest='ranges', type=str, + help='Control id range reservation file.') args = parser.parse_args(argv[1:]) + ranges = [] + if args.ranges: + data = open(args.ranges, 'rb').read() + ranges = yaml.safe_load(data)['ranges'] + controls = [] for input in args.inputs: data = open(input, 'rb').read() @@ -382,7 +391,7 @@ def main(argv): if args.template.endswith('.cpp.in'): data = generate_cpp(controls) elif args.template.endswith('.h.in'): - data = generate_h(controls, args.mode) + data = generate_h(controls, args.mode, ranges) else: raise RuntimeError('Unknown template type') From patchwork Fri Nov 10 11:00:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19197 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id EEDCFC32B7 for ; Fri, 10 Nov 2023 11:00:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 49134629C8; Fri, 10 Nov 2023 12:00:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1699614004; bh=BujmkP8fmfhR0LMQCcXv3ZSr/BmtbSBskgS4/ORnL/M=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=CcxS2HXuJdlWimy/jcLHUNjwTnDVdbU8A3aR7n441//wg6/2poeARRZBJT5QhL/rd xefUv0vH78+LIiQo/IoQkhpa+RA2TjRSdqV1RlcqI4sPRZidUYTGK93VIARQAQHofP XZRKd70ttmYjtMa10O9joJBKyvKA7Efa/2YkOKoDzmyhZ+ghnXyreP+OmICPwBnb7m ZYvjdVv6wEgGLnA++NWSACAagBiE510OGlwQW1mcG8053xI/yBp3H9R+vtvKSncWzk oAB8ibu54WJQ8Id+LuGq3YLIcJdUh5QW1WZnx/dtzErATRyQjvFRNnkTA4JzH+ej7z 78OZHBs/CRXJg== Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E4A64629BD for ; Fri, 10 Nov 2023 12:00:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="F1jkDkPD"; dkim-atps=neutral Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-32da4ffd7e5so1160999f8f.0 for ; Fri, 10 Nov 2023 03:00:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1699614000; x=1700218800; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mxI+weENNPsYR1EldaSKh0p2BN4afZzpADMkPpTpHDw=; b=F1jkDkPDxHnxbx5nG+x2ldg7PrG8Fk1Q/XbZcplQumJ/FgApohDA41q7vvSoXj2Fp6 /TTUFVz1qxR3NI7dlNfxGBV+QkP1UBxR81kCcH1oHZqBQyO+daITBmNb64Xoa+DDDaQ0 INUjVfRxFb4T5XjSQ8LBX4awbcrWSX+g0wmnOrNDNHcbFq9fmalfwNuu7epIghhhzYVk /PtDmNeZUkDGqt7mq3mrdIufwerIM3zaratXjMU2HqZyWH9SEwYWGbQWm0R3ApF2i6in AXQsiGFKZWYmvZH10mphY68aOCLOSnZd1hc1RLPYmEl/tIwtevCzAsAPHUFrUoJax0tH vKfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699614000; x=1700218800; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mxI+weENNPsYR1EldaSKh0p2BN4afZzpADMkPpTpHDw=; b=rE1nywUZ7lMCI7Yq8jNS3xUe0n/BHymk++SLcS9BSRZXHIvQktSBzcvMcGYrdi3zcn nH/E942D+daRNmEM4/SrFlezKzKtQ4LE7W98vyt3UkNTD4EkIoD0EYX4yP+yLn6Hkx0x AlbHD2jWAM7986M1miacQm+xVqJnXYWMsxGOVsn2G0250awcYXPUmO42RDcrMfekJ7lp 0SrT+n+ZwVLMfogxI4qo3lUanYS8FEMlTpSRcLXS8T3nFHCu/T52JZNCKziwBnPQnuCF VYJCt2dK7FtLO0chX/tuqLjQWPMxQf0Hh6JaYqMHBEp2Jsa4Kifm6xPcJkpn5ADCmv3F E2VQ== X-Gm-Message-State: AOJu0Yzlj5siBMo570DBqevqnAPMqboY6/xJ5wMUXDHOc9LGWaS36mSV G88c+YoCrQhS1c38Mz4hfNT+fbNmpe8+XNNagaH9Ew== X-Google-Smtp-Source: AGHT+IE/+qZitPN+84xVYPoNrAoVtSaCFwjt+sNbOG5dAqAyR5tgkBKCC42nlk9UiTcljnzKkn8fUA== X-Received: by 2002:a05:6000:1565:b0:32f:b47c:f1f6 with SMTP id 5-20020a056000156500b0032fb47cf1f6mr1841239wrz.32.1699614000018; Fri, 10 Nov 2023 03:00:00 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id r15-20020a05600c35cf00b0040531f5c51asm4883156wmq.5.2023.11.10.02.59.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Nov 2023 02:59:59 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 10 Nov 2023 11:00:01 +0000 Message-Id: <20231110110002.21381-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231110110002.21381-1-naush@raspberrypi.com> References: <20231110110002.21381-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 4/5] libcamera: controls: Use vendor tags for draft controls and properties X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Label draft controls and properties through the "draft" vendor tag and deprecate the existing "draft: true" mechanism. This uses the new vendor tags mechanism to place draft controls in the same libcamera::controls::draft namespace and provide a defined control id range for these controls. One breaking change in this commit is that draft control ids also move to the libcamera::controls::draft namespace from the existing libcamera::controls namespace. This is desirable to avoid API breakages when adding new libcamera controls. So, for example, the use of controls::NOISE_REDUCTION_MODE will need to be replaced with controls::draft::NOISE_REDUCTION_MODE. Signed-off-by: Naushir Patuck --- include/libcamera/control_ids.h.in | 6 --- include/libcamera/property_ids.h.in | 6 --- src/ipa/rpi/common/ipa_base.cpp | 2 +- src/ipa/rpi/vc4/vc4.cpp | 2 +- src/libcamera/control_ids.cpp.in | 16 +------- src/libcamera/control_ids.yaml | 20 +++++----- src/libcamera/property_ids.cpp.in | 16 +------- src/libcamera/property_ids.yaml | 2 +- src/py/libcamera/gen-py-controls.py | 5 +-- src/py/libcamera/py_controls_generated.cpp.in | 5 --- .../libcamera/py_properties_generated.cpp.in | 1 - utils/gen-controls.py | 39 +++++-------------- 12 files changed, 27 insertions(+), 93 deletions(-) diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index c97b09a82450..d53b1cf7beb2 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -26,12 +26,6 @@ ${controls} extern const ControlIdMap controls; -namespace draft { - -${draft_controls} - -} /* namespace draft */ - ${vendor_controls} } /* namespace controls */ diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in index 47c5d6bf2e28..43372c718fc9 100644 --- a/include/libcamera/property_ids.h.in +++ b/include/libcamera/property_ids.h.in @@ -23,12 +23,6 @@ ${ids} ${controls} -namespace draft { - -${draft_controls} - -} /* namespace draft */ - extern const ControlIdMap properties; ${vendor_controls} diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index a1fec3aa3dd1..6ac9d5de2f88 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -1024,7 +1024,7 @@ void IpaBase::applyControls(const ControlList &controls) break; } - case controls::NOISE_REDUCTION_MODE: + case controls::draft::NOISE_REDUCTION_MODE: /* Handled below in handleControls() */ libcameraMetadata_.set(controls::draft::NoiseReductionMode, ctrl.second.get()); diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp index c4baf04fb1e7..c165a5b8b0b6 100644 --- a/src/ipa/rpi/vc4/vc4.cpp +++ b/src/ipa/rpi/vc4/vc4.cpp @@ -260,7 +260,7 @@ void IpaVc4::handleControls(const ControlList &controls) for (auto const &ctrl : controls) { switch (ctrl.first) { - case controls::NOISE_REDUCTION_MODE: { + case controls::draft::NOISE_REDUCTION_MODE: { RPiController::DenoiseAlgorithm *sdn = dynamic_cast( controller_.getAlgorithm("SDN")); /* Some platforms may have a combined "denoise" algorithm instead. */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index d26eb930b30c..284589567cfb 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -24,15 +24,6 @@ namespace controls { ${controls_doc} -/** - * \brief Namespace for libcamera draft controls - */ -namespace draft { - -${draft_controls_doc} - -} /* namespace draft */ - ${vendor_controls_doc} #ifndef __DOXYGEN__ @@ -42,13 +33,8 @@ ${vendor_controls_doc} */ ${controls_def} -namespace draft { - -${draft_controls_def} - -} /* namespace draft */ - ${vendor_controls_def} + #endif /** diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index 5827d7ecef49..ce65522e1b71 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -869,7 +869,7 @@ controls: - AePrecaptureTrigger: type: int32_t - draft: true + vendor: draft description: | Control for AE metering trigger. Currently identical to ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER. @@ -891,7 +891,7 @@ controls: - NoiseReductionMode: type: int32_t - draft: true + vendor: draft description: | Control to select the noise reduction algorithm mode. Currently identical to ANDROID_NOISE_REDUCTION_MODE. @@ -920,7 +920,7 @@ controls: - ColorCorrectionAberrationMode: type: int32_t - draft: true + vendor: draft description: | Control to select the color correction aberration mode. Currently identical to ANDROID_COLOR_CORRECTION_ABERRATION_MODE. @@ -941,7 +941,7 @@ controls: - AeState: type: int32_t - draft: true + vendor: draft description: | Control to report the current AE algorithm state. Currently identical to ANDROID_CONTROL_AE_STATE. @@ -971,7 +971,7 @@ controls: - AwbState: type: int32_t - draft: true + vendor: draft description: | Control to report the current AWB algorithm state. Currently identical to ANDROID_CONTROL_AWB_STATE. @@ -993,7 +993,7 @@ controls: - SensorRollingShutterSkew: type: int64_t - draft: true + vendor: draft description: | Control to report the time between the start of exposure of the first row and the start of exposure of the last row. Currently identical to @@ -1001,7 +1001,7 @@ controls: - LensShadingMapMode: type: int32_t - draft: true + vendor: draft description: | Control to report if the lens shading map is available. Currently identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE. @@ -1015,7 +1015,7 @@ controls: - PipelineDepth: type: int32_t - draft: true + vendor: draft description: | Specifies the number of pipeline stages the frame went through from when it was exposed to when the final completed result was available to the @@ -1030,7 +1030,7 @@ controls: - MaxLatency: type: int32_t - draft: true + vendor: draft description: | The maximum number of frames that can occur after a request (different than the previous) has been submitted, and before the result's state @@ -1040,7 +1040,7 @@ controls: - TestPatternMode: type: int32_t - draft: true + vendor: draft description: | Control to select the test pattern mode. Currently identical to ANDROID_SENSOR_TEST_PATTERN_MODE. diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in index ddbe714c3f00..b72e12e4cc70 100644 --- a/src/libcamera/property_ids.cpp.in +++ b/src/libcamera/property_ids.cpp.in @@ -23,14 +23,7 @@ namespace properties { ${controls_doc} -/** - * \brief Namespace for libcamera draft properties - */ -namespace draft { - -${draft_controls_doc} - -} /* namespace draft */ +${vendor_controls_doc} ${vendor_controls_doc} @@ -41,13 +34,8 @@ ${vendor_controls_doc} */ ${controls_def} -namespace draft { - -${draft_controls_def} - -} /* namespace draft */ - ${vendor_controls_def} + #endif /** diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index f35563842a5a..622d0a8cf26f 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -705,7 +705,7 @@ controls: - ColorFilterArrangement: type: int32_t - draft: true + vendor: draft description: | The arrangement of color filters on sensor; represents the colors in the top-left 2x2 section of the sensor, in reading order. Currently diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index a32ef09c2f48..9416be6e611d 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -36,10 +36,7 @@ def generate_py(controls, mode): vendor_defs.append('\tauto {} = py::class_(controls, \"{}\");'.format(vendor, vendor, vendor)) vendors.append(vendor) - if ctrl.get('draft'): - ns = 'libcamera::{}::draft::'.format(mode) - container = 'draft' - elif vendor: + if vendor: ns = 'libcamera::{}::{}::'.format(mode, vendor) container = vendor else: diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in index ec4b55ef2011..8d282ce51856 100644 --- a/src/py/libcamera/py_controls_generated.cpp.in +++ b/src/py/libcamera/py_controls_generated.cpp.in @@ -17,16 +17,11 @@ class PyControls { }; -class PyDraftControls -{ -}; - ${vendors_class_def} void init_py_controls_generated(py::module& m) { auto controls = py::class_(m, "controls"); - auto draft = py::class_(controls, "draft"); ${vendors_defs} ${controls} diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in index 87bc5e5d937e..1fa1967a9672 100644 --- a/src/py/libcamera/py_properties_generated.cpp.in +++ b/src/py/libcamera/py_properties_generated.cpp.in @@ -26,7 +26,6 @@ ${vendors_class_def} void init_py_properties_generated(py::module& m) { auto controls = py::class_(m, "properties"); - auto draft = py::class_(controls, "draft"); ${vendors_defs} ${controls} diff --git a/utils/gen-controls.py b/utils/gen-controls.py index a10b9fdc19ee..3ae48ca3e0bc 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -84,11 +84,6 @@ class Control(object): """Is the control an enumeration""" return self.__enum_values is not None - @property - def is_draft(self): - """Is the control a draft control""" - return self.__data.get('draft') is not None - @property def vendor(self): """The vendor string, or None""" @@ -99,12 +94,6 @@ class Control(object): """The control name (CamelCase)""" return self.__name - @property - def q_name(self): - """The control name, qualified with a namespace""" - ns = 'draft::' if self.is_draft else '' - return ns + self.__name - @property def type(self): typ = self.__data.get('type') @@ -159,7 +148,7 @@ ${description} vendor = ctrl.vendor if vendor is None: - vendor = 'draft' if ctrl.is_draft else 'libcamera' + vendor = 'libcamera' if vendor not in ctrls_doc: ctrls_doc[vendor] = [] @@ -211,7 +200,7 @@ ${description} target_doc.append(doc_template.substitute(info)) target_def.append(def_template.substitute(info)) - target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.name + ' },') vendor_ctrl_doc_sub = [] vendor_ctrl_template = string.Template(''' @@ -221,11 +210,11 @@ ${vendor_controls_str} } /* namespace ${vendor} */''') - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_doc_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n\n'.join(ctrls_doc[vendor])})) vendor_ctrl_def_sub = [] - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_def_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n'.join(ctrls_def[vendor])})) vendor_ctrl_map_sub = [] @@ -243,16 +232,14 @@ ${vendor_controls_map} } /* namespace ${vendor} */ ''') - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_map_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_map': '\n'.join(ctrls_map[vendor])})) return { 'controls_doc': '\n\n'.join(ctrls_doc['libcamera']), 'controls_def': '\n'.join(ctrls_def['libcamera']), - 'draft_controls_doc': '\n\n'.join(ctrls_doc['draft']), - 'draft_controls_def': '\n\n'.join(ctrls_def['draft']), - 'controls_map': '\n'.join(ctrls_map['libcamera'] + ctrls_map['draft']), + 'controls_map': '\n'.join(ctrls_map['libcamera']), 'vendor_controls_doc': '\n'.join(vendor_ctrl_doc_sub), 'vendor_controls_def': '\n'.join(vendor_ctrl_def_sub), 'vendor_controls_map': '\n'.join(vendor_ctrl_map_sub), @@ -274,7 +261,7 @@ def generate_h(controls, mode, ranges): vendor = ctrl.vendor if vendor is None: - vendor = 'draft' if ctrl.is_draft else 'libcamera' + vendor = 'libcamera' if vendor not in ctrls: if vendor not in ranges.keys(): @@ -283,8 +270,7 @@ def generate_h(controls, mode, ranges): ids[vendor] = [] ctrls[vendor] = [] - # Core and draft controls use the same ID value - target_ids = ids['libcamera'] if vendor in ['libcamera', 'draft'] else ids[vendor] + target_ids = ids[vendor] target_ids.append('\t' + id_name + ' = ' + str(id_value[vendor]) + ',') info = { @@ -292,11 +278,7 @@ def generate_h(controls, mode, ranges): 'type': ctrl.type, } - target_ctrls = ctrls['libcamera'] - if ctrl.is_draft: - target_ctrls = ctrls['draft'] - elif vendor != 'libcamera': - target_ctrls = ctrls[vendor] + target_ctrls = ctrls[vendor] if ctrl.is_enum: target_ctrls.append(enum_template_start.substitute(info)) @@ -337,7 +319,7 @@ ${vendor_controls} ''') vendor_sub = [] - for vendor in [v for v in ctrls.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls.keys() if v != 'libcamera']: vendor_sub.append(vendor_template.substitute({'mode': mode.upper(), 'vendor': vendor, 'vendor_def': vendor.upper(), @@ -347,7 +329,6 @@ ${vendor_controls} return { 'ids': '\n'.join(ids['libcamera']), 'controls': '\n'.join(ctrls['libcamera']), - 'draft_controls': '\n'.join(ctrls['draft']), 'vendor_controls': '\n'.join(vendor_sub) } From patchwork Fri Nov 10 11:00:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19198 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id CD5AAC32B8 for ; Fri, 10 Nov 2023 11:00:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EEA28629D0; Fri, 10 Nov 2023 12:00:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1699614005; bh=1AU+IJ1M/QDQijTXGAuccno9bu5RU0Owm0U59pqB/ls=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=fWSQtSKraT1nRxPz4c7bHroi1rXH0QL2TbO/y8ARg1g09gv4rtWgug9KCEObU0mVm OeBupYj6CbQ7OviT2kIS/oeM7ELa6eqVuzMaJre/O3L+TizXivLFLmhYp0H6n/nc6t h0wvoltbD87ntUG6nxKxB48ff+uvwkcIgY/y/6DqC8WlgeWn9kp7jM0XqIHIEyh9cJ I8pZVPsjmekZ3qGnhhOOah1j6y7UzI4AZSx9nydEJHLptFC12PyxPnJABznjUCGXpC JfngOyvbJScROy69PfkFhF65zqe6z4F/ph7ZQAo0QEw3H3aZ6PKE0aq+wh92qXHVAi UY3UMZP9o2zbg== Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 53FF7629C9 for ; Fri, 10 Nov 2023 12:00:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="Hm/WvHyJ"; dkim-atps=neutral Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-4084095722aso14074515e9.1 for ; Fri, 10 Nov 2023 03:00:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1699614001; x=1700218801; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=93proqkiUMkkk25+FdjfHybOo3hIivrSKFMW3MZhICg=; b=Hm/WvHyJ/2xwuvdWJ5BdPBf89vbcSYARJp6DAVHotfzGq0QIf6zqj42qccoHMg7Q97 DMW4hy2WVfYrcCOOmqxQOmCm3W6znlYpiMyNLF84Xk+EcFZgDDgD8lXwCFtM/ytvhyhp /rabDiJgdohtT03Dmo6JAWdadQoKOlRuQa0ZtpnUiJST6nzLS0rtbUrhjaJtprmGj2Oz AIAIrQ4VdAaLLzX/LPH0sLFWnTF3m+eUAQ3Dkr+NCjm0p2iCYExf4BalmPFuac9Brdhq 6ePjlwZrHP9YsZKwvSFbxt0aoyEK0Ccf3i0UBvucCJZ+Pt6apjkpA7V6p0FmHmQJd0TY r0Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699614001; x=1700218801; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=93proqkiUMkkk25+FdjfHybOo3hIivrSKFMW3MZhICg=; b=SwY7sZaJA3ouAnRTtddkdpNdmtda4IDmILW8WNb81L1yxCCMgxW535JdcpY/Haj6nz XLcrSjp6UT4Llh/W4EfdhulT/bYIb76xqCax4vhlPIPySZnmsWirUlqBfiNLc6/i4UKU ifScpmVdLyIBNST+VK4Fks0WmyFs/svA209b6uvRfEvZjV2Ain4uuni/gIHb33TRmKnt M7emwPPhkvdYlwmpJhS1i/zBZxMNAX3F4YN9I5NKPep0AfQxKqvTIT+OUxuHCHvC889c k3DvDyut4/PdB3TPH+yz3QPfq0TCmcEkBlPzyrmRYjBboAUrouHXt3uf8TEto0lEpl+1 1zEg== X-Gm-Message-State: AOJu0YwZ+fwDSfutmn1iy2PRu0WNk1MM2Rts0zBIqr93DtF0fT9+3fOH SVb+CBgOocXEJrMGHAbAwRU+ndGLQr7SGf6btJd9QQ== X-Google-Smtp-Source: AGHT+IF5/GAIVtoWOfGc9fUb7PO0hOmaM1g2zVjcl/HiR6HQZ567njNDuveBEtPDxtdWFQTVybI7gQ== X-Received: by 2002:a05:600c:a4c:b0:409:718b:33e0 with SMTP id c12-20020a05600c0a4c00b00409718b33e0mr7741973wmq.16.1699614000672; Fri, 10 Nov 2023 03:00:00 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id r15-20020a05600c35cf00b0040531f5c51asm4883156wmq.5.2023.11.10.03.00.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Nov 2023 03:00:00 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 10 Nov 2023 11:00:02 +0000 Message-Id: <20231110110002.21381-6-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231110110002.21381-1-naush@raspberrypi.com> References: <20231110110002.21381-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 5/5] documentation: Document vendor specific control and properties handling X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add some documentation to the pipeline handler file describing how to implement and handle vendor specific controls and properties with a small example. Signed-off-by: Naushir Patuck --- Documentation/guides/pipeline-handler.rst | 53 +++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst index 10b9c75c2a7f..417eceeb62bd 100644 --- a/Documentation/guides/pipeline-handler.rst +++ b/Documentation/guides/pipeline-handler.rst @@ -672,6 +672,59 @@ handling controls: #include #include +Vendor specific controls and properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Vendor specific controls and properties may be defined in a separate YMAL file +and included in the build by defining the pipeline handler to file mapping in +include/libcamera/meson.build. + +For example, adding a Raspberry Pi vendor control file for the PiSP pipeline +handler is done with the following mapping: + +.. code-block:: meson + + vendor_mappings = { + # Mapping of vendor (pipeline handler) specific controls files + 'controls': + { + 'rpi/pisp': 'control_ids_rpi.yaml', + }, + # Mapping of vendor (pipeline handler) specific properties files + 'properties': + { + + } + } + +It is also possible (though inadvisable for maintenance purposes) to add vendor +specific controls directly in the the src/libcamera/`control_ids.yaml`_ or +src/libcamera/`properties_ids.yaml`_ files. + +Vendor specific controls and properties must contain a `vendor: ` +tag in the YAML definition. Every unique vendor tag must define a unique and +non-overlapping range of reserved control IDs in src/libcamera/control_ranges.yaml. + +For example, the following block defines a vendor specific control with the +`rpi` vendor tag: + +.. code-block:: yaml + + - PispConfigDumpFile: + type: string + vendor: rpi + description: | + Triggers the Raspberry Pi PiSP pipeline handler to generate a JSON + formatted dump of the Backend configuration to the filename given by the + value of the control. + +This controls will be generated in the vendor specific namespace +`libcamera::controls::rpi`. Additionally a `#define +LIBCAMERA_RPI_VENDOR_CONTROL` will be available to allow applications to test +for the availability of these controls. + +Note that draft controls are defined with the `vendor: draft` tag. + Generating a default configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~