}
+/* 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;
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;
if (fork())
return;
}
}
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++) {
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));