summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qcwcn/wifi_hal/common.h8
-rw-r--r--qcwcn/wifi_hal/ifaceeventhandler.cpp41
-rw-r--r--qcwcn/wifi_hal/ifaceeventhandler.h2
-rw-r--r--qcwcn/wifi_hal/qca-vendor_copy.h4
-rw-r--r--qcwcn/wifi_hal/wifi_hal.cpp48
-rw-r--r--qcwcn/wifi_hal/wificonfig.cpp21
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();