]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add driver API to get current channel parameters
authorMathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
Mon, 6 Aug 2018 19:46:19 +0000 (15:46 -0400)
committerJouni Malinen <j@w1.fi>
Sun, 16 Dec 2018 16:35:30 +0000 (18:35 +0200)
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>
src/ap/ap_drv_ops.h
src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h

index db93fde7d6e3a005eea54fa04c740596555dd0d6..d45ab8462147a074591fa07ae8e1f5a8a533f338 100644 (file)
@@ -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 */
index 4ac9f16a0efcfdcb584e202e69895a1482ff66a7..a880aea7f31e959c8e28584e948b072d824bf3c2 100644 (file)
@@ -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
index 871a5d0b4a205b4b9d09db52faeec07d0579194d..2de15f20dec6dd04921b8371b0575cf205584e2f 100644 (file)
@@ -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,
index 078de23f794fd43290270cfb38e2d37b3bfeae9c..5581bb064501930d61a2a126a4cb4966062790c2 100644 (file)
@@ -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)
 {