Add driver API to get current channel parameters
This adds driver API functions to get the current operating channel parameters. This encompasses the center frequency, channel bandwidth, frequency segment 1 index (for 80+80 channels), and so on. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
This commit is contained in:
parent
183a6c93cd
commit
7f00dc6e15
4 changed files with 109 additions and 0 deletions
|
@ -356,4 +356,12 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
|
|||
return hapd->driver->stop_ap(hapd->drv_priv);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
|
||||
struct wpa_channel_info *ci)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->channel_info)
|
||||
return -1;
|
||||
return hapd->driver->channel_info(hapd->drv_priv, ci);
|
||||
}
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
||||
|
|
|
@ -1942,6 +1942,26 @@ struct wpa_signal_info {
|
|||
int center_frq2;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_channel_info - Information about the current channel
|
||||
* @frequency: Center frequency of the primary 20 MHz channel
|
||||
* @chanwidth: Width of the current operating channel
|
||||
* @sec_channel: Location of the secondary 20 MHz channel (either +1 or -1).
|
||||
* This field is only filled in when using a 40 MHz channel.
|
||||
* @center_frq1: Center frequency of frequency segment 0
|
||||
* @center_frq2: Center frequency of frequency segment 1 (for 80+80 channels)
|
||||
* @seg1_idx: Frequency segment 1 index when using a 80+80 channel. This is
|
||||
* derived from center_frq2 for convenience.
|
||||
*/
|
||||
struct wpa_channel_info {
|
||||
u32 frequency;
|
||||
enum chan_width chanwidth;
|
||||
int sec_channel;
|
||||
int center_frq1;
|
||||
int center_frq2;
|
||||
u8 seg1_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct beacon_data - Beacon data
|
||||
* @head: Head portion of Beacon frame (before TIM IE)
|
||||
|
@ -3377,6 +3397,14 @@ struct wpa_driver_ops {
|
|||
*/
|
||||
int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info);
|
||||
|
||||
/**
|
||||
* channel_info - Get parameters of the current operating channel
|
||||
* @priv: Private driver interface data
|
||||
* @channel_info: Channel info structure
|
||||
* Returns: 0 on success, negative (<0) on failure
|
||||
*/
|
||||
int (*channel_info)(void *priv, struct wpa_channel_info *channel_info);
|
||||
|
||||
/**
|
||||
* set_authmode - Set authentication algorithm(s) for static WEP
|
||||
* @priv: Private driver interface data
|
||||
|
|
|
@ -1539,6 +1539,70 @@ int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static int get_channel_info(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *tb[NL80211_ATTR_MAX + 1] = { 0 };
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct wpa_channel_info *chan_info = arg;
|
||||
|
||||
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||
genlmsg_attrlen(gnlh, 0), NULL);
|
||||
|
||||
os_memset(chan_info, 0, sizeof(struct wpa_channel_info));
|
||||
chan_info->chanwidth = CHAN_WIDTH_UNKNOWN;
|
||||
|
||||
if (tb[NL80211_ATTR_WIPHY_FREQ])
|
||||
chan_info->frequency =
|
||||
nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (tb[NL80211_ATTR_CHANNEL_WIDTH])
|
||||
chan_info->chanwidth = convert2width(
|
||||
nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
|
||||
if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
|
||||
enum nl80211_channel_type ct =
|
||||
nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
|
||||
|
||||
switch (ct) {
|
||||
case NL80211_CHAN_HT40MINUS:
|
||||
chan_info->sec_channel = -1;
|
||||
break;
|
||||
case NL80211_CHAN_HT40PLUS:
|
||||
chan_info->sec_channel = 1;
|
||||
break;
|
||||
default:
|
||||
chan_info->sec_channel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tb[NL80211_ATTR_CENTER_FREQ1])
|
||||
chan_info->center_frq1 =
|
||||
nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
|
||||
if (tb[NL80211_ATTR_CENTER_FREQ2])
|
||||
chan_info->center_frq2 =
|
||||
nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
|
||||
|
||||
if (chan_info->center_frq2) {
|
||||
u8 seg1_idx = 0;
|
||||
|
||||
if (ieee80211_freq_to_chan(chan_info->center_frq2, &seg1_idx) !=
|
||||
NUM_HOSTAPD_MODES)
|
||||
chan_info->seg1_idx = seg1_idx;
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
|
||||
static int nl80211_channel_info(void *priv, struct wpa_channel_info *ci)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct nl_msg *msg;
|
||||
|
||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
|
||||
return send_and_recv_msgs(drv, msg, get_channel_info, ci);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
|
||||
void *handle)
|
||||
{
|
||||
|
@ -10728,6 +10792,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.resume = wpa_driver_nl80211_resume,
|
||||
.signal_monitor = nl80211_signal_monitor,
|
||||
.signal_poll = nl80211_signal_poll,
|
||||
.channel_info = nl80211_channel_info,
|
||||
.send_frame = nl80211_send_frame,
|
||||
.set_param = nl80211_set_param,
|
||||
.get_radio_name = nl80211_get_radio_name,
|
||||
|
|
|
@ -492,6 +492,14 @@ static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_channel_info *ci)
|
||||
{
|
||||
if (wpa_s->driver->channel_info)
|
||||
return wpa_s->driver->channel_info(wpa_s->drv_priv, ci);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s,
|
||||
struct hostap_sta_driver_data *sta)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue