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