Wifi: Add Qpower interface to wifi_hal of qcom

Add Qpower interface to wifi_hal of qcom

Change-Id: I2a140d040260668930c7574c6b43adcb90f5d609
CRs-Fixed: 2145148
diff --git a/qcwcn/wifi_hal/vendor_definitions.h b/qcwcn/wifi_hal/vendor_definitions.h
index ea105fa..81b7b03 100644
--- a/qcwcn/wifi_hal/vendor_definitions.h
+++ b/qcwcn/wifi_hal/vendor_definitions.h
@@ -247,6 +247,8 @@
     QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_TX_RATE = 5,
     /* Unsigned 32-bit value */
     QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS = 6,
+    /* Unsigned 8-bit, for setting qpower dynamically */
+    QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER_VENDOR = 25,
     /* keep last */
     QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_AFTER_LAST,
     QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_MAX =
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 6117301..bb8fbe7 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -408,6 +408,7 @@
     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
     fn->wifi_configure_roaming = wifi_configure_roaming;
     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
+    fn->wifi_set_qpower = wifi_set_qpower;
 
     return WIFI_SUCCESS;
 }
diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/qcwcn/wifi_hal/wificonfig.cpp
index c244c58..0dc423e 100644
--- a/qcwcn/wifi_hal/wificonfig.cpp
+++ b/qcwcn/wifi_hal/wificonfig.cpp
@@ -157,6 +157,80 @@
     return ret;
 }
 
+/*
+ * Set the powersave to driver.
+ */
+wifi_error wifi_set_qpower(wifi_interface_handle iface,
+                                 u8 powersave)
+{
+    int requestId, ret = 0;
+    WiFiConfigCommand *wifiConfigCommand;
+    struct nlattr *nlData;
+    interface_info *ifaceInfo = getIfaceInfo(iface);
+    wifi_handle wifiHandle = getWifiHandle(iface);
+    //hal_info *info = getHalInfo(wifiHandle);
+
+    ALOGD("%s: %d", __FUNCTION__, powersave);
+
+    requestId = get_requestid();
+
+    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("wifi_set_qpower: 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 < 0) {
+        ALOGE("wifi_set_qpower: 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) {
+        ALOGE("wifi_set_qpower: failed attr_start for "
+            "VENDOR_DATA. Error:%d", ret);
+        goto cleanup;
+    }
+
+    if (wifiConfigCommand->put_u8(
+        QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER_VENDOR, powersave)) {
+        ALOGE("wifi_set_qpower(): failed to put vendor data. "
+            "Error:%d", ret);
+        goto cleanup;
+    }
+    wifiConfigCommand->attr_end(nlData);
+
+    /* Send the NL msg. */
+    wifiConfigCommand->waitForRsp(false);
+    ret = wifiConfigCommand->requestEvent();
+    if (ret != 0) {
+        ALOGE("wifi_set_qpower(): requestEvent Error:%d", ret);
+        goto cleanup;
+    }
+
+cleanup:
+    delete wifiConfigCommand;
+    return (wifi_error)ret;
+
+}
+
 wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor(
                                                 wifi_request_id id,
                                                 wifi_interface_handle iface,