iwinfo: add device id for Marvell 88W8864
[project/iwinfo.git] / iwinfo_nl80211.c
index 7711b61..be58c56 100644 (file)
@@ -23,6 +23,8 @@
  */
 
 #include <limits.h>
+#include <glob.h>
+#include <fnmatch.h>
 #include "iwinfo_nl80211.h"
 
 #define min(x, y) ((x) < (y)) ? (x) : (y)
@@ -124,6 +126,27 @@ static int nl80211_readint(const char *path)
        return rv;
 }
 
+static int nl80211_readstr(const char *path, char *buffer, int length)
+{
+       int fd;
+       int rv = -1;
+
+       if ((fd = open(path, O_RDONLY)) > -1)
+       {
+               if ((rv = read(fd, buffer, length - 1)) > 0)
+               {
+                       if (buffer[rv - 1] == '\n')
+                               rv--;
+
+                       buffer[rv] = 0;
+               }
+
+               close(fd);
+       }
+
+       return rv;
+}
+
 
 static int nl80211_msg_error(struct sockaddr_nl *nla,
        struct nlmsgerr *err, void *arg)
@@ -209,6 +232,98 @@ static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
        return nl80211_new(nls->nlctrl, cmd, flags);
 }
 
+static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
+{
+       const char *opt;
+       char buf[128];
+       int idx = -1;
+       glob_t gl;
+
+       opt = uci_lookup_option_string(uci_ctx, s, "path");
+       if (!opt)
+               return -1;
+
+       snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt);  /**/
+       if (glob(buf, 0, NULL, &gl))
+               return -1;
+
+       if (gl.gl_pathc > 0)
+               idx = nl80211_readint(gl.gl_pathv[0]);
+
+       globfree(&gl);
+
+       return idx;
+}
+
+static int nl80211_phy_idx_from_uci_macaddr(struct uci_section *s)
+{
+       const char *opt;
+       char buf[128];
+       int i, idx = -1;
+       glob_t gl;
+
+       opt = uci_lookup_option_string(uci_ctx, s, "macaddr");
+       if (!opt)
+               return -1;
+
+       snprintf(buf, sizeof(buf), "/sys/class/ieee80211/*", opt);      /**/
+       if (glob(buf, 0, NULL, &gl))
+               return -1;
+
+       for (i = 0; i < gl.gl_pathc; i++)
+       {
+               snprintf(buf, sizeof(buf), "%s/macaddress", gl.gl_pathv[i]);
+               if (nl80211_readstr(buf, buf, sizeof(buf)) <= 0)
+                       continue;
+
+               if (fnmatch(opt, buf, FNM_CASEFOLD))
+                       continue;
+
+               snprintf(buf, sizeof(buf), "%s/index", gl.gl_pathv[i]);
+               if ((idx = nl80211_readint(buf)) > -1)
+                       break;
+       }
+
+       globfree(&gl);
+
+       return idx;
+}
+
+static int nl80211_phy_idx_from_uci_phy(struct uci_section *s)
+{
+       const char *opt;
+       char buf[128];
+
+       opt = uci_lookup_option_string(uci_ctx, s, "phy");
+       if (!opt)
+               return -1;
+
+       snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", opt);
+       return nl80211_readint(buf);
+}
+
+static int nl80211_phy_idx_from_uci(const char *name)
+{
+       struct uci_section *s;
+       int idx = -1;
+
+       s = iwinfo_uci_get_radio(name, "mac80211");
+       if (!s)
+               goto free;
+
+       idx = nl80211_phy_idx_from_uci_path(s);
+
+       if (idx < 0)
+               idx = nl80211_phy_idx_from_uci_macaddr(s);
+
+       if (idx < 0)
+               idx = nl80211_phy_idx_from_uci_phy(s);
+
+free:
+       iwinfo_uci_free();
+       return idx;
+}
+
 static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
                                                  int cmd, int flags)
 {
@@ -224,7 +339,7 @@ static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
        if (!strncmp(ifname, "phy", 3))
                phyidx = atoi(&ifname[3]);
        else if (!strncmp(ifname, "radio", 5))
-               phyidx = atoi(&ifname[5]);
+               phyidx = nl80211_phy_idx_from_uci(ifname);
        else if (!strncmp(ifname, "mon.", 4))
                ifidx = if_nametoindex(&ifname[4]);
        else
@@ -510,7 +625,7 @@ static char * nl80211_phy2ifname(const char *ifname)
        else if (!strncmp(ifname, "phy", 3))
                phyidx = atoi(&ifname[3]);
        else if (!strncmp(ifname, "radio", 5))
-               phyidx = atoi(&ifname[5]);
+               phyidx = nl80211_phy_idx_from_uci(ifname);
        else
                return NULL;
 
@@ -2331,15 +2446,15 @@ static int nl80211_get_ifcomb_cb(struct nl_msg *msg, void *arg)
                        [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
                        [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
                };
-               struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+               struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB+1];
                static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
                        [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
                        [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
                };
-               struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+               struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT+1];
                struct nlattr *limit;
 
-               nla_parse_nested(tb_comb, NL80211_BAND_ATTR_MAX, comb, iface_combination_policy);
+               nla_parse_nested(tb_comb, NUM_NL80211_IFACE_COMB, comb, iface_combination_policy);
 
                if (!tb_comb[NL80211_IFACE_COMB_LIMITS])
                        continue;
@@ -2460,6 +2575,17 @@ static int nl80211_get_frequency_offset(const char *ifname, int *buf)
        return 0;
 }
 
+static int nl80211_lookup_phyname(const char *section, char *buf)
+{
+       int idx;
+
+       if ((idx = nl80211_phy_idx_from_uci(section)) < 0)
+               return -1;
+
+       sprintf(buf, "phy%d", idx);
+       return 0;
+}
+
 const struct iwinfo_ops nl80211_ops = {
        .name             = "nl80211",
        .probe            = nl80211_probe,
@@ -2488,5 +2614,6 @@ const struct iwinfo_ops nl80211_ops = {
        .scanlist         = nl80211_get_scanlist,
        .freqlist         = nl80211_get_freqlist,
        .countrylist      = nl80211_get_countrylist,
+       .lookup_phy       = nl80211_lookup_phyname,
        .close            = nl80211_close
 };