Merge "cld80211: Fix makefile to build as vendor module" into wlan-aosp.lnx.6.0
diff --git a/qcwcn/wpa_supplicant_8_lib/Android.mk b/qcwcn/wpa_supplicant_8_lib/Android.mk
index 5db3cdd..e33f9cc 100644
--- a/qcwcn/wpa_supplicant_8_lib/Android.mk
+++ b/qcwcn/wpa_supplicant_8_lib/Android.mk
@@ -32,6 +32,7 @@
 	$(WPA_SUPPL_DIR)/src/l2_packet \
 	$(WPA_SUPPL_DIR)/src/utils \
 	$(WPA_SUPPL_DIR)/src/wps \
+	$(WPA_SUPPL_DIR)/src/ap \
 	$(WPA_SUPPL_DIR)/wpa_supplicant
 
 ifdef CONFIG_DRIVER_NL80211
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index 15e216d..265e964 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -24,6 +24,9 @@
 #include "driver_nl80211.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
+#include "wpa_driver_common_lib.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
 #ifdef LINUX_EMBEDDED
 #include <sys/ioctl.h>
 #endif
@@ -35,6 +38,7 @@
 #define WPA_PS_ENABLED		0
 #define WPA_PS_DISABLED		1
 #define UNUSED(x)	(void)(x)
+#define NL80211_ATTR_MAX_INTERNAL 256
 
 
 /* ============ nl80211 driver extensions ===========  */
@@ -111,6 +115,942 @@
 	}
 }
 
