set rate in wificonf from wl0_rate (fixes #159)
[openwrt/svn-archive/archive.git] / openwrt / package / wificonf / wificonf.c
index a5062c585d1f04ccfc40ec98e0ea06e18285a55a..5c3581df638da5c6b64aca765ca19c8a3832d65a 100644 (file)
@@ -23,7 +23,7 @@
 #include <signal.h>
 
 #define        ADD_VIF_RETRIES 5
-#define DEBUG
+// #define DEBUG
 
 /*------------------------------------------------------------------*/
 /*
@@ -112,6 +112,64 @@ static int nvram_disabled(char *name)
 }
 
 
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153
+#define QDBM_TABLE_LEN 40
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm:        +0             +1              +2              +3              +4              +5              +6              +7      */
+/* 153: */      6683,  7079,   7499,   7943,   8414,   8913,   9441,   10000,
+/* 161: */      10593, 11220,  11885,  12589,  13335,  14125,  14962,  15849,
+/* 169: */      16788, 17783,  18836,  19953,  21135,  22387,  23714,  25119,
+/* 177: */      26607, 28184,  29854,  31623,  33497,  35481,  37584,  39811,
+/* 185: */      42170, 44668,  47315,  50119,  53088,  56234,  59566,  63096
+};
+
+unsigned char mw_to_qdbm(uint16 mw)
+{
+       char qdbm;
+       int offset;
+       uint mw_uint = mw;
+       uint boundary;
+       
+       /* handle boundary case */
+       if (mw_uint <= 1)
+               return 0;
+       
+       offset = QDBM_OFFSET;
+       
+       /* move mw into the range of the table */
+       while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+               mw_uint *= 10;
+               offset -= 40;
+       }
+
+       for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+               boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - nqdBm_to_mW_map[qdbm])/2;
+               if (mw_uint < boundary) break;
+       }
+
+       qdbm += (unsigned char)offset;
+
+       return(qdbm);
+}
+
 static int bcom_ioctl(int skfd, char *ifname, int cmd, void *buf, int len)
 {
        struct ifreq ifr;
@@ -337,7 +395,8 @@ void start_watchdog(int skfd, char *ifname)
        FILE *f;
        char *v, *next;
        unsigned char buf[8192], buf2[8192], wbuf[80], *p, *tmp;
-       int wds = 0, i, restart_wds;
+       int wds = 0, i, j, restart_wds;
+       wlc_ssid_t ssid;
 
        if (fork())
                return;
@@ -357,11 +416,41 @@ void start_watchdog(int skfd, char *ifname)
                }
        }
        v = nvram_safe_get(wl_var("ssid"));
+       ssid.SSID_len = strlen(v);
+       strncpy(ssid.SSID, v, 32);
        
        for (;;) {
                sleep(5);
-               if (bcom_ioctl(skfd, ifname, WLC_GET_BSSID, buf, 6) < 0)
-                       bcom_ioctl(skfd, ifname, WLC_SET_SSID, v, strlen(v));
+
+               /* client mode */
+               bcom_ioctl(skfd, ifname, WLC_GET_AP, &i, sizeof(i));
+               if (!i) {
+                       i = 0;
+                       if (bcom_ioctl(skfd, ifname, WLC_GET_BSSID, buf, 6) < 0) 
+                               i = 1;
+                       memcpy(buf + 6, "\x00\x00\x00\x00\x00\x00", 6);
+                       if (memcmp(buf, buf + 6, 6) == 0)
+                               i = 1;
+                       
+                       memset(buf, 0, 8192);
+                       strcpy(buf, "sta_info");
+                       bcom_ioctl(skfd, ifname, WLC_GET_BSSID, buf + strlen(buf) + 1, 6);
+                       if (bcom_ioctl(skfd, ifname, WLC_GET_VAR, buf, 8192) < 0) {
+                               i = 1;
+                       } else {
+                               sta_info_t *sta = (sta_info_t *) (buf + 4);
+                               if ((sta->flags & 0x18) != 0x18) 
+                                       i = 1;
+                               if (sta->idle > 20)
+                                       i = 1;
+                       }
+                       
+                       if (i) 
+                               bcom_ioctl(skfd, ifname, WLC_SET_SSID, &ssid, sizeof(ssid));
+               }
+
+               
+               /* wds */
                p = buf2;
                restart_wds = 0;
                for (i = 0; i < wds; i++) {
@@ -462,7 +551,7 @@ static void setup_bcom_vif_sec(int skfd, char *ifname, int vif)
                                wep = 1;
                                bcom_set_bss_int(skfd, ifname, vif, "wsec", WEP_ENABLED);
                                bcom_set_bss_int(skfd, ifname, vif, "wsec_restrict", 1);
-                               bcom_set_bss_int(skfd, ifname, vif, "auth", 1);
+                               bcom_set_bss_int(skfd, ifname, vif, "auth", nvram_enabled(vif_var(vif, "auth")));
                        } else {
                                wep = 0;
                        }
@@ -523,10 +612,20 @@ static void setup_bcom_common(int skfd, char *ifname)
        buf[3] = 0;
        bcom_ioctl(skfd, ifname, WLC_SET_COUNTRY, buf, 4);
        
+       if (v = nvram_get(wl_var("txpwr"))) {
+               val = atoi(v);
+               val = mw_to_qdbm(val);
+               bcom_set_int(skfd, ifname, "qtxpower", val);
+       }
+       
        /* Set other options */
        val = nvram_enabled(wl_var("lazywds"));
        bcom_ioctl(skfd, ifname, WLC_SET_LAZYWDS, &val, sizeof(val));
 
+       if ((val = atoi(nvram_safe_get(wl_var("rate")))) > 0) {
+               val *= 2;
+               bcom_ioctl(skfd, ifname, WLC_SET_RATE, &val, sizeof(val));
+       }
        if (v = nvram_get(wl_var("dtim"))) {
                val = atoi(v);
                bcom_ioctl(skfd, ifname, WLC_SET_DTIMPRD, &val, sizeof(val));
@@ -773,8 +872,14 @@ static void setup_bcom_old(int skfd, char *ifname)
                bcom_ioctl(skfd, ifname, WLC_SET_EAP_RESTRICT, &val, sizeof(val));
                bcom_set_int(skfd, ifname, "sup_wpa", 0);
        }
+
+       if (v = nvram_get(wl_var("auth"))) {
+               val = atoi(v);
+               bcom_ioctl(skfd, ifname, WLC_SET_AUTH, &val, sizeof(val));
+       }
 }
 
+
 static void set_wext_ssid(int skfd, char *ifname)
 {
        char *buffer;