From: cinap_lenrek Date: Mon, 21 Apr 2014 01:43:51 +0000 (+0200) Subject: wifi: first attempt on negotiating data rates X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3b87d6114dceccd0a5cee998ab6d6cc393de1ef2;p=plan9front.git wifi: first attempt on negotiating data rates driver sets wifi->rates array to tell wifi layer what rates it supports. when we receive beacon, we determine the minimum and maximum data rates and set wn->minrate and wn->maxrate to point to the entries in wifi->rates. it is the responsibility of the driver to use this information on transmit. --- diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c index 50c134c85..ee44aa3f4 100644 --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -1813,6 +1813,24 @@ static struct ratetab { { 120, 0x3, 0 } }; +static uchar iwlrates[] = { + 0x80 | 2, + 0x80 | 4, + 0x80 | 11, + 0x80 | 22, + 12, + 18, + 24, + 36, + 48, + 72, + 96, + 108, + 120, + + 0 +}; + enum { TFlagNeedProtection = 1<<0, TFlagNeedRTS = 1<<1, @@ -1858,9 +1876,9 @@ transmit(Wifi *wifi, Wnode *wn, Block *b) return; } - rate = 0; flags = 0; nodeid = ctlr->bcastnodeid; + p = wn->minrate; w = (Wifipkt*)b->rp; if((w->a1[0] & 1) == 0){ flags |= TFlagNeedACK; @@ -1870,7 +1888,7 @@ transmit(Wifi *wifi, Wnode *wn, Block *b) if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ nodeid = ctlr->bssnodeid; - rate = 2; /* BUG: hardcode 11Mbit */ + p = wn->maxrate; } if(flags & (TFlagNeedRTS|TFlagNeedCTS)){ @@ -1883,6 +1901,10 @@ transmit(Wifi *wifi, Wnode *wn, Block *b) } qunlock(ctlr); + rate = 0; + if(p >= iwlrates && p < &iwlrates[nelem(ratetab)]) + rate = p - iwlrates; + /* select first available antenna */ ant = ctlr->rfcfg.txantmask & 7; ant |= (ant == 0); @@ -2048,8 +2070,10 @@ iwlattach(Ether *edev) if((csr32r(ctlr, Gpc) & RfKill) == 0) error("wifi disabled by switch"); - if(ctlr->wifi == nil) + if(ctlr->wifi == nil){ ctlr->wifi = wifiattach(edev, transmit); + ctlr->wifi->rates = iwlrates; + } if(ctlr->fw == nil){ fw = readfirmware(fwname[ctlr->type]); @@ -2359,7 +2383,7 @@ again: edev->shutdown = iwlshutdown; edev->promiscuous = iwlpromiscuous; edev->multicast = nil; - edev->mbps = 10; + edev->mbps = 54; if(iwlinit(edev) < 0){ edev->ctlr = nil; diff --git a/sys/src/9/pc/wifi.c b/sys/src/9/pc/wifi.c index 2f4c63711..6d7a2536c 100644 --- a/sys/src/9/pc/wifi.c +++ b/sys/src/9/pc/wifi.c @@ -37,6 +37,15 @@ static char Sassoc[] = "associated"; static char Sunassoc[] = "unassociated"; static char Sblocked[] = "blocked"; /* no keys negotiated. only pass EAPOL frames */ +static uchar basicrates[] = { + 0x80 | 2, /* 1.0 Mb/s */ + 0x80 | 4, /* 2.0 Mb/s */ + 0x80 | 11, /* 5.5 Mb/s */ + 0x80 | 22, /* 11.0 Mb/s */ + + 0 +}; + static Block* wifidecrypt(Wifi *, Wnode *, Block *); static Block* wifiencrypt(Wifi *, Wnode *, Block *); @@ -187,6 +196,29 @@ nodelookup(Wifi *wifi, uchar *bssid, int new) return nn; } +static uchar* +putrates(uchar *p, uchar *rates) +{ + int n, m; + + 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; + } + return p; +} + static void wifiprobe(Wifi *wifi, Wnode *wn) { @@ -212,19 +244,14 @@ wifiprobe(Wifi *wifi, Wnode *wn) b->wp += WIFIHDRSIZE; p = b->wp; - *p++ = 0x00; /* set */ + *p++ = 0; /* set */ *p++ = n; memmove(p, wifi->essid, n); p += n; - *p++ = 1; /* RATES (BUG: these are all lies!) */ - *p++ = 4; - *p++ = 0x82; - *p++ = 0x84; - *p++ = 0x8b; - *p++ = 0x96; + p = putrates(p, wifi->rates); - *p++ = 0x03; /* ds parameter set */ + *p++ = 3; /* ds parameter set */ *p++ = 1; *p++ = wn->channel; @@ -283,17 +310,13 @@ sendassoc(Wifi *wifi, Wnode *bss) *p++ = 16; /* interval */ *p++ = 16>>8; + n = strlen(bss->ssid); *p++ = 0; /* SSID */ - *p = strlen(bss->ssid); - memmove(p+1, bss->ssid, *p); - p += 1+*p; + *p++ = n; + memmove(p, bss->ssid, n); + p += n; - *p++ = 1; /* RATES (BUG: these are all lies!) */ - *p++ = 4; - *p++ = 0x82; - *p++ = 0x84; - *p++ = 0x8b; - *p++ = 0x96; + p = putrates(p, wifi->rates); n = bss->rsnelen; if(n > 0){ @@ -346,10 +369,10 @@ recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len) } static void -recvbeacon(Wifi *, Wnode *wn, uchar *d, int len) +recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len) { static uchar wpa1oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; - uchar *e, *x; + uchar *e, *x, *p; uchar t, m[256/8]; if(len < 8+2+2) @@ -373,7 +396,7 @@ recvbeacon(Wifi *, Wnode *wn, uchar *d, int len) m[t/8] |= 1<<(t%8); switch(t){ - case 0x00: /* SSID */ + case 0: /* SSID */ len = 0; while(len < Essidlen && d+len < x && d[len] != 0) len++; @@ -384,16 +407,33 @@ recvbeacon(Wifi *, Wnode *wn, uchar *d, int len) wn->ssid[len] = 0; } break; - case 0x03: /* DSPARAMS */ + case 1: /* supported rates */ + case 50: /* extended rates */ + if(wn->minrate != nil || wn->maxrate != nil || wifi->rates == nil) + break; /* already set */ + while(d < x){ + t = *d++ & 0x7f; + for(p = wifi->rates; *p != 0; p++){ + if((*p & 0x7f) == t){ + if(wn->minrate == nil || t < (*wn->minrate & 0x7f)) + wn->minrate = p; + if(wn->maxrate == nil || t > (*wn->maxrate & 0x7f)) + wn->maxrate = p; + break; + } + } + } + break; + case 3: /* DSPARAMS */ if(d != x) wn->channel = d[0]; break; - case 0xdd: /* vendor specific */ + case 221: /* vendor specific */ len = x - d; if(len < sizeof(wpa1oui) || memcmp(d, wpa1oui, sizeof(wpa1oui)) != 0) break; /* no break */ - case 0x30: /* RSN information */ + case 48: /* RSN information */ len = x - &d[-2]; memmove(wn->brsne, &d[-2], len); wn->brsnelen = len; @@ -673,6 +713,8 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)) wifi->ether = ether; wifi->transmit = transmit; + wifi->rates = basicrates; + wifi->essid[0] = 0; memmove(wifi->bssid, ether->bcast, Eaddrlen); diff --git a/sys/src/9/pc/wifi.h b/sys/src/9/pc/wifi.h index bc451cf3d..9b878d192 100644 --- a/sys/src/9/pc/wifi.h +++ b/sys/src/9/pc/wifi.h @@ -37,6 +37,9 @@ struct Wnode ulong lastsend; ulong lastseen; + uchar *minrate; /* pointers into wifi->rates */ + uchar *maxrate; + /* stuff from beacon */ int ival; int cap; @@ -60,6 +63,9 @@ struct Wifi uchar bssid[Eaddrlen]; char essid[Essidlen+2]; + /* supported data rates by hardware */ + uchar *rates; + /* effective base station */ Wnode *bss;