Browse Source

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>
Felix Fietkau 2 years ago
parent
commit
aa0e3c4bbe
3 changed files with 91 additions and 0 deletions
  1. 1 0
      include/iwinfo.h
  2. 14 0
      iwinfo_cli.c
  3. 76 0
      iwinfo_nl80211.c

+ 1 - 0
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);
 };
 

+ 14 - 0
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':

+ 76 - 0
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
 };