summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-06-09 13:57:23 +0200
committerFelix Fietkau <nbd@nbd.name>2021-06-09 13:57:26 +0200
commitaa0e3c4bbe12f02ddb3a0a2e69b3b4f0b30b9b79 (patch)
tree34943e6d8d97203ff7cc824292c56eae28cb53e1
parentc45f0b584b4b86f8250f90ea19afca271c114fa2 (diff)
downloadiwinfo-aa0e3c4bbe12f02ddb3a0a2e69b3b4f0b30b9b79.tar.gz
iwinfo: nl80211: add support for printing the device path for a phy
Will be used to replace the shell code from mac80211.sh Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--include/iwinfo.h1
-rw-r--r--iwinfo_cli.c14
-rw-r--r--iwinfo_nl80211.c76
3 files changed, 91 insertions, 0 deletions
diff --git a/include/iwinfo.h b/include/iwinfo.h
index 3fc414b..f7097cc 100644
--- a/include/iwinfo.h
+++ b/include/iwinfo.h
@@ -293,6 +293,7 @@ struct iwinfo_ops {
int (*countrylist)(const char *, char *, int *);
int (*survey)(const char *, char *, int *);
int (*lookup_phy)(const char *, char *);
+ int (*phy_path)(const char *phyname, const char **path);
void (*close)(void);
};
diff --git a/iwinfo_cli.c b/iwinfo_cli.c
index 8691f31..456c67a 100644
--- a/iwinfo_cli.c
+++ b/iwinfo_cli.c
@@ -875,6 +875,16 @@ static void lookup_phy(const struct iwinfo_ops *iw, const char *section)
}
+static void lookup_path(const struct iwinfo_ops *iw, const char *phy)
+{
+ const char *path;
+
+ if (!iw->phy_path || iw->phy_path(phy, &path) || !path)
+ return;
+
+ printf("%s\n", path);
+}
+
int main(int argc, char **argv)
{
int i, rv = 0;
@@ -934,6 +944,10 @@ int main(int argc, char **argv)
}
else
{
+ if (!strcmp(argv[2], "path")) {
+ lookup_path(iw, argv[3]);
+ return 0;
+ }
switch (argv[2][0])
{
case 'p':
diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
index eea521e..be90824 100644
--- a/iwinfo_nl80211.c
+++ b/iwinfo_nl80211.c
@@ -233,6 +233,66 @@ static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
return nl80211_new(nls->nlctrl, cmd, flags);
}
+static const char *nl80211_phy_path_str(const char *phyname)
+{
+ static char path[PATH_MAX];
+ const char *prefix = "/sys/devices/";
+ int prefix_len = strlen(prefix);
+ int buf_len, offset;
+ struct dirent *e;
+ char buf[128], *link;
+ int phy_id;
+ int seq = 0;
+ DIR *d;
+
+ if (strncmp(phyname, "phy", 3) != 0)
+ return NULL;
+
+ phy_id = atoi(phyname + 3);
+ buf_len = snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/device", phyname);
+ link = realpath(buf, path);
+ if (!link)
+ return NULL;
+
+ if (strncmp(link, prefix, prefix_len) != 0)
+ return NULL;
+
+ link += prefix_len;
+
+ prefix = "platform/";
+ prefix_len = strlen(prefix);
+ if (!strncmp(link, prefix, prefix_len) && strstr(link, "/pci"))
+ link += prefix_len;
+
+ snprintf(buf + buf_len, sizeof(buf) - buf_len, "/ieee80211");
+ d = opendir(buf);
+ if (!d)
+ return link;
+
+ while ((e = readdir(d)) != NULL) {
+ int cur_id;
+
+ if (strncmp(e->d_name, "phy", 3) != 0)
+ continue;
+
+ cur_id = atoi(e->d_name + 3);
+ if (cur_id >= phy_id)
+ continue;
+
+ seq++;
+ }
+
+ closedir(d);
+
+ if (!seq)
+ return link;
+
+ offset = link - path + strlen(link);
+ snprintf(path + offset, sizeof(path) - offset, "+%d", seq);
+
+ return link;
+}
+
static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
{
size_t linklen, pathlen;
@@ -3429,6 +3489,21 @@ static int nl80211_lookup_phyname(const char *section, char *buf)
return 0;
}
+static int nl80211_phy_path(const char *phyname, const char **path)
+{
+ if (strncmp(phyname, "phy", 3) != 0)
+ return -1;
+
+ if (strchr(phyname, '/'))
+ return -1;
+
+ *path = nl80211_phy_path_str(phyname);
+ if (!*path)
+ return -1;
+
+ return 0;
+}
+
const struct iwinfo_ops nl80211_ops = {
.name = "nl80211",
.probe = nl80211_probe,
@@ -3463,5 +3538,6 @@ const struct iwinfo_ops nl80211_ops = {
.countrylist = nl80211_get_countrylist,
.survey = nl80211_get_survey,
.lookup_phy = nl80211_lookup_phyname,
+ .phy_path = nl80211_phy_path,
.close = nl80211_close
};