summaryrefslogtreecommitdiff
path: root/wcn6740
diff options
context:
space:
mode:
authorHsiu-Chang Chen <hsiuchangchen@google.com>2022-08-19 16:33:54 +0530
committerHsiu-Chang Chen <hsiuchangchen@google.com>2022-09-01 10:04:23 +0000
commit3a945babc01bd694d6d3d8f476b585715b470eda (patch)
treeffafb3c252da232f8fb5663a951d3712f8bd6d44 /wcn6740
parent21f16b2f41fb51ab0ea374a3c996e7bd19844e97 (diff)
downloadwlan-3a945babc01bd694d6d3d8f476b585715b470eda.tar.gz
Wifihal: Add SAR V2 Support.
The patch checks the SAR version from firmware and adds commands/values to support SAR V2. Bug: 238570847 Test: haltuil -sar Change-Id: I531e7f7f685373cfd5566ac6fd3f7fb3540e8219 CRs-Fixed: 3278406
Diffstat (limited to 'wcn6740')
-rw-r--r--wcn6740/qcwcn/wifi_hal/common.h1
-rw-r--r--wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp44
-rw-r--r--wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h1
-rw-r--r--wcn6740/qcwcn/wifi_hal/wifi_hal.cpp29
-rw-r--r--wcn6740/qcwcn/wifi_hal/wificonfig.cpp182
5 files changed, 256 insertions, 1 deletions
diff --git a/wcn6740/qcwcn/wifi_hal/common.h b/wcn6740/qcwcn/wifi_hal/common.h
index a48605a..8816f5f 100644
--- a/wcn6740/qcwcn/wifi_hal/common.h
+++ b/wcn6740/qcwcn/wifi_hal/common.h
@@ -213,6 +213,7 @@ typedef struct hal_info_s {
bool apf_enabled;
bool support_nan_ext_cmd;
pkt_log_version pkt_log_ver;
+ qca_wlan_vendor_sar_version sar_version;
} hal_info;
typedef struct {
diff --git a/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
index ef582e0..0c44e25 100644
--- a/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
+++ b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
@@ -33,6 +33,7 @@
#include <errno.h>
#include "ifaceeventhandler.h"
+#include "common.h"
/* Used to handle NL command events from driver/firmware. */
IfaceEventHandlerCommand *mwifiEventHandler = NULL;
@@ -560,6 +561,21 @@ int WifihalGeneric::handleResponse(WifiEvent &reply)
wifiParseRadarHistory();
}
break;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_MAX,
+ (struct nlattr *)mVendorData,mDataLen, NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION])
+ {
+ mInfo->sar_version = (qca_wlan_vendor_sar_version) nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION]);
+ }
+ ALOGV("%s: sar_version return %d", __func__, mInfo->sar_version);
+ }
+ break;
default :
ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
}
@@ -912,3 +928,31 @@ void WifihalGeneric::freeCachedRadarHistory() {
mRadarResultParams.num_entries = 0;
}
}
+
+wifi_error WifihalGeneric::getSarVersion(wifi_interface_handle handle)
+{
+ wifi_error ret;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+
+
+ /* Create the NL message. */
+ ret = create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create NL message, Error:%d", __FUNCTION__, ret);
+ return ret;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
+ return ret;
+ }
+
+ ret = requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
+
+ return ret;
+}
+
diff --git a/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
index f0b681a..eef9624 100644
--- a/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
+++ b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
@@ -126,6 +126,7 @@ public:
virtual wifi_error copyCachedRadarHistory(radar_history_result *resultBuf,
int resultBufSize, int *numResults);
virtual void freeCachedRadarHistory();
+ virtual wifi_error getSarVersion(wifi_interface_handle handle);
};
/**
diff --git a/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp b/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
index 9288aed..f31c641 100644
--- a/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
@@ -415,6 +415,28 @@ static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
return ret;
}
+static wifi_error wifi_get_sar_version(wifi_interface_handle handle)
+{
+ wifi_error ret;
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ WifihalGeneric *sarVersion = new WifihalGeneric(
+ wifiHandle,
+ 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY);
+ if (!sarVersion) {
+ ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ ret = sarVersion->getSarVersion(handle);
+
+ delete sarVersion;
+ return ret;
+}
+
static wifi_error get_firmware_bus_max_size_supported(
wifi_interface_handle iface)
{
@@ -1395,6 +1417,13 @@ wifi_error wifi_initialize(wifi_handle *handle)
ALOGV("support_nan_ext_cmd is %d",
info->support_nan_ext_cmd);
+ ret = wifi_get_sar_version(iface_handle);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to get SAR Version, Setting it to default.");
+ info->sar_version = QCA_WLAN_VENDOR_SAR_VERSION_1;
+ ret = WIFI_SUCCESS;
+ }
+
cld80211_cleanup:
if (status != 0 || ret != WIFI_SUCCESS) {
ret = WIFI_ERROR_UNKNOWN;
diff --git a/wcn6740/qcwcn/wifi_hal/wificonfig.cpp b/wcn6740/qcwcn/wifi_hal/wificonfig.cpp
index 82bcfda..3a47634 100644
--- a/wcn6740/qcwcn/wifi_hal/wificonfig.cpp
+++ b/wcn6740/qcwcn/wifi_hal/wificonfig.cpp
@@ -41,6 +41,10 @@
#include <net/if_arp.h>
#include <sys/socket.h>
#include "wificonfigcommand.h"
+#include "ifaceeventhandler.h"
+
+#define NUM_OF_SAR_LIMITS_SPECS 2
+#define NUM_OF_SPEC_CHAINS 2
/* Implementation of the API functions exposed in wifi_config.h */
wifi_error wifi_extended_dtim_config_set(wifi_request_id id,
@@ -392,7 +396,7 @@ cleanup:
return ret;
}
-wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
+wifi_error wifi_select_SARv01_tx_power_scenario(wifi_interface_handle handle,
wifi_power_scenario scenario)
{
wifi_error ret;
@@ -431,6 +435,7 @@ wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
/* Add the vendor specific attributes for the NL command. */
nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA. "
"Error:%d", ret);
goto cleanup;
@@ -496,6 +501,181 @@ cleanup:
return ret;
}
+wifi_error wifi_select_SARv02_tx_power_scenario(wifi_interface_handle handle,
+ wifi_power_scenario scenario)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData, *nlSpecList, *nlSpec;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ u32 power_lim_idx = 0;
+
+ ALOGV("%s : power scenario SARV2:%d", __FUNCTION__, scenario);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ 1,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA.");
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_ENABLE");
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS,
+ NUM_OF_SAR_LIMITS_SPECS)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_LIMITS_NUM_SPECS");
+ goto cleanup;
+ }
+
+ switch (scenario) {
+ case WIFI_POWER_SCENARIO_VOICE_CALL:
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW:
+
+ power_lim_idx = 0;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF:
+ power_lim_idx = 1;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW:
+ power_lim_idx = 2;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON:
+ power_lim_idx = 3;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT:
+ power_lim_idx = 4;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF:
+ case WIFI_POWER_SCENARIO_ON_BODY_BT:
+ power_lim_idx = 5;
+ break;
+ default:
+ ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+
+ nlSpecList = wifiConfigCommand->attr_start(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC);
+ if (!nlSpecList)
+ {
+ ALOGE("Cannot create spec list");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+
+ for (int i = 0; i < NUM_OF_SPEC_CHAINS; i++) {
+ nlSpec = wifiConfigCommand->attr_start(0);
+ if (!nlSpec) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN,
+ i))
+ {
+ ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX,
+ power_lim_idx))
+ {
+ ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ wifiConfigCommand->attr_end(nlSpec);
+ }
+
+
+
+ wifiConfigCommand->attr_end(nlSpecList);
+
+ wifiConfigCommand->attr_end(nlData);
+ ALOGV("wifi_select_tx_power_scenario %u selected", power_lim_idx);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+
+wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
+ wifi_power_scenario scenario)
+{
+
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ hal_info *info = getHalInfo(wifiHandle);
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ ALOGV("wifi_select_tx_power_scenario: sarVer%u", (u32)info->sar_version);
+ if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_1)
+ return wifi_select_SARv01_tx_power_scenario(handle,scenario);
+ else if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_2)
+ return wifi_select_SARv02_tx_power_scenario(handle,scenario);
+ else {
+ ALOGE("wifi_select_tx_power_scenario %u invalid or not supported", (u32)info->sar_version);
+ return WIFI_ERROR_UNKNOWN;
+ }
+}
+
+
wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
{
wifi_error ret;