Merge "WifiHal: Implement wifi_set_voip_mode hal api" into wlan-aosp.lnx.7.0
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 5398680..03ae563 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -146,6 +146,8 @@
 wifi_error
     wifi_init_tcp_param_change_event_handler(wifi_interface_handle iface);
 
+wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode);
+
 /* Initialize/Cleanup */
 
 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
@@ -1086,6 +1088,7 @@
     fn->wifi_multi_sta_set_use_case = wifi_multi_sta_set_use_case;
     fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
     fn->wifi_set_dtim_config = wifi_set_dtim_config;
+    fn->wifi_set_voip_mode = wifi_set_voip_mode;
     fn->wifi_get_usable_channels = wifi_get_usable_channels;
 
     return WIFI_SUCCESS;
diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/qcwcn/wifi_hal/wificonfig.cpp
index a026e0b..6131034 100644
--- a/qcwcn/wifi_hal/wificonfig.cpp
+++ b/qcwcn/wifi_hal/wificonfig.cpp
@@ -1631,3 +1631,77 @@
     delete wifiConfigCommand;
     return (wifi_error)ret;
 }
+
+/**
+ * Invoked to set voip optimization mode for the provided STA iface
+ */
+ wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode)
+{
+    int requestId;
+    WiFiConfigCommand *wifiConfigCommand;
+    wifi_error ret;
+
+    struct nlattr *nlData;
+    interface_info *ifaceInfo = getIfaceInfo(iface);
+
+    wifi_handle wifiHandle = getWifiHandle(iface);
+    if (!wifiHandle) {
+        ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    requestId = get_requestid();
+    ALOGV("%s: voip mode=%d", __FUNCTION__, mode);
+    wifiConfigCommand = new WiFiConfigCommand(
+                            wifiHandle,
+                            requestId,
+                            OUI_QCA,
+                            QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+    if (wifiConfigCommand == NULL) {
+        ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    /* Create the NL message. */
+    ret = wifiConfigCommand->create();
+    if (ret < 0) {
+        ALOGE("%s: failed to create NL msg. Error:%d", __FUNCTION__, ret);
+        goto cleanup;
+    }
+
+    /* Set the interface Id of the message. */
+    ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+    if (ret < 0) {
+        ALOGE("%s: failed to set iface id. Error:%d", __FUNCTION__, ret);
+        goto cleanup;
+    }
+
+    /* Add the vendor specific attributes for the NL command. */
+    nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+    if (!nlData) {
+        ALOGE("%s: failed attr_start for VENDOR_DATA", __FUNCTION__);
+        ret = WIFI_ERROR_UNKNOWN;
+        goto cleanup;
+    }
+
+    if (wifiConfigCommand->put_u8(QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE,
+        (mode==WIFI_VOIP_MODE_ON) ? 1 : 0)) {
+        ALOGE("%s: failed to put vendor data", __FUNCTION__);
+        ret = WIFI_ERROR_UNKNOWN;
+        goto cleanup;
+    }
+    wifiConfigCommand->attr_end(nlData);
+
+    /* Send the NL msg. */
+    wifiConfigCommand->waitForRsp(false);
+    ret = wifiConfigCommand->requestEvent();
+    if (ret != 0) {
+        ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+        goto cleanup;
+    }
+
+cleanup:
+    delete wifiConfigCommand;
+    return ret;
+}