Skip to content

Commit

Permalink
hwmon: refactor & support lookup of all indices
Browse files Browse the repository at this point in the history
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...
  • Loading branch information
vmatare committed Apr 7, 2023
1 parent 6049d39 commit f6310a3
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 33 deletions.
88 changes: 55 additions & 33 deletions src/hwmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@
#include <sys/stat.h>
#include <algorithm>
#include <functional>
#include <filesystem>

namespace thinkfan {

namespace filesystem = std::filesystem;


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


Expand All @@ -50,6 +53,43 @@ static int filter_subdirs(const struct dirent *entry)
}


template<>
int HwmonInterface<SensorDriver>::filter_driver_file(const struct dirent *entry)
{
int idx;
return (entry->d_type == DT_REG || entry->d_type == DT_LNK)
&& !::sscanf(entry->d_name, "temp%d_input", &idx)
;
}

template<>
int HwmonInterface<FanDriver>::filter_driver_file(const struct dirent *entry)
{
int idx;
return (entry->d_type == DT_REG || entry->d_type == DT_LNK)
&& !::sscanf(entry->d_name, "pwm%d", &idx)
;
}


template<int (* filter_fn)(const struct dirent *)>
vector<filesystem::path> dir_entries(const filesystem::path &dir)
{
struct dirent **entries;
int nentries = ::scandir(dir.c_str(), &entries, filter_fn, nullptr);
if (nentries == -1)
return {};

vector<filesystem::path> rv;
for (int i = 0; i < nentries; ++i) {
rv.emplace_back(dir / entries[i]->d_name);
::free(entries[i]);
}
::free(entries);
return rv;
}


template<class HwmonT>
vector<string> HwmonInterface<HwmonT>::find_files(const string &path, const vector<unsigned int> &indices)
{
Expand Down Expand Up @@ -87,6 +127,7 @@ HwmonInterface<HwmonT>::HwmonInterface(const string &base_path, opt<const string
, indices_(indices)
{}


template<class HwmonT>
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
const string &path,
Expand All @@ -108,15 +149,7 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
return result; // don't recurse to subdirs
}

struct dirent **entries;
int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr);
if (nentries == -1) {
return result;
}
for (int i = 0; i < nentries; i++) {
auto subdir = path + "/" + entries[i]->d_name;
free(entries[i]);

for (const filesystem::path &subdir : dir_entries<filter_subdirs>(path)) {
struct stat statbuf;
int err = stat(path.c_str(), &statbuf);
if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR)
Expand All @@ -125,11 +158,11 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_name(
auto found = find_hwmons_by_name(subdir, name, depth + 1);
result.insert(result.end(), found.begin(), found.end());
}
free(entries);

return result;
}


template<class HwmonT>
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
const string &path,
Expand All @@ -154,15 +187,7 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
return result; // don't recurse to subdirs
}

struct dirent **entries;
int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr);
if (nentries == -1) {
return result;
}
for (int i = 0; i < nentries; i++) {
auto subdir = path + "/" + entries[i]->d_name;
free(entries[i]);

for (const filesystem::path &subdir : dir_entries<filter_subdirs>(path)) {
struct stat statbuf;
int err = stat(path.c_str(), &statbuf);
if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR)
Expand All @@ -171,11 +196,11 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_model(
auto found = find_hwmons_by_model(subdir, model, depth + 1);
result.insert(result.end(), found.begin(), found.end());
}
free(entries);

return result;
}


template<class HwmonT>
vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
const string &path,
Expand All @@ -189,24 +214,20 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
}
catch (IOerror &) {
if (depth <= max_depth) {
struct dirent **entries;
int nentries = ::scandir(path.c_str(), &entries, filter_hwmon_dirs, alphasort);
if (nentries < 0)
vector<filesystem::path> hwmon_dirs = dir_entries<filter_hwmon_dirs>(path);
if (hwmon_dirs.empty())
throw IOerror("Error scanning " + path + ": ", errno);

vector<string> rv;
for (int i = 0; i < nentries; i++) {
for (const filesystem::path &hwmon_dir : hwmon_dirs) {
rv = HwmonInterface<HwmonT>::find_hwmons_by_indices(
path + "/" + entries[i]->d_name,
hwmon_dir,
indices,
depth + 1
);
if (rv.size())
break;
}
for (int i = 0; i < nentries; i++)
free(entries[i]);
free(entries);

return rv;
}
Expand All @@ -216,7 +237,6 @@ vector<string> HwmonInterface<HwmonT>::find_hwmons_by_indices(
}



template<class HwmonT>
string HwmonInterface<HwmonT>::lookup()
{
Expand All @@ -231,7 +251,7 @@ string HwmonInterface<HwmonT>::lookup()
if (paths.size() != 1) {
string msg(path + ": ");
if (paths.size() == 0) {
msg += "Could not find a hwmon with this name: " + name_.value();
msg += "Could not find an hwmon with this name: " + name_.value();
} else {
msg += MSG_MULTIPLE_HWMONS_FOUND;
for (string hwmon_path : paths)
Expand Down Expand Up @@ -261,8 +281,10 @@ string HwmonInterface<HwmonT>::lookup()
if (found_paths_.size() == 0)
throw DriverInitError(path + ": " + "Could not find any hwmons in " + path);
}
else
found_paths_.push_back(path);
else {
vector<filesystem::path> paths = dir_entries<filter_driver_file>(path);
found_paths_.assign(paths.begin(), paths.end());
}

paths_it_.emplace(found_paths_.begin());
}
Expand Down
2 changes: 2 additions & 0 deletions src/hwmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ class HwmonInterface {
string lookup();

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

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


protected:
opt<const string> base_path_;
opt<const string> name_;
Expand Down

0 comments on commit f6310a3

Please sign in to comment.