{"id":24343,"url":"https://patchwork.libcamera.org/api/patches/24343/?format=json","web_url":"https://patchwork.libcamera.org/patch/24343/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20250912-flash_reco-v2-2-d5bb80a2e619@emfend.at>","date":"2025-09-12T07:13:21","name":"[v2,2/5] libcamera: Add support for camera flash devices","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"87466c850a5385bf1093d3e001b16f6c23e62107","submitter":{"id":134,"url":"https://patchwork.libcamera.org/api/people/134/?format=json","name":"Matthias Fend","email":"matthias.fend@emfend.at"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/24343/mbox/","series":[{"id":5437,"url":"https://patchwork.libcamera.org/api/series/5437/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5437","date":"2025-09-12T07:13:19","name":"Support for v4l2 flash devices","version":2,"mbox":"https://patchwork.libcamera.org/series/5437/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/24343/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/24343/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B13E8C324E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 12 Sep 2025 07:13:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2D31F6936E;\n\tFri, 12 Sep 2025 09:13:32 +0200 (CEST)","from lx20.hoststar.hosting (lx20.hoststar.hosting [168.119.41.54])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0EE696936E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Sep 2025 09:13:29 +0200 (CEST)","from 194-208-208-245.tele.net ([194.208.208.245]:58477\n\thelo=[127.0.1.1]) by lx20.hoststar.hosting with esmtpsa (TLS1.3) tls\n\tTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93)\n\t(envelope-from <matthias.fend@emfend.at>)\n\tid 1uwxyJ-008cBW-Cl; Fri, 12 Sep 2025 09:13:28 +0200"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=emfend.at header.i=@emfend.at\n\theader.b=\"Aert2LBo\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=emfend.at;\n\ts=mail;\n\th=Cc:To:In-Reply-To:References:Message-Id:Content-Transfer-Encoding:\n\tContent-Type:MIME-Version:Subject:Date:From:Sender:Reply-To:Content-ID:\n\tContent-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc\n\t:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:\n\tList-Post:List-Owner:List-Archive;\n\tbh=GagT+0KaniNMwlu9XlSP4iapYWrcu26VFeoGcHDKnw0=;\n\tb=Aert2LBoqgEcOgln+P3PjWpGnE\n\trxwzyRbDbYnKWYMhBByXKkXVJ4MiwCjELU2MBAYYj6QD6VvU2/2f1CiezoM/Ny0psGwfPOM+7acEY\n\t9doc9SdfOThuoUVhcvX0w22JhPU+qrZt0uxikUnv8UOP0qRehwltchGg4ITZKKVFUrlg=;","From":"Matthias Fend <matthias.fend@emfend.at>","Date":"Fri, 12 Sep 2025 09:13:21 +0200","Subject":"[PATCH v2 2/5] libcamera: Add support for camera flash devices","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"<20250912-flash_reco-v2-2-d5bb80a2e619@emfend.at>","References":"<20250912-flash_reco-v2-0-d5bb80a2e619@emfend.at>","In-Reply-To":"<20250912-flash_reco-v2-0-d5bb80a2e619@emfend.at>","To":"libcamera-devel@lists.libcamera.org","Cc":"Matthias Fend <matthias.fend@emfend.at>","X-Mailer":"b4 0.14.2","X-Spam-Score":"-1.0","X-Spam-Bar":"-","X-Spam-Report":"Spam detection software,\n\trunning on the system \"lx20.hoststar.hosting\", \n\thas NOT identified this incoming email as spam.  The original\n\tmessage has been attached to this so you can view it or label\n\tsimilar future email.  If you have any questions, see\n\tthe administrator of that system for details.\n\tContent preview: Define a set of controls to control camera flash\n\tdevices.\n\tSigned-off-by: Matthias Fend <matthias.fend@emfend.at> ---\n\tsrc/libcamera/control_ids_core.yaml\n\t| 78 +++++++++++++++++++++++++++++++++++++ 1 file changed,\n\t78 insertions(+)\n\tContent analysis details:   (-1.0 points, 5.0 required)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP\n\t0.0 Local_hs1_NotHoststar  Sender is not from hoststar.ch|de|com\n\t0.0 TVD_RCVD_IP            Message was received from an IP address\n\t0.0 KAM_DMARC_STATUS Test Rule for DKIM or SPF Failure with Strict\n\tAlignment","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Add a class to model camera flash devices. Currently, only v4l2 flash\ndevices are supported. The v4l2 flash devices are implemented similar to\nthe camera lenses.\n\nSigned-off-by: Matthias Fend <matthias.fend@emfend.at>\n---\n include/libcamera/internal/camera_flash.h     |  72 ++++++++\n include/libcamera/internal/camera_sensor.h    |   2 +\n src/libcamera/camera_flash.cpp                | 249 ++++++++++++++++++++++++++\n src/libcamera/meson.build                     |   1 +\n src/libcamera/sensor/camera_sensor_legacy.cpp |  13 ++\n src/libcamera/sensor/camera_sensor_raw.cpp    |  13 ++\n 6 files changed, 350 insertions(+)","diff":"diff --git a/include/libcamera/internal/camera_flash.h b/include/libcamera/internal/camera_flash.h\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..70234ca96d98dd88a084e2c6804a66e455d87ef8\n--- /dev/null\n+++ b/include/libcamera/internal/camera_flash.h\n@@ -0,0 +1,72 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2025, matthias.fend@emfend.at\n+ *\n+ * Camera flash support\n+ */\n+#pragma once\n+\n+#include <memory>\n+#include <stdint.h>\n+#include <string>\n+\n+#include <libcamera/base/class.h>\n+#include <libcamera/base/log.h>\n+\n+#include <libcamera/controls.h>\n+\n+namespace libcamera {\n+\n+class MediaEntity;\n+class V4L2Subdevice;\n+\n+class CameraFlash : protected Loggable\n+{\n+public:\n+\tenum class Mode {\n+\t\tNone,\n+\t\tFlash,\n+\t\tTorch,\n+\t};\n+\n+\tenum class StrobeSource {\n+\t\tSoftware,\n+\t\tExternal,\n+\t};\n+\n+\texplicit CameraFlash(const MediaEntity *entity);\n+\t~CameraFlash();\n+\tint init();\n+\tstd::optional<Mode> getMode() const;\n+\tint setMode(Mode mode);\n+\tconst ControlInfo &getFlashIntensityInfo() const;\n+\tstd::optional<int32_t> getFlashIntensity() const;\n+\tint setFlashIntensity(int32_t intensity);\n+\tconst ControlInfo &getFlashTimeoutInfo() const;\n+\tstd::optional<int32_t> getFlashTimeout() const;\n+\tint setFlashTimeout(int32_t timeout_us);\n+\tstd::optional<StrobeSource> getStrobeSource() const;\n+\tint setStrobeSource(StrobeSource source);\n+\tint startStrobe();\n+\tint stopStrobe();\n+\tconst ControlInfo &getTorchIntensityInfo() const;\n+\tstd::optional<int32_t> getTorchIntensity() const;\n+\tint setTorchIntensity(int32_t intensity);\n+\n+protected:\n+\tstd::string logPrefix() const override;\n+\n+private:\n+\tLIBCAMERA_DISABLE_COPY_AND_MOVE(CameraFlash)\n+\n+\tstd::optional<int32_t> getSubdevControl(uint32_t id) const;\n+\tint setSubdevControl(uint32_t id, int32_t value);\n+\tint validateDriver();\n+\n+\tconst MediaEntity *entity_;\n+\tstd::unique_ptr<V4L2Subdevice> subdev_;\n+\tstd::string model_;\n+\tconst ControlInfoMap *controlInfoMap_ = nullptr;\n+};\n+\n+} /* namespace libcamera */\ndiff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\nindex f6ef4df170d43500bc652762e9a575010a6c1cbd..faeecf244c8d42a43eca52ae04813e0c2f80e516 100644\n--- a/include/libcamera/internal/camera_sensor.h\n+++ b/include/libcamera/internal/camera_sensor.h\n@@ -28,6 +28,7 @@\n \n namespace libcamera {\n \n+class CameraFlash;\n class CameraLens;\n class MediaEntity;\n class SensorConfiguration;\n@@ -48,6 +49,7 @@ public:\n \tvirtual V4L2Subdevice *device() = 0;\n \n \tvirtual CameraLens *focusLens() = 0;\n+\tvirtual CameraFlash *flash() = 0;\n \n \tvirtual const std::vector<unsigned int> &mbusCodes() const = 0;\n \tvirtual std::vector<Size> sizes(unsigned int mbusCode) const = 0;\ndiff --git a/src/libcamera/camera_flash.cpp b/src/libcamera/camera_flash.cpp\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..d3b9fbf78f063ae0cb67635c4cda667508479534\n--- /dev/null\n+++ b/src/libcamera/camera_flash.cpp\n@@ -0,0 +1,249 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2025, matthias.fend@emfend.at\n+ *\n+ * Camera flash support\n+ */\n+\n+#include \"libcamera/internal/camera_flash.h\"\n+\n+#include <libcamera/base/utils.h>\n+\n+#include \"libcamera/internal/v4l2_subdevice.h\"\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(CameraFlash)\n+\n+CameraFlash::CameraFlash(const MediaEntity *entity)\n+\t: entity_(entity)\n+{\n+}\n+\n+CameraFlash::~CameraFlash() = default;\n+\n+int CameraFlash::init()\n+{\n+\tif (entity_->function() != MEDIA_ENT_F_FLASH) {\n+\t\tLOG(CameraFlash, Error)\n+\t\t\t<< \"Invalid flash function \"\n+\t\t\t<< utils::hex(entity_->function());\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsubdev_ = std::make_unique<V4L2Subdevice>(entity_);\n+\tint ret = subdev_->open();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tcontrolInfoMap_ = &subdev_->controls();\n+\n+\tret = validateDriver();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmodel_ = subdev_->model();\n+\n+\treturn 0;\n+}\n+\n+std::optional<CameraFlash::Mode> CameraFlash::getMode() const\n+{\n+\tMode mode;\n+\n+\tauto v4l2Mode = getSubdevControl(V4L2_CID_FLASH_LED_MODE);\n+\tif (!v4l2Mode)\n+\t\treturn std::nullopt;\n+\n+\tswitch (*v4l2Mode) {\n+\tcase V4L2_FLASH_LED_MODE_FLASH:\n+\t\tmode = Mode::Flash;\n+\t\tbreak;\n+\tcase V4L2_FLASH_LED_MODE_TORCH:\n+\t\tmode = Mode::Torch;\n+\t\tbreak;\n+\tcase V4L2_FLASH_LED_MODE_NONE:\n+\tdefault:\n+\t\tmode = Mode::None;\n+\t\tbreak;\n+\t}\n+\n+\treturn mode;\n+}\n+\n+int CameraFlash::setMode(Mode mode)\n+{\n+\tint32_t v4l2Mode;\n+\n+\tswitch (mode) {\n+\tcase Mode::Flash:\n+\t\tv4l2Mode = V4L2_FLASH_LED_MODE_FLASH;\n+\t\tbreak;\n+\tcase Mode::Torch:\n+\t\tv4l2Mode = V4L2_FLASH_LED_MODE_TORCH;\n+\t\tbreak;\n+\tcase Mode::None:\n+\t\tv4l2Mode = V4L2_FLASH_LED_MODE_NONE;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn setSubdevControl(V4L2_CID_FLASH_LED_MODE, v4l2Mode);\n+}\n+\n+const ControlInfo &CameraFlash::getFlashIntensityInfo() const\n+{\n+\treturn controlInfoMap_->find(V4L2_CID_FLASH_INTENSITY)->second;\n+}\n+\n+std::optional<int32_t> CameraFlash::getFlashIntensity() const\n+{\n+\treturn getSubdevControl(V4L2_CID_FLASH_INTENSITY);\n+}\n+\n+int CameraFlash::setFlashIntensity(int32_t intensity)\n+{\n+\treturn setSubdevControl(V4L2_CID_FLASH_INTENSITY, intensity);\n+}\n+\n+const ControlInfo &CameraFlash::getFlashTimeoutInfo() const\n+{\n+\treturn controlInfoMap_->find(V4L2_CID_FLASH_TIMEOUT)->second;\n+}\n+\n+std::optional<int32_t> CameraFlash::getFlashTimeout() const\n+{\n+\treturn getSubdevControl(V4L2_CID_FLASH_TIMEOUT);\n+}\n+\n+int CameraFlash::setFlashTimeout(int32_t timeout)\n+{\n+\treturn setSubdevControl(V4L2_CID_FLASH_TIMEOUT, timeout);\n+}\n+\n+std::optional<CameraFlash::StrobeSource> CameraFlash::getStrobeSource() const\n+{\n+\tStrobeSource source;\n+\n+\tauto v4l2Source = getSubdevControl(V4L2_CID_FLASH_STROBE_SOURCE);\n+\tif (!v4l2Source)\n+\t\treturn std::nullopt;\n+\n+\tswitch (*v4l2Source) {\n+\tcase V4L2_FLASH_STROBE_SOURCE_EXTERNAL:\n+\t\tsource = StrobeSource::External;\n+\t\tbreak;\n+\tcase V4L2_FLASH_STROBE_SOURCE_SOFTWARE:\n+\tdefault:\n+\t\tsource = StrobeSource::Software;\n+\t\tbreak;\n+\t}\n+\n+\treturn source;\n+}\n+\n+int CameraFlash::setStrobeSource(StrobeSource source)\n+{\n+\tint32_t v4l2Source;\n+\n+\tswitch (source) {\n+\tcase StrobeSource::External:\n+\t\tv4l2Source = V4L2_FLASH_STROBE_SOURCE_EXTERNAL;\n+\t\tbreak;\n+\tcase StrobeSource::Software:\n+\t\tv4l2Source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn setSubdevControl(V4L2_CID_FLASH_STROBE_SOURCE, v4l2Source);\n+}\n+\n+int CameraFlash::startStrobe()\n+{\n+\treturn setSubdevControl(V4L2_CID_FLASH_STROBE, 1);\n+}\n+\n+int CameraFlash::stopStrobe()\n+{\n+\treturn setSubdevControl(V4L2_CID_FLASH_STROBE_STOP, 1);\n+}\n+\n+const ControlInfo &CameraFlash::getTorchIntensityInfo() const\n+{\n+\treturn controlInfoMap_->find(V4L2_CID_FLASH_TORCH_INTENSITY)->second;\n+}\n+\n+std::optional<int32_t> CameraFlash::getTorchIntensity() const\n+{\n+\treturn getSubdevControl(V4L2_CID_FLASH_TORCH_INTENSITY);\n+}\n+\n+int CameraFlash::setTorchIntensity(int32_t intensity)\n+{\n+\treturn setSubdevControl(V4L2_CID_FLASH_TORCH_INTENSITY, intensity);\n+}\n+\n+std::string CameraFlash::logPrefix() const\n+{\n+\treturn \"'\" + entity_->name() + \"'\";\n+}\n+\n+std::optional<int32_t> CameraFlash::getSubdevControl(uint32_t id) const\n+{\n+\tControlList controlList = subdev_->getControls(std::array{ id });\n+\n+\tif (controlList.contains(id))\n+\t\treturn std::nullopt;\n+\n+\treturn controlList.get(id).get<int32_t>();\n+}\n+\n+int CameraFlash::setSubdevControl(uint32_t id, int32_t value)\n+{\n+\tControlList flashCtrls(*controlInfoMap_);\n+\n+\tflashCtrls.set(id, value);\n+\n+\tif (subdev_->setControls(&flashCtrls))\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+int CameraFlash::validateDriver()\n+{\n+\tint ret = 0;\n+\tstatic constexpr uint32_t mandatoryControls[] = {\n+\t\tV4L2_CID_FLASH_LED_MODE,\n+\t\tV4L2_CID_FLASH_STROBE_SOURCE,\n+\t\tV4L2_CID_FLASH_STROBE,\n+\t\tV4L2_CID_FLASH_TIMEOUT,\n+\t\tV4L2_CID_FLASH_INTENSITY,\n+\t\tV4L2_CID_FLASH_TORCH_INTENSITY,\n+\t};\n+\n+\tfor (uint32_t ctrl : mandatoryControls) {\n+\t\tif (!controlInfoMap_->count(ctrl)) {\n+\t\t\tLOG(CameraFlash, Error)\n+\t\t\t\t<< \"Mandatory V4L2 control \" << utils::hex(ctrl)\n+\t\t\t\t<< \" not available\";\n+\t\t\tret = -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (ret) {\n+\t\tLOG(CameraFlash, Error)\n+\t\t\t<< \"The flash kernel driver needs to be fixed\";\n+\t\tLOG(CameraFlash, Error)\n+\t\t\t<< \"See Documentation/flash_driver_requirements.rst in\"\n+\t\t\t<< \" the libcamera sources for more information\";\n+\t\treturn ret;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex b3ca27f217da4ba3a896ef7cbfb5502fa82a4907..0f125661a51e2431c1febc353cef30a1219f9ce7 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -20,6 +20,7 @@ libcamera_internal_sources = files([\n     'bayer_format.cpp',\n     'byte_stream_buffer.cpp',\n     'camera_controls.cpp',\n+    'camera_flash.cpp',\n     'camera_lens.cpp',\n     'clock_recovery.cpp',\n     'control_serializer.cpp',\ndiff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp\nindex f9e685a9acc499fc91d51ed1d66780a0ad2d2a8f..632b66ea0aa15fcd654e7f0efb50c24cb9b973bf 100644\n--- a/src/libcamera/sensor/camera_sensor_legacy.cpp\n+++ b/src/libcamera/sensor/camera_sensor_legacy.cpp\n@@ -31,6 +31,7 @@\n #include <libcamera/ipa/core_ipa_interface.h>\n \n #include \"libcamera/internal/bayer_format.h\"\n+#include \"libcamera/internal/camera_flash.h\"\n #include \"libcamera/internal/camera_lens.h\"\n #include \"libcamera/internal/camera_sensor.h\"\n #include \"libcamera/internal/camera_sensor_properties.h\"\n@@ -68,6 +69,7 @@ public:\n \tV4L2Subdevice *device() override { return subdev_.get(); }\n \n \tCameraLens *focusLens() override { return focusLens_.get(); }\n+\tCameraFlash *flash() override { return flash_.get(); }\n \n \tconst std::vector<unsigned int> &mbusCodes() const override { return mbusCodes_; }\n \tstd::vector<Size> sizes(unsigned int mbusCode) const override;\n@@ -139,6 +141,7 @@ private:\n \tControlList properties_;\n \n \tstd::unique_ptr<CameraLens> focusLens_;\n+\tstd::unique_ptr<CameraFlash> flash_;\n };\n \n /**\n@@ -665,6 +668,16 @@ int CameraSensorLegacy::discoverAncillaryDevices()\n \t\t\t}\n \t\t\tbreak;\n \n+\t\tcase MEDIA_ENT_F_FLASH:\n+\t\t\tflash_ = std::make_unique<CameraFlash>(ancillary);\n+\t\t\tret = flash_->init();\n+\t\t\tif (ret) {\n+\t\t\t\tLOG(CameraSensor, Error)\n+\t\t\t\t\t<< \"Flash initialisation failed, flash disabled\";\n+\t\t\t\tflash_.reset();\n+\t\t\t}\n+\t\t\tbreak;\n+\n \t\tdefault:\n \t\t\tLOG(CameraSensor, Warning)\n \t\t\t\t<< \"Unsupported ancillary entity function \"\ndiff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp\nindex 8ea4423698cd8c1eaae43eb5ba8b5d524b94d515..9d533d814b9df453aa4009a87818c1558bcbd665 100644\n--- a/src/libcamera/sensor/camera_sensor_raw.cpp\n+++ b/src/libcamera/sensor/camera_sensor_raw.cpp\n@@ -32,6 +32,7 @@\n #include <libcamera/ipa/core_ipa_interface.h>\n \n #include \"libcamera/internal/bayer_format.h\"\n+#include \"libcamera/internal/camera_flash.h\"\n #include \"libcamera/internal/camera_lens.h\"\n #include \"libcamera/internal/camera_sensor.h\"\n #include \"libcamera/internal/camera_sensor_properties.h\"\n@@ -69,6 +70,7 @@ public:\n \tV4L2Subdevice *device() override { return subdev_.get(); }\n \n \tCameraLens *focusLens() override { return focusLens_.get(); }\n+\tCameraFlash *flash() override { return flash_.get(); }\n \n \tconst std::vector<unsigned int> &mbusCodes() const override { return mbusCodes_; }\n \tstd::vector<Size> sizes(unsigned int mbusCode) const override;\n@@ -150,6 +152,7 @@ private:\n \tControlList properties_;\n \n \tstd::unique_ptr<CameraLens> focusLens_;\n+\tstd::unique_ptr<CameraFlash> flash_;\n };\n \n /**\n@@ -513,6 +516,16 @@ std::optional<int> CameraSensorRaw::init()\n \t\t\t}\n \t\t\tbreak;\n \n+\t\tcase MEDIA_ENT_F_FLASH:\n+\t\t\tflash_ = std::make_unique<CameraFlash>(ancillary);\n+\t\t\tret = flash_->init();\n+\t\t\tif (ret) {\n+\t\t\t\tLOG(CameraSensor, Error)\n+\t\t\t\t\t<< \"Flash initialisation failed, flash disabled\";\n+\t\t\t\tflash_.reset();\n+\t\t\t}\n+\t\t\tbreak;\n+\n \t\tdefault:\n \t\t\tLOG(CameraSensor, Warning)\n \t\t\t\t<< \"Unsupported ancillary entity function \"\n","prefixes":["v2","2/5"]}