diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-08-06 23:13:23 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-08-06 23:13:23 +0200 |
commit | abe463b931338e77095586052b66daade0428c95 (patch) | |
tree | af1354447c58d4d336bdb6e1f02697625aab7ef5 /sys/src/9/port/wifi.c | |
parent | 2b619dc9669e34c7b110ce188a10d03849119c78 (diff) |
wifi: lilu dallas multirate
now handle the supported rates element properly, only
providing the intersecting set of rates that the bss
advertises and what the driver supports, putting the
basic rates first.
also avoid using usupported rates.
Diffstat (limited to 'sys/src/9/port/wifi.c')
-rw-r--r-- | sys/src/9/port/wifi.c | 83 |
1 files changed, 61 insertions, 22 deletions
diff --git a/sys/src/9/port/wifi.c b/sys/src/9/port/wifi.c index 67fa5fc46..10b5417a2 100644 --- a/sys/src/9/port/wifi.c +++ b/sys/src/9/port/wifi.c @@ -173,7 +173,7 @@ wifitx(Wifi *wifi, Wnode *wn, Block *b) uchar *a, *p; for(a = wn->maxrate, p = wifi->rates; *p; p++){ - if(*p < *a && *p > *wn->actrate) + if(*p < *a && *p > *wn->actrate && (wn->validrates & (1UL << p-wifi->rates)) != 0) a = p; } wn->actrate = a; @@ -229,7 +229,7 @@ wifitxfail(Wifi *wifi, Block *b) uchar *a, *p; for(a = wn->minrate, p = wifi->rates; *p; p++){ - if(*p > *a && *p < *wn->actrate) + if(*p > *a && *p < *wn->actrate && (wn->validrates & (1UL << p-wifi->rates)) != 0) a = p; } wn->actrate = a; @@ -237,25 +237,59 @@ wifitxfail(Wifi *wifi, Block *b) } static uchar* -putrates(uchar *p, uchar *rates) +putrates(uchar *p, uchar *rates, ulong valid, ulong basic) { - int n, m; + int n, i, j; + + valid |= basic; + + for(i = n = 0; i < 32 && rates[i] != 0; i++) + if(valid & (1UL<<i)) + n++; + + valid &= ~basic; + + if(n > 0){ + /* supported rates */ + *p++ = 1; + *p++ = n; + for(i = j = 0; j < n; i++){ + if(basic & (1UL<<i)){ + *p++ = rates[i] | 0x80; + j++; + } + } + for(i = 0; j < n; i++){ + if(valid & (1UL<<i)){ + *p++ = rates[i] & 0x7f; + j++; + } + } + } + + if(n > 8){ + /* truncate supported rates element */ + p -= n; + p[-1] = 8; + p += 8; - n = m = strlen((char*)rates); - if(n > 8) - n = 8; - /* supported rates */ - *p++ = 1; - *p++ = n; - memmove(p, rates, n); - p += n; - if(m > 8){ /* extended supported rates */ *p++ = 50; - *p++ = m; - memmove(p, rates, m); - p += m; + *p++ = n; + for(i = j = 0; j < n; i++){ + if(basic & (1UL<<i)){ + *p++ = rates[i] | 0x80; + j++; + } + } + for(i = 0; j < n; i++){ + if(valid & (1UL<<i)){ + *p++ = rates[i] & 0x7f; + j++; + } + } } + return p; } @@ -289,7 +323,7 @@ wifiprobe(Wifi *wifi, Wnode *wn) memmove(p, wifi->essid, n); p += n; - p = putrates(p, wifi->rates); + p = putrates(p, wifi->rates, wn->validrates, wn->basicrates); *p++ = 3; /* ds parameter set */ *p++ = 1; @@ -363,7 +397,7 @@ sendassoc(Wifi *wifi, Wnode *bss) memmove(p, bss->ssid, n); p += n; - p = putrates(p, wifi->rates); + p = putrates(p, wifi->rates, bss->validrates, bss->basicrates); n = bss->rsnelen; if(n > 0){ @@ -454,12 +488,15 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len) break; case 1: /* supported rates */ case 50: /* extended rates */ - if(wn->actrate != nil || wifi->rates == nil) - break; /* already set */ + if(wifi->rates == nil) + break; while(d < x){ - t = *d++ | 0x80; + t = *d | 0x80; for(p = wifi->rates; *p != 0; p++){ if(*p == t){ + wn->validrates |= 1UL << p-wifi->rates; + if(*d & 0x80) + wn->basicrates |= 1UL << p-wifi->rates; if(wn->minrate == nil || t < *wn->minrate) wn->minrate = p; if(wn->maxrate == nil || t > *wn->maxrate) @@ -467,8 +504,10 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len) break; } } - wn->actrate = wn->maxrate; + d++; } + if(wn->actrate == nil) + wn->actrate = wn->maxrate; break; case 3: /* DSPARAMS */ if(d != x) |