{"id":11199,"url":"https://patchwork.libcamera.org/api/patches/11199/?format=json","web_url":"https://patchwork.libcamera.org/patch/11199/","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":"<20210208225429.31627-3-laurent.pinchart@ideasonboard.com>","date":"2021-02-08T22:54:29","name":"[libcamera-devel,PATCH/RFC,2/2] libcamera: Use V4L2 Control instances","commit_ref":null,"pull_url":null,"state":"rfc","archived":false,"hash":"dc23f72435758d5d45fcbc116ed3ac79fc8f43a9","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":{"id":14,"url":"https://patchwork.libcamera.org/api/users/14/?format=json","username":"pinchartl","first_name":"Laurent","last_name":"Pinchart","email":"laurent.pinchart@ideasonboard.com"},"mbox":"https://patchwork.libcamera.org/patch/11199/mbox/","series":[{"id":1669,"url":"https://patchwork.libcamera.org/api/series/1669/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=1669","date":"2021-02-08T22:54:27","name":"libcamera: Add Control instances for V4L2 controls","version":1,"mbox":"https://patchwork.libcamera.org/series/1669/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/11199/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/11199/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 084BABD160\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  8 Feb 2021 22:55:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CABB96160E;\n\tMon,  8 Feb 2021 23:55:00 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A4BF360D37\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  8 Feb 2021 23:54:57 +0100 (CET)","from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 404903D7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  8 Feb 2021 23:54:57 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"pFErNuh2\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1612824897;\n\tbh=VzCdV7ikEmrOe0+22ZFpHP/iKAuQTiPigwAc3Ql+BFQ=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=pFErNuh2F/79r0TP2u2bresdfGrDdsEn2p9FWi+ucEWwjlgvnjg5ymFRIQYHB3Plu\n\tec1rvzEM9PjxFx3O6cfPYfkSpZPd+9Ydis6zaSOz3AlpH20w6i6q1EXgJ7aE/Hq0lP\n\tpC7JV/XK9R3EvXhA/W80cCc0cYmH0t/s5VhqlFOM=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Tue,  9 Feb 2021 00:54:29 +0200","Message-Id":"<20210208225429.31627-3-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.28.0","In-Reply-To":"<20210208225429.31627-1-laurent.pinchart@ideasonboard.com>","References":"<20210208225429.31627-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Subject":"[libcamera-devel] [PATCH/RFC 2/2] libcamera: Use V4L2 Control\n\tinstances","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>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Use the V4L2 Control instances instead of the numerical V4L2_CID_*\nidentifiers where possible. This simplify usage of the ControlList API\nin several places, and allows printing control names in the CameraSensor\nclass and the RaspberryPi IPA.\n\nThere are still locations where the numerical identifiers are used:\n\n- In the IPU3 and RaspberryPi code, for custom controls not defined in\n  linux/v4l2-controls.h, which can be fixed by adding additional\n  device-specific Control instances.\n\n- In the DelayedControls and V4L2Device controls APIs, which we could\n  move to ControlId if desired.\n\n- In the uvcvideo and vimc pipeline handlers, when translating between\n  V4L2 and libcamera controls, for switch/case or for code that operate\n  on different controls in a generic way. This would be more difficult\n  to replace.\n\nFurther improvements to the controls API may be possible on top of this,\nsuch as dropping the ID-based ControlList::get() and ControlList::set()\nfunctions (at possibly replacing them with a version that takes a\nControlId pointer). Another possibly interesting improvement would be to\nadd a lookup API to the ControlInfoMap class that would take a\nControl<T> reference, and return a type-aware wrapper around ControlInfo\nto avoid having to deal manually with ControlValue.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/ipa/ipu3/ipu3.cpp                         | 10 +++---\n src/ipa/raspberrypi/raspberrypi.cpp           | 25 ++++++-------\n src/ipa/rkisp1/rkisp1.cpp                     | 10 +++---\n src/libcamera/camera_sensor.cpp               | 36 +++++++++----------\n src/libcamera/pipeline/ipu3/ipu3.cpp          |  2 +-\n .../pipeline/raspberrypi/raspberrypi.cpp      | 16 ++++-----\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  | 29 +++++++--------\n src/libcamera/pipeline/vimc/vimc.cpp          | 10 +++---\n 8 files changed, 68 insertions(+), 70 deletions(-)","diff":"diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp\nindex b11b03efa6ce..5ee3fd302e01 100644\n--- a/src/ipa/ipu3/ipu3.cpp\n+++ b/src/ipa/ipu3/ipu3.cpp\n@@ -11,7 +11,6 @@\n #include <sys/mman.h>\n \n #include <linux/intel-ipu3.h>\n-#include <linux/v4l2-controls.h>\n \n #include <libcamera/buffer.h>\n #include <libcamera/control_ids.h>\n@@ -23,6 +22,7 @@\n \n #include \"libcamera/internal/buffer.h\"\n #include \"libcamera/internal/log.h\"\n+#include \"libcamera/internal/v4l2_controls.h\"\n \n namespace libcamera {\n \n@@ -80,13 +80,13 @@ void IPAIPU3::configure([[maybe_unused]] const CameraSensorInfo &info,\n \n \tctrls_ = entityControls.at(0);\n \n-\tconst auto itExp = ctrls_.find(V4L2_CID_EXPOSURE);\n+\tconst auto itExp = ctrls_.find(&v4l2::EXPOSURE);\n \tif (itExp == ctrls_.end()) {\n \t\tLOG(IPAIPU3, Error) << \"Can't find exposure control\";\n \t\treturn;\n \t}\n \n-\tconst auto itGain = ctrls_.find(V4L2_CID_ANALOGUE_GAIN);\n+\tconst auto itGain = ctrls_.find(&v4l2::ANALOGUE_GAIN);\n \tif (itGain == ctrls_.end()) {\n \t\tLOG(IPAIPU3, Error) << \"Can't find gain control\";\n \t\treturn;\n@@ -214,8 +214,8 @@ void IPAIPU3::setControls(unsigned int frame)\n \top.operation = IPU3_IPA_ACTION_SET_SENSOR_CONTROLS;\n \n \tControlList ctrls(ctrls_);\n-\tctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_));\n-\tctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain_));\n+\tctrls.set(v4l2::EXPOSURE, exposure_);\n+\tctrls.set(v4l2::ANALOGUE_GAIN, gain_);\n \top.controls.push_back(ctrls);\n \n \tqueueFrameAction.emit(frame, op);\ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex ff14cfc4b706..897f3f0b91f1 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -542,16 +542,16 @@ void IPARPi::reportMetadata()\n \n bool IPARPi::validateSensorControls()\n {\n-\tstatic const uint32_t ctrls[] = {\n-\t\tV4L2_CID_ANALOGUE_GAIN,\n-\t\tV4L2_CID_EXPOSURE,\n-\t\tV4L2_CID_VBLANK,\n+\tstatic const ControlId *const ctrls[] = {\n+\t\t&v4l2::ANALOGUE_GAIN,\n+\t\t&v4l2::EXPOSURE,\n+\t\t&v4l2::VBLANK,\n \t};\n \n \tfor (auto c : ctrls) {\n \t\tif (sensorCtrls_.find(c) == sensorCtrls_.end()) {\n \t\t\tLOG(IPARPI, Error) << \"Unable to find sensor control \"\n-\t\t\t\t\t   << utils::hex(c);\n+\t\t\t\t\t   << c->name();\n \t\t\treturn false;\n \t\t}\n \t}\n@@ -1038,10 +1038,8 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n \tLOG(IPARPI, Debug) << \"Applying WB R: \" << awbStatus->gain_r << \" B: \"\n \t\t\t   << awbStatus->gain_b;\n \n-\tctrls.set(V4L2_CID_RED_BALANCE,\n-\t\t  static_cast<int32_t>(awbStatus->gain_r * 1000));\n-\tctrls.set(V4L2_CID_BLUE_BALANCE,\n-\t\t  static_cast<int32_t>(awbStatus->gain_b * 1000));\n+\tctrls.set(v4l2::RED_BALANCE, awbStatus->gain_r * 1000);\n+\tctrls.set(v4l2::BLUE_BALANCE, awbStatus->gain_b * 1000);\n }\n \n void IPARPi::applyFrameDurations(double minFrameDuration, double maxFrameDuration)\n@@ -1100,15 +1098,14 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n \t * exposure time without us knowing. The next time though this function should\n \t * clip exposure correctly.\n \t */\n-\tctrls.set(V4L2_CID_VBLANK, vblanking);\n-\tctrls.set(V4L2_CID_EXPOSURE, exposureLines);\n-\tctrls.set(V4L2_CID_ANALOGUE_GAIN, gainCode);\n+\tctrls.set(v4l2::VBLANK, vblanking);\n+\tctrls.set(v4l2::EXPOSURE, exposureLines);\n+\tctrls.set(v4l2::ANALOGUE_GAIN, gainCode);\n }\n \n void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)\n {\n-\tctrls.set(V4L2_CID_DIGITAL_GAIN,\n-\t\t  static_cast<int32_t>(dgStatus->digital_gain * 1000));\n+\tctrls.set(v4l2::DIGITAL_GAIN, dgStatus->digital_gain * 1000);\n }\n \n void IPARPi::applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls)\ndiff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp\nindex 39783abd731b..ce47ba8cb38a 100644\n--- a/src/ipa/rkisp1/rkisp1.cpp\n+++ b/src/ipa/rkisp1/rkisp1.cpp\n@@ -13,7 +13,6 @@\n #include <sys/mman.h>\n \n #include <linux/rkisp1-config.h>\n-#include <linux/v4l2-controls.h>\n \n #include <libcamera/buffer.h>\n #include <libcamera/control_ids.h>\n@@ -25,6 +24,7 @@\n #include <libipa/ipa_interface_wrapper.h>\n \n #include \"libcamera/internal/log.h\"\n+#include \"libcamera/internal/v4l2_controls.h\"\n \n namespace libcamera {\n \n@@ -91,13 +91,13 @@ void IPARkISP1::configure([[maybe_unused]] const CameraSensorInfo &info,\n \n \tctrls_ = entityControls.at(0);\n \n-\tconst auto itExp = ctrls_.find(V4L2_CID_EXPOSURE);\n+\tconst auto itExp = ctrls_.find(&v4l2::EXPOSURE);\n \tif (itExp == ctrls_.end()) {\n \t\tLOG(IPARkISP1, Error) << \"Can't find exposure control\";\n \t\treturn;\n \t}\n \n-\tconst auto itGain = ctrls_.find(V4L2_CID_ANALOGUE_GAIN);\n+\tconst auto itGain = ctrls_.find(&v4l2::ANALOGUE_GAIN);\n \tif (itGain == ctrls_.end()) {\n \t\tLOG(IPARkISP1, Error) << \"Can't find gain control\";\n \t\treturn;\n@@ -261,8 +261,8 @@ void IPARkISP1::setControls(unsigned int frame)\n \top.operation = RKISP1_IPA_ACTION_V4L2_SET;\n \n \tControlList ctrls(ctrls_);\n-\tctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_));\n-\tctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain_));\n+\tctrls.set(v4l2::EXPOSURE, exposure_);\n+\tctrls.set(v4l2::ANALOGUE_GAIN, gain_);\n \top.controls.push_back(ctrls);\n \n \tqueueFrameAction.emit(frame, op);\ndiff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\nindex c9e8d49b7935..eb96c4841708 100644\n--- a/src/libcamera/camera_sensor.cpp\n+++ b/src/libcamera/camera_sensor.cpp\n@@ -280,16 +280,16 @@ int CameraSensor::validateSensorDriver()\n \t * Optional controls are used to register optional sensor properties. If\n \t * not present, some values will be defaulted.\n \t */\n-\tstatic constexpr uint32_t optionalControls[] = {\n-\t\tV4L2_CID_CAMERA_ORIENTATION,\n-\t\tV4L2_CID_CAMERA_SENSOR_ROTATION,\n+\tstatic const ControlId *const optionalControls[] = {\n+\t\t&v4l2::CAMERA_ORIENTATION,\n+\t\t&v4l2::CAMERA_SENSOR_ROTATION,\n \t};\n \n-\tconst ControlIdMap &controls = subdev_->controls().idmap();\n-\tfor (uint32_t ctrl : optionalControls) {\n+\tconst ControlInfoMap &controls = subdev_->controls();\n+\tfor (const ControlId *ctrl : optionalControls) {\n \t\tif (!controls.count(ctrl))\n \t\t\tLOG(CameraSensor, Debug)\n-\t\t\t\t<< \"Optional V4L2 control \" << utils::hex(ctrl)\n+\t\t\t\t<< \"Optional V4L2 control \" << ctrl->name()\n \t\t\t\t<< \" not supported\";\n \t}\n \n@@ -346,18 +346,18 @@ int CameraSensor::validateSensorDriver()\n \t * For raw sensors, make sure the sensor driver supports the controls\n \t * required by the CameraSensor class.\n \t */\n-\tstatic constexpr uint32_t mandatoryControls[] = {\n-\t\tV4L2_CID_EXPOSURE,\n-\t\tV4L2_CID_HBLANK,\n-\t\tV4L2_CID_PIXEL_RATE,\n-\t\tV4L2_CID_VBLANK,\n+\tstatic const ControlId *const mandatoryControls[] = {\n+\t\t&v4l2::EXPOSURE,\n+\t\t&v4l2::HBLANK,\n+\t\t&v4l2::PIXEL_RATE,\n+\t\t&v4l2::VBLANK,\n \t};\n \n \terr = 0;\n-\tfor (uint32_t ctrl : mandatoryControls) {\n+\tfor (const ControlId *ctrl : mandatoryControls) {\n \t\tif (!controls.count(ctrl)) {\n \t\t\tLOG(CameraSensor, Error)\n-\t\t\t\t<< \"Mandatory V4L2 control \" << utils::hex(ctrl)\n+\t\t\t\t<< \"Mandatory V4L2 control \" << ctrl->name()\n \t\t\t\t<< \" not available\";\n \t\t\terr = -EINVAL;\n \t\t}\n@@ -425,7 +425,7 @@ int CameraSensor::initProperties()\n \tconst ControlInfoMap &controls = subdev_->controls();\n \tint32_t propertyValue;\n \n-\tconst auto &orientation = controls.find(V4L2_CID_CAMERA_ORIENTATION);\n+\tconst auto &orientation = controls.find(&v4l2::CAMERA_ORIENTATION);\n \tif (orientation != controls.end()) {\n \t\tint32_t v4l2Orientation = orientation->second.def().get<int32_t>();\n \n@@ -450,7 +450,7 @@ int CameraSensor::initProperties()\n \t}\n \tproperties_.set(properties::Location, propertyValue);\n \n-\tconst auto &rotationControl = controls.find(V4L2_CID_CAMERA_SENSOR_ROTATION);\n+\tconst auto &rotationControl = controls.find(&v4l2::CAMERA_SENSOR_ROTATION);\n \tif (rotationControl != controls.end()) {\n \t\tpropertyValue = rotationControl->second.def().get<int32_t>();\n \t\tproperties_.set(properties::Rotation, propertyValue);\n@@ -775,11 +775,11 @@ int CameraSensor::sensorInfo(CameraSensorInfo *info) const\n \t\treturn -EINVAL;\n \t}\n \n-\tint32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();\n+\tint32_t hblank = ctrls.get(v4l2::HBLANK);\n \tinfo->lineLength = info->outputSize.width + hblank;\n-\tinfo->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();\n+\tinfo->pixelRate = ctrls.get(v4l2::PIXEL_RATE);\n \n-\tconst ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK);\n+\tconst ControlInfo vblank = ctrls.infoMap()->at(&v4l2::VBLANK);\n \tinfo->minFrameLength = info->outputSize.height + vblank.min().get<int32_t>();\n \tinfo->maxFrameLength = info->outputSize.height + vblank.max().get<int32_t>();\n \ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex 9bc3df3352fd..d3fc51518598 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -845,7 +845,7 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data)\n \tdouble lineDuration = sensorInfo.lineLength\n \t\t\t    / (sensorInfo.pixelRate / 1e6);\n \tconst ControlInfoMap &sensorControls = sensor->controls();\n-\tconst ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;\n+\tconst ControlInfo &v4l2Exposure = sensorControls.find(&v4l2::EXPOSURE)->second;\n \tint32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;\n \tint32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;\n \tint32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;\ndiff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 0804a4393c19..90f846530346 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -992,8 +992,8 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)\n \t\tdata->flipsAlterBayerOrder_ = hflipCtrl->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT;\n \n \t\tControlList ctrls(dev->controls());\n-\t\tctrls.set(V4L2_CID_HFLIP, 0);\n-\t\tctrls.set(V4L2_CID_VFLIP, 0);\n+\t\tctrls.set(v4l2::HFLIP, 0);\n+\t\tctrls.set(v4l2::VFLIP, 0);\n \t\tdev->setControls(&ctrls);\n \t}\n \n@@ -1246,10 +1246,10 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)\n \t */\n \tif (supportsFlips_) {\n \t\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n-\t\tctrls.set(V4L2_CID_HFLIP,\n-\t\t\t  static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::HFlip)));\n-\t\tctrls.set(V4L2_CID_VFLIP,\n-\t\t\t  static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::VFlip)));\n+\t\tctrls.set(v4l2::HFLIP,\n+\t\t\t  !!(rpiConfig->combinedTransform_ & Transform::HFlip));\n+\t\tctrls.set(v4l2::VFLIP,\n+\t\t\t  !!(rpiConfig->combinedTransform_ & Transform::VFlip));\n \t\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\n \t}\n \n@@ -1383,8 +1383,8 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)\n \t\t\tauto it = mappedEmbeddedBuffers_.find(bufferId);\n \t\t\tif (it != mappedEmbeddedBuffers_.end()) {\n \t\t\t\tuint32_t *mem = reinterpret_cast<uint32_t *>(it->second.maps()[0].data());\n-\t\t\t\tmem[0] = ctrl.get(V4L2_CID_EXPOSURE).get<int32_t>();\n-\t\t\t\tmem[1] = ctrl.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();\n+\t\t\t\tmem[0] = ctrl.get(v4l2::EXPOSURE);\n+\t\t\t\tmem[1] = ctrl.get(v4l2::ANALOGUE_GAIN);\n \t\t\t} else {\n \t\t\t\tLOG(RPI, Warning) << \"Failed to find embedded buffer \"\n \t\t\t\t\t\t  << bufferId;\ndiff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex 08a594175091..a80b51f174a9 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -260,20 +260,20 @@ void PipelineHandlerUVC::stop(Camera *camera)\n int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t\t\t\t       const ControlValue &value)\n {\n-\tuint32_t cid;\n+\tconst ControlId *cid;\n \n \tif (id == controls::Brightness)\n-\t\tcid = V4L2_CID_BRIGHTNESS;\n+\t\tcid = &v4l2::BRIGHTNESS;\n \telse if (id == controls::Contrast)\n-\t\tcid = V4L2_CID_CONTRAST;\n+\t\tcid = &v4l2::CONTRAST;\n \telse if (id == controls::Saturation)\n-\t\tcid = V4L2_CID_SATURATION;\n+\t\tcid = &v4l2::SATURATION;\n \telse if (id == controls::AeEnable)\n-\t\tcid = V4L2_CID_EXPOSURE_AUTO;\n+\t\tcid = &v4l2::EXPOSURE_AUTO;\n \telse if (id == controls::ExposureTime)\n-\t\tcid = V4L2_CID_EXPOSURE_ABSOLUTE;\n+\t\tcid = &v4l2::EXPOSURE_ABSOLUTE;\n \telse if (id == controls::AnalogueGain)\n-\t\tcid = V4L2_CID_GAIN;\n+\t\tcid = &v4l2::GAIN;\n \telse\n \t\treturn -EINVAL;\n \n@@ -286,18 +286,18 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t * See UVCCameraData::addControl() for explanations of the different\n \t * value mappings.\n \t */\n-\tswitch (cid) {\n+\tswitch (cid->id()) {\n \tcase V4L2_CID_BRIGHTNESS: {\n \t\tfloat scale = std::max(max - def, def - min);\n \t\tfloat fvalue = value.get<float>() * scale + def;\n-\t\tcontrols->set(cid, static_cast<int32_t>(lroundf(fvalue)));\n+\t\tcontrols->set(v4l2::BRIGHTNESS, lroundf(fvalue));\n \t\tbreak;\n \t}\n \n \tcase V4L2_CID_SATURATION: {\n \t\tfloat scale = def - min;\n \t\tfloat fvalue = value.get<float>() * scale + min;\n-\t\tcontrols->set(cid, static_cast<int32_t>(lroundf(fvalue)));\n+\t\tcontrols->set(v4l2::SATURATION, lroundf(fvalue));\n \t\tbreak;\n \t}\n \n@@ -305,12 +305,13 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t\tint32_t ivalue = value.get<bool>()\n \t\t\t       ? V4L2_EXPOSURE_APERTURE_PRIORITY\n \t\t\t       : V4L2_EXPOSURE_MANUAL;\n-\t\tcontrols->set(V4L2_CID_EXPOSURE_AUTO, ivalue);\n+\t\tcontrols->set(v4l2::EXPOSURE_AUTO, ivalue);\n \t\tbreak;\n \t}\n \n \tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n-\t\tcontrols->set(cid, value.get<int32_t>() / 100);\n+\t\tcontrols->set(v4l2::EXPOSURE_ABSOLUTE,\n+\t\t\t      value.get<int32_t>() / 100);\n \t\tbreak;\n \n \tcase V4L2_CID_CONTRAST:\n@@ -324,13 +325,13 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n \t\t}\n \n \t\tfloat fvalue = (value.get<float>() - p) / m;\n-\t\tcontrols->set(cid, static_cast<int32_t>(lroundf(fvalue)));\n+\t\tcontrols->set(cid->id(), static_cast<int32_t>(lroundf(fvalue)));\n \t\tbreak;\n \t}\n \n \tdefault: {\n \t\tint32_t ivalue = value.get<int32_t>();\n-\t\tcontrols->set(cid, ivalue);\n+\t\tcontrols->set(cid->id(), ivalue);\n \t\tbreak;\n \t}\n \t}\ndiff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\nindex 36325ffbbd7d..24b39b7dd879 100644\n--- a/src/libcamera/pipeline/vimc/vimc.cpp\n+++ b/src/libcamera/pipeline/vimc/vimc.cpp\n@@ -342,24 +342,24 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request)\n \n \tfor (auto it : request->controls()) {\n \t\tunsigned int id = it.first;\n+\t\tconst ControlId *cid;\n \t\tunsigned int offset;\n-\t\tuint32_t cid;\n \n \t\tif (id == controls::Brightness) {\n-\t\t\tcid = V4L2_CID_BRIGHTNESS;\n+\t\t\tcid = &v4l2::BRIGHTNESS;\n \t\t\toffset = 128;\n \t\t} else if (id == controls::Contrast) {\n-\t\t\tcid = V4L2_CID_CONTRAST;\n+\t\t\tcid = &v4l2::CONTRAST;\n \t\t\toffset = 0;\n \t\t} else if (id == controls::Saturation) {\n-\t\t\tcid = V4L2_CID_SATURATION;\n+\t\t\tcid = &v4l2::SATURATION;\n \t\t\toffset = 0;\n \t\t} else {\n \t\t\tcontinue;\n \t\t}\n \n \t\tint32_t value = lroundf(it.second.get<float>() * 128 + offset);\n-\t\tcontrols.set(cid, std::clamp(value, 0, 255));\n+\t\tcontrols.set(cid->id(), std::clamp(value, 0, 255));\n \t}\n \n \tfor (const auto &ctrl : controls)\n","prefixes":["libcamera-devel","PATCH/RFC","2/2"]}