From patchwork Sat Sep 3 18:10:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17288 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6A74EC3272 for ; Sat, 3 Sep 2022 18:10:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 375B76203C; Sat, 3 Sep 2022 20:10:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1662228654; bh=eMGSi/27H+OU236Wr8sTP2VnIhK3fDLlkmTXN6wvgBM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=K8rWVZiq6NVPiOB3zVsTZ+fwADIKvdEFMmKpi35XKVqj5WQrvHBwvqc4HvKiMWJgP xKswp/eaSwqTB1QBz9be77Yy92Lqwe6w8DrJvsLyz9R2Sb3gQgtEZsI+OkXBdynL3R kfISr4Np/z/kHM2hsxa9ZsyTfPlFA2kcvk7fDYlgX7XBuH1Kzr5aGb3vUIRzIQuU3s ym6UDtXGM5RCqCv08mAQ2gYreA6M1adIUsAm2IN0ow5XstQAPf164SW6bMcOsud0sI w6wRhR1N1GLZVrfGsipRS6G9MActFMG0b54yFJHF31PTQqwN5Mat2meISQe0KV30hL x+XxlQevUkM8Q== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C9C9D6203C for ; Sat, 3 Sep 2022 20:10:51 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="JMo2tXtX"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4F3024A8; Sat, 3 Sep 2022 20:10:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1662228651; bh=eMGSi/27H+OU236Wr8sTP2VnIhK3fDLlkmTXN6wvgBM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JMo2tXtXP44PwLB9vpwsQmYpWbIA6If/anQjfeoMNNmhDqgUEb3HPvOP2e9I7bGEl YtkONLsNvUgAdfET6+wuNU3i74vO34DHH3BTPOIQ4WsRGp6kEv8zWmBP+BoGmIrOku Vjco/pEiM+SbaHDvrN0xbWGZ91I+3k4bqrLhaRDI= To: libcamera-devel@lists.libcamera.org Date: Sat, 3 Sep 2022 21:10:35 +0300 Message-Id: <20220903181037.1406-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> References: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/3] pipeline: uvcvideo: Move camera ID generation to UVCCameraData class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the camera ID generation to UVCCameraData, and cache the ID in that class. This will be useful to access the ID in multiple locations, such as when printing error messages. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 149 ++++++++++--------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 2ae640a31f68..22b67faf309e 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -46,8 +46,15 @@ public: ControlInfoMap::Map *ctrls); void bufferReady(FrameBuffer *buffer); + const std::string &id() const { return id_; } + std::unique_ptr video_; Stream stream_; + +private: + bool generateId(); + + std::string id_; }; class UVCCameraConfiguration : public CameraConfiguration @@ -81,8 +88,6 @@ public: bool match(DeviceEnumerator *enumerator) override; private: - std::string generateId(const UVCCameraData *data); - int processControl(ControlList *controls, unsigned int id, const ControlValue &value); int processControls(UVCCameraData *data, Request *request); @@ -384,69 +389,6 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request) return 0; } -std::string PipelineHandlerUVC::generateId(const UVCCameraData *data) -{ - const std::string path = data->video_->devicePath(); - - /* Create a controller ID from first device described in firmware. */ - std::string controllerId; - std::string searchPath = path; - while (true) { - std::string::size_type pos = searchPath.rfind('/'); - if (pos <= 1) { - LOG(UVC, Error) << "Can not find controller ID"; - return {}; - } - - searchPath = searchPath.substr(0, pos); - - controllerId = sysfs::firmwareNodePath(searchPath); - if (!controllerId.empty()) - break; - } - - /* - * Create a USB ID from the device path which has the known format: - * - * path = bus, "-", ports, ":", config, ".", interface ; - * bus = number ; - * ports = port, [ ".", ports ] ; - * port = number ; - * config = number ; - * interface = number ; - * - * Example: 3-2.4:1.0 - * - * The bus is not guaranteed to be stable and needs to be stripped from - * the USB ID. The final USB ID is built up of the ports, config and - * interface properties. - * - * Example 2.4:1.0. - */ - std::string usbId = utils::basename(path.c_str()); - usbId = usbId.substr(usbId.find('-') + 1); - - /* Creata a device ID from the USB devices vendor and product ID. */ - std::string deviceId; - for (const char *name : { "idVendor", "idProduct" }) { - std::ifstream file(path + "/../" + name); - - if (!file.is_open()) - return {}; - - std::string value; - std::getline(file, value); - file.close(); - - if (!deviceId.empty()) - deviceId += ":"; - - deviceId += value; - } - - return controllerId + "-" + usbId + "-" + deviceId; -} - bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) { MediaDevice *media; @@ -462,12 +404,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) return false; /* Create and register the camera. */ - std::string id = generateId(data.get()); - if (id.empty()) { - LOG(UVC, Error) << "Failed to generate camera ID"; - return false; - } - + std::string id = data->id(); std::set streams{ &data->stream_ }; std::shared_ptr camera = Camera::create(std::move(data), id, streams); @@ -502,6 +439,12 @@ int UVCCameraData::init(MediaDevice *media) video_->bufferReady.connect(this, &UVCCameraData::bufferReady); + /* Generate the camera ID. */ + if (!generateId()) { + LOG(UVC, Error) << "Failed to generate camera ID"; + return -EINVAL; + } + properties_.set(properties::Model, utils::toAscii(media->model())); /* @@ -563,6 +506,70 @@ int UVCCameraData::init(MediaDevice *media) return 0; } +bool UVCCameraData::generateId() +{ + const std::string path = video_->devicePath(); + + /* Create a controller ID from first device described in firmware. */ + std::string controllerId; + std::string searchPath = path; + while (true) { + std::string::size_type pos = searchPath.rfind('/'); + if (pos <= 1) { + LOG(UVC, Error) << "Can not find controller ID"; + return false; + } + + searchPath = searchPath.substr(0, pos); + + controllerId = sysfs::firmwareNodePath(searchPath); + if (!controllerId.empty()) + break; + } + + /* + * Create a USB ID from the device path which has the known format: + * + * path = bus, "-", ports, ":", config, ".", interface ; + * bus = number ; + * ports = port, [ ".", ports ] ; + * port = number ; + * config = number ; + * interface = number ; + * + * Example: 3-2.4:1.0 + * + * The bus is not guaranteed to be stable and needs to be stripped from + * the USB ID. The final USB ID is built up of the ports, config and + * interface properties. + * + * Example 2.4:1.0. + */ + std::string usbId = utils::basename(path.c_str()); + usbId = usbId.substr(usbId.find('-') + 1); + + /* Creata a device ID from the USB devices vendor and product ID. */ + std::string deviceId; + for (const char *name : { "idVendor", "idProduct" }) { + std::ifstream file(path + "/../" + name); + + if (!file.is_open()) + return false; + + std::string value; + std::getline(file, value); + file.close(); + + if (!deviceId.empty()) + deviceId += ":"; + + deviceId += value; + } + + id_ = controllerId + "-" + usbId + "-" + deviceId; + return true; +} + void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info, ControlInfoMap::Map *ctrls) { From patchwork Sat Sep 3 18:10:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17289 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 434E3C327D for ; Sat, 3 Sep 2022 18:10:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AB3E562041; Sat, 3 Sep 2022 20:10:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1662228654; bh=h+Ea5s0Py13CdWRkDEd6pdhtJD2qNog0XbZAWrjL24o=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ucgzWyxptvwUNRR/N+udfmSX9DTvDp9NK7lMwoowaj+2nPfK/hpituv47V72bfyTj PsTUlOvTlRzFpNls7RIBteEg5Ff2ubkoVJEhh8btelIExN7AZ9csbsvzujtv6PvqhT 61B7O/KKmdlTNVbezicKSA9bqK2wpj/H3YBb1yfMe2LfKAVYFkHbCNMCcAQ0RyhcXs DOHww0VlTkb9j76tuAR3VSTOWPm/3tGUSD8iCeOhMc9iKZojK4+65QqSnkMGP6rgG2 MPbO30DafDPCiY3Mv5XWc13D+0qBKHsRCCmxZqlmh02kB0RJYhx6/OJIPhijd+0GRc 5+BxD4rbrgZew== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4455F62033 for ; Sat, 3 Sep 2022 20:10:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ISZQg2oV"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C147751E; Sat, 3 Sep 2022 20:10:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1662228653; bh=h+Ea5s0Py13CdWRkDEd6pdhtJD2qNog0XbZAWrjL24o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ISZQg2oVcxde0lZGgZu5a1QNZXwcFcyKMrlF729ekz1NPMyWYZjdlzUWkl5foJShO vYnvPQTwY2N9htfekLxpzYfIG2zQd+qblEJ1Z2rQWomyOOSR3LzlE7YU11vEkF/o9p z99Vx64Rod+N7d3jEa6YP99Zr8pvPfCrQWqxP5UY= To: libcamera-devel@lists.libcamera.org Date: Sat, 3 Sep 2022 21:10:36 +0300 Message-Id: <20220903181037.1406-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> References: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/3] pipeline: uvcvideo: Cache supported formats in UVCCameraData X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Populate and cache the list of supported formats in UVCCameraData::init(), to avoid repeating the operation every time generateConfiguration() is called. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 44 ++++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 22b67faf309e..be0fbaea508a 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -50,6 +50,7 @@ public: std::unique_ptr video_; Stream stream_; + std::map> formats_; private: bool generateId(); @@ -186,15 +187,7 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, if (roles.empty()) return config; - V4L2VideoDevice::Formats v4l2Formats = data->video_->formats(); - std::map> deviceFormats; - for (const auto &format : v4l2Formats) { - PixelFormat pixelFormat = format.first.toPixelFormat(); - if (pixelFormat.isValid()) - deviceFormats[pixelFormat] = format.second; - } - - StreamFormats formats(deviceFormats); + StreamFormats formats(data->formats_); StreamConfiguration cfg(formats); cfg.pixelFormat = formats.pixelformats().front(); @@ -445,6 +438,26 @@ int UVCCameraData::init(MediaDevice *media) return -EINVAL; } + /* + * Populate the map of supported formats, and infer the camera sensor + * resolution from the largest size it advertises. + */ + Size resolution; + for (const auto &format : video_->formats()) { + PixelFormat pixelFormat = format.first.toPixelFormat(); + if (!pixelFormat.isValid()) + continue; + + formats_[pixelFormat] = format.second; + + const std::vector &sizeRanges = format.second; + for (const SizeRange &sizeRange : sizeRanges) { + if (sizeRange.max > resolution) + resolution = sizeRange.max; + } + } + + /* Populate the camera properties. */ properties_.set(properties::Model, utils::toAscii(media->model())); /* @@ -475,19 +488,6 @@ int UVCCameraData::init(MediaDevice *media) properties_.set(properties::Location, location); - /* - * Get the current format in order to initialize the sensor array - * properties. - */ - Size resolution; - for (const auto &it : video_->formats()) { - const std::vector &sizeRanges = it.second; - for (const SizeRange &sizeRange : sizeRanges) { - if (sizeRange.max > resolution) - resolution = sizeRange.max; - } - } - properties_.set(properties::PixelArraySize, resolution); properties_.set(properties::PixelArrayActiveAreas, { Rectangle(resolution) }); From patchwork Sat Sep 3 18:10:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17290 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 5AB74C3272 for ; Sat, 3 Sep 2022 18:10:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0C67862048; Sat, 3 Sep 2022 20:10:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1662228657; bh=YoHGUU+J9t51mCK0KvdpqzuRO7l4o4hUUuhgOmBgcf8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Ef09zyUNhYWbvyZVDcVLT++d9PXNhfyC8+S4tordDqS5UkZLi1/kM3dB+c0i5edIx 8ZWWDeXZ7PQrwsMeMd52T7YNzWqbBNCdDmR0izt6rTqc3adVEUmKJExZwTiqTX0R0I 1c2a0b0hqBmHa1MgP0QiIdJyALhJM0lTIGgnujeO918qlyKlLFq0UFx5TXxtvgVkLS MeupuG+nG3JkjC6YQ2qRwcgGDYw2p1wyAy4LFFCIo0EXO/Ar7KhmdBxqsFbufRG+pB WhjkFTPzTfUAbhftxTMGycrcG+M4zlBMWoH53aLz18aPXn49McEwPo5cB7l0cWoQII p//BP519xr8kg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 97EF562033 for ; Sat, 3 Sep 2022 20:10:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DY5ie0OA"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1FC6F51E; Sat, 3 Sep 2022 20:10:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1662228654; bh=YoHGUU+J9t51mCK0KvdpqzuRO7l4o4hUUuhgOmBgcf8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DY5ie0OAsm+mMlutpEtOp88T88XCcUFdMsxetb0FlvmpVvLfqmBPi+njlj/OmC8xI KBmQT1LZI1KGsSFC/QYN5OUFPdIJn2jekJq9Bwfkw4N+h9HLOZEGqiIut/+W1d8A+A VDNoO61FQW2ZkmfuTWWZMRDdUpJJglXvrNp6Nfxs= To: libcamera-devel@lists.libcamera.org Date: Sat, 3 Sep 2022 21:10:37 +0300 Message-Id: <20220903181037.1406-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> References: <20220903181037.1406-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/3] pipeline: uvcvideo: Fail match() if the camera has no supported format X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A UVC device could expose only formats that are not supported by libcamera. The pipeline handler doesn't currently consider this as an error, and happily creates a camera. The camera won't be usable, and worse, generateConfiguration() and validate() will crash as those functions assume that at least one format is supported. Fix this by failing match() if none of the formats exposed by the camera are supported. Log an error message in that case to notify the user. Bug: https://bugs.libcamera.org/show_bug.cgi?id=145 Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index be0fbaea508a..a28195450634 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -457,6 +457,13 @@ int UVCCameraData::init(MediaDevice *media) } } + if (formats_.empty()) { + LOG(UVC, Error) + << "Camera " << id_ << " (" << media->model() + << ") doesn't expose any supported format"; + return -EINVAL; + } + /* Populate the camera properties. */ properties_.set(properties::Model, utils::toAscii(media->model()));