diff options
author | Peng Xu <pxu@codeaurora.org> | 2018-03-14 14:11:37 -0700 |
---|---|---|
committer | Ahmed ElArabawy <arabawy@google.com> | 2019-02-06 10:03:30 -0800 |
commit | 1abf1675d4bb7f595d48de1f56aaee435c604279 (patch) | |
tree | 3b0ee65e0896aaa0e01649ea1a2428f8aa6a386d /qcwcn/wifi_hal | |
parent | 4333c0e76d0c8427e308d866ef0349753d2c984d (diff) | |
download | wlan-1abf1675d4bb7f595d48de1f56aaee435c604279.tar.gz |
WiFi-HAL: Add user hint sub-type to set country code commmand
Add new user hint sub-type NL80211_USER_REG_HINT_CELL_BASE to
wifi_set_country_code command if the feature is supported by
host driver.
Bug: 121154896
Test: Regression test
Change-Id: Ie1c0da1cc75aba02809ffd0f5d76bdb4f2ec680c
CRs-fixed: 2205885
Diffstat (limited to 'qcwcn/wifi_hal')
-rw-r--r-- | qcwcn/wifi_hal/common.h | 8 | ||||
-rw-r--r-- | qcwcn/wifi_hal/ifaceeventhandler.cpp | 41 | ||||
-rw-r--r-- | qcwcn/wifi_hal/ifaceeventhandler.h | 2 | ||||
-rw-r--r-- | qcwcn/wifi_hal/qca-vendor_copy.h | 4 | ||||
-rw-r--r-- | qcwcn/wifi_hal/wifi_hal.cpp | 48 | ||||
-rw-r--r-- | qcwcn/wifi_hal/wificonfig.cpp | 21 |
6 files changed, 124 insertions, 0 deletions
diff --git a/qcwcn/wifi_hal/common.h b/qcwcn/wifi_hal/common.h index 5604669..3ea962d 100644 --- a/qcwcn/wifi_hal/common.h +++ b/qcwcn/wifi_hal/common.h @@ -89,6 +89,11 @@ typedef struct { wifi_roaming_capabilities roaming_capa; } wifi_capa; +typedef struct { + u8 *flags; + size_t flags_len; +} features_info; + struct gscan_event_handlers_s; struct rssi_monitor_event_handler_s; struct cld80211_ctx; @@ -115,6 +120,9 @@ typedef struct hal_info_s { int num_interfaces; // number of interfaces feature_set supported_feature_set; + /* driver supported features defined by enum qca_wlan_vendor_features that + can be queried by vendor command QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */ + features_info driver_supported_features; u32 supported_logger_feature_set; // add other details int user_sock_arg; diff --git a/qcwcn/wifi_hal/ifaceeventhandler.cpp b/qcwcn/wifi_hal/ifaceeventhandler.cpp index b0133c0..8750999 100644 --- a/qcwcn/wifi_hal/ifaceeventhandler.cpp +++ b/qcwcn/wifi_hal/ifaceeventhandler.cpp @@ -205,11 +205,16 @@ WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id, mCapa = &(info->capa); mfilter_packet_read_buffer = NULL; mfilter_packet_length = 0; + memset(&mDriverFeatures, 0, sizeof(mDriverFeatures)); } WifihalGeneric::~WifihalGeneric() { mCapa = NULL; + if (mDriverFeatures.flags != NULL) { + free(mDriverFeatures.flags); + mDriverFeatures.flags = NULL; + } } wifi_error WifihalGeneric::requestResponse() @@ -243,6 +248,23 @@ int WifihalGeneric::handleResponse(WifiEvent &reply) break; } + case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: + { + struct nlattr *attr; + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1]; + nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX, + (struct nlattr *)mVendorData, mDataLen, NULL); + attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS]; + if (attr) { + int len = nla_len(attr); + mDriverFeatures.flags = (u8 *)malloc(len); + if (mDriverFeatures.flags != NULL) { + memcpy(mDriverFeatures.flags, nla_data(attr), len); + mDriverFeatures.flags_len = len; + } + } + break; + } case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX: { struct nlattr *tb_vendor[ @@ -543,6 +565,25 @@ void WifihalGeneric::getResponseparams(feature_set *pset) *pset = mSet; } +void WifihalGeneric::getDriverFeatures(features_info *pfeatures) +{ + if (!pfeatures) + return; + + if (mDriverFeatures.flags != NULL) { + pfeatures->flags = (u8 *)malloc(mDriverFeatures.flags_len); + if (pfeatures->flags) { + memcpy(pfeatures->flags, mDriverFeatures.flags, + mDriverFeatures.flags_len); + pfeatures->flags_len = mDriverFeatures.flags_len; + return; + } + } + + pfeatures->flags_len = 0; + pfeatures->flags = NULL; +} + void WifihalGeneric::setMaxSetSize(int set_size_max) { mSetSizeMax = set_size_max; } diff --git a/qcwcn/wifi_hal/ifaceeventhandler.h b/qcwcn/wifi_hal/ifaceeventhandler.h index cdbd59d..c993a7e 100644 --- a/qcwcn/wifi_hal/ifaceeventhandler.h +++ b/qcwcn/wifi_hal/ifaceeventhandler.h @@ -83,6 +83,7 @@ class WifihalGeneric: public WifiVendorCommand { private: feature_set mSet; + features_info mDriverFeatures; int mSetSizeMax; int *mSetSizePtr; feature_set *mConcurrencySet; @@ -101,6 +102,7 @@ public: virtual wifi_error requestResponse(); virtual int handleResponse(WifiEvent &reply); virtual void getResponseparams(feature_set *pset); + virtual void getDriverFeatures(features_info *pfeatures); virtual void setMaxSetSize(int set_size_max); virtual void setSizePtr(int *set_size); virtual void setPacketBufferParams(u8 *host_packet_buffer, int packet_length); diff --git a/qcwcn/wifi_hal/qca-vendor_copy.h b/qcwcn/wifi_hal/qca-vendor_copy.h index 6d2f0c7..3f5163f 100644 --- a/qcwcn/wifi_hal/qca-vendor_copy.h +++ b/qcwcn/wifi_hal/qca-vendor_copy.h @@ -944,6 +944,10 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4, + QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5, + QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6, + QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp index 315c814..8e8367c 100644 --- a/qcwcn/wifi_hal/wifi_hal.cpp +++ b/qcwcn/wifi_hal/wifi_hal.cpp @@ -195,6 +195,38 @@ cleanup: return ret; } +static wifi_error acquire_driver_supported_features(wifi_interface_handle iface, + features_info *driver_features) +{ + wifi_error ret; + interface_info *iinfo = getIfaceInfo(iface); + wifi_handle handle = getWifiHandle(iface); + + WifihalGeneric driverFeatures(handle, 0, + OUI_QCA, + QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES); + + /* create the message */ + ret = driverFeatures.create(); + if (ret != WIFI_SUCCESS) + goto cleanup; + + ret = driverFeatures.set_iface_id(iinfo->name); + if (ret != WIFI_SUCCESS) + goto cleanup; + + ret = driverFeatures.requestResponse(); + if (ret != WIFI_SUCCESS) { + ALOGE("%s: requestResponse Error:%d",__func__, ret); + goto cleanup; + } + + driverFeatures.getDriverFeatures(driver_features); + +cleanup: + return mapKernelErrortoWifiHalError(ret); +} + static wifi_error wifi_get_capabilities(wifi_interface_handle handle) { wifi_error ret; @@ -626,6 +658,13 @@ wifi_error wifi_initialize(wifi_handle *handle) ret = WIFI_SUCCESS; } + ret = acquire_driver_supported_features(iface_handle, + &info->driver_supported_features); + if (ret != WIFI_SUCCESS) { + ALOGI("Failed to get vendor feature set : %d", ret); + ret = WIFI_SUCCESS; + } + ret = wifi_get_logger_supported_feature_set(iface_handle, &info->supported_logger_feature_set); if (ret != WIFI_SUCCESS) @@ -715,6 +754,10 @@ unload: cleanupGscanHandlers(info); cleanupRSSIMonitorHandler(info); free(info->event_cb); + if (info->driver_supported_features.flags) { + free(info->driver_supported_features.flags); + info->driver_supported_features.flags = NULL; + } free(info); } } @@ -812,6 +855,11 @@ static void internal_cleaned_up_handler(wifi_handle handle) info->pkt_fate_stats = NULL; } + if (info->driver_supported_features.flags) { + free(info->driver_supported_features.flags); + info->driver_supported_features.flags = NULL; + } + (*cleaned_up_handler)(handle); pthread_mutex_destroy(&info->cb_lock); pthread_mutex_destroy(&info->pkt_fate_stats_lock); diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/qcwcn/wifi_hal/wificonfig.cpp index 40d765f..2c2d1cd 100644 --- a/qcwcn/wifi_hal/wificonfig.cpp +++ b/qcwcn/wifi_hal/wificonfig.cpp @@ -105,6 +105,14 @@ cleanup: return ret; } +int check_feature(enum qca_wlan_vendor_features feature, features_info *info) +{ + size_t idx = feature / 8; + + return (idx < info->flags_len) && + (info->flags[idx] & BIT(feature % 8)); +} + /* Set the country code to driver. */ wifi_error wifi_set_country_code(wifi_interface_handle iface, const char* country_code) @@ -113,6 +121,7 @@ wifi_error wifi_set_country_code(wifi_interface_handle iface, wifi_error ret; WiFiConfigCommand *wifiConfigCommand; wifi_handle wifiHandle = getWifiHandle(iface); + hal_info *info = getHalInfo(wifiHandle); ALOGV("%s: %s", __FUNCTION__, country_code); @@ -144,6 +153,18 @@ wifi_error wifi_set_country_code(wifi_interface_handle iface, goto cleanup; } + if (check_feature(QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY, + &info->driver_supported_features)) { + ret = wifiConfigCommand->put_u32(NL80211_ATTR_USER_REG_HINT_TYPE, + NL80211_USER_REG_HINT_CELL_BASE); + if (ret != WIFI_SUCCESS) { + ALOGE("wifi_set_country_code: put reg hint type failed. Error:%d", + ret); + goto cleanup; + } + } + + /* Send the NL msg. */ wifiConfigCommand->waitForRsp(false); ret = wifiConfigCommand->requestEvent(); |