1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* sysfs.cpp - Miscellaneous utility functions to access sysfs
*/
#include "libcamera/internal/sysfs.h"
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <libcamera/base/file.h>
#include <libcamera/base/log.h>
/**
* \file sysfs.h
* \brief Miscellaneous utility functions to access sysfs
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(SysFs)
namespace sysfs {
/**
* \brief Retrieve the sysfs path for a character device
* \param[in] deviceNode Path to character device node
* \return The sysfs path on success or an empty string on failure
*/
std::string charDevPath(const std::string &deviceNode)
{
struct stat st;
int ret = stat(deviceNode.c_str(), &st);
if (ret < 0) {
ret = -errno;
LOG(SysFs, Error)
<< "Unable to stat '" << deviceNode << "': "
<< strerror(-ret);
return {};
}
std::ostringstream dev("/sys/dev/char/", std::ios_base::ate);
dev << major(st.st_rdev) << ":" << minor(st.st_rdev);
return dev.str();
}
/**
* \brief Retrieve the path of the firmware node for a device
* \param[in] device Path in sysfs to search
*
* Physical devices in a system are described by the system firmware. Depending
* on the type of platform, devices are identified using different naming
* schemes. The Linux kernel abstract those differences with "firmware nodes".
* This function retrieves the firmware node path corresponding to the
* \a device.
*
* For DT-based systems, the path is the full name of the DT node that
* represents the device. For ACPI-based systems, the path is the absolute
* namespace path to the ACPI object that represents the device. In both cases,
* the path is guaranteed to be unique and persistent as long as the system
* firmware is not modified.
*
* \return The firmware node path on success or an empty string on failure
*/
std::string firmwareNodePath(const std::string &device)
{
std::string fwPath, node;
struct stat st;
/* Lookup for DT-based systems */
node = device + "/of_node";
if (!stat(node.c_str(), &st)) {
char *ofPath = realpath(node.c_str(), nullptr);
if (!ofPath)
return {};
static const char prefix[] = "/sys/firmware/devicetree";
if (strncmp(ofPath, prefix, strlen(prefix)) == 0)
fwPath = ofPath + strlen(prefix);
else
fwPath = ofPath;
free(ofPath);
return fwPath;
}
/* Lookup for ACPI-based systems */
node = device + "/firmware_node/path";
if (File::exists(node)) {
std::ifstream file(node);
if (!file.is_open())
return {};
std::getline(file, fwPath);
file.close();
return fwPath;
}
return {};
}
} /* namespace sysfs */
} /* namespace libcamera */
|