git: 9front

Download patch

ref: 1f26c5d16281d4cd2124f0932d84cf7a7fc97930
parent: b8ade0f0e74db49b8d1686e29a5d3dabb3a2d93b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Aug 6 19:13:23 EDT 2018

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.

--- a/sys/src/9/port/wifi.c
+++ b/sys/src/9/port/wifi.c
@@ -173,7 +173,7 @@
 		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 @@
 		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 @@
 }
 
 static uchar*
-putrates(uchar *p, uchar *rates)
+putrates(uchar *p, uchar *rates, ulong valid, ulong basic)
 {
-	int n, m;
+	int n, i, j;
 
-	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){
+	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;
+
 		/* 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 @@
 	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 @@
 	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 @@
 			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 @@
 						break;
 					}
 				}
-				wn->actrate = wn->maxrate;
+				d++;
 			}
+			if(wn->actrate == nil)
+				wn->actrate = wn->maxrate;
 			break;
 		case 3:		/* DSPARAMS */
 			if(d != x)
--- a/sys/src/9/port/wifi.h
+++ b/sys/src/9/port/wifi.h
@@ -43,6 +43,9 @@
 	uchar	*maxrate;
 	uchar	*actrate;
 
+	ulong	validrates;	/* bitmap on wifi->rates */
+	ulong	basicrates;
+
 	ulong	txcount;	/* statistics for rate adaption */
 	ulong	txerror;
 
--