[{"id":14423,"web_url":"https://patchwork.libcamera.org/comment/14423/","msgid":"<X+zaxvxWfayjmVKx@pendragon.ideasonboard.com>","date":"2020-12-30T19:53:42","subject":"Re: [libcamera-devel] [PATCH v3 2/6] libcamera: camera_sensor:\n\tValidate driver support","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Wed, Dec 30, 2020 at 07:01:16PM +0100, Jacopo Mondi wrote:\n> The CameraSensor class requires the sensor driver to report\n> information through V4L2 controls and through the V4L2 selection API,\n> and uses that information to register Camera properties and to\n> construct CameraSensorInfo class instances to provide them to the IPA.\n> \n> Currently, validation of the kernel support happens each time a\n> feature is requested, with slighly similar debug/error messages\n> output to the user in case a feature is not supported.\n> \n> Rationalize this by:\n> - Validate the sensor driver requirements in a single function\n> - Expand the debug output when a property gets defaulted to a value\n> - Be more verbose when constructing CameraSensorInfo is not possible\n> \n> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  include/libcamera/internal/camera_sensor.h |   1 +\n>  src/libcamera/camera_sensor.cpp            | 117 ++++++++++++++++++---\n>  2 files changed, 102 insertions(+), 16 deletions(-)\n> \n> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\n> index f80d836161a5..aee10aa6e3c7 100644\n> --- a/include/libcamera/internal/camera_sensor.h\n> +++ b/include/libcamera/internal/camera_sensor.h\n> @@ -69,6 +69,7 @@ protected:\n>  \n>  private:\n>  \tint generateId();\n> +\tint validateSensorDriver();\n>  \tint initProperties();\n>  \n>  \tconst MediaEntity *entity_;\n> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp\n> index e786821d4ba2..a1f1256bd6f4 100644\n> --- a/src/libcamera/camera_sensor.cpp\n> +++ b/src/libcamera/camera_sensor.cpp\n> @@ -207,6 +207,10 @@ int CameraSensor::init()\n>  \t */\n>  \tresolution_ = sizes_.back();\n>  \n> +\tret = validateSensorDriver();\n> +\tif (ret)\n> +\t\treturn ret;\n> +\n>  \tret = initProperties();\n>  \tif (ret)\n>  \t\treturn ret;\n> @@ -214,6 +218,86 @@ int CameraSensor::init()\n>  \treturn 0;\n>  }\n>  \n> +int CameraSensor::validateSensorDriver()\n> +{\n> +\t/*\n> +\t * Make sure the sensor driver supports the mandatory controls\n> +\t * required by the CameraSensor class.\n> +\t * - V4L2_CID_PIXEL_RATE is used to calculate the sensor timings\n> +\t * - V4L2_CID_HBLANK is used to calculate the line length\n> +\t */\n> +\tconst std::vector<uint32_t> mandatoryControls{\n> +\t\tV4L2_CID_PIXEL_RATE,\n> +\t\tV4L2_CID_HBLANK,\n> +\t};\n> +\n> +\tControlList ctrls = subdev_->getControls(mandatoryControls);\n> +\tif (ctrls.empty()) {\n> +\t\tLOG(CameraSensor, Error)\n> +\t\t\t<< \"Mandatory V4L2 controls not available\";\n> +\t\tLOG(CameraSensor, Error)\n> +\t\t\t<< \"The sensor kernel driver needs to be fixed\";\n> +\t\tLOG(CameraSensor, Error)\n> +\t\t\t<< \"See Documentation/sensor_driver_requirements.rst in the libcamera sources for more information\";\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tint err = 0;\n> +\t/*\n> +\t * Optional controls are used to register optional sensor\n> +\t * properties. If not present, some values will be defaulted.\n\nYou could wrap less agressively if desired :-)\n\n> +\t */\n> +\tconst std::vector<uint32_t> optionalControls{\n> +\t\tV4L2_CID_CAMERA_ORIENTATION,\n> +\t\tV4L2_CID_CAMERA_SENSOR_ROTATION,\n> +\t};\n> +\n> +\tctrls = subdev_->getControls(optionalControls);\n> +\tif (ctrls.empty()) {\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"Optional V4L2 controls not supported\";\n> +\t\terr = -EINVAL;\n\nIt's valid for those controls not to be reported by the kernel, as\nthey're not always available in the firmware. I'd thus make this a debug\nmessage, and not touch err, to void printing the messages at the end.\n\n> +\t}\n> +\n> +\t/*\n> +\t * Make sure the required selection targets are supported.\n> +\t *\n> +\t * Failures in reading any of the targets are not deemed to be fatal,\n> +\t * but some properties and features, like constructing a\n> +\t * CameraSensorInfo for the IPA module, won't be supported.\n> +\t */\n> +\tRectangle rect;\n> +\tint ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_BOUNDS, &rect);\n> +\tif (ret) {\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"Failed to retrieve the readable pixel area size\";\n\nWe write \"pixel array\" in the properties definitions, I'd do the same\nhere (and below as well).\n\n> +\t\terr = -EINVAL;\n> +\t}\n> +\n> +\tret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_DEFAULT, &rect);\n> +\tif (ret) {\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"Failed to retrieve the active pixel area size\";\n> +\t\terr = -EINVAL;\n> +\t}\n> +\n> +\tret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP, &rect);\n> +\tif (ret) {\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"Failed to retreive the sensor crop rectangle\";\n> +\t\terr = -EINVAL;\n> +\t}\n> +\n> +\tif (err) {\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"The sensor kernel driver needs to be fixed\";\n> +\t\tLOG(CameraSensor, Info)\n> +\t\t\t<< \"See Documentation/sensor_driver_requirements.rst in the libcamera sources for more information\";\n\nHow about making all these warnings already, so that the only thing\nwe'll need to do is add a return err here ?\n\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n>  int CameraSensor::initProperties()\n>  {\n>  \t/*\n> @@ -278,21 +362,29 @@ int CameraSensor::initProperties()\n>  \t\t}\n>  \t} else {\n>  \t\tpropertyValue = properties::CameraLocationFront;\n> +\t\tLOG(CameraSensor, Debug)\n> +\t\t\t<< \"Location property defaulted to 'Front Camera'\";\n>  \t}\n>  \tproperties_.set(properties::Location, propertyValue);\n>  \n>  \t/* Camera Rotation: default is 0 degrees. */\n>  \tconst auto &rotationControl = controls.find(V4L2_CID_CAMERA_SENSOR_ROTATION);\n> -\tif (rotationControl != controls.end())\n> +\tif (rotationControl != controls.end()) {\n>  \t\tpropertyValue = rotationControl->second.def().get<int32_t>();\n> -\telse\n> +\t} else {\n>  \t\tpropertyValue = 0;\n> +\t\tLOG(CameraSensor, Debug)\n> +\t\t\t<< \"Rotation property defaulted to 0 degrees\";\n> +\t}\n>  \tproperties_.set(properties::Rotation, propertyValue);\n>  \n>  \tRectangle bounds;\n>  \tret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_BOUNDS, &bounds);\n>  \tif (!ret)\n>  \t\tproperties_.set(properties::PixelArraySize, bounds.size());\n> +\telse\n> +\t\tLOG(CameraSensor, Debug)\n> +\t\t\t<< \"PixelArraySize property not registered\";\n\nI think we'll drop those messages when we will consider this a fatal\nerror, but that doesn't mean we can't have them in the meantime.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n>  \n>  \tRectangle crop;\n>  \tret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_DEFAULT, &crop);\n> @@ -306,6 +398,9 @@ int CameraSensor::initProperties()\n>  \t\tcrop.x -= bounds.x;\n>  \t\tcrop.y -= bounds.y;\n>  \t\tproperties_.set(properties::PixelArrayActiveAreas, { crop });\n> +\t} else {\n> +\t\tLOG(CameraSensor, Debug)\n> +\t\t\t<< \"PixelArrayActiveAreas property not registered\";\n>  \t}\n>  \n>  \t/* Color filter array pattern, register only for RAW sensors. */\n> @@ -566,10 +661,7 @@ int CameraSensor::sensorInfo(CameraSensorInfo *info) const\n>  \tRectangle rect;\n>  \tint ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_DEFAULT, &rect);\n>  \tif (ret) {\n> -\t\tLOG(CameraSensor, Error)\n> -\t\t\t<< \"Failed to construct camera sensor info: \"\n> -\t\t\t<< \"the camera sensor does not report the active area\";\n> -\n> +\t\tLOG(CameraSensor, Error) << \"Failed to get the active area\";\n>  \t\treturn ret;\n>  \t}\n>  \tinfo->activeAreaSize = { rect.width, rect.height };\n> @@ -577,9 +669,7 @@ int CameraSensor::sensorInfo(CameraSensorInfo *info) const\n>  \t/* It's mandatory for the subdevice to report its crop rectangle. */\n>  \tret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP, &info->analogCrop);\n>  \tif (ret) {\n> -\t\tLOG(CameraSensor, Error)\n> -\t\t\t<< \"Failed to construct camera sensor info: \"\n> -\t\t\t<< \"the camera sensor does not report the crop rectangle\";\n> +\t\tLOG(CameraSensor, Error) << \"Failed to get the crop rectangle\";\n>  \t\treturn ret;\n>  \t}\n>  \n> @@ -601,16 +691,11 @@ int CameraSensor::sensorInfo(CameraSensorInfo *info) const\n>  \tinfo->bitsPerPixel = format.bitsPerPixel();\n>  \tinfo->outputSize = format.size;\n>  \n> -\t/*\n> -\t * Retrieve the pixel rate and the line length through V4L2 controls.\n> -\t * Support for the V4L2_CID_PIXEL_RATE and V4L2_CID_HBLANK controls is\n> -\t * mandatory.\n> -\t */\n> +\t/* Retrieve the pixel rate and the line length through V4L2 controls. */\n>  \tControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,\n>  \t\t\t\t\t\t   V4L2_CID_HBLANK });\n>  \tif (ctrls.empty()) {\n> -\t\tLOG(CameraSensor, Error)\n> -\t\t\t<< \"Failed to retrieve camera info controls\";\n> +\t\tLOG(CameraSensor, Error) << \"Failed to retrieve camera controls\";\n>  \t\treturn -EINVAL;\n>  \t}\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 710D8C0F1A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 30 Dec 2020 19:53:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D5177615B4;\n\tWed, 30 Dec 2020 20:53:55 +0100 (CET)","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 544A960526\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 30 Dec 2020 20:53:54 +0100 (CET)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id B61E82A3;\n\tWed, 30 Dec 2020 20:53:53 +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=\"CA2rVTXJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1609358033;\n\tbh=OTsAqVYoIVtSPOpiFVvBhsyUdWeBmdLzvfhDcmzyG0Q=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=CA2rVTXJVvB7/4dghu7PBLeMoBjCN/BzC+fN166DVbxDPCoB3m0cr9Jm1H4pIYLXc\n\tbZDhYQX62I/OY0KUrWze3ky5YGGhL94/sWw0LEu72Sn4+HDyZb6n7eIBlnKr/iTORP\n\tJd784+xBCl1//P0IhYi/w0QTEnZMmCIGNrdT3TSY=","Date":"Wed, 30 Dec 2020 21:53:42 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<X+zaxvxWfayjmVKx@pendragon.ideasonboard.com>","References":"<20201230180120.78407-1-jacopo@jmondi.org>\n\t<20201230180120.78407-3-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20201230180120.78407-3-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v3 2/6] libcamera: camera_sensor:\n\tValidate driver support","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>","Cc":"libcamera-devel@lists.libcamera.org","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>"}}]