+static struct remote_sta_info g_sta_info = {0};
+
+static struct nl_msg *prepare_nlmsg(struct wpa_driver_nl80211_data *drv,
+				    char *ifname, int cmdid, int subcmd,
+				    int flag)
+{
+	int res;
+	struct nl_msg *nlmsg = nlmsg_alloc();
+	int ifindex;
+
+	if (nlmsg == NULL) {
+		wpa_printf(MSG_ERROR,"Out of memory");
+		return NULL;
+	}
+
+	genlmsg_put(nlmsg, /* pid = */ 0, /* seq = */ 0,
+		    drv->global->nl80211_id, 0, flag, cmdid, 0);
+
+	if (cmdid == NL80211_CMD_VENDOR) {
+		res = nla_put_u32(nlmsg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
+		if (res < 0) {
+			wpa_printf(MSG_ERROR,"Failed to put vendor id");
+			goto cleanup;
+		}
+
+		res = nla_put_u32(nlmsg, NL80211_ATTR_VENDOR_SUBCMD, subcmd);
+		if (res < 0) {
+			wpa_printf(MSG_ERROR,"Failed to put vendor sub command");
+			goto cleanup;
+		}
+	}
+
+	if (ifname && (strlen(ifname) > 0))
+		ifindex = if_nametoindex(ifname);
+	else
+		ifindex = if_nametoindex("wlan0");
+
+	if (nla_put_u32(nlmsg, NL80211_ATTR_IFINDEX, ifindex) != 0) {
+		wpa_printf(MSG_ERROR,"Failed to get iface index for iface: %s", ifname);
+		goto cleanup;
+	}
+
+	return nlmsg;
+
+cleanup:
+	if (nlmsg)
+		nlmsg_free(nlmsg);
+	return NULL;
+}
+
+static struct nl_msg *prepare_vendor_nlmsg(struct wpa_driver_nl80211_data *drv,
+					   char *ifname, int subcmd)
+{
+	return prepare_nlmsg(drv, ifname, NL80211_CMD_VENDOR, subcmd, 0);
+}
+
+static int parse_station_info(struct resp_info *info, struct nlattr *vendata,
+			      int datalen)
+{
+	struct bss_info data;
+	struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX + 1];
+	struct nlattr *attr, *attr1, *attr2;
+	u8 *beacon_ies = NULL;
+	size_t beacon_ies_len = 0;
+
+	os_memset(&data, 0, sizeof(struct bss_info));
+
+	data.oui[0] = (OUI_QCA) & 0xFF;
+	data.oui[1] = ((OUI_QCA)>>8) & 0xFF;
+	data.oui[2] = ((OUI_QCA)>>16) & 0xFF;
+
+	nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX,
+		  vendata, datalen, NULL);
+
+	attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR];
+	if (attr) {
+		struct nlattr *tb1[NL80211_ATTR_MAX + 1];
+
+		nla_parse(tb1, NL80211_ATTR_MAX, nla_data(attr),
+			  nla_len(attr), NULL);
+		if (tb1[NL80211_ATTR_SSID] &&
+		    (nla_len(tb1[NL80211_ATTR_SSID]) <= MAX_SSID_LEN)) {
+			os_memcpy(data.ssid, nla_data(tb1[NL80211_ATTR_SSID]),
+					  nla_len(tb1[NL80211_ATTR_SSID]));
+			data.ssid[nla_len(tb1[NL80211_ATTR_SSID])] = '\0';
+		} else {
+			wpa_printf(MSG_ERROR,"NL80211_ATTR_SSID not found");
+		}
+		if (tb1[NL80211_ATTR_MAC]) {
+			os_memcpy(data.oui, nla_data(tb1[NL80211_ATTR_MAC]), OUI_LEN);
+		} else {
+			wpa_printf(MSG_ERROR,"NL80211_ATTR_MAC not found");
+		}
+		if (tb1[NL80211_ATTR_SURVEY_INFO]) {
+			struct nlattr *tb2[NL80211_SURVEY_INFO_MAX + 1];
+
+			nla_parse(tb2, NL80211_SURVEY_INFO_MAX,
+				  nla_data(tb1[NL80211_ATTR_SURVEY_INFO]),
+				  nla_len(tb1[NL80211_ATTR_SURVEY_INFO]), NULL);
+			if (tb2[NL80211_SURVEY_INFO_FREQUENCY]) {
+				data.channel =
+				nla_get_u32(tb2[NL80211_SURVEY_INFO_FREQUENCY]);
+			} else {
+				wpa_printf(MSG_ERROR,
+				    "NL80211_SURVEY_INFO_FREQUENCY not found");
+			}
+			if (tb2[NL80211_SURVEY_INFO_NOISE]) {
+				data.noise =
+				nla_get_u8(tb2[NL80211_SURVEY_INFO_NOISE]);
+				data.noise -= 100;
+			} else {
+				wpa_printf(MSG_ERROR,"NL80211_SURVEY_INFO_NOISE not found");
+			}
+		} else {
+			wpa_printf(MSG_ERROR,"NL80211_ATTR_SURVEY_INFO not found");
+		}
+
+		if (tb1[NL80211_ATTR_STA_INFO]) {
+			struct nlattr *tb2[NL80211_STA_INFO_MAX + 1];
+
+			nla_parse(tb2, NL80211_STA_INFO_MAX,
+				  nla_data(tb1[NL80211_ATTR_STA_INFO]),
+				  nla_len(tb1[NL80211_ATTR_STA_INFO]), NULL);
+			if (tb2[NL80211_STA_INFO_SIGNAL]) {
+				data.rssi =
+				nla_get_u8(tb2[NL80211_STA_INFO_SIGNAL]);
+				data.rssi -= 100;
+			} else {
+				wpa_printf(MSG_ERROR,"NL80211_STA_INFO_SIGNAL not found");
+			}
+			data.snr = data.rssi - data.noise;
+
+			attr1 = tb2[NL80211_STA_INFO_TX_BITRATE];
+			if (attr1) {
+				struct nlattr *tb3[NL80211_RATE_INFO_MAX + 1];
+
+				nla_parse(tb3, NL80211_RATE_INFO_MAX,
+					  nla_data(attr1), nla_len(attr1),
+					  NULL);
+				if (tb3[NL80211_RATE_INFO_BITRATE32]) {
+					data.data_rate = nla_get_u32(
+					tb3[NL80211_RATE_INFO_BITRATE32])/10;
+				} else if (tb3[NL80211_RATE_INFO_BITRATE]) {
+					data.data_rate = nla_get_u16(
+					tb3[NL80211_RATE_INFO_BITRATE])/10;
+				}
+
+			} else {
+				wpa_printf(MSG_ERROR,"NL80211_STA_INFO_TX_BITRATE not found");
+			}
+		} else {
+			wpa_printf(MSG_ERROR,"NL80211_ATTR_STA_INFO not found");
+		}
+	} else {
+		wpa_printf(MSG_ERROR,
+		   "QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR not found");
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM]) {
+		data.akm = nla_get_u32(
+			tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM]);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]) {
+		data.mode_80211 = nla_get_u32(
+			tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]);
+	}
+
+	attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION];
+	attr1 = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION];
+	attr2 = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION];
+	if (attr) {
+		struct ieee80211_vht_operation *info = nla_data(attr);
+
+		switch (info->vht_op_info_chwidth) {
+		case CHANWIDTH_USE_HT:
+			if (attr1) {
+				struct ieee80211_ht_operation *info;
+
+				info = nla_data(attr1);
+				data.bw = info->ht_param ? 40:20;
+			}
+			break;
+		case CHANWIDTH_80MHZ:
+			data.bw = 80;
+			break;
+		case CHANWIDTH_160MHZ:
+			data.bw = 160;
+			break;
+		case CHANWIDTH_80P80MHZ:
+			data.bw = 160;
+			break;
+		default:
+			wpa_printf(MSG_ERROR,"Invalid channel width received : %u",
+						 info->vht_op_info_chwidth);
+		}
+	} else if (attr1) {
+		struct ieee80211_ht_operation *info = nla_data(attr1);
+
+		data.bw = info->ht_param ? 40:20;
+	} else
+		data.bw = 20;
+
+	if (attr2) {
+		struct ieee80211_he_operation *he_info = nla_data(attr2);
+		uint8_t *opr, ch_bw = CHANNEL_BW_INVALID;
+
+		/* Check optional field in he_info is present of not */
+		if (!he_info || (nla_len(attr2) <=
+		    (sizeof(he_info->he_oper_params) +
+		    sizeof(he_info->he_mcs_nss_set)))) {
+			he_info ? wpa_printf(MSG_ERROR,"Invalid he operation len: %d", nla_len(attr2)):
+			wpa_printf(MSG_ERROR,"Invalid he_info: NULL");
+			goto parse_beacon_ies;
+		}
+
+		opr = (uint8_t *)he_info;
+		/* Point to operational field */
+		opr += (sizeof(he_info->he_oper_params) +
+			sizeof(he_info->he_mcs_nss_set));
+		if (he_info->he_oper_params &
+		    IEEE80211_HE_OPERATION_VHT_OPER_MASK) {
+			ch_bw = opr[HE_OPER_VHT_CH_WIDTH_OFFSET];
+			opr += (HE_OPER_VHT_MAX_OFFSET + 1);
+		}
+
+		if (he_info->he_oper_params &
+		    IEEE80211_HE_OPERATION_CO_LOC_BSS_MASK) {
+			opr += (HE_OPER_CO_LOCATED_MAX_OFFSET + 1);
+		}
+
+		if (he_info->he_oper_params &
+		    IEEE80211_HE_OPERATION_6G_OPER_MASK) {
+			ch_bw = (opr[HE_OPER_6G_PARAMS_OFFSET] &
+				 HE_OPER_6G_PARAMS_SUB_CH_BW_MASK);
+		}
+
+		switch (ch_bw) {
+		case CHANWIDTH_USE_HT:
+			/* TO DO */
+			break;
+		case CHANWIDTH_80MHZ:
+			data.bw = 80;
+			break;
+		case CHANWIDTH_160MHZ:
+			data.bw = 160;
+			break;
+		case CHANWIDTH_80P80MHZ:
+			data.bw = 160;
+			break;
+		default:
+			wpa_printf(MSG_ERROR,"Invalid channel width received : %u", ch_bw);
+		}
+	}
+
+parse_beacon_ies:
+	attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES];
+	if (attr) {
+		beacon_ies = nla_data(attr);
+
+		beacon_ies_len = nla_len(attr);
+		if (beacon_ies && beacon_ies_len > 12) {
+			beacon_ies += 12;
+			beacon_ies_len -= 12;
+		}
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON]) {
+		data.disc_reasn_code = nla_get_u32(tb_vendor[
+			QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON]);
+	}
+	snprintf(info->reply_buf, info->reply_buf_len,
+		 "%02x%02x%02x %s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %u %s",
+		 data.oui[0],
+		 data.oui[1],
+		 data.oui[2],
+		 data.ssid,
+		 data.channel,
+		 data.bw,
+		 data.rssi,
+		 data.data_rate,
+		 data.mode_80211,
+		 -1,
+		 -1,
+		 -1,
+		 data.snr,
+		 data.noise,
+		 data.akm,
+		 data.roaming_count,
+		 -1,
+		 -1,
+		 -1,
+		 -1,
+		 data.disc_reasn_code,
+		 info->country);
+
+	return 0;
+}
+
+static int handle_response(struct resp_info *info, struct nlattr *vendata,
+			   int datalen)
+{
+	switch (info->subcmd) {
+	case QCA_NL80211_VENDOR_SUBCMD_GET_STATION:
+		os_memset(info->reply_buf, 0, info->reply_buf_len);
+		if (info->cmd_type == GETSTATSBSSINFO)
+			parse_station_info(info, vendata, datalen);
+
+		wpa_printf(MSG_INFO,"STAINFO: %s", info->reply_buf);
+		break;
+	default:
+		wpa_printf(MSG_ERROR,"Unsupported response type: %d", info->subcmd);
+		break;
+	}
+	return 0;
+}
+
+static int response_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *mHeader;
+	struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
+	struct nlattr *vendata;
+	int datalen;
+	struct resp_info *info = (struct resp_info *) arg;
+	int status;
+
+	mHeader = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
+	nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL,
+			  genlmsg_attrdata(mHeader, 0),
+			  genlmsg_attrlen(mHeader, 0), NULL);
+
+	if (mAttributes[NL80211_ATTR_VENDOR_DATA]) {
+		vendata = nla_data(mAttributes[NL80211_ATTR_VENDOR_DATA]);
+		datalen = nla_len(mAttributes[NL80211_ATTR_VENDOR_DATA]);
+		if (!vendata) {
+			wpa_printf(MSG_ERROR,"Vendor data not found");
+			return -1;
+		}
+		status = handle_response(info, vendata, datalen);
+	} else {
+		wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA not found");
+		status = -1;
+	}
+
+	return status;
+}
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+	int *err = (int *)arg;
+
+	*err = 0;
+	return NL_STOP;
+}
+
+
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+	int *ret = (int *)arg;
+
+	*ret = 0;
+	return NL_SKIP;
+}
+
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+						 void *arg)
+{
+	int *ret = (int *)arg;
+
+	*ret = err->error;
+	wpa_printf(MSG_ERROR,"%s received : %d - %s", __func__,
+	      err->error, strerror(err->error));
+	return NL_SKIP;
+}
+
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+	return NL_OK;
+}
+
+static int send_nlmsg(struct nl_sock *cmd_sock, struct nl_msg *nlmsg,
+		      nl_recvmsg_msg_cb_t customer_cb, void *arg)
+{
+	int err = 0;
+	struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
+
+	if (!cb)
+		goto out;
+
+	err = nl_send_auto_complete(cmd_sock, nlmsg);	/* send message */
+	if (err < 0)
+		goto out;
+
+	err = 1;
+
+	nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
+	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+	if (customer_cb)
+		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, customer_cb, arg);
+
+	while (err > 0) {				   /* wait for reply */
+		int res = nl_recvmsgs(cmd_sock, cb);
+
+		if (res)
+			wpa_printf(MSG_ERROR,"nl80211: %s->nl_recvmsgs failed: %d",
+				 __func__, res);
+	}
+out:
+	nl_cb_put(cb);
+	if (nlmsg)
+		nlmsg_free(nlmsg);
+	return err;
+}
+
+static int chartohex(char c)
+{
+	int val = -1;
+
+	if (c >= '0' && c <= '9')
+		val = c - '0';
+	else if (c >= 'a' && c <= 'f')
+		val = c - 'a' + 10;
+	else if (c >= 'A' && c <= 'F')
+		val = c - 'A' + 10;
+
+	return val;
+}
+
+static int convert_string_to_bytes(u8 *addr, const char *text, u16 max_bytes)
+{
+	u16 i = 0;
+	int nibble;
+	const char *temp = text;
+
+	while (temp && *temp != '\0' && i < max_bytes) {
+		nibble = chartohex(*temp++);
+		if (nibble == -1)
+			return -1;
+		addr[i] = nibble << 4;
+		nibble = chartohex(*temp++);
+		if (nibble == -1)
+			return -1;
+		addr[i++] += nibble;
+		if (*temp == ':')
+			temp++;
+	}
+
+	return i;
+}
+
+static int populate_nlmsg(struct nl_msg *nlmsg, char *cmd,
+			  enum get_info_cmd type)
+{
+	struct nlattr *attr;
+
+	attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+	if (attr == NULL)
+		return -1;
+
+	switch (type) {
+	case GETSTATSBSSINFO:
+		if (nla_put_flag(nlmsg,
+				 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO)) {
+			wpa_printf(MSG_ERROR,"Failed to put flag QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO");
+			return -1;
+		}
+		break;
+	default:
+		wpa_printf(MSG_ERROR,"Unsupported command: %d", type);
+		break;
+	}
+
+	nla_nest_end(nlmsg, attr);
+	return 0;
+}
+
+static char *skip_white_space(char *cmd)
+{
+	char *pos = cmd;
+
+	while (*pos == ' ')
+		pos++;
+
+	return pos;
+}
+
+void ap_sta_copy_supp_op_classes(const u8 *supp_op_classes,
+				 size_t supp_op_classes_len) {
+	if (!supp_op_classes)
+		return;
+	os_free(g_sta_info.supp_op_classes);
+	g_sta_info.supp_op_classes = malloc(1 + supp_op_classes_len);
+	if(!g_sta_info.supp_op_classes)
+		return;
+	g_sta_info.supp_op_classes[0] = supp_op_classes_len;
+	os_memcpy(g_sta_info.supp_op_classes + 1, supp_op_classes,
+		  supp_op_classes_len);
+}
+
+void ap_sta_copy_channels(const u8 *supp_channels,
+				 size_t supp_channels_len) {
+	if (!supp_channels)
+		return;
+	os_free(g_sta_info.supp_channels);
+	g_sta_info.supp_channels = malloc(1 + supp_channels_len);
+	if(!g_sta_info.supp_channels)
+		return;
+	g_sta_info.supp_channels[0] = supp_channels_len;
+	os_memcpy(g_sta_info.supp_channels + 1, supp_channels,
+		  supp_channels_len);
+}
+
+static void parse_assoc_req_ies(const u8 *ies, int ies_len) {
+	int left = ies_len;
+	const u8 *pos = ies;
+
+	while (left >= 2) {
+		u8 id, ie_len;
+		id = *pos++;
+		ie_len = *pos++;
+		left -= 2;
+
+		if (ie_len > left) {
+			wpa_printf(MSG_ERROR,"parse error, id = %d, ie_len = %d, left = %d",
+			      id, ie_len, left);
+			return;
+		}
+
+		switch (id) {
+		case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
+			ap_sta_copy_supp_op_classes(pos, ie_len);
+			break;
+		case WLAN_EID_SUPPORTED_CHANNELS:
+			ap_sta_copy_channels(pos, ie_len);
+			break;
+		default:
+			break;
+		}
+
+		left -= ie_len;
+		pos += ie_len;
+	}
+
+	if (left)
+		wpa_printf(MSG_ERROR,"parse error, left = %d", left);
+	return;
+}
+
+void op_class_band_conversion(u8 *op_classes) {
+	int count = (g_sta_info.supp_op_classes[0]);
+	int i = 1;
+	int temp;
+
+	if (count <= 1)
+		g_sta_info.supported_band = 0;
+	while((count-1) != 0) {
+		temp = g_sta_info.supp_op_classes[i];
+		if (temp >= 81 && temp <= 84)
+			g_sta_info.supported_band |= BIT(0);
+		else if (temp >= 115 && temp <= 130)
+			g_sta_info.supported_band |= BIT(1);
+		else if (temp >= 131 && temp <= 135)
+			g_sta_info.supported_band |= BIT(2);
+		i++;
+		count--;
+	}
+}
+
+void supp_channels_band_conversion(u8 *supp_channels) {
+	int count = 0;
+	int i = 1;
+	int temp = 0;
+
+	count = (g_sta_info.supp_channels[0]);
+	if (count < 2)
+		g_sta_info.supported_band = 0;
+
+	while((count-1) >= 0) {
+		temp = g_sta_info.supp_channels[i];
+		if (temp >= 1 && temp <= 13)
+			g_sta_info.supported_band |= BIT(0);
+		else if (temp >= 32 && temp <= 173)
+			g_sta_info.supported_band |= BIT(1);
+		i += 2;
+		count -= 2;
+	}
+}
+
+static int get_sta_info_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *msg_hdr;
+	struct nlattr *tb[NL80211_ATTR_MAX_INTERNAL + 1];
+	struct nlattr *tb_vendor[NL80211_ATTR_MAX_INTERNAL + 1];
+	struct nlattr *vendor_data, *attr_link_info;
+	int vendor_len;
+	struct resp_info *info = (struct resp_info *)arg;
+	u8 *assoc_req_ie = NULL;
+	size_t assoc_req_ie_len = 0;
+
+	if (!info || !info->reply_buf) {
+		wpa_printf(MSG_ERROR,"Invalid reply_buf");
+		return -1;
+	}
+
+	wpa_printf(MSG_INFO,"Recv STA info %02x:%02x:%02x:%02x:%02x:%02x",
+	      info->mac_addr[0], info->mac_addr[1], info->mac_addr[2],
+	      info->mac_addr[3], info->mac_addr[4], info->mac_addr[5]);
+
+	msg_hdr = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
+	nla_parse(tb, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(msg_hdr, 0),
+		  genlmsg_attrlen(msg_hdr, 0), NULL);
+
+	if (!tb[NL80211_ATTR_VENDOR_DATA]) {
+		wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA not found");
+		return -1;
+	}
+
+	vendor_data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
+	vendor_len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
+
+	if (nla_parse(tb_vendor, NL80211_ATTR_MAX_INTERNAL,
+		      vendor_data, vendor_len, NULL)) {
+		wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA not found");
+		return -1;
+	}
+
+	attr_link_info = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR];
+	if (attr_link_info) {
+		struct nlattr *tb_link_info[NL80211_ATTR_MAX + 1];
+		struct nlattr *attr_survey_info, *attr_sta_info;
+
+		nla_parse(tb_link_info, NL80211_ATTR_MAX, nla_data(attr_link_info),
+			  nla_len(attr_link_info), NULL);
+		attr_survey_info = tb_link_info[NL80211_ATTR_SURVEY_INFO];
+		if (attr_survey_info) {
+			struct nlattr *tb_survey_info[NL80211_SURVEY_INFO_MAX + 1];
+
+			nla_parse(tb_survey_info, NL80211_SURVEY_INFO_MAX,
+				  nla_data(attr_survey_info),
+				  nla_len(attr_survey_info), NULL);
+			if (tb_survey_info[NL80211_SURVEY_INFO_FREQUENCY]) {
+				g_sta_info.freq =
+					nla_get_u32(tb_survey_info[NL80211_SURVEY_INFO_FREQUENCY]);
+				wpa_printf(MSG_INFO,"channel %d", g_sta_info.freq);
+			}
+		}
+
+		attr_sta_info = tb_link_info[NL80211_ATTR_STA_INFO];
+		if (attr_sta_info) {
+			struct nlattr *tb_sta_info[NL80211_STA_INFO_MAX + 1];
+
+			nla_parse(tb_sta_info, NL80211_STA_INFO_MAX,
+				  nla_data(attr_sta_info),
+				  nla_len(attr_sta_info), NULL);
+			if (tb_sta_info[NL80211_STA_INFO_SIGNAL]) {
+				g_sta_info.rssi = nla_get_u8(tb_sta_info[NL80211_STA_INFO_SIGNAL]);
+				g_sta_info.rssi -= NOISE_FLOOR_DBM;
+				wpa_printf(MSG_INFO,"rssi %d", g_sta_info.rssi);
+			}
+			if (tb_sta_info[NL80211_STA_INFO_TX_BITRATE]) {
+				struct nlattr *tb_antenna_info[NL80211_RATE_INFO_MAX + 1];
+				nla_parse(tb_antenna_info, NL80211_RATE_INFO_MAX,
+					  nla_data(tb_sta_info[NL80211_STA_INFO_TX_BITRATE]),
+					  nla_len(tb_sta_info[NL80211_STA_INFO_TX_BITRATE]),
+					  NULL);
+			}
+		}
+
+		if (tb_link_info[NL80211_ATTR_REASON_CODE]) {
+			g_sta_info.reason =
+				nla_get_u32(tb_link_info[NL80211_ATTR_REASON_CODE]);
+			wpa_printf(MSG_INFO,"reason %d", g_sta_info.reason);
+		}
+
+		if (tb_link_info[NL80211_ATTR_STA_CAPABILITY]) {
+			g_sta_info.cap =
+				nla_get_u16(tb_link_info[NL80211_ATTR_STA_CAPABILITY]);
+			wpa_printf(MSG_INFO,"cap %04x", g_sta_info.cap);
+		}
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE]) {
+		g_sta_info.data_rate =
+			nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE]);
+		wpa_printf(MSG_INFO,"data_rate %d", g_sta_info.data_rate);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT]) {
+		g_sta_info.rx_retry_pkts +=
+			nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT]);
+		wpa_printf(MSG_INFO,"rx_retry_pkts %d", g_sta_info.rx_retry_pkts);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT]) {
+		g_sta_info.rx_bcmc_pkts +=
+			nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT]);
+		wpa_printf(MSG_INFO,"rx_bcmc_pkts %d", g_sta_info.rx_bcmc_pkts);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH]) {
+		g_sta_info.bandwidth =
+			nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH]);
+		wpa_printf(MSG_INFO,"bandwidth %d", g_sta_info.bandwidth);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]) {
+		g_sta_info.dot11_mode =
+			nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]);
+		wpa_printf(MSG_INFO,"dot11_mode %d", g_sta_info.dot11_mode);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE]) {
+		g_sta_info.supported_mode =
+			nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE]);
+		wpa_printf(MSG_INFO,"supported_mode %d", g_sta_info.supported_mode);
+	}
+
+	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES]) {
+		assoc_req_ie =
+			nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES]);
+		assoc_req_ie_len =
+			nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES]);
+	}
+	parse_assoc_req_ies(assoc_req_ie, assoc_req_ie_len);
+
+	if (g_sta_info.supp_op_classes) {
+		op_class_band_conversion(g_sta_info.supp_op_classes);
+	}
+	else if (g_sta_info.supp_channels) {
+		supp_channels_band_conversion(g_sta_info.supp_channels);
+	}
+	else
+		wpa_printf(MSG_ERROR,"supp_op_classes and supp_channels both are null");
+
+	g_sta_info.num_received_sta_info++;
+
+	if (g_sta_info.num_received_sta_info == g_sta_info.num_sta) {
+		if (g_sta_info.num_sta == 1 && tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS]) {
+			snprintf(info->reply_buf, info->reply_buf_len,
+				 "%02x:%02x:%02x:%02x:%02x:%02x "
+				 "%d %d %04x "
+				 "%02x:%02x:%02x %d %d %d %d %d %d %d %d %d %s",
+				 info->mac_addr[0], info->mac_addr[1],
+				 info->mac_addr[2], info->mac_addr[3],
+				 info->mac_addr[4], info->mac_addr[5],
+				 g_sta_info.rx_retry_pkts, g_sta_info.rx_bcmc_pkts,
+				 g_sta_info.cap, info->mac_addr[0],
+				 info->mac_addr[1], info->mac_addr[2],
+				 g_sta_info.freq,
+				 g_sta_info.bandwidth,
+				 g_sta_info.rssi,
+				 g_sta_info.data_rate,
+				 g_sta_info.dot11_mode,
+				 -1,
+				 -1,
+				 g_sta_info.reason,
+				 g_sta_info.supported_mode,
+				 info->country);
+		} else if (g_sta_info.num_sta == 1 && !tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS]) {
+			snprintf(info->reply_buf, info->reply_buf_len,
+				 "%02x:%02x:%02x:%02x:%02x:%02x "
+				 "%d %d %04x "
+				 "%02x:%02x:%02x %d %d %d %d %d %d %d %d %u %s",
+				 info->mac_addr[0], info->mac_addr[1],
+				 info->mac_addr[2], info->mac_addr[3],
+				 info->mac_addr[4], info->mac_addr[5],
+				 g_sta_info.rx_retry_pkts, g_sta_info.rx_bcmc_pkts,
+				 g_sta_info.cap, info->mac_addr[0],
+				 info->mac_addr[1], info->mac_addr[2],
+				 g_sta_info.freq,
+				 g_sta_info.bandwidth,
+				 g_sta_info.rssi,
+				 g_sta_info.data_rate,
+				 g_sta_info.supported_mode,
+				 -1,
+				 -1,
+				 g_sta_info.reason,
+				 g_sta_info.supported_band,
+				 info->country);
+		} else {
+			/* Summary of all STAs */
+			snprintf(info->reply_buf, info->reply_buf_len,
+				 "%d %d %04x "
+				 "%d %d %d %d %d %d %d %d %d %s",
+				 g_sta_info.rx_retry_pkts, g_sta_info.rx_bcmc_pkts,
+				 -1, /* CAP */
+				 -1, /* Channel */
+				 -1, /* Bandwidth */
+				 -1, /* Rssi */
+				 -1, /* Data_rate */
+				 -1, /* 11_mode */
+				 -1,
+				 -1,
+				 -1, /* Reason */
+				 -1, /* Support_mode */
+				 info->country);
+		}
+
+		wpa_printf(MSG_INFO,"%s", info->reply_buf);
+	}
+
+	return 0;
+}
+
+static int wpa_driver_ioctl(struct i802_bss *bss, char *cmd,
+				 char *buf, size_t buf_len, int *status,
+				 struct wpa_driver_nl80211_data *drv) {
+	struct ifreq ifr;
+	android_wifi_priv_cmd priv_cmd;
+	memset(&ifr, 0, sizeof(ifr));
+	memset(&priv_cmd, 0, sizeof(priv_cmd));
+	os_memcpy(buf, cmd, strlen(cmd) + 1);
+	strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+	priv_cmd.buf = buf;
+	priv_cmd.used_len = buf_len;
+	priv_cmd.total_len = buf_len;
+	ifr.ifr_data = &priv_cmd;
+
+	if ((ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) {
+		wpa_printf(MSG_ERROR,"%s: failed to issue private commands\n", __func__);
+		*status = 1;
+		return WPA_DRIVER_OEM_STATUS_FAILURE;
+	} else {
+		wpa_printf(MSG_ERROR,"Response: %s", buf);
+		return WPA_DRIVER_OEM_STATUS_SUCCESS;
+	}
+}
+
+static int wpa_driver_send_get_sta_info_cmd(struct i802_bss *bss, u8 *mac,
+					    char *buf, size_t buf_len,
+					    int *status)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *nlmsg;
+	struct nlattr *attr;
+	struct resp_info info;
+
+	memset(&info, 0, sizeof(info));
+	os_memcpy(&info.mac_addr[0], mac, MAC_ADDR_LEN);
+	info.reply_buf = buf;
+	info.reply_buf_len = buf_len;
+
+	char *p;
+	if(wpa_driver_ioctl(bss, "GETCOUNTRYREV", buf, buf_len, &status, drv) == 0){
+		p = strstr(buf, " ");
+		if(p != NULL)
+			memcpy(info.country, (p+1), strlen(p+1)+1);//length of p including null
+	}
+
+	nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+				     QCA_NL80211_VENDOR_SUBCMD_GET_STATION);
+	if (!nlmsg) {
+		wpa_printf(MSG_ERROR,"Failed to allocate nl message");
+		return -1;
+	}
+
+	attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+	if (!attr) {
+		nlmsg_free(nlmsg);
+		return -1;
+	}
+
+	if (nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE,
+		    MAC_ADDR_LEN, mac)) {
+		wpa_printf(MSG_ERROR,"Failed to put QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE");
+		nlmsg_free(nlmsg);
+		return -1;
+	}
+
+	nla_nest_end(nlmsg, attr);
+
+	*status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+			     get_sta_info_handler, &info);
+	if (*status != 0) {
+		wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", *status);
+		return -1;
+	}
+
+	return strlen(info.reply_buf);
+}
+
+static int wpa_driver_get_all_sta_info(struct i802_bss *bss, char *buf,
+				       size_t buf_len, int *status)
+{
+	struct hostapd_data *hapd = bss->ctx;
+	struct sta_info *sta;
+	int ret, total_ret = 0;
+
+	if (!hapd) {
+		wpa_printf(MSG_ERROR,"hapd is NULL");
+		return -1;
+	}
+
+	g_sta_info.num_sta = hapd->num_sta;
+
+	sta = hapd->sta_list;
+	while (sta) {
+		ret = wpa_driver_send_get_sta_info_cmd(bss, sta->addr, buf,
+						       buf_len, status);
+		if (ret < 0) {
+			wpa_printf(MSG_ERROR,"Failed to get STA info, num_sta %d, sent %d",
+			      g_sta_info.num_sta, g_sta_info.num_request_sta_info);
+			g_sta_info.num_sta = 0;
+			return ret;
+		}
+		g_sta_info.num_request_sta_info++;
+		sta = sta->next;
+		total_ret += ret;
+	}
+
+	return total_ret;
+}
+
+static int wpa_driver_handle_get_sta_info(struct i802_bss *bss, char *cmd,
+					  char *buf, size_t buf_len,
+					  int *status)
+{
+	u8 mac[MAC_ADDR_LEN];
+
+	os_memset(&g_sta_info, 0, sizeof(g_sta_info));
+
+	cmd = skip_white_space(cmd);
+	if (strlen(cmd) >= MAC_ADDR_LEN * 2 + MAC_ADDR_LEN - 1
+	    && convert_string_to_bytes(mac, cmd, MAC_ADDR_LEN) > 0) {
+		g_sta_info.num_sta = 1;
+		return wpa_driver_send_get_sta_info_cmd(bss, mac, buf, buf_len,
+							status);
+	}
+
+	return wpa_driver_get_all_sta_info(bss, buf, buf_len, status);
+}
+
 int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
 				  size_t buf_len )
 {
@@ -167,6 +1107,51 @@
 					  "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
 	} else if (os_strncasecmp(cmd, "SET_TXPOWER ", 12) == 0) {
 		return wpa_driver_cmd_set_tx_power(priv, cmd + 12);
+	} else if(os_strncasecmp(cmd, "GETSTATSBSSINFO", 15) == 0) {
+
+		struct resp_info info;
+		struct nl_msg *nlmsg;
+
+		memset(&info, 0, sizeof(struct resp_info));
+		info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION;
+		info.cmd_type = GETSTATSBSSINFO;
+		char *p;
+		if(wpa_driver_ioctl(bss, "GETCOUNTRYREV", buf, buf_len, &status, drv) == 0){
+			p = strstr(buf, " ");
+			if(p != NULL)
+				memcpy(info.country, (p+1), strlen(p+1)+1);//length of p including null
+		}
+		cmd += 16;
+		os_memset(buf, 0, buf_len);
+
+		info.reply_buf = buf;
+		info.reply_buf_len = buf_len;
+
+		nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+					     info.subcmd);
+		if (!nlmsg) {
+			wpa_printf(MSG_ERROR,"Failed to allocate nl message");
+			return -1;
+		}
+
+		if (populate_nlmsg(nlmsg, cmd, info.cmd_type)) {
+			wpa_printf(MSG_ERROR,"Failed to populate nl message");
+			nlmsg_free(nlmsg);
+			return -1;
+		}
+
+		status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+				     response_handler, &info);
+		if (status != 0) {
+			wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", status);
+			return -1;
+		}
+
+		return strlen(info.reply_buf);
+	} else if (os_strncasecmp(cmd, "GETSTATSSTAINFO", 15) == 0) {
+		cmd += 15;
+		return wpa_driver_handle_get_sta_info(bss, cmd, buf, buf_len,
+						      &status);
 	} 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
new file mode 100644
index 0000000..ef16c13
--- /dev/null
+++ b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WPA_DRIVER_COMMON_LIB
+#define WPA_DRIVER_COMMON_LIB
+
+#include "android_drv.h"	//needed?
+#define OUI_LEN		3
+#define MAX_CMD_LEN	32
+#define MAC_ADDR_LEN	6
+
+#define IEEE80211_HE_OPERATION_VHT_OPER_MASK 0x00004000
+#define IEEE80211_HE_OPERATION_CO_LOC_BSS_MASK 0x00008000
+#define IEEE80211_HE_OPERATION_6G_OPER_MASK 0x00020000
+
+#define HE_OPER_VHT_CH_WIDTH_OFFSET 0
+#define HE_OPER_VHT_MAX_OFFSET 2
+
+#define HE_OPER_CO_LOCATED_MAX_OFFSET 0
+
+#define HE_OPER_6G_PARAMS_OFFSET 1
+
+#define HE_OPER_6G_PARAMS_SUB_CH_BW_MASK 0X03
+
+#define CHANNEL_BW_INVALID 255
+
+struct bss_info {
+	uint8_t oui[OUI_LEN];
+	char ssid[MAX_SSID_LEN + 1];
+	int channel;
+	int bw;
+	int rssi;
+	int data_rate;
+	/* 0 : 11b, 1 : 11g, 2 : 11n, 3 : 11a, 4 : 11ac */
+	int mode_80211;
+	/* 0 : SISO, 1 : MIMO (2X2), 2 : MIMO (3X3), 3 : MIMO (4X4) */
+	int snr;
+	int noise;
+	int akm;
+	int roaming_count;
+	/* 0: None, 1: 11k, 2: 11v, 3: 11kv */
+	int mode_11kv;
+	/* Bit mask value of 11kv support */
+	int mask_11kv;
+	u32 disc_reasn_code;
+};
+
+enum get_info_cmd {
+	GETSTATSBSSINFO = 1,
+};
+
+struct resp_info {
+	u32 subcmd;
+	char *reply_buf;
+	int reply_buf_len;
+	enum get_info_cmd cmd_type;
+	uint8_t mac_addr[MAC_ADDR_LEN];
+	u32 freq;
+	uint8_t country[4];
+};
+
+#define QCA_NL80211_VENDOR_SUBCMD_GET_STATION 121
+
+#ifndef CHANWIDTH_USE_HT
+#define CHANWIDTH_USE_HT VHT_CHANWIDTH_USE_HT
+#endif /* CHANWIDTH_USE_HT */
+#ifndef CHANWIDTH_80MHZ
+#define CHANWIDTH_80MHZ VHT_CHANWIDTH_80MHZ
+#endif /* CHANWIDTH_80MHZ */
+#ifndef CHANWIDTH_160MHZ
+#define CHANWIDTH_160MHZ VHT_CHANWIDTH_160MHZ
+#endif /* CHANWIDTH_160MHZ */
+#ifndef CHANWIDTH_80P80MHZ
+#define CHANWIDTH_80P80MHZ VHT_CHANWIDTH_80P80MHZ
+#endif /* CHANWIDTH_80P80MHZ */
+
+/**
+ * enum qca_wlan_vendor_attr_get_station - Sub commands used by
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STATION to get the corresponding
+ * station information. The information obtained through these
+ * commands signify the current info in connected state and
+ * latest cached information during the connected state , if queried
+ * when in disconnected state.
+ */
+enum qca_wlan_vendor_attr_get_station {
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX =
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_station_info - Station Info queried
+ * through QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
+ */
+enum qca_wlan_vendor_attr_get_station_info {
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_INVALID = 0,
+	/*
+	 * Get the standard NL attributes Nested with this attribute.
+	 * Ex : Query BW , BITRATE32 , NSS , Signal , Noise of the Link -
+	 * NL80211_ATTR_SSID / NL80211_ATTR_SURVEY_INFO (Connected Channel) /
+	 * NL80211_ATTR_STA_INFO
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR,
+	/*
+	 * Get the standard NL attributes Nested with this attribute.
+	 * Ex : Query HT/VHT Capability advertized by the AP.
+	 * NL80211_ATTR_VHT_CAPABILITY / NL80211_ATTR_HT_CAPABILITY
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_AP_INFO_ATTR,
+
+	/* Number of successful Roam attempts before a disconnect,
+	 * Unsigned 32 bit value
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT,
+
+	/* Authentication Key Management Type used for the connected session.
+	 * Signified by enum qca_wlan_auth_type
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM,
+
+	/* 802.11 Mode of the connected Session,
+	 * signified by enum qca_wlan_802_11_mode
+	 */
+	QCA_WLAN_VENDOR_ATTR_802_11_MODE,
+
+	/* HS20 Indication Element */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_AP_INFO_HS20_INDICATION,
+
+	/* HT/VHT operation elements */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION,
+
+	/* Status Code Corresponding to the Association Failure.
+	 * Unsigned 32 bit value
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSSOC_FAIL_REASON,
+
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_FAILURE,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AVG_RSSI_PER_CHAIN,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_SUCCEED,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_LAST_PKT_RSSI,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_EXHAUST,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_TOTAL_FW,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_FW,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_EXHAUST_FW,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST - 1,
+};
+
+#define NOISE_FLOOR_DBM (96)
+
+#define WMI_MAX_CHAINS (3)
+
+struct remote_sta_info {
+	u8 num_sta;
+	u8 num_request_sta_info;
+	u8 num_received_sta_info;
+	u32 rx_retry_pkts;
+	u32 rx_bcmc_pkts;
+	u16 cap;
+	u32 freq;
+	u8 bandwidth;
+	s8 rssi;
+	u32 data_rate;
+	u32 dot11_mode;
+	u32 reason;
+	u8 supported_mode;
+	u32 tx_pckts;
+	u32 tx_failures;
+	u32 tx_rate;
+	s32 avg_rssi_per_chain[WMI_MAX_CHAINS];
+	u32 tx_pkts_retried;
+	u32 tx_pkts_retry_exhausted;
+	s32 rx_lastpkt_rssi;
+	u32 tx_pkts_total;
+	u32 tx_pkts_retries;
+	u32 tx_pkts_fw_total;
+	u32 tx_pkts_fw_retries;
+	u32 tx_pkts_fw_retry_exhausted;
+	u8 *supp_op_classes; /* Supported Operating Classes element, if
+			      * received, starting from the Length field */
+	u8 *supp_channels;
+	u32 supported_band;
+};
+
+#endif