[{"id":2083,"web_url":"https://patchwork.libcamera.org/comment/2083/","msgid":"<20190701170353.6yuhbyzltip4gz4i@uno.localdomain>","date":"2019-07-01T17:03:53","subject":"Re: [libcamera-devel] [PATCH v3 09/14] libcamera: pipeline:\n\tuvcvideo: Add controls support","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Kieran, Laurent,\n\nOn Mon, Jul 01, 2019 at 02:38:12AM +0300, Laurent Pinchart wrote:\n> From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>\n> Implement control support in the UVC pipeline handler by dynamically\n> querying the V4L2 device for the supported V4L2 controls and populating\n> the list of camera controls accordingly.\n>\n> Not-signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nWhy so?\n\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/libcamera/pipeline/uvcvideo.cpp | 129 +++++++++++++++++++++++++---\n>  1 file changed, 115 insertions(+), 14 deletions(-)\n>\n> diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp\n> index 2e22523d7cb1..f68dc5bd6f74 100644\n> --- a/src/libcamera/pipeline/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo.cpp\n> @@ -6,8 +6,11 @@\n>   */\n>\n>  #include <algorithm>\n> +#include <iomanip>\n> +#include <tuple>\n>\n>  #include <libcamera/camera.h>\n> +#include <libcamera/controls.h>\n>  #include <libcamera/request.h>\n>  #include <libcamera/stream.h>\n>\n> @@ -16,6 +19,7 @@\n>  #include \"media_device.h\"\n>  #include \"pipeline_handler.h\"\n>  #include \"utils.h\"\n> +#include \"v4l2_controls.h\"\n>  #include \"v4l2_videodevice.h\"\n>\n>  namespace libcamera {\n> @@ -35,6 +39,7 @@ public:\n>  \t\tdelete video_;\n>  \t}\n>\n> +\tint init(MediaEntity *entity);\n>  \tvoid bufferReady(Buffer *buffer);\n>\n>  \tV4L2VideoDevice *video_;\n> @@ -71,6 +76,8 @@ public:\n>  \tbool match(DeviceEnumerator *enumerator) override;\n>\n>  private:\n> +\tint processControls(UVCCameraData *data, Request *request);\n> +\n>  \tUVCCameraData *cameraData(const Camera *camera)\n>  \t{\n>  \t\treturn static_cast<UVCCameraData *>(\n> @@ -216,6 +223,54 @@ void PipelineHandlerUVC::stop(Camera *camera)\n>  \tPipelineHandler::stop(camera);\n>  }\n>\n> +int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)\n> +{\n> +\tV4L2ControlList controls;\n> +\n> +\tfor (auto it : request->controls()) {\n> +\t\tconst ControlInfo *ci = it.first;\n> +\t\tControlValue &value = it.second;\n\nIt would really be nice if we could move to a simple wrapper to\nreplace the typedef and be able to\n\n        for (Control ctrl : request->controls()) {\n                const ControlInfo *ci = ctrl->info();\n                ControlValue &value = ctrl->value();\n> +\n> +\t\tswitch (ci->id()) {\n> +\t\tcase Brightness:\n> +\t\t\tcontrols.add(V4L2_CID_BRIGHTNESS, value.getInt());\n> +\t\t\tbreak;\n> +\n> +\t\tcase Contrast:\n> +\t\t\tcontrols.add(V4L2_CID_CONTRAST, value.getInt());\n> +\t\t\tbreak;\n> +\n> +\t\tcase Saturation:\n> +\t\t\tcontrols.add(V4L2_CID_SATURATION, value.getInt());\n> +\t\t\tbreak;\n> +\n> +\t\tcase ManualExposure:\n> +\t\t\tcontrols.add(V4L2_CID_EXPOSURE_AUTO, 1);\n> +\t\t\tcontrols.add(V4L2_CID_EXPOSURE_ABSOLUTE, value.getInt());\n> +\t\t\tbreak;\n> +\n> +\t\tcase ManualGain:\n> +\t\t\tcontrols.add(V4L2_CID_GAIN, value.getInt());\n\nor even be able to\n                        ctrl.getInt()\n\n> +\t\t\tbreak;\n> +\n> +\t\tdefault:\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n\nWill every pipeline handler have to do this translation by itself? I\nguess so, as each platform would map a Libcamera control to possibly\ndifferent controls or parameters..\n\n> +\n> +\tfor (const V4L2Control &ctrl : controls)\n> +\t\tLOG(UVC, Debug)\n> +\t\t\t<< \"Setting control 0x\"\n> +\t\t\t<< std::hex << std::setw(8) << ctrl.id() << std::dec\n> +\t\t\t<< \" to \" << ctrl.value();\n> +\n> +\tint ret = data->video_->setControls(&controls);\n> +\tif (ret)\n> +\t\tLOG(UVC, Error) << \"Failed to set controls\";\n\nPrint out the return value as it would tell which control has failed\n\n> +\n> +\treturn ret;\n> +}\n> +\n>  int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request)\n>  {\n>  \tUVCCameraData *data = cameraData(camera);\n> @@ -227,7 +282,11 @@ int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request)\n>  \t\treturn -ENOENT;\n>  \t}\n>\n> -\tint ret = data->video_->queueBuffer(buffer);\n> +\tint ret = processControls(data, request);\n> +\tif (ret < 0)\n\nNot just < 0, as V4L2Device::setControls() can return a positive\ninteger\n\n> +\t\treturn ret;\n> +\n> +\tret = data->video_->queueBuffer(buffer);\n>  \tif (ret < 0)\n>  \t\treturn ret;\n>\n> @@ -247,24 +306,14 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n>\n>  \tstd::unique_ptr<UVCCameraData> data = utils::make_unique<UVCCameraData>(this);\n>\n> -\t/* Locate and open the default video node. */\n> +\t/* Locate and initialise the camera data with the default video node. */\n>  \tfor (MediaEntity *entity : media->entities()) {\n>  \t\tif (entity->flags() & MEDIA_ENT_FL_DEFAULT) {\n> -\t\t\tdata->video_ = new V4L2VideoDevice(entity);\n> -\t\t\tbreak;\n> +\t\t\tif (data->init(entity))\n> +\t\t\t\treturn false;\n\nYou can break the loop here I guess\n\n>  \t\t}\n>  \t}\n>\n> -\tif (!data->video_) {\n> -\t\tLOG(UVC, Error) << \"Could not find a default video device\";\n> -\t\treturn false;\n> -\t}\n> -\n> -\tif (data->video_->open())\n> -\t\treturn false;\n> -\n> -\tdata->video_->bufferReady.connect(data.get(), &UVCCameraData::bufferReady);\n> -\n>  \t/* Create and register the camera. */\n>  \tstd::set<Stream *> streams{ &data->stream_ };\n>  \tstd::shared_ptr<Camera> camera = Camera::create(this, media->model(), streams);\n> @@ -276,6 +325,58 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n>  \treturn true;\n>  }\n>\n> +int UVCCameraData::init(MediaEntity *entity)\n> +{\n> +\tint ret;\n> +\n> +\t/* Create and open the video device. */\n> +\tvideo_ = new V4L2VideoDevice(entity);\n> +\tif (!video_) {\n> +\t\tLOG(UVC, Error) << \"Could not find a default video device\";\n\nUpdate the error message\n\n> +\t\treturn -ENODEV;\n> +\t}\n> +\n> +\tret = video_->open();\n> +\tif (ret)\n> +\t\treturn ret;\n> +\n> +\tvideo_->bufferReady.connect(this, &UVCCameraData::bufferReady);\n> +\n> +\t/* Initialise the supported controls. */\n> +\tconst V4L2ControlInfoMap &controls = video_->controls();\n> +\tfor (const auto &ctrl : controls) {\n> +\t\tunsigned int v4l2Id = ctrl.first;\n> +\t\tconst V4L2ControlInfo &info = ctrl.second;\n> +\t\tControlId id;\n> +\n> +\t\tswitch (v4l2Id) {\n> +\t\tcase V4L2_CID_BRIGHTNESS:\n> +\t\t\tid = Brightness;\n> +\t\t\tbreak;\n> +\t\tcase V4L2_CID_CONTRAST:\n> +\t\t\tid = Contrast;\n> +\t\t\tbreak;\n> +\t\tcase V4L2_CID_SATURATION:\n> +\t\t\tid = Saturation;\n> +\t\t\tbreak;\n> +\t\tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n> +\t\t\tid = ManualExposure;\n> +\t\t\tbreak;\n> +\t\tcase V4L2_CID_GAIN:\n> +\t\t\tid = ManualGain;\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tcontrolInfo_.emplace(std::piecewise_construct,\n> +\t\t\t\t     std::forward_as_tuple(id),\n> +\t\t\t\t     std::forward_as_tuple(id, info.min(), info.max()));\n\nAwesome! Thanks for clarifying offline.\n\nMinors apart, I'm happy with the direction this is taking, if not for\nthe fact we have to access maps with the horrible first and second\naccessors for both libcamera controls and v4l2 controls. A way to\nabstract that away would make this very nice.\n\nThanks\n   j\n\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n>  void UVCCameraData::bufferReady(Buffer *buffer)\n>  {\n>  \tRequest *request = queuedRequests_.front();\n> --\n> Regards,\n>\n> Laurent Pinchart\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net\n\t[217.70.183.195])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D839860BF8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  1 Jul 2019 19:02:36 +0200 (CEST)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 6CE0D6000C;\n\tMon,  1 Jul 2019 17:02:36 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Mon, 1 Jul 2019 19:03:53 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190701170353.6yuhbyzltip4gz4i@uno.localdomain>","References":"<20190630233817.10130-1-laurent.pinchart@ideasonboard.com>\n\t<20190630233817.10130-10-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"sr6n6avtwautmkfs\"","Content-Disposition":"inline","In-Reply-To":"<20190630233817.10130-10-laurent.pinchart@ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v3 09/14] libcamera: pipeline:\n\tuvcvideo: Add controls support","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 01 Jul 2019 17:02:37 -0000"}},{"id":2089,"web_url":"https://patchwork.libcamera.org/comment/2089/","msgid":"<20190701172055.GL5018@pendragon.ideasonboard.com>","date":"2019-07-01T17:20:55","subject":"Re: [libcamera-devel] [PATCH v3 09/14] libcamera: pipeline:\n\tuvcvideo: Add controls support","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Mon, Jul 01, 2019 at 07:03:53PM +0200, Jacopo Mondi wrote:\n> On Mon, Jul 01, 2019 at 02:38:12AM +0300, Laurent Pinchart wrote:\n> > From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> >\n> > Implement control support in the UVC pipeline handler by dynamically\n> > querying the V4L2 device for the supported V4L2 controls and populating\n> > the list of camera controls accordingly.\n> >\n> > Not-signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> Why so?\n\nI believe because the previous version was work in progress.\n\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/libcamera/pipeline/uvcvideo.cpp | 129 +++++++++++++++++++++++++---\n> >  1 file changed, 115 insertions(+), 14 deletions(-)\n> >\n> > diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp\n> > index 2e22523d7cb1..f68dc5bd6f74 100644\n> > --- a/src/libcamera/pipeline/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo.cpp\n> > @@ -6,8 +6,11 @@\n> >   */\n> >\n> >  #include <algorithm>\n> > +#include <iomanip>\n> > +#include <tuple>\n> >\n> >  #include <libcamera/camera.h>\n> > +#include <libcamera/controls.h>\n> >  #include <libcamera/request.h>\n> >  #include <libcamera/stream.h>\n> >\n> > @@ -16,6 +19,7 @@\n> >  #include \"media_device.h\"\n> >  #include \"pipeline_handler.h\"\n> >  #include \"utils.h\"\n> > +#include \"v4l2_controls.h\"\n> >  #include \"v4l2_videodevice.h\"\n> >\n> >  namespace libcamera {\n> > @@ -35,6 +39,7 @@ public:\n> >  \t\tdelete video_;\n> >  \t}\n> >\n> > +\tint init(MediaEntity *entity);\n> >  \tvoid bufferReady(Buffer *buffer);\n> >\n> >  \tV4L2VideoDevice *video_;\n> > @@ -71,6 +76,8 @@ public:\n> >  \tbool match(DeviceEnumerator *enumerator) override;\n> >\n> >  private:\n> > +\tint processControls(UVCCameraData *data, Request *request);\n> > +\n> >  \tUVCCameraData *cameraData(const Camera *camera)\n> >  \t{\n> >  \t\treturn static_cast<UVCCameraData *>(\n> > @@ -216,6 +223,54 @@ void PipelineHandlerUVC::stop(Camera *camera)\n> >  \tPipelineHandler::stop(camera);\n> >  }\n> >\n> > +int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)\n> > +{\n> > +\tV4L2ControlList controls;\n> > +\n> > +\tfor (auto it : request->controls()) {\n> > +\t\tconst ControlInfo *ci = it.first;\n> > +\t\tControlValue &value = it.second;\n> \n> It would really be nice if we could move to a simple wrapper to\n> replace the typedef and be able to\n> \n>         for (Control ctrl : request->controls()) {\n>                 const ControlInfo *ci = ctrl->info();\n>                 ControlValue &value = ctrl->value();\n\nWe could create a custom iterator whose first and second members would\nbe named info and value. Wanna give it a try ? :-)\n\n> > +\n> > +\t\tswitch (ci->id()) {\n> > +\t\tcase Brightness:\n> > +\t\t\tcontrols.add(V4L2_CID_BRIGHTNESS, value.getInt());\n> > +\t\t\tbreak;\n> > +\n> > +\t\tcase Contrast:\n> > +\t\t\tcontrols.add(V4L2_CID_CONTRAST, value.getInt());\n> > +\t\t\tbreak;\n> > +\n> > +\t\tcase Saturation:\n> > +\t\t\tcontrols.add(V4L2_CID_SATURATION, value.getInt());\n> > +\t\t\tbreak;\n> > +\n> > +\t\tcase ManualExposure:\n> > +\t\t\tcontrols.add(V4L2_CID_EXPOSURE_AUTO, 1);\n> > +\t\t\tcontrols.add(V4L2_CID_EXPOSURE_ABSOLUTE, value.getInt());\n> > +\t\t\tbreak;\n> > +\n> > +\t\tcase ManualGain:\n> > +\t\t\tcontrols.add(V4L2_CID_GAIN, value.getInt());\n> \n> or even be able to\n>                         ctrl.getInt()\n> \n> > +\t\t\tbreak;\n> > +\n> > +\t\tdefault:\n> > +\t\t\tbreak;\n> > +\t\t}\n> > +\t}\n> \n> Will every pipeline handler have to do this translation by itself? I\n> guess so, as each platform would map a Libcamera control to possibly\n> different controls or parameters..\n\nYes and no. The IPU3 and RkISP1 pipeline handlers won't use V4L2 for\ncontrols. For UVC and VIMC there's indeed some overlap, and I think\nhelpers would make sense, but it's a bit early to define an API for\nthese helpers. I think we need to play a bit with controls first.\n\n> > +\n> > +\tfor (const V4L2Control &ctrl : controls)\n> > +\t\tLOG(UVC, Debug)\n> > +\t\t\t<< \"Setting control 0x\"\n> > +\t\t\t<< std::hex << std::setw(8) << ctrl.id() << std::dec\n> > +\t\t\t<< \" to \" << ctrl.value();\n> > +\n> > +\tint ret = data->video_->setControls(&controls);\n> > +\tif (ret)\n> > +\t\tLOG(UVC, Error) << \"Failed to set controls\";\n> \n> Print out the return value as it would tell which control has failed\n> \n> > +\n> > +\treturn ret;\n> > +}\n> > +\n> >  int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request)\n> >  {\n> >  \tUVCCameraData *data = cameraData(camera);\n> > @@ -227,7 +282,11 @@ int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request)\n> >  \t\treturn -ENOENT;\n> >  \t}\n> >\n> > -\tint ret = data->video_->queueBuffer(buffer);\n> > +\tint ret = processControls(data, request);\n> > +\tif (ret < 0)\n> \n> Not just < 0, as V4L2Device::setControls() can return a positive\n> integer\n\nI will instead return -EINVAL in processControls() if ret > 0, as we\ndon't want to propagate positive values up.\n\n> > +\t\treturn ret;\n> > +\n> > +\tret = data->video_->queueBuffer(buffer);\n> >  \tif (ret < 0)\n> >  \t\treturn ret;\n> >\n> > @@ -247,24 +306,14 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> >\n> >  \tstd::unique_ptr<UVCCameraData> data = utils::make_unique<UVCCameraData>(this);\n> >\n> > -\t/* Locate and open the default video node. */\n> > +\t/* Locate and initialise the camera data with the default video node. */\n> >  \tfor (MediaEntity *entity : media->entities()) {\n> >  \t\tif (entity->flags() & MEDIA_ENT_FL_DEFAULT) {\n> > -\t\t\tdata->video_ = new V4L2VideoDevice(entity);\n> > -\t\t\tbreak;\n> > +\t\t\tif (data->init(entity))\n> > +\t\t\t\treturn false;\n> \n> You can break the loop here I guess\n> \n> >  \t\t}\n> >  \t}\n> >\n> > -\tif (!data->video_) {\n> > -\t\tLOG(UVC, Error) << \"Could not find a default video device\";\n> > -\t\treturn false;\n> > -\t}\n> > -\n> > -\tif (data->video_->open())\n> > -\t\treturn false;\n> > -\n> > -\tdata->video_->bufferReady.connect(data.get(), &UVCCameraData::bufferReady);\n> > -\n> >  \t/* Create and register the camera. */\n> >  \tstd::set<Stream *> streams{ &data->stream_ };\n> >  \tstd::shared_ptr<Camera> camera = Camera::create(this, media->model(), streams);\n> > @@ -276,6 +325,58 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> >  \treturn true;\n> >  }\n> >\n> > +int UVCCameraData::init(MediaEntity *entity)\n> > +{\n> > +\tint ret;\n> > +\n> > +\t/* Create and open the video device. */\n> > +\tvideo_ = new V4L2VideoDevice(entity);\n> > +\tif (!video_) {\n> > +\t\tLOG(UVC, Error) << \"Could not find a default video device\";\n> \n> Update the error message\n\nMore than that, the above function needs this error check after the\nloop.\n\n        if (!data) {\n                LOG(UVC, Error) << \"Could not find a default video device\";\n                return -ENODEV;\n        }\n\n> > +\t\treturn -ENODEV;\n> > +\t}\n> > +\n> > +\tret = video_->open();\n> > +\tif (ret)\n> > +\t\treturn ret;\n> > +\n> > +\tvideo_->bufferReady.connect(this, &UVCCameraData::bufferReady);\n> > +\n> > +\t/* Initialise the supported controls. */\n> > +\tconst V4L2ControlInfoMap &controls = video_->controls();\n> > +\tfor (const auto &ctrl : controls) {\n> > +\t\tunsigned int v4l2Id = ctrl.first;\n> > +\t\tconst V4L2ControlInfo &info = ctrl.second;\n> > +\t\tControlId id;\n> > +\n> > +\t\tswitch (v4l2Id) {\n> > +\t\tcase V4L2_CID_BRIGHTNESS:\n> > +\t\t\tid = Brightness;\n> > +\t\t\tbreak;\n> > +\t\tcase V4L2_CID_CONTRAST:\n> > +\t\t\tid = Contrast;\n> > +\t\t\tbreak;\n> > +\t\tcase V4L2_CID_SATURATION:\n> > +\t\t\tid = Saturation;\n> > +\t\t\tbreak;\n> > +\t\tcase V4L2_CID_EXPOSURE_ABSOLUTE:\n> > +\t\t\tid = ManualExposure;\n> > +\t\t\tbreak;\n> > +\t\tcase V4L2_CID_GAIN:\n> > +\t\t\tid = ManualGain;\n> > +\t\t\tbreak;\n> > +\t\tdefault:\n> > +\t\t\tcontinue;\n> > +\t\t}\n> > +\n> > +\t\tcontrolInfo_.emplace(std::piecewise_construct,\n> > +\t\t\t\t     std::forward_as_tuple(id),\n> > +\t\t\t\t     std::forward_as_tuple(id, info.min(), info.max()));\n> \n> Awesome! Thanks for clarifying offline.\n> \n> Minors apart, I'm happy with the direction this is taking, if not for\n> the fact we have to access maps with the horrible first and second\n> accessors for both libcamera controls and v4l2 controls. A way to\n> abstract that away would make this very nice.\n> \n> > +\t}\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> >  void UVCCameraData::bufferReady(Buffer *buffer)\n> >  {\n> >  \tRequest *request = queuedRequests_.front();","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["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 6B8BC60BF8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  1 Jul 2019 19:21:15 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 12EA1524;\n\tMon,  1 Jul 2019 19:21:15 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1562001675;\n\tbh=Cg4EKL4Ftx2DWt/LWiY27IZIlzfxOsRmj3txRz516kY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=uTYTTxphcnS0T9BmM4gWdjLeOuKb13/gOEs5GiKNd53L805fVy42E+Sd7rfIITsIl\n\tlAUcAtf9YY3DF9mrHxjD+tE//VwYYwdTXQZ+m9B+vZIJuCC8MdAadNweQrt/qnlfFq\n\t17/exDIxe+2ibynfRahLAxUf41mfBGMvqtK5r8R8=","Date":"Mon, 1 Jul 2019 20:20:55 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190701172055.GL5018@pendragon.ideasonboard.com>","References":"<20190630233817.10130-1-laurent.pinchart@ideasonboard.com>\n\t<20190630233817.10130-10-laurent.pinchart@ideasonboard.com>\n\t<20190701170353.6yuhbyzltip4gz4i@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190701170353.6yuhbyzltip4gz4i@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v3 09/14] libcamera: pipeline:\n\tuvcvideo: Add controls support","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 01 Jul 2019 17:21:15 -0000"}}]