]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
QCA vendor command support to set band to driver
authorSrinivas Dasari <dasaris@qti.qualcomm.com>
Mon, 27 Jul 2015 10:14:22 +0000 (15:44 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 28 Jul 2015 18:00:18 +0000 (21:00 +0300)
Add vendor command to pass SET setband command to the driver and read
the updated channel list from driver when this notification succeeds.
This allows the driver to update its internal channel lists based on
setband configuration.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/common/defs.h
src/common/qca-vendor.h
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_capa.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/driver_i.h
wpa_supplicant/wpa_supplicant_i.h

index 5b2d7c42bcb017ab0ff08f10c82a1da6032de908..eb080ea8a14d5a1f67c8b001321c5d5bdd0502f9 100644 (file)
@@ -328,4 +328,10 @@ enum mesh_plink_state {
        PLINK_BLOCKED,
 };
 
+enum set_band {
+       WPA_SETBAND_AUTO,
+       WPA_SETBAND_5G,
+       WPA_SETBAND_2G
+};
+
 #endif /* DEFS_H */
index 1c8496d481e570553b060590407923230937bfee..2a6e24298639673f25377635c73942df5b6762ed 100644 (file)
@@ -155,6 +155,7 @@ enum qca_nl80211_vendor_subcmds {
        QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102,
        QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
        QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
+       QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
 };
 
 
@@ -182,6 +183,8 @@ enum qca_wlan_vendor_attr {
        QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10,
        /* Unsigned 32-bit value */
        QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
+       /* Unsigned 32-bit value from enum qca_set_band. */
+       QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
        /* keep last */
        QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
        QCA_WLAN_VENDOR_ATTR_MAX        = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@@ -314,4 +317,10 @@ enum qca_iface_type {
        QCA_IFACE_TYPE_TDLS,
 };
 
+enum qca_set_band {
+       QCA_SETBAND_AUTO,
+       QCA_SETBAND_5G,
+       QCA_SETBAND_2G,
+};
+
 #endif /* QCA_VENDOR_H */
index 7c8bca2e5ef0dde8278a78b1db980f87a4695d03..6e39aa3e0b1aff5dab5955e195b2749c7488a5cd 100644 (file)
@@ -3387,6 +3387,14 @@ struct wpa_driver_ops {
         * indicates support for such offloading (WPA_DRIVER_FLAGS_ACS_OFFLOAD).
         */
        int (*do_acs)(void *priv, struct drv_acs_params *params);
+
+       /**
+        * set_band - Notify driver of band selection
+        * @priv: Private driver interface data
+        * @band: The selected band(s)
+        * Returns 0 on success, -1 on failure
+        */
+       int (*set_band)(void *priv, enum set_band band);
 };
 
 
index 69e2f27893abd9b8ebdb3306ee2ee2fbc76ab49d..a6441e3dc98310cc3af15023250c96c6e5c8b883 100644 (file)
@@ -8435,6 +8435,53 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
 }
 
 
+static int nl80211_set_band(void *priv, enum set_band band)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg;
+       struct nlattr *data;
+       int ret;
+       enum qca_set_band qca_band;
+
+       if (!drv->setband_vendor_cmd_avail)
+               return -1;
+
+       switch (band) {
+       case WPA_SETBAND_AUTO:
+               qca_band = QCA_SETBAND_AUTO;
+               break;
+       case WPA_SETBAND_5G:
+               qca_band = QCA_SETBAND_5G;
+               break;
+       case WPA_SETBAND_2G:
+               qca_band = QCA_SETBAND_2G;
+               break;
+       default:
+               return -1;
+       }
+
+       if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+                       QCA_NL80211_VENDOR_SUBCMD_SETBAND) ||
+           !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+           nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) {
+               nlmsg_free(msg);
+               return -ENOBUFS;
+       }
+       nla_nest_end(msg, data);
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+       if (ret) {
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: Driver setband function failed: %s",
+                          strerror(errno));
+       }
+       return ret;
+}
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .name = "nl80211",
        .desc = "Linux nl80211/cfg80211",
@@ -8542,4 +8589,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .add_tx_ts = nl80211_add_ts,
        .del_tx_ts = nl80211_del_ts,
        .do_acs = wpa_driver_do_acs,
+       .set_band = nl80211_set_band,
 };
index acfe959e4214ca35532bc180a07870c4adab8776..1536d2ffbd2a2ea3461f374170ebf353a6ea9845 100644 (file)
@@ -145,6 +145,7 @@ struct wpa_driver_nl80211_data {
        unsigned int get_features_vendor_cmd_avail:1;
        unsigned int set_rekey_offload:1;
        unsigned int p2p_go_ctwindow_supported:1;
+       unsigned int setband_vendor_cmd_avail:1;
 
        u64 remain_on_chan_cookie;
        u64 send_action_cookie;
index e23c57eddebb024746f9eb380ca8f492553cc1c1..4929cea21300ab5395b2539f7593e78c1d1d935f 100644 (file)
@@ -593,6 +593,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                                        drv->capa.flags |=
                                                WPA_DRIVER_FLAGS_ACS_OFFLOAD;
                                        break;
+                               case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
+                                       drv->setband_vendor_cmd_avail = 1;
+                                       break;
                                }
                        }
 
index f7882ca5445274dbdd930c5a0e15cc26fe308dce..41f9090ef5ec495753dc777b73db07b862cdb878 100644 (file)
@@ -286,6 +286,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
 }
 
 
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+{
+       union wpa_event_data event;
+
+       if (os_strcmp(band, "AUTO") == 0)
+               wpa_s->setband = WPA_SETBAND_AUTO;
+       else if (os_strcmp(band, "5G") == 0)
+               wpa_s->setband = WPA_SETBAND_5G;
+       else if (os_strcmp(band, "2G") == 0)
+               wpa_s->setband = WPA_SETBAND_2G;
+       else
+               return -1;
+
+       if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+               os_memset(&event, 0, sizeof(event));
+               event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+               event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+               wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
+       }
+
+       return 0;
+}
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                                         char *cmd)
 {
@@ -449,14 +473,7 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                ret = wpas_ctrl_set_blob(wpa_s, value);
 #endif /* CONFIG_NO_CONFIG_BLOBS */
        } else if (os_strcasecmp(cmd, "setband") == 0) {
-               if (os_strcmp(value, "AUTO") == 0)
-                       wpa_s->setband = WPA_SETBAND_AUTO;
-               else if (os_strcmp(value, "5G") == 0)
-                       wpa_s->setband = WPA_SETBAND_5G;
-               else if (os_strcmp(value, "2G") == 0)
-                       wpa_s->setband = WPA_SETBAND_2G;
-               else
-                       ret = -1;
+               ret = wpas_ctrl_set_band(wpa_s, value);
        } else {
                value[-1] = '=';
                ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
index 1fcb18067edc7c35190977f526727253d62db5c1..d1f9f8be1be432ce01e5e67b3010e9bd136c9fe0 100644 (file)
@@ -885,4 +885,12 @@ static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s,
 }
 #endif /* CONFIG_MACSEC */
 
+static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
+                                 enum set_band band)
+{
+       if (!wpa_s->driver->set_band)
+               return -1;
+       return wpa_s->driver->set_band(wpa_s->drv_priv, band);
+}
+
 #endif /* DRIVER_I_H */
index 1338e17d8e826fe80fc291fb68bf3698055c1a40..0636ee45473954ab7dbe366ae8234168e332a008 100644 (file)
@@ -482,7 +482,7 @@ struct wpa_supplicant {
        struct wpa_ssid_value *disallow_aps_ssid;
        size_t disallow_aps_ssid_count;
 
-       enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
+       enum set_band setband;
 
        /* Preferred network for the next connection attempt */
        struct wpa_ssid *next_ssid;