wpa_supplicant_8_lib: Add support to configure listen interval

Add support for user to configure listen interval
Syntax: driver SET_LISTEN_INTERVAL <listen_interval>
listen_interval can be configured between 0 to 10.
Default value is 1. If set to 0, it removes user
configuration.

Change-Id: Ifa7c5d6a06f6857ce1cdaad52bf60b9a62405a2a
CRs-Fixed: 3417732
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index e8a234b..dbc89af 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -6290,6 +6290,65 @@
 	return ret;
 }
 
+static int wpa_driver_cfg_listen_interval_cmd(struct i802_bss *bss, char *cmd)
+{
+	struct wpa_driver_nl80211_data *drv;
+	struct nl_msg *nlmsg;
+	struct nlattr *attr;
+	int ret;
+	u32 listen_interval = 0;
+
+	if (!bss || !bss->drv || !cmd) {
+		wpa_printf(MSG_ERROR, "%s:Invalid arguments", __func__);
+		return -EINVAL;
+	}
+	cmd = skip_white_space(cmd);
+	if (*cmd == '\0') {
+		wpa_printf(MSG_ERROR, "listen interval values missing");
+		return -EINVAL;
+	}
+	drv = bss->drv;
+	listen_interval = get_u32_from_string(cmd, &ret);
+	if (ret < 0)
+		return ret;
+	if (listen_interval < CONFIG_LISTEN_INTERVAL_MIN ||
+			listen_interval > CONFIG_LISTEN_INTERVAL_MAX) {
+		wpa_printf(MSG_ERROR, "listen interval values to be in range of %d-%d",
+			CONFIG_LISTEN_INTERVAL_MIN, CONFIG_LISTEN_INTERVAL_MAX);
+		return -EINVAL;
+	}
+	nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+				     QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+	if (!nlmsg) {
+		wpa_printf(MSG_ERROR, "Fail to allocate nlmsg for Listen Interval cmd");
+		return -ENOMEM;
+	}
+
+	attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+	if (!attr) {
+		ret = -ENOMEM;
+		wpa_printf(MSG_ERROR, "Fail to create Listen Interval cmd nl attribute");
+		goto nlmsg_fail;
+	}
+	if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL, listen_interval)) {
+		ret = -ENOMEM;
+		wpa_printf(MSG_ERROR, "Fail to put listen interval value");
+		goto nlmsg_fail;
+	}
+	nla_nest_end(nlmsg, attr);
+
+	ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_ERROR, "Fail to send listen_interval nlmsg, error:%d", ret);
+		return ret;
+	}
+	return 0;
+nlmsg_fail:
+	nlmsg_free(nlmsg);
+	return ret;
+}
+
+
 int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
 				  size_t buf_len )
 {
@@ -6628,6 +6687,10 @@
 		 */
 		cmd += 16;
 		return wpa_driver_rate_mask_config(bss, cmd);
+	} else if (os_strncasecmp(cmd, "SET_LISTEN_INTERVAL ", 20) == 0) {
+		/* DRIVER SET_LISTEN_INTERVAL <listen_interval> */
+		cmd += 20;
+		return wpa_driver_cfg_listen_interval_cmd(bss, cmd);
 	} else { /* Use private command */
 		memset(&ifr, 0, sizeof(ifr));
 		memset(&priv_cmd, 0, sizeof(priv_cmd));
diff --git a/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
index e623b19..6df4ded 100644
--- a/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
+++ b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
@@ -121,6 +121,8 @@
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON
 #define GET_STA_INFO_MAX \
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX
+#define CONFIG_LISTEN_INTERVAL_MIN 0
+#define CONFIG_LISTEN_INTERVAL_MAX 10
 
 #define RATEMASK_PARAMS_TYPE_MAX  4