|
@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
|
|
|
|
+ int attr)
|
|
|
|
+{
|
|
|
|
+ struct nlattr *rate;
|
|
|
|
+ u16 bitrate;
|
|
|
|
+
|
|
|
|
+ rate = nla_nest_start(msg, attr);
|
|
|
|
+ if (!rate)
|
|
|
|
+ goto nla_put_failure;
|
|
|
|
+
|
|
|
|
+ /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
|
|
|
|
+ bitrate = cfg80211_calculate_bitrate(info);
|
|
|
|
+ if (bitrate > 0)
|
|
|
|
+ NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
|
|
|
|
+
|
|
|
|
+ if (info->flags & RATE_INFO_FLAGS_MCS)
|
|
|
|
+ NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
|
|
|
|
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
|
|
|
|
+ NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
|
|
|
|
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
|
|
|
|
+ NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
|
|
|
|
+
|
|
|
|
+ nla_nest_end(msg, rate);
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+nla_put_failure:
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
|
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
|
int flags, struct net_device *dev,
|
|
int flags, struct net_device *dev,
|
|
const u8 *mac_addr, struct station_info *sinfo)
|
|
const u8 *mac_addr, struct station_info *sinfo)
|
|
{
|
|
{
|
|
void *hdr;
|
|
void *hdr;
|
|
- struct nlattr *sinfoattr, *txrate;
|
|
|
|
- u16 bitrate;
|
|
|
|
|
|
+ struct nlattr *sinfoattr;
|
|
|
|
|
|
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
|
|
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
|
|
if (!hdr)
|
|
if (!hdr)
|
|
@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
|
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
|
|
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
|
|
sinfo->signal_avg);
|
|
sinfo->signal_avg);
|
|
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
|
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
|
- txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
|
|
|
|
- if (!txrate)
|
|
|
|
|
|
+ if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
|
|
|
|
+ NL80211_STA_INFO_TX_BITRATE))
|
|
|
|
+ goto nla_put_failure;
|
|
|
|
+ }
|
|
|
|
+ if (sinfo->filled & STATION_INFO_RX_BITRATE) {
|
|
|
|
+ if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
|
|
|
|
+ NL80211_STA_INFO_RX_BITRATE))
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
-
|
|
|
|
- /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
|
|
|
|
- bitrate = cfg80211_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);
|
|
|
|
}
|
|
}
|
|
if (sinfo->filled & STATION_INFO_RX_PACKETS)
|
|
if (sinfo->filled & STATION_INFO_RX_PACKETS)
|
|
NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
|
|
NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
|