diff options
-rw-r--r-- | wcn6740/qcwcn/wifi_hal/common.h | 1 | ||||
-rw-r--r-- | wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp | 44 | ||||
-rw-r--r-- | wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h | 1 | ||||
-rw-r--r-- | wcn6740/qcwcn/wifi_hal/wifi_hal.cpp | 29 | ||||
-rw-r--r-- | wcn6740/qcwcn/wifi_hal/wificonfig.cpp | 182 |
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; |