From patchwork Wed Aug 20 13:23:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 24168 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 DFBDEBD87C for ; Wed, 20 Aug 2025 13:23:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1B35C692DD; Wed, 20 Aug 2025 15:23:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="aTrKZx6i"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5EEDD6925D for ; Wed, 20 Aug 2025 15:23:37 +0200 (CEST) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BF45D6AF; Wed, 20 Aug 2025 15:22:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755696158; bh=SfG9M9QxXbOfLKLfb9ULC3+cwJExQNZdq4HRuBotRFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aTrKZx6iCy7WBAHZVkECWZbFblFYYsord2Po9iQ3v7DWqcgSaue28D6IyUOSnmEk9 duBXF2jXMe7+CPe//jtOe7LtPM8tlnEjjlcEvf8Oo3XxZ3651T/J/9vzIBLtTvdbr2 U+7C15Z1LQkp14NtuEGpA2JkyG6prrLgWM3zQfeA= From: Daniel Scally To: libcamera-devel@lists.libcamera.org Cc: dan.scally@ideasonboard.com Subject: [PATCH 3/3] libcamera: device_enumerator_udev: Defer invalid media devices Date: Wed, 20 Aug 2025 14:23:16 +0100 Message-ID: <20250820132316.1033443-4-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250820132316.1033443-1-dan.scally@ideasonboard.com> References: <20250820132316.1033443-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A MediaDevice created by DeviceEnumeratorUdev may have an invalid topology if the device nodes for some of its entities have not yet been created. If that's the case, defer initialisation of the MediaDevice. Re-try all deferred media devices whenever a new device is added to see if they're ready to be initialised yet. Signed-off-by: Daniel Scally --- .../internal/device_enumerator_udev.h | 2 + src/libcamera/device_enumerator.cpp | 2 +- src/libcamera/device_enumerator_udev.cpp | 37 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h index a5e5e6efe..b76315c63 100644 --- a/include/libcamera/internal/device_enumerator_udev.h +++ b/include/libcamera/internal/device_enumerator_udev.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "libcamera/internal/device_enumerator.h" @@ -67,6 +68,7 @@ private: EventNotifier *notifier_; std::set orphans_; + std::vector> topologyPending_; std::list pending_; std::map devMap_; }; diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index ae17862f6..ab7bceec4 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -220,7 +220,7 @@ std::unique_ptr DeviceEnumerator::createDevice(const std::string &d std::unique_ptr media = std::make_unique(deviceNode); int ret = media->populate(); - if (ret < 0) { + if (ret < 0 && ret != -EAGAIN) { LOG(DeviceEnumerator, Info) << "Unable to populate media device " << deviceNode << " (" << strerror(-ret) << "), skipping"; diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp index 53b4fac80..631e583e7 100644 --- a/src/libcamera/device_enumerator_udev.cpp +++ b/src/libcamera/device_enumerator_udev.cpp @@ -82,6 +82,14 @@ int DeviceEnumeratorUdev::addUdevDevice(struct udev_device *dev) if (!media) return -ENODEV; + if (!media->isValid()) { + LOG(DeviceEnumerator, Debug) + << "Defer media device " << media->deviceNode() + << " due to an invalid topology"; + topologyPending_.emplace_back(std::move(media)); + return 0; + } + return initMediaDevice(std::move(media)); } @@ -353,6 +361,35 @@ void DeviceEnumeratorUdev::udevNotify() << action << " device " << deviceNode; if (action == "add") { + /* + * The addition of a new device may signal that a previously + * deferred media device has had its topology updated to the + * extent that it's now valid - retry devices deferred due to + * invalid topology to see if they're now ready. + */ + + LOG(DeviceEnumerator, Debug) + << "Re-evaluating " << topologyPending_.size() + << " deferred media devices"; + + for (auto media = topologyPending_.begin(); + media != topologyPending_.end(); ++media) { + LOG(DeviceEnumerator, Debug) + << "Evaluating media device " << (*media)->deviceNode() + << " again..."; + + int ret = (*media)->populate(); + if (ret == -EAGAIN) { + LOG(DeviceEnumerator, Debug) + << "Media device " << (*media)->deviceNode() + << " still has invalid topology"; + continue; + } + + initMediaDevice(std::move(*media)); + topologyPending_.erase(media); + } + addUdevDevice(dev); } else if (action == "remove") { const char *subsystem = udev_device_get_subsystem(dev);