[{"id":31232,"web_url":"https://patchwork.libcamera.org/comment/31232/","msgid":"<172639676204.1521289.201347217996869366@ping.linuxembedded.co.uk>","date":"2024-09-15T10:39:22","subject":"Re: [PATCH v2] libcamera: pipeline: uvcvideo: Map focus controls","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Cláudio Paulo (2024-09-14 22:55:49)\n> Added mapping of controls::LensPosition and controls::AfMode to\n> v4l2 controls V4L2_CID_FOCUS_ABSOLUTE and V4L2_CID_FOCUS_AUTO\n> respectively when the device supports them.\n> \n> If not supported, they are not registered.\n> \n> Signed-off-by: Cláudio Paulo <claudio.paulo@makewise.pt>\n> ---\n\nI've tested this and it's functional.\n\nTested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> Fixed issues pointed out on feedback.\n> \n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 101 +++++++++++++++++--\n>  1 file changed, 93 insertions(+), 8 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index 6b32fa18..11e34e95 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -304,13 +304,26 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n>                 cid = V4L2_CID_EXPOSURE_ABSOLUTE;\n>         else if (id == controls::AnalogueGain)\n>                 cid = V4L2_CID_GAIN;\n> +       else if (id == controls::LensPosition)\n> +               cid = V4L2_CID_FOCUS_ABSOLUTE;\n> +       else if (id == controls::AfMode)\n> +               cid = V4L2_CID_FOCUS_AUTO;\n>         else\n>                 return -EINVAL;\n>  \n> +       /* Check if the device supports this control. */\n> +       if (controls->idMap()->find(cid) == controls->idMap()->end())\n> +               return -EINVAL;\n> +\n>         const ControlInfo &v4l2Info = controls->infoMap()->at(cid);\n> -       int32_t min = v4l2Info.min().get<int32_t>();\n> -       int32_t def = v4l2Info.def().get<int32_t>();\n> -       int32_t max = v4l2Info.max().get<int32_t>();\n> +\n> +       int32_t min = -1, def = -1, max = -1;\n> +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> +               min = v4l2Info.min().get<int32_t>();\n> +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> +               def = v4l2Info.def().get<int32_t>();\n> +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> +               max = v4l2Info.max().get<int32_t>();\n>  \n>         /*\n>          * See UVCCameraData::addControl() for explanations of the different\n> @@ -333,8 +346,8 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n>  \n>         case V4L2_CID_EXPOSURE_AUTO: {\n>                 int32_t ivalue = value.get<bool>()\n> -                              ? V4L2_EXPOSURE_APERTURE_PRIORITY\n> -                              : V4L2_EXPOSURE_MANUAL;\n> +                                        ? V4L2_EXPOSURE_APERTURE_PRIORITY\n> +                                        : V4L2_EXPOSURE_MANUAL;\n\nI'm sorry for this one - but this is a false positive from clang-format\nin checkstyle. I never could coax it into styling this how we like.\n\nWe should remove this hunk from the patch.\n\n>                 controls->set(V4L2_CID_EXPOSURE_AUTO, ivalue);\n>                 break;\n>         }\n> @@ -358,6 +371,20 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n>                 break;\n>         }\n>  \n> +       case V4L2_CID_FOCUS_ABSOLUTE: {\n> +               float focusedAt50Cm = 0.15f * (max - min);\n> +               float scale = focusedAt50Cm / 2.0f;\n> +\n> +               controls->set(cid, static_cast<int32_t>(value.get<float>() * scale + min));\n> +               break;\n> +       }\n> +\n> +       case V4L2_CID_FOCUS_AUTO: {\n> +               int32_t ivalue = value.get<int32_t>() != controls::AfModeManual;\n> +               controls->set(cid, ivalue);\n> +               break;\n> +       }\n> +\n>         default: {\n>                 int32_t ivalue = value.get<int32_t>();\n>                 controls->set(cid, ivalue);\n> @@ -655,14 +682,32 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n>         case V4L2_CID_GAIN:\n>                 id = &controls::AnalogueGain;\n>                 break;\n> +       case V4L2_CID_FOCUS_ABSOLUTE:\n> +               id = &controls::LensPosition;\n> +               break;\n> +       case V4L2_CID_FOCUS_AUTO:\n> +               id = &controls::AfMode;\n> +               break;\n>         default:\n>                 return;\n>         }\n>  \n>         /* Map the control info. */\n> -       int32_t min = v4l2Info.min().get<int32_t>();\n> -       int32_t max = v4l2Info.max().get<int32_t>();\n> -       int32_t def = v4l2Info.def().get<int32_t>();\n> +       int32_t min = -1, def = -1, max = -1;\n> +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> +               min = v4l2Info.min().get<int32_t>();\n> +       else if (v4l2Info.min().type() == ControlTypeBool)\n> +               min = v4l2Info.min().get<bool>();\n> +\n> +       if (v4l2Info.def().type() == ControlTypeInteger32)\n> +               def = v4l2Info.def().get<int32_t>();\n> +       else if (v4l2Info.def().type() == ControlTypeBool)\n> +               def = v4l2Info.def().get<bool>();\n> +\n> +       if (v4l2Info.max().type() == ControlTypeInteger32)\n> +               max = v4l2Info.max().get<int32_t>();\n> +       else if (v4l2Info.max().type() == ControlTypeBool)\n> +               max = v4l2Info.max().get<bool>();\n>  \n>         switch (cid) {\n>         case V4L2_CID_BRIGHTNESS: {\n> @@ -738,6 +783,46 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n>                 };\n>                 break;\n>         }\n> +       case V4L2_CID_FOCUS_ABSOLUTE: {\n> +               /*\n> +                * LensPosition expects values to be in the range of\n> +                * [0.0f, maxDioptres], while a value of 0 means focused to\n> +                * infinity, 0.5 means focused at 2m, 2 means focused at 50cm\n> +                * and maxDioptres will be the closest possible focus which\n> +                * will equate to a focus distance of (1 / maxDioptres) metres.\n> +                *\n> +                * In this case 0.15f (~= 150 / (1023 - 1)) was a value read\n> +                * from V4L2_CID_FOCUS_ABSOLUTE control when using a random\n> +                * camera and having it autofocus at a distance of about 50cm.\n\nThis is a potentially contentious area if it's hardcoding to one\nspecific device.\n\n> +                * This means the minimum focus distance of this camera should\n> +                * be 75mm (0.15 / 2) which equals a maxDioptres value of ~=\n> +                * 13.3333 (2 / 0.15).\n> +                *\n> +                * These values will definitely vary for each different\n> +                * hardware. Also, the values might not scale linearly, but\n> +                * this implementation assumes they do.\n> +                */\n\nI think we'll have to put this in as a \\todo rather than a comment to\nexpress that there is further work required here.\n\n> +               float focusedAt50Cm = 0.15f * (max - min);\n\nSo it seems like this should be a tunable parameter. But I'm not sure\nhow we can handle that...\n\nPerhaps if we can determine some (not insane) default value and let it\nbe specified in the upcoming camera configuration files that Milan is\nworking on. Or we go and put a full tuning file for UVC ... but that\nseems impractical..\n\nBut otherwise, this indeed lets the UVC camera start to progress with\nthe plumbing.\n\n\n> +               float scale = 2.0f / focusedAt50Cm;\n> +\n> +               info = ControlInfo{\n> +                       { 0.0f },\n> +                       { (max - min) * scale },\n> +                       { (def - min) * scale }\n> +               };\n> +               break;\n> +       }\n> +       case V4L2_CID_FOCUS_AUTO: {\n> +               int32_t manual = controls::AfModeManual;\n> +               int32_t continuous = controls::AfModeContinuous;\n> +\n> +               info = ControlInfo{\n> +                       { manual },\n> +                       { continuous },\n> +                       { def ? continuous : manual },\n> +               };\n> +               break;\n> +       }\n>  \n>         default:\n>                 info = v4l2Info;\n> -- \n> 2.34.1\n>","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 6E4EAC324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 15 Sep 2024 10:39:28 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8B4CF634F5;\n\tSun, 15 Sep 2024 12:39:27 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B216D634F4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 15 Sep 2024 12:39:25 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 17E68524;\n\tSun, 15 Sep 2024 12:38:05 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"BQ/uPSTz\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1726396685;\n\tbh=jqertoi+N5XNeJ0f9mIhXJ+Srww7hUnqsbvlG5AnUQI=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=BQ/uPSTzI7G2tSi8ktksZU/2yaxoya9AZqhEqpGAcbSQNmfAvEr0KrwOzkoQFLjz1\n\tK5cDk+8TrKzQSkZz+J8g3j7ilfTL+R00i3YvQhpkHuGLIBxe/i/0DpA4QeHNoIwzWM\n\ty8H6YEASPmC0l1C8jMSxBC6bhLbE71XZFEDvBJP4=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<01020191f288fe5f-fb094635-2cc7-4e76-8492-a42e0b6978e3-000000@eu-west-1.amazonses.com>","References":"<01020191f288fe5f-fb094635-2cc7-4e76-8492-a42e0b6978e3-000000@eu-west-1.amazonses.com>","Subject":"Re: [PATCH v2] libcamera: pipeline: uvcvideo: Map focus controls","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"=?utf-8?q?Cl=C3=A1udio?= Paulo <claudio.paulo@makewise.pt>","To":"=?utf-8?q?Cl=C3=A1udio?= Paulo <claudio.paulo@makewise.pt>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Sun, 15 Sep 2024 11:39:22 +0100","Message-ID":"<172639676204.1521289.201347217996869366@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}},{"id":31366,"web_url":"https://patchwork.libcamera.org/comment/31366/","msgid":"<20240925215549.GC11070@pendragon.ideasonboard.com>","date":"2024-09-25T21:55:49","subject":"Re: [PATCH v2] libcamera: pipeline: uvcvideo: Map focus controls","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Sun, Sep 15, 2024 at 11:39:22AM +0100, Kieran Bingham wrote:\n> Quoting Cláudio Paulo (2024-09-14 22:55:49)\n> > Added mapping of controls::LensPosition and controls::AfMode to\n> > v4l2 controls V4L2_CID_FOCUS_ABSOLUTE and V4L2_CID_FOCUS_AUTO\n> > respectively when the device supports them.\n> > \n> > If not supported, they are not registered.\n> > \n> > Signed-off-by: Cláudio Paulo <claudio.paulo@makewise.pt>\n> > ---\n> \n> I've tested this and it's functional.\n> \n> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> > Fixed issues pointed out on feedback.\n> > \n> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 101 +++++++++++++++++--\n> >  1 file changed, 93 insertions(+), 8 deletions(-)\n> > \n> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > index 6b32fa18..11e34e95 100644\n> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > @@ -304,13 +304,26 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n> >                 cid = V4L2_CID_EXPOSURE_ABSOLUTE;\n> >         else if (id == controls::AnalogueGain)\n> >                 cid = V4L2_CID_GAIN;\n> > +       else if (id == controls::LensPosition)\n> > +               cid = V4L2_CID_FOCUS_ABSOLUTE;\n> > +       else if (id == controls::AfMode)\n> > +               cid = V4L2_CID_FOCUS_AUTO;\n> >         else\n> >                 return -EINVAL;\n> >  \n> > +       /* Check if the device supports this control. */\n> > +       if (controls->idMap()->find(cid) == controls->idMap()->end())\n> > +               return -EINVAL;\n> > +\n> >         const ControlInfo &v4l2Info = controls->infoMap()->at(cid);\n> > -       int32_t min = v4l2Info.min().get<int32_t>();\n> > -       int32_t def = v4l2Info.def().get<int32_t>();\n> > -       int32_t max = v4l2Info.max().get<int32_t>();\n> > +\n> > +       int32_t min = -1, def = -1, max = -1;\n> > +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> > +               min = v4l2Info.min().get<int32_t>();\n> > +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> > +               def = v4l2Info.def().get<int32_t>();\n> > +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> > +               max = v4l2Info.max().get<int32_t>();\n> >  \n> >         /*\n> >          * See UVCCameraData::addControl() for explanations of the different\n> > @@ -333,8 +346,8 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n> >  \n> >         case V4L2_CID_EXPOSURE_AUTO: {\n> >                 int32_t ivalue = value.get<bool>()\n> > -                              ? V4L2_EXPOSURE_APERTURE_PRIORITY\n> > -                              : V4L2_EXPOSURE_MANUAL;\n> > +                                        ? V4L2_EXPOSURE_APERTURE_PRIORITY\n> > +                                        : V4L2_EXPOSURE_MANUAL;\n> \n> I'm sorry for this one - but this is a false positive from clang-format\n> in checkstyle. I never could coax it into styling this how we like.\n\nI tried to find a way to get clang-format to understand our coding\nstyle, but didn't succeed :-(\n\n> We should remove this hunk from the patch.\n> \n> >                 controls->set(V4L2_CID_EXPOSURE_AUTO, ivalue);\n> >                 break;\n> >         }\n> > @@ -358,6 +371,20 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n> >                 break;\n> >         }\n> >  \n> > +       case V4L2_CID_FOCUS_ABSOLUTE: {\n> > +               float focusedAt50Cm = 0.15f * (max - min);\n> > +               float scale = focusedAt50Cm / 2.0f;\n> > +\n> > +               controls->set(cid, static_cast<int32_t>(value.get<float>() * scale + min));\n> > +               break;\n> > +       }\n> > +\n> > +       case V4L2_CID_FOCUS_AUTO: {\n> > +               int32_t ivalue = value.get<int32_t>() != controls::AfModeManual;\n> > +               controls->set(cid, ivalue);\n> > +               break;\n> > +       }\n> > +\n> >         default: {\n> >                 int32_t ivalue = value.get<int32_t>();\n> >                 controls->set(cid, ivalue);\n> > @@ -655,14 +682,32 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> >         case V4L2_CID_GAIN:\n> >                 id = &controls::AnalogueGain;\n> >                 break;\n> > +       case V4L2_CID_FOCUS_ABSOLUTE:\n> > +               id = &controls::LensPosition;\n> > +               break;\n> > +       case V4L2_CID_FOCUS_AUTO:\n> > +               id = &controls::AfMode;\n> > +               break;\n> >         default:\n> >                 return;\n> >         }\n> >  \n> >         /* Map the control info. */\n> > -       int32_t min = v4l2Info.min().get<int32_t>();\n> > -       int32_t max = v4l2Info.max().get<int32_t>();\n> > -       int32_t def = v4l2Info.def().get<int32_t>();\n> > +       int32_t min = -1, def = -1, max = -1;\n> > +       if (v4l2Info.min().type() == ControlTypeInteger32)\n> > +               min = v4l2Info.min().get<int32_t>();\n> > +       else if (v4l2Info.min().type() == ControlTypeBool)\n> > +               min = v4l2Info.min().get<bool>();\n> > +\n> > +       if (v4l2Info.def().type() == ControlTypeInteger32)\n> > +               def = v4l2Info.def().get<int32_t>();\n> > +       else if (v4l2Info.def().type() == ControlTypeBool)\n> > +               def = v4l2Info.def().get<bool>();\n> > +\n> > +       if (v4l2Info.max().type() == ControlTypeInteger32)\n> > +               max = v4l2Info.max().get<int32_t>();\n> > +       else if (v4l2Info.max().type() == ControlTypeBool)\n> > +               max = v4l2Info.max().get<bool>();\n> >  \n> >         switch (cid) {\n> >         case V4L2_CID_BRIGHTNESS: {\n> > @@ -738,6 +783,46 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> >                 };\n> >                 break;\n> >         }\n> > +       case V4L2_CID_FOCUS_ABSOLUTE: {\n> > +               /*\n> > +                * LensPosition expects values to be in the range of\n> > +                * [0.0f, maxDioptres], while a value of 0 means focused to\n> > +                * infinity, 0.5 means focused at 2m, 2 means focused at 50cm\n> > +                * and maxDioptres will be the closest possible focus which\n> > +                * will equate to a focus distance of (1 / maxDioptres) metres.\n> > +                *\n> > +                * In this case 0.15f (~= 150 / (1023 - 1)) was a value read\n> > +                * from V4L2_CID_FOCUS_ABSOLUTE control when using a random\n> > +                * camera and having it autofocus at a distance of about 50cm.\n> \n> This is a potentially contentious area if it's hardcoding to one\n> specific device.\n> \n> > +                * This means the minimum focus distance of this camera should\n> > +                * be 75mm (0.15 / 2) which equals a maxDioptres value of ~=\n> > +                * 13.3333 (2 / 0.15).\n> > +                *\n> > +                * These values will definitely vary for each different\n> > +                * hardware. Also, the values might not scale linearly, but\n> > +                * this implementation assumes they do.\n> > +                */\n> \n> I think we'll have to put this in as a \\todo rather than a comment to\n> express that there is further work required here.\n> \n> > +               float focusedAt50Cm = 0.15f * (max - min);\n> \n> So it seems like this should be a tunable parameter. But I'm not sure\n> how we can handle that...\n> \n> Perhaps if we can determine some (not insane) default value and let it\n> be specified in the upcoming camera configuration files that Milan is\n> working on. Or we go and put a full tuning file for UVC ... but that\n> seems impractical..\n\nThere are thousands of UVC cameras out there, I don't think we can do\nthat. We may need to expose a new property to indicate that the focus\nlens isn't calibrated and that applications can't rely on any particular\nmapping between the LensPosition control and focal values.\n\n> But otherwise, this indeed lets the UVC camera start to progress with\n> the plumbing.\n\nIndeed :-)\n\n> > +               float scale = 2.0f / focusedAt50Cm;\n> > +\n> > +               info = ControlInfo{\n> > +                       { 0.0f },\n> > +                       { (max - min) * scale },\n> > +                       { (def - min) * scale }\n> > +               };\n> > +               break;\n> > +       }\n> > +       case V4L2_CID_FOCUS_AUTO: {\n> > +               int32_t manual = controls::AfModeManual;\n> > +               int32_t continuous = controls::AfModeContinuous;\n> > +\n> > +               info = ControlInfo{\n> > +                       { manual },\n> > +                       { continuous },\n> > +                       { def ? continuous : manual },\n> > +               };\n> > +               break;\n> > +       }\n> >  \n> >         default:\n> >                 info = v4l2Info;","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 4403CC0F1B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 25 Sep 2024 21:55:54 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 286F26350E;\n\tWed, 25 Sep 2024 23:55:53 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8403E634F4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 25 Sep 2024 23:55:51 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 749D27E2;\n\tWed, 25 Sep 2024 23:54:23 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Aj/XVeaM\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1727301263;\n\tbh=Ebz9TbLaWRnVX+xTAsPuleGNNQaTZlQYDdMv1SBp+9s=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Aj/XVeaMKkzQ55pCAaUoUX7pxS+36MnZwud+I/Sg/jCPMUGhSIAYWyuGlK371biW5\n\taAyqr+PDwCQW503Gibl7aiIKSeJFRUbc8ALAgP+5O0u/y+TqgPqKuDVqGaEv3rQAfF\n\tDhsa7oTsp++0hOu8dqdr8Pdk9ejwKLm9LtX9R+MY=","Date":"Thu, 26 Sep 2024 00:55:49 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"=?utf-8?q?Cl=C3=A1udio?= Paulo <claudio.paulo@makewise.pt>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2] libcamera: pipeline: uvcvideo: Map focus controls","Message-ID":"<20240925215549.GC11070@pendragon.ideasonboard.com>","References":"<01020191f288fe5f-fb094635-2cc7-4e76-8492-a42e0b6978e3-000000@eu-west-1.amazonses.com>\n\t<172639676204.1521289.201347217996869366@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<172639676204.1521289.201347217996869366@ping.linuxembedded.co.uk>","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>"}}]