Search Linux Wireless

[PATCH 2/2] Add signal strength and bandwith to nl80211station info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds the total transmission bitrate for adhoc station even for 
802.11n transmissions. It must be applied after the first patch of this 
series.

-------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..b5abe36 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_TOTAL: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_TOTAL,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9268b2..8689744 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1080,6 +1080,35 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = rate->mcs >> 3;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1123,13 +1152,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_TOTAL,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..b5abe36 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_TOTAL: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_TOTAL,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9268b2..8689744 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1080,6 +1080,35 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = rate->mcs >> 3;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1123,13 +1152,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_TOTAL,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)

Attachment: signature.asc
Description: This is a digitally signed message part.


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux