summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2021-02-22 00:35:32 -0800
committerLinux Build Service Account <lnxbuild@localhost>2021-02-22 00:35:32 -0800
commitbd151b73d210040516e5482143f7a06146a8ef5c (patch)
tree5c91feb998fa5c6409e653df8008c86be5146944
parent0639e782b8c9e2e15f09c41e127d99a9bfdb97e7 (diff)
parent2777b3a69a7517627e04c5873c496e974a3717c7 (diff)
Merge 2777b3a69a7517627e04c5873c496e974a3717c7 on remote branch
Change-Id: I475cb3cfc122624e2d0f643947436d91ece356a6
-rw-r--r--qcwcn/wifi_hal/llstats.cpp13
-rw-r--r--qcwcn/wifi_hal/llstatscommand.h3
-rw-r--r--qcwcn/wifi_hal/nan.cpp14
-rw-r--r--qcwcn/wifi_hal/nan_i.h4
-rw-r--r--qcwcn/wifi_hal/nan_ind.cpp18
-rw-r--r--qcwcn/wifi_hal/nan_rsp.cpp2
-rw-r--r--qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c770
-rw-r--r--qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h90
8 files changed, 779 insertions, 135 deletions
diff --git a/qcwcn/wifi_hal/llstats.cpp b/qcwcn/wifi_hal/llstats.cpp
index fc36df9..46f6a5e 100644
--- a/qcwcn/wifi_hal/llstats.cpp
+++ b/qcwcn/wifi_hal/llstats.cpp
@@ -54,6 +54,7 @@ LLStatsCommand::LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 su
memset(&mHandler, 0,sizeof(mHandler));
mRadioStatsSize = 0;
mNumRadios = 0;
+ mNumRadiosAllocated = 0;
}
LLStatsCommand::~LLStatsCommand()
@@ -864,6 +865,11 @@ wifi_error LLStatsCommand::notifyResponse()
/* Indicate stats to framework only if both radio and iface stats
* are present */
if (mResultsParams.radio_stat && mResultsParams.iface_stat) {
+ if (mNumRadios > mNumRadiosAllocated) {
+ ALOGE("%s: Force reset mNumRadios=%d to allocated=%d",
+ __FUNCTION__, mNumRadios, mNumRadiosAllocated);
+ mNumRadios = mNumRadiosAllocated;
+ }
mHandler.on_link_stats_results(mRequestId,
mResultsParams.iface_stat, mNumRadios,
mResultsParams.radio_stat);
@@ -882,6 +888,11 @@ void LLStatsCommand::clearStats()
if(mResultsParams.radio_stat)
{
wifi_radio_stat *radioStat = mResultsParams.radio_stat;
+ if (mNumRadios > mNumRadiosAllocated) {
+ ALOGE("%s: Force reset mNumRadios=%d to allocated=%d",
+ __FUNCTION__, mNumRadios, mNumRadiosAllocated);
+ mNumRadios = mNumRadiosAllocated;
+ }
for (u8 radio = 0; radio < mNumRadios; radio++) {
if (radioStat->tx_time_per_levels) {
free(radioStat->tx_time_per_levels);
@@ -895,6 +906,7 @@ void LLStatsCommand::clearStats()
mResultsParams.radio_stat = NULL;
mRadioStatsSize = 0;
mNumRadios = 0;
+ mNumRadiosAllocated = 0;
}
if(mResultsParams.iface_stat)
{
@@ -979,6 +991,7 @@ int LLStatsCommand::handleResponse(WifiEvent &reply)
+ mRadioStatsSize);
memset(radioStatsBuf, 0, resultsBufSize);
mRadioStatsSize += resultsBufSize;
+ mNumRadiosAllocated ++;
if (tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS])
radioStatsBuf->num_tx_levels = nla_get_u32(tb_vendor[
diff --git a/qcwcn/wifi_hal/llstatscommand.h b/qcwcn/wifi_hal/llstatscommand.h
index 5d4c480..86b9672 100644
--- a/qcwcn/wifi_hal/llstatscommand.h
+++ b/qcwcn/wifi_hal/llstatscommand.h
@@ -83,7 +83,10 @@ private:
u32 mRadioStatsSize;
+ // mNumRadios is decoded from tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS]
+ // nNumRadiosAllocated is the actual radio stats received.
u8 mNumRadios;
+ u8 mNumRadiosAllocated;
LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
diff --git a/qcwcn/wifi_hal/nan.cpp b/qcwcn/wifi_hal/nan.cpp
index 3df67f9..2428e1d 100644
--- a/qcwcn/wifi_hal/nan.cpp
+++ b/qcwcn/wifi_hal/nan.cpp
@@ -1393,7 +1393,7 @@ u16 NANTLV_WriteTlv(pNanTlv pInTlv, u8 *pOutTlv)
return writeLen;
}
-u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv)
+u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv, int inBufferSize)
{
u16 readLen = 0;
@@ -1409,6 +1409,12 @@ u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv)
return readLen;
}
+ if(inBufferSize < NAN_TLV_HEADER_SIZE) {
+ ALOGE("Insufficient length to process TLV header, inBufferSize = %d",
+ inBufferSize);
+ return readLen;
+ }
+
pOutTlv->type = *pInTlv++;
pOutTlv->type |= *pInTlv++ << 8;
readLen += 2;
@@ -1419,6 +1425,12 @@ u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv)
pOutTlv->length |= *pInTlv++ << 8;
readLen += 2;
+ if(pOutTlv->length > inBufferSize - NAN_TLV_HEADER_SIZE) {
+ ALOGE("Insufficient length to process TLV header, inBufferSize = %d",
+ inBufferSize);
+ return readLen;
+ }
+
ALOGV("READ TLV length %u, readLen %u", pOutTlv->length, readLen);
if (pOutTlv->length) {
diff --git a/qcwcn/wifi_hal/nan_i.h b/qcwcn/wifi_hal/nan_i.h
index f79d842..d9aa39c 100644
--- a/qcwcn/wifi_hal/nan_i.h
+++ b/qcwcn/wifi_hal/nan_i.h
@@ -340,6 +340,8 @@ typedef enum
#define NAN_WINDOW_DW 0
#define NAN_WINDOW_FAW 1
+#define NAN_TLV_HEADER_SIZE 4
+
/* NAN Error Rsp */
typedef struct PACKED
{
@@ -786,7 +788,7 @@ typedef struct PACKED
/* Function Declarations */
u8* addTlv(u16 type, u16 length, const u8* value, u8* pOutTlv);
-u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv);
+u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv, int inBufferSize);
u16 NANTLV_WriteTlv(pNanTlv pInTlv, u8 *pOutTlv);
/* NAN Beacon Sdf Payload Req */
diff --git a/qcwcn/wifi_hal/nan_ind.cpp b/qcwcn/wifi_hal/nan_ind.cpp
index 6496314..834cc2a 100644
--- a/qcwcn/wifi_hal/nan_ind.cpp
+++ b/qcwcn/wifi_hal/nan_ind.cpp
@@ -227,7 +227,7 @@ int NanCommand::getNanPublishReplied(NanPublishRepliedInd *event)
return WIFI_SUCCESS;
}
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
switch (outputTlv.type) {
case NAN_TLV_TYPE_MAC_ADDRESS:
if (outputTlv.length > sizeof(event->addr)) {
@@ -296,7 +296,7 @@ int NanCommand::getNanMatch(NanMatchInd *event)
}
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -484,7 +484,7 @@ int NanCommand::getNanFollowup(NanFollowupInd *event)
}
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -548,7 +548,7 @@ int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event)
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -635,7 +635,7 @@ int NanCommand::getNanTca(NanTCAInd *event)
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -688,7 +688,7 @@ int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event)
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -811,7 +811,7 @@ int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue,
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -1299,7 +1299,7 @@ int NanCommand::getNanRangeRequestReceivedInd(NanRangeRequestInd *event)
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
@@ -1348,7 +1348,7 @@ int NanCommand::getNanRangeReportInd(NanRangeReportInd *event)
ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
while ((remainingLen > 0) &&
- (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
diff --git a/qcwcn/wifi_hal/nan_rsp.cpp b/qcwcn/wifi_hal/nan_rsp.cpp
index 2ab0a5d..b461b88 100644
--- a/qcwcn/wifi_hal/nan_rsp.cpp
+++ b/qcwcn/wifi_hal/nan_rsp.cpp
@@ -513,7 +513,7 @@ int NanCommand::getNanResponse(transaction_id *id, NanResponseMsg *pRsp)
int remainingLen = (mNanDataLen - \
(sizeof(NanMsgHeader) + sizeof(NanStatsRspParams)));
if (remainingLen > 0) {
- readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv);
+ readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen);
ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index 9fc42d4..c2db662 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -72,6 +72,63 @@ static int wpa_driver_cmd_set_ani_level(struct i802_bss *bss, int mode, int ofdm
return ret;
}
+static int wpa_driver_cmd_set_congestion_report(struct i802_bss *bss, char *cmd)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *params = NULL;
+ char *endptr = NULL;
+ int ret;
+ int enable = -1, threshold = -1, interval = -1;
+
+ wpa_printf(MSG_INFO, "%s enter", __FUNCTION__);
+
+ enable = strtol(cmd, &endptr, 10);
+ if (enable != 0 && enable != 1) {
+ wpa_printf(MSG_ERROR, "%s: invalid enable arg %d", __FUNCTION__, enable);
+ return -EINVAL;
+ }
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE,
+ QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT) ||
+ nla_put_u8(msg,
+ QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE,
+ enable)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+ if (enable == 1) {
+ if (!(*endptr) ||
+ ((threshold = strtol(endptr, &endptr, 10)) < 0 || threshold > 100) ||
+ !(*endptr) ||
+ ((interval = strtol(endptr, &endptr, 10)) < 1 || interval > 255)) {
+ wpa_printf(MSG_ERROR, "%s: args less or invalid", __FUNCTION__);
+ return -EINVAL;
+ }
+ if (nla_put_u8(msg,
+ QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD,
+ threshold) || nla_put_u8(msg,
+ QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL,
+ interval)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+ }
+ nla_nest_end(msg, params);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ wpa_printf(MSG_INFO, "%s: set congestion report: enable=%d, threshold=%d,"
+ "interval=%d", __FUNCTION__, enable, threshold, interval);
+ if (!ret)
+ return 0;
+ wpa_printf(MSG_ERROR, "%s: Failed set congestion report, ret=%d", __FUNCTION__, ret);
+ return ret;
+}
+
static int wpa_driver_cmd_set_tx_power(struct i802_bss *bss, char *cmd)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -205,7 +262,7 @@ 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 *tb_vendor[GET_STATION_INFO_MAX + 1];
struct nlattr *attr, *attr1, *attr2;
u8 *beacon_ies = NULL;
size_t beacon_ies_len = 0;
@@ -217,7 +274,7 @@ static int parse_station_info(struct resp_info *info, struct nlattr *vendata,
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,
+ nla_parse(tb_vendor, GET_STATION_INFO_MAX,
vendata, datalen, NULL);
attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR];
@@ -304,19 +361,18 @@ static int parse_station_info(struct resp_info *info, struct nlattr *vendata,
"QCA_WLAN_VENDOR_ATTR_GET_STATION_LINK_INFO_ATTR not found");
}
- if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM]) {
+ if (tb_vendor[GET_STATION_INFO_AKM]) {
data.akm = nla_get_u32(
- tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM]);
+ tb_vendor[GET_STATION_INFO_AKM]);
}
- if (tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]) {
+ 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];
+ attr = tb_vendor[GET_STATION_INFO_VHT_OPERATION];
+ attr1 = tb_vendor[GET_STATION_INFO_HT_OPERATION];
+ attr2 = tb_vendor[GET_STATION_INFO_HE_OPERATION];
if (attr) {
struct ieee80211_vht_operation *info = nla_data(attr);
@@ -429,7 +485,7 @@ static int parse_station_info(struct resp_info *info, struct nlattr *vendata,
}
parse_beacon_ies:
- attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES];
+ attr = tb_vendor[GET_STATION_INFO_BEACON_IES];
if (attr) {
beacon_ies = nla_data(attr);
@@ -440,9 +496,9 @@ parse_beacon_ies:
}
}
- if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON]) {
+ if (tb_vendor[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]);
+ 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",
@@ -848,7 +904,33 @@ void ap_sta_copy_channels(const u8 *supp_channels,
supp_channels_len);
}
-static void parse_assoc_req_ies(const u8 *ies, int ies_len) {
+static void parse_ext_ie(const u8 *ie, int ie_len)
+{
+ u8 ext_id;
+
+ if (ie_len < 1) {
+ wpa_printf(MSG_ERROR,"parse error, ie_len = %d", ie_len);
+ return;
+ }
+
+ ext_id = *ie++;
+ ie_len--;
+
+ switch (ext_id) {
+ case WLAN_EID_EXT_HE_CAPABILITIES:
+ wpa_printf(MSG_INFO,"HE supported");
+ g_sta_info.flags.he_supported = 1;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,"ext_id = %d", ext_id);
+ break;
+ }
+
+ return;
+}
+
+static void parse_assoc_req_ies(const u8 *ies, int ies_len)
+{
int left = ies_len;
const u8 *pos = ies;
@@ -871,6 +953,17 @@ static void parse_assoc_req_ies(const u8 *ies, int ies_len) {
case WLAN_EID_SUPPORTED_CHANNELS:
ap_sta_copy_channels(pos, ie_len);
break;
+ case WLAN_EID_HT_CAP:
+ wpa_printf(MSG_INFO,"HT supported");
+ g_sta_info.flags.ht_supported = 1;
+ break;
+ case WLAN_EID_VHT_CAP:
+ wpa_printf(MSG_INFO,"VHT supported");
+ g_sta_info.flags.vht_supported = 1;
+ break;
+ case WLAN_EID_EXTENSION:
+ parse_ext_ie(pos, ie_len);
+ break;
default:
break;
}
@@ -881,7 +974,6 @@ static void parse_assoc_req_ies(const u8 *ies, int ies_len) {
if (left)
wpa_printf(MSG_ERROR,"parse error, left = %d", left);
- return;
}
void op_class_band_conversion(u8 *op_classes) {
@@ -924,7 +1016,69 @@ void supp_channels_band_conversion(u8 *supp_channels) {
}
}
-static int get_sta_info_handler(struct nl_msg *msg, void *arg)
+static int fill_sta_info(struct remote_sta_info *sta_info,
+ char *buf, size_t buf_len)
+{
+ int ret;
+ if (sta_info->num_sta == 1) {
+ if (sta_info->show_band)
+ ret = snprintf(buf, buf_len,
+ "%02x:%02x:%02x:%02x:%02x:%02x %d %d %04x %02x:%02x:%02x %d %d %d %d %d %d %d %d %d %s",
+ sta_info->mac_addr[0], sta_info->mac_addr[1],
+ sta_info->mac_addr[2], sta_info->mac_addr[3],
+ sta_info->mac_addr[4], sta_info->mac_addr[5],
+ sta_info->rx_retry_pkts, sta_info->rx_bcmc_pkts,
+ sta_info->cap, sta_info->mac_addr[0],
+ sta_info->mac_addr[1], sta_info->mac_addr[2],
+ sta_info->freq,
+ sta_info->bandwidth,
+ sta_info->rssi,
+ sta_info->data_rate,
+ sta_info->dot11_mode,
+ -1,
+ -1,
+ sta_info->reason,
+ sta_info->supported_mode,
+ sta_info->country);
+ else
+ ret = snprintf(buf, buf_len,
+ "%02x:%02x:%02x:%02x:%02x:%02x %d %d %04x %02x:%02x:%02x %d %d %d %d %d %d %d %d %u %s",
+ sta_info->mac_addr[0], sta_info->mac_addr[1],
+ sta_info->mac_addr[2], sta_info->mac_addr[3],
+ sta_info->mac_addr[4], sta_info->mac_addr[5],
+ sta_info->rx_retry_pkts, sta_info->rx_bcmc_pkts,
+ sta_info->cap, sta_info->mac_addr[0],
+ sta_info->mac_addr[1], sta_info->mac_addr[2],
+ sta_info->freq,
+ sta_info->bandwidth,
+ sta_info->rssi,
+ sta_info->data_rate,
+ sta_info->supported_mode,
+ -1,
+ -1,
+ sta_info->reason,
+ sta_info->supported_band,
+ sta_info->country);
+ } else {
+ ret = snprintf(buf, buf_len,
+ "%d %d %04x %d %d %d %d %d %d %d %d %d %s",
+ sta_info->rx_retry_pkts, 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 */
+ sta_info->country);
+ }
+ return ret;
+}
+
+static int get_sta_info_legacy_handler(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *msg_hdr;
struct nlattr *tb[NL80211_ATTR_MAX_INTERNAL + 1];
@@ -935,8 +1089,8 @@ static int get_sta_info_handler(struct nl_msg *msg, void *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");
+ if (!info) {
+ wpa_printf(MSG_ERROR,"Invalid arg");
return -1;
}
@@ -949,7 +1103,7 @@ static int get_sta_info_handler(struct nl_msg *msg, void *arg)
genlmsg_attrlen(msg_hdr, 0), NULL);
if (!tb[NL80211_ATTR_VENDOR_DATA]) {
- wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA not found");
+ wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA parse error");
return -1;
}
@@ -1017,27 +1171,27 @@ static int get_sta_info_handler(struct nl_msg *msg, void *arg)
}
}
- if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE]) {
+ if (tb_vendor[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]);
+ nla_get_u32(tb_vendor[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]) {
+ if (tb_vendor[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]);
+ nla_get_u32(tb_vendor[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]) {
+ if (tb_vendor[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]);
+ nla_get_u32(tb_vendor[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]) {
+ if (tb_vendor[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]);
+ nla_get_u8(tb_vendor[GET_STATION_INFO_REMOTE_CH_WIDTH]);
wpa_printf(MSG_INFO,"bandwidth %d", g_sta_info.bandwidth);
}
@@ -1047,96 +1201,179 @@ static int get_sta_info_handler(struct nl_msg *msg, void *arg)
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]) {
+ if (tb_vendor[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]);
+ nla_get_u8(tb_vendor[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]) {
+ if (tb_vendor[GET_STATION_INFO_ASSOC_REQ_IES]) {
assoc_req_ie =
- nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES]);
+ nla_data(tb_vendor[GET_STATION_INFO_ASSOC_REQ_IES]);
assoc_req_ie_len =
- nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES]);
+ nla_len(tb_vendor[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);
+ g_sta_info.show_band = true;
}
else if (g_sta_info.supp_channels) {
supp_channels_band_conversion(g_sta_info.supp_channels);
+ g_sta_info.show_band = true;
}
else
wpa_printf(MSG_ERROR,"supp_op_classes and supp_channels both are null");
- g_sta_info.num_received_sta_info++;
+ g_sta_info.num_received_vendor_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,"num_received_vendor_sta_info %d",
+ g_sta_info.num_received_vendor_sta_info);
+
+ return 0;
+}
+
+static int
+wpa_driver_send_get_sta_info_legacy_cmd(struct i802_bss *bss, u8 *mac,
+ 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);
+ os_memcpy(&g_sta_info.mac_addr[0], mac, MAC_ADDR_LEN);
+
+ 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_legacy_handler, &info);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", *status);
+ return -1;
+ }
+
+ return 0;
+}
+
+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[GET_STA_INFO_MAX + 1];
+ struct nlattr *vendor_data;
+ int vendor_len;
+ struct resp_info *info = (struct resp_info *)arg;
+ uint8_t mac_addr[MAC_ADDR_LEN];
+
+ if (!info) {
+ wpa_printf(MSG_ERROR,"Invalid arg");
+ return -1;
+ }
+
+ 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 parse error");
+ return -1;
+ }
+
+ if (tb_vendor[GET_STA_INFO_MAC]) {
+ nla_memcpy(mac_addr,
+ tb_vendor[GET_STA_INFO_MAC],MAC_ADDR_LEN);
+ if (os_memcmp(mac_addr, info->mac_addr, MAC_ADDR_LEN)) {
+ wpa_printf(MSG_ERROR,"MAC address mismatch");
+ 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]);
+
+ if (tb_vendor[GET_STA_INFO_RX_RETRY_COUNT]) {
+ g_sta_info.rx_retry_pkts +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_RX_RETRY_COUNT]);
+ wpa_printf(MSG_INFO,"rx_retry_pkts %d", g_sta_info.rx_retry_pkts);
+ }
+
+ if (tb_vendor[GET_STA_INFO_RX_BC_MC_COUNT]) {
+ g_sta_info.rx_bcmc_pkts +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_RX_BC_MC_COUNT]);
+ wpa_printf(MSG_INFO,"rx_bcmc_pkts %d", g_sta_info.rx_bcmc_pkts);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TX_RETRY_SUCCEED]) {
+ g_sta_info.tx_pkts_retried +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_TX_RETRY_SUCCEED]);
+ wpa_printf(MSG_INFO,"tx_pkts_retried %d", g_sta_info.tx_pkts_retried);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TX_RETRY_EXHAUSTED]) {
+ g_sta_info.tx_pkts_retry_exhausted +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_TX_RETRY_EXHAUSTED]);
+ wpa_printf(MSG_INFO,"tx_pkts_retry_exhausted %d", g_sta_info.tx_pkts_retry_exhausted);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TARGET_TX_TOTAL]) {
+ g_sta_info.tx_pkts_fw_total +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_TX_TOTAL]);
+ wpa_printf(MSG_INFO,"tx_pkts_fw_total %d", g_sta_info.tx_pkts_fw_total);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TARGET_TX_RETRY]) {
+ g_sta_info.tx_pkts_fw_retries +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_TX_RETRY]);
+ wpa_printf(MSG_INFO,"tx_pkts_fw_retries %d", g_sta_info.tx_pkts_fw_retries);
+ }
- wpa_printf(MSG_INFO,"%s", info->reply_buf);
+ if (tb_vendor[GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED]) {
+ g_sta_info.tx_pkts_fw_retry_exhausted +=
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED]);
+ wpa_printf(MSG_INFO,"tx_pkts_fw_retry_exhausted %d", g_sta_info.tx_pkts_fw_retry_exhausted);
}
+
+ g_sta_info.num_received_vendor_sta_info++;
+
+ wpa_printf(MSG_INFO,"num_received_vendor_sta_info %d",
+ g_sta_info.num_received_vendor_sta_info);
+
return 0;
}
@@ -1165,8 +1402,7 @@ static int wpa_driver_ioctl(struct i802_bss *bss, char *cmd,
}
static int wpa_driver_send_get_sta_info_cmd(struct i802_bss *bss, u8 *mac,
- char *buf, size_t buf_len,
- int *status)
+ int *status, bool *new_cmd)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *nlmsg;
@@ -1175,18 +1411,13 @@ static int wpa_driver_send_get_sta_info_cmd(struct i802_bss *bss, u8 *mac,
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;
+ os_memcpy(&g_sta_info.mac_addr[0], mac, MAC_ADDR_LEN);
+
+ *new_cmd = true;
- 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);
+ QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO);
if (!nlmsg) {
wpa_printf(MSG_ERROR,"Failed to allocate nl message");
return -1;
@@ -1198,9 +1429,9 @@ static int wpa_driver_send_get_sta_info_cmd(struct i802_bss *bss, u8 *mac,
return -1;
}
- if (nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE,
+ if (nla_put(nlmsg, GET_STA_INFO_MAC,
MAC_ADDR_LEN, mac)) {
- wpa_printf(MSG_ERROR,"Failed to put QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE");
+ wpa_printf(MSG_ERROR,"Failed to put GET_STA_INFO_MAC");
nlmsg_free(nlmsg);
return -1;
}
@@ -1210,15 +1441,297 @@ static int wpa_driver_send_get_sta_info_cmd(struct i802_bss *bss, u8 *mac,
*status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
get_sta_info_handler, &info);
if (*status != 0) {
+ if (*status == -EOPNOTSUPP) {
+ wpa_printf(MSG_INFO,"Command is not supported, try legacy command");
+ *new_cmd = false;
+ return wpa_driver_send_get_sta_info_legacy_cmd(bss,
+ mac,
+ status);
+ } else {
+ wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", *status);
+ return -1;
+ }
+ }
+
+ g_sta_info.num_request_vendor_sta_info++;
+ wpa_printf(MSG_INFO,"num_request_vendor_sta_info %d",
+ g_sta_info.num_request_vendor_sta_info);
+
+ return 0;
+}
+
+static int get_station_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *msg_hdr;
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct nlattr *tb_sinfo[NL80211_STA_INFO_MAX + 1];
+ struct nlattr *tb_rate[NL80211_RATE_INFO_MAX + 1];
+ struct nlattr *sinfo_data, *attr;
+ int sinfo_len, tmp, num_chain = 0;
+ struct resp_info *info = (struct resp_info *)arg;
+ uint8_t mac_addr[MAC_ADDR_LEN];
+
+ if (!info) {
+ wpa_printf(MSG_ERROR,"Invalid arg");
+ return -1;
+ }
+
+ msg_hdr = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(msg_hdr, 0),
+ genlmsg_attrlen(msg_hdr, 0), NULL);
+
+ if (tb[NL80211_ATTR_MAC]) {
+ nla_memcpy(mac_addr, tb[NL80211_ATTR_MAC], MAC_ADDR_LEN);
+ if (os_memcmp(mac_addr, info->mac_addr, MAC_ADDR_LEN)) {
+ wpa_printf(MSG_ERROR,"MAC address mismatch");
+ 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]);
+
+ if (!tb[NL80211_ATTR_STA_INFO]) {
+ wpa_printf(MSG_ERROR,"NL80211_ATTR_STA_INFO not found");
+ return -1;
+ }
+
+ sinfo_data = nla_data(tb[NL80211_ATTR_STA_INFO]);
+ sinfo_len = nla_len(tb[NL80211_ATTR_STA_INFO]);
+
+ if (nla_parse(tb_sinfo, NL80211_STA_INFO_MAX, sinfo_data, sinfo_len,
+ NULL)) {
+ wpa_printf(MSG_ERROR,"NL80211_ATTR_STA_INFO parse error");
+ return -1;
+ }
+
+ /* No need to read for summary */
+ if (g_sta_info.num_sta == 1) {
+ if (tb[NL80211_ATTR_IE])
+ parse_assoc_req_ies(nla_data(tb[NL80211_ATTR_IE]),
+ nla_len(tb[NL80211_ATTR_IE]));
+
+ attr = tb_sinfo[NL80211_STA_INFO_TX_BITRATE];
+ if (attr) {
+ nla_parse(tb_rate, NL80211_RATE_INFO_MAX,
+ nla_data(attr), nla_len(attr), NULL);
+
+ if (tb_rate[NL80211_RATE_INFO_BITRATE32]) {
+ g_sta_info.tx_rate =
+ nla_get_u32(tb_rate[NL80211_RATE_INFO_BITRATE32]);
+ wpa_printf(MSG_INFO,"tx_rate %d", g_sta_info.tx_rate);
+ }
+
+ if (tb_rate[NL80211_RATE_INFO_160_MHZ_WIDTH])
+ g_sta_info.bandwidth = QCA_VENDOR_WLAN_CHAN_WIDTH_160;
+ else if (tb_rate[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
+ g_sta_info.bandwidth = QCA_VENDOR_WLAN_CHAN_WIDTH_80_80;
+ else if (tb_rate[NL80211_RATE_INFO_80_MHZ_WIDTH])
+ g_sta_info.bandwidth = QCA_VENDOR_WLAN_CHAN_WIDTH_80;
+ else if (tb_rate[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ g_sta_info.bandwidth = QCA_VENDOR_WLAN_CHAN_WIDTH_40;
+ else
+ g_sta_info.bandwidth = QCA_VENDOR_WLAN_CHAN_WIDTH_20;
+ wpa_printf(MSG_INFO,"bandwidth %d", g_sta_info.bandwidth);
+ }
+
+ attr = tb_sinfo[NL80211_STA_INFO_RX_BITRATE];
+ if (attr) {
+ nla_parse(tb_rate, NL80211_RATE_INFO_MAX,
+ nla_data(attr), nla_len(attr), NULL);
+ if (tb_rate[NL80211_RATE_INFO_BITRATE32]) {
+ g_sta_info.data_rate =
+ nla_get_u32(tb_rate[NL80211_RATE_INFO_BITRATE32]);
+ wpa_printf(MSG_INFO,"data_rate %d", g_sta_info.data_rate);
+ }
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_SIGNAL_AVG]) {
+ g_sta_info.rssi =
+ nla_get_u8(tb_sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
+ g_sta_info.rssi -= NOISE_FLOOR_DBM;
+ wpa_printf(MSG_INFO,"rssi %d", g_sta_info.rssi);
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_SIGNAL]) {
+ g_sta_info.rx_lastpkt_rssi =
+ nla_get_u8(tb_sinfo[NL80211_STA_INFO_SIGNAL]);
+ g_sta_info.rx_lastpkt_rssi -= NOISE_FLOOR_DBM;
+ wpa_printf(MSG_INFO,"rx_lastpkt_rssi %d", g_sta_info.rx_lastpkt_rssi);
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]) {
+ nla_for_each_nested(attr,
+ tb_sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG],
+ tmp) {
+ if (num_chain >= WMI_MAX_CHAINS) {
+ wpa_printf(MSG_ERROR,"WMI_MAX_CHAINS reached");
+ break;
+ }
+ g_sta_info.avg_rssi_per_chain[num_chain] = nla_get_u8(attr);
+ g_sta_info.avg_rssi_per_chain[num_chain] -= NOISE_FLOOR_DBM;
+ wpa_printf(MSG_INFO,"avg_rssi_per_chain[%d] %d", num_chain,
+ g_sta_info.avg_rssi_per_chain[num_chain]);
+ num_chain++;
+ }
+ }
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_TX_PACKETS]) {
+ g_sta_info.tx_pkts_total +=
+ nla_get_u32(tb_sinfo[NL80211_STA_INFO_TX_PACKETS]);
+ g_sta_info.tx_pckts +=
+ nla_get_u32(tb_sinfo[NL80211_STA_INFO_TX_PACKETS]);
+ wpa_printf(MSG_INFO,"tx_pkts_total %d", g_sta_info.tx_pkts_total);
+ wpa_printf(MSG_INFO,"tx_pckts %d", g_sta_info.tx_pckts);
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_TX_FAILED]) {
+ g_sta_info.tx_failures +=
+ nla_get_u32(tb_sinfo[NL80211_STA_INFO_TX_FAILED]);
+ wpa_printf(MSG_INFO,"tx_failures %d", g_sta_info.tx_failures);
+ }
+
+ if (tb_sinfo[NL80211_STA_INFO_TX_RETRIES]) {
+ g_sta_info.tx_pkts_retries +=
+ nla_get_u32(tb_sinfo[NL80211_STA_INFO_TX_RETRIES]);
+ wpa_printf(MSG_INFO,"tx_pkts_retries %d", g_sta_info.tx_pkts_retries);
+ }
+
+
+ g_sta_info.num_received_nl80211_sta_info++;
+
+ wpa_printf(MSG_INFO,"num_received_nl80211_sta_info %d",
+ g_sta_info.num_received_nl80211_sta_info);
+
+ return 0;
+}
+
+static int wpa_driver_send_get_station_cmd(struct i802_bss *bss, u8 *mac,
+ int *status)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *nlmsg;
+ struct resp_info info;
+
+ memset(&info, 0, sizeof(info));
+ os_memcpy(&info.mac_addr[0], mac, MAC_ADDR_LEN);
+ os_memcpy(&g_sta_info.mac_addr[0], mac, MAC_ADDR_LEN);
+
+ nlmsg = prepare_nlmsg(drv, bss->ifname, NL80211_CMD_GET_STATION, 0, 0);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR,"Failed to allocate nl message");
+ return -1;
+ }
+
+ if (nla_put(nlmsg, NL80211_ATTR_MAC, MAC_ADDR_LEN, mac)) {
+ wpa_printf(MSG_ERROR,"Failed to put NL80211_ATTR_MAC");
+ nlmsg_free(nlmsg);
+ return -1;
+ }
+
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+ get_station_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);
+ g_sta_info.num_request_nl80211_sta_info++;
+ wpa_printf(MSG_INFO,"num_request_nl80211_sta_info %d",
+ g_sta_info.num_request_nl80211_sta_info);
+
+ return 0;
}
-static int wpa_driver_get_all_sta_info(struct i802_bss *bss, char *buf,
- size_t buf_len, int *status)
+static int wpa_driver_get_sta_info(struct i802_bss *bss, u8 *mac,
+ int *status)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct hostapd_data *hapd = bss->ctx;
+ struct sta_info *iter, *sta = NULL;
+ bool new_cmd;
+ int ret;
+ char buf[MAX_DRV_CMD_SIZE];
+ char *p;
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = wpa_driver_send_get_sta_info_cmd(bss, mac, status, &new_cmd);
+ if (ret < 0)
+ return ret;
+
+ if (new_cmd) {
+ ret = wpa_driver_send_get_station_cmd(bss, mac, status);
+ if (ret < 0)
+ return ret;
+
+ /* No need to read for summary */
+ if (g_sta_info.num_sta == 1) {
+ if (!hapd) {
+ wpa_printf(MSG_ERROR,"hapd is NULL");
+ return -1;
+ }
+ iter = hapd->sta_list;
+ while (iter) {
+ if (os_memcmp(mac, iter->addr, MAC_ADDR_LEN) == 0) {
+ sta = iter;
+ break;
+ }
+ iter = iter->next;
+ }
+ if (!sta) {
+ wpa_printf(MSG_ERROR,"STA is not found");
+ return -1;
+ }
+
+ g_sta_info.cap = sta->capability;
+ wpa_printf(MSG_INFO,"cap %04x", g_sta_info.cap);
+ g_sta_info.freq = (u32)hapd->iface->freq;
+ wpa_printf(MSG_INFO,"freq %d", g_sta_info.freq);
+
+ if (g_sta_info.flags.he_supported) {
+ g_sta_info.dot11_mode = QCA_VENDOR_WLAN_802_11_MODE_AX;
+ g_sta_info.supported_mode = QCA_VENDOR_WLAN_PHY_MODE_HE;
+ } else if (g_sta_info.flags.vht_supported) {
+ g_sta_info.dot11_mode = QCA_VENDOR_WLAN_802_11_MODE_AC;
+ g_sta_info.supported_mode = QCA_VENDOR_WLAN_PHY_MODE_VHT;
+ } else if (g_sta_info.flags.ht_supported) {
+ g_sta_info.dot11_mode = QCA_VENDOR_WLAN_802_11_MODE_N;
+ g_sta_info.supported_mode = QCA_VENDOR_WLAN_PHY_MODE_HT;
+ } else {
+ if (g_sta_info.freq < 4900) {
+ if (hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211B)
+ g_sta_info.dot11_mode =
+ QCA_VENDOR_WLAN_802_11_MODE_B;
+ else
+ g_sta_info.dot11_mode =
+ QCA_VENDOR_WLAN_802_11_MODE_G;
+ } else {
+ g_sta_info.dot11_mode = QCA_VENDOR_WLAN_802_11_MODE_A;
+ }
+ g_sta_info.supported_mode = QCA_VENDOR_WLAN_PHY_MODE_LEGACY;
+ }
+
+ wpa_printf(MSG_INFO,"dot11_mode %d", g_sta_info.dot11_mode);
+ wpa_printf(MSG_INFO,"supported_mode %d", g_sta_info.supported_mode);
+ }
+ }
+
+ if(wpa_driver_ioctl(bss, "GETCOUNTRYREV", buf, sizeof(buf), &status, drv) == 0){
+ p = strstr(buf, " ");
+ if(p != NULL)
+ memcpy(g_sta_info.country, (p+1), strlen(p+1)+1);//length of p including null
+ }else{
+ }
+
+ wpa_printf(MSG_INFO,"STA information completed");
+
+ return 0;
+}
+
+static int wpa_driver_get_all_sta_info(struct i802_bss *bss, int *status)
{
struct hostapd_data *hapd = bss->ctx;
struct sta_info *sta;
@@ -1233,19 +1746,15 @@ static int wpa_driver_get_all_sta_info(struct i802_bss *bss, char *buf,
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;
+ ret = wpa_driver_get_sta_info(bss, sta->addr, status);
+ if (ret < 0)
return ret;
- }
- g_sta_info.num_request_sta_info++;
sta = sta->next;
total_ret += ret;
}
+ wpa_printf(MSG_INFO,"All STAs information completed");
+
return total_ret;
}
@@ -1254,6 +1763,7 @@ static int wpa_driver_handle_get_sta_info(struct i802_bss *bss, char *cmd,
int *status)
{
u8 mac[MAC_ADDR_LEN];
+ int ret;
os_memset(&g_sta_info, 0, sizeof(g_sta_info));
@@ -1261,11 +1771,29 @@ static int wpa_driver_handle_get_sta_info(struct i802_bss *bss, char *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);
+ ret = wpa_driver_get_sta_info(bss, mac, status);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = wpa_driver_get_all_sta_info(bss, status);
+ if (ret < 0)
+ return ret;
}
- return wpa_driver_get_all_sta_info(bss, buf, buf_len, status);
+ if (ret == 0) {
+ ret = fill_sta_info(&g_sta_info, buf, buf_len);
+ wpa_printf(MSG_INFO,"%s", buf);
+ } else {
+ wpa_printf(MSG_ERROR,"Failed to get STA info, num_sta %d vendor_sent %d vendor_recv %d nl80211_send %d nl80211 recv %d",
+ g_sta_info.num_sta,
+ g_sta_info.num_request_vendor_sta_info,
+ g_sta_info.num_received_vendor_sta_info,
+ g_sta_info.num_request_nl80211_sta_info,
+ g_sta_info.num_received_nl80211_sta_info);
+ wpa_printf(MSG_ERROR,"GETSTAINFO failed");
+ }
+
+ return ret;
}
static int thermal_info_handler(struct nl_msg *msg, void *arg)
@@ -1378,6 +1906,8 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
if (!ret)
ret = os_snprintf(buf, buf_len,
"Macaddr = " MACSTR "\n", MAC2STR(macaddr));
+ } else if (os_strncasecmp(cmd, "SET_CONGESTION_REPORT ", 22) == 0) {
+ return wpa_driver_cmd_set_congestion_report(priv, cmd + 22);
} 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) {
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 6249d14..572bf81 100644
--- a/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
+++ b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
@@ -34,6 +34,7 @@
#define OUI_LEN 3
#define MAX_CMD_LEN 32
#define MAC_ADDR_LEN 6
+#define COUNTRY_LEN 4
#define IEEE80211_HE_OPERATION_VHT_OPER_MASK 0x00004000
#define IEEE80211_HE_OPERATION_CO_LOC_BSS_MASK 0x00008000
@@ -52,6 +53,53 @@
#define CHANNEL_BW_INVALID 255
+/* Define short names */
+#define GET_STATION_INFO_AKM \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
+#define GET_STATION_INFO_HT_OPERATION \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
+#define GET_STATION_INFO_VHT_OPERATION \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
+#define GET_STATION_INFO_REMOTE_LAST_RX_RATE \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
+#define GET_STATION_INFO_REMOTE_SUPPORTED_MODE \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
+#define GET_STATION_INFO_REMOTE_CH_WIDTH \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
+#define GET_STATION_INFO_REMOTE_RX_RETRY_COUNT \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT
+#define GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT
+#define GET_STATION_INFO_BEACON_IES \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES
+#define GET_STATION_INFO_DRIVER_DISCONNECT_REASON \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON
+#define GET_STATION_INFO_ASSOC_REQ_IES \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES
+#define GET_STATION_INFO_HE_OPERATION \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION
+#define GET_STATION_INFO_MAX \
+ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX
+
+#define GET_STA_INFO_MAC \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC
+#define GET_STA_INFO_RX_RETRY_COUNT \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT
+#define GET_STA_INFO_RX_BC_MC_COUNT \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT
+#define GET_STA_INFO_TX_RETRY_SUCCEED \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED
+#define GET_STA_INFO_TX_RETRY_EXHAUSTED \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED
+#define GET_STA_INFO_TARGET_TX_TOTAL \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL
+#define GET_STA_INFO_TARGET_TX_RETRY \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY
+#define GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED
+#define GET_STA_INFO_MAX \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX
+
struct bss_info {
uint8_t oui[OUI_LEN];
char ssid[MAX_SSID_LEN + 1];
@@ -86,7 +134,7 @@ struct resp_info {
enum get_info_cmd cmd_type;
uint8_t mac_addr[MAC_ADDR_LEN];
u32 freq;
- uint8_t country[4];
+ uint8_t country[COUNTRY_LEN];
};
#define QCA_NL80211_VENDOR_SUBCMD_GET_STATION 121
@@ -219,10 +267,43 @@ enum qca_wlan_vendor_attr_get_station_info {
#define WMI_MAX_CHAINS (3)
+enum qca_vendor_wlan_chan_width {
+ QCA_VENDOR_WLAN_CHAN_WIDTH_20 = 0,
+ QCA_VENDOR_WLAN_CHAN_WIDTH_40 = 1,
+ QCA_VENDOR_WLAN_CHAN_WIDTH_80 = 2,
+ QCA_VENDOR_WLAN_CHAN_WIDTH_80_80 = 3,
+ QCA_VENDOR_WLAN_CHAN_WIDTH_160 = 4,
+};
+
+enum qca_vendor_wlan_802_11_mode {
+ QCA_VENDOR_WLAN_802_11_MODE_B = 0,
+ QCA_VENDOR_WLAN_802_11_MODE_G = 1,
+ QCA_VENDOR_WLAN_802_11_MODE_N = 2,
+ QCA_VENDOR_WLAN_802_11_MODE_A = 3,
+ QCA_VENDOR_WLAN_802_11_MODE_AC = 4,
+ QCA_VENDOR_WLAN_802_11_MODE_AX = 5,
+};
+
+enum qca_vendor_wlan_phy_mode {
+ QCA_VENDOR_WLAN_PHY_MODE_LEGACY = 0,
+ QCA_VENDOR_WLAN_PHY_MODE_HT = 1,
+ QCA_VENDOR_WLAN_PHY_MODE_VHT = 2,
+ QCA_VENDOR_WLAN_PHY_MODE_HE = 3,
+};
+
+struct assoc_req_ie_flags {
+ u8 ht_supported:1;
+ u8 vht_supported:1;
+ u8 he_supported:1;
+};
+
struct remote_sta_info {
u8 num_sta;
- u8 num_request_sta_info;
- u8 num_received_sta_info;
+ u8 num_request_vendor_sta_info;
+ u8 num_received_vendor_sta_info;
+ u8 num_request_nl80211_sta_info;
+ u8 num_received_nl80211_sta_info;
+ u8 mac_addr[MAC_ADDR_LEN];
u32 rx_retry_pkts;
u32 rx_bcmc_pkts;
u16 cap;
@@ -249,6 +330,9 @@ struct remote_sta_info {
* received, starting from the Length field */
u8 *supp_channels;
u32 supported_band;
+ bool show_band;
+ struct assoc_req_ie_flags flags;
+ uint8_t country[COUNTRY_LEN];
};
#endif