diff --git a/info_scr.c b/info_scr.c index acb1a23..5fb3e72 100644 --- a/info_scr.c +++ b/info_scr.c @@ -45,16 +45,22 @@ void sampling_do_poll(void) { iw_getstat(&cur); iw_nl80211_get_linkstat(&ls); - iw_cache_update(&cur, &ls); + iw_cache_update(&ls); } static void display_levels(void) { + static float qual, signal, noise, ssnr; char nscale[2] = { cur.dbm.signal - 20, cur.dbm.signal }, lvlscale[2] = { -40, -20}; char tmp[0x100]; - static float qual, signal, noise, ssnr; int line; + bool noise_data_valid = iw_nl80211_have_survey_data(&ls); + int sig_level = ls.signal_avg ?: ls.signal; + + /* See comments in iw_cache_update */ + if (sig_level == 0) + sig_level = ls.bss_signal; for (line = 1; line <= WH_LEVEL; line++) mvwclrtoborder(w_levels, line, 1); @@ -68,7 +74,7 @@ static void display_levels(void) line = 1; /* Noise data is rare. Use the space for spreading out. */ - if (!iw_nl80211_have_survey_data(&ls)) + if (!noise_data_valid) line++; if (cur.stat.qual.updated & IW_QUAL_QUAL_INVALID) { @@ -88,11 +94,11 @@ static void display_levels(void) /* Spacer */ line++; - if (!iw_nl80211_have_survey_data(&ls)) + if (!noise_data_valid) line++; - if (!(cur.stat.qual.updated & IW_QUAL_LEVEL_INVALID)) { - signal = ewma(signal, cur.dbm.signal, conf.meter_decay / 100.0); + if (sig_level != 0) { + signal = ewma(signal, sig_level, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "signal level: "); sprintf(tmp, "%.0f dBm (%s) ", signal, dbm2units(signal)); @@ -110,7 +116,7 @@ static void display_levels(void) line++; - if (iw_nl80211_have_survey_data(&ls)) { + if (noise_data_valid) { noise = ewma(noise, ls.survey.noise, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "noise level: "); diff --git a/iw_if.h b/iw_if.h index a078762..e6fdbb7 100644 --- a/iw_if.h +++ b/iw_if.h @@ -207,11 +207,7 @@ struct iw_stat { /* * Periodic sampling of wireless statistics via timer alarm */ -/* FIXME: remove forward declaration */ -struct iw_nl80211_linkstat; - extern void iw_getstat(struct iw_stat *stat); -extern void iw_cache_update(struct iw_stat *iw, struct iw_nl80211_linkstat *ls); extern void sampling_init(void (*sampling_handler)(int)); extern void sampling_do_poll(void); diff --git a/iw_nl80211.c b/iw_nl80211.c index 197f18d..9b36ed7 100644 --- a/iw_nl80211.c +++ b/iw_nl80211.c @@ -351,6 +351,14 @@ static int link_handler(struct nl_msg *msg, void *arg) if (!bss[NL80211_BSS_STATUS]) return NL_SKIP; + if (bss[NL80211_BSS_SIGNAL_UNSPEC]) + ls->bss_signal_qual = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); + + if (bss[NL80211_BSS_SIGNAL_MBM]) { + int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); + ls->bss_signal = s / 100; + } + ls->status = nla_get_u32(bss[NL80211_BSS_STATUS]); switch (ls->status) { case NL80211_BSS_STATUS_ASSOCIATED: /* apparently no longer used */ diff --git a/iw_nl80211.h b/iw_nl80211.h index 13cf58f..997d889 100644 --- a/iw_nl80211.h +++ b/iw_nl80211.h @@ -16,7 +16,8 @@ #define BIT(x) (1ULL<<(x)) /* from iw:iw.h */ -/** struct msg_attribute - attributes to nla_put into the message +/** + * struct msg_attribute - attributes to nla_put into the message * @type: type of the attribute * @len: attribute length * @data: pointer to data area of length @len @@ -119,12 +120,14 @@ extern void iw_nl80211_get_survey(struct iw_nl80211_survey *sd); * @beacon_int: beacon interval in Time Units of 1024usec * @dtim_period: DTIM period for beaconing * @beacon_avg_sig: average beacon signal (in dBm) - * @beacons: number of beacons received + * @beacons: number of beacons received * @beacon_loss: count of times beacon loss was detected - * @signal: signal strength in dBm - * @signal_avg: average signal strength in dBm - * @tx_bitrate: string describing current TX bitrate - * @rx_bitrate: string describing current RX bitrate + * @signal: signal strength in dBm (0 if not present) + * @signal_avg: average signal strength in dBm + * @bss_signal: signal strength of BSS probe in dBm (or 0) + * @bss_signal_qual: unitless signal strength of BSS probe, 0..100 + * @tx_bitrate: string describing current TX bitrate + * @rx_bitrate: string describing current RX bitrate * @authorized: FIXME * @authenticated: FIXME * @long_preamble: whether using long or short preamble @@ -161,6 +164,9 @@ struct iw_nl80211_linkstat { int8_t signal, signal_avg; + int8_t bss_signal; + uint8_t bss_signal_qual; + char tx_bitrate[100], rx_bitrate[100]; @@ -177,6 +183,7 @@ struct iw_nl80211_linkstat { struct iw_nl80211_survey survey; }; extern void iw_nl80211_get_linkstat(struct iw_nl80211_linkstat *ls); +extern void iw_cache_update(struct iw_nl80211_linkstat *ls); /* Indicate whether @ls contains usable channel survey data */ static inline bool iw_nl80211_have_survey_data(struct iw_nl80211_linkstat *ls) diff --git a/lhist_scr.c b/lhist_scr.c index 44df34a..2595b45 100644 --- a/lhist_scr.c +++ b/lhist_scr.c @@ -118,24 +118,34 @@ static struct iw_levelstat iw_cache_get(const uint32_t index) return iw_stats_cache[(count - index) % IW_STACKSIZE]; } -// XXX FIXME: rewrite in terms of struct iw_nl80211_linkstat -void iw_cache_update(struct iw_stat *iw, - struct iw_nl80211_linkstat *ls) +void iw_cache_update(struct iw_nl80211_linkstat *ls) { static struct iw_levelstat prev, avg = IW_LSTAT_INIT; static int slot; + int sig_level = ls->signal_avg ?: ls->signal; - if (! (iw->stat.qual.updated & IW_QUAL_LEVEL_INVALID)) { + /* + * If hardware does not support dBm signal level, it will not + * be filled in, and show up as 0. Try to fall back to the BSS + * probe where again a 0 dBm value reflects 'not initialized'. + */ + if (sig_level == 0) + sig_level = ls->bss_signal; + + if (sig_level == 0) { + avg.flags |= IW_QUAL_LEVEL_INVALID; + } else { avg.flags &= ~IW_QUAL_LEVEL_INVALID; - avg.signal += iw->dbm.signal / conf.slotsize; - track_extrema(iw->dbm.signal, &e_signal); + avg.signal += (float)sig_level / conf.slotsize; + track_extrema(sig_level, &e_signal); } if (iw_nl80211_have_survey_data(ls)) { avg.flags &= ~IW_QUAL_NOISE_INVALID; avg.noise += (float)ls->survey.noise / conf.slotsize; track_extrema(ls->survey.noise, &e_noise); - track_extrema(iw->dbm.signal - ls->survey.noise, &e_snr); + if (! (avg.flags & IW_QUAL_LEVEL_INVALID)) + track_extrema(sig_level - ls->survey.noise, &e_snr); } if (++slot >= conf.slotsize) {