| Message ID | 20260918080734.1228227-2-naush@raspberrypi.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
Hi 2026. 09. 18. 9:59 keltezéssel, Naushir Patuck írta: > 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 <naush@raspberrypi.com> > --- > 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 <fstream> > #include <sstream> > +#include <stdlib.h> > #include <sys/stat.h> > #include <sys/sysmacros.h> > > @@ -26,6 +27,26 @@ LOG_DEFINE_CATEGORY(SysFs) > > namespace sysfs { > > +namespace { > + Let's make some small optimizations with this move. > +/* > + * 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) std::string charDevDir > +{ > + char *realPath = realpath((charDevDir + "/device").c_str(), nullptr); (std::move(charDevDir) + "/device").c_str() > + 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); std::move(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()); std::move(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; > }
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 <fstream> #include <sstream> +#include <stdlib.h> #include <sys/stat.h> #include <sys/sysmacros.h> @@ -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; }
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 <naush@raspberrypi.com> --- include/libcamera/internal/sysfs.h | 3 ++ src/libcamera/sysfs.cpp | 61 ++++++++++++++++++++++++++++++ src/libcamera/v4l2_device.cpp | 13 ++----- 3 files changed, 67 insertions(+), 10 deletions(-)