summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorHenning Rogge <hrogge@googlemail.com>2008-12-11 21:04:19 (GMT)
committerJohn W. Linville <linville@tuxdriver.com>2008-12-19 20:04:54 (GMT)
commit420e7fabd9c6d907280ed6b3e40eef425c5d8d8d (patch)
tree6effc9f9386746d1aeb953e32fe82b0a5a5fdf18 /net
parent221b3d60cbb2740ec7d46a4f1ea6d3318a112e51 (diff)
downloadlinux-420e7fabd9c6d907280ed6b3e40eef425c5d8d8d.tar.xz
nl80211: Add signal strength and bandwith to nl80211station info
This patch adds signal strength and transmission bitrate to the station_info of nl80211. Signed-off-by: Henning Rogge <rogge@fgan.de> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c25
-rw-r--r--net/wireless/nl80211.c58
2 files changed, 81 insertions, 2 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..23b5eea 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->filled = STATION_INFO_INACTIVE_TIME |
STATION_INFO_RX_BYTES |
- STATION_INFO_TX_BYTES;
+ STATION_INFO_TX_BYTES |
+ STATION_INFO_TX_BITRATE;
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
sinfo->rx_bytes = sta->rx_bytes;
sinfo->tx_bytes = sta->tx_bytes;
+ if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = (s8)sta->last_signal;
+ }
+
+ sinfo->txrate.flags = 0;
+ if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+ if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+ struct ieee80211_supported_band *sband;
+ sband = sta->local->hw.wiphy->bands[
+ sta->local->hw.conf.channel->band];
+ sinfo->txrate.legacy =
+ sband->bitrates[sta->last_tx_rate.idx].bitrate;
+ } else
+ sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH
sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ 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;
+
+ /* the formula below does only work for MCS values smaller than 32 */
+ if (rate->mcs >= 32)
+ return 0;
+
+ modulation = rate->mcs & 7;
+ streams = (rate->mcs >> 3) + 1;
+
+ 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 / 9) * 10;
+
+ /* 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)
{
void *hdr;
- struct nlattr *sinfoattr;
+ struct nlattr *sinfoattr, *txrate;
+ u16 bitrate;
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
if (sinfo->filled & STATION_INFO_PLINK_STATE)
NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
sinfo->plink_state);
+ if (sinfo->filled & STATION_INFO_SIGNAL)
+ NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+ sinfo->signal);
+ if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+ txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+ if (!txrate)
+ goto nla_put_failure;
+
+ /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+ bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+ if (bitrate > 0)
+ NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
+ 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)
+ NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+ nla_nest_end(msg, txrate);
+ }
nla_nest_end(msg, sinfoattr);
return genlmsg_end(msg, hdr);