Skip to content

Commit 04f91c3

Browse files
committed
hwmon: refactor & support lookup of all indices
This should allow the user to omit the indices: config field if a sensor input is sufficiently specified by other criteria. In this case, thinkfan should pick up all pwm/temp files found for the given sensor. A major caveat being that the number of available temperature inputs won't be known before a sensors has been successfully looked up...
1 parent c406d14 commit 04f91c3

File tree

2 files changed

+57
-33
lines changed

2 files changed

+57
-33
lines changed

src/hwmon.cpp

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@
2929
#include <cstring>
3030
#include <sys/types.h>
3131
#include <sys/stat.h>
32+
#include <filesystem>
3233

3334
namespace thinkfan {
3435

36+
namespace filesystem = std::filesystem;
37+
3538

3639
static int filter_hwmon_dirs(const struct dirent *entry)
3740
{
3841
return (entry->d_type == DT_DIR || entry->d_type == DT_LNK)
39-
&& (!strncmp("hwmon", entry->d_name, 5) || !strcmp("device", entry->d_name));
42+
&& (string(entry->d_name) == "hwmon" || string(entry->d_name) == "device");
4043
}
4144

4245

@@ -48,6 +51,43 @@ static int filter_subdirs(const struct dirent *entry)
4851
}
4952

5053

54+
template<>
55+
int HwmonInterface<SensorDriver>::filter_driver_file(const struct dirent *entry)
56+
{
57+
int idx;
58+
return (entry->d_type == DT_REG || entry->d_type == DT_LNK)
59+
&& !::sscanf(entry->d_name, "temp%d_input", &idx)
60+
;
61+
}
62+
63+
template<>
64+
int HwmonInterface<FanDriver>::filter_driver_file(const struct dirent *entry)
65+
{
66+
int idx;
67+
return (entry->d_type == DT_REG || entry->d_type == DT_LNK)
68+
&& !::sscanf(entry->d_name, "pwm%d", &idx)
69+
;
70+
}
71+
72+
73+
template<int (* filter_fn)(const struct dirent *)>
74+
vector<filesystem::path> dir_entries(const filesystem::path &dir)
75+
{
76+
struct dirent **entries;
77+
int nentries = ::scandir(dir.c_str(), &entries, filter_fn, nullptr);
78+
if (nentries == -1)
79+
return {};
80+
81+
vector<filesystem::path> rv;
82+
for (int i = 0; i < nentries; ++i) {
83+
rv.emplace_back(dir / entries[i]->d_name);
84+
::free(entries[i]);
85+
}
86+
::free(entries);
87+
return rv;
88+
}
89+
90+
5191
template<class HwmonT>
5292
vector<string> HwmonInterface<HwmonT>::find_files(const string &path, const vector<unsigned int> &indices)
5393
{
@@ -85,6 +125,7 @@ HwmonInterface<HwmonT>::HwmonInterface(const string &base_path, opt<const string
85125
, indices_(indices)
86126
{}
87127

128+
88129
template<class HwmonT>
89130
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
90131
const string &path,
@@ -106,15 +147,7 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
106147
return result; // don't recurse to subdirs
107148
}
108149

109-
struct dirent **entries;
110-
int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr);
111-
if (nentries == -1) {
112-
return result;
113-
}
114-
for (int i = 0; i < nentries; i++) {
115-
auto subdir = path + "/" + entries[i]->d_name;
116-
free(entries[i]);
117-
150+
for (const filesystem::path &subdir : dir_entries<filter_subdirs>(path)) {
118151
struct stat statbuf;
119152
int err = stat(path.c_str(), &statbuf);
120153
if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR)
@@ -123,11 +156,11 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
123156
auto found = find_hwmons_by_name(subdir, name, depth + 1);
124157
result.insert(result.end(), found.begin(), found.end());
125158
}
126-
free(entries);
127159

128160
return result;
129161
}
130162

163+
131164
template<class HwmonT>
132165
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
133166
const string &path,
@@ -152,15 +185,7 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
152185
return result; // don't recurse to subdirs
153186
}
154187

155-
struct dirent **entries;
156-
int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr);
157-
if (nentries == -1) {
158-
return result;
159-
}
160-
for (int i = 0; i < nentries; i++) {
161-
auto subdir = path + "/" + entries[i]->d_name;
162-
free(entries[i]);
163-
188+
for (const filesystem::path &subdir : dir_entries<filter_subdirs>(path)) {
164189
struct stat statbuf;
165190
int err = stat(path.c_str(), &statbuf);
166191
if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR)
@@ -169,11 +194,11 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
169194
auto found = find_hwmons_by_model(subdir, model, depth + 1);
170195
result.insert(result.end(), found.begin(), found.end());
171196
}
172-
free(entries);
173197

174198
return result;
175199
}
176200

201+
177202
template<class HwmonT>
178203
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
179204
const string &path,
@@ -187,24 +212,20 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
187212
}
188213
catch (IOerror &) {
189214
if (depth <= max_depth) {
190-
struct dirent **entries;
191-
int nentries = ::scandir(path.c_str(), &entries, filter_hwmon_dirs, alphasort);
192-
if (nentries < 0)
215+
vector<filesystem::path> hwmon_dirs = dir_entries<filter_hwmon_dirs>(path);
216+
if (hwmon_dirs.empty())
193217
throw IOerror("Error scanning " + path + ": ", errno);
194218

195219
vector<string> rv;
196-
for (int i = 0; i < nentries; i++) {
220+
for (const filesystem::path &hwmon_dir : hwmon_dirs) {
197221
rv = HwmonInterface<HwmonT>::find_hwmons_by_indices(
198-
path + "/" + entries[i]->d_name,
222+
hwmon_dir,
199223
indices,
200224
depth + 1
201225
);
202226
if (rv.size())
203227
break;
204228
}
205-
for (int i = 0; i < nentries; i++)
206-
free(entries[i]);
207-
free(entries);
208229

209230
return rv;
210231
}
@@ -214,7 +235,6 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
214235
}
215236

216237

217-
218238
template<class HwmonT>
219239
string HwmonInterface<HwmonT>::lookup()
220240
{
@@ -229,7 +249,7 @@ string HwmonInterface<HwmonT>::lookup()
229249
if (paths.size() != 1) {
230250
string msg(path + ": ");
231251
if (paths.size() == 0) {
232-
msg += "Could not find a hwmon with this name: " + name_.value();
252+
msg += "Could not find an hwmon with this name: " + name_.value();
233253
} else {
234254
msg += MSG_MULTIPLE_HWMONS_FOUND;
235255
for (string hwmon_path : paths)
@@ -259,8 +279,10 @@ string HwmonInterface<HwmonT>::lookup()
259279
if (found_paths_.size() == 0)
260280
throw DriverInitError(path + ": " + "Could not find any hwmons in " + path);
261281
}
262-
else
263-
found_paths_.push_back(path);
282+
else {
283+
vector<filesystem::path> paths = dir_entries<filter_driver_file>(path);
284+
found_paths_.assign(paths.begin(), paths.end());
285+
}
264286

265287
paths_it_.emplace(found_paths_.begin());
266288
}

src/hwmon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@ class HwmonInterface {
4141
string lookup();
4242

4343
private:
44+
static int filter_driver_file(const struct dirent *entry);
4445
static vector<string> find_files(const string &path, const vector<unsigned int> &indices);
4546
static string filename(unsigned int index);
4647

4748
static vector<string> find_hwmons_by_model(const string &path, const string &model, unsigned char depth);
4849
static vector<string> find_hwmons_by_name(const string &path, const string &name, unsigned char depth);
4950
static vector<string> find_hwmons_by_indices(const string &path, const vector<unsigned int> &indices, unsigned char depth);
5051

52+
5153
protected:
5254
opt<const string> base_path_;
5355
opt<const string> name_;

0 commit comments

Comments
 (0)