nl80211: Add build option for QCA vendor extensions
[mech_eap.git] / src / drivers / driver_nl80211_capa.c
index 13c446f..5c82546 100644 (file)
@@ -575,22 +575,39 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                                continue;
                        }
                        vinfo = nla_data(nl);
-                       switch (vinfo->subcmd) {
-                       case QCA_NL80211_VENDOR_SUBCMD_TEST:
-                               drv->vendor_cmd_test_avail = 1;
-                               break;
-                       case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
-                               drv->roaming_vendor_cmd_avail = 1;
-                               break;
-                       case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
-                               drv->dfs_vendor_cmd_avail = 1;
-                               break;
-                       case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
-                               drv->get_features_vendor_cmd_avail = 1;
-                               break;
-                       case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
-                               drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD;
-                               break;
+                       if (vinfo->vendor_id == OUI_QCA) {
+                               switch (vinfo->subcmd) {
+                               case QCA_NL80211_VENDOR_SUBCMD_TEST:
+                                       drv->vendor_cmd_test_avail = 1;
+                                       break;
+#ifdef CONFIG_DRIVER_NL80211_QCA
+                               case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
+                                       drv->roaming_vendor_cmd_avail = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
+                                       drv->dfs_vendor_cmd_avail = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
+                                       drv->get_features_vendor_cmd_avail = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST:
+                                       drv->get_pref_freq_list = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL:
+                                       drv->set_prob_oper_freq = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
+                                       drv->capa.flags |=
+                                               WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
+                                       drv->setband_vendor_cmd_avail = 1;
+                                       break;
+                               case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
+                                       drv->scan_vendor_cmd_avail = 1;
+                                       break;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+                               }
                        }
 
                        wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
@@ -690,6 +707,8 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
 }
 
 
+#ifdef CONFIG_DRIVER_NL80211_QCA
+
 static int dfs_info_handler(struct nl_msg *msg, void *arg)
 {
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
@@ -745,6 +764,7 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv)
 struct features_info {
        u8 *flags;
        size_t flags_len;
+       struct wpa_driver_capa *capa;
 };
 
 
@@ -770,6 +790,19 @@ static int features_info_handler(struct nl_msg *msg, void *arg)
                        info->flags = nla_data(attr);
                        info->flags_len = nla_len(attr);
                }
+               attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA];
+               if (attr)
+                       info->capa->conc_capab = nla_get_u32(attr);
+
+               attr = tb_vendor[
+                       QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND];
+               if (attr)
+                       info->capa->max_conc_chan_2_4 = nla_get_u32(attr);
+
+               attr = tb_vendor[
+                       QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND];
+               if (attr)
+                       info->capa->max_conc_chan_5_0 = nla_get_u32(attr);
        }
 
        return NL_SKIP;
@@ -804,14 +837,24 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
        }
 
        os_memset(&info, 0, sizeof(info));
+       info.capa = &drv->capa;
        ret = send_and_recv_msgs(drv, msg, features_info_handler, &info);
        if (ret || !info.flags)
                return;
 
        if (check_feature(QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD, &info))
                drv->capa.flags |= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD;
+
+       if (check_feature(QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY, &info))
+               drv->capa.flags |= WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
+
+       if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS,
+                         &info))
+               drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
 }
 
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
 
 int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
 {
@@ -892,9 +935,21 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
        if (!drv->use_monitor && !info.data_tx_status)
                drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
 
+#ifdef CONFIG_DRIVER_NL80211_QCA
        qca_nl80211_check_dfs_capa(drv);
        qca_nl80211_get_features(drv);
 
+       /*
+        * To enable offchannel simultaneous support in wpa_supplicant, the
+        * underlying driver needs to support the same along with offchannel TX.
+        * Offchannel TX support is needed since remain_on_channel and
+        * action_tx use some common data structures and hence cannot be
+        * scheduled simultaneously.
+        */
+       if (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))
+               drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
        return 0;
 }