From patchwork Fri Sep 18 07:59:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 28313 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 11750BE175 for ; Fri, 18 Sep 2026 08:07:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 49A7268715; Fri, 18 Sep 2026 10:07:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="JJvnS8PL"; dkim-atps=neutral Received: from mail-wr2-x10.google.com (mail-wr2-x10.google.com [IPv6:2a00:1450:4864:30::10]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0EA91686C6 for ; Fri, 18 Sep 2026 10:07:39 +0200 (CEST) Received: by mail-wr2-x10.google.com with SMTP id ffacd0b85a97d-4843af75de5so45602f8f.3 for ; Fri, 18 Sep 2026 01:07:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1789718858; x=1790323658; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=pWte4PF2E/tGRz7BJM4oPrDJmjYKQaUPe9tX1qsF+8U=; b=JJvnS8PL+Qr8SHU0Eu0rqkTwfYidkZ0a1PMveg5rfeUUK1Q59hCQnA54NkH7fIlJWb /2WnK5qmWOYhKJuBQfzyXFmkaizWmzJmzreH4NWVVamSLWEerWqAzIhl26NTpaj+ZKij J0TKTVokP+IswGHmjcMlCKBRr1o81HkJNrA2V08UfAn4vuE+/0Jgk/mLu9fje7nf88b/ fZuXf0LE+0qWbnv7iAcFzRDTkuqO5YO2jeQhNMkfe6XY5Qc0o9HUPkya7+ySKRiVuY84 yuJv/mSPNrjUOwX9loP85eFWQei0cpbxq4IBZ3ZtqDtB987p4lDCpD1E4PE825RxlBGm vdrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789718858; x=1790323658; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=pWte4PF2E/tGRz7BJM4oPrDJmjYKQaUPe9tX1qsF+8U=; b=dZBPV0W3FWJ4RF+16StvehVFmAeRkRmOk8wayQEHIXmLxKlh60FKyFGXmVMFZPfxgh TVOPEdBQpFlpkBG/sS9nvtVn5q0abwjvH93GPfv2PmjggNLfk/qNYQF5qAjfBwonY+GA QXj69/6tcN+2Pp11hZu9UwIqJbGRlEPO0thuwB+DtL63TKlWWgPw7Dg8RZ4zaUAcjGA+ A/64Epms5YdRqn2pVMwuC/W2PwPhA0GGrvWYQBbagsxS54umB9yJCXLxj2m7Qw4wC+uB LGMtzpa6RE+NR5rdfSSSXwELnWMm9PAgr982BDRorrsxWh8i1BhgaiyCAWYQU/gf96pA Oxyw== X-Gm-Message-State: AFuF++nKDIOIpBTx4jD2AJHUNXo+DFdTAxefRMJv3yJeMDD8S6515g6z SShMT9al1vNmAAX8jVV36/jM1ZCrB2tdyra9Mt4/AwGyK6eN71cX/vrJpFN+nTIckdoKolOey2v WS7yJJo0= X-Gm-Gg: AYBFou2ZRV0RjuWhM9Qt3NguVnOzanDQIBHcJUoHvgvl6wHbfy/5f8jxDkwyl/o7v8J /kbOGemfHgzYm6Fo8iREPgfrLFVAIF2UrEe8HDyXwrbhZ/KIr/8lOnhKXjmpeYz6RLrjXJk5Fi+ /EO73KVscxM2nrEftH6n1YPOFIhhjyYyU4YRWjOJ/FILQ/jZjI90r3fUf0DxyzRWOO8lvs2fbyH e+UHjD15Qh3kfkgiMNl/qU95RqmhRjnGyh04oNxE1ZfPwQYwZifZCKb0ZRK7dAi7zfEWnRX8F7d vW6FkhTvlyEwVu/TBlcrRPqrXyMLdxpjnipbylAQff/bEVIyrP8xBwxrW7vA/SDtQ0YBIDMTfIZ NQs9xYlpoUuyEsvMVVsIWjfUPlDbGMkbdMjzVgOsEcbOhLCX4bW3B0OezGLSyeCcRFs+NSqSACy HBXGO2AR3/YKiBs3DgGBI+rULfa/+pCcLDUECR/CPBECwz/G9KvoVS1Z8D6tbEXFWj9DaOTg8tO 4xhyRUe7ZtWQa9eQHrXjp/IfZ9OHsHqfNC0WnamHWHbPwm14PjkfLNnj/2+AJRHl9ssCcyeVSo7 SihGV4ffH5SQODBAECF0A02AHFhawJTdi/o8p0sKEKV1/7Bq1Zv//ZersAZ6lT04To1X8qLnZrr iIuqQdSJG5o+Ovgm5fWMle521oDXWrG3oQWk= X-Received: by 2002:a05:6000:2405:b0:487:11e0:cb4b with SMTP id ffacd0b85a97d-4871fa85a20mr1266967f8f.4.1789718858432; Fri, 18 Sep 2026 01:07:38 -0700 (PDT) Received: from naush-dell.pitowers.org ([2a00:1098:3142:1f:45e3:df8b:2b18:6253]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-487203f077fsm1742230f8f.26.2026.09.18.01.07.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 01:07:37 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Cc: Naushir Patuck Subject: [RFC PATCH v1 01/20] libcamera: sysfs: Add devicePath() helpers Date: Fri, 18 Sep 2026 08:59:39 +0100 Message-ID: <20260918080734.1228227-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918080734.1228227-1-naush@raspberrypi.com> References: <20260918080734.1228227-1-naush@raspberrypi.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" Add sysfs::devicePath() helpers to resolve the sysfs path of the device via a character device from either the device node or the device major and minor numbers. The helper is used in V4L2Device::devicePath(), replacing the baked in logic there. Signed-off-by: Naushir Patuck --- include/libcamera/internal/sysfs.h | 3 ++ src/libcamera/sysfs.cpp | 61 ++++++++++++++++++++++++++++++ src/libcamera/v4l2_device.cpp | 13 ++----- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/include/libcamera/internal/sysfs.h b/include/libcamera/internal/sysfs.h index aca60fb6c8ab..1b30317c0dea 100644 --- a/include/libcamera/internal/sysfs.h +++ b/include/libcamera/internal/sysfs.h @@ -15,6 +15,9 @@ namespace sysfs { std::string charDevPath(const std::string &deviceNode); +std::string devicePath(const std::string &deviceNode); +std::string devicePath(unsigned int deviceMajor, unsigned int deviceMinor); + std::string firmwareNodePath(const std::string &device); } /* namespace sysfs */ diff --git a/src/libcamera/sysfs.cpp b/src/libcamera/sysfs.cpp index 3d9885b080c6..7c441a17f86d 100644 --- a/src/libcamera/sysfs.cpp +++ b/src/libcamera/sysfs.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -26,6 +27,26 @@ LOG_DEFINE_CATEGORY(SysFs) namespace sysfs { +namespace { + +/* + * Resolve the "device" symbolic link of a sysfs character device directory to + * the sysfs path of the physical device associated with it. + */ +std::string resolveDevicePath(const std::string &charDevDir) +{ + char *realPath = realpath((charDevDir + "/device").c_str(), nullptr); + if (!realPath) + return {}; + + std::string path{ realPath }; + free(realPath); + + return path; +} + +} /* namespace */ + /** * \brief Retrieve the sysfs path for a character device * \param[in] deviceNode Path to character device node @@ -49,6 +70,46 @@ std::string charDevPath(const std::string &deviceNode) return dev.str(); } +/** + * \brief Retrieve the sysfs path of the physical device for a character device + * \param[in] deviceNode Path to character device node + * + * Retrieve the sysfs path of the physical device associated with the character + * device \a deviceNode. The path is absolute and contains no symbolic link. + * + * \return The device path on success or an empty string on failure + */ +std::string devicePath(const std::string &deviceNode) +{ + std::string path = charDevPath(deviceNode); + if (path.empty()) + return {}; + + return resolveDevicePath(path); +} + +/** + * \brief Retrieve the sysfs path of the physical device for a character device + * \param[in] deviceMajor The character device major number + * \param[in] deviceMinor The character device minor number + * + * Retrieve the sysfs path of the physical device associated with the character + * device identified by \a deviceMajor and \a deviceMinor. The path is absolute + * and contains no symbolic link. + * + * Unlike the device node variant of this function, resolving the device from + * its device numbers requires no access to the device node itself. + * + * \return The device path on success or an empty string on failure + */ +std::string devicePath(unsigned int deviceMajor, unsigned int deviceMinor) +{ + std::ostringstream dev("/sys/dev/char/", std::ios_base::ate); + dev << deviceMajor << ":" << deviceMinor; + + return resolveDevicePath(dev.str()); +} + /** * \brief Retrieve the path of the firmware node for a device * \param[in] device Path in sysfs to search diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 258c82b8d238..8b9c3a357149 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -454,17 +454,10 @@ const struct v4l2_query_ext_ctrl *V4L2Device::controlInfo(uint32_t id) const */ std::string V4L2Device::devicePath() const { - std::string devicePath = sysfs::charDevPath(deviceNode_) + "/device"; - - char *realPath = realpath(devicePath.c_str(), nullptr); - if (!realPath) { + std::string path = sysfs::devicePath(deviceNode_); + if (path.empty()) LOG(V4L2, Fatal) - << "Can not resolve device path for " << devicePath; - return {}; - } - - std::string path{ realPath }; - free(realPath); + << "Can not resolve device path for " << deviceNode_; return path; }