wlan: Get the supported features by driver/firmware
Get the supported features by driver/firmware using vendor
commands. Middleware can query for the feature capability and
respond to the upper layers based on the result.
Change-Id: Ib78a91a66c1abc3c49f5879edd8331dc0b9485a0
CRs-Fixed: 718716
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 6c31f3e..5e3be45 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -566,6 +566,9 @@
};
extern struct net_device_ops net_ops_struct;
+#ifdef FEATURE_WLAN_SCAN_PNO
+static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter);
+#endif
#ifdef WLAN_NL80211_TESTMODE
enum wlan_hdd_tm_attr
@@ -4295,6 +4298,116 @@
return (wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer));
}
+static int
+wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ void *data, int data_len)
+{
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+ struct sk_buff *skb = NULL;
+ tANI_U32 fset = 0;
+
+ if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
+ hddLog(LOG1, FL("Infra Station mode is supported by driver"));
+ fset |= WIFI_FEATURE_INFRA;
+ }
+
+ if (TRUE == hdd_is_5g_supported(pHddCtx)) {
+ hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
+ fset |= WIFI_FEATURE_INFRA_5G;
+ }
+
+#ifdef WLAN_FEATURE_P2P
+ if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
+ (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
+ hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
+ fset |= WIFI_FEATURE_P2P;
+ }
+#endif
+
+ /* Soft-AP is supported currently by default */
+ fset |= WIFI_FEATURE_SOFT_AP;
+
+#ifdef WLAN_FEATURE_EXTSCAN
+ if ((TRUE == pHddCtx->cfg_ini->fEnableEXTScan) &&
+ sme_IsFeatureSupportedByFW(EXTENDED_SCAN)) {
+ hddLog(LOG1, FL("EXTScan is supported by firmware"));
+ fset |= WIFI_FEATURE_EXTSCAN;
+ }
+#endif
+
+#ifdef WLAN_FEATURE_NAN
+ if (sme_IsFeatureSupportedByFW(NAN)) {
+ hddLog(LOG1, FL("NAN is supported by firmware"));
+ fset |= WIFI_FEATURE_NAN;
+ }
+#endif
+
+ /* D2D RTT is not supported currently by default */
+ if (sme_IsFeatureSupportedByFW(RTT)) {
+ hddLog(LOG1, FL("RTT is supported by firmware"));
+ fset |= WIFI_FEATURE_D2AP_RTT;
+ }
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+ if (fset & WIFI_FEATURE_EXTSCAN) {
+ hddLog(LOG1, FL("Batch scan is supported as extscan is supported"));
+ fset &= ~WIFI_FEATURE_BATCH_SCAN;
+ } else if (sme_IsFeatureSupportedByFW(BATCH_SCAN)) {
+ hddLog(LOG1, FL("Batch scan is supported by firmware"));
+ fset |= WIFI_FEATURE_BATCH_SCAN;
+ }
+#endif
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+ if (pHddCtx->cfg_ini->configPNOScanSupport &&
+ (eHAL_STATUS_SUCCESS == wlan_hdd_is_pno_allowed(pAdapter))) {
+ hddLog(LOG1, FL("PNO is supported by firmware"));
+ fset |= WIFI_FEATURE_PNO;
+ }
+#endif
+
+ /* STA+STA is supported currently by default */
+ fset |= WIFI_FEATURE_ADDITIONAL_STA;
+
+#ifdef FEATURE_WLAN_TDLS
+ if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSSupport) &&
+ sme_IsFeatureSupportedByFW(TDLS)) {
+ hddLog(LOG1, FL("TDLS is supported by firmware"));
+ fset |= WIFI_FEATURE_TDLS;
+ }
+
+ /* TDLS_OFFCHANNEL is not supported currently by default */
+#endif
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+ /* AP+STA concurrency is supported currently by default */
+ fset |= WIFI_FEATURE_AP_STA;
+#endif
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
+ NLMSG_HDRLEN);
+
+ if (!skb) {
+ hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
+ return -EINVAL;
+ }
+ hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
+
+ if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
+ hddLog(LOGE, FL("nla put fail"));
+ goto nla_put_failure;
+ }
+
+ return cfg80211_vendor_cmd_reply(skb);
+
+nla_put_failure:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
{
@@ -4423,6 +4536,13 @@
WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wlan_hdd_cfg80211_exttdls_get_status
},
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wlan_hdd_cfg80211_get_supported_features
+ },
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,