Snap for 10453563 from 17fad3051142f31d3814b20ca9bf43459b762c2a to mainline-os-statsd-release
Change-Id: I9c6468bfd5346c5bd5cfa8c09da968e76f02c368
diff --git a/Android.mk b/Android.mk
index cb1010a..bba4a38 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,8 @@
#set TARGET_USES_HARDWARE_QCOM_WLAN to false to disable this project.
ifneq ($(TARGET_USES_HARDWARE_QCOM_WLAN),false)
-include $(call all-subdir-makefiles)
+ ifneq ($(filter wcn6740,$(BOARD_WLAN_CHIP)),)
+ include $(call all-named-subdir-makefiles,wcn6740)
+ else
+ include $(call all-named-subdir-makefiles,legacy)
+ endif
endif
diff --git a/OWNERS b/OWNERS
index d8c95cc..4ab11f8 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,5 @@
arabawy@google.com
etancohen@google.com
kumachang@google.com
+hsuvictor@google.com
+wangroger@google.com
diff --git a/legacy/Android.mk b/legacy/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/legacy/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/cld80211-lib/Android.mk b/legacy/cld80211-lib/Android.mk
similarity index 100%
rename from cld80211-lib/Android.mk
rename to legacy/cld80211-lib/Android.mk
diff --git a/cld80211-lib/cld80211_lib.c b/legacy/cld80211-lib/cld80211_lib.c
similarity index 99%
rename from cld80211-lib/cld80211_lib.c
rename to legacy/cld80211-lib/cld80211_lib.c
index 5c8255b..b34ed28 100644
--- a/cld80211-lib/cld80211_lib.c
+++ b/legacy/cld80211-lib/cld80211_lib.c
@@ -446,7 +446,7 @@
}
-struct cld80211_ctx * cld80211_init()
+struct cld80211_ctx * cld80211_init(void)
{
struct cld80211_ctx *ctx;
diff --git a/cld80211-lib/cld80211_lib.h b/legacy/cld80211-lib/cld80211_lib.h
similarity index 93%
rename from cld80211-lib/cld80211_lib.h
rename to legacy/cld80211-lib/cld80211_lib.h
index 3dd53bb..2503f2a 100644
--- a/cld80211-lib/cld80211_lib.h
+++ b/legacy/cld80211-lib/cld80211_lib.h
@@ -58,6 +58,10 @@
* CLD80211_ATTR_META_DATA: Embed meta data for above data. This will help
* wlan driver to peek into request message packet without opening up definition
* of complete request message.
+ * @CLD80211_ATTR_CMD: cld80211 vendor subcommand in this attribute
+ * @CLD80211_ATTR_CMD_TAG_DATA: cld80211 vendor subcommand data is present in
+ * this attribute. It is a nested attribute with sub attributes of specified
+ * vendor sub command.
*
* Any new message in future can be added as another attribute
*/
@@ -65,6 +69,8 @@
CLD80211_ATTR_VENDOR_DATA = 1,
CLD80211_ATTR_DATA,
CLD80211_ATTR_META_DATA,
+ CLD80211_ATTR_CMD,
+ CLD80211_ATTR_CMD_TAG_DATA,
__CLD80211_ATTR_AFTER_LAST,
CLD80211_ATTR_MAX = __CLD80211_ATTR_AFTER_LAST - 1
@@ -75,7 +81,7 @@
* Retuns valid sock only if socket creation is succesful and cld80211
* family is present, returns NULL otherwise
*/
-struct cld80211_ctx *cld80211_init();
+struct cld80211_ctx *cld80211_init(void);
/**
* free the socket created in cld80211_init()
diff --git a/qcwcn/Android.mk b/legacy/qcwcn/Android.mk
similarity index 100%
rename from qcwcn/Android.mk
rename to legacy/qcwcn/Android.mk
diff --git a/qcwcn/config/Android.mk b/legacy/qcwcn/config/Android.mk
similarity index 100%
rename from qcwcn/config/Android.mk
rename to legacy/qcwcn/config/Android.mk
diff --git a/qcwcn/wcnss-service/Android.mk b/legacy/qcwcn/wcnss-service/Android.mk
similarity index 100%
rename from qcwcn/wcnss-service/Android.mk
rename to legacy/qcwcn/wcnss-service/Android.mk
diff --git a/qcwcn/wcnss-service/wcnss_qmi_client.c b/legacy/qcwcn/wcnss-service/wcnss_qmi_client.c
similarity index 100%
rename from qcwcn/wcnss-service/wcnss_qmi_client.c
rename to legacy/qcwcn/wcnss-service/wcnss_qmi_client.c
diff --git a/qcwcn/wcnss-service/wcnss_qmi_client.h b/legacy/qcwcn/wcnss-service/wcnss_qmi_client.h
similarity index 100%
rename from qcwcn/wcnss-service/wcnss_qmi_client.h
rename to legacy/qcwcn/wcnss-service/wcnss_qmi_client.h
diff --git a/qcwcn/wcnss-service/wcnss_service.c b/legacy/qcwcn/wcnss-service/wcnss_service.c
similarity index 100%
rename from qcwcn/wcnss-service/wcnss_service.c
rename to legacy/qcwcn/wcnss-service/wcnss_service.c
diff --git a/qcwcn/wifi_hal/Android.mk b/legacy/qcwcn/wifi_hal/Android.mk
similarity index 100%
rename from qcwcn/wifi_hal/Android.mk
rename to legacy/qcwcn/wifi_hal/Android.mk
diff --git a/qcwcn/wifi_hal/common.cpp b/legacy/qcwcn/wifi_hal/common.cpp
similarity index 100%
rename from qcwcn/wifi_hal/common.cpp
rename to legacy/qcwcn/wifi_hal/common.cpp
diff --git a/qcwcn/wifi_hal/common.h b/legacy/qcwcn/wifi_hal/common.h
similarity index 99%
rename from qcwcn/wifi_hal/common.h
rename to legacy/qcwcn/wifi_hal/common.h
index b0aca97..401921b 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/legacy/qcwcn/wifi_hal/common.h
@@ -174,6 +174,7 @@
wifi_capa capa;
struct cld80211_ctx *cldctx;
bool apf_enabled;
+ bool support_nan_ext_cmd;
pkt_log_version pkt_log_ver;
} hal_info;
diff --git a/qcwcn/wifi_hal/cpp_bindings.cpp b/legacy/qcwcn/wifi_hal/cpp_bindings.cpp
similarity index 100%
rename from qcwcn/wifi_hal/cpp_bindings.cpp
rename to legacy/qcwcn/wifi_hal/cpp_bindings.cpp
diff --git a/qcwcn/wifi_hal/cpp_bindings.h b/legacy/qcwcn/wifi_hal/cpp_bindings.h
similarity index 100%
rename from qcwcn/wifi_hal/cpp_bindings.h
rename to legacy/qcwcn/wifi_hal/cpp_bindings.h
diff --git a/qcwcn/wifi_hal/gscan.cpp b/legacy/qcwcn/wifi_hal/gscan.cpp
similarity index 100%
rename from qcwcn/wifi_hal/gscan.cpp
rename to legacy/qcwcn/wifi_hal/gscan.cpp
diff --git a/qcwcn/wifi_hal/gscan_event_handler.cpp b/legacy/qcwcn/wifi_hal/gscan_event_handler.cpp
similarity index 100%
rename from qcwcn/wifi_hal/gscan_event_handler.cpp
rename to legacy/qcwcn/wifi_hal/gscan_event_handler.cpp
diff --git a/qcwcn/wifi_hal/gscan_event_handler.h b/legacy/qcwcn/wifi_hal/gscan_event_handler.h
similarity index 100%
rename from qcwcn/wifi_hal/gscan_event_handler.h
rename to legacy/qcwcn/wifi_hal/gscan_event_handler.h
diff --git a/qcwcn/wifi_hal/gscancommand.h b/legacy/qcwcn/wifi_hal/gscancommand.h
similarity index 100%
rename from qcwcn/wifi_hal/gscancommand.h
rename to legacy/qcwcn/wifi_hal/gscancommand.h
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.cpp b/legacy/qcwcn/wifi_hal/ifaceeventhandler.cpp
similarity index 85%
rename from qcwcn/wifi_hal/ifaceeventhandler.cpp
rename to legacy/qcwcn/wifi_hal/ifaceeventhandler.cpp
index 6e70ab5..82f1add 100644
--- a/qcwcn/wifi_hal/ifaceeventhandler.cpp
+++ b/legacy/qcwcn/wifi_hal/ifaceeventhandler.cpp
@@ -205,6 +205,8 @@
mCapa = &(info->capa);
mfilter_packet_read_buffer = NULL;
mfilter_packet_length = 0;
+ res_size = 0;
+ channel_buff = NULL;
memset(&mDriverFeatures, 0, sizeof(mDriverFeatures));
}
@@ -222,6 +224,119 @@
return WifiCommand::requestResponse(mMsg);
}
+static u32 get_wifi_iftype_masks(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & BIT(NL80211_IFTYPE_STATION)) {
+ op_mask |= BIT(WIFI_INTERFACE_STA);
+ op_mask |= BIT(WIFI_INTERFACE_TDLS);
+ }
+ if (in_mask & BIT(NL80211_IFTYPE_AP))
+ op_mask |= BIT(WIFI_INTERFACE_SOFTAP);
+ if (in_mask & BIT(NL80211_IFTYPE_P2P_CLIENT))
+ op_mask |= BIT(WIFI_INTERFACE_P2P_CLIENT);
+ if (in_mask & BIT(NL80211_IFTYPE_P2P_GO))
+ op_mask |= BIT(WIFI_INTERFACE_P2P_GO);
+ if (in_mask & BIT(NL80211_IFTYPE_NAN))
+ op_mask |= BIT(WIFI_INTERFACE_NAN);
+
+ return op_mask;
+}
+
+static wifi_channel_width get_channel_width(u32 nl_width)
+{
+ switch(nl_width) {
+ case NL80211_CHAN_WIDTH_20:
+ return WIFI_CHAN_WIDTH_20;
+ case NL80211_CHAN_WIDTH_40:
+ return WIFI_CHAN_WIDTH_40;
+ case NL80211_CHAN_WIDTH_80:
+ return WIFI_CHAN_WIDTH_80;
+ case NL80211_CHAN_WIDTH_160:
+ return WIFI_CHAN_WIDTH_160;
+ case NL80211_CHAN_WIDTH_80P80:
+ return WIFI_CHAN_WIDTH_80P80;
+ case NL80211_CHAN_WIDTH_5:
+ return WIFI_CHAN_WIDTH_5;
+ case NL80211_CHAN_WIDTH_10:
+ return WIFI_CHAN_WIDTH_10;
+ default:
+ return WIFI_CHAN_WIDTH_INVALID;
+ }
+}
+
+int WifihalGeneric::handle_response_usable_channels(struct nlattr *VendorData,
+ u32 mDataLen)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
+ struct nlattr *curr_attr;
+ wifi_usable_channel *chan_info = NULL;
+ int rem;
+ u32 currSize = 0;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL)) {
+ ALOGE("Failed to parse NL channels list");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO]) {
+ ALOGE("%s: USABLE_CHANNELS_CHAN_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ for_each_nested_attribute(curr_attr,
+ tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO], rem) {
+ struct nlattr *ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1];
+
+ if (currSize >= mSetSizeMax) {
+ ALOGE("Got max channels %d completed", mSetSizeMax);
+ break;
+ }
+
+ if (nla_parse_nested(ch_info, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX,
+ curr_attr, NULL)) {
+ ALOGE("Failed to get usable channel info");
+ return NL_SKIP;
+ }
+
+ chan_info = &channel_buff[currSize];
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]) {
+ ALOGE("%s: CHAN_INFO_PRIMARY_FREQ not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->freq = nla_get_u32(ch_info[
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]);
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]) {
+ ALOGE("%s: CHAN_INFO_BANDWIDTH not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->width = get_channel_width(nla_get_u32(
+ ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]));
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]) {
+ ALOGE("%s: CHAN_INFO_IFACE_MODE_MASK not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->iface_mode_mask = get_wifi_iftype_masks(nla_get_u32(
+ ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]));
+ ALOGV("Primary freq %d BW %d iface mask %d", chan_info->freq,
+ chan_info->width, chan_info->iface_mode_mask);
+ currSize++;
+ }
+
+ res_size = currSize;
+ ALOGV("%s: Result size %d", __FUNCTION__, res_size);
+
+ return NL_SKIP;
+}
+
int WifihalGeneric::handleResponse(WifiEvent &reply)
{
ALOGV("Got a Wi-Fi HAL module message from Driver");
@@ -436,6 +551,9 @@
}
}
break;
+ case QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS:
+ return handle_response_usable_channels((struct nlattr *)mVendorData,
+ mDataLen);
default :
ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
}
@@ -612,6 +730,17 @@
return firmware_bus_max_size;
}
+void WifihalGeneric::set_channels_buff(wifi_usable_channel* channels)
+{
+ channel_buff = channels;
+ memset(channel_buff, 0, sizeof(wifi_usable_channel) * mSetSizeMax);
+}
+
+u32 WifihalGeneric::get_results_size(void)
+{
+ return res_size;
+}
+
wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
{
wifi_error ret;
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.h b/legacy/qcwcn/wifi_hal/ifaceeventhandler.h
similarity index 86%
rename from qcwcn/wifi_hal/ifaceeventhandler.h
rename to legacy/qcwcn/wifi_hal/ifaceeventhandler.h
index c993a7e..d055a1b 100644
--- a/qcwcn/wifi_hal/ifaceeventhandler.h
+++ b/legacy/qcwcn/wifi_hal/ifaceeventhandler.h
@@ -94,6 +94,8 @@
/* Packet Filter buffer and length */
u8 *mfilter_packet_read_buffer;
int mfilter_packet_length;
+ u32 res_size;
+ wifi_usable_channel *channel_buff;
virtual wifi_error wifiParseCapabilities(struct nlattr **tbVendor);
public:
@@ -101,6 +103,8 @@
virtual ~WifihalGeneric();
virtual wifi_error requestResponse();
virtual int handleResponse(WifiEvent &reply);
+ virtual int handle_response_usable_channels(struct nlattr *VendorData,
+ u32 mDataLen);
virtual void getResponseparams(feature_set *pset);
virtual void getDriverFeatures(features_info *pfeatures);
virtual void setMaxSetSize(int set_size_max);
@@ -111,7 +115,19 @@
virtual int getFilterLength();
virtual int getBusSize();
virtual wifi_error wifiGetCapabilities(wifi_interface_handle handle);
+ virtual void set_channels_buff(wifi_usable_channel *channels);
+ virtual u32 get_results_size(void);
};
+
+/**
+ * nla_for_each_nested from libnl is throwing implicit conversion from void*
+ * error. Adding a local definition to avoid it.
+ */
+#define for_each_nested_attribute(pos, nla, rem) \
+ for (pos = (struct nlattr *)nla_data(nla), rem = nla_len(nla); \
+ nla_ok(pos, rem); \
+ pos = nla_next(pos, &(rem)))
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/qcwcn/wifi_hal/list.cpp b/legacy/qcwcn/wifi_hal/list.cpp
similarity index 100%
rename from qcwcn/wifi_hal/list.cpp
rename to legacy/qcwcn/wifi_hal/list.cpp
diff --git a/qcwcn/wifi_hal/list.h b/legacy/qcwcn/wifi_hal/list.h
similarity index 100%
rename from qcwcn/wifi_hal/list.h
rename to legacy/qcwcn/wifi_hal/list.h
diff --git a/qcwcn/wifi_hal/llstats.cpp b/legacy/qcwcn/wifi_hal/llstats.cpp
similarity index 100%
rename from qcwcn/wifi_hal/llstats.cpp
rename to legacy/qcwcn/wifi_hal/llstats.cpp
diff --git a/qcwcn/wifi_hal/llstatscommand.h b/legacy/qcwcn/wifi_hal/llstatscommand.h
similarity index 100%
rename from qcwcn/wifi_hal/llstatscommand.h
rename to legacy/qcwcn/wifi_hal/llstatscommand.h
diff --git a/qcwcn/wifi_hal/nan.cpp b/legacy/qcwcn/wifi_hal/nan.cpp
similarity index 90%
rename from qcwcn/wifi_hal/nan.cpp
rename to legacy/qcwcn/wifi_hal/nan.cpp
index ac378fa..9e74cea 100644
--- a/qcwcn/wifi_hal/nan.cpp
+++ b/legacy/qcwcn/wifi_hal/nan.cpp
@@ -73,10 +73,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -115,10 +123,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -158,10 +174,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -201,10 +225,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -244,10 +276,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -287,10 +327,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -330,10 +378,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -373,10 +429,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -416,10 +480,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -459,10 +531,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -505,10 +585,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -571,10 +659,18 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -615,6 +711,12 @@
NanCommand *nanCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(iface);
wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
if (debug_msg_length <= 0) {
ALOGE("%s: Invalid debug message length = %d", __FUNCTION__,
@@ -625,6 +727,8 @@
nanCommand = new NanCommand(wifiHandle,
0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
if (nanCommand == NULL) {
ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
@@ -795,7 +899,7 @@
{
ALOGV("NAN_DP_REQUEST_INITIATOR");
wifi_error ret;
- struct nlattr *nlData, *nlCfgSecurity, *nlCfgQos;
+ struct nlattr *nlData, *nlCfgQos;
NanCommand *nanCommand = NULL;
if (msg == NULL)
@@ -866,19 +970,6 @@
goto cleanup;
}
}
- if (msg->ndp_cfg.security_cfg == NAN_DP_CONFIG_SECURITY) {
- nlCfgSecurity =
- nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY);
- if (!nlCfgSecurity)
- goto cleanup;
-
- if (nanCommand->put_u32(
- QCA_WLAN_VENDOR_ATTR_NDP_SECURITY_TYPE,
- 0)) {
- goto cleanup;
- }
- nanCommand->attr_end(nlCfgSecurity);
- }
if (msg->ndp_cfg.qos_cfg == NAN_DP_CONFIG_QOS) {
nlCfgQos =
nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS);
@@ -930,7 +1021,7 @@
{
ALOGV("NAN_DP_INDICATION_RESPONSE");
wifi_error ret;
- struct nlattr *nlData, *nlCfgSecurity, *nlCfgQos;
+ struct nlattr *nlData, *nlCfgQos;
NanCommand *nanCommand = NULL;
if (msg == NULL)
@@ -981,19 +1072,6 @@
goto cleanup;
}
}
- if (msg->ndp_cfg.security_cfg == NAN_DP_CONFIG_SECURITY) {
- nlCfgSecurity =
- nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY);
- if (!nlCfgSecurity)
- goto cleanup;
- /* Setting value to 0 for now */
- if (nanCommand->put_u32(
- QCA_WLAN_VENDOR_ATTR_NDP_SECURITY_TYPE,
- 0)) {
- goto cleanup;
- }
- nanCommand->attr_end(nlCfgSecurity);
- }
if (msg->ndp_cfg.qos_cfg == NAN_DP_CONFIG_QOS) {
nlCfgQos =
nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS);
@@ -1102,13 +1180,23 @@
NanCommand* NanCommand::instance(wifi_handle handle)
{
+ hal_info *info;
+
if (handle == NULL) {
ALOGE("Handle is invalid");
return NULL;
}
+ info = getHalInfo(handle);
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return NULL;
+ }
+
if (mNanCommandInstance == NULL) {
mNanCommandInstance = new NanCommand(handle, 0,
OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
QCA_NL80211_VENDOR_SUBCMD_NAN);
ALOGV("NanCommand %p created", mNanCommandInstance);
return mNanCommandInstance;
diff --git a/qcwcn/wifi_hal/nan_cert.h b/legacy/qcwcn/wifi_hal/nan_cert.h
similarity index 100%
rename from qcwcn/wifi_hal/nan_cert.h
rename to legacy/qcwcn/wifi_hal/nan_cert.h
diff --git a/qcwcn/wifi_hal/nan_i.h b/legacy/qcwcn/wifi_hal/nan_i.h
similarity index 100%
rename from qcwcn/wifi_hal/nan_i.h
rename to legacy/qcwcn/wifi_hal/nan_i.h
diff --git a/qcwcn/wifi_hal/nan_ind.cpp b/legacy/qcwcn/wifi_hal/nan_ind.cpp
similarity index 100%
rename from qcwcn/wifi_hal/nan_ind.cpp
rename to legacy/qcwcn/wifi_hal/nan_ind.cpp
diff --git a/qcwcn/wifi_hal/nan_req.cpp b/legacy/qcwcn/wifi_hal/nan_req.cpp
similarity index 84%
rename from qcwcn/wifi_hal/nan_req.cpp
rename to legacy/qcwcn/wifi_hal/nan_req.cpp
index fd8516f..f411802 100644
--- a/qcwcn/wifi_hal/nan_req.cpp
+++ b/legacy/qcwcn/wifi_hal/nan_req.cpp
@@ -25,12 +25,18 @@
wifi_error ret;
ALOGV("NAN_ENABLE");
size_t message_len = NAN_MAX_ENABLE_REQ_SIZE;
+ int freq_24g;
if (pReq == NULL) {
cleanup();
return WIFI_ERROR_INVALID_ARGS;
}
+ if (pReq->config_24g_channel == 0)
+ freq_24g = 2437;
+ else
+ freq_24g = pReq->channel_24g_val;
+
message_len += \
(
pReq->config_support_5g ? (SIZEOF_TLV_HDR + \
@@ -117,8 +123,8 @@
sizeof(pReq->hop_count_force_val)) : 0 \
) + \
(
- pReq->config_24g_channel ? (SIZEOF_TLV_HDR + \
- sizeof(u32)) : 0 \
+ /* always include 24g channel/freq */
+ SIZEOF_TLV_HDR + sizeof(u32) \
) + \
(
pReq->config_5g_channel ? (SIZEOF_TLV_HDR + \
@@ -288,11 +294,9 @@
sizeof(pReq->hop_count_force_val),
(const u8*)&pReq->hop_count_force_val, tlvs);
}
- if (pReq->config_24g_channel) {
- tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
+ tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
sizeof(u32),
- (const u8*)&pReq->channel_24g_val, tlvs);
- }
+ (const u8*)&freq_24g, tlvs);
if (pReq->config_5g_channel) {
tlvs = addTlv(NAN_TLV_TYPE_5G_CHANNEL,
sizeof(u32),
@@ -352,12 +356,48 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- //Insert the vendor specific data
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ //Insert the vendor specific data
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ) ||
+ mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ,
+ freq_24g)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (pReq->config_5g_channel) {
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ,
+ pReq->config_5g_channel)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -385,11 +425,32 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ) ||
+ mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -645,11 +706,29 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -709,7 +788,7 @@
if (pReq->publish_id == 0) {
pFwReq->fwHeader.handle = 0xFFFF;
} else {
- pFwReq->fwHeader.handle = pReq->publish_id;
+ pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
}
pFwReq->fwHeader.transactionId = id;
@@ -863,11 +942,29 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -895,17 +992,36 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->publish_id;
+ pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -969,7 +1085,7 @@
if (pReq->subscribe_id == 0) {
pFwReq->fwHeader.handle = 0xFFFF;
} else {
- pFwReq->fwHeader.handle = pReq->subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
}
pFwReq->fwHeader.transactionId = id;
@@ -1123,11 +1239,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1156,16 +1291,35 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1201,7 +1355,7 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->publish_subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->publish_subscribe_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
pFwReq->transmitFollowupReqParams.matchHandle = pReq->requestor_instance_id;
@@ -1235,11 +1389,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1276,11 +1449,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1332,11 +1524,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1399,11 +1610,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1668,11 +1898,30 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1711,12 +1960,31 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- /* Write the TLVs to the message. */
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ /* Write the TLVs to the message. */
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
diff --git a/qcwcn/wifi_hal/nan_rsp.cpp b/legacy/qcwcn/wifi_hal/nan_rsp.cpp
similarity index 100%
rename from qcwcn/wifi_hal/nan_rsp.cpp
rename to legacy/qcwcn/wifi_hal/nan_rsp.cpp
diff --git a/qcwcn/wifi_hal/nancommand.h b/legacy/qcwcn/wifi_hal/nancommand.h
similarity index 100%
rename from qcwcn/wifi_hal/nancommand.h
rename to legacy/qcwcn/wifi_hal/nancommand.h
diff --git a/qcwcn/wifi_hal/pkt_stats.h b/legacy/qcwcn/wifi_hal/pkt_stats.h
similarity index 100%
rename from qcwcn/wifi_hal/pkt_stats.h
rename to legacy/qcwcn/wifi_hal/pkt_stats.h
diff --git a/qcwcn/wifi_hal/qca-vendor_copy.h b/legacy/qcwcn/wifi_hal/qca-vendor_copy.h
similarity index 81%
rename from qcwcn/wifi_hal/qca-vendor_copy.h
rename to legacy/qcwcn/wifi_hal/qca-vendor_copy.h
index 11442ee..24a31a3 100644
--- a/qcwcn/wifi_hal/qca-vendor_copy.h
+++ b/legacy/qcwcn/wifi_hal/qca-vendor_copy.h
@@ -1,10 +1,7 @@
/*
* Qualcomm Atheros OUI and vendor specific assignments
* Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
- * Copyright (c) 2018-2019, The Linux Foundation
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#ifndef QCA_VENDOR_H
@@ -512,7 +509,9 @@
* @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
* configure parameters per peer to capture Channel Frequency Response
* (CFR) and enable Periodic CFR capture. The attributes for this command
- * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command
+ * can also be used to send CFR data from the driver to userspace when
+ * netlink events are used to send CFR data.
*
* @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
* in throughput dynamically. The driver estimates the throughput based on
@@ -620,7 +619,14 @@
* This new command is alternative to existing command
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
* is using stream of bytes instead of structured data using vendor
- * attributes.
+ * attributes. User space sends unsafe frequency ranges to the driver using
+ * a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
+ * reception of this command, the driver shall check if an interface is
+ * operating on an unsafe frequency and the driver shall try to move to a
+ * safe channel when needed. If the driver is not able to find a safe
+ * channel the interface can keep operating on an unsafe channel with the
+ * TX power limit derived based on internal configurations like
+ * regulatory/SAR rules.
*
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
* add the STA node details in driver/firmware. Attributes for this event
@@ -664,36 +670,95 @@
* qca_wlan_vendor_attr_driver_disconnect_reason.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to
- * add/delete TSPEC for each AC. One command is for one specific AC only.
- * This command can only be used in STA mode and the STA must be
- * associated with an AP when the command is issued. Uses attributes
- * defined in enum qca_wlan_vendor_attr_config_tspec.
+ * add/delete TSPEC for each AC. One command is for one specific AC only.
+ * This command can only be used in STA mode and the STA must be
+ * associated with an AP when the command is issued. Uses attributes
+ * defined in enum qca_wlan_vendor_attr_config_tspec.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT.
- * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
*
* @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from
- * the driver. The band configurations obtained are referred through
- * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
+ * the driver. The band configurations obtained are referred through
+ * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
*
* @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium
- * assessment.
- * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
+ * assessment.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
*
* @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is
- * used to update SSID information in hostapd when it is updated in the
- * driver. Uses the attribute NL80211_ATTR_SSID.
+ * used to update SSID information in hostapd when it is updated in the
+ * driver. Uses the attribute NL80211_ATTR_SSID.
*
* @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by
- * the driver to send opaque data from the firmware to userspace. The
- * driver sends an event to userspace whenever such data is received from
- * the firmware.
+ * the driver to send opaque data from the firmware to userspace. The
+ * driver sends an event to userspace whenever such data is received from
+ * the firmware.
*
- * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
- * send this opaque data for this event.
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
+ * send this opaque data for this event.
*
- * The format of the opaque data is specific to the particular firmware
- * version and there is no guarantee of the format remaining same.
+ * The format of the opaque data is specific to the particular firmware
+ * version and there is no guarantee of the format remaining same.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event.
+ * The host driver selects Tx VDEV, and notifies user. The attributes
+ * used with this event are defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_status.
+ * This event contains Tx VDEV group information, other VDEVs
+ * interface index, and status information.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY: Vendor command to
+ * configure the concurrent session policies when multiple STA interfaces
+ * are (getting) active. The attributes used by this command are defined
+ * in enum qca_wlan_vendor_attr_concurrent_sta_policy.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command
+ * to query usable channels for different interface types such as STA,
+ * AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable
+ * channels in the response based on country code, different static
+ * configurations, concurrency combinations, etc. The attributes used
+ * with this command are defined in
+ * enum qca_wlan_vendor_attr_usable_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used
+ * to get DFS radar history from the driver to userspace. The driver
+ * returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an
+ * array of nested entries.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to
+ * enable/disable mDNS offload to the firmware. The attributes used with
+ * this command are defined in enum qca_wlan_vendor_attr_mdns_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used
+ * to set packet monitor mode that aims to send the specified set of TX and
+ * RX frames on the current client interface to an active monitor
+ * interface. If this monitor mode is set, the driver will send the
+ * configured frames, from the interface on which the command is issued, to
+ * an active monitor interface. The attributes used with this command are
+ * defined in enum qca_wlan_vendor_attr_set_monitor_mode.
+ *
+ * Though the monitor mode is configured for the respective
+ * Data/Management/Control frames, it is up to the respective WLAN
+ * driver/firmware/hardware designs to consider the possibility of sending
+ * these frames over the monitor interface. For example, the Control frames
+ * are handled within the hardware and thus passing such frames over the
+ * monitor interface is left to the respective designs.
+ *
+ * Also, this monitor mode is governed to behave accordingly in
+ * suspend/resume states. If the firmware handles any of such frames in
+ * suspend state without waking up the host and if the monitor mode is
+ * configured to notify all such frames, the firmware is expected to resume
+ * the host and forward the respective frames to the monitor interface.
+ * Please note that such a request to get the frames over the monitor
+ * interface will have a definite power implication.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both
+ * as a request to set the driver/firmware with the parameters to trigger
+ * the roaming events, and also used by the driver/firmware to pass on the
+ * various roam events to userspace.
+ * Applicable only for the STA mode. The attributes used with this command
+ * are defined in enum qca_wlan_vendor_attr_roam_events.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -879,6 +944,14 @@
QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193,
QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194,
QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195,
+ QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196,
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199,
+ QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200,
+ /* 201 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203,
};
enum qca_wlan_vendor_attr {
@@ -1117,7 +1190,7 @@
* @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
* or environment being very noisy or congested.
*
- * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
* from the user (user space).
*
* @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
@@ -1125,6 +1198,26 @@
*
* @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
* breaching out the configured threshold.
+ *
+ * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
+ * transition request.
+ *
+ * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no
+ * data activity with the AP and the current RSSI falls below a certain
+ * threshold.
+ *
+ * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or
+ * Disassociation frames received from the connected AP.
+ *
+ * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan
+ * that happens when there is no candidate AP found during the poor RSSI scan
+ * trigger.
+ *
+ * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results
+ * obtained from an external scan (not aimed at roaming).
+ *
+ * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is
+ * established when the station is connected in the 2.4 GHz band.
*/
enum qca_roam_reason {
QCA_ROAM_REASON_UNKNOWN,
@@ -1136,6 +1229,12 @@
QCA_ROAM_REASON_USER_TRIGGER,
QCA_ROAM_REASON_BTM,
QCA_ROAM_REASON_BSS_LOAD,
+ QCA_ROAM_REASON_WTC,
+ QCA_ROAM_REASON_IDLE,
+ QCA_ROAM_REASON_DISCONNECTION,
+ QCA_ROAM_REASON_PERIODIC_TIMER,
+ QCA_ROAM_REASON_BACKGROUND_SCAN,
+ QCA_ROAM_REASON_BT_ACTIVITY,
};
enum qca_wlan_vendor_attr_roam_auth {
@@ -1355,6 +1454,11 @@
* Used with event to notify the EDMG channel number selected in ACS
* operation.
* EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16).
+ * Used with event to notify the puncture pattern selected in ACS operation.
+ * Encoding for this attribute will follow the convention used in the Disabled
+ * Subchannel Bitmap field of the EHT Operation IE.
*/
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1375,6 +1479,7 @@
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
+ QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -1438,6 +1543,25 @@
* %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and
* %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from
* userspace.
+ * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r.
+ * With Adaptive 11r feature, access points advertise the vendor
+ * specific IEs and MDE but do not include FT AKM in the RSNE.
+ * The Adaptive 11r supported stations are expected to identify
+ * such vendor specific IEs and connect to the AP in FT mode though
+ * the profile is configured in non-FT mode.
+ * The driver-based SME cases also need to have this support for
+ * Adaptive 11r to handle the connection and roaming scenarios.
+ * This flag indicates the support for the same to the user space.
+ * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports
+ * concurrent network sessions on different Wi-Fi bands. This feature
+ * capability is attributed to the hardware's capability to support
+ * the same (e.g., DBS).
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT: Flag indicating whether the
+ * responses for the respective TWT operations are asynchronous (separate
+ * event message) from the driver. If not specified, the responses are
+ * synchronous (in vendor command reply) to the request. Each TWT
+ * operation is specifically mentioned (against its respective
+ * documentation) to support either of these or both modes.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
@@ -1453,6 +1577,9 @@
QCA_WLAN_VENDOR_FEATURE_11AX = 9,
QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10,
QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11,
+ QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12,
+ QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13,
+ QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT = 14,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -1679,11 +1806,22 @@
* @QCA_TSF_CAPTURE: Initiate TSF Capture
* @QCA_TSF_GET: Get TSF capture value
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
*/
enum qca_tsf_cmd {
QCA_TSF_CAPTURE,
QCA_TSF_GET,
QCA_TSF_SYNC_GET,
+ QCA_TSF_AUTO_REPORT_ENABLE,
+ QCA_TSF_AUTO_REPORT_DISABLE,
};
/**
@@ -1777,6 +1915,23 @@
};
/**
+ * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the
+ * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take.
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority
+ */
+enum qca_wlan_vendor_scan_priority {
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4,
+};
+
+/**
* enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
*
* @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
@@ -1801,6 +1956,11 @@
* @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in
* microseconds. This is a common value which applies across all
* frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to
+ * other scan requests. It is a u32 attribute and takes values from enum
+ * qca_wlan_vendor_scan_priority. This is an optional attribute.
+ * If this attribute is not configured, the driver shall use
+ * QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
*/
enum qca_wlan_vendor_attr_scan {
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -1816,6 +1976,7 @@
QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
+ QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -2278,6 +2439,10 @@
* frame. The updated NSS value after the connection shall not be
* greater than the one negotiated during the connection. Any such
* higher value configuration shall be returned with a failure.
+ * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done
+ * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to
+ * configure the asymmetric NSS configuration (such as 1X2).
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70,
/* 8-bit unsigned value to trigger Optimized Power Management:
@@ -2326,6 +2491,86 @@
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76,
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for transmitting the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The TX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver
+ * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77,
+
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for receiving the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The RX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver
+ * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78,
+
+ /*
+ * 8-bit unsigned value. This attribute, when set, indicates whether the
+ * specified interface is the primary STA interface when there are more
+ * than one STA interfaces concurrently active.
+ *
+ * This configuration helps the firmware/hardware to support certain
+ * features (e.g., roaming) on this primary interface, if the same
+ * cannot be supported on the concurrent STA interfaces simultaneously.
+ *
+ * This configuration is only applicable for a single STA interface on
+ * a device and gives the priority for it only over other concurrent STA
+ * interfaces.
+ *
+ * If the device is a multi wiphy/soc, this configuration applies to a
+ * single STA interface across the wiphys.
+ *
+ * 1-Enable (is the primary STA), 0-Disable (is not the primary STA)
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * driver to enable/disable FT-over-DS feature. Possible values for
+ * this attribute are 1-Enable and 0-Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * firmware to enable/disable ARP/NS offload feature. Possible values
+ * for this attribute are 0-Disable and 1-Enable.
+ *
+ * This attribute is only applicable for STA/P2P-Client interface,
+ * and is optional, default behavior is ARP/NS offload enabled.
+ *
+ * This attribute can be set in disconnected and connected state, and
+ * will restore to the default behavior if the interface is closed.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -2421,23 +2666,50 @@
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
* %QCA_WLAN_VENDOR_GPIO_OUTPUT.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32)
* value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32)
* value to specify the GPIO interrupt mode. Please refer to enum
* qca_gpio_interrupt_mode for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32)
* value to specify the GPIO direction. Please refer to enum qca_gpio_direction
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32)
+ * Value to specify the mux config. Meaning of a given value is dependent
+ * on the target chipset and GPIO pin. Must be of the range 0-15.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32)
+ * Value to specify the drive, refer to enum qca_gpio_drive.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag)
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all
+ * other parameters for the given GPIO will be obtained from internal
+ * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be
+ * specified to indicate the GPIO pin being configured.
*/
enum qca_wlan_gpio_attr {
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
@@ -2453,6 +2725,12 @@
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5,
/* Unsigned 32-bit attribute for GPIO direction to configure */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6,
+ /* Unsigned 32-bit attribute for GPIO mux config */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7,
+ /* Unsigned 32-bit attribute for GPIO drive */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8,
+ /* Flag attribute for using internal GPIO configuration */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
@@ -2528,6 +2806,30 @@
};
/**
+ * enum qca_gpio_drive - GPIO drive
+ * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA
+ * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA
+ * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA
+ * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA
+ * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA
+ * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA
+ * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA
+ * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA
+ * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive
+ */
+enum qca_gpio_drive {
+ QCA_WLAN_GPIO_DRIVE_2MA = 0,
+ QCA_WLAN_GPIO_DRIVE_4MA = 1,
+ QCA_WLAN_GPIO_DRIVE_6MA = 2,
+ QCA_WLAN_GPIO_DRIVE_8MA = 3,
+ QCA_WLAN_GPIO_DRIVE_10MA = 4,
+ QCA_WLAN_GPIO_DRIVE_12MA = 5,
+ QCA_WLAN_GPIO_DRIVE_14MA = 6,
+ QCA_WLAN_GPIO_DRIVE_16MA = 7,
+ QCA_WLAN_GPIO_DRIVE_MAX,
+};
+
+/**
* qca_wlan_set_qdepth_thresh_attr - Parameters for setting
* MSDUQ depth threshold per peer per tid in the target
*
@@ -3688,6 +3990,14 @@
* QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+ /* u8 value representing the channel load percentage. Possible values
+ * are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
+ /* u8 value representing the time slicing duty cycle percentage.
+ * Possible values are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4035,6 +4345,30 @@
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1,
};
+/**
+ * enum qca_roam_scan_scheme: Scan scheme
+ *
+ * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan.
+ * Indicates the driver to not scan on a Roam Trigger scenario, but
+ * disconnect. E.g., on a BTM request from the AP the driver/firmware shall
+ * disconnect from the current connected AP by notifying a failure
+ * code in the BTM response.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to
+ * trigger partial frequency scans. These frequencies are the ones learned
+ * or maintained by the driver based on the probability of finding the
+ * BSSIDs in the ESS for which the roaming is triggered.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to
+ * trigger the scan on all the valid frequencies to find better
+ * candidates to roam.
+ */
+enum qca_roam_scan_scheme {
+ QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0,
+ QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1,
+ QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2,
+};
+
/*
* enum qca_vendor_roam_triggers: Bitmap of roaming triggers
*
@@ -4055,6 +4389,18 @@
* when BTM Request frame is received from the connected AP.
* @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered
* when the channel utilization is goes above the configured threshold.
+ * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered
+ * based on the request from the user (space).
+ * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when
+ * device receives Deauthentication/Disassociation frame from connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the
+ * device is in idle state (no TX/RX) and suspend mode, if the current RSSI
+ * is determined to be a poor one.
+ * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered
+ * based on continuous TX Data frame failures to the connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered
+ * based on the scan results obtained from an external scan (not triggered
+ * to aim roaming).
*
* Set the corresponding roam trigger reason bit to consider it for roam
* trigger.
@@ -4070,6 +4416,144 @@
QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5,
QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6,
QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7,
+ QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8,
+ QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9,
+ QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10,
+ QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11,
+ QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12,
+};
+
+/*
+ * enum qca_vendor_roam_fail_reasons: Defines the various roam
+ * fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED: Roam module in the firmware is not
+ * able to trigger the scan.
+ * @QCA_ROAM_FAIL_REASON_NO_AP_FOUND: No roamable APs found during roam scan.
+ * @QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND: No candidate APs found during roam
+ * scan.
+ * @QCA_ROAM_FAIL_REASON_HOST: Roam fail due to disconnect issued from host.
+ * @QCA_ROAM_FAIL_REASON_AUTH_SEND: Unable to send Authentication frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_RECV: Received Authentication frame with error
+ * status code.
+ * @QCA_ROAM_FAIL_REASON_NO_AUTH_RESP: Authentication frame not received.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_SEND: Unable to send Reassociation Request
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_RECV: Received Reassociation Response frame
+ * with error status code.
+ * @QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP: Reassociation Response frame not
+ * received.
+ * @QCA_ROAM_FAIL_REASON_SCAN_FAIL: Scan module not able to start scan.
+ * @QCA_ROAM_FAIL_REASON_AUTH_NO_ACK: No ACK is received for Authentication
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP: Authentication frame is dropped
+ * internally before transmission.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK: No ACK is received for Reassociation
+ * Request frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP: Reassociation Request frame is
+ * dropped internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT: EAPOL-Key M1 is not received and
+ * times out.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND: Unable to send EAPOL-Key M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP: EAPOL-Key M2 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK: No ACK is received for EAPOL-Key
+ * M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT: EAPOL-Key M3 frame is not received.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND: Unable to send EAPOL-Key M4 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP: EAPOL-Key M4 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK: No ACK is received for EAPOL-Key M4
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS: Roam scan is not
+ * started for final beacon miss case.
+ * @QCA_ROAM_FAIL_REASON_DISCONNECT: Deauthentication or Disassociation frame
+ * received from the AP during roaming handoff.
+ * @QCA_ROAM_FAIL_REASON_RESUME_ABORT: Firmware roams to the AP when the Apps
+ * or host is suspended and gives the indication of the last roamed AP only
+ * when the Apps is resumed. If the Apps is resumed while the roaming is in
+ * progress, this ongoing roaming is aborted and the last roamed AP is
+ * indicated to host.
+ * @QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID: WPA3-SAE invalid PMKID.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT: WPA3-SAE pre-authentication times
+ * out.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL: WPA3-SAE pre-authentication fails.
+ */
+enum qca_vendor_roam_fail_reasons {
+ QCA_ROAM_FAIL_REASON_NONE = 0,
+ QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED = 1,
+ QCA_ROAM_FAIL_REASON_NO_AP_FOUND = 2,
+ QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND = 3,
+ QCA_ROAM_FAIL_REASON_HOST = 4,
+ QCA_ROAM_FAIL_REASON_AUTH_SEND = 5,
+ QCA_ROAM_FAIL_REASON_AUTH_RECV = 6,
+ QCA_ROAM_FAIL_REASON_NO_AUTH_RESP = 7,
+ QCA_ROAM_FAIL_REASON_REASSOC_SEND = 8,
+ QCA_ROAM_FAIL_REASON_REASSOC_RECV = 9,
+ QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP = 10,
+ QCA_ROAM_FAIL_REASON_SCAN_FAIL = 11,
+ QCA_ROAM_FAIL_REASON_AUTH_NO_ACK = 12,
+ QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP = 13,
+ QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK = 14,
+ QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP = 15,
+ QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT = 16,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND = 17,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP = 18,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK = 19,
+ QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT = 20,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND = 21,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP = 22,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK = 23,
+ QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS = 24,
+ QCA_ROAM_FAIL_REASON_DISCONNECT = 25,
+ QCA_ROAM_FAIL_REASON_RESUME_ABORT = 26,
+ QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID = 27,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT = 28,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL = 29,
+};
+
+/*
+ * enum qca_vendor_roam_invoke_fail_reasons: Defines the various roam
+ * invoke fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_INVOKE_STATUS_IFACE_INVALID: Invalid interface ID is passed
+ * in roam invoke command.
+ * @QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE: Roam offload in firmware is not
+ * enabled.
+ * @QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID: Connected AP profile SSID
+ * length is invalid.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW: Firmware internal roaming is already
+ * in progress.
+ * @QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP: Host sends the Beacon/Probe Response
+ * of the AP in the roam invoke command to firmware. This reason is sent by the
+ * firmware when the given AP is configured to be ignored or SSID/security
+ * does not match.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL: Roam handoff failed because of
+ * firmware internal reasons.
+ * @QCA_ROAM_INVOKE_STATUS_DISALLOW: Roam invoke trigger is not enabled.
+ * @QCA_ROAM_INVOKE_STATUS_SCAN_FAIL: Scan start fail for roam invoke.
+ * @QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL: Roam handoff start fail.
+ * @QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS: Roam invoke parameters are invalid.
+ * @QCA_ROAM_INVOKE_STATUS_NO_CAND_AP: No candidate AP found to roam to.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_FAIL: Roam handoff failed.
+ */
+enum qca_vendor_roam_invoke_fail_reasons {
+ QCA_ROAM_INVOKE_STATUS_NONE = 0,
+ QCA_ROAM_INVOKE_STATUS_IFACE_INVALID = 1,
+ QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE = 2,
+ QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID = 3,
+ QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW = 4,
+ QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP = 5,
+ QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL = 6,
+ QCA_ROAM_INVOKE_STATUS_DISALLOW = 7,
+ QCA_ROAM_INVOKE_STATUS_SCAN_FAIL = 8,
+ QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL = 9,
+ QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS = 10,
+ QCA_ROAM_INVOKE_STATUS_NO_CAND_AP = 11,
+ QCA_ROAM_INVOKE_STATUS_ROAM_FAIL = 12,
+
};
/**
@@ -4226,6 +4710,109 @@
*
* Clears the selection criteria configured in the driver when specified
* with clear command.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value.
+ * Represents value of the scan frequency scheme from enum
+ * qca_roam_scan_scheme.
+ * It's an optional attribute. If this attribute is not configured, the
+ * driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the current connected AP, indicating
+ * the driver to trigger roam only when the current connected AP's RSSI
+ * is less than this threshold.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the candidate AP, indicating
+ * the driver to trigger roam only to the candidate AP with RSSI
+ * better than this threshold. If RSSI thresholds for candidate APs found
+ * in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ,
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will
+ * take precedence over the value configured using the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the
+ * user defined reason code to be sent to the AP in response to AP's
+ * request to trigger the roam if the roaming cannot be triggered.
+ * Applies to all the scenarios of AP assisted roaming (e.g., BTM).
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value.
+ * Carries a bitmap of the roam triggers specified in
+ * enum qca_vendor_roam_triggers.
+ * Represents the roam triggers for which the specific scan scheme from
+ * enum qca_roam_scan_scheme has to be applied.
+ * It's an optional attribute. If this attribute is not configured, but
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme
+ * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for
+ * all the roams.
+ * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the
+ * driver shall proceed with the default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value
+ * in dBm, signifying the RSSI threshold of the candidate AP found in the
+ * 2.4 GHz band. The driver/firmware shall trigger roaming to the candidate
+ * AP found in the 2.4 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 5
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 5 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by tge
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 6
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 6 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value.
+ * Carries bitmask value of bits from &enum qca_set_band and represents
+ * all the bands in which roaming is allowed. The configuration is valid
+ * until next disconnection. If this attribute is not present, the
+ * existing configuration shall be used. By default, roaming is allowed on
+ * all bands supported by the local device. When the value is set to
+ * %QCA_SETBAND_AUTO, all supported bands shall be enabled.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz
+ * bands. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for passive channels in the 5 GHz
+ * band. If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds.
+ * Optional parameter. The minimum duration to stay on the connected AP
+ * channel during the channel scanning. If this attribute is not
+ * configured, the driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds.
+ * Optional parameter. The maximum duration for which the radio can scan
+ * foreign channels consecutively without coming back to home channel. If
+ * this attribute is not configured, the driver shall proceed with default
+ * behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Preferred Scanning Channels.
+ * If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Non Preferred Scanning
+ * Channels. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
*/
enum qca_vendor_attr_roam_control {
QCA_ATTR_ROAM_CONTROL_ENABLE = 1,
@@ -4236,6 +4823,21 @@
QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6,
QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7,
QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9,
+ QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11,
+ QCA_ATTR_ROAM_CONTROL_USER_REASON = 12,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16,
+ QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17,
+ QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18,
+ QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19,
+ QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20,
+ QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23,
/* keep last */
QCA_ATTR_ROAM_CONTROL_AFTER_LAST,
@@ -5843,6 +6445,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29,
+ /* This attribute specifies the bandwidth to be used for spectral scan
+ * operation. This is an u8 attribute and uses the values in enum
+ * nl80211_chan_width. This is an optional attribute.
+ * If this attribute is not populated, the driver should configure the
+ * spectral scan bandwidth to the maximum value supported by the target
+ * for the current operating bandwidth.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -5953,6 +6563,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18,
+ /* Flag attribute to indicate agile spectral scan capability
+ * for 320 MHz mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19,
+ /* Number of spectral detectors used for scan in 320 MHz.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
@@ -6135,6 +6753,16 @@
* the FW on a specific VDEV.
*/
QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22,
+ /* WMI sequence mismatch between WMI command and Tx completion */
+ QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23,
+ /* Write to Device HAL register failed */
+ QCA_WLAN_HANG_REG_WRITE_FAILURE = 24,
+ /* No credit left to send the wow_wakeup_from_sleep to firmware */
+ QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25,
+ /* Bus failure */
+ QCA_WLAN_HANG_BUS_FAILURE = 26,
+ /* tasklet/credit latency found */
+ QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27,
};
/**
@@ -6801,8 +7429,9 @@
/**
* enum qca_wlan_vendor_thermal_level - Defines various thermal levels
- * configured by userspace to the driver/firmware. The values will be
- * encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL attribute.
+ * configured by userspace to the driver/firmware.
+ * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute.
* The driver/firmware takes actions requested by userspace such as throttling
* wifi TX etc. in order to mitigate high temperature.
*
@@ -6836,8 +7465,9 @@
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1,
/* Userspace uses this attribute to configure thermal level to the
- * driver/firmware. Used in request, u32 attribute, possible values
- * are defined in enum qca_wlan_vendor_thermal_level.
+ * driver/firmware, or get thermal level from the driver/firmware.
+ * Used in request or response, u32 attribute,
+ * possible values are defined in enum qca_wlan_vendor_thermal_level.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2,
/* Userspace uses this attribute to configure the time in which the
@@ -6850,6 +7480,15 @@
* there is any critical ongoing operation.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3,
+ /* Nested attribute, the driver/firmware uses this attribute to report
+ * thermal statistics of different thermal levels to userspace when
+ * requested using the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command
+ * type. This attribute contains a nested array of records of thermal
+ * statistics of multiple levels. The attributes used inside this nested
+ * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
@@ -6875,6 +7514,16 @@
* resume action.
* @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to
* the driver/firmware.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current
+ * thermal level from the driver/firmware. The driver should respond with a
+ * thermal level defined in enum qca_wlan_vendor_thermal_level.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the
+ * current thermal statistics from the driver/firmware. The driver should
+ * respond with statistics of all thermal levels encapsulated in the attribute
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear
+ * the current thermal statistics for all thermal levels maintained in the
+ * driver/firmware and start counting from zero again.
*/
enum qca_wlan_vendor_attr_thermal_cmd_type {
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
@@ -6882,6 +7531,9 @@
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS,
};
/**
@@ -6964,6 +7616,11 @@
* NLA_FLAG attribute.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE,
+ /* Thermal level from the driver.
+ * u32 attribute. Possible values are defined in
+ * enum qca_wlan_vendor_thermal_level.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST,
@@ -6972,6 +7629,35 @@
};
/**
+ * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes
+ * to get thermal status from the driver/firmware.
+ * enum values are used for NL attributes encapsulated inside the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute.
+ *
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each
+ * thermal level in milliseconds. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number
+ * of times the temperature crossed into the temperature range defined by the
+ * thermal level from both higher and lower directions. u32 size.
+ */
+enum qca_wlan_vendor_attr_thermal_stats {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST - 1,
+};
+
+/**
* enum he_fragmentation_val - HE fragmentation support values
* Indicates level of dynamic fragmentation that is supported by
* a STA as a recipient.
@@ -7130,6 +7816,21 @@
};
/**
+ * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration
+ *
+ * Indicates the frame types to use for keep alive data.
+ *
+ * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive.
+ */
+enum qca_wlan_keep_alive_data_type {
+ QCA_WLAN_KEEP_ALIVE_DEFAULT = 0,
+ QCA_WLAN_KEEP_ALIVE_DATA = 1,
+ QCA_WLAN_KEEP_ALIVE_MGMT = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
* HE operating mode control transmit request. These attributes are
* sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
@@ -7577,6 +8278,128 @@
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43,
+ /* 8-bit unsigned value to configure the driver/firmware to start or
+ * stop transmitting FILS discovery frames.
+ * 0 - Stop transmitting FILS discovery frames
+ * 1 - Start transmitting FILS discovery frames
+ * This attribute is used to configure the testbed device.
+ * This attribute can be configured only in AP mode and the
+ * configuration is valid until AP restart.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable full bandwidth UL MU-MIMO subfield
+ * 1 - Enable full bandwidth UL MU-MIMO subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45,
+
+ /* 16-bit unsigned value to configure the driver with a specific BSS
+ * max idle period to advertise in the BSS Max Idle Period element
+ * (IEEE Std 802.11-2016, 9.4.2.79) in (Re)Association Request frames.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD = 46,
+
+ /* 8-bit unsigned value to configure the driver to use only RU 242 tone
+ * for data transmission.
+ * 0 - Default behavior, 1 - Configure RU 242 tone for data Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX = 47,
+
+ /* 8-bit unsigned value to configure the driver to disable data and
+ * management response frame transmission to test the BSS max idle
+ * feature.
+ * 0 - Default behavior, 1 - Disable data and management response Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX = 48,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Punctured Preamble Rx subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable Punctured Preamble Rx subfield
+ * 1 - Enable Punctured Preamble Rx subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49,
+
+ /* 8-bit unsigned value to configure the driver to ignore the SAE H2E
+ * requirement mismatch for 6 GHz connection.
+ * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50,
+
+ /* 8-bit unsigned value to configure the driver to allow 6 GHz
+ * connection with all security modes.
+ * 0 - Default behavior, 1 - Allow 6 GHz connection with all security
+ * modes.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51,
+
+ /* 8-bit unsigned value to configure the driver to transmit data with
+ * ER SU PPDU type.
+ *
+ * 0 - Default behavior, 1 - Enable ER SU PPDU type TX.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52,
+
+ /* 8-bit unsigned value to configure the driver to use Data or
+ * Management frame type for keep alive data.
+ * Uses enum qca_wlan_keep_alive_data_type values.
+ *
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+
+ /* 8-bit unsigned value to configure the driver to use scan request
+ * BSSID value in Probe Request frame RA(A1) during the scan. The
+ * driver saves this configuration and applies this setting to all user
+ * space scan requests until the setting is cleared. If this
+ * configuration is set, the driver uses the BSSID value from the scan
+ * request to set the RA(A1) in the Probe Request frames during the
+ * scan.
+ *
+ * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+ * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * BSS max idle period support.
+ *
+ * 0 - Disable the BSS max idle support.
+ * 1 - Enable the BSS max idle support.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Rx control frame to MultiBSS subfield in the HE MAC
+ * capabilities information field.
+ * 0 - Disable Rx control frame to MultiBSS subfield
+ * 1 - Enable Rx control frame to MultiBSS subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Broadcast TWT support subfield in the HE MAC capabilities
+ * information field.
+ * 0 - Disable Broadcast TWT support subfield
+ * 1 - Enable Broadcast TWT support subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -7586,26 +8409,73 @@
/**
* enum qca_wlan_twt_operation - Operation of the config TWT request
* Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION.
+ * The response for the respective operations can be either synchronous or
+ * asynchronous (wherever specified). If synchronous, the response to this
+ * operation is obtained in the corresponding vendor command reply to the user
+ * space. For the asynchronous case the response is obtained as an event with
+ * the same operation type.
+ *
+ * Drivers shall support either of these modes but not both simultaneously.
+ * This support for asynchronous mode is advertised through the flag
+ * QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT. If this flag is not advertised,
+ * the driver shall support synchronous mode.
*
* @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured
* through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. Depending upon the
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, this is either a
+ * synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. This is a synchronous operation.
*
* @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * This terminate can either get triggered by the user space or can as well be
+ * a notification from the firmware if it initiates a terminate.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * the request from user space can either be a synchronous or asynchronous
+ * operation.
*
* @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * this is either a synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are
* configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup.
+ * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE
+ * request. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a
+ * combination of suspend and resume in a single request. Required parameters
+ * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the
+ * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is
+ * setup. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information.
+ * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT
+ * session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information.
+ * Valid only after the TWT session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its
+ * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous
+ * operation.
+ *
+ * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is
+ * ready for a new TWT session setup after it issued a TWT teardown.
+ *
+ * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required
+ * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer
+ * the enum qca_wlan_vendor_attr_twt_set_param.
*/
enum qca_wlan_twt_operation {
QCA_WLAN_TWT_SET = 0,
@@ -7613,6 +8483,12 @@
QCA_WLAN_TWT_TERMINATE = 2,
QCA_WLAN_TWT_SUSPEND = 3,
QCA_WLAN_TWT_RESUME = 4,
+ QCA_WLAN_TWT_NUDGE = 5,
+ QCA_WLAN_TWT_GET_STATS = 6,
+ QCA_WLAN_TWT_CLEAR_STATS = 7,
+ QCA_WLAN_TWT_GET_CAPABILITIES = 8,
+ QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9,
+ QCA_WLAN_TWT_SET_PARAM = 10,
};
/**
@@ -7626,8 +8502,9 @@
*
* @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the
* parameters configured for TWT. These parameters are represented by
- * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume
- * based on the operation.
+ * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume,
+ * enum qca_wlan_vendor_attr_twt_set_param, or
+ * enum qca_wlan_vendor_attr_twt_stats based on the operation.
*/
enum qca_wlan_vendor_attr_config_twt {
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0,
@@ -7788,6 +8665,19 @@
};
/**
+ * qca_wlan_twt_setup_state: Represents the TWT session states.
+ *
+ * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established.
+ * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active.
+ * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state.
+ */
+enum qca_wlan_twt_setup_state {
+ QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0,
+ QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1,
+ QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_twt_setup: Represents attributes for
* TWT (Target Wake Time) setup request. These attributes are sent as part of
* %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and
@@ -7837,6 +8727,14 @@
* 2. TWT GET Request and Response
* 3. TWT TERMINATE Request and Response
* 4. TWT SUSPEND Request and Response
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions for the following
+ * 1. TWT TERMINATE Request and Response
+ * 2. TWT SUSPEND Request and Response
+ * 4. TWT CLEAR STATISTICS request
+ * 5. TWT GET STATISTICS request and response
+ * If an invalid dialog ID is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8)
* This attribute (exp) is used along with the mantissa to derive the
@@ -7887,6 +8785,7 @@
* 2. TWT TERMINATE Response
* 3. TWT SUSPEND Response
* 4. TWT RESUME Response
+ * 5. TWT NUDGE Response
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8)
* This field is applicable for TWT response only.
@@ -7896,9 +8795,13 @@
* response.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64)
- * This field is applicable for TWT response only.
- * This field contains absolute TSF value of the wake time received
- * from the TWT responder and is passed to the userspace.
+ * In TWT setup command this field contains absolute TSF that will
+ * be used by TWT requester during setup.
+ * In TWT response this field contains absolute TSF value of the
+ * wake time received from the TWT responder and is passed to
+ * the userspace.
+ * This is an optional parameter for
+ * 1. TWT SET Request
* This is a required parameter for
* 1. TWT SET Response
* 2. TWT GET Response
@@ -7915,14 +8818,87 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer for which the TWT session
* is being configured. This is used in AP mode to represent the respective
- * client. In AP mode, this is an optional parameter for response and is
- * a required parameter for
- * 1. TWT SET Request
- * 2. TWT GET Request
- * 3. TWT TERMINATE Request
- * 4. TWT SUSPEND Request
+ * client.
+ * In AP mode, this is a required parameter in response for
+ * 1. TWT SET
+ * 2. TWT GET
+ * 3. TWT TERMINATE
+ * 4. TWT SUSPEND
* In STA mode, this is an optional parameter in request and response for
* the above four TWT operations.
+ * In AP mode, this is a required parameter in request for
+ * 1. TWT GET
+ * 2. TWT TERMINATE
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32)
+ * Minimum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32)
+ * Maximum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32)
+ * Minimum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32)
+ * Maximum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32)
+ * TWT state for the given dialog id. The values for this are represented
+ * by enum qca_wlan_twt_setup_state.
+ * This is obtained through TWT GET operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The unit is microseconds. This attribute, when specified, takes
+ * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA.
+ * This parameter is used for
+ * 1. TWT SET Request and Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
+ * This attribute is used to configure Broadcast TWT ID.
+ * The Broadcast TWT ID indicates a specific Broadcast TWT for which the
+ * transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
+ * This parameter is used for
+ * 1. TWT SET Request
+ * 2. TWT TERMINATE Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
+ * This attribute is used to configure Broadcast TWT recommendation.
+ * The Broadcast TWT Recommendation subfield contains a value that indicates
+ * recommendations on the types of frames that are transmitted by TWT
+ * scheduled STAs and scheduling AP during the broadcast TWT SP.
+ * The allowed values are 0 - 3.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
+ * This attribute is used to configure Broadcast TWT Persistence.
+ * The Broadcast TWT Persistence subfield indicates the number of
+ * TBTTs during which the Broadcast TWT SPs corresponding to this
+ * broadcast TWT Parameter set are present. The number of beacon intervals
+ * during which the Broadcast TWT SPs are present is equal to the value in the
+ * Broadcast TWT Persistence subfield plus 1 except that the value 255
+ * indicates that the Broadcast TWT SPs are present until explicitly terminated.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8)
+ * This attribute contains the value of the Responder PM Mode subfield (0 or 1)
+ * from TWT response frame.
+ * This parameter is used for
+ * 1. TWT SET Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32)
+ * This attribute is used to configure the announce timeout value (in us) in
+ * the firmware. This timeout value is only applicable for the announced TWT. If
+ * the timeout value is non-zero the firmware waits up to the timeout value to
+ * use Data frame as an announcement frame. If the timeout value is 0 the
+ * firmware sends an explicit QoS NULL frame as the announcement frame on SP
+ * start. The default value in the firmware is 0.
+ * This parameter is used for
+ * 1. TWT SET Request
*/
enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@@ -7944,6 +8920,20 @@
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
@@ -7971,6 +8961,30 @@
* @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request
* @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an
* unknown reason
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in
+ * suspend state
+ * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to
+ * invalid IE in the received TWT frame
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from
+ * the responder are not in the specified range
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to request from the responder. Used on the TWT_TERMINATE
+ * notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to roaming. Used on the TWT_TERMINATE notification from the
+ * firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
+ * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
+ * Concurrency). Used on the TWT_TERMINATE notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
+ * request due to roaming in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
+ * setup request due to channel switch in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup
+ * request due to scan in progress.
+ * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to
+ * terminate an existing TWT session on power save exit request from userspace.
+ * Used on the TWT_TERMINATE notification from the driver/firmware.
*/
enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@@ -7986,6 +9000,16 @@
QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10,
QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11,
QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12,
+ QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13,
+ QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14,
+ QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
+ QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
+ QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21,
+ QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22,
};
/**
@@ -8012,6 +9036,10 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8).
* Flow ID is the unique identifier for each TWT session. This attribute
* represents the respective TWT session to resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer to which TWT Resume is
@@ -8034,6 +9062,231 @@
};
/**
+ * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for
+ * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend
+ * and resume in a single request. These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session to suspend and resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request
+ * and response.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32)
+ * This attribute is used as the SP offset which is the offset from
+ * TSF after which the wake happens. The units are in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32)
+ * This attribute represents the next TWT subfield size.
+ * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits,
+ * and 4 for 64 bits.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer to which TWT Suspend and Resume is
+ * being sent. This is used in AP mode to represent the respective
+ * client and is a required parameter. In STA mode, this is an optional
+ * parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64)
+ * This field contains absolute TSF value of the time at which the TWT
+ * session will be resumed.
+ */
+enum qca_wlan_vendor_attr_twt_nudge {
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for
+ * TWT (Target Wake Time) get statistics and clear statistics request.
+ * These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session for get and clear TWT statistics.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which TWT Statistics
+ * is required.
+ * In AP mode this is used to represent the respective
+ * client and is a required parameter for
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request and response
+ * In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32)
+ * This is the duration of the service period in microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32)
+ * Average of the actual wake duration observed so far. Unit is microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32)
+ * The number of TWT service periods elapsed so far.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32)
+ * This is the minimum value of the wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32)
+ * This is the maximum value of wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32)
+ * Average number of MPDUs transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32)
+ * Average number of MPDUs received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32)
+ * Average number of bytes transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32)
+ * Average number of bytes received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32)
+ * Status of the TWT GET STATISTICS request.
+ * This contains status values in enum qca_wlan_vendor_twt_status
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ */
+enum qca_wlan_vendor_attr_twt_stats {
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities
+ * supported by the device and the peer.
+ * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by
+ * TWT non-scheduling STA. This capability is advertised in the HE
+ * Capability/Extended Capabilities information element in the
+ * Association Request frame by the device.
+ *
+ * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by
+ * the TWT scheduling AP. This capability is advertised in the Extended
+ * Capabilities/HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support
+ * for the broadcast TWT functionality. On the responder side, this indicates
+ * support for the role of broadcast TWT scheduling functionality. This
+ * capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule.
+ * This capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate
+ * that it mandates the associated HE STAs to support TWT. This capability is
+ * advertised by AP in the HE Operation Parameters field of the HE Operation
+ * information element.
+ */
+enum qca_wlan_twt_capa {
+ QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0),
+ QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1),
+ QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2),
+ QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3),
+ QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT
+ * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT
+ * operation.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which the TWT capabilities
+ * are being queried. This is used in AP mode to represent the respective
+ * client. In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16).
+ * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16).
+ * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ */
+enum qca_wlan_vendor_attr_twt_capability {
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for
+ * TWT (Target Wake Time) related parameters. It is used when
+ * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM.
+ * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8)
+ * This attribute configures AC parameters to be used for all TWT
+ * sessions in AP mode.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+enum qca_wlan_vendor_attr_twt_set_param {
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1,
+};
+
+/**
* enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by
* the TWT responder
*
@@ -8124,6 +9377,22 @@
};
/**
+ * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data
+ * transport modes and is used by the attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data.
+ * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR
+ * data. The data shall be encapsulated within
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event.
+ */
+enum qca_wlan_vendor_cfr_data_transport_modes {
+ QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0,
+ QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1,
+};
+
+/**
* enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
* attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
* command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
@@ -8313,6 +9582,27 @@
* MAC for CFR capture. This is a bitmask in which each bit represents the
* corresponding Data frame subtype value per IEEE Std 802.11-2016,
* 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8)
+ * Userspace can use this attribute to specify the driver about which transport
+ * mode shall be used by the driver to send CFR data to userspace. Uses values
+ * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is
+ * not present, the driver shall use the default transport mechanism which is
+ * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32)
+ * Userspace can use this attribute to specify the nl port id of the application
+ * which receives the CFR data and processes it further so that the drivers can
+ * unicast the netlink events to a specific application. Optionally included
+ * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to
+ * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers
+ * shall multicast the netlink events when this attribute is not included.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY).
+ * This attribute will be used by the driver to encapsulate and send CFR data
+ * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an
+ * asynchronous event when the driver is configured to send CFR data using
+ * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS.
*/
enum qca_wlan_vendor_peer_cfr_capture_attr {
QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
@@ -8341,6 +9631,9 @@
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28,
/* Keep last */
QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
@@ -9027,20 +10320,48 @@
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
* Nested attribute containing multiple ranges with following attributes:
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
* Starting center frequency in MHz.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
* Ending center frequency in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
+ * s32 attribute, optional. It is a per frequency range attribute.
+ * The maximum TX power limit from user space is to be applied on an
+ * unrestricted interface for corresponding frequency range. It is also
+ * possible that the actual TX power may be even lower than this cap due to
+ * other considerations such as regulatory compliance, SAR, etc. In absence of
+ * this attribute the driver shall follow current behavior which means
+ * interface (SAP/P2P) function can keep operating on an unsafe channel with TX
+ * power derived by the driver based on regulatory/SAR during interface up.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
+ * u32 attribute, optional. Indicates all the interface types which are
+ * restricted for all frequency ranges provided in
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * This attribute encapsulates bitmasks of interface types defined in
+ * enum nl80211_iftype. If an interface is marked as restricted the driver must
+ * move to a safe channel and if no safe channel is available the driver shall
+ * terminate that interface functionality. In absence of this attribute,
+ * interface (SAP/P2P) can still continue operating on an unsafe channel with
+ * TX power limit derived from either
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
+ * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
+ * is not provided.
*/
enum qca_wlan_vendor_attr_avoid_frequency_ext {
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -9366,7 +10687,56 @@
* @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode
* only. This represents number of Beacon frames received from this station with
* the packet number less than or equal to the last received packet number when
- * beacon protection is enabled.
+ * beacon protection is enabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in
+ * STA mode only. The driver uses this attribute to populate the connection
+ * failure reason codes and the values are defined in
+ * enum qca_sta_connect_fail_reason_codes. Userspace applications can send
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving
+ * a connection failure indication from the driver. The driver shall not
+ * include this attribute in response to the
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection
+ * failure observed in the last attempted connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE: u32, latest TX rate (Kbps)
+ * used by the station in its last TX frame while communicating to the AP in the
+ * connected state. When queried in the disconnected state, this represents the
+ * rate used by the STA in the last TX frame to the AP when it was connected.
+ * This attribute is used for STA mode only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX: u32, used in STA mode only.
+ * This represents the rate index used by the STA for the last TX frame to the
+ * AP. When queried in the disconnected state, this gives the last RIX used by
+ * the STA in the last TX frame to the AP when it was connected.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT: u32, used in STA
+ * mode only. This represents the number of times the STA TSF goes out of sync
+ * from the AP after the connection. If queried in the disconnected state, this
+ * gives the count of TSF out of sync for the last connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. This can be queried either in connected state or
+ * disconnected state. Each bit of this attribute represents the different
+ * roam trigger reason code which are defined in enum qca_vendor_roam_triggers.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON: u32, used in STA mode
+ * only. This represents the roam fail reason for the last failed roaming
+ * attempt by the firmware. Different roam failure reason codes are specified
+ * in enum qca_vendor_roam_fail_reasons. This can be queried either in
+ * connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
+ * queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
*/
enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -9412,6 +10782,14 @@
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE = 44,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX = 45,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT = 46,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
@@ -9842,4 +11220,600 @@
QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL:
+ * u8 attribute. Notify the TX VDEV status. Possible values 0, 1
+ * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV,
+ * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT:
+ * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID:
+ * u8 attribute, required. Indicates group id of Tx VDEV.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * group information. The attributes defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info
+ * are nested in this attribute.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_status {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX:
+ * u32 attribute, required. Contains interface index.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS:
+ * u8 attribute, required. 0 - means vdev is in down state.
+ * 1 - means vdev is in up state.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary
+ * STA interface has to be given while selecting the connection policies
+ * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface.
+ * An interface is set as primary through the attribute
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not
+ * applicable if the primary interface has not been set earlier.
+ *
+ * The intention is not to downgrade the primary STA performance, such as:
+ * - Do not reduce the number of TX/RX chains of primary connection.
+ * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of
+ * chains.
+ * - If using MCC, should set the MCC duty cycle of the primary connection to
+ * be higher than the secondary connection.
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the
+ * subsequent STA connection shall be chosen to balance with the existing
+ * concurrent STA's performance.
+ * Such as
+ * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware
+ * capability.
+ * - If using MCC, set the MCC duty cycle of the primary connection to be equal
+ * to the secondary.
+ * - Prefer BSSID candidates which will help provide the best "overall"
+ * performance for all the STA connections.
+ */
+enum qca_wlan_concurrent_sta_policy_config {
+ QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0,
+ QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_concurrent_sta_policy - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG:
+ * u8 attribute. Configures the concurrent STA policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config.
+ */
+enum qca_wlan_vendor_attr_concurrent_sta_policy {
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST - 1,
+
+};
+
+/**
+ * enum qca_sta_connect_fail_reason_codes - Defines values carried
+ * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor
+ * attribute.
+ * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received
+ * for unicast Probe Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for
+ * auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not
+ * received from AP.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response
+ * frame is not received from AP.
+ */
+enum qca_sta_connect_fail_reason_codes {
+ QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
+};
+
+/**
+ * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different
+ * filters defined in this enum are used in attribute
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK.
+ *
+ * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver
+ * shall filter the channels which are not usable because of coexistence with
+ * cellular radio.
+ * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver
+ * shall filter the channels which are not usable because of existing active
+ * interfaces in the driver and will result in Multi Channel Concurrency, etc.
+ *
+ */
+enum qca_wlan_vendor_usable_channels_filter {
+ QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0,
+ QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_chan_info - Attributes used inside
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ:
+ * u32 attribute, required. Indicates the center frequency of the primary
+ * channel in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ:
+ * u32 attribute. Indicates the center frequency of the primary segment of the
+ * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz,
+ * 160 MHz, and 320 MHz channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ:
+ * u32 attribute. Indicates the center frequency of the secondary segment of
+ * 80+80 channel in MHz. This attribute is required only when
+ * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH:
+ * u32 attribute, required. Indicates the bandwidth of the channel, possible
+ * values are defined in enum nl80211_chan_width.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK:
+ * u32 attribute, required. Indicates all the interface types for which this
+ * channel is usable. This attribute encapsulates bitmasks of interface types
+ * defined in enum nl80211_iftype.
+ *
+ */
+enum qca_wlan_vendor_attr_chan_info {
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_usable_channels - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK:
+ * u32 attribute. Indicates the bands from which the channels should be reported
+ * in response. This attribute encapsulates bit masks of bands defined in enum
+ * nl80211_band. Optional attribute, if not present in the request the driver
+ * shall return channels from all supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK:
+ * u32 attribute. Indicates all the interface types for which the usable
+ * channels information is requested. This attribute encapsulates bitmasks of
+ * interface types defined in enum nl80211_iftype. Optional attribute, if not
+ * present in the request the driver shall send information of all supported
+ * interface modes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK:
+ * u32 attribute. This attribute carries information of all filters that shall
+ * be applied while populating usable channels information by the driver. This
+ * attribute carries bit masks of different filters defined in enum
+ * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present
+ * in the request the driver shall send information of channels without applying
+ * any of the filters that can be configured through this attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * usability information of each channel. The attributes defined in enum
+ * qca_wlan_vendor_attr_chan_info are used inside this attribute.
+ */
+enum qca_wlan_vendor_attr_usable_channels {
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX =
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry
+ * the list of radar history entries.
+ * Each entry contains freq, timestamp, and radar signal detect flag.
+ * The driver shall add an entry when CAC has finished, or radar signal
+ * has been detected post AP beaconing. The driver shall maintain at least
+ * 8 entries in order to save CAC result for a 160 MHz channel.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute.
+ * Channel frequency in MHz.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds.
+ * CLOCK_BOOTTIME timestamp when this entry is updated due to CAC
+ * or radar detection.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute.
+ * This flag indicates radar signal has been detected.
+ */
+enum qca_wlan_vendor_attr_radar_history {
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag)
+ * Enable mDNS offload. This attribute is mandatory to enable
+ * mDNS offload feature. If this attribute is not present, mDNS offload
+ * is disabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing
+ * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This
+ * attribute is mandatory when enabling the feature, and not required when
+ * disabling the feature.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing
+ * the following attributes:
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute.
+ * It consists of a hostname and ".local" as the domain name. The character
+ * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes.
+ * It is used to compare the domain in the "QU" query. Only 1 FQDN is
+ * supported per vdev.
+ * For example: myphone.local
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required
+ * u16 attribute. It specifies the total number of resource records present
+ * in the answer section of the answer payload. This attribute is needed by the
+ * firmware to populate the mDNS response frame for mDNS queries without having
+ * to parse the answer payload.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob
+ * attribute sent by the mdnsResponder from userspace. It contains resource
+ * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This
+ * payload is passed down to the firmware and is transmitted in response to
+ * mDNS queries.
+ * The maximum supported size of the answer payload is 512 bytes.
+ */
+enum qca_wlan_vendor_attr_mdns_offload {
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_monitor_data_frame_type - Represent the various
+ * Data frame types to be sent over the monitor interface.
+ */
+enum qca_wlan_vendor_monitor_data_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17),
+};
+
+/**
+ * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various
+ * Management frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames
+ * except the Beacon frame.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected
+ * BSSID Beacon frames. Valid only in the connected state.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents
+ * the Beacon frames obtained during the scan (off channel and connected
+ * channel), when in connected state.
+ */
+
+enum qca_wlan_vendor_monitor_mgmt_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3),
+};
+
+/**
+ * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various
+ * Control frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame
+ */
+enum qca_wlan_vendor_monitor_ctrl_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the
+ * monitor mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32
+ * attribute.
+ * Represents the interval in milliseconds only for the connected Beacon frames,
+ * expecting the connected BSS's Beacon frames to be sent on the monitor
+ * interface at this specific interval.
+ */
+enum qca_wlan_vendor_attr_set_monitor_mode
+{
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX =
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags.
+ * Bits will be set to 1 if the corresponding state is enabled.
+ *
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start.
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end.
+ */
+enum qca_wlan_vendor_roam_scan_state {
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_roam_event_type - Roam event type flags.
+ * Bits will be set to 1 if the corresponding event is notified.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event
+ * carries the trigger reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries
+ * the BSSID, RSSI, frequency info of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event
+ * carries the roam fail reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the
+ * BSSID, RSSI, frequency info of the AP to which the roam was attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam
+ * event carries the roam invoke fail reason. When set, it is expected that
+ * the roam event carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event
+ * carries the roam scan state. When set, it is expected that the roam event
+ * carries the respective scan state via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding
+ * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST.
+ */
+enum qca_wlan_vendor_roam_event_type {
+ QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1),
+ QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2),
+ QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info.
+ * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address
+ * representing the BSSID of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value
+ * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is
+ * attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz
+ * on which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam fail reason for the last failed
+ * roaming attempt by the firmware for the specific BSSID. Different roam
+ * failure reason codes are specified in enum qca_vendor_roam_fail_reasons.
+ */
+enum qca_wlan_vendor_attr_roam_events_candidate_info {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the
+ * roam events to the driver or notify these events from the driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the
+ * driver/firmware to enable/disable the notification of roam events. It's a
+ * mandatory attribute and used only in the request from the userspace to the
+ * host driver. 1-Enable, 0-Disable.
+ * If the roaming is totally offloaded to the firmware, this request when
+ * enabled shall mandate the firmware to notify all the relevant roam events
+ * represented by the below attributes. If the host is in the suspend mode,
+ * the behavior of the firmware to notify these events is guided by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get
+ * these events in the suspend state, the firmware is expected to wake up the
+ * host before the respective events are notified. Please note that such a
+ * request to get the events in the suspend state will have a definite power
+ * implication.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents
+ * that the roam events need to be notified in the suspend state too. By
+ * default, these roam events are notified in the resume state. With this flag,
+ * the roam events are notified in both resume and suspend states.
+ * This attribute is used in the request from the userspace to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only.
+ * Represents the different roam event types, signified by the enum
+ * qca_wlan_vendor_roam_event_type.
+ * Each bit of this attribute represents the different roam even types reported
+ * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. Each bit of this attribute represents the
+ * different roam trigger reason code which are defined in enum
+ * qca_vendor_roam_triggers.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info
+ * for which the roam is attempted. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_roam_events_candidate_info.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents
+ * the scan state on which the roam events need to be notified. The values for
+ * this attribute are referred from enum qca_wlan_vendor_roam_scan_state.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of
+ * u32 values. List of frequencies in MHz considered for a roam scan.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ */
+
+enum qca_wlan_vendor_attr_roam_events
+{
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/qcwcn/wifi_hal/radio_mode.cpp b/legacy/qcwcn/wifi_hal/radio_mode.cpp
similarity index 100%
rename from qcwcn/wifi_hal/radio_mode.cpp
rename to legacy/qcwcn/wifi_hal/radio_mode.cpp
diff --git a/qcwcn/wifi_hal/radio_mode.h b/legacy/qcwcn/wifi_hal/radio_mode.h
similarity index 100%
rename from qcwcn/wifi_hal/radio_mode.h
rename to legacy/qcwcn/wifi_hal/radio_mode.h
diff --git a/qcwcn/wifi_hal/rb_wrapper.cpp b/legacy/qcwcn/wifi_hal/rb_wrapper.cpp
similarity index 99%
rename from qcwcn/wifi_hal/rb_wrapper.cpp
rename to legacy/qcwcn/wifi_hal/rb_wrapper.cpp
index 4c9e475..9017d21 100644
--- a/qcwcn/wifi_hal/rb_wrapper.cpp
+++ b/legacy/qcwcn/wifi_hal/rb_wrapper.cpp
@@ -117,7 +117,7 @@
wifi_ring_buffer_status rbs;
wifi_ring_buffer_data_handler handler;
- while (1) {
+ while (info && !info->clean_up) {
size_t length = 0;
u8 *buf;
diff --git a/qcwcn/wifi_hal/rb_wrapper.h b/legacy/qcwcn/wifi_hal/rb_wrapper.h
similarity index 100%
rename from qcwcn/wifi_hal/rb_wrapper.h
rename to legacy/qcwcn/wifi_hal/rb_wrapper.h
diff --git a/qcwcn/wifi_hal/ring_buffer.cpp b/legacy/qcwcn/wifi_hal/ring_buffer.cpp
similarity index 94%
rename from qcwcn/wifi_hal/ring_buffer.cpp
rename to legacy/qcwcn/wifi_hal/ring_buffer.cpp
index d78bd62..1a65bb6 100644
--- a/qcwcn/wifi_hal/ring_buffer.cpp
+++ b/legacy/qcwcn/wifi_hal/ring_buffer.cpp
@@ -160,7 +160,7 @@
// write in current buffer
unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
- if (record_length > rbc->each_buf_size) {
+ if (record_length > rbc->each_buf_size || length > rbc->each_buf_size) {
return RB_FAILURE;
}
@@ -279,6 +279,17 @@
}
}
rb_unlock(&rbc->rb_rw_lock);
+ if(rbc->bufs[rbc->wr_buf_no].data == NULL || (rbc->bufs[rbc->wr_buf_no].data + rbc->cur_wr_buf_idx) == NULL ||
+ buf == NULL || buf + bytes_written == NULL) {
+ ALOGE("The read or Write buffer is null");
+ return RB_FAILURE;
+ }
+ if (((bytes_written + cur_copy_len) > length
+ || (rbc->cur_wr_buf_idx + cur_copy_len) > rbc->each_buf_size)) {
+ ALOGE("LOG_RB rb_write overflow - cur_copy_len=%d wr_buf[max=%zu no=%d idx=%d] buf[max=%zu accessed=%d]",
+ cur_copy_len, rbc->each_buf_size, rbc->wr_buf_no, rbc->cur_wr_buf_idx, length, bytes_written + cur_copy_len);
+ return RB_FAILURE;
+ }
/* don't use lock while doing memcpy, so that we don't block the read
* context for too long. There is no harm while writing the memory if
@@ -476,7 +487,12 @@
cur_read_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
} else {
/* write is rolled over and just behind the read */
- cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ if (rbc->bufs[rbc->rd_buf_no].last_wr_index >= rbc->cur_rd_buf_idx) {
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ } else {
+ ALOGE("Alert: cur_read_len=%u invalid, rd_buf[no=%d rd_idx=%d wr_index=%d]",cur_read_len, rbc->rd_buf_no, rbc->cur_rd_buf_idx, rbc->bufs[rbc->rd_buf_no].last_wr_index);
+ return NULL;
+ }
}
} else {
if (rbc->cur_rd_buf_idx == 0) {
diff --git a/qcwcn/wifi_hal/ring_buffer.h b/legacy/qcwcn/wifi_hal/ring_buffer.h
similarity index 100%
rename from qcwcn/wifi_hal/ring_buffer.h
rename to legacy/qcwcn/wifi_hal/ring_buffer.h
diff --git a/qcwcn/wifi_hal/roam.cpp b/legacy/qcwcn/wifi_hal/roam.cpp
similarity index 100%
rename from qcwcn/wifi_hal/roam.cpp
rename to legacy/qcwcn/wifi_hal/roam.cpp
diff --git a/qcwcn/wifi_hal/roamcommand.h b/legacy/qcwcn/wifi_hal/roamcommand.h
similarity index 100%
rename from qcwcn/wifi_hal/roamcommand.h
rename to legacy/qcwcn/wifi_hal/roamcommand.h
diff --git a/qcwcn/wifi_hal/rssi_monitor.cpp b/legacy/qcwcn/wifi_hal/rssi_monitor.cpp
similarity index 100%
rename from qcwcn/wifi_hal/rssi_monitor.cpp
rename to legacy/qcwcn/wifi_hal/rssi_monitor.cpp
diff --git a/qcwcn/wifi_hal/rssi_monitor.h b/legacy/qcwcn/wifi_hal/rssi_monitor.h
similarity index 100%
rename from qcwcn/wifi_hal/rssi_monitor.h
rename to legacy/qcwcn/wifi_hal/rssi_monitor.h
diff --git a/qcwcn/wifi_hal/rtt.cpp b/legacy/qcwcn/wifi_hal/rtt.cpp
similarity index 100%
rename from qcwcn/wifi_hal/rtt.cpp
rename to legacy/qcwcn/wifi_hal/rtt.cpp
diff --git a/qcwcn/wifi_hal/sync.h b/legacy/qcwcn/wifi_hal/sync.h
similarity index 100%
rename from qcwcn/wifi_hal/sync.h
rename to legacy/qcwcn/wifi_hal/sync.h
diff --git a/qcwcn/wifi_hal/tdls.cpp b/legacy/qcwcn/wifi_hal/tdls.cpp
similarity index 100%
rename from qcwcn/wifi_hal/tdls.cpp
rename to legacy/qcwcn/wifi_hal/tdls.cpp
diff --git a/qcwcn/wifi_hal/tdlsCommand.h b/legacy/qcwcn/wifi_hal/tdlsCommand.h
similarity index 100%
rename from qcwcn/wifi_hal/tdlsCommand.h
rename to legacy/qcwcn/wifi_hal/tdlsCommand.h
diff --git a/qcwcn/wifi_hal/vendor_definitions.h b/legacy/qcwcn/wifi_hal/vendor_definitions.h
similarity index 100%
rename from qcwcn/wifi_hal/vendor_definitions.h
rename to legacy/qcwcn/wifi_hal/vendor_definitions.h
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/legacy/qcwcn/wifi_hal/wifi_hal.cpp
similarity index 83%
rename from qcwcn/wifi_hal/wifi_hal.cpp
rename to legacy/qcwcn/wifi_hal/wifi_hal.cpp
index 372d9e1..cb4b8e7 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/legacy/qcwcn/wifi_hal/wifi_hal.cpp
@@ -12,6 +12,40 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#include <stdint.h>
@@ -106,6 +140,7 @@
u8 enable);
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle handle);
/* Initialize/Cleanup */
@@ -473,6 +508,226 @@
return WIFI_SUCCESS;
}
+static uint32_t get_frequency_from_channel(uint32_t channel, wlan_mac_band band)
+{
+ uint32_t freq = 0;
+
+ switch (band)
+ {
+ case WLAN_MAC_2_4_BAND:
+ if (!(channel >= 1 && channel <= 14))
+ goto failure;
+ //special handling for channel 14 by filling freq here
+ if (channel == 14)
+ freq = 2484;
+ else
+ freq = 2407 + (channel * 5);
+ break;
+ case WLAN_MAC_5_0_BAND:
+ if (!((channel >= 34 && channel < 65) ||
+ (channel > 99 && channel <= 196)))
+ goto failure;
+ freq = 5000 + (channel * 5);
+ break;
+ case WLAN_MAC_6_0_BAND:
+ if (!(channel >= 1 && channel <= 233))
+ goto failure;
+ freq = 5950 + (channel * 5);
+ break;
+ default:
+ break;
+ }
+
+failure:
+ return freq;
+}
+
+static u32 get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (!in_mask)
+ return op_mask;
+ if (in_mask & SOFTAP)
+ op_mask |= BIT(NL80211_IFTYPE_AP);
+ if (in_mask & WIFI_DIRECT)
+ op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
+ if (in_mask & WIFI_AWARE)
+ op_mask |= BIT(NL80211_IFTYPE_NAN);
+
+ return op_mask;
+}
+
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
+ wifi_coex_unsafe_channel *unsafeChannels,
+ u32 restrictions)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ WifihalGeneric *cmd = NULL;
+ struct nlattr *nl_data = NULL;
+ struct nlattr *nl_attr_unsafe_chan = NULL;
+ struct nlattr *unsafe_channels_attr = NULL;
+ hal_info *info = NULL;
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
+ goto cleanup;
+ }
+
+ info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT);
+ if (cmd == NULL) {
+ ALOGE("%s: Error, created command NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ /* Create the NL message. */
+ ret = cmd->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg due to error: (%d)",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ ALOGE("%s: failed attr_start for NL80211_ATTR_VENDOR_DATA",
+ __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ nl_attr_unsafe_chan = cmd->attr_start(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE);
+ if (!nl_attr_unsafe_chan) {
+ ALOGE("%s: failed attr_start for"
+ " QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ ALOGD("%s: num_channels:%d, restrictions:%x", __FUNCTION__, num_channels,
+ restrictions);
+ if (num_channels == 0) {
+ unsafe_channels_attr = cmd->attr_start(0);
+ if (!unsafe_channels_attr) {
+ ALOGE("%s: failed attr_start for unsafe_channels_attr when"
+ " trying to clear usafe channels clear", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, 0);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency start, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, 0);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency end, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ cmd->attr_end(unsafe_channels_attr);
+ }
+ else {
+ if (!unsafeChannels) {
+ ALOGE("%s: unsafe channels buffer should not be NULL when"
+ " there are unsafe channels", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ }
+ for (int i = 0; i < num_channels; i++) {
+ unsafe_channels_attr = cmd->attr_start(i);
+ if (!unsafe_channels_attr) {
+ ALOGE("%s: failed attr_start for unsafe_channels_attr of"
+ " index:%d", __FUNCTION__, i);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ u32 freq = get_frequency_from_channel(unsafeChannels[i].channel,
+ unsafeChannels[i].band);
+ if (!freq) {
+ ALOGE("%s: Failed to get frequency of band:%d, channel:%d",
+ __FUNCTION__, (int)unsafeChannels[i].band,
+ unsafeChannels[i].channel);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, freq);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency start, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, freq);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency end, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ /**
+ * WIFI_COEX_NO_POWER_CAP (0x7FFFFFF) is specific to android
+ * framework, this value denotes that framework/wifihal is not
+ * providing any power cap and allow driver/firmware to operate on
+ * current power cap dbm. As driver is supposed to work on with
+ * LA/LE etc, we are skipping to send 0x7FFFFFF down to driver,
+ * hence driver will be operating as per current power cap calculated
+ * based on regulatory or other constraints.
+ */
+ if (unsafeChannels[i].power_cap_dbm != WIFI_COEX_NO_POWER_CAP) {
+ ret = cmd->put_s32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM,
+ unsafeChannels[i].power_cap_dbm);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put power_cap_dbm, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ }
+ cmd->attr_end(unsafe_channels_attr);
+ ALOGD("%s: channel:%d, freq:%d, power_cap_dbm:%d, band:%d",
+ __FUNCTION__, unsafeChannels[i].channel, freq,
+ unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
+ }
+ cmd->attr_end(nl_attr_unsafe_chan);
+ if (num_channels > 0) {
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK,
+ get_nl_ifmask_from_coex_restriction_mask(restrictions));
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put restrictions mask, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ }
+ cmd->attr_end(nl_data);
+
+ /* Send the msg and wait for a response. */
+ ret = cmd->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ if (cmd)
+ delete cmd;
+ return ret;
+}
+
wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
{
wifi_error ret = WIFI_ERROR_INVALID_ARGS;
@@ -543,6 +798,161 @@
return ret;
}
+static u32 get_nl_band_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & WLAN_MAC_2_4_BAND)
+ op_mask |= BIT(NL80211_BAND_2GHZ);
+ if (in_mask & WLAN_MAC_5_0_BAND)
+ op_mask |= BIT(NL80211_BAND_5GHZ);
+ if (in_mask & WLAN_MAC_6_0_BAND)
+ op_mask |= BIT(NL80211_BAND_6GHZ);
+ if (in_mask & WLAN_MAC_60_0_BAND)
+ op_mask |= BIT(NL80211_BAND_60GHZ);
+
+ return op_mask;
+}
+
+static u32 get_nl_iftype_mode_masks(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & BIT(WIFI_INTERFACE_STA) ||
+ in_mask & BIT(WIFI_INTERFACE_TDLS))
+ op_mask |= BIT(NL80211_IFTYPE_STATION);
+ if (in_mask & BIT(WIFI_INTERFACE_SOFTAP))
+ op_mask |= BIT(NL80211_IFTYPE_AP);
+ if (in_mask & BIT(WIFI_INTERFACE_P2P_CLIENT))
+ op_mask |= BIT(NL80211_IFTYPE_P2P_CLIENT);
+ if (in_mask & BIT(WIFI_INTERFACE_P2P_GO))
+ op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
+ if (in_mask & BIT(WIFI_INTERFACE_NAN))
+ op_mask |= BIT(NL80211_IFTYPE_NAN);
+
+ return op_mask;
+}
+
+static u32 get_vendor_filter_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE)
+ op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX);
+ if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY)
+ op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY);
+
+ return op_mask;
+}
+
+wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask,
+ u32 iface_mode_mask, u32 filter_mask,
+ u32 max_size, u32* size,
+ wifi_usable_channel* channels)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ WifihalGeneric *cmd = NULL;
+ struct nlattr *nl_data = NULL;
+ hal_info *info = NULL;
+ u32 band = 0, iface_mask = 0, filter = 0;
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
+ goto cleanup;
+ }
+
+ info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ if (!max_size) {
+ ALOGE("%s: max channel size is zero", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ if (!channels) {
+ ALOGE("%s: user input channel buffer NULL", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS);
+ if (cmd == NULL) {
+ ALOGE("%s: Error, created command NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ /* Create the NL message. */
+ ret = cmd->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg due to error: (%d)",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ ALOGE("%s: failed attr_start for VENDOR_DATA due to error: (%d)",
+ __FUNCTION__, ret);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ band = get_nl_band_mask(band_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK,
+ band);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ iface_mask = get_nl_iftype_mode_masks(iface_mode_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK,
+ iface_mask);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ filter = get_vendor_filter_mask(filter_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK,
+ filter);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ cmd->attr_end(nl_data);
+
+ /* Populate the input received from caller/framework. */
+ cmd->setMaxSetSize(max_size);
+ cmd->set_channels_buff(channels);
+
+ /* Send the msg and wait for a response. */
+ ret = cmd->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ *size = cmd->get_results_size();
+
+cleanup:
+ if (cmd)
+ delete cmd;
+ return ret;
+}
+
/*initialize function pointer table with Qualcomm HAL API*/
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
if (fn == NULL) {
@@ -644,7 +1054,9 @@
fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
+ fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
fn->wifi_set_dtim_config = wifi_set_dtim_config;
+ fn->wifi_get_usable_channels = wifi_get_usable_channels;
return WIFI_SUCCESS;
}
@@ -955,6 +1367,14 @@
ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
" features : 0x%" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
+ if (wifi_is_nan_ext_cmd_supported(iface_handle))
+ info->support_nan_ext_cmd = true;
+ else
+ info->support_nan_ext_cmd = false;
+
+ ALOGV("support_nan_ext_cmd is %d",
+ info->support_nan_ext_cmd);
+
cld80211_cleanup:
if (status != 0 || ret != WIFI_SUCCESS) {
ret = WIFI_ERROR_UNKNOWN;
@@ -2711,3 +3131,99 @@
delete vCommand;
return ret;
}
+
+class GetSupportedVendorCmd : public WifiCommand
+{
+private:
+ u32 mVendorCmds[256];
+ int mNumOfVendorCmds;
+
+public:
+ GetSupportedVendorCmd(wifi_handle handle) : WifiCommand(handle, 0)
+ {
+ mNumOfVendorCmds = 0;
+ memset(mVendorCmds, 0, 256);
+ }
+
+ virtual wifi_error create() {
+ int nl80211_id = genl_ctrl_resolve(mInfo->cmd_sock, "nl80211");
+ wifi_error ret = mMsg.create(nl80211_id, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
+ mMsg.put_flag(NL80211_ATTR_SPLIT_WIPHY_DUMP);
+
+ return ret;
+ }
+
+ virtual wifi_error requestResponse() {
+ return WifiCommand::requestResponse(mMsg);
+ }
+ virtual wifi_error set_iface_id(const char* name) {
+ unsigned ifindex = if_nametoindex(name);
+ return mMsg.set_iface_id(ifindex);
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ struct nlattr **tb = reply.attributes();
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ struct nlattr *nl;
+ int rem, i = 0;
+
+ for_each_attr(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
+ struct nl80211_vendor_cmd_info *vinfo;
+ if (nla_len(nl) != sizeof(*vinfo)) {
+ ALOGE("Unexpected vendor data info found in attribute");
+ continue;
+ }
+ vinfo = (struct nl80211_vendor_cmd_info *)nla_data(nl);
+ if (vinfo->vendor_id == OUI_QCA) {
+ mVendorCmds[i] = vinfo->subcmd;
+ i++;
+ }
+ }
+ mNumOfVendorCmds = i;
+ }
+ return NL_SKIP;
+ }
+
+ int isVendorCmdSupported(u32 cmdId) {
+ int i, ret;
+
+ ret = 0;
+ for (i = 0; i < mNumOfVendorCmds; i++) {
+ if (cmdId == mVendorCmds[i]) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+ }
+};
+
+static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)
+{
+ wifi_error ret;
+ wifi_handle handle = getWifiHandle(iface_handle);
+ interface_info *info = getIfaceInfo(iface_handle);
+ GetSupportedVendorCmd cmd(handle);
+
+ ret = cmd.create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: create command failed", __func__);
+ return 0;
+ }
+
+ ret = cmd.set_iface_id(info->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: set iface id failed", __func__);
+ return 0;
+ }
+
+ ret = cmd.requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to query nan_ext command support, ret=%d", ret);
+ return 0;
+ } else {
+ return cmd.isVendorCmdSupported(QCA_NL80211_VENDOR_SUBCMD_NAN_EXT);
+ }
+}
diff --git a/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c b/legacy/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c
similarity index 100%
rename from qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c
rename to legacy/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c
diff --git a/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h b/legacy/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h
similarity index 100%
rename from qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h
rename to legacy/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h
diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/legacy/qcwcn/wifi_hal/wificonfig.cpp
similarity index 100%
rename from qcwcn/wifi_hal/wificonfig.cpp
rename to legacy/qcwcn/wifi_hal/wificonfig.cpp
diff --git a/qcwcn/wifi_hal/wificonfigcommand.h b/legacy/qcwcn/wifi_hal/wificonfigcommand.h
similarity index 100%
rename from qcwcn/wifi_hal/wificonfigcommand.h
rename to legacy/qcwcn/wifi_hal/wificonfigcommand.h
diff --git a/qcwcn/wifi_hal/wifihal_internal.h b/legacy/qcwcn/wifi_hal/wifihal_internal.h
similarity index 100%
rename from qcwcn/wifi_hal/wifihal_internal.h
rename to legacy/qcwcn/wifi_hal/wifihal_internal.h
diff --git a/qcwcn/wifi_hal/wifihal_vendor.cpp b/legacy/qcwcn/wifi_hal/wifihal_vendor.cpp
similarity index 100%
rename from qcwcn/wifi_hal/wifihal_vendor.cpp
rename to legacy/qcwcn/wifi_hal/wifihal_vendor.cpp
diff --git a/qcwcn/wifi_hal/wifihal_vendorcommand.h b/legacy/qcwcn/wifi_hal/wifihal_vendorcommand.h
similarity index 100%
rename from qcwcn/wifi_hal/wifihal_vendorcommand.h
rename to legacy/qcwcn/wifi_hal/wifihal_vendorcommand.h
diff --git a/qcwcn/wifi_hal/wifilogger.cpp b/legacy/qcwcn/wifi_hal/wifilogger.cpp
similarity index 100%
rename from qcwcn/wifi_hal/wifilogger.cpp
rename to legacy/qcwcn/wifi_hal/wifilogger.cpp
diff --git a/qcwcn/wifi_hal/wifilogger_diag.cpp b/legacy/qcwcn/wifi_hal/wifilogger_diag.cpp
similarity index 95%
rename from qcwcn/wifi_hal/wifilogger_diag.cpp
rename to legacy/qcwcn/wifi_hal/wifilogger_diag.cpp
index bdc9c7f..09ac928 100644
--- a/qcwcn/wifi_hal/wifilogger_diag.cpp
+++ b/legacy/qcwcn/wifi_hal/wifilogger_diag.cpp
@@ -24,6 +24,40 @@
* 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.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
/* Suppress -Waddress-of-packed-member for new toolchain update.
@@ -862,8 +896,23 @@
buf += 4;
length -= 4;
- while (length > (count + sizeof(fw_diag_msg_fixed_hdr_t))) {
+ while ((info && !info->clean_up)
+ && (length > (count + sizeof(fw_diag_msg_fixed_hdr_t)))) {
diag_msg_fixed_hdr = (fw_diag_msg_fixed_hdr_t *)(buf + count);
+
+ if (diag_msg_fixed_hdr->diag_event_type > WLAN_DIAG_TYPE_LEGACY_MSG) {
+ hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
+ } else {
+ hdr_size = sizeof(fw_diag_msg_hdr_t);
+ }
+
+ if ((count + hdr_size) > length)
+ {
+ ALOGE("process_fw_diag_msg (%d) - possible buffer over access, length=%d count=%d hdr_size=%d",
+ diag_msg_fixed_hdr->diag_event_type, length, count, hdr_size);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (diag_msg_fixed_hdr->diag_event_type) {
case WLAN_DIAG_TYPE_EVENT:
case WLAN_DIAG_TYPE_EVENT_V2:
@@ -883,6 +932,12 @@
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
}
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_EVENT - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (id) {
case EVENT_WLAN_BT_COEX_BT_SCO_START:
case EVENT_WLAN_BT_COEX_BT_SCO_STOP:
@@ -980,6 +1035,12 @@
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
}
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_LOG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (id) {
case LOG_WLAN_EXTSCAN_CAPABILITIES:
status = process_log_extscan_capabilities(info,
@@ -1002,6 +1063,11 @@
payloadlen = diag_msg_hdr->u.msg_hdr.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_t);
payload = diag_msg_hdr->payload;
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_MSG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
payloadlen + hdr_size);
break;
@@ -1012,6 +1078,11 @@
payloadlen = diag_msg_hdr_v2->u.msg_hdr.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_MSG_V2 - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
payloadlen + hdr_size);
break;
@@ -1023,6 +1094,11 @@
payload = diag_msg_hdr->payload;
payloadlen = diag_msg_hdr->u.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_t);
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_CONFIG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_hdr,
payloadlen + hdr_size);
}
@@ -1510,7 +1586,7 @@
wifi_ring_per_packet_status_entry *pps_entry;
u32 index = 0;
- while (index < info->rx_buf_size_occupied) {
+ while ((info && !info->clean_up) && (index < info->rx_buf_size_occupied)) {
pps_entry = (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
pps_entry->MCS = info->aggr_stats.RxMCS.mcs;
@@ -2347,6 +2423,9 @@
rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_80211_HEADER;
}
break;
+ default:
+ // TODO: Unexpected PKTLOG types
+ break;
}
if (info->pkt_stats->tx_stats_events & BIT(PKTLOG_TYPE_TX_STAT)) {
/* if bmap_enqueued is 1 ,Handle non aggregated cases */
@@ -2385,7 +2464,7 @@
data = (u8*) (data + sizeof(wh_pktlog_hdr_v2_t) + node_pkt_len);
info->pkt_stats->tx_stats_events = 0;
}
- } while (pkt_stats_len > 0);
+ } while ((info && !info->clean_up) && (pkt_stats_len > 0));
return status;
}
@@ -2522,7 +2601,7 @@
data += record_len;
buflen -= record_len;
- } while (buflen > 0);
+ } while ((info && !info->clean_up) && (buflen > 0));
return status;
}
@@ -2597,14 +2676,14 @@
clh = (tAniCLDHdr *)nla_data(tb_vendor[CLD80211_ATTR_DATA]);
}
}
- if (!clh) {
- ALOGE("Invalid data received from driver");
- return WIFI_SUCCESS;
- }
if((info->wifihal_ctrl_sock.s > 0) && (genlh->cmd == WLAN_NL_MSG_OEM)) {
wifihal_ctrl_event_t *ctrl_evt;
wifihal_mon_sock_t *reg;
+ if (!(tb_vendor[CLD80211_ATTR_DATA] || tb_vendor[CLD80211_ATTR_CMD])) {
+ ALOGE("Invalid oem data received from driver");
+ return WIFI_ERROR_UNKNOWN;
+ }
ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
if(ctrl_evt == NULL)
@@ -2653,6 +2732,7 @@
}
}
free(ctrl_evt);
+ return WIFI_SUCCESS;
}
}
} else {
@@ -2660,6 +2740,10 @@
cmd = wnl->nlh.nlmsg_type;
}
+ if (!clh) {
+ ALOGE("Invalid data received from driver");
+ return WIFI_ERROR_UNKNOWN;
+ }
/* Check nlmsg_type also to avoid processing unintended msgs */
if (cmd == ANI_NL_MSG_PUMAC) {
if (!info->cldctx) {
diff --git a/qcwcn/wifi_hal/wifilogger_diag.h b/legacy/qcwcn/wifi_hal/wifilogger_diag.h
similarity index 100%
rename from qcwcn/wifi_hal/wifilogger_diag.h
rename to legacy/qcwcn/wifi_hal/wifilogger_diag.h
diff --git a/qcwcn/wifi_hal/wifilogger_event_defs.h b/legacy/qcwcn/wifi_hal/wifilogger_event_defs.h
similarity index 100%
rename from qcwcn/wifi_hal/wifilogger_event_defs.h
rename to legacy/qcwcn/wifi_hal/wifilogger_event_defs.h
diff --git a/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h b/legacy/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
similarity index 100%
rename from qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
rename to legacy/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
diff --git a/qcwcn/wifi_hal/wifiloggercmd.h b/legacy/qcwcn/wifi_hal/wifiloggercmd.h
similarity index 100%
rename from qcwcn/wifi_hal/wifiloggercmd.h
rename to legacy/qcwcn/wifi_hal/wifiloggercmd.h
diff --git a/qcwcn/wpa_supplicant_8_lib/Android.mk b/legacy/qcwcn/wpa_supplicant_8_lib/Android.mk
similarity index 100%
rename from qcwcn/wpa_supplicant_8_lib/Android.mk
rename to legacy/qcwcn/wpa_supplicant_8_lib/Android.mk
diff --git a/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD b/legacy/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
similarity index 100%
rename from qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
rename to legacy/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
diff --git a/qcwcn/wpa_supplicant_8_lib/NOTICE b/legacy/qcwcn/wpa_supplicant_8_lib/NOTICE
similarity index 100%
rename from qcwcn/wpa_supplicant_8_lib/NOTICE
rename to legacy/qcwcn/wpa_supplicant_8_lib/NOTICE
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/legacy/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
similarity index 100%
rename from qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
rename to legacy/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
diff --git a/wcn6740/Android.mk b/wcn6740/Android.mk
new file mode 100644
index 0000000..6695cef
--- /dev/null
+++ b/wcn6740/Android.mk
@@ -0,0 +1,6 @@
+# TODO: Find a better way to separate build configs for ADP vs non-ADP devices
+QCOM_WLAN_ROOT := $(call my-dir)
+
+ifneq ($(BOARD_IS_AUTOMOTIVE),true)
+include $(call all-subdir-makefiles)
+endif
diff --git a/wcn6740/cld80211-lib/Android.mk b/wcn6740/cld80211-lib/Android.mk
new file mode 100644
index 0000000..7b40fe1
--- /dev/null
+++ b/wcn6740/cld80211-lib/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH := $(call my-dir)
+
+# =================================
+# copy header
+# =================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libcld80211_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_VENDOR_MODULE := true
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+include $(BUILD_HEADER_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcld80211
+LOCAL_CLANG := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES += $(LOCAL_PATH) \
+ external/libnl/include
+LOCAL_SHARED_LIBRARIES := libcutils libnl liblog
+LOCAL_SRC_FILES := cld80211_lib.c
+LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
+LOCAL_HEADER_LIBRARIES := libcld80211_headers
+LOCAL_VENDOR_MODULE := true
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+include $(BUILD_SHARED_LIBRARY)
diff --git a/wcn6740/cld80211-lib/Makefile.am b/wcn6740/cld80211-lib/Makefile.am
new file mode 100644
index 0000000..19cdc49
--- /dev/null
+++ b/wcn6740/cld80211-lib/Makefile.am
@@ -0,0 +1,27 @@
+# Makefile.am - Automake script for cld80211-lib
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS = -Wall
+
+if DEBUG
+AM_CFLAGS += -g
+else
+AM_CFLAGS += -O2
+endif
+
+AM_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast \
+ -Wno-maybe-uninitialized -Wno-parentheses -DLE_BUILD \
+ -D_GNU_SOURCE=1
+
+h_sources = cld80211_lib.h
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(h_sources)
+
+libcld80211_la_SOURCES = cld80211_lib.c
+libcld80211_la_CFLAGS = ${AM_CFLAGS} ${LIBNL_CFLAGS}
+libcld80211_la_LIBADD = ${LIBNL_LIBS}
+lib_LTLIBRARIES = libcld80211.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = cld80211-lib.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/wcn6740/cld80211-lib/cld80211-lib.pc.in b/wcn6740/cld80211-lib/cld80211-lib.pc.in
new file mode 100644
index 0000000..c611c64
--- /dev/null
+++ b/wcn6740/cld80211-lib/cld80211-lib.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: cld80211-lib
+Description: "cld80211 Library"
+Version: @VERSION@
+Libs: -L${libdir} -lcld80211
+Cflags: -I${includedir}/@PACKAGE@
diff --git a/cld80211-lib/cld80211_lib.c b/wcn6740/cld80211-lib/cld80211_lib.c
similarity index 93%
copy from cld80211-lib/cld80211_lib.c
copy to wcn6740/cld80211-lib/cld80211_lib.c
index 5c8255b..bc082a9 100644
--- a/cld80211-lib/cld80211_lib.c
+++ b/wcn6740/cld80211-lib/cld80211_lib.c
@@ -5,7 +5,7 @@
* Copyright (c) 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
* Copyright (c) 2009-2010, Atheros Communications
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -38,11 +38,22 @@
#include <netlink/genl/ctrl.h>
#include <linux/pkt_sched.h>
#include <unistd.h>
-#include <log/log.h>
#include "cld80211_lib.h"
-#undef LOG_TAG
-#define LOG_TAG "CLD80211"
+#ifndef LE_BUILD
+ #include <log/log.h>
+ #undef LOG_TAG
+ #define LOG_TAG "CLD80211"
+#else
+ #include <stdlib.h>
+ #include <syslog.h>
+ #include <unistd.h>
+ #define ALOGI(fmt, args...) syslog(LOG_INFO, fmt, ## args)
+ #define ALOGE(fmt, args...) syslog(LOG_ERR, fmt, ## args)
+ extern const char *__progname;
+ const char *getprogname() { return (__progname); }
+#endif
+
#define SOCK_BUF_SIZE (256*1024)
struct family_data {
@@ -225,7 +236,7 @@
}
-static int get_multicast_id(struct cld80211_ctx *ctx, const char *group, bool sync_driver)
+static int get_multicast_id(struct cld80211_ctx *ctx, const char *group)
{
struct family_data res = { group, -ENOENT };
struct nl_msg *nlmsg = nlmsg_alloc();
@@ -238,11 +249,9 @@
CTRL_CMD_GETFAMILY, 0);
nla_put_string(nlmsg, CTRL_ATTR_FAMILY_NAME, "cld80211");
- if (sync_driver == true) {
- cld80211_send_recv_msg(ctx, nlmsg, family_handler, &res);
- ALOGI("%s: nlctrl family id: %d group: %s mcast_id: %d", getprogname(),
- ctx->nlctrl_familyid, group, res.id);
- }
+ cld80211_send_recv_msg(ctx, nlmsg, family_handler, &res);
+ ALOGI("%s: nlctrl family id: %d group: %s mcast_id: %d", getprogname(),
+ ctx->nlctrl_familyid, group, res.id);
nlmsg_free(nlmsg);
return res.id;
}
@@ -254,7 +263,7 @@
ALOGE("%s: ctx/mcgroup is NULL: %s", getprogname(), __func__);
return 0;
}
- int id = get_multicast_id(ctx, mcgroup, true);
+ int id = get_multicast_id(ctx, mcgroup);
if (id < 0) {
ALOGE("%s: Could not find group %s, errno: %d id: %d",
getprogname(), mcgroup, errno, id);
@@ -273,11 +282,13 @@
int cld80211_remove_mcast_group(struct cld80211_ctx *ctx, const char* mcgroup)
{
+ // Drop membership is not a necessary cleanup action so comment it out.
+#if 0
if (!ctx || !mcgroup) {
ALOGE("%s: ctx/mcgroup is NULL: %s", getprogname(), __func__);
return 0;
}
- int id = get_multicast_id(ctx, mcgroup, false);
+ int id = get_multicast_id(ctx, mcgroup);
if (id < 0) {
ALOGE("%s: Could not find group %s, errno: %d id: %d",
getprogname(), mcgroup, errno, id);
@@ -290,7 +301,7 @@
" ret: %d", getprogname(), mcgroup, errno, ret);
return ret;
}
-
+#endif
return 0;
}
@@ -315,7 +326,7 @@
0, 0, cmd, /* version = */ 0);
*nla_data = nla_nest_start(nlmsg, CLD80211_ATTR_VENDOR_DATA);
- if (!nla_data)
+ if (!*nla_data)
goto cleanup;
return nlmsg;
@@ -446,7 +457,7 @@
}
-struct cld80211_ctx * cld80211_init()
+struct cld80211_ctx * cld80211_init(void)
{
struct cld80211_ctx *ctx;
diff --git a/cld80211-lib/cld80211_lib.h b/wcn6740/cld80211-lib/cld80211_lib.h
similarity index 93%
copy from cld80211-lib/cld80211_lib.h
copy to wcn6740/cld80211-lib/cld80211_lib.h
index 3dd53bb..2503f2a 100644
--- a/cld80211-lib/cld80211_lib.h
+++ b/wcn6740/cld80211-lib/cld80211_lib.h
@@ -58,6 +58,10 @@
* CLD80211_ATTR_META_DATA: Embed meta data for above data. This will help
* wlan driver to peek into request message packet without opening up definition
* of complete request message.
+ * @CLD80211_ATTR_CMD: cld80211 vendor subcommand in this attribute
+ * @CLD80211_ATTR_CMD_TAG_DATA: cld80211 vendor subcommand data is present in
+ * this attribute. It is a nested attribute with sub attributes of specified
+ * vendor sub command.
*
* Any new message in future can be added as another attribute
*/
@@ -65,6 +69,8 @@
CLD80211_ATTR_VENDOR_DATA = 1,
CLD80211_ATTR_DATA,
CLD80211_ATTR_META_DATA,
+ CLD80211_ATTR_CMD,
+ CLD80211_ATTR_CMD_TAG_DATA,
__CLD80211_ATTR_AFTER_LAST,
CLD80211_ATTR_MAX = __CLD80211_ATTR_AFTER_LAST - 1
@@ -75,7 +81,7 @@
* Retuns valid sock only if socket creation is succesful and cld80211
* family is present, returns NULL otherwise
*/
-struct cld80211_ctx *cld80211_init();
+struct cld80211_ctx *cld80211_init(void);
/**
* free the socket created in cld80211_init()
diff --git a/wcn6740/cld80211-lib/configure.ac b/wcn6740/cld80211-lib/configure.ac
new file mode 100644
index 0000000..7996d3f
--- /dev/null
+++ b/wcn6740/cld80211-lib/configure.ac
@@ -0,0 +1,77 @@
+# -*- Autoconf -*-
+# configure.ac -- Autoconf script for qcacld-tools
+#
+
+AC_PREREQ(2.61)
+AC_INIT([cld80211-lib], 1.0.0)
+AM_INIT_AUTOMAKE([foreign])
+AM_MAINTAINER_MODE
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+LT_INIT
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+AC_ARG_ENABLE([debug],
+ [ --enable-debug Turn on debugging],
+ [case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+ esac],[debug=false])
+AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
+
+has_libnl_ver=0
+# libnl-2 provides only libnl-2.0.pc file, so we check for separate libnl-genl-3.0.pc
+# pkg-config file just for libnl-3.0 case.
+#
+PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.0 libnl-genl-3.0 >= 3.0], [has_libnl_ver=3], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-2.0 >= 2.0], [has_libnl_ver=2], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-1], [has_libnl_ver=1], [has_libnl_ver=0])])])
+
+if (test "$has_libnl_ver" -eq 0); then
+ AC_MSG_ERROR(libnl and libnl-genl are required but were not found)
+fi
+
+if (test "$has_libnl_ver" -gt 1); then
+ AC_DEFINE([HAVE_LIBNL20], [1], [Define if you have libnl-2.0 or higher])
+fi
+
+if (test "$has_libnl_ver" -gt 2); then
+ AC_DEFINE([HAVE_LIBNL30], [1], [Define if you have libnl-3.0 or higher])
+fi
+
+AC_SUBST([LIBNL_CFLAGS])
+AC_SUBST([LIBNL_LIBS])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_HEADER_STDC
+AC_C_INLINE
+AC_TYPE_INT64_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ cld80211-lib.pc
+])
+AC_OUTPUT
diff --git a/qcwcn/Android.mk b/wcn6740/qcwcn/Android.mk
similarity index 100%
copy from qcwcn/Android.mk
copy to wcn6740/qcwcn/Android.mk
diff --git a/qcwcn/config/Android.mk b/wcn6740/qcwcn/config/Android.mk
similarity index 100%
copy from qcwcn/config/Android.mk
copy to wcn6740/qcwcn/config/Android.mk
diff --git a/wcn6740/qcwcn/wifi_hal/Android.mk b/wcn6740/qcwcn/wifi_hal/Android.mk
new file mode 100644
index 0000000..7cb6611
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/Android.mk
@@ -0,0 +1,203 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# Control APIs used by clients to communicate with HAL.
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_MODULE := libwifi-hal-ctrl
+LOCAL_VENDOR_MODULE := true
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/wifi_hal_ctrl
+LOCAL_SRC_FILES := wifi_hal_ctrl/wifi_hal_ctrl.c
+LOCAL_HEADER_LIBRARIES := libcutils_headers
+LOCAL_LICENSE_KINDS := legacy_not_a_contribution SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwifi-hal-ctrl_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/wifi_hal_ctrl
+LOCAL_HEADER_LIBRARIES := libcutils_headers
+LOCAL_LICENSE_KINDS := legacy_not_a_contribution SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+include $(BUILD_HEADER_LIBRARY)
+
+# Make the HAL library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -Wno-unused-parameter
+ifeq ($(TARGET_BUILD_VARIANT),userdebug)
+LOCAL_CFLAGS += "-DLOG_NDEBUG=0"
+endif
+
+ifneq ($(TARGET_USES_AOSP_FOR_WLAN), true)
+LOCAL_CFLAGS += -DWCNSS_QTI_AOSP
+endif
+
+# gscan.cpp: address of array 'cached_results[i].results' will always evaluate to 'true'
+LOCAL_CLANG_CFLAGS := -Wno-pointer-bool-conversion
+
+LOCAL_CFLAGS += -Wall -Werror
+
+ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\"
+ifdef WIFI_DRIVER_STATE_ON
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\"
+endif
+endif
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH) \
+ external/libnl/include \
+ $(call include-path-for, libhardware_legacy)/hardware_legacy \
+ external/wpa_supplicant_8/src/drivers \
+ $(TARGET_OUT_HEADERS)/cld80211-lib
+
+LOCAL_C_INCLUDES += \
+ external/boringssl/include \
+ external/boringssl/src/crypto/digest \
+ external/boringssl/src/crypto/evp/
+
+LOCAL_SRC_FILES := \
+ list.cpp \
+ wifi_hal.cpp \
+ common.cpp \
+ cpp_bindings.cpp \
+ llstats.cpp \
+ gscan.cpp \
+ gscan_event_handler.cpp \
+ rtt.cpp \
+ ifaceeventhandler.cpp \
+ tdls.cpp \
+ nan.cpp \
+ nan_ind.cpp \
+ nan_req.cpp \
+ nan_rsp.cpp \
+ wificonfig.cpp \
+ wifilogger.cpp \
+ wifilogger_diag.cpp \
+ ring_buffer.cpp \
+ rb_wrapper.cpp \
+ rssi_monitor.cpp \
+ roam.cpp \
+ radio_mode.cpp \
+ tcp_params_update.cpp \
+ wifihal_vendor.cpp
+
+LOCAL_MODULE := libwifi-hal-qcom
+LOCAL_VENDOR_MODULE := true
+LOCAL_CLANG := true
+LOCAL_SHARED_LIBRARIES += libnetutils liblog libcld80211
+LOCAL_SHARED_LIBRARIES += libcrypto
+
+ifneq ($(wildcard external/libnl),)
+LOCAL_SHARED_LIBRARIES += libnl
+LOCAL_C_INCLUDES += external/libnl/include
+else
+LOCAL_SHARED_LIBRARIES += libnl_2
+LOCAL_C_INCLUDES += external/libnl-headers
+endif
+
+LOCAL_HEADER_LIBRARIES := libcutils_headers libutils_headers libwifi-hal-ctrl_headers libcld80211_headers
+LOCAL_SANITIZE := cfi
+
+LOCAL_LICENSE_KINDS := legacy_not_a_contribution SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_REQUIRED_MODULES :=
+
+LOCAL_CFLAGS += -Wno-unused-parameter -Wall -Werror
+LOCAL_CPPFLAGS += -Wno-conversion-null
+ifeq ($(TARGET_BUILD_VARIANT),userdebug)
+LOCAL_CFLAGS += "-DLOG_NDEBUG=0"
+endif
+
+# gscan.cpp: address of array 'cached_results[i].results' will always evaluate to 'true'
+LOCAL_CLANG_CFLAGS := -Wno-pointer-bool-conversion
+
+ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\"
+ifdef WIFI_DRIVER_STATE_ON
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\"
+endif
+endif
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH) \
+ external/libnl/include \
+ $(call include-path-for, libhardware_legacy)/hardware_legacy \
+ external/wpa_supplicant_8/src/drivers \
+ $(TARGET_OUT_HEADERS)/cld80211-lib
+
+LOCAL_C_INCLUDES += \
+ external/boringssl/include \
+ external/boringssl/src/crypto/digest \
+ external/boringssl/src/crypto/evp/
+
+LOCAL_SRC_FILES := \
+ list.cpp \
+ wifi_hal.cpp \
+ common.cpp \
+ cpp_bindings.cpp \
+ llstats.cpp \
+ gscan.cpp \
+ gscan_event_handler.cpp \
+ rtt.cpp \
+ ifaceeventhandler.cpp \
+ tdls.cpp \
+ nan.cpp \
+ nan_ind.cpp \
+ nan_req.cpp \
+ nan_rsp.cpp \
+ wificonfig.cpp \
+ wifilogger.cpp \
+ wifilogger_diag.cpp \
+ ring_buffer.cpp \
+ rb_wrapper.cpp \
+ rssi_monitor.cpp \
+ roam.cpp \
+ radio_mode.cpp \
+ tcp_params_update.cpp \
+ wifihal_vendor.cpp
+
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_MODULE := libwifi-hal-qcom
+LOCAL_VENDOR_MODULE := true
+LOCAL_CLANG := true
+LOCAL_SHARED_LIBRARIES += libnetutils liblog
+LOCAL_SHARED_LIBRARIES += libdl libcld80211
+LOCAL_SHARED_LIBRARIES += libwifi-hal-ctrl
+LOCAL_SHARED_LIBRARIES += libcrypto
+
+ifneq ($(wildcard external/libnl),)
+LOCAL_SHARED_LIBRARIES += libnl
+LOCAL_C_INCLUDES += external/libnl/include
+else
+LOCAL_SHARED_LIBRARIES += libnl_2
+LOCAL_C_INCLUDES += external/libnl-headers
+endif
+
+LOCAL_HEADER_LIBRARIES := libcutils_headers libutils_headers libwifi-hal-ctrl_headers libcld80211_headers
+LOCAL_SANITIZE := cfi integer_overflow
+LOCAL_LICENSE_KINDS := legacy_not_a_contribution SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+include $(BUILD_SHARED_LIBRARY)
diff --git a/wcn6740/qcwcn/wifi_hal/common.cpp b/wcn6740/qcwcn/wifi_hal/common.cpp
new file mode 100644
index 0000000..263043b
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/common.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <linux/pkt_sched.h>
+#include <linux-private/linux/fib_rules.h>
+#include <netlink/object-api.h>
+#include <netlink-private/object-api.h>
+#include <netlink-private/types.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include "wifi_hal.h"
+#include "common.h"
+#include <errno.h>
+
+interface_info *getIfaceInfo(wifi_interface_handle handle)
+{
+ return (interface_info *)handle;
+}
+
+wifi_handle getWifiHandle(wifi_interface_handle handle)
+{
+ return getIfaceInfo(handle)->handle;
+}
+
+hal_info *getHalInfo(wifi_handle handle)
+{
+ return (hal_info *)handle;
+}
+
+hal_info *getHalInfo(wifi_interface_handle handle)
+{
+ return getHalInfo(getWifiHandle(handle));
+}
+
+wifi_handle getWifiHandle(hal_info *info)
+{
+ return (wifi_handle)info;
+}
+
+wifi_interface_handle getIfaceHandle(interface_info *info)
+{
+ return (wifi_interface_handle)info;
+}
+
+wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
+{
+ hal_info *info = (hal_info *)handle;
+
+ pthread_mutex_lock(&info->cb_lock);
+
+ wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
+
+ for (int i = 0; i < info->num_event_cb; i++) {
+ if(info->event_cb[i].nl_cmd == cmd &&
+ info->event_cb[i].cb_arg == arg) {
+ info->event_cb[i].cb_func = func;
+ ALOGV("Updated event handler %p for nl_cmd 0x%0x"
+ " and arg %p", func, cmd, arg);
+ pthread_mutex_unlock(&info->cb_lock);
+ return WIFI_SUCCESS;
+ }
+ }
+
+ if (info->num_event_cb < info->alloc_event_cb) {
+ info->event_cb[info->num_event_cb].nl_cmd = cmd;
+ info->event_cb[info->num_event_cb].vendor_id = 0;
+ info->event_cb[info->num_event_cb].vendor_subcmd = 0;
+ info->event_cb[info->num_event_cb].cb_func = func;
+ info->event_cb[info->num_event_cb].cb_arg = arg;
+ info->num_event_cb++;
+ ALOGV("Successfully added event handler %p for command %d", func, cmd);
+ result = WIFI_SUCCESS;
+ } else {
+ result = WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ pthread_mutex_unlock(&info->cb_lock);
+ return result;
+}
+
+wifi_error wifi_register_vendor_handler(wifi_handle handle,
+ uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
+{
+ hal_info *info = (hal_info *)handle;
+
+ pthread_mutex_lock(&info->cb_lock);
+
+ wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
+
+ for (int i = 0; i < info->num_event_cb; i++) {
+ if(info->event_cb[i].vendor_id == id &&
+ info->event_cb[i].vendor_subcmd == subcmd)
+ {
+ info->event_cb[i].cb_func = func;
+ info->event_cb[i].cb_arg = arg;
+ ALOGV("Updated event handler %p for vendor 0x%0x, subcmd 0x%0x"
+ " and arg %p", func, id, subcmd, arg);
+ pthread_mutex_unlock(&info->cb_lock);
+ return WIFI_SUCCESS;
+ }
+ }
+
+ if (info->num_event_cb < info->alloc_event_cb) {
+ info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
+ info->event_cb[info->num_event_cb].vendor_id = id;
+ info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
+ info->event_cb[info->num_event_cb].cb_func = func;
+ info->event_cb[info->num_event_cb].cb_arg = arg;
+ info->num_event_cb++;
+ ALOGV("Added event handler %p for vendor 0x%0x, subcmd 0x%0x and arg"
+ " %p", func, id, subcmd, arg);
+ result = WIFI_SUCCESS;
+ } else {
+ result = WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ pthread_mutex_unlock(&info->cb_lock);
+ return result;
+}
+
+void wifi_unregister_handler(wifi_handle handle, int cmd)
+{
+ hal_info *info = (hal_info *)handle;
+
+ if (cmd == NL80211_CMD_VENDOR) {
+ ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers");
+ return;
+ }
+
+ pthread_mutex_lock(&info->cb_lock);
+
+ for (int i = 0; i < info->num_event_cb; i++) {
+ if (info->event_cb[i].nl_cmd == cmd) {
+ if(i < info->num_event_cb-1) {
+ /* No need to memmove if only one entry exist and deleting
+ * the same, as the num_event_cb will become 0 in this case.
+ */
+ memmove(&info->event_cb[i], &info->event_cb[i+1],
+ (info->num_event_cb - i) * sizeof(cb_info));
+ }
+ info->num_event_cb--;
+ ALOGV("Successfully removed event handler for command %d", cmd);
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&info->cb_lock);
+}
+
+void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
+{
+ hal_info *info = (hal_info *)handle;
+
+ pthread_mutex_lock(&info->cb_lock);
+
+ for (int i = 0; i < info->num_event_cb; i++) {
+
+ if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
+ && info->event_cb[i].vendor_id == id
+ && info->event_cb[i].vendor_subcmd == subcmd) {
+ if(i < info->num_event_cb-1) {
+ /* No need to memmove if only one entry exist and deleting
+ * the same, as the num_event_cb will become 0 in this case.
+ */
+ memmove(&info->event_cb[i], &info->event_cb[i+1],
+ (info->num_event_cb - i) * sizeof(cb_info));
+ }
+ info->num_event_cb--;
+ ALOGV("Successfully removed event handler for vendor 0x%0x", id);
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&info->cb_lock);
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+void hexdump(void *buf, u16 len)
+{
+ int i=0;
+ char *bytes = (char *)buf;
+
+ if (len) {
+ ALOGV("******HexDump len:%d*********", len);
+ for (i = 0; ((i + 7) < len); i+=8) {
+ ALOGV("%02x %02x %02x %02x %02x %02x %02x %02x",
+ bytes[i], bytes[i+1],
+ bytes[i+2], bytes[i+3],
+ bytes[i+4], bytes[i+5],
+ bytes[i+6], bytes[i+7]);
+ }
+ if ((len - i) >= 4) {
+ ALOGV("%02x %02x %02x %02x",
+ bytes[i], bytes[i+1],
+ bytes[i+2], bytes[i+3]);
+ i+=4;
+ }
+ for (;i < len;i++) {
+ ALOGV("%02x", bytes[i]);
+ }
+ ALOGV("******HexDump End***********");
+ } else {
+ return;
+ }
+}
+
+/* Firmware sends RSSI value without noise floor.
+ * Add noise floor to the same and return absolute values.
+ */
+u8 get_rssi(u8 rssi_wo_noise_floor)
+{
+ return abs((int)rssi_wo_noise_floor - 96);
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/* Pointer to the table of LOWI callback funcs */
+lowi_cb_table_t *LowiWifiHalApi = NULL;
+/* LowiSupportedCapabilities read */
+u32 lowiSupportedCapabilities = 0;
+
+int compareLowiVersion(u16 major, u16 minor, u16 micro)
+{
+ u32 currVersion = 0x10000*(WIFIHAL_LOWI_MAJOR_VERSION) + \
+ 0x100*(WIFIHAL_LOWI_MINOR_VERSION) + \
+ WIFIHAL_LOWI_MICRO_VERSION;
+
+ u32 lowiVersion = 0x10000*(major) + \
+ 0x100*(minor) + \
+ micro;
+
+ return (memcmp(&currVersion, &lowiVersion, sizeof(u32)));
+}
+
+/*
+ * This function will open the lowi shared library and obtain the
+ * Lowi Callback table and the capabilities supported.
+ * A version check is also performed in this function and if the version
+ * check fails then the callback table returned will be NULL.
+ */
+wifi_error fetchLowiCbTableAndCapabilities(lowi_cb_table_t **lowi_wifihal_api,
+ bool *lowi_get_capa_supported)
+{
+ getCbTable_t* lowiCbTable = NULL;
+ int ret = 0;
+ wifi_error retVal = WIFI_SUCCESS;
+
+ *lowi_wifihal_api = NULL;
+ *lowi_get_capa_supported = false;
+
+#if __WORDSIZE == 64
+ void* lowi_handle = dlopen("/vendor/lib64/liblowi_wifihal.so", RTLD_NOW);
+#else
+ void* lowi_handle = dlopen("/vendor/lib/liblowi_wifihal.so", RTLD_NOW);
+#endif
+ if (!lowi_handle) {
+ ALOGE("%s: NULL lowi_handle, err: %s", __FUNCTION__, dlerror());
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ lowiCbTable = (getCbTable_t*)dlsym(lowi_handle,
+ "lowi_wifihal_get_cb_table");
+ if (!lowiCbTable) {
+ ALOGE("%s: NULL lowi callback table", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ *lowi_wifihal_api = lowiCbTable();
+
+ /* First check whether lowi module implements the get_lowi_version
+ * function. All the functions in lowi module starts with
+ * "lowi_wifihal_" prefix thus the below function name.
+ */
+ if ((dlsym(lowi_handle, "lowi_wifihal_get_lowi_version") != NULL) &&
+ ((*lowi_wifihal_api)->get_lowi_version != NULL)) {
+ u16 lowiMajorVersion = WIFIHAL_LOWI_MAJOR_VERSION;
+ u16 lowiMinorVersion = WIFIHAL_LOWI_MINOR_VERSION;
+ u16 lowiMicroVersion = WIFIHAL_LOWI_MICRO_VERSION;
+ int versionCheck = -1;
+
+ ret = (*lowi_wifihal_api)->get_lowi_version(&lowiMajorVersion,
+ &lowiMinorVersion,
+ &lowiMicroVersion);
+ if (ret) {
+ ALOGE("%s: get_lowi_version returned error:%d",
+ __FUNCTION__, ret);
+ retVal = WIFI_ERROR_NOT_SUPPORTED;
+ goto cleanup;
+ }
+ ALOGV("%s: Lowi version:%d.%d.%d", __FUNCTION__,
+ lowiMajorVersion, lowiMinorVersion,
+ lowiMicroVersion);
+
+ /* Compare the version with version in wifihal_internal.h */
+ versionCheck = compareLowiVersion(lowiMajorVersion,
+ lowiMinorVersion,
+ lowiMicroVersion);
+ if (versionCheck < 0) {
+ ALOGE("%s: Version Check failed:%d", __FUNCTION__,
+ versionCheck);
+ retVal = WIFI_ERROR_NOT_SUPPORTED;
+ goto cleanup;
+ }
+ }
+ else {
+ ALOGV("%s: lowi_wifihal_get_lowi_version not present",
+ __FUNCTION__);
+ }
+
+
+ /* Check if get_lowi_capabilities func pointer exists in
+ * the lowi lib and populate lowi_get_capa_supported
+ * All the functions in lowi modules starts with
+ * "lowi_wifihal_ prefix" thus the below function name.
+ */
+ if (dlsym(lowi_handle, "lowi_wifihal_get_lowi_capabilities") != NULL) {
+ *lowi_get_capa_supported = true;
+ }
+ else {
+ ALOGV("lowi_wifihal_get_lowi_capabilities() is not supported.");
+ *lowi_get_capa_supported = false;
+ }
+cleanup:
+ if (retVal) {
+ *lowi_wifihal_api = NULL;
+ }
+ return retVal;
+}
+
+lowi_cb_table_t *getLowiCallbackTable(u32 requested_lowi_capabilities)
+{
+ int ret = WIFI_SUCCESS;
+ bool lowi_get_capabilities_support = false;
+
+ if (LowiWifiHalApi == NULL) {
+ ALOGV("%s: LowiWifiHalApi Null, Initialize Lowi",
+ __FUNCTION__);
+ ret = fetchLowiCbTableAndCapabilities(&LowiWifiHalApi,
+ &lowi_get_capabilities_support);
+ if (ret != WIFI_SUCCESS || LowiWifiHalApi == NULL ||
+ LowiWifiHalApi->init == NULL) {
+ ALOGE("%s: LOWI is not supported.", __FUNCTION__);
+ goto cleanup;
+ }
+ /* Initialize LOWI if it isn't up already. */
+ ret = LowiWifiHalApi->init();
+ if (ret) {
+ ALOGE("%s: failed lowi initialization. "
+ "Returned error:%d. Exit.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ if (!lowi_get_capabilities_support ||
+ LowiWifiHalApi->get_lowi_capabilities == NULL) {
+ ALOGV("%s: Allow rtt APIs thru LOWI to proceed even though "
+ "get_lowi_capabilities() is not supported. Returning",
+ __FUNCTION__);
+ lowiSupportedCapabilities |=
+ (ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ return LowiWifiHalApi;
+ }
+ ret =
+ LowiWifiHalApi->get_lowi_capabilities(&lowiSupportedCapabilities);
+ if (ret) {
+ ALOGV("%s: failed to get lowi supported capabilities."
+ "Returned error:%d. Exit.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ } else if (lowiSupportedCapabilities == 0 &&
+ LowiWifiHalApi->get_lowi_capabilities) {
+ LowiWifiHalApi->get_lowi_capabilities(&lowiSupportedCapabilities);
+ }
+
+ if ((lowiSupportedCapabilities & requested_lowi_capabilities) == 0) {
+ return NULL;
+ }
+ return LowiWifiHalApi;
+
+cleanup:
+ if (LowiWifiHalApi && LowiWifiHalApi->destroy) {
+ ret = LowiWifiHalApi->destroy();
+ }
+ LowiWifiHalApi = NULL;
+ lowiSupportedCapabilities = 0;
+ return LowiWifiHalApi;
+}
+
+wifi_error mapKernelErrortoWifiHalError(int kern_err)
+{
+ if (kern_err >= 0)
+ return WIFI_SUCCESS;
+
+ switch (kern_err) {
+ case -EOPNOTSUPP:
+ return WIFI_ERROR_NOT_SUPPORTED;
+ case -EAGAIN:
+ return WIFI_ERROR_NOT_AVAILABLE;
+ case -EINVAL:
+ return WIFI_ERROR_INVALID_ARGS;
+ case -ETIMEDOUT:
+ return WIFI_ERROR_TIMED_OUT;
+ case -ENOMEM:
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ case -EBUSY:
+ return WIFI_ERROR_BUSY;
+ case -ENOBUFS:
+ return WIFI_ERROR_TOO_MANY_REQUESTS;
+ }
+ return WIFI_ERROR_UNKNOWN;
+}
diff --git a/qcwcn/wifi_hal/common.h b/wcn6740/qcwcn/wifi_hal/common.h
similarity index 75%
copy from qcwcn/wifi_hal/common.h
copy to wcn6740/qcwcn/wifi_hal/common.h
index b0aca97..8816f5f 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/wcn6740/qcwcn/wifi_hal/common.h
@@ -12,6 +12,40 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#include "wifi_hal.h"
@@ -53,6 +87,7 @@
#define RECV_BUF_SIZE (4096)
#define DEFAULT_EVENT_CB_SIZE (64)
#define NUM_RING_BUFS 5
+#define MAX_NUM_RADAR_HISTORY 64
#define WIFI_HAL_CTRL_IFACE "/dev/socket/wifihal/wifihal_ctrlsock"
@@ -161,6 +196,7 @@
u32 prev_seq_no;
// pointer to structure having various gscan_event_handlers
struct gscan_event_handlers_s *gscan_handlers;
+ struct tcp_param_cmd_handler_s *tcp_param_handler;
/* mutex for the log_handler access*/
pthread_mutex_t lh_lock;
/* mutex for the alert_handler access*/
@@ -171,12 +207,26 @@
/* mutex for the packet fate stats shared resource protection */
pthread_mutex_t pkt_fate_stats_lock;
struct rssi_monitor_event_handler_s *rssi_handlers;
+ struct radio_event_handler_s *radio_handlers;
wifi_capa capa;
struct cld80211_ctx *cldctx;
bool apf_enabled;
+ bool support_nan_ext_cmd;
pkt_log_version pkt_log_ver;
+ qca_wlan_vendor_sar_version sar_version;
} hal_info;
+typedef struct {
+ bool radar_detected;
+ u32 freq;
+ u64 clock_boottime;
+} radar_history_result;
+
+static inline void wifi_put_le16(u8 *a, u16 val) {
+ a[1] = val >> 8;
+ a[0] = val & 0xff;
+}
+
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
wifi_error wifi_register_vendor_handler(wifi_handle handle,
uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg);
@@ -194,12 +244,14 @@
wifi_error cleanupGscanHandlers(hal_info *info);
wifi_error initializeRSSIMonitorHandler(hal_info *info);
wifi_error cleanupRSSIMonitorHandler(hal_info *info);
+wifi_error initializeRadioHandler(hal_info *info);
+wifi_error cleanupRadioHandler(hal_info *info);
lowi_cb_table_t *getLowiCallbackTable(u32 requested_lowi_capabilities);
wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
- wifi_interface_handle iface, u16 ether_type, u8 *ip_packet,
- u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec);
+ wifi_interface_handle iface, u8 *ip_packet, u16 ip_packet_len,
+ u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec);
wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
wifi_interface_handle iface);
wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
@@ -212,6 +264,9 @@
wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
wifi_interface_type iface_type);
wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname);
+wifi_error wifi_get_radar_history(wifi_interface_handle handle,
+ radar_history_result *resultBuf, int resultBufSize, int *numResults);
+wifi_error wifi_disable_next_cac(wifi_interface_handle handle);
// some common macros
#define min(x, y) ((x) < (y) ? (x) : (y))
diff --git a/wcn6740/qcwcn/wifi_hal/cpp_bindings.cpp b/wcn6740/qcwcn/wifi_hal/cpp_bindings.cpp
new file mode 100644
index 0000000..4ac01b7
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/cpp_bindings.cpp
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
+ */
+
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <net/if.h>
+
+#include "nl80211_copy.h"
+#include <ctype.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "vendor_definitions.h"
+
+void appendFmt(char *buf, size_t buf_len, int &offset, const char *fmt, ...)
+{
+ va_list params;
+ va_start(params, fmt);
+ offset += vsnprintf(buf + offset, buf_len - offset, fmt, params);
+ va_end(params);
+}
+
+#define C2S(x) case x: return #x;
+
+static const char *cmdToString(int cmd)
+{
+ switch (cmd) {
+ C2S(NL80211_CMD_UNSPEC)
+ C2S(NL80211_CMD_GET_WIPHY)
+ C2S(NL80211_CMD_SET_WIPHY)
+ C2S(NL80211_CMD_NEW_WIPHY)
+ C2S(NL80211_CMD_DEL_WIPHY)
+ C2S(NL80211_CMD_GET_INTERFACE)
+ C2S(NL80211_CMD_SET_INTERFACE)
+ C2S(NL80211_CMD_NEW_INTERFACE)
+ C2S(NL80211_CMD_DEL_INTERFACE)
+ C2S(NL80211_CMD_GET_KEY)
+ C2S(NL80211_CMD_SET_KEY)
+ C2S(NL80211_CMD_NEW_KEY)
+ C2S(NL80211_CMD_DEL_KEY)
+ C2S(NL80211_CMD_GET_BEACON)
+ C2S(NL80211_CMD_SET_BEACON)
+ C2S(NL80211_CMD_START_AP)
+ C2S(NL80211_CMD_STOP_AP)
+ C2S(NL80211_CMD_GET_STATION)
+ C2S(NL80211_CMD_SET_STATION)
+ C2S(NL80211_CMD_NEW_STATION)
+ C2S(NL80211_CMD_DEL_STATION)
+ C2S(NL80211_CMD_GET_MPATH)
+ C2S(NL80211_CMD_SET_MPATH)
+ C2S(NL80211_CMD_NEW_MPATH)
+ C2S(NL80211_CMD_DEL_MPATH)
+ C2S(NL80211_CMD_SET_BSS)
+ C2S(NL80211_CMD_SET_REG)
+ C2S(NL80211_CMD_REQ_SET_REG)
+ C2S(NL80211_CMD_GET_MESH_CONFIG)
+ C2S(NL80211_CMD_SET_MESH_CONFIG)
+ C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
+ C2S(NL80211_CMD_GET_REG)
+ C2S(NL80211_CMD_GET_SCAN)
+ C2S(NL80211_CMD_TRIGGER_SCAN)
+ C2S(NL80211_CMD_NEW_SCAN_RESULTS)
+ C2S(NL80211_CMD_SCAN_ABORTED)
+ C2S(NL80211_CMD_REG_CHANGE)
+ C2S(NL80211_CMD_AUTHENTICATE)
+ C2S(NL80211_CMD_ASSOCIATE)
+ C2S(NL80211_CMD_DEAUTHENTICATE)
+ C2S(NL80211_CMD_DISASSOCIATE)
+ C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
+ C2S(NL80211_CMD_REG_BEACON_HINT)
+ C2S(NL80211_CMD_JOIN_IBSS)
+ C2S(NL80211_CMD_LEAVE_IBSS)
+ C2S(NL80211_CMD_TESTMODE)
+ C2S(NL80211_CMD_CONNECT)
+ C2S(NL80211_CMD_ROAM)
+ C2S(NL80211_CMD_DISCONNECT)
+ C2S(NL80211_CMD_SET_WIPHY_NETNS)
+ C2S(NL80211_CMD_GET_SURVEY)
+ C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
+ C2S(NL80211_CMD_SET_PMKSA)
+ C2S(NL80211_CMD_DEL_PMKSA)
+ C2S(NL80211_CMD_FLUSH_PMKSA)
+ C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
+ C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
+ C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
+ C2S(NL80211_CMD_REGISTER_FRAME)
+ C2S(NL80211_CMD_FRAME)
+ C2S(NL80211_CMD_FRAME_TX_STATUS)
+ C2S(NL80211_CMD_SET_POWER_SAVE)
+ C2S(NL80211_CMD_GET_POWER_SAVE)
+ C2S(NL80211_CMD_SET_CQM)
+ C2S(NL80211_CMD_NOTIFY_CQM)
+ C2S(NL80211_CMD_SET_CHANNEL)
+ C2S(NL80211_CMD_SET_WDS_PEER)
+ C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
+ C2S(NL80211_CMD_JOIN_MESH)
+ C2S(NL80211_CMD_LEAVE_MESH)
+ C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
+ C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
+ C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
+ C2S(NL80211_CMD_GET_WOWLAN)
+ C2S(NL80211_CMD_SET_WOWLAN)
+ C2S(NL80211_CMD_START_SCHED_SCAN)
+ C2S(NL80211_CMD_STOP_SCHED_SCAN)
+ C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
+ C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
+ C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
+ C2S(NL80211_CMD_PMKSA_CANDIDATE)
+ C2S(NL80211_CMD_TDLS_OPER)
+ C2S(NL80211_CMD_TDLS_MGMT)
+ C2S(NL80211_CMD_UNEXPECTED_FRAME)
+ C2S(NL80211_CMD_PROBE_CLIENT)
+ C2S(NL80211_CMD_REGISTER_BEACONS)
+ C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
+ C2S(NL80211_CMD_SET_NOACK_MAP)
+ C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
+ C2S(NL80211_CMD_START_P2P_DEVICE)
+ C2S(NL80211_CMD_STOP_P2P_DEVICE)
+ C2S(NL80211_CMD_CONN_FAILED)
+ C2S(NL80211_CMD_SET_MCAST_RATE)
+ C2S(NL80211_CMD_SET_MAC_ACL)
+ C2S(NL80211_CMD_RADAR_DETECT)
+ C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
+ C2S(NL80211_CMD_UPDATE_FT_IES)
+ C2S(NL80211_CMD_FT_EVENT)
+ C2S(NL80211_CMD_CRIT_PROTOCOL_START)
+ C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
+ C2S(NL80211_CMD_GET_COALESCE)
+ C2S(NL80211_CMD_SET_COALESCE)
+ C2S(NL80211_CMD_CHANNEL_SWITCH)
+ C2S(NL80211_CMD_VENDOR)
+ C2S(NL80211_CMD_SET_QOS_MAP)
+ default:
+ return "NL80211_CMD_UNKNOWN";
+ }
+}
+
+const char *attributeToString(int attribute)
+{
+ switch (attribute) {
+ C2S(NL80211_ATTR_UNSPEC)
+
+ C2S(NL80211_ATTR_WIPHY)
+ C2S(NL80211_ATTR_WIPHY_NAME)
+
+ C2S(NL80211_ATTR_IFINDEX)
+ C2S(NL80211_ATTR_IFNAME)
+ C2S(NL80211_ATTR_IFTYPE)
+
+ C2S(NL80211_ATTR_MAC)
+
+ C2S(NL80211_ATTR_KEY_DATA)
+ C2S(NL80211_ATTR_KEY_IDX)
+ C2S(NL80211_ATTR_KEY_CIPHER)
+ C2S(NL80211_ATTR_KEY_SEQ)
+ C2S(NL80211_ATTR_KEY_DEFAULT)
+
+ C2S(NL80211_ATTR_BEACON_INTERVAL)
+ C2S(NL80211_ATTR_DTIM_PERIOD)
+ C2S(NL80211_ATTR_BEACON_HEAD)
+ C2S(NL80211_ATTR_BEACON_TAIL)
+
+ C2S(NL80211_ATTR_STA_AID)
+ C2S(NL80211_ATTR_STA_FLAGS)
+ C2S(NL80211_ATTR_STA_LISTEN_INTERVAL)
+ C2S(NL80211_ATTR_STA_SUPPORTED_RATES)
+ C2S(NL80211_ATTR_STA_VLAN)
+ C2S(NL80211_ATTR_STA_INFO)
+
+ C2S(NL80211_ATTR_WIPHY_BANDS)
+
+ C2S(NL80211_ATTR_MNTR_FLAGS)
+
+ C2S(NL80211_ATTR_MESH_ID)
+ C2S(NL80211_ATTR_STA_PLINK_ACTION)
+ C2S(NL80211_ATTR_MPATH_NEXT_HOP)
+ C2S(NL80211_ATTR_MPATH_INFO)
+
+ C2S(NL80211_ATTR_BSS_CTS_PROT)
+ C2S(NL80211_ATTR_BSS_SHORT_PREAMBLE)
+ C2S(NL80211_ATTR_BSS_SHORT_SLOT_TIME)
+
+ C2S(NL80211_ATTR_HT_CAPABILITY)
+
+ C2S(NL80211_ATTR_SUPPORTED_IFTYPES)
+
+ C2S(NL80211_ATTR_REG_ALPHA2)
+ C2S(NL80211_ATTR_REG_RULES)
+
+ C2S(NL80211_ATTR_MESH_CONFIG)
+
+ C2S(NL80211_ATTR_BSS_BASIC_RATES)
+
+ C2S(NL80211_ATTR_WIPHY_TXQ_PARAMS)
+ C2S(NL80211_ATTR_WIPHY_FREQ)
+ C2S(NL80211_ATTR_WIPHY_CHANNEL_TYPE)
+
+ C2S(NL80211_ATTR_KEY_DEFAULT_MGMT)
+
+ C2S(NL80211_ATTR_MGMT_SUBTYPE)
+ C2S(NL80211_ATTR_IE)
+
+ C2S(NL80211_ATTR_MAX_NUM_SCAN_SSIDS)
+
+ C2S(NL80211_ATTR_SCAN_FREQUENCIES)
+ C2S(NL80211_ATTR_SCAN_SSIDS)
+ C2S(NL80211_ATTR_GENERATION) /* replaces old SCAN_GENERATION */
+ C2S(NL80211_ATTR_BSS)
+
+ C2S(NL80211_ATTR_REG_INITIATOR)
+ C2S(NL80211_ATTR_REG_TYPE)
+
+ C2S(NL80211_ATTR_SUPPORTED_COMMANDS)
+
+ C2S(NL80211_ATTR_FRAME)
+ C2S(NL80211_ATTR_SSID)
+ C2S(NL80211_ATTR_AUTH_TYPE)
+ C2S(NL80211_ATTR_REASON_CODE)
+
+ C2S(NL80211_ATTR_KEY_TYPE)
+
+ C2S(NL80211_ATTR_MAX_SCAN_IE_LEN)
+ C2S(NL80211_ATTR_CIPHER_SUITES)
+
+ C2S(NL80211_ATTR_FREQ_BEFORE)
+ C2S(NL80211_ATTR_FREQ_AFTER)
+
+ C2S(NL80211_ATTR_FREQ_FIXED)
+
+
+ C2S(NL80211_ATTR_WIPHY_RETRY_SHORT)
+ C2S(NL80211_ATTR_WIPHY_RETRY_LONG)
+ C2S(NL80211_ATTR_WIPHY_FRAG_THRESHOLD)
+ C2S(NL80211_ATTR_WIPHY_RTS_THRESHOLD)
+
+ C2S(NL80211_ATTR_TIMED_OUT)
+
+ C2S(NL80211_ATTR_USE_MFP)
+
+ C2S(NL80211_ATTR_STA_FLAGS2)
+
+ C2S(NL80211_ATTR_CONTROL_PORT)
+
+ C2S(NL80211_ATTR_TESTDATA)
+
+ C2S(NL80211_ATTR_PRIVACY)
+
+ C2S(NL80211_ATTR_DISCONNECTED_BY_AP)
+ C2S(NL80211_ATTR_STATUS_CODE)
+
+ C2S(NL80211_ATTR_CIPHER_SUITES_PAIRWISE)
+ C2S(NL80211_ATTR_CIPHER_SUITE_GROUP)
+ C2S(NL80211_ATTR_WPA_VERSIONS)
+ C2S(NL80211_ATTR_AKM_SUITES)
+
+ C2S(NL80211_ATTR_REQ_IE)
+ C2S(NL80211_ATTR_RESP_IE)
+
+ C2S(NL80211_ATTR_PREV_BSSID)
+
+ C2S(NL80211_ATTR_KEY)
+ C2S(NL80211_ATTR_KEYS)
+
+ C2S(NL80211_ATTR_PID)
+
+ C2S(NL80211_ATTR_4ADDR)
+
+ C2S(NL80211_ATTR_SURVEY_INFO)
+
+ C2S(NL80211_ATTR_PMKID)
+ C2S(NL80211_ATTR_MAX_NUM_PMKIDS)
+
+ C2S(NL80211_ATTR_DURATION)
+
+ C2S(NL80211_ATTR_COOKIE)
+
+ C2S(NL80211_ATTR_WIPHY_COVERAGE_CLASS)
+
+ C2S(NL80211_ATTR_TX_RATES)
+
+ C2S(NL80211_ATTR_FRAME_MATCH)
+
+ C2S(NL80211_ATTR_ACK)
+
+ C2S(NL80211_ATTR_PS_STATE)
+
+ C2S(NL80211_ATTR_CQM)
+
+ C2S(NL80211_ATTR_LOCAL_STATE_CHANGE)
+
+ C2S(NL80211_ATTR_AP_ISOLATE)
+
+ C2S(NL80211_ATTR_WIPHY_TX_POWER_SETTING)
+ C2S(NL80211_ATTR_WIPHY_TX_POWER_LEVEL)
+
+ C2S(NL80211_ATTR_TX_FRAME_TYPES)
+ C2S(NL80211_ATTR_RX_FRAME_TYPES)
+ C2S(NL80211_ATTR_FRAME_TYPE)
+
+ C2S(NL80211_ATTR_CONTROL_PORT_ETHERTYPE)
+ C2S(NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)
+
+ C2S(NL80211_ATTR_SUPPORT_IBSS_RSN)
+
+ C2S(NL80211_ATTR_WIPHY_ANTENNA_TX)
+ C2S(NL80211_ATTR_WIPHY_ANTENNA_RX)
+
+ C2S(NL80211_ATTR_MCAST_RATE)
+
+ C2S(NL80211_ATTR_OFFCHANNEL_TX_OK)
+
+ C2S(NL80211_ATTR_BSS_HT_OPMODE)
+
+ C2S(NL80211_ATTR_KEY_DEFAULT_TYPES)
+
+ C2S(NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION)
+
+ C2S(NL80211_ATTR_MESH_SETUP)
+
+ C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX)
+ C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX)
+
+ C2S(NL80211_ATTR_SUPPORT_MESH_AUTH)
+ C2S(NL80211_ATTR_STA_PLINK_STATE)
+
+ C2S(NL80211_ATTR_WOWLAN_TRIGGERS)
+ C2S(NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED)
+
+ C2S(NL80211_ATTR_SCHED_SCAN_INTERVAL)
+
+ C2S(NL80211_ATTR_INTERFACE_COMBINATIONS)
+ C2S(NL80211_ATTR_SOFTWARE_IFTYPES)
+
+ C2S(NL80211_ATTR_REKEY_DATA)
+
+ C2S(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS)
+ C2S(NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN)
+
+ C2S(NL80211_ATTR_SCAN_SUPP_RATES)
+
+ C2S(NL80211_ATTR_HIDDEN_SSID)
+
+ C2S(NL80211_ATTR_IE_PROBE_RESP)
+ C2S(NL80211_ATTR_IE_ASSOC_RESP)
+
+ C2S(NL80211_ATTR_STA_WME)
+ C2S(NL80211_ATTR_SUPPORT_AP_UAPSD)
+
+ C2S(NL80211_ATTR_ROAM_SUPPORT)
+
+ C2S(NL80211_ATTR_SCHED_SCAN_MATCH)
+ C2S(NL80211_ATTR_MAX_MATCH_SETS)
+
+ C2S(NL80211_ATTR_PMKSA_CANDIDATE)
+
+ C2S(NL80211_ATTR_TX_NO_CCK_RATE)
+
+ C2S(NL80211_ATTR_TDLS_ACTION)
+ C2S(NL80211_ATTR_TDLS_DIALOG_TOKEN)
+ C2S(NL80211_ATTR_TDLS_OPERATION)
+ C2S(NL80211_ATTR_TDLS_SUPPORT)
+ C2S(NL80211_ATTR_TDLS_EXTERNAL_SETUP)
+
+ C2S(NL80211_ATTR_DEVICE_AP_SME)
+
+ C2S(NL80211_ATTR_DONT_WAIT_FOR_ACK)
+
+ C2S(NL80211_ATTR_FEATURE_FLAGS)
+
+ C2S(NL80211_ATTR_PROBE_RESP_OFFLOAD)
+
+ C2S(NL80211_ATTR_PROBE_RESP)
+
+ C2S(NL80211_ATTR_DFS_REGION)
+
+ C2S(NL80211_ATTR_DISABLE_HT)
+ C2S(NL80211_ATTR_HT_CAPABILITY_MASK)
+
+ C2S(NL80211_ATTR_NOACK_MAP)
+
+ C2S(NL80211_ATTR_INACTIVITY_TIMEOUT)
+
+ C2S(NL80211_ATTR_RX_SIGNAL_DBM)
+
+ C2S(NL80211_ATTR_BG_SCAN_PERIOD)
+
+ C2S(NL80211_ATTR_WDEV)
+
+ C2S(NL80211_ATTR_USER_REG_HINT_TYPE)
+
+ C2S(NL80211_ATTR_CONN_FAILED_REASON)
+
+ C2S(NL80211_ATTR_SAE_DATA)
+
+ C2S(NL80211_ATTR_VHT_CAPABILITY)
+
+ C2S(NL80211_ATTR_SCAN_FLAGS)
+
+ C2S(NL80211_ATTR_CHANNEL_WIDTH)
+ C2S(NL80211_ATTR_CENTER_FREQ1)
+ C2S(NL80211_ATTR_CENTER_FREQ2)
+
+ C2S(NL80211_ATTR_P2P_CTWINDOW)
+ C2S(NL80211_ATTR_P2P_OPPPS)
+
+ C2S(NL80211_ATTR_LOCAL_MESH_POWER_MODE)
+
+ C2S(NL80211_ATTR_ACL_POLICY)
+
+ C2S(NL80211_ATTR_MAC_ADDRS)
+
+ C2S(NL80211_ATTR_MAC_ACL_MAX)
+
+ C2S(NL80211_ATTR_RADAR_EVENT)
+
+ C2S(NL80211_ATTR_EXT_CAPA)
+ C2S(NL80211_ATTR_EXT_CAPA_MASK)
+
+ C2S(NL80211_ATTR_STA_CAPABILITY)
+ C2S(NL80211_ATTR_STA_EXT_CAPABILITY)
+
+ C2S(NL80211_ATTR_PROTOCOL_FEATURES)
+ C2S(NL80211_ATTR_SPLIT_WIPHY_DUMP)
+
+ C2S(NL80211_ATTR_DISABLE_VHT)
+ C2S(NL80211_ATTR_VHT_CAPABILITY_MASK)
+
+ C2S(NL80211_ATTR_MDID)
+ C2S(NL80211_ATTR_IE_RIC)
+
+ C2S(NL80211_ATTR_CRIT_PROT_ID)
+ C2S(NL80211_ATTR_MAX_CRIT_PROT_DURATION)
+
+ C2S(NL80211_ATTR_PEER_AID)
+
+ C2S(NL80211_ATTR_COALESCE_RULE)
+
+ C2S(NL80211_ATTR_CH_SWITCH_COUNT)
+ C2S(NL80211_ATTR_CH_SWITCH_BLOCK_TX)
+ C2S(NL80211_ATTR_CSA_IES)
+ C2S(NL80211_ATTR_CSA_C_OFF_BEACON)
+ C2S(NL80211_ATTR_CSA_C_OFF_PRESP)
+
+ C2S(NL80211_ATTR_RXMGMT_FLAGS)
+
+ C2S(NL80211_ATTR_STA_SUPPORTED_CHANNELS)
+
+ C2S(NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES)
+
+ C2S(NL80211_ATTR_HANDLE_DFS)
+
+ C2S(NL80211_ATTR_SUPPORT_5_MHZ)
+ C2S(NL80211_ATTR_SUPPORT_10_MHZ)
+
+ C2S(NL80211_ATTR_OPMODE_NOTIF)
+
+ C2S(NL80211_ATTR_VENDOR_ID)
+ C2S(NL80211_ATTR_VENDOR_SUBCMD)
+ C2S(NL80211_ATTR_VENDOR_DATA)
+ C2S(NL80211_ATTR_VENDOR_EVENTS)
+
+ C2S(NL80211_ATTR_QOS_MAP)
+ default:
+ return "NL80211_ATTR_UNKNOWN";
+ }
+}
+
+void WifiEvent::log() {
+ parse();
+
+ byte *data = (byte *)genlmsg_attrdata(mHeader, 0);
+ int len = genlmsg_attrlen(mHeader, 0);
+
+ for (int i = 0; i < len; i += 16) {
+ char line[81];
+ int linelen = min(16, len - i);
+ int offset = 0;
+ appendFmt(line, sizeof(line), offset, "%02x", data[i]);
+ for (int j = 1; j < linelen; j++) {
+ appendFmt(line, sizeof(line), offset, " %02x", data[i+j]);
+ }
+
+ for (int j = linelen; j < 16; j++) {
+ appendFmt(line, sizeof(line), offset, " ");
+ }
+
+ line[23] = '-';
+
+ appendFmt(line, sizeof(line), offset, " ");
+
+ for (int j = 0; j < linelen; j++) {
+ if (isprint(data[i+j])) {
+ appendFmt(line, sizeof(line), offset, "%c", data[i+j]);
+ } else {
+ appendFmt(line, sizeof(line), offset, "-");
+ }
+ }
+
+ }
+
+}
+
+const char *WifiEvent::get_cmdString() {
+ return cmdToString(get_cmd());
+}
+
+
+int WifiEvent::parse() {
+ if (mHeader != NULL) {
+ return WIFI_SUCCESS;
+ }
+ mHeader = (genlmsghdr *)nlmsg_data(nlmsg_hdr(mMsg));
+ int result = nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(mHeader, 0),
+ genlmsg_attrlen(mHeader, 0), NULL);
+
+ return result;
+}
+
+wifi_error WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) {
+
+ destroy();
+
+ mMsg = nlmsg_alloc();
+ if (mMsg != NULL) {
+ genlmsg_put(mMsg, /* pid = */ 0, /* seq = */ 0, family,
+ hdrlen, flags, cmd, /* version = */ 0);
+ return WIFI_SUCCESS;
+ } else {
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+}
+
+wifi_error WifiRequest::create(uint32_t id, int subcmd) {
+ wifi_error res = create(NL80211_CMD_VENDOR);
+ if (res != WIFI_SUCCESS)
+ return res;
+
+ res = put_u32(NL80211_ATTR_VENDOR_ID, id);
+ if (res != WIFI_SUCCESS)
+ return res;
+
+ res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd);
+ if (res != WIFI_SUCCESS)
+ return res;
+
+ if (mIface != -1)
+ res = set_iface_id(mIface);
+
+ return res;
+}
+
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+wifi_error WifiCommand::requestResponse()
+{
+ wifi_error err = create(); /* create the message */
+ if (err != WIFI_SUCCESS)
+ return err;
+
+ return requestResponse(mMsg);
+}
+
+wifi_error WifiCommand::requestResponse(WifiRequest& request)
+{
+ int err = 0;
+
+ struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ goto out;
+
+ err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* 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);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, response_handler, this);
+
+ while (err > 0) { /* wait for reply */
+ int res = nl_recvmsgs(mInfo->cmd_sock, cb);
+ if (res) {
+ ALOGE("nl80211: %s->nl_recvmsgs failed: %d", __FUNCTION__, res);
+ }
+ }
+out:
+ nl_cb_put(cb);
+ mMsg.destroy();
+ return mapKernelErrortoWifiHalError(err);
+}
+
+wifi_error WifiCommand::requestEvent(int cmd)
+{
+
+ int status;
+ wifi_error res = wifi_register_handler(wifiHandle(), cmd, event_handler,
+ this);
+ if (res != WIFI_SUCCESS)
+ return res;
+
+ res = create(); /* create the message */
+ if (res != WIFI_SUCCESS)
+ goto out;
+
+ status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */
+ if (status < 0) {
+ res = mapKernelErrortoWifiHalError(status);
+ goto out;
+ }
+
+ res = mCondition.wait();
+ if (res != WIFI_SUCCESS)
+ goto out;
+
+out:
+ wifi_unregister_handler(wifiHandle(), cmd);
+ return res;
+}
+
+wifi_error WifiCommand::requestVendorEvent(uint32_t id, int subcmd) {
+ int status;
+ wifi_error res = wifi_register_vendor_handler(wifiHandle(), id, subcmd,
+ event_handler, this);
+ if (res != WIFI_SUCCESS)
+ return res;
+
+ res = create(); /* create the message */
+ if (res != WIFI_SUCCESS)
+ goto out;
+
+ status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */
+ if (status < 0) {
+ res = mapKernelErrortoWifiHalError(status);
+ goto out;
+ }
+
+ res = mCondition.wait();
+ if (res != WIFI_SUCCESS)
+ goto out;
+
+out:
+ wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
+ return res;
+}
+
+/* Event handlers */
+int WifiCommand::response_handler(struct nl_msg *msg, void *arg) {
+ WifiCommand *cmd = (WifiCommand *)arg;
+ WifiEvent reply(msg);
+ int res = reply.parse();
+ if (res < 0) {
+ ALOGE("Failed to parse reply message = %d", res);
+ return NL_SKIP;
+ } else {
+ // reply.log(); /* Don't call log() to avoid excess WiFi HAL logging */
+ return cmd->handleResponse(reply);
+ }
+}
+
+int WifiCommand::event_handler(struct nl_msg *msg, void *arg) {
+ WifiCommand *cmd = (WifiCommand *)arg;
+ WifiEvent event(msg);
+ int res = event.parse();
+ if (res < 0) {
+ ALOGE("Failed to parse event = %d", res);
+ res = NL_SKIP;
+ } else {
+ res = cmd->handleEvent(event);
+ }
+
+ cmd->mCondition.signal();
+ return res;
+}
+
+/* Other event handlers */
+int WifiCommand::valid_handler(struct nl_msg *msg, void *arg) {
+ int *err = (int *)arg;
+ *err = 0;
+ return NL_SKIP;
+}
+
+int WifiCommand::ack_handler(struct nl_msg *msg, void *arg) {
+ int *err = (int *)arg;
+ *err = 0;
+ return NL_STOP;
+}
+
+int WifiCommand::finish_handler(struct nl_msg *msg, void *arg) {
+ int *ret = (int *)arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+int WifiCommand::error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
+ int *ret = (int *)arg;
+ *ret = err->error;
+
+ return NL_SKIP;
+}
+
+
+WifiVendorCommand::WifiVendorCommand(wifi_handle handle,
+ wifi_request_id id,
+ u32 vendor_id,
+ u32 subcmd)
+ : WifiCommand(handle, id), mVendor_id(vendor_id), mSubcmd(subcmd),
+ mVendorData(NULL), mDataLen(0)
+{
+ ALOGV("WifiVendorCommand %p created vendor_id:0x%x subcmd:%u",
+ this, mVendor_id, mSubcmd);
+}
+
+WifiVendorCommand::~WifiVendorCommand()
+{
+ //ALOGV("~WifiVendorCommand %p destroyed", this);
+ //mVendorData is not destroyed here. Assumption
+ //is that VendorData is specific to each Vendor and they
+ //are responsible for owning the same.
+}
+
+// Override this method to parse reply and dig out data; save it
+// in the corresponding object
+int WifiVendorCommand::handleResponse(WifiEvent &reply)
+{
+ struct nlattr **tb = reply.attributes();
+ struct genlmsghdr *gnlh = reply.header();
+
+ if (gnlh->cmd == NL80211_CMD_VENDOR) {
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ mVendorData = (char *)nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
+ mDataLen = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
+ }
+ }
+ return NL_SKIP;
+}
+
+// Override this method to parse event and dig out data;
+// save it in the object
+int WifiVendorCommand::handleEvent(WifiEvent &event)
+{
+ struct nlattr **tb = event.attributes();
+ struct genlmsghdr *gnlh = event.header();
+
+ if (gnlh->cmd == NL80211_CMD_VENDOR) {
+ /* Vendor Event */
+ if (!tb[NL80211_ATTR_VENDOR_ID] ||
+ !tb[NL80211_ATTR_VENDOR_SUBCMD])
+ return NL_SKIP;
+
+ mVendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
+ mSubcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
+
+ ALOGV("%s: Vendor event: vendor_id=0x%x subcmd=%u",
+ __FUNCTION__, mVendor_id, mSubcmd);
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ mVendorData = (char *)nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
+ mDataLen = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
+ ALOGV("%s: Vendor data len received:%d", __FUNCTION__, mDataLen);
+ hexdump(mVendorData, mDataLen);
+ }
+ }
+ return NL_SKIP;
+}
+
+wifi_error WifiVendorCommand::create() {
+ int ifindex;
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ // insert the oui in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+ // insert the subcmd in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+ //Insert the vendor specific data
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+ hexdump(mVendorData, mDataLen);
+
+ //insert the iface id to be "wlan0"
+ ifindex = if_nametoindex("wlan0");
+ ret = mMsg.set_iface_id(ifindex);
+out:
+ return ret;
+}
+
+wifi_error WifiVendorCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+wifi_error WifiVendorCommand::requestEvent()
+{
+ wifi_error res = requestVendorEvent(mVendor_id, mSubcmd);
+ return res;
+}
+
+wifi_error WifiVendorCommand::put_u8(int attribute, uint8_t value)
+{
+ return mMsg.put_u8(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_u16(int attribute, uint16_t value)
+{
+ return mMsg.put_u16(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_u32(int attribute, uint32_t value)
+{
+ return mMsg.put_u32(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_u64(int attribute, uint64_t value)
+{
+ return mMsg.put_u64(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_s8(int attribute, s8 value)
+{
+ return mMsg.put_s8(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_s16(int attribute, s16 value)
+{
+ return mMsg.put_s16(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_s32(int attribute, s32 value)
+{
+ return mMsg.put_s32(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_s64(int attribute, s64 value)
+{
+ return mMsg.put_s64(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_flag(int attribute)
+{
+ return mMsg.put_flag(attribute);
+}
+
+u8 WifiVendorCommand::get_u8(const struct nlattr *nla)
+{
+ return mMsg.get_u8(nla);
+}
+
+u16 WifiVendorCommand::get_u16(const struct nlattr *nla)
+{
+ return mMsg.get_u16(nla);
+}
+
+u32 WifiVendorCommand::get_u32(const struct nlattr *nla)
+{
+ return mMsg.get_u32(nla);
+}
+
+u64 WifiVendorCommand::get_u64(const struct nlattr *nla)
+{
+ return mMsg.get_u64(nla);
+}
+
+s8 WifiVendorCommand::get_s8(const struct nlattr *nla)
+{
+ return mMsg.get_s8(nla);
+}
+
+s16 WifiVendorCommand::get_s16(const struct nlattr *nla)
+{
+ return mMsg.get_s16(nla);
+}
+
+s32 WifiVendorCommand::get_s32(const struct nlattr *nla)
+{
+ return mMsg.get_s32(nla);
+}
+
+s64 WifiVendorCommand::get_s64(const struct nlattr *nla)
+{
+ return mMsg.get_s64(nla);
+}
+
+wifi_error WifiVendorCommand::put_ipv6_addr(int attribute, uint8_t value[16])
+{
+ return mMsg.put_ipv6_addr(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_string(int attribute, const char *value)
+{
+ return mMsg.put_string(attribute, value);
+}
+
+wifi_error WifiVendorCommand::put_addr(int attribute, mac_addr value)
+{
+ return mMsg.put_addr(attribute, value);
+}
+
+struct nlattr * WifiVendorCommand::attr_start(int attribute)
+{
+ return mMsg.attr_start(attribute);
+}
+
+void WifiVendorCommand::attr_end(struct nlattr *attribute)
+{
+ return mMsg.attr_end(attribute);
+}
+
+wifi_error WifiVendorCommand::set_iface_id(const char* name)
+{
+ unsigned ifindex = if_nametoindex(name);
+ return mMsg.set_iface_id(ifindex);
+}
+
+wifi_error WifiVendorCommand::put_bytes(int attribute,
+ const char *data,
+ int len)
+{
+ return mMsg.put_bytes(attribute, data, len);
+}
+
+wifi_error WifiVendorCommand::get_mac_addr(struct nlattr **tb_vendor,
+ int attribute,
+ mac_addr addr)
+{
+ if (!tb_vendor[attribute]) {
+ ALOGE("Failed to get attribute : %d", attribute);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (!addr) {
+ ALOGE("addr is NULL");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (nla_len(tb_vendor[attribute]) != sizeof(mac_addr)) {
+ ALOGE("Invalid mac addr lenght\n");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ memcpy(addr, (u8 *)nla_data(tb_vendor[attribute]),
+ nla_len(tb_vendor[attribute]));
+
+ return WIFI_SUCCESS;
+}
+
+wifi_error initialize_vendor_cmd(wifi_interface_handle iface,
+ wifi_request_id id,
+ u32 subcmd,
+ WifiVendorCommand **vCommand)
+{
+ wifi_error ret;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ if (vCommand == NULL) {
+ ALOGE("%s: Error vCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ *vCommand = new WifiVendorCommand(wifiHandle, id,
+ OUI_QCA,
+ subcmd);
+ if (*vCommand == NULL) {
+ ALOGE("%s: Object creation failed", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Create the message */
+ ret = (*vCommand)->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = (*vCommand)->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ return WIFI_SUCCESS;
+
+cleanup:
+ delete *vCommand;
+ return ret;
+}
diff --git a/wcn6740/qcwcn/wifi_hal/cpp_bindings.h b/wcn6740/qcwcn/wifi_hal/cpp_bindings.h
new file mode 100644
index 0000000..4ddb93e
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/cpp_bindings.h
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
+ */
+
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __WIFI_HAL_CPP_BINDINGS_H__
+#define __WIFI_HAL_CPP_BINDINGS_H__
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "sync.h"
+
+class WifiEvent
+{
+ /* TODO: remove this when nl headers are updated */
+ static const unsigned NL80211_ATTR_MAX_INTERNAL = 256;
+private:
+ struct nl_msg *mMsg;
+ struct genlmsghdr *mHeader;
+ struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
+
+public:
+ WifiEvent(nl_msg *msg) {
+ mMsg = msg;
+ mHeader = NULL;
+ memset(mAttributes, 0, sizeof(mAttributes));
+ }
+ ~WifiEvent() {
+ /* don't destroy mMsg; it doesn't belong to us */
+ }
+
+ void log();
+
+ int parse();
+
+ genlmsghdr *header() {
+ return mHeader;
+ }
+
+ int get_cmd() {
+ return mHeader->cmd;
+ }
+
+ int get_vendor_id() {
+ return get_u32(NL80211_ATTR_VENDOR_ID);
+ }
+
+ int get_vendor_subcmd() {
+ return get_u32(NL80211_ATTR_VENDOR_SUBCMD);
+ }
+
+ void *get_vendor_data() {
+ return get_data(NL80211_ATTR_VENDOR_DATA);
+ }
+
+ int get_vendor_data_len() {
+ return get_len(NL80211_ATTR_VENDOR_DATA);
+ }
+
+ const char *get_cmdString();
+
+ nlattr ** attributes() {
+ return mAttributes;
+ }
+
+ nlattr *get_attribute(int attribute) {
+ return mAttributes[attribute];
+ }
+
+ uint8_t get_u8(int attribute) {
+ return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0;
+ }
+
+ uint16_t get_u16(int attribute) {
+ return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0;
+ }
+
+ uint32_t get_u32(int attribute) {
+ return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0;
+ }
+
+ uint64_t get_u64(int attribute) {
+ return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0;
+ }
+
+ int get_len(int attribute) {
+ return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0;
+ }
+
+ void *get_data(int attribute) {
+ return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
+ }
+
+private:
+ WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies
+};
+
+class nl_iterator {
+ struct nlattr *pos;
+ int rem;
+public:
+ nl_iterator(struct nlattr *attr) {
+ pos = (struct nlattr *)nla_data(attr);
+ rem = nla_len(attr);
+ }
+ bool has_next() {
+ return nla_ok(pos, rem);
+ }
+ void next() {
+ pos = (struct nlattr *)nla_next(pos, &(rem));
+ }
+ struct nlattr *get() {
+ return pos;
+ }
+ uint16_t get_type() {
+ return pos->nla_type;
+ }
+ uint8_t get_u8() {
+ return nla_get_u8(pos);
+ }
+ uint16_t get_u16() {
+ return nla_get_u16(pos);
+ }
+ uint32_t get_u32() {
+ return nla_get_u32(pos);
+ }
+ uint64_t get_u64() {
+ return nla_get_u64(pos);
+ }
+ void* get_data() {
+ return nla_data(pos);
+ }
+ int get_len() {
+ return nla_len(pos);
+ }
+private:
+ nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies
+};
+
+class WifiRequest
+{
+private:
+ int mFamily;
+ int mIface;
+ struct nl_msg *mMsg;
+
+public:
+ WifiRequest(int family) {
+ mMsg = NULL;
+ mFamily = family;
+ mIface = -1;
+ }
+
+ WifiRequest(int family, int iface) {
+ mMsg = NULL;
+ mFamily = family;
+ mIface = iface;
+ }
+
+ ~WifiRequest() {
+ destroy();
+ }
+
+ void destroy() {
+ if (mMsg) {
+ nlmsg_free(mMsg);
+ mMsg = NULL;
+ }
+ }
+
+ nl_msg *getMessage() {
+ return mMsg;
+ }
+
+ /* Command assembly helpers */
+ wifi_error create(int family, uint8_t cmd, int flags, int hdrlen);
+ wifi_error create(uint8_t cmd, int flags, int hdrlen) {
+ return create(mFamily, cmd, flags, hdrlen);
+ }
+ wifi_error create(uint8_t cmd) {
+ return create(mFamily, cmd, 0, 0);
+ }
+
+ wifi_error create(uint32_t id, int subcmd);
+
+ wifi_error wifi_nla_put(struct nl_msg *msg, int attr,
+ int attrlen, const void *data)
+ {
+ int status;
+
+ status = nla_put(msg, attr, attrlen, data);
+ if (status < 0)
+ ALOGE("Failed to put attr with size = %d, type = %d, error = %d",
+ attrlen, attr, status);
+ return mapKernelErrortoWifiHalError(status);
+ }
+ wifi_error put_u8(int attribute, uint8_t value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(value), &value);
+ }
+ wifi_error put_u16(int attribute, uint16_t value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(value), &value);
+ }
+ wifi_error put_u32(int attribute, uint32_t value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(value), &value);
+ }
+
+ wifi_error put_u64(int attribute, uint64_t value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(value), &value);
+ }
+
+ wifi_error put_s8(int attribute, s8 value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(int8_t), &value);
+ }
+ wifi_error put_s16(int attribute, s16 value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(int16_t), &value);
+ }
+ wifi_error put_s32(int attribute, s32 value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(int32_t), &value);
+ }
+ wifi_error put_s64(int attribute, s64 value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(int64_t), &value);
+ }
+ wifi_error put_flag(int attribute) {
+ int status;
+
+ status = nla_put_flag(mMsg, attribute);
+ if(status < 0)
+ ALOGE("Failed to put flag attr of type = %d, error = %d",
+ attribute, status);
+ return mapKernelErrortoWifiHalError(status);
+ }
+
+ u8 get_u8(const struct nlattr *nla)
+ {
+ return *(u8 *) nla_data(nla);
+ }
+ u16 get_u16(const struct nlattr *nla)
+ {
+ return *(u16 *) nla_data(nla);
+ }
+ u32 get_u32(const struct nlattr *nla)
+ {
+ return *(u32 *) nla_data(nla);
+ }
+ u64 get_u64(const struct nlattr *nla)
+ {
+ return *(u64 *) nla_data(nla);
+ }
+
+ s8 get_s8(const struct nlattr *nla)
+ {
+ return *(s8 *) nla_data(nla);
+ }
+
+ s16 get_s16(const struct nlattr *nla)
+ {
+ return *(s16 *) nla_data(nla);
+ }
+ s32 get_s32(const struct nlattr *nla)
+ {
+ return *(s32 *) nla_data(nla);
+ }
+ s64 get_s64(const struct nlattr *nla)
+ {
+ return *(s64 *) nla_data(nla);
+ }
+
+ wifi_error put_ipv6_addr(int attribute, uint8_t *value) {
+ return wifi_nla_put(mMsg, attribute, 16, value);
+ }
+
+ wifi_error put_string(int attribute, const char *value) {
+ return wifi_nla_put(mMsg, attribute, strlen(value) + 1, value);
+ }
+ wifi_error put_addr(int attribute, mac_addr value) {
+ return wifi_nla_put(mMsg, attribute, sizeof(mac_addr), value);
+ }
+
+ struct nlattr * attr_start(int attribute) {
+ return nla_nest_start(mMsg, attribute);
+ }
+ void attr_end(struct nlattr *attr) {
+ nla_nest_end(mMsg, attr);
+ }
+
+ wifi_error set_iface_id(int ifindex) {
+ return put_u32(NL80211_ATTR_IFINDEX, ifindex);
+ }
+
+ wifi_error put_bytes(int attribute, const char *data, int len) {
+ return wifi_nla_put(mMsg, attribute, len, data);
+ }
+
+private:
+ WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies
+
+};
+
+class WifiCommand
+{
+protected:
+ hal_info *mInfo;
+ WifiRequest mMsg;
+ Condition mCondition;
+ wifi_request_id mId;
+ interface_info *mIfaceInfo;
+public:
+ WifiCommand(wifi_handle handle, wifi_request_id id)
+ : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id)
+ {
+ mIfaceInfo = NULL;
+ mInfo = getHalInfo(handle);
+ }
+
+ WifiCommand(wifi_interface_handle iface, wifi_request_id id)
+ : mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), mId(id)
+ {
+ mIfaceInfo = getIfaceInfo(iface);
+ mInfo = getHalInfo(iface);
+ }
+
+ virtual ~WifiCommand() {
+ }
+
+ wifi_request_id id() {
+ return mId;
+ }
+
+ virtual wifi_error create() {
+ /* by default there is no way to cancel */
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ virtual wifi_error cancel() {
+ /* by default there is no way to cancel */
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ wifi_error requestResponse();
+ wifi_error requestEvent(int cmd);
+ wifi_error requestVendorEvent(uint32_t id, int subcmd);
+ wifi_error requestResponse(WifiRequest& request);
+
+protected:
+ wifi_handle wifiHandle() {
+ return getWifiHandle(mInfo);
+ }
+
+ wifi_interface_handle ifaceHandle() {
+ return getIfaceHandle(mIfaceInfo);
+ }
+
+ int familyId() {
+ return mInfo->nl80211_family_id;
+ }
+
+ int ifaceId() {
+ return mIfaceInfo->id;
+ }
+
+ /* Override this method to parse reply and dig out data; save it in the object */
+ virtual int handleResponse(WifiEvent& reply) {
+ UNUSED(reply);
+ return NL_SKIP;
+ }
+
+ /* Override this method to parse event and dig out data; save it in the object */
+ virtual int handleEvent(WifiEvent& event) {
+ UNUSED(event);
+ return NL_SKIP;
+ }
+
+ int registerHandler(int cmd) {
+ return wifi_register_handler(wifiHandle(), cmd, &event_handler, this);
+ }
+
+ void unregisterHandler(int cmd) {
+ wifi_unregister_handler(wifiHandle(), cmd);
+ }
+
+ wifi_error registerVendorHandler(uint32_t id, int subcmd) {
+ return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
+ }
+
+ void unregisterVendorHandler(uint32_t id, int subcmd) {
+ wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
+ }
+
+private:
+ WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies
+
+ /* Event handling */
+ static int response_handler(struct nl_msg *msg, void *arg);
+
+ static int event_handler(struct nl_msg *msg, void *arg);
+
+ /* Other event handlers */
+ static int valid_handler(struct nl_msg *msg, void *arg);
+
+ static int ack_handler(struct nl_msg *msg, void *arg);
+
+ static int finish_handler(struct nl_msg *msg, void *arg);
+
+ static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
+};
+
+//WifiVendorCommand class
+class WifiVendorCommand: public WifiCommand
+{
+protected:
+ u32 mVendor_id;
+ u32 mSubcmd;
+ char *mVendorData;
+ u32 mDataLen;
+
+
+public:
+ WifiVendorCommand(wifi_handle handle, wifi_request_id id, u32 vendor_id, u32 subcmd);
+
+ virtual ~WifiVendorCommand();
+
+ virtual wifi_error create();
+
+ virtual wifi_error requestResponse();
+
+ virtual wifi_error requestEvent();
+
+ virtual wifi_error put_u8(int attribute, uint8_t value);
+
+ virtual wifi_error put_u16(int attribute, uint16_t value);
+
+ virtual wifi_error put_u32(int attribute, uint32_t value);
+
+ virtual wifi_error put_u64(int attribute, uint64_t value);
+
+ virtual wifi_error put_s8(int attribute, s8 value);
+
+ virtual wifi_error put_s16(int attribute, s16 value);
+
+ virtual wifi_error put_s32(int attribute, s32 value);
+
+ virtual wifi_error put_s64(int attribute, s64 value);
+
+ wifi_error put_flag(int attribute);
+
+ virtual u8 get_u8(const struct nlattr *nla);
+ virtual u16 get_u16(const struct nlattr *nla);
+ virtual u32 get_u32(const struct nlattr *nla);
+ virtual u64 get_u64(const struct nlattr *nla);
+
+ virtual s8 get_s8(const struct nlattr *nla);
+ virtual s16 get_s16(const struct nlattr *nla);
+ virtual s32 get_s32(const struct nlattr *nla);
+ virtual s64 get_s64(const struct nlattr *nla);
+
+ virtual wifi_error put_ipv6_addr(int attribute, uint8_t value[16]);
+
+ virtual wifi_error put_string(int attribute, const char *value);
+
+ virtual wifi_error put_addr(int attribute, mac_addr value);
+
+ virtual struct nlattr * attr_start(int attribute);
+
+ virtual void attr_end(struct nlattr *attribute);
+
+ virtual wifi_error set_iface_id(const char* name);
+
+ virtual wifi_error put_bytes(int attribute, const char *data, int len);
+
+ virtual wifi_error get_mac_addr(struct nlattr **tb_vendor,
+ int attribute,
+ mac_addr addr);
+
+protected:
+
+ /* Override this method to parse reply and dig out data; save it in the corresponding
+ object */
+ virtual int handleResponse(WifiEvent &reply);
+
+ /* Override this method to parse event and dig out data; save it in the object */
+ virtual int handleEvent(WifiEvent &event);
+};
+
+/* nl message processing macros (required to pass C++ type checks) */
+
+#define for_each_attr(pos, nla, rem) \
+ for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \
+ nla_ok(pos, rem); \
+ pos = (nlattr *)nla_next(pos, &(rem)))
+
+wifi_error initialize_vendor_cmd(wifi_interface_handle iface,
+ wifi_request_id id,
+ u32 subcmd,
+ WifiVendorCommand **vCommand);
+#endif
diff --git a/wcn6740/qcwcn/wifi_hal/gscan.cpp b/wcn6740/qcwcn/wifi_hal/gscan.cpp
new file mode 100644
index 0000000..fc76219
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/gscan.cpp
@@ -0,0 +1,2344 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+#define LOG_TAG "WifiHAL"
+#include <utils/Log.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "cpp_bindings.h"
+#include "gscancommand.h"
+#include "gscan_event_handler.h"
+#include "vendor_definitions.h"
+
+#define GSCAN_EVENT_WAIT_TIME_SECONDS 4
+#define WIFI_SCANNING_MAC_OUI_LENGTH 3
+#define EPNO_NO_NETWORKS 0
+
+/* BSSID blacklist */
+typedef struct {
+ int num_bssid; // number of blacklisted BSSIDs
+ mac_addr bssids[MAX_BLACKLIST_BSSID]; // blacklisted BSSIDs
+} wifi_bssid_params;
+
+/* Used to handle gscan command events from driver/firmware.*/
+typedef struct gscan_event_handlers_s {
+ GScanCommandEventHandler *gscanStartCmdEventHandler;
+ GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
+ GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
+ GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler;
+ GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
+ GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
+} gscan_event_handlers;
+
+wifi_error initializeGscanHandlers(hal_info *info)
+{
+ info->gscan_handlers = (gscan_event_handlers *)malloc(sizeof(gscan_event_handlers));
+ if (info->gscan_handlers) {
+ memset(info->gscan_handlers, 0, sizeof(gscan_event_handlers));
+ }
+ else {
+ ALOGE("%s: Allocation of gscan event handlers failed",
+ __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error cleanupGscanHandlers(hal_info *info)
+{
+ gscan_event_handlers* event_handlers;
+ if (info && info->gscan_handlers) {
+ event_handlers = (gscan_event_handlers*) info->gscan_handlers;
+ if (event_handlers->gscanStartCmdEventHandler) {
+ delete event_handlers->gscanStartCmdEventHandler;
+ }
+ if (event_handlers->gScanSetBssidHotlistCmdEventHandler) {
+ delete event_handlers->gScanSetBssidHotlistCmdEventHandler;
+ }
+ if (event_handlers->gScanSetSignificantChangeCmdEventHandler) {
+ delete event_handlers->gScanSetSignificantChangeCmdEventHandler;
+ }
+ if (event_handlers->gScanSetSsidHotlistCmdEventHandler) {
+ delete event_handlers->gScanSetSsidHotlistCmdEventHandler;
+ }
+ if (event_handlers->gScanSetPnoListCmdEventHandler) {
+ delete event_handlers->gScanSetPnoListCmdEventHandler;
+ }
+ if (event_handlers->gScanPnoSetPasspointListCmdEventHandler) {
+ delete event_handlers->gScanPnoSetPasspointListCmdEventHandler;
+ }
+ memset(event_handlers, 0, sizeof(gscan_event_handlers));
+ free(info->gscan_handlers);
+ info->gscan_handlers = NULL;
+ return WIFI_SUCCESS;
+ }
+ ALOGE ("%s: info or info->gscan_handlers NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+}
+
+/* Implementation of the API functions exposed in gscan.h */
+wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
+ int band, int max_channels, wifi_channel *channels, int *num_channels)
+{
+ int requestId;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid();
+ ALOGV("%s: RequestId:%d band:%d max_channels:%d", __FUNCTION__,
+ requestId, band, max_channels);
+
+ if (channels == NULL) {
+ ALOGE("%s: NULL channels pointer provided. Exit.",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData)
+ goto cleanup;
+
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ requestId) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND,
+ band) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS,
+ max_channels) )
+ {
+ goto cleanup;
+ }
+ gScanCommand->attr_end(nlData);
+ /* Populate the input received from caller/framework. */
+ gScanCommand->setMaxChannels(max_channels);
+ gScanCommand->setChannels(channels);
+ gScanCommand->setNumChannelsPtr(num_channels);
+
+ /* Send the msg and wait for a response. */
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
+ wifi_gscan_capabilities *capabilities)
+{
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (capabilities == NULL) {
+ ALOGE("%s: NULL capabilities pointer provided. Exit.", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ memcpy(capabilities, &info->capa.gscan_capa, sizeof(wifi_gscan_capabilities));
+
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_start_gscan(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_scan_cmd_params params,
+ wifi_scan_result_handler handler)
+{
+ wifi_error ret;
+ u32 i, j;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ u32 num_scan_buckets, numChannelSpecs;
+ wifi_scan_bucket_spec bucketSpec;
+ struct nlattr *nlBuckectSpecList;
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanStartCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ALOGV("%s: RequestId:%d ", __FUNCTION__, id);
+ /* Wi-Fi HAL doesn't need to check if a similar request to start gscan was
+ * made earlier. If start_gscan() is called while another gscan is already
+ * running, the request will be sent down to driver and firmware. If new
+ * request is successfully honored, then Wi-Fi HAL will use the new request
+ * id for the gScanStartCmdEventHandler object.
+ */
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_START);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ num_scan_buckets = (unsigned int)params.num_buckets > MAX_BUCKETS ?
+ MAX_BUCKETS : params.num_buckets;
+
+ ALOGV("%s: Base Period:%d Max_ap_per_scan:%d "
+ "Threshold_percent:%d Threshold_num_scans:%d "
+ "num_buckets:%d", __FUNCTION__, params.base_period,
+ params.max_ap_per_scan, params.report_threshold_percent,
+ params.report_threshold_num_scans, num_scan_buckets);
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD,
+ params.base_period) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN,
+ params.max_ap_per_scan) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT,
+ params.report_threshold_percent) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS,
+ params.report_threshold_num_scans) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS,
+ num_scan_buckets))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ nlBuckectSpecList =
+ gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC);
+ /* Add NL attributes for scan bucket specs . */
+ for (i = 0; i < num_scan_buckets; i++) {
+ bucketSpec = params.buckets[i];
+ numChannelSpecs = (unsigned int)bucketSpec.num_channels > MAX_CHANNELS ?
+ MAX_CHANNELS : bucketSpec.num_channels;
+
+ ALOGV("%s: Index: %d Bucket Id:%d Band:%d Period:%d ReportEvent:%d "
+ "numChannelSpecs:%d max_period:%d base:%d step_count:%d",
+ __FUNCTION__, i, bucketSpec.bucket, bucketSpec.band,
+ bucketSpec.period, bucketSpec.report_events,
+ numChannelSpecs, bucketSpec.max_period,
+ bucketSpec.base, bucketSpec.step_count);
+
+ struct nlattr *nlBucketSpec = gScanCommand->attr_start(i);
+ if (gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX,
+ bucketSpec.bucket) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND,
+ bucketSpec.band) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD,
+ bucketSpec.period) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS,
+ bucketSpec.report_events) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS,
+ numChannelSpecs) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD,
+ bucketSpec.max_period) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE,
+ bucketSpec.base) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT,
+ bucketSpec.step_count))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ struct nlattr *nl_channelSpecList =
+ gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC);
+
+ /* Add NL attributes for scan channel specs . */
+ for (j = 0; j < numChannelSpecs; j++) {
+ struct nlattr *nl_channelSpec = gScanCommand->attr_start(j);
+ wifi_scan_channel_spec channel_spec = bucketSpec.channels[j];
+
+ ALOGV("%s: Channel Spec Index:%d Channel:%d Dwell Time:%d "
+ "passive:%d", __FUNCTION__, j, channel_spec.channel,
+ channel_spec.dwellTimeMs, channel_spec.passive);
+
+ if ( gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL,
+ channel_spec.channel) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME,
+ channel_spec.dwellTimeMs) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE,
+ channel_spec.passive) )
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ gScanCommand->attr_end(nl_channelSpec);
+ }
+ gScanCommand->attr_end(nl_channelSpecList);
+ gScanCommand->attr_end(nlBucketSpec);
+ }
+ gScanCommand->attr_end(nlBuckectSpecList);
+
+ gScanCommand->attr_end(nlData);
+
+ /* Set the callback handler functions for related events. */
+ GScanCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_full_scan_result = handler.on_full_scan_result;
+ callbackHandler.on_scan_event = handler.on_scan_event;
+
+ /* Create an object to handle the related events from firmware/driver. */
+ if (gScanStartCmdEventHandler == NULL) {
+ gScanStartCmdEventHandler = new GScanCommandEventHandler(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_START,
+ callbackHandler);
+ if (gScanStartCmdEventHandler == NULL) {
+ ALOGE("%s: Error gScanStartCmdEventHandler NULL", __FUNCTION__);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ event_handlers->gscanStartCmdEventHandler = gScanStartCmdEventHandler;
+ } else {
+ gScanStartCmdEventHandler->setCallbackHandler(callbackHandler);
+ }
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : requestResponse Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanStartCmdEventHandler != NULL) {
+ gScanStartCmdEventHandler->set_request_id(id);
+ gScanStartCmdEventHandler->enableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ /* Disable Event Handling if ret != 0 */
+ if ((ret != WIFI_SUCCESS) && gScanStartCmdEventHandler) {
+ ALOGI("%s: Error ret:%d, disable event handling",
+ __FUNCTION__, ret);
+ gScanStartCmdEventHandler->disableEventHandling();
+ }
+ return ret;
+
+}
+
+wifi_error wifi_stop_gscan(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanStartCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (gScanStartCmdEventHandler == NULL ||
+ gScanStartCmdEventHandler->isEventHandlingEnabled() == false) {
+ ALOGE("%s: GSCAN isn't running or already stopped. "
+ "Nothing to do. Exit", __FUNCTION__);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ gScanCommand->attr_end(nlData);
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ /* Disable Event Handling. */
+ if (gScanStartCmdEventHandler) {
+ gScanStartCmdEventHandler->disableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+/* Set the GSCAN BSSID Hotlist. */
+wifi_error wifi_set_bssid_hotlist(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_bssid_hotlist_params params,
+ wifi_hotlist_ap_found_handler handler)
+{
+ int i, numAp;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData, *nlApThresholdParamList;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanSetBssidHotlistCmdEventHandler =
+ event_handlers->gScanSetBssidHotlistCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Wi-Fi HAL doesn't need to check if a similar request to set bssid
+ * hotlist was made earlier. If set_bssid_hotlist() is called while
+ * another one is running, the request will be sent down to driver and
+ * firmware. If the new request is successfully honored, then Wi-Fi HAL
+ * will use the new request id for the gScanSetBssidHotlistCmdEventHandler
+ * object.
+ */
+
+ gScanCommand =
+ new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ numAp = (unsigned int)params.num_bssid > MAX_HOTLIST_APS ?
+ MAX_HOTLIST_APS : params.num_bssid;
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE,
+ params.lost_ap_sample_size) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP,
+ numAp))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ALOGV("%s: lost_ap_sample_size:%d numAp:%d", __FUNCTION__,
+ params.lost_ap_sample_size, numAp);
+ /* Add the vendor specific attributes for the NL command. */
+ nlApThresholdParamList =
+ gScanCommand->attr_start(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
+ if (!nlApThresholdParamList){
+ ret = WIFI_ERROR_UNINITIALIZED;
+ goto cleanup;
+ }
+
+ /* Add nested NL attributes for AP Threshold Param. */
+ for (i = 0; i < numAp; i++) {
+ ap_threshold_param apThreshold = params.ap[i];
+ struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
+ if (!nlApThresholdParam){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ if (gScanCommand->put_addr(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
+ apThreshold.bssid) ||
+ gScanCommand->put_s32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
+ apThreshold.low) ||
+ gScanCommand->put_s32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
+ apThreshold.high))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ALOGV("%s: Index:%d BssId: %hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
+ "Threshold low:%d high:%d", __FUNCTION__, i,
+ apThreshold.bssid[0], apThreshold.bssid[1],
+ apThreshold.bssid[2], apThreshold.bssid[3],
+ apThreshold.bssid[4], apThreshold.bssid[5],
+ apThreshold.low, apThreshold.high);
+ gScanCommand->attr_end(nlApThresholdParam);
+ }
+
+ gScanCommand->attr_end(nlApThresholdParamList);
+
+ gScanCommand->attr_end(nlData);
+
+ GScanCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_hotlist_ap_found = handler.on_hotlist_ap_found;
+ callbackHandler.on_hotlist_ap_lost = handler.on_hotlist_ap_lost;
+
+ /* Create an object of the event handler class to take care of the
+ * asychronous events on the north-bound.
+ */
+ if (gScanSetBssidHotlistCmdEventHandler == NULL) {
+ gScanSetBssidHotlistCmdEventHandler = new GScanCommandEventHandler(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST,
+ callbackHandler);
+ if (gScanSetBssidHotlistCmdEventHandler == NULL) {
+ ALOGE("%s: Error instantiating "
+ "gScanSetBssidHotlistCmdEventHandler.", __FUNCTION__);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ event_handlers->gScanSetBssidHotlistCmdEventHandler =
+ gScanSetBssidHotlistCmdEventHandler;
+ } else {
+ gScanSetBssidHotlistCmdEventHandler->setCallbackHandler(callbackHandler);
+ }
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanSetBssidHotlistCmdEventHandler != NULL) {
+ gScanSetBssidHotlistCmdEventHandler->set_request_id(id);
+ gScanSetBssidHotlistCmdEventHandler->enableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ /* Disable Event Handling if ret != 0 */
+ if ((ret != WIFI_SUCCESS) && gScanSetBssidHotlistCmdEventHandler) {
+ ALOGI("%s: Error ret:%d, disable event handling",
+ __FUNCTION__, ret);
+ gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
+ }
+ return ret;
+}
+
+wifi_error wifi_reset_bssid_hotlist(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanSetBssidHotlistCmdEventHandler =
+ event_handlers->gScanSetBssidHotlistCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (gScanSetBssidHotlistCmdEventHandler == NULL ||
+ (gScanSetBssidHotlistCmdEventHandler->isEventHandlingEnabled() ==
+ false)) {
+ ALOGE("wifi_reset_bssid_hotlist: GSCAN bssid_hotlist isn't set. "
+ "Nothing to do. Exit");
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST);
+
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ gScanCommand->attr_end(nlData);
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ /* Disable Event Handling. */
+ if (gScanSetBssidHotlistCmdEventHandler) {
+ gScanSetBssidHotlistCmdEventHandler->disableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+/* Set the GSCAN Significant AP Change list. */
+wifi_error wifi_set_significant_change_handler(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_significant_change_params params,
+ wifi_significant_change_handler handler)
+{
+ int i, numAp;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData, *nlApThresholdParamList;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanSetSignificantChangeCmdEventHandler =
+ event_handlers->gScanSetSignificantChangeCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Wi-Fi HAL doesn't need to check if a similar request to set significant
+ * change list was made earlier. If set_significant_change() is called while
+ * another one is running, the request will be sent down to driver and
+ * firmware. If the new request is successfully honored, then Wi-Fi HAL
+ * will use the new request id for the gScanSetSignificantChangeCmdEventHandler
+ * object.
+ */
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ numAp = (unsigned int)params.num_bssid > MAX_SIGNIFICANT_CHANGE_APS ?
+ MAX_SIGNIFICANT_CHANGE_APS : params.num_bssid;
+
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE,
+ params.rssi_sample_size) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE,
+ params.lost_ap_sample_size) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING,
+ params.min_breaching) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP,
+ numAp))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ALOGV("%s: Number of AP params:%d Rssi_sample_size:%d "
+ "lost_ap_sample_size:%d min_breaching:%d", __FUNCTION__,
+ numAp, params.rssi_sample_size, params.lost_ap_sample_size,
+ params.min_breaching);
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlApThresholdParamList =
+ gScanCommand->attr_start(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM);
+ if (!nlApThresholdParamList){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ /* Add nested NL attributes for AP Threshold Param list. */
+ for (i = 0; i < numAp; i++) {
+ ap_threshold_param apThreshold = params.ap[i];
+ struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i);
+ if (!nlApThresholdParam){
+ ret = WIFI_ERROR_UNINITIALIZED;
+ goto cleanup;
+ }
+ if ( gScanCommand->put_addr(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID,
+ apThreshold.bssid) ||
+ gScanCommand->put_s32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW,
+ apThreshold.low) ||
+ gScanCommand->put_s32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH,
+ apThreshold.high))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ALOGV("%s: ap[%d].bssid:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
+ "ap[%d].low:%d ap[%d].high:%d", __FUNCTION__,
+ i,
+ apThreshold.bssid[0], apThreshold.bssid[1],
+ apThreshold.bssid[2], apThreshold.bssid[3],
+ apThreshold.bssid[4], apThreshold.bssid[5],
+ i, apThreshold.low, i, apThreshold.high);
+ gScanCommand->attr_end(nlApThresholdParam);
+ }
+
+ gScanCommand->attr_end(nlApThresholdParamList);
+
+ gScanCommand->attr_end(nlData);
+
+ GScanCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_significant_change = handler.on_significant_change;
+
+ /* Create an object of the event handler class to take care of the
+ * asychronous events on the north-bound.
+ */
+ if (gScanSetSignificantChangeCmdEventHandler == NULL) {
+ gScanSetSignificantChangeCmdEventHandler =
+ new GScanCommandEventHandler(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE,
+ callbackHandler);
+ if (gScanSetSignificantChangeCmdEventHandler == NULL) {
+ ALOGE("%s: Error in instantiating, "
+ "gScanSetSignificantChangeCmdEventHandler.",
+ __FUNCTION__);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ event_handlers->gScanSetSignificantChangeCmdEventHandler =
+ gScanSetSignificantChangeCmdEventHandler;
+ } else {
+ gScanSetSignificantChangeCmdEventHandler->setCallbackHandler(callbackHandler);
+ }
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanSetSignificantChangeCmdEventHandler != NULL) {
+ gScanSetSignificantChangeCmdEventHandler->set_request_id(id);
+ gScanSetSignificantChangeCmdEventHandler->enableEventHandling();
+ }
+
+cleanup:
+ /* Disable Event Handling if ret != 0 */
+ if ((ret != WIFI_SUCCESS) && gScanSetSignificantChangeCmdEventHandler) {
+ ALOGI("%s: Error ret:%d, disable event handling",
+ __FUNCTION__, ret);
+ gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
+ }
+ delete gScanCommand;
+ return ret;
+}
+
+/* Clear the GSCAN Significant AP change list. */
+wifi_error wifi_reset_significant_change_handler(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanSetSignificantChangeCmdEventHandler =
+ event_handlers->gScanSetSignificantChangeCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (gScanSetSignificantChangeCmdEventHandler == NULL ||
+ (gScanSetSignificantChangeCmdEventHandler->isEventHandlingEnabled() ==
+ false)) {
+ ALOGE("wifi_reset_significant_change_handler: GSCAN significant_change"
+ " isn't set. Nothing to do. Exit");
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ gScanCommand =
+ new GScanCommand
+ (
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ gScanCommand->attr_end(nlData);
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ /* Disable Event Handling. */
+ if (gScanSetSignificantChangeCmdEventHandler) {
+ gScanSetSignificantChangeCmdEventHandler->disableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+/* Get the GSCAN cached scan results. */
+wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface,
+ byte flush, int max,
+ wifi_cached_scan_results *results,
+ int *num)
+{
+ int requestId, retRequestRsp = 0;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ ALOGE("%s: GSCAN is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* No request id from caller, so generate one and pass it on to the driver. */
+ /* Generate it randomly */
+ requestId = get_requestid();
+
+ if (results == NULL || num == NULL) {
+ ALOGE("%s: NULL pointer provided. Exit.",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = gScanCommand->allocRspParams(eGScanGetCachedResultsRspParams);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to allocate memory for response struct. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = gScanCommand->allocCachedResultsTemp(max, results);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to allocate memory for temp gscan cached list. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Clear the destination cached results list before copying results. */
+ memset(results, 0, max * sizeof(wifi_cached_scan_results));
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ requestId) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH,
+ flush) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX,
+ max))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ALOGV("%s: flush:%d max:%d", __FUNCTION__, flush, max);
+ gScanCommand->attr_end(nlData);
+
+ retRequestRsp = gScanCommand->requestResponse();
+ if (retRequestRsp != 0) {
+ ALOGE("%s: requestResponse Error:%d",
+ __FUNCTION__, retRequestRsp);
+ /* It's possible to get ETIMEDOUT after receiving few results from
+ * driver. Copy and forward them to framework.
+ */
+ if (retRequestRsp != -ETIMEDOUT) {
+ /* Proceed to cleanup & return no results */
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+
+ /* No more data, copy the parsed results into the caller's results array */
+ ret = gScanCommand->copyCachedScanResults(num, results);
+ ALOGV("%s: max: %d, num:%d", __FUNCTION__, max, *num);
+
+ if (!ret) {
+ /* If requestResponse returned a TIMEOUT */
+ if (retRequestRsp == -ETIMEDOUT) {
+ if (*num > 0) {
+ /* Mark scan results as incomplete for the last scan_id */
+ results[(*num)-1].flags = WIFI_SCAN_FLAG_INTERRUPTED;
+ ALOGV("%s: Timeout happened. Mark scan results as incomplete "
+ "for scan_id:%d", __FUNCTION__, results[(*num)-1].scan_id);
+ ret = WIFI_SUCCESS;
+ } else
+ ret = WIFI_ERROR_TIMED_OUT;
+ }
+ }
+cleanup:
+ gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams);
+ delete gScanCommand;
+ return ret;
+}
+
+/* Random MAC OUI for PNO */
+wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
+{
+ wifi_error ret;
+ struct nlattr *nlData;
+ WifiVendorCommand *vCommand = NULL;
+ interface_info *iinfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ vCommand = new WifiVendorCommand(wifiHandle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI);
+ if (vCommand == NULL) {
+ ALOGE("%s: Error vCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* create the message */
+ ret = vCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = vCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ALOGV("%s: MAC_OUI - %02x:%02x:%02x", __FUNCTION__,
+ scan_oui[0], scan_oui[1], scan_oui[2]);
+
+ /* Add the fixed part of the mac_oui to the nl command */
+ ret = vCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI,
+ (char *)scan_oui,
+ WIFI_SCANNING_MAC_OUI_LENGTH);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ vCommand->attr_end(nlData);
+
+ ret = vCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete vCommand;
+ return ret;
+}
+
+
+GScanCommand::GScanCommand(wifi_handle handle, int id, u32 vendor_id,
+ u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ /* Initialize the member data variables here */
+ mGetCachedResultsRspParams = NULL;
+ mChannels = NULL;
+ mMaxChannels = 0;
+ mNumChannelsPtr = NULL;
+
+ mRequestId = id;
+ memset(&mHandler, 0,sizeof(mHandler));
+}
+
+GScanCommand::~GScanCommand()
+{
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+}
+
+
+/* This function implements creation of Vendor command */
+wifi_error GScanCommand::create() {
+ wifi_error ret;
+
+ ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ /* Insert the oui in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ /* Insert the subcmd in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
+ __FUNCTION__, mVendor_id, mSubcmd);
+
+ return ret;
+}
+
+wifi_error GScanCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+int GScanCommand::handleResponse(WifiEvent &reply)
+{
+ int i = 0;
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ u32 val;
+
+ WifiVendorCommand::handleResponse(reply);
+
+ struct nlattr *tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
+ nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
+ (struct nlattr *)mVendorData,mDataLen, NULL);
+
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS:
+ {
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS"
+ " not found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ val = nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]);
+
+ val = val > (unsigned int)mMaxChannels ?
+ (unsigned int)mMaxChannels : val;
+ *mNumChannelsPtr = val;
+
+ /* Extract the list of channels. */
+ if (*mNumChannelsPtr > 0 ) {
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS"
+ " not found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ nla_memcpy(mChannels,
+ tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS],
+ sizeof(wifi_channel) * (*mNumChannelsPtr));
+ }
+ char buf[256];
+ size_t len = 0;
+ for (i = 0; i < *mNumChannelsPtr && len < sizeof(buf); i++) {
+ len += snprintf(buf + len, sizeof(buf) - len, "%u ",
+ *(mChannels + i));
+ }
+ ALOGV("%s: Num Channels %d: List of valid channels are: %s",
+ __FUNCTION__, *mNumChannelsPtr, buf);
+
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
+ {
+ wifi_request_id id;
+ u32 numResults = 0;
+ int firstScanIdInPatch = -1;
+
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) {
+ ALOGE("%s: GSCAN_RESULTS_REQUEST_ID not"
+ "found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ id = nla_get_u32(
+ tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]
+ );
+ /* If this is not for us, just ignore it. */
+ if (id != mRequestId) {
+ ALOGV("%s: Event has Req. ID:%d <> ours:%d",
+ __FUNCTION__, id, mRequestId);
+ break;
+ }
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
+ ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not"
+ "found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ /* Read num of cached scan results in this data chunk. Note that
+ * this value doesn't represent the number of unique gscan scan Ids
+ * since the first scan id in this new chunk could be similar to
+ * the last scan id in the previous chunk.
+ */
+ numResults = nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
+ ALOGV("%s: num Cached results in this fragment:%d",
+ __FUNCTION__, numResults);
+
+ if (!mGetCachedResultsRspParams) {
+ ALOGE("%s: mGetCachedResultsRspParams is NULL, exit.",
+ __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+
+ /* To support fragmentation from firmware, monitor the
+ * MORE_DATA flag and cache results until MORE_DATA = 0.
+ */
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) {
+ ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA "
+ "not found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ } else {
+ mGetCachedResultsRspParams->more_data = nla_get_u8(
+ tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
+ }
+
+ /* No data in this chunk so skip this chunk */
+ if (numResults == 0) {
+ return NL_SKIP;
+ }
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]) {
+ ALOGE("GSCAN_CACHED_RESULTS_SCAN_ID not found");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+
+ /* Get the first Scan-Id in this chuck of cached results. */
+ firstScanIdInPatch = nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]);
+
+ ALOGV("More data: %d, firstScanIdInPatch: %d, lastProcessedScanId: %d",
+ mGetCachedResultsRspParams->more_data, firstScanIdInPatch,
+ mGetCachedResultsRspParams->lastProcessedScanId);
+
+ if (numResults) {
+ if (firstScanIdInPatch !=
+ mGetCachedResultsRspParams->lastProcessedScanId) {
+ /* New result scan Id block, update the starting index. */
+ mGetCachedResultsRspParams->cachedResultsStartingIndex++;
+ }
+
+ ret = gscan_get_cached_results(
+ mGetCachedResultsRspParams->cached_results,
+ tbVendor);
+ /* If a parsing error occurred, exit and proceed for cleanup. */
+ if (ret)
+ break;
+ }
+ }
+ break;
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong GScan subcmd response received %d",
+ __FUNCTION__, mSubcmd);
+ }
+
+ /* A parsing error occurred, do the cleanup of gscan result lists. */
+ if (ret) {
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS:
+ {
+ ALOGE("%s: Parsing error, free CachedResultsRspParams",
+ __FUNCTION__);
+ freeRspParams(eGScanGetCachedResultsRspParams);
+ }
+ break;
+ default:
+ ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+ }
+ return NL_SKIP;
+}
+
+/* Called to parse and extract cached results. */
+wifi_error GScanCommand:: gscan_get_cached_results(
+ wifi_cached_scan_results *cached_results,
+ struct nlattr **tb_vendor)
+{
+ int j = 0;
+ struct nlattr *scanResultsInfo, *wifiScanResultsInfo;
+ int rem = 0, remResults = 0;
+ u32 len = 0, numScanResults = 0;
+ int i = mGetCachedResultsRspParams->cachedResultsStartingIndex;
+ ALOGV("%s: starting counter: %d", __FUNCTION__, i);
+
+ for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]),
+ rem = nla_len(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]);
+ nla_ok(scanResultsInfo, rem) && i < mGetCachedResultsRspParams->max;
+ scanResultsInfo = nla_next(scanResultsInfo, &(rem)))
+ {
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
+ (struct nlattr *) nla_data(scanResultsInfo),
+ nla_len(scanResultsInfo), NULL);
+
+ if (!
+ tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
+ ])
+ {
+ ALOGE("%s: GSCAN_CACHED_RESULTS_SCAN_ID"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].scan_id =
+ nla_get_u32(
+ tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID
+ ]);
+
+ if (!
+ tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS
+ ])
+ {
+ ALOGE("%s: GSCAN_CACHED_RESULTS_FLAGS "
+ "not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].flags =
+ nla_get_u32(
+ tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED])
+ {
+ ALOGI("%s: GSCAN_RESULTS_BUCKETS_SCANNED"
+ "not found", __FUNCTION__);
+ } else {
+ cached_results[i].buckets_scanned = nla_get_u32(
+ tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]);
+ }
+
+ if (!
+ tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
+ ])
+ {
+ ALOGE("%s: RESULTS_NUM_RESULTS_AVAILABLE "
+ "not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ numScanResults =
+ nla_get_u32(
+ tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
+
+ if (mGetCachedResultsRspParams->lastProcessedScanId !=
+ cached_results[i].scan_id) {
+ j = 0; /* reset wifi_scan_result counter */
+ cached_results[i].num_results = 0;
+ ALOGV("parsing: *lastProcessedScanId [%d] !="
+ " cached_results[%d].scan_id:%d, j:%d "
+ "numScanResults: %d",
+ mGetCachedResultsRspParams->lastProcessedScanId, i,
+ cached_results[i].scan_id, j, numScanResults);
+ mGetCachedResultsRspParams->lastProcessedScanId =
+ cached_results[i].scan_id;
+ mGetCachedResultsRspParams->wifiScanResultsStartingIndex = 0;
+ /* Increment the number of cached scan results received */
+ mGetCachedResultsRspParams->num_cached_results++;
+ } else {
+ j = mGetCachedResultsRspParams->wifiScanResultsStartingIndex;
+ ALOGV("parsing: *lastProcessedScanId [%d] == "
+ "cached_results[%d].scan_id:%d, j:%d "
+ "numScanResults:%d",
+ mGetCachedResultsRspParams->lastProcessedScanId, i,
+ cached_results[i].scan_id, j, numScanResults);
+ }
+
+ ALOGV("%s: scan_id %d ", __FUNCTION__,
+ cached_results[i].scan_id);
+ ALOGV("%s: flags %u ", __FUNCTION__,
+ cached_results[i].flags);
+
+ for (wifiScanResultsInfo = (struct nlattr *) nla_data(tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]),
+ remResults = nla_len(tb2[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]);
+ nla_ok(wifiScanResultsInfo, remResults);
+ wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(remResults)))
+ {
+ struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
+ nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
+ (struct nlattr *) nla_data(wifiScanResultsInfo),
+ nla_len(wifiScanResultsInfo), NULL);
+ if (j < MAX_AP_CACHE_PER_SCAN) {
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_TIME_STAMP not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].results[j].ts =
+ nla_get_u64(
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
+ ]);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_SSID not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]);
+ len =
+ sizeof(cached_results[i].results[j].ssid) <= len ?
+ sizeof(cached_results[i].results[j].ssid) : len;
+ memcpy((void *)&cached_results[i].results[j].ssid,
+ nla_data(
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]),
+ len);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_BSSID not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]);
+ len =
+ sizeof(cached_results[i].results[j].bssid) <= len ?
+ sizeof(cached_results[i].results[j].bssid) : len;
+ memcpy(&cached_results[i].results[j].bssid,
+ nla_data(
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]),
+ len);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_CHANNEL not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].results[j].channel =
+ nla_get_u32(
+ tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_RSSI not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].results[j].rssi =
+ get_s32(
+ tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_RTT not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].results[j].rtt =
+ nla_get_u32(
+ tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]);
+ if (!
+ tb3[
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD
+ ])
+ {
+ ALOGE("%s: "
+ "RESULTS_SCAN_RESULT_RTT_SD not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ cached_results[i].results[j].rtt_sd =
+ nla_get_u32(
+ tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]);
+#ifdef QC_HAL_DEBUG
+ /* Enable these prints for debugging if needed. */
+ ALOGD("%s: ts %" PRId64, __FUNCTION__,
+ cached_results[i].results[j].ts);
+ ALOGD("%s: SSID %s ", __FUNCTION__,
+ cached_results[i].results[j].ssid);
+ ALOGD("%s: BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
+ __FUNCTION__, cached_results[i].results[j].bssid[0],
+ cached_results[i].results[j].bssid[1],
+ cached_results[i].results[j].bssid[2],
+ cached_results[i].results[j].bssid[3],
+ cached_results[i].results[j].bssid[4],
+ cached_results[i].results[j].bssid[5]);
+ ALOGD("%s: channel %d ", __FUNCTION__,
+ cached_results[i].results[j].channel);
+ ALOGD("%s: rssi %d ", __FUNCTION__,
+ cached_results[i].results[j].rssi);
+ ALOGD("%s: rtt %" PRId64, __FUNCTION__,
+ cached_results[i].results[j].rtt);
+ ALOGD("%s: rtt_sd %" PRId64, __FUNCTION__,
+ cached_results[i].results[j].rtt_sd);
+#endif
+ /* Increment loop index for next record */
+ j++;
+ /* For this scan id, update the wifiScanResultsStartingIndex
+ * and number of cached results parsed so far.
+ */
+ mGetCachedResultsRspParams->wifiScanResultsStartingIndex = j;
+ cached_results[i].num_results++;
+ } else {
+ /* We already parsed and stored up to max wifi_scan_results
+ * specified by the caller. Now, continue to loop over NL
+ * entries in order to properly update NL parsing pointer
+ * so it points to the next scan_id results.
+ */
+ ALOGD("%s: loop index:%d > max num"
+ " of wifi_scan_results:%d for gscan cached results"
+ " bucket:%d. Dummy loop", __FUNCTION__,
+ j, MAX_AP_CACHE_PER_SCAN, i);
+ }
+ }
+ ALOGV("%s: cached_results[%d].num_results: %d ", __FUNCTION__,
+ i, cached_results[i].num_results);
+ /* Increment loop index for next cached scan result record */
+ i++;
+ }
+ /* Increment starting index of filling cached results received */
+ if (mGetCachedResultsRspParams->num_cached_results <= 1024)
+ mGetCachedResultsRspParams->cachedResultsStartingIndex =
+ mGetCachedResultsRspParams->num_cached_results - 1;
+ return WIFI_SUCCESS;
+}
+
+/* Set the GSCAN BSSID Hotlist. */
+wifi_error wifi_set_epno_list(wifi_request_id id,
+ wifi_interface_handle iface,
+ const wifi_epno_params *epno_params,
+ wifi_epno_handler handler)
+{
+ int i, num_networks;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData, *nlPnoParamList;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanSetPnoListCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanSetPnoListCmdEventHandler =
+ event_handlers->gScanSetPnoListCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
+ ALOGE("%s: Enhanced PNO is not supported by the driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
+ * list was made earlier. If wifi_set_epno_list() is called while
+ * another one is running, the request will be sent down to driver and
+ * firmware. If the new request is successfully honored, then Wi-Fi HAL
+ * will use the new request id for the gScanSetPnoListCmdEventHandler
+ * object.
+ */
+
+ gScanCommand =
+ new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ num_networks = (unsigned int)epno_params->num_networks > MAX_EPNO_NETWORKS ?
+ MAX_EPNO_NETWORKS : epno_params->num_networks;
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI,
+ epno_params->min5GHz_rssi) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI,
+ epno_params->min24GHz_rssi) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX,
+ epno_params->initial_score_max) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS,
+ epno_params->current_connection_bonus) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS,
+ epno_params->same_network_bonus) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS,
+ epno_params->secure_bonus) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS,
+ epno_params->band5GHz_bonus) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
+ num_networks))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlPnoParamList =
+ gScanCommand->attr_start(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST);
+ if (!nlPnoParamList) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add attr. PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add nested NL attributes for ePno List. */
+ for (i = 0; i < num_networks; i++) {
+ wifi_epno_network pnoNetwork = epno_params->networks[i];
+ struct nlattr *nlPnoNetwork = gScanCommand->attr_start(i);
+ if (!nlPnoNetwork) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed attr_start for nlPnoNetwork. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ if (gScanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID,
+ pnoNetwork.ssid) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS,
+ pnoNetwork.flags) ||
+ gScanCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT,
+ pnoNetwork.auth_bit_field))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add PNO_SET_LIST_PARAM_EPNO_NETWORK_*. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ gScanCommand->attr_end(nlPnoNetwork);
+ }
+
+ gScanCommand->attr_end(nlPnoParamList);
+
+ gScanCommand->attr_end(nlData);
+
+ GScanCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_pno_network_found = handler.on_network_found;
+
+ /* Create an object of the event handler class to take care of the
+ * asychronous events on the north-bound.
+ */
+ if (gScanSetPnoListCmdEventHandler == NULL) {
+ gScanSetPnoListCmdEventHandler = new GScanCommandEventHandler(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST,
+ callbackHandler);
+ if (gScanSetPnoListCmdEventHandler == NULL) {
+ ALOGE("%s: Error instantiating "
+ "gScanSetPnoListCmdEventHandler.", __FUNCTION__);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ event_handlers->gScanSetPnoListCmdEventHandler =
+ gScanSetPnoListCmdEventHandler;
+ } else {
+ gScanSetPnoListCmdEventHandler->setCallbackHandler(callbackHandler);
+ }
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanSetPnoListCmdEventHandler != NULL) {
+ gScanSetPnoListCmdEventHandler->set_request_id(id);
+ gScanSetPnoListCmdEventHandler->enableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ /* Disable Event Handling if ret != 0 */
+ if ((ret != WIFI_SUCCESS) && gScanSetPnoListCmdEventHandler) {
+ ALOGI("%s: Error ret:%d, disable event handling",
+ __FUNCTION__, ret);
+ gScanSetPnoListCmdEventHandler->disableEventHandling();
+ }
+ return ret;
+}
+
+/* Reset the ePNO list - no ePNO networks should be matched after this */
+wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
+{
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
+ ALOGE("%s: Enhanced PNO is not supported by the driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ gScanCommand = new GScanCommand(wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS,
+ EPNO_NO_NETWORKS))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add vendor atributes Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ gScanCommand->attr_end(nlData);
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+/* Set the ePNO Passpoint List. */
+wifi_error wifi_set_passpoint_list(wifi_request_id id,
+ wifi_interface_handle iface, int num,
+ wifi_passpoint_network *networks,
+ wifi_passpoint_event_handler handler)
+{
+ int i;
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData, *nlPasspointNetworksParamList;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanPnoSetPasspointListCmdEventHandler =
+ event_handlers->gScanPnoSetPasspointListCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
+ ALOGE("%s: Enhanced PNO is not supported by the driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO
+ * passpoint list was made earlier. If wifi_set_passpoint_list() is called
+ * while another one is running, the request will be sent down to driver and
+ * firmware. If the new request is successfully honored, then Wi-Fi HAL
+ * will use the new request id for the
+ * gScanPnoSetPasspointListCmdEventHandler object.
+ */
+ gScanCommand =
+ new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST);
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID,
+ id) ||
+ gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM,
+ num))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlPasspointNetworksParamList =
+ gScanCommand->attr_start(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY);
+ if (!nlPasspointNetworksParamList) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed attr_start for PASSPOINT_LIST_PARAM_NETWORK_ARRAY. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add nested NL attributes for Passpoint List param. */
+ for (i = 0; i < num; i++) {
+ wifi_passpoint_network passpointNetwork = networks[i];
+ struct nlattr *nlPasspointNetworkParam = gScanCommand->attr_start(i);
+ if (!nlPasspointNetworkParam) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed attr_start for nlPasspointNetworkParam. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ if (gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID,
+ passpointNetwork.id) ||
+ gScanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM,
+ passpointNetwork.realm) ||
+ gScanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID,
+ (char*)passpointNetwork.roamingConsortiumIds,
+ 16 * sizeof(int64_t)) ||
+ gScanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN,
+ (char*)passpointNetwork.plmn, 3 * sizeof(u8)))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add PNO_PASSPOINT_NETWORK_PARAM_ROAM_* attr. "
+ "Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ gScanCommand->attr_end(nlPasspointNetworkParam);
+ }
+
+ gScanCommand->attr_end(nlPasspointNetworksParamList);
+
+ gScanCommand->attr_end(nlData);
+
+ GScanCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_passpoint_network_found =
+ handler.on_passpoint_network_found;
+
+ /* Create an object of the event handler class to take care of the
+ * asychronous events on the north-bound.
+ */
+ if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
+ gScanPnoSetPasspointListCmdEventHandler = new GScanCommandEventHandler(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST,
+ callbackHandler);
+ if (gScanPnoSetPasspointListCmdEventHandler == NULL) {
+ ALOGE("%s: Error instantiating "
+ "gScanPnoSetPasspointListCmdEventHandler.", __FUNCTION__);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ event_handlers->gScanPnoSetPasspointListCmdEventHandler =
+ gScanPnoSetPasspointListCmdEventHandler;
+ } else {
+ gScanPnoSetPasspointListCmdEventHandler->setCallbackHandler(callbackHandler);
+ }
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (gScanPnoSetPasspointListCmdEventHandler != NULL) {
+ gScanPnoSetPasspointListCmdEventHandler->set_request_id(id);
+ gScanPnoSetPasspointListCmdEventHandler->enableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ /* Disable Event Handling if ret != 0 */
+ if ((ret != WIFI_SUCCESS) && gScanPnoSetPasspointListCmdEventHandler) {
+ ALOGI("%s: Error ret:%d, disable event handling",
+ __FUNCTION__, ret);
+ gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
+ }
+ return ret;
+}
+
+wifi_error wifi_reset_passpoint_list(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ GScanCommand *gScanCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ gscan_event_handlers* event_handlers;
+ GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler;
+
+ event_handlers = (gscan_event_handlers*)info->gscan_handlers;
+ gScanPnoSetPasspointListCmdEventHandler =
+ event_handlers->gScanPnoSetPasspointListCmdEventHandler;
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) {
+ ALOGE("%s: Enhanced PNO is not supported by the driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (gScanPnoSetPasspointListCmdEventHandler == NULL ||
+ (gScanPnoSetPasspointListCmdEventHandler->isEventHandlingEnabled() ==
+ false)) {
+ ALOGE("wifi_reset_passpoint_list: ePNO passpoint_list isn't set. "
+ "Nothing to do. Exit.");
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ gScanCommand = new GScanCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST);
+
+ if (gScanCommand == NULL) {
+ ALOGE("%s: Error GScanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = gScanCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = gScanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = gScanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id);
+ if (ret != WIFI_SUCCESS) {
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ ALOGE("%s: Failed to add vendor data attributes. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ gScanCommand->attr_end(nlData);
+
+ ret = gScanCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ /* Disable Event Handling. */
+ if (gScanPnoSetPasspointListCmdEventHandler) {
+ gScanPnoSetPasspointListCmdEventHandler->disableEventHandling();
+ }
+
+cleanup:
+ delete gScanCommand;
+ return ret;
+}
+
+wifi_error GScanCommand::allocCachedResultsTemp(int max,
+ wifi_cached_scan_results *cached_results)
+{
+ /* Alloc memory for "max" number of cached results. */
+ mGetCachedResultsRspParams->cached_results =
+ (wifi_cached_scan_results*)
+ malloc(max * sizeof(wifi_cached_scan_results));
+ if (!mGetCachedResultsRspParams->cached_results) {
+ ALOGE("%s: Failed to allocate memory for "
+ "mGetCachedResultsRspParams->cached_results.",
+ __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(mGetCachedResultsRspParams->cached_results, 0,
+ max * sizeof(wifi_cached_scan_results));
+
+ mGetCachedResultsRspParams->max = max;
+
+ return WIFI_SUCCESS;
+}
+
+/*
+ * Allocates memory for the subCmd response struct and initializes status = -1
+ */
+wifi_error GScanCommand::allocRspParams(eGScanRspRarams cmd)
+{
+ switch(cmd)
+ {
+ case eGScanGetCachedResultsRspParams:
+ mGetCachedResultsRspParams = (GScanGetCachedResultsRspParams *)
+ malloc(sizeof(GScanGetCachedResultsRspParams));
+ if (!mGetCachedResultsRspParams)
+ return WIFI_ERROR_OUT_OF_MEMORY;
+
+ mGetCachedResultsRspParams->num_cached_results = 0;
+ mGetCachedResultsRspParams->more_data = false;
+ mGetCachedResultsRspParams->cachedResultsStartingIndex = -1;
+ mGetCachedResultsRspParams->lastProcessedScanId = -1;
+ mGetCachedResultsRspParams->wifiScanResultsStartingIndex = -1;
+ mGetCachedResultsRspParams->max = 0;
+ mGetCachedResultsRspParams->cached_results = NULL;
+ break;
+ default:
+ ALOGD("%s: Wrong request for alloc.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return WIFI_SUCCESS;
+}
+
+void GScanCommand::freeRspParams(eGScanRspRarams cmd)
+{
+ switch(cmd)
+ {
+ case eGScanGetCachedResultsRspParams:
+ if (mGetCachedResultsRspParams) {
+ if (mGetCachedResultsRspParams->cached_results) {
+ free(mGetCachedResultsRspParams->cached_results);
+ mGetCachedResultsRspParams->cached_results = NULL;
+ }
+ free(mGetCachedResultsRspParams);
+ mGetCachedResultsRspParams = NULL;
+ }
+ break;
+ default:
+ ALOGD("%s: Wrong request for free.", __FUNCTION__);
+ }
+}
+
+wifi_error GScanCommand::copyCachedScanResults(
+ int *numResults,
+ wifi_cached_scan_results *cached_results)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ int i;
+ wifi_cached_scan_results *cachedResultRsp;
+
+ if (mGetCachedResultsRspParams && cached_results)
+ {
+ /* Populate the number of parsed cached results. */
+ *numResults = mGetCachedResultsRspParams->num_cached_results;
+
+ for (i = 0; i < *numResults; i++) {
+ cachedResultRsp = &mGetCachedResultsRspParams->cached_results[i];
+ cached_results[i].scan_id = cachedResultRsp->scan_id;
+ cached_results[i].flags = cachedResultRsp->flags;
+ cached_results[i].num_results = cachedResultRsp->num_results;
+ cached_results[i].buckets_scanned = cachedResultRsp->buckets_scanned;
+
+ if (!cached_results[i].num_results) {
+ ALOGI("Error: cached_results[%d].num_results=0", i);
+ continue;
+ }
+
+ ALOGV("copyCachedScanResults: "
+ "cached_results[%d].num_results : %d",
+ i, cached_results[i].num_results);
+
+ memcpy(cached_results[i].results,
+ cachedResultRsp->results,
+ cached_results[i].num_results * sizeof(wifi_scan_result));
+ ret = WIFI_SUCCESS;
+ }
+ } else {
+ ALOGE("%s: mGetCachedResultsRspParams is NULL", __FUNCTION__);
+ *numResults = 0;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ }
+ return ret;
+}
+
+void GScanCommand::setMaxChannels(int max_channels) {
+ mMaxChannels = max_channels;
+}
+
+void GScanCommand::setChannels(int *channels) {
+ mChannels = channels;
+}
+
+void GScanCommand::setNumChannelsPtr(int *num_channels) {
+ mNumChannelsPtr = num_channels;
+}
diff --git a/qcwcn/wifi_hal/gscan_event_handler.cpp b/wcn6740/qcwcn/wifi_hal/gscan_event_handler.cpp
similarity index 100%
copy from qcwcn/wifi_hal/gscan_event_handler.cpp
copy to wcn6740/qcwcn/wifi_hal/gscan_event_handler.cpp
diff --git a/qcwcn/wifi_hal/gscan_event_handler.h b/wcn6740/qcwcn/wifi_hal/gscan_event_handler.h
similarity index 100%
copy from qcwcn/wifi_hal/gscan_event_handler.h
copy to wcn6740/qcwcn/wifi_hal/gscan_event_handler.h
diff --git a/wcn6740/qcwcn/wifi_hal/gscancommand.h b/wcn6740/qcwcn/wifi_hal/gscancommand.h
new file mode 100644
index 0000000..6fbc90b
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/gscancommand.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WIFI_HAL_GSCAN_COMMAND_H__
+#define __WIFI_HAL_GSCAN_COMMAND_H__
+
+#include "common.h"
+#include "cpp_bindings.h"
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
+#include "gscan.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+typedef struct{
+ u32 status;
+ u32 num_channels;
+ wifi_channel channels[];
+} GScanGetValidChannelsRspParams;
+
+typedef struct{
+ wifi_gscan_capabilities capabilities;
+} GScanGetCapabilitiesRspParams;
+
+typedef struct{
+ u8 more_data;
+ u32 num_cached_results;
+ int cachedResultsStartingIndex; /* Used in filling cached scan results */
+ int lastProcessedScanId; /* Last scan id in gscan cached results block */
+ int wifiScanResultsStartingIndex; /* For the lastProcessedScanId */
+ int max; /* max num of cached results specified by caller */
+ wifi_cached_scan_results *cached_results;
+} GScanGetCachedResultsRspParams;
+
+typedef struct {
+ int max_channels;
+ wifi_channel *channels;
+ int *number_channels;
+} GScan_get_valid_channels_cb_data;
+
+typedef enum{
+ eGScanRspParamsInvalid = 0,
+ eGScanGetValidChannelsRspParams,
+ eGScanGetCapabilitiesRspParams,
+ eGScanGetCachedResultsRspParams,
+} eGScanRspRarams;
+
+/* Response and Event Callbacks */
+typedef struct {
+ /* Various Events Callback */
+ void (*on_hotlist_ap_found)(wifi_request_id id,
+ unsigned num_results, wifi_scan_result *results);
+ void (*on_hotlist_ap_lost)(wifi_request_id id,
+ unsigned num_results, wifi_scan_result *results);
+ void (*on_significant_change)(wifi_request_id id,
+ unsigned num_results,
+ wifi_significant_change_result **results);
+ /* Reported when each probe response is received, if report_events
+ * enabled in wifi_scan_cmd_params
+ */
+ void (*on_full_scan_result) (wifi_request_id id, wifi_scan_result *result,
+ unsigned buckets_scanned);
+ /* Optional event - indicates progress of scanning statemachine */
+ void (*on_scan_event) (wifi_request_id id, wifi_scan_event event);
+ void (*on_hotlist_ssid_found)(wifi_request_id id,
+ unsigned num_results, wifi_scan_result *results);
+ void (*on_hotlist_ssid_lost)(wifi_request_id id,
+ unsigned num_results, wifi_scan_result *results);
+ void (*on_pno_network_found)(wifi_request_id id,
+ unsigned num_results, wifi_scan_result *results);
+ void (*on_passpoint_network_found)(wifi_request_id id,
+ int net_id,
+ wifi_scan_result *result,
+ int anqp_len,
+ byte *anqp
+ );
+} GScanCallbackHandler;
+
+class GScanCommand: public WifiVendorCommand
+{
+private:
+ GScanGetCachedResultsRspParams *mGetCachedResultsRspParams;
+ GScanCallbackHandler mHandler;
+ int mRequestId;
+ int *mChannels;
+ int mMaxChannels;
+ int *mNumChannelsPtr;
+
+public:
+ GScanCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+ virtual ~GScanCommand();
+
+ /* This function implements creation of GSCAN specific Request
+ * based on the request type.
+ */
+ virtual wifi_error create();
+ virtual wifi_error requestResponse();
+ virtual int handleResponse(WifiEvent &reply);
+ virtual void setMaxChannels(int max_channels);
+ virtual void setChannels(int *channels);
+ virtual void setNumChannelsPtr(int *num_channels);
+ virtual wifi_error allocRspParams(eGScanRspRarams cmd);
+ virtual void freeRspParams(eGScanRspRarams cmd);
+ virtual wifi_error copyCachedScanResults(int *numResults,
+ wifi_cached_scan_results *cached_results);
+ virtual wifi_error gscan_get_cached_results(wifi_cached_scan_results *results,
+ struct nlattr **tb_vendor);
+ wifi_error validateGscanConfig(wifi_scan_cmd_params params);
+ wifi_error validateSignificantChangeParams(
+ wifi_significant_change_params params);
+ virtual wifi_error allocCachedResultsTemp(int max,
+ wifi_cached_scan_results *results);
+};
+
+#define GSCAN_BASE_PERIOD_MIN 1
+#define GSCAN_MAX_AP_PER_SCAN_MIN 1
+#define GSCAN_REPORT_THRESHOLD_MIN 1
+#define GSCAN_NUM_BUCKETS_MIN 1
+#define GSCAN_BUCKET_INDEX_MIN 0
+#define GSCAN_REPORT_EVENT0 0
+#define GSCAN_REPORT_EVENT1 1
+#define GSCAN_REPORT_EVENT2 2
+#define GSCAN_MIN_CHANNELS 0
+#define GSCAN_ACTIVE_SCAN 0
+#define GSCAN_PASSIVE_SCAN 1
+
+#define BSSID_HOTLIST_NUM_AP_MIN 1
+
+#define RSSI_SAMPLE_SIZE_MIN 1
+#define LOSTAP_SAMPLE_SIZE_MIN 1
+#define MIN_BREACHING_MIN 1
+#define SIGNIFICANT_CHANGE_NUM_AP_MIN 1
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.cpp b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
similarity index 70%
copy from qcwcn/wifi_hal/ifaceeventhandler.cpp
copy to wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
index 6e70ab5..0c44e25 100644
--- a/qcwcn/wifi_hal/ifaceeventhandler.cpp
+++ b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.cpp
@@ -33,6 +33,7 @@
#include <errno.h>
#include "ifaceeventhandler.h"
+#include "common.h"
/* Used to handle NL command events from driver/firmware. */
IfaceEventHandlerCommand *mwifiEventHandler = NULL;
@@ -205,7 +206,10 @@
mCapa = &(info->capa);
mfilter_packet_read_buffer = NULL;
mfilter_packet_length = 0;
+ res_size = 0;
+ channel_buff = NULL;
memset(&mDriverFeatures, 0, sizeof(mDriverFeatures));
+ memset(&mRadarResultParams, 0, sizeof(RadarHistoryResultsParams));
}
WifihalGeneric::~WifihalGeneric()
@@ -222,6 +226,119 @@
return WifiCommand::requestResponse(mMsg);
}
+static u32 get_wifi_iftype_masks(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & BIT(NL80211_IFTYPE_STATION)) {
+ op_mask |= BIT(WIFI_INTERFACE_STA);
+ op_mask |= BIT(WIFI_INTERFACE_TDLS);
+ }
+ if (in_mask & BIT(NL80211_IFTYPE_AP))
+ op_mask |= BIT(WIFI_INTERFACE_SOFTAP);
+ if (in_mask & BIT(NL80211_IFTYPE_P2P_CLIENT))
+ op_mask |= BIT(WIFI_INTERFACE_P2P_CLIENT);
+ if (in_mask & BIT(NL80211_IFTYPE_P2P_GO))
+ op_mask |= BIT(WIFI_INTERFACE_P2P_GO);
+ if (in_mask & BIT(NL80211_IFTYPE_NAN))
+ op_mask |= BIT(WIFI_INTERFACE_NAN);
+
+ return op_mask;
+}
+
+static wifi_channel_width get_channel_width(u32 nl_width)
+{
+ switch(nl_width) {
+ case NL80211_CHAN_WIDTH_20:
+ return WIFI_CHAN_WIDTH_20;
+ case NL80211_CHAN_WIDTH_40:
+ return WIFI_CHAN_WIDTH_40;
+ case NL80211_CHAN_WIDTH_80:
+ return WIFI_CHAN_WIDTH_80;
+ case NL80211_CHAN_WIDTH_160:
+ return WIFI_CHAN_WIDTH_160;
+ case NL80211_CHAN_WIDTH_80P80:
+ return WIFI_CHAN_WIDTH_80P80;
+ case NL80211_CHAN_WIDTH_5:
+ return WIFI_CHAN_WIDTH_5;
+ case NL80211_CHAN_WIDTH_10:
+ return WIFI_CHAN_WIDTH_10;
+ default:
+ return WIFI_CHAN_WIDTH_INVALID;
+ }
+}
+
+int WifihalGeneric::handle_response_usable_channels(struct nlattr *VendorData,
+ u32 mDataLen)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
+ struct nlattr *curr_attr;
+ wifi_usable_channel *chan_info = NULL;
+ int rem;
+ u32 currSize = 0;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL)) {
+ ALOGE("Failed to parse NL channels list");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO]) {
+ ALOGE("%s: USABLE_CHANNELS_CHAN_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ for_each_nested_attribute(curr_attr,
+ tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO], rem) {
+ struct nlattr *ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1];
+
+ if (currSize >= mSetSizeMax) {
+ ALOGE("Got max channels %d completed", mSetSizeMax);
+ break;
+ }
+
+ if (nla_parse_nested(ch_info, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX,
+ curr_attr, NULL)) {
+ ALOGE("Failed to get usable channel info");
+ return NL_SKIP;
+ }
+
+ chan_info = &channel_buff[currSize];
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]) {
+ ALOGE("%s: CHAN_INFO_PRIMARY_FREQ not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->freq = nla_get_u32(ch_info[
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]);
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]) {
+ ALOGE("%s: CHAN_INFO_BANDWIDTH not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->width = get_channel_width(nla_get_u32(
+ ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]));
+ if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]) {
+ ALOGE("%s: CHAN_INFO_IFACE_MODE_MASK not found",
+ __FUNCTION__);
+ return NL_SKIP;
+ }
+
+ chan_info->iface_mode_mask = get_wifi_iftype_masks(nla_get_u32(
+ ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]));
+ ALOGV("Primary freq %d BW %d iface mask %d", chan_info->freq,
+ chan_info->width, chan_info->iface_mode_mask);
+ currSize++;
+ }
+
+ res_size = currSize;
+ ALOGV("%s: Result size %d", __FUNCTION__, res_size);
+
+ return NL_SKIP;
+}
+
int WifihalGeneric::handleResponse(WifiEvent &reply)
{
ALOGV("Got a Wi-Fi HAL module message from Driver");
@@ -244,7 +361,7 @@
return -EINVAL;
}
mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
- ALOGV("Supported feature set : 0x%" PRIx64, mSet);
+ ALOGV("Supported feature set : %" PRIx64, mSet);
break;
}
@@ -304,7 +421,7 @@
__func__);
for(i = 0; i < *mSetSizePtr; i++)
{
- ALOGV("0x%" PRIx64, *(mConcurrencySet + i));
+ ALOGV("%" PRIx64, *(mConcurrencySet + i));
}
}
}
@@ -436,6 +553,29 @@
}
}
break;
+ case QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS:
+ return handle_response_usable_channels((struct nlattr *)mVendorData,
+ mDataLen);
+ case QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY:
+ {
+ wifiParseRadarHistory();
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_MAX,
+ (struct nlattr *)mVendorData,mDataLen, NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION])
+ {
+ mInfo->sar_version = (qca_wlan_vendor_sar_version) nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION]);
+ }
+ ALOGV("%s: sar_version return %d", __func__, mInfo->sar_version);
+ }
+ break;
default :
ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
}
@@ -550,8 +690,8 @@
}
if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID]) {
- ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID not found. Set to 0.",
- __FUNCTION__);
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
+ "_NUM_BLACKLIST_BSSID not found. Set to 0.", __FUNCTION__);
mCapa->roaming_capa.max_blacklist_size = 0;
} else {
mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
@@ -560,6 +700,96 @@
return WIFI_SUCCESS;
}
+wifi_error WifihalGeneric::wifiParseRadarHistory() {
+{
+ // tbVendor
+ struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX + 1];
+ int rem = 0, num_dfs_entries = 0;
+
+ if (nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX,
+ (struct nlattr *)mVendorData,mDataLen, NULL)) {
+ ALOGE("%s: nla_parse fail", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES]) {
+ ALOGE("%s: radar attr entries not present", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ // nested radar history
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX + 1];
+ struct nlattr *attr;
+ static struct nla_policy
+ policy[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX + 1] = {
+ [QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ] = { .type = NLA_U32 },
+ [QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP] = { .type = NLA_U64 },
+ [QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED] = { .type = NLA_FLAG },
+ };
+ radar_history_result *newEntry;
+ radar_history_result *temp;
+ u32 totalEntrySize = 0;
+ u32 newEntrySize = sizeof(radar_history_result);
+
+ nla_for_each_nested(attr,
+ tbVendor[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES],
+ rem) {
+ if ((num_dfs_entries ++) > MAX_NUM_RADAR_HISTORY) {
+ ALOGE("%s: exceeded max entries, drop others", __FUNCTION__);
+ break;
+ }
+ if (nla_parse_nested(tb, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX,
+ attr, policy)) {
+ ALOGI("%s: nla_parse_nested fail", __FUNCTION__);
+ continue;
+ }
+ if (!tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ]) {
+ ALOGI("%s: radar attr freq not present", __FUNCTION__);
+ continue;
+ }
+ if (!tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP]) {
+ ALOGI("%s: radar attr timestamp not present", __FUNCTION__);
+ continue;
+ }
+
+ // realloc buffer for new entry
+ temp = (radar_history_result *) realloc(
+ mRadarResultParams.entries, totalEntrySize + newEntrySize);
+ if (temp == NULL) {
+ ALOGE("%s: failed to realloc memory", __FUNCTION__);
+ free(mRadarResultParams.entries);
+ mRadarResultParams.entries = NULL;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ mRadarResultParams.entries = temp;
+
+ newEntry = (radar_history_result *)(
+ (u8 *) mRadarResultParams.entries + totalEntrySize);
+ memset(newEntry, 0, newEntrySize);
+ totalEntrySize += newEntrySize;
+
+ // save to current radar entry
+ newEntry->freq = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ]);
+ newEntry->clock_boottime = nla_get_u64(
+ tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP]);
+ newEntry->radar_detected = false;
+ if (tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED]) {
+ newEntry->radar_detected = nla_get_flag(
+ tb[QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED]);
+ }
+ mRadarResultParams.num_entries ++;
+
+ ALOGI("Radar history: freq:%d boottime: %" PRId64 " detected:%d",
+ newEntry->freq,
+ newEntry->clock_boottime,
+ newEntry->radar_detected);
+ }
+ }
+
+ return WIFI_SUCCESS;
+}
+
+
void WifihalGeneric::getResponseparams(feature_set *pset)
{
*pset = mSet;
@@ -612,6 +842,17 @@
return firmware_bus_max_size;
}
+void WifihalGeneric::set_channels_buff(wifi_usable_channel* channels)
+{
+ channel_buff = channels;
+ memset(channel_buff, 0, sizeof(wifi_usable_channel) * mSetSizeMax);
+}
+
+u32 WifihalGeneric::get_results_size(void)
+{
+ return res_size;
+}
+
wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
{
wifi_error ret;
@@ -651,3 +892,67 @@
return ret;
}
+
+wifi_error WifihalGeneric::copyCachedRadarHistory(
+ radar_history_result *resultBuf, int resultBufSize, int *numResults) {
+ *numResults = 0;
+
+ if (mRadarResultParams.entries) {
+ radar_history_result *sEntry = NULL;
+ radar_history_result *tEntry = NULL;
+ u32 offset = 0;
+ int i;
+
+ for (i = 0; i < mRadarResultParams.num_entries; i ++) {
+ if (resultBufSize < (offset + sizeof(radar_history_result))) {
+ break;
+ }
+
+ sEntry = (radar_history_result *)(
+ (u8 *) mRadarResultParams.entries + offset);
+ tEntry = (radar_history_result *)(
+ (u8 *) resultBuf + offset);
+ memcpy(tEntry, sEntry, sizeof(radar_history_result));
+ (*numResults) += 1;
+ offset += sizeof(radar_history_result);
+ }
+ }
+
+ return WIFI_SUCCESS;
+}
+
+void WifihalGeneric::freeCachedRadarHistory() {
+ if (mRadarResultParams.entries) {
+ free(mRadarResultParams.entries);
+ mRadarResultParams.entries = NULL;
+ mRadarResultParams.num_entries = 0;
+ }
+}
+
+wifi_error WifihalGeneric::getSarVersion(wifi_interface_handle handle)
+{
+ wifi_error ret;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+
+
+ /* Create the NL message. */
+ ret = create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create NL message, Error:%d", __FUNCTION__, ret);
+ return ret;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
+ return ret;
+ }
+
+ ret = requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
+
+ return ret;
+}
+
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.h b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
similarity index 78%
copy from qcwcn/wifi_hal/ifaceeventhandler.h
copy to wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
index c993a7e..eef9624 100644
--- a/qcwcn/wifi_hal/ifaceeventhandler.h
+++ b/wcn6740/qcwcn/wifi_hal/ifaceeventhandler.h
@@ -46,6 +46,10 @@
{
#endif /* __cplusplus */
+typedef struct{
+ int num_entries;
+ radar_history_result *entries;
+} RadarHistoryResultsParams;
class wifiEventHandler: public WifiCommand
{
@@ -94,13 +98,19 @@
/* Packet Filter buffer and length */
u8 *mfilter_packet_read_buffer;
int mfilter_packet_length;
+ u32 res_size;
+ wifi_usable_channel *channel_buff;
+ RadarHistoryResultsParams mRadarResultParams;
virtual wifi_error wifiParseCapabilities(struct nlattr **tbVendor);
+ virtual wifi_error wifiParseRadarHistory();
public:
WifihalGeneric(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
virtual ~WifihalGeneric();
virtual wifi_error requestResponse();
virtual int handleResponse(WifiEvent &reply);
+ virtual int handle_response_usable_channels(struct nlattr *VendorData,
+ u32 mDataLen);
virtual void getResponseparams(feature_set *pset);
virtual void getDriverFeatures(features_info *pfeatures);
virtual void setMaxSetSize(int set_size_max);
@@ -111,7 +121,23 @@
virtual int getFilterLength();
virtual int getBusSize();
virtual wifi_error wifiGetCapabilities(wifi_interface_handle handle);
+ virtual void set_channels_buff(wifi_usable_channel *channels);
+ virtual u32 get_results_size(void);
+ virtual wifi_error copyCachedRadarHistory(radar_history_result *resultBuf,
+ int resultBufSize, int *numResults);
+ virtual void freeCachedRadarHistory();
+ virtual wifi_error getSarVersion(wifi_interface_handle handle);
};
+
+/**
+ * nla_for_each_nested from libnl is throwing implicit conversion from void*
+ * error. Adding a local definition to avoid it.
+ */
+#define for_each_nested_attribute(pos, nla, rem) \
+ for (pos = (struct nlattr *)nla_data(nla), rem = nla_len(nla); \
+ nla_ok(pos, rem); \
+ pos = nla_next(pos, &(rem)))
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/qcwcn/wifi_hal/list.cpp b/wcn6740/qcwcn/wifi_hal/list.cpp
similarity index 100%
copy from qcwcn/wifi_hal/list.cpp
copy to wcn6740/qcwcn/wifi_hal/list.cpp
diff --git a/qcwcn/wifi_hal/list.h b/wcn6740/qcwcn/wifi_hal/list.h
similarity index 100%
copy from qcwcn/wifi_hal/list.h
copy to wcn6740/qcwcn/wifi_hal/list.h
diff --git a/wcn6740/qcwcn/wifi_hal/llstats.cpp b/wcn6740/qcwcn/wifi_hal/llstats.cpp
new file mode 100644
index 0000000..3bed31c
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/llstats.cpp
@@ -0,0 +1,1484 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "llstatscommand.h"
+
+//Singleton Static Instance
+LLStatsCommand* LLStatsCommand::mLLStatsCommandInstance = NULL;
+
+// This function implements creation of Vendor command
+// For LLStats just call base Vendor command create
+wifi_error LLStatsCommand::create() {
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ // insert the oui in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ // insert the subcmd in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+
+ return ret;
+}
+
+LLStatsCommand::LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mClearRspParams, 0,sizeof(LLStatsClearRspParams));
+ memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
+ memset(&mHandler, 0,sizeof(mHandler));
+ mRadioStatsSize = 0;
+ mNumRadios = 0;
+ mNumRadiosAllocated = 0;
+}
+
+LLStatsCommand::~LLStatsCommand()
+{
+ mLLStatsCommandInstance = NULL;
+}
+
+LLStatsCommand* LLStatsCommand::instance(wifi_handle handle)
+{
+ if (handle == NULL) {
+ ALOGE("Interface Handle is invalid");
+ return NULL;
+ }
+ if (mLLStatsCommandInstance == NULL) {
+ mLLStatsCommandInstance = new LLStatsCommand(handle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
+ return mLLStatsCommandInstance;
+ }
+ else
+ {
+ if (handle != getWifiHandle(mLLStatsCommandInstance->mInfo))
+ {
+ /* upper layer must have cleaned up the handle and reinitialized,
+ so we need to update the same */
+ ALOGE("Handle different, update the handle");
+ mLLStatsCommandInstance->mInfo = (hal_info *)handle;
+ }
+ }
+ return mLLStatsCommandInstance;
+}
+
+void LLStatsCommand::initGetContext(u32 reqId)
+{
+ mRequestId = reqId;
+ memset(&mHandler, 0,sizeof(mHandler));
+}
+
+void LLStatsCommand::setSubCmd(u32 subcmd)
+{
+ mSubcmd = subcmd;
+}
+
+void LLStatsCommand::setHandler(wifi_stats_result_handler handler)
+{
+ mHandler = handler;
+}
+
+static wifi_error get_wifi_interface_info(wifi_interface_link_layer_info *stats,
+ struct nlattr **tb_vendor)
+{
+ u32 len = 0;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mode = (wifi_interface_mode)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE]);
+
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]);
+ len = ((sizeof(stats->mac_addr) <= len) ? sizeof(stats->mac_addr) : len);
+ memcpy(&stats->mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]), len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->state = (wifi_connection_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->roaming = (wifi_roam_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]);
+ len = ((sizeof(stats->ssid) <= len) ? sizeof(stats->ssid) : len);
+ memcpy(&stats->ssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]), len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]);
+ len = ((sizeof(stats->bssid) <= len) ? sizeof(stats->bssid) : len);
+ memcpy(&stats->bssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]), len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]);
+ len = ((sizeof(stats->ap_country_str) <= len) ? sizeof(stats->ap_country_str) : len);
+ memcpy(&stats->ap_country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]),
+ len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]);
+ len = ((sizeof(stats->country_str) < len) ? sizeof(stats->country_str) : len);
+ memcpy(&stats->country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]),
+ len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->time_slicing_duty_cycle_percent = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE]);
+#if QC_HAL_DEBUG
+ ALOGV("Mode : %d\n"
+ "Mac addr : "
+ MAC_ADDR_STR
+ "\nState : %d\n"
+ "Roaming : %d\n"
+ "capabilities : %0x\n"
+ "SSID :%s\n"
+ "BSSID : "
+ MAC_ADDR_STR
+ "\nAP country str : %c%c%c\n"
+ "Country String for this Association : %c%c%c\n"
+ "Time slicing duty cycle : %d",
+ stats->mode,
+ MAC_ADDR_ARRAY(stats->mac_addr),
+ stats->state,
+ stats->roaming,
+ stats->capabilities,
+ stats->ssid,
+ MAC_ADDR_ARRAY(stats->bssid),
+ stats->ap_country_str[0],
+ stats->ap_country_str[1],
+ stats->ap_country_str[2],
+ stats->country_str[0],
+ stats->country_str[1],
+ stats->country_str[2],
+ stats->time_slicing_duty_cycle_percent);
+#endif
+ return WIFI_SUCCESS;
+}
+
+static wifi_error get_wifi_wmm_ac_stat(wifi_wmm_ac_stat *stats,
+ struct nlattr **tb_vendor)
+{
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->ac = (wifi_traffic_ac)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_mcast = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rx_mcast = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rx_ampdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_ampdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mpdu_lost = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries_short = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries_long = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->contention_time_min = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->contention_time_max = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->contention_time_avg = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->contention_num_samples = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("%4u | %6u | %6u | %7u | %7u | %7u |"
+ " %7u | %8u | %7u | %12u |"
+ " %11u | %17u | %17u |"
+ " %17u | %20u",
+ stats->ac,
+ stats->tx_mpdu,
+ stats->rx_mpdu,
+ stats->tx_mcast,
+ stats->rx_mcast,
+ stats->rx_ampdu,
+ stats->tx_ampdu,
+ stats->mpdu_lost,
+ stats->retries,
+ stats->retries_short,
+ stats->retries_long,
+ stats->contention_time_min,
+ stats->contention_time_max,
+ stats->contention_time_avg,
+ stats->contention_num_samples);
+#endif
+ return WIFI_SUCCESS;
+}
+
+static wifi_error get_wifi_rate_stat(wifi_rate_stat *stats,
+ struct nlattr **tb_vendor)
+{
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rate.preamble = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rate.nss = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rate.bw = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rate.rateMcsIdx = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rate.bitrate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mpdu_lost = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries_short = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->retries_long = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("%8u | %3u | %2u | %10u | %7u | %6u | %6u | %8u | %7u | %12u | %11u",
+ stats->rate.preamble,
+ stats->rate.nss,
+ stats->rate.bw,
+ stats->rate.rateMcsIdx,
+ stats->rate.bitrate,
+ stats->tx_mpdu,
+ stats->rx_mpdu,
+ stats->mpdu_lost,
+ stats->retries,
+ stats->retries_short,
+ stats->retries_long);
+#endif
+ return WIFI_SUCCESS;
+}
+
+static wifi_error get_wifi_peer_info(wifi_peer_info *stats,
+ struct nlattr **tb_vendor)
+{
+ u32 i = 0, len = 0;
+ int rem;
+ wifi_rate_stat * pRateStats;
+ struct nlattr *rateInfo;
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->type = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]);
+ len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len);
+ memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]),
+ len);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->num_rate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("numPeers %u Peer MAC addr :" MAC_ADDR_STR " capabilities %0x numRate %u",
+ stats->type, MAC_ADDR_ARRAY(stats->peer_mac_address),
+ stats->capabilities, stats->num_rate);
+#endif
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+#ifdef QC_HAL_DEBUG
+ ALOGV("%8s | %3s | %2s | %10s | %7s | %6s | %6s | %8s | %7s | %12s | %11s",
+ "preamble", "nss", "bw", "rateMcsIdx", "bitrate", "txMpdu", "rxMpdu", "mpduLost", "retries", "retriesShort", "retriesLong");
+#endif
+ for (rateInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]);
+ nla_ok(rateInfo, rem);
+ rateInfo = nla_next(rateInfo, &(rem)))
+ {
+ struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
+ pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat)));
+
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL);
+ ret = get_wifi_rate_stat(pRateStats, tb2);
+ if(ret != WIFI_SUCCESS)
+ {
+ return ret;
+ }
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error LLStatsCommand::get_wifi_iface_stats(wifi_iface_stat *stats,
+ struct nlattr **tb_vendor)
+{
+ struct nlattr *wmmInfo;
+ wifi_wmm_ac_stat *pWmmStats;
+ int i=0, rem;
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX"
+ "not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->beacon_rx = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET])
+ {
+ stats->average_tsf_offset = 0;
+ } else {
+ stats->average_tsf_offset = nla_get_u64(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET]);
+ }
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED])
+ {
+ stats->leaky_ap_detected = 0;
+ } else {
+ stats->leaky_ap_detected = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED]);
+ }
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED])
+ {
+ stats->leaky_ap_avg_num_frames_leaked = 0;
+ } else {
+ stats->leaky_ap_avg_num_frames_leaked = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED]);
+ }
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME])
+ {
+ stats->leaky_ap_guard_time = 0;
+ } else {
+ stats->leaky_ap_guard_time = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME]);
+ }
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mgmt_rx = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX])
+ {
+ ALOGE("%s: "
+ "QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mgmt_action_rx = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX])
+ {
+ ALOGE("%s: "
+ "QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->mgmt_action_tx = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rssi_mgmt = get_s32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rssi_data = get_s32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rssi_ack = get_s32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("WMM STATS");
+ ALOGV("beaconRx : %u "
+ "mgmtRx : %u "
+ "mgmtActionRx : %u "
+ "mgmtActionTx : %u "
+ "rssiMgmt : %d "
+ "rssiData : %d "
+ "rssiAck : %d ",
+ stats->beacon_rx,
+ stats->mgmt_rx,
+ stats->mgmt_action_rx,
+ stats->mgmt_action_tx,
+ stats->rssi_mgmt,
+ stats->rssi_data,
+ stats->rssi_ack);
+#endif
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+#ifdef QC_HAL_DEBUG
+ ALOGV("%4s | %6s | %6s | %7s | %7s | %7s |"
+ " %7s | %8s | %7s | %12s |"
+ " %11s | %17s | %17s |"
+ " %17s | %20s",
+ "ac","txMpdu", "rxMpdu", "txMcast", "rxMcast", "rxAmpdu",
+ "txAmpdu", "mpduLost", "retries", "retriesShort",
+ "retriesLong", "contentionTimeMin", "contentionTimeMax",
+ "contentionTimeAvg", "contentionNumSamples");
+#endif
+ for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]),
+ rem = nla_len(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]);
+ nla_ok(wmmInfo, rem);
+ wmmInfo = nla_next(wmmInfo, &(rem)))
+ {
+ struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
+ pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac
+ + (i++ * sizeof(wifi_wmm_ac_stat)));
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
+ (struct nlattr *) nla_data(wmmInfo),
+ nla_len(wmmInfo), NULL);
+ ret = get_wifi_wmm_ac_stat(pWmmStats, tb2);
+ if(ret != WIFI_SUCCESS)
+ {
+ return ret;
+ }
+ }
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error get_wifi_radio_stats(wifi_radio_stat *stats,
+ struct nlattr **tb_vendor)
+{
+ u32 i = 0;
+ struct nlattr *chInfo;
+ wifi_channel_stat *pChStats;
+ int rem;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->radio = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME]);
+
+ if (stats->num_tx_levels) {
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL]) {
+ ALOGE("%s: num_tx_levels is %u but QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL not found", __func__, stats->num_tx_levels);
+ stats->num_tx_levels = 0;
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->tx_time_per_levels =
+ (u32 *) malloc(sizeof(u32) * stats->num_tx_levels);
+ if (!stats->tx_time_per_levels) {
+ ALOGE("%s: radio_stat: tx_time_per_levels malloc Failed", __func__);
+ stats->num_tx_levels = 0;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ nla_memcpy(stats->tx_time_per_levels,
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL],
+ sizeof(u32) * stats->num_tx_levels);
+ }
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->rx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_nbd = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_gscan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_roam_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_pno_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20 not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->on_time_hs20 = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20]);
+
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ stats->num_channels = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]);
+
+ if (stats->num_channels == 0) {
+ return WIFI_SUCCESS;
+ }
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ for (chInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]);
+ nla_ok(chInfo, rem);
+ chInfo = nla_next(chInfo, &(rem)))
+ {
+ struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
+ pChStats = (wifi_channel_stat *) ((u8 *)stats->channels + (i++ * (sizeof(wifi_channel_stat))));
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->channel.width = (wifi_channel_width)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->channel.center_freq = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->channel.center_freq0 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1 not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->channel.center_freq1 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->on_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME]);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChStats->cca_busy_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME]);
+
+ if (tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME] &&
+ nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME]) <= pChStats->cca_busy_time)
+ pChStats->cca_busy_time -= nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME]);
+
+ }
+ return WIFI_SUCCESS;
+}
+
+void LLStatsCommand::getClearRspParams(u32 *stats_clear_rsp_mask, u8 *stop_rsp)
+{
+ *stats_clear_rsp_mask = mClearRspParams.stats_clear_rsp_mask;
+ *stop_rsp = mClearRspParams.stop_rsp;
+}
+
+wifi_error LLStatsCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+wifi_error LLStatsCommand::notifyResponse()
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+
+ /* 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);
+ ret = WIFI_SUCCESS;
+ } else {
+ ret = WIFI_ERROR_INVALID_ARGS;
+ }
+
+ clearStats();
+
+ return ret;
+}
+
+
+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);
+ radioStat->tx_time_per_levels = NULL;
+ }
+ radioStat = (wifi_radio_stat *)((u8 *)radioStat +
+ sizeof(wifi_radio_stat) + (sizeof(wifi_channel_stat) *
+ radioStat->num_channels));
+ }
+ free(mResultsParams.radio_stat);
+ mResultsParams.radio_stat = NULL;
+ mRadioStatsSize = 0;
+ mNumRadios = 0;
+ mNumRadiosAllocated = 0;
+ }
+ if(mResultsParams.iface_stat)
+ {
+ free(mResultsParams.iface_stat);
+ mResultsParams.iface_stat = NULL;
+ }
+}
+
+
+int LLStatsCommand::handleResponse(WifiEvent &reply)
+{
+ unsigned i=0;
+ int status = WIFI_ERROR_NONE;
+ WifiVendorCommand::handleResponse(reply);
+
+ // Parse the vendordata and get the attribute
+
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET:
+ {
+ u32 resultsBufSize = 0;
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
+ int rem;
+ wifi_radio_stat *radioStatsBuf;
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE not found",
+ __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ switch(nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE]))
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO:
+ {
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mNumRadios = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS]);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS
+ ])
+ {
+ ALOGE("%s:"
+ "QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ resultsBufSize += (nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
+ * sizeof(wifi_channel_stat)
+ + sizeof(wifi_radio_stat));
+
+ radioStatsBuf = (wifi_radio_stat *)realloc(
+ mResultsParams.radio_stat,
+ mRadioStatsSize + resultsBufSize);
+ if (!radioStatsBuf)
+ {
+ ALOGE("%s: radio_stat: malloc Failed", __FUNCTION__);
+ status = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ mResultsParams.radio_stat = radioStatsBuf;
+
+ //Move the buffer to populate current radio stats
+ radioStatsBuf = (wifi_radio_stat *)(
+ (u8 *)mResultsParams.radio_stat
+ + 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[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS]);
+
+ wifi_channel_stat *pWifiChannelStats;
+ status = get_wifi_radio_stats(radioStatsBuf,
+ tb_vendor);
+ if(status != WIFI_SUCCESS)
+ {
+ goto cleanup;
+ }
+#ifdef QC_HAL_DEBUG
+ ALOGV("radio :%u onTime :%u txTime :%u rxTime :%u"
+ " onTimeScan :%u onTimeNbd :%u onTimeGscan :%u"
+ " onTimeRoamScan :%u onTimePnoScan :%u"
+ " onTimeHs20 :%u numChannels :%u num_tx_levels: %u",
+ radioStatsBuf->radio,
+ radioStatsBuf->on_time,
+ radioStatsBuf->tx_time,
+ radioStatsBuf->rx_time,
+ radioStatsBuf->on_time_scan,
+ radioStatsBuf->on_time_nbd,
+ radioStatsBuf->on_time_gscan,
+ radioStatsBuf->on_time_roam_scan,
+ radioStatsBuf->on_time_pno_scan,
+ radioStatsBuf->on_time_hs20,
+ radioStatsBuf->num_channels,
+ radioStatsBuf->num_tx_levels);
+#ifdef QC_HAL_DEBUG
+ for (i = 0; i < radioStatsBuf->num_tx_levels; i++) {
+ ALOGV("Power level: %u tx_time: %u", i,
+ radioStatsBuf->tx_time_per_levels[i]);
+ }
+#endif
+ ALOGV("%5s | %10s | %11s | %11s | %6s | %11s", "width",
+ "CenterFreq", "CenterFreq0", "CenterFreq1",
+ "onTime", "ccaBusyTime");
+#endif
+ for ( i=0; i < radioStatsBuf->num_channels; i++)
+ {
+ pWifiChannelStats =
+ (wifi_channel_stat *) (
+ (u8 *)radioStatsBuf->channels
+ + (i * sizeof(wifi_channel_stat)));
+
+#ifdef QC_HAL_DEBUG
+ ALOGV("%5u | %10u | %11u | %11u | %6u | %11u",
+ pWifiChannelStats->channel.width,
+ pWifiChannelStats->channel.center_freq,
+ pWifiChannelStats->channel.center_freq0,
+ pWifiChannelStats->channel.center_freq1,
+ pWifiChannelStats->on_time,
+ pWifiChannelStats->cca_busy_time);
+#endif
+ }
+ }
+ break;
+
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE:
+ {
+ resultsBufSize = sizeof(wifi_iface_stat);
+ mResultsParams.iface_stat =
+ (wifi_iface_stat *) malloc (resultsBufSize);
+ if (!mResultsParams.iface_stat)
+ {
+ ALOGE("%s: iface_stat: malloc Failed", __FUNCTION__);
+ status = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ memset(mResultsParams.iface_stat, 0, resultsBufSize);
+ status = get_wifi_interface_info(
+ &mResultsParams.iface_stat->info, tb_vendor);
+ if(status != WIFI_SUCCESS)
+ {
+ goto cleanup;
+ }
+ status = get_wifi_iface_stats(mResultsParams.iface_stat,
+ tb_vendor);
+ if(status != WIFI_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ /* Driver/firmware might send this attribute when there
+ * are no peers connected.
+ * So that, the event
+ * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS can be
+ * avoided.
+ */
+ if (tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
+ {
+ mResultsParams.iface_stat->num_peers =
+ nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("%s: numPeers is %u\n", __FUNCTION__,
+ mResultsParams.iface_stat->num_peers);
+#endif
+ }
+ }
+ break;
+
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS:
+ {
+ struct nlattr *peerInfo;
+ wifi_iface_stat *pIfaceStat = NULL;
+ u32 numPeers, num_rates = 0;
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
+ {
+ ALOGE("%s:QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+#ifdef QC_HAL_DEBUG
+ ALOGV(" numPeers is %u in %s\n",
+ nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]),
+ __FUNCTION__);
+#endif
+ if((numPeers = nla_get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
+ {
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
+ rem = nla_len(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
+ nla_ok(peerInfo, rem);
+ peerInfo = nla_next(peerInfo, &(rem)))
+ {
+ struct nlattr *tb2[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
+
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
+ (struct nlattr *) nla_data(peerInfo),
+ nla_len(peerInfo), NULL);
+
+ if (!tb2[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
+ {
+ ALOGE("%s:"
+ "QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ num_rates += nla_get_u32(tb2[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
+ }
+ resultsBufSize += (numPeers * sizeof(wifi_peer_info)
+ + num_rates * sizeof(wifi_rate_stat)
+ + sizeof (wifi_iface_stat));
+ pIfaceStat = (wifi_iface_stat *) malloc (
+ resultsBufSize);
+ if (!pIfaceStat)
+ {
+ ALOGE("%s: pIfaceStat: malloc Failed", __FUNCTION__);
+ status = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ memset(pIfaceStat, 0, resultsBufSize);
+ if(mResultsParams.iface_stat) {
+ if(resultsBufSize >= sizeof(wifi_iface_stat)) {
+ memcpy ( pIfaceStat, mResultsParams.iface_stat,
+ sizeof(wifi_iface_stat));
+ free (mResultsParams.iface_stat);
+ mResultsParams.iface_stat = pIfaceStat;
+ } else {
+ ALOGE("%s: numPeers = %u, num_rates= %u, "
+ "either numPeers or num_rates is invalid",
+ __FUNCTION__,numPeers,num_rates);
+ status = WIFI_ERROR_UNKNOWN;
+ free(pIfaceStat);
+ goto cleanup;
+ }
+ }
+ wifi_peer_info *pPeerStats;
+ pIfaceStat->num_peers = numPeers;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ num_rates = 0;
+ for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
+ rem = nla_len(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
+ nla_ok(peerInfo, rem);
+ peerInfo = nla_next(peerInfo, &(rem)))
+ {
+ struct nlattr *tb2[
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
+ pPeerStats = (wifi_peer_info *) (
+ (u8 *)pIfaceStat->peer_info
+ + (i++ * sizeof(wifi_peer_info))
+ + (num_rates * sizeof(wifi_rate_stat)));
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
+ (struct nlattr *) nla_data(peerInfo),
+ nla_len(peerInfo), NULL);
+ status = get_wifi_peer_info(pPeerStats, tb2);
+ if(status != WIFI_SUCCESS)
+ {
+ goto cleanup;
+ }
+ num_rates += pPeerStats->num_rate;
+ }
+ }
+
+ }
+ break;
+
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID:
+ default:
+ //error case should not happen print log
+ ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__,
+ mSubcmd);
+ }
+ }
+ break;
+
+ case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
+ {
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
+ break;
+ }
+ default :
+ ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+ return NL_SKIP;
+
+cleanup:
+ clearStats();
+ return status;
+}
+
+//Implementation of the functions exposed in linklayer.h
+wifi_error wifi_set_link_stats(wifi_interface_handle iface,
+ wifi_link_layer_params params)
+{
+ wifi_error ret;
+ LLStatsCommand *LLCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(handle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_LINK_LAYER_STATS)) {
+ ALOGI("%s: LLS is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ALOGI("mpdu_size_threshold : %u, aggressive_statistics_gathering : %u",
+ params.mpdu_size_threshold, params.aggressive_statistics_gathering);
+ LLCommand = LLStatsCommand::instance(handle);
+ if (LLCommand == NULL) {
+ ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
+
+ /* create the message */
+ ret = LLCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = LLCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the attributes*/
+ nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ /**/
+ ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
+ params.mpdu_size_threshold);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ /**/
+ ret = LLCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
+ params.aggressive_statistics_gathering);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ LLCommand->attr_end(nl_data);
+
+ ret = LLCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ return ret;
+}
+
+//Implementation of the functions exposed in LLStats.h
+wifi_error wifi_get_link_stats(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_stats_result_handler handler)
+{
+ wifi_error ret;
+ LLStatsCommand *LLCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(handle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_LINK_LAYER_STATS)) {
+ ALOGI("%s: LLS is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ LLCommand = LLStatsCommand::instance(handle);
+ if (LLCommand == NULL) {
+ ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
+
+ LLCommand->initGetContext(id);
+
+ LLCommand->setHandler(handler);
+
+ /* create the message */
+ ret = LLCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = LLCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ /*add the attributes*/
+ nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
+ id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
+ 7);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /**/
+ LLCommand->attr_end(nl_data);
+
+ ret = LLCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ if (ret != WIFI_SUCCESS) {
+ LLCommand->clearStats();
+ goto cleanup;
+ }
+
+ if (ret == WIFI_SUCCESS)
+ ret = LLCommand->notifyResponse();
+
+cleanup:
+ return ret;
+}
+
+
+//Implementation of the functions exposed in LLStats.h
+wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
+ u32 stats_clear_req_mask,
+ u32 *stats_clear_rsp_mask,
+ u8 stop_req, u8 *stop_rsp)
+{
+ wifi_error ret;
+ LLStatsCommand *LLCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(handle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_LINK_LAYER_STATS)) {
+ ALOGI("%s: LLS is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ALOGI("clear_req : %x, stop_req : %u", stats_clear_req_mask, stop_req);
+ LLCommand = LLStatsCommand::instance(handle);
+ if (LLCommand == NULL) {
+ ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
+
+ /* create the message */
+ ret = LLCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = LLCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ /*add the attributes*/
+ nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ /**/
+ ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
+ stats_clear_req_mask);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ /**/
+ ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
+ stop_req);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ LLCommand->attr_end(nl_data);
+
+ ret = LLCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+ LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
+
+cleanup:
+ delete LLCommand;
+ return ret;
+}
diff --git a/qcwcn/wifi_hal/llstatscommand.h b/wcn6740/qcwcn/wifi_hal/llstatscommand.h
similarity index 100%
copy from qcwcn/wifi_hal/llstatscommand.h
copy to wcn6740/qcwcn/wifi_hal/llstatscommand.h
diff --git a/wcn6740/qcwcn/wifi_hal/nan.cpp b/wcn6740/qcwcn/wifi_hal/nan.cpp
new file mode 100644
index 0000000..1690a86
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nan.cpp
@@ -0,0 +1,2156 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include "sync.h"
+
+#include "wifi_hal.h"
+#include "nan_i.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include <utils/Log.h>
+#include <errno.h>
+#include "nancommand.h"
+#include "vendor_definitions.h"
+#include "wificonfigcommand.h"
+#include <ctype.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
+
+#define OUT_OF_BAND_SERVICE_INSTANCE_ID 0
+
+//Singleton Static Instance
+NanCommand* NanCommand::mNanCommandInstance = NULL;
+
+//Implementation of the functions exposed in nan.h
+wifi_error nan_register_handler(wifi_interface_handle iface,
+ NanCallbackHandler handlers)
+{
+ // Obtain the singleton instance
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ nanCommand = NanCommand::instance(wifiHandle);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->setCallbackHandler(handlers);
+ return ret;
+}
+
+wifi_error nan_get_version(wifi_handle handle,
+ NanVersion* version)
+{
+ *version = (NAN_MAJOR_VERSION <<16 | NAN_MINOR_VERSION << 8 | NAN_MICRO_VERSION);
+ return WIFI_SUCCESS;
+}
+
+/* Function to send enable request to the wifi driver.*/
+wifi_error nan_enable_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanEnableRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ NanCommand *t_nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanEnable(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanEnable Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+ if (ret == WIFI_SUCCESS) {
+ t_nanCommand = NanCommand::instance(wifiHandle);
+ if (t_nanCommand != NULL) {
+ t_nanCommand->allocSvcParams();
+ }
+ }
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send disable request to the wifi driver.*/
+wifi_error nan_disable_request(transaction_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ NanCommand *t_nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanDisable(id);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanDisable Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+ if (ret == WIFI_SUCCESS) {
+ t_nanCommand = NanCommand::instance(wifiHandle);
+ if (t_nanCommand != NULL) {
+ t_nanCommand->deallocSvcParams();
+ }
+ }
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send publish request to the wifi driver.*/
+wifi_error nan_publish_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanPublishRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanPublish(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanPublish Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send publish cancel to the wifi driver.*/
+wifi_error nan_publish_cancel_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanPublishCancelRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanPublishCancel(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanPublishCancel Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send Subscribe request to the wifi driver.*/
+wifi_error nan_subscribe_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanSubscribeRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanSubscribe(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanSubscribe Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to cancel subscribe to the wifi driver.*/
+wifi_error nan_subscribe_cancel_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanSubscribeCancelRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ NanCommand *t_nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanSubscribeCancel(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanSubscribeCancel Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+ if (ret == WIFI_SUCCESS) {
+ t_nanCommand = NanCommand::instance(wifiHandle);
+ if (t_nanCommand != NULL) {
+ t_nanCommand->deleteServiceId(msg->subscribe_id,
+ 0, NAN_ROLE_SUBSCRIBER);
+ }
+ }
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send NAN follow up request to the wifi driver.*/
+wifi_error nan_transmit_followup_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanTransmitFollowupRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanTransmitFollowup(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanTransmitFollowup Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send NAN statistics request to the wifi driver.*/
+wifi_error nan_stats_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanStatsRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanStats(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanStats Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send NAN configuration request to the wifi driver.*/
+wifi_error nan_config_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanConfigRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanConfig(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanConfig Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send NAN request to the wifi driver.*/
+wifi_error nan_tca_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanTCARequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanTCA(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanTCA Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to send NAN Beacon sdf payload to the wifi driver.
+ This instructs the Discovery Engine to begin publishing the
+ received payload in any Beacon or Service Discovery Frame
+ transmitted*/
+wifi_error nan_beacon_sdf_payload_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanBeaconSdfPayloadRequest* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanBeaconSdfPayload(id, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanBeaconSdfPayload Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+wifi_error nan_get_sta_parameter(transaction_id id,
+ wifi_interface_handle iface,
+ NanStaParameter* msg)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ nanCommand = NanCommand::instance(wifiHandle);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->getNanStaParameter(iface, msg);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: getNanStaParameter Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ return ret;
+}
+
+/* Function to get NAN capabilities */
+wifi_error nan_get_capabilities(transaction_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanCapabilities(id);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanCapabilities Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+/* Function to get NAN capabilities */
+wifi_error nan_debug_command_config(transaction_id id,
+ wifi_interface_handle iface,
+ NanDebugParams debug,
+ int debug_msg_length)
+{
+ wifi_error ret;
+ NanCommand *nanCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (debug_msg_length <= 0) {
+ ALOGE("%s: Invalid debug message length = %d", __FUNCTION__,
+ debug_msg_length);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nanCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = nanCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = nanCommand->putNanDebugCommand(debug, debug_msg_length);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanDebugCommand Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+wifi_error nan_initialize_vendor_cmd(wifi_interface_handle iface,
+ NanCommand **nanCommand)
+{
+ wifi_error ret;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ if (nanCommand == NULL) {
+ ALOGE("%s: Error nanCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ *nanCommand = new NanCommand(wifiHandle,
+ 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_NDP);
+ if (*nanCommand == NULL) {
+ ALOGE("%s: Object creation failed", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Create the message */
+ ret = (*nanCommand)->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = (*nanCommand)->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ return WIFI_SUCCESS;
+
+cleanup:
+ delete *nanCommand;
+ return ret;
+}
+
+wifi_error nan_data_interface_create(transaction_id id,
+ wifi_interface_handle iface,
+ char* iface_name)
+{
+ ALOGV("NAN_DP_INTERFACE_CREATE");
+ wifi_error ret;
+ struct nlattr *nlData;
+ NanCommand *nanCommand = NULL;
+ WiFiConfigCommand *wifiConfigCommand;
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(handle);
+ bool ndi_created = false;
+
+ if (iface_name == NULL) {
+ ALOGE("%s: Invalid Nan Data Interface Name. \n", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI,
+ &info->driver_supported_features)) {
+ wifiConfigCommand = new WiFiConfigCommand(handle,
+ get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+ info->interfaces[0]->id);
+ wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, iface_name);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE,
+ NL80211_IFTYPE_STATION);
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Create intf failed, Error:%d", __FUNCTION__, ret);
+ delete wifiConfigCommand;
+ return ret;
+ }
+ ndi_created = true;
+ delete wifiConfigCommand;
+ }
+
+ ret = nan_initialize_vendor_cmd(iface, &nanCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ goto delete_ndi;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = nanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE) ||
+ nanCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ id) ||
+ nanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+ iface_name)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ nanCommand->attr_end(nlData);
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+
+delete_ndi:
+ if (ndi_created && ret != WIFI_SUCCESS) {
+ wifiConfigCommand = new WiFiConfigCommand(handle,
+ get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return ret;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+ if_nametoindex(iface_name));
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ if (wifiConfigCommand->requestEvent() != WIFI_SUCCESS)
+ ALOGE("%s: Delete intf failed", __FUNCTION__);
+
+ delete wifiConfigCommand;
+ }
+ return ret;
+}
+
+wifi_error nan_data_interface_delete(transaction_id id,
+ wifi_interface_handle iface,
+ char* iface_name)
+{
+ ALOGV("NAN_DP_INTERFACE_DELETE");
+ wifi_error ret;
+ struct nlattr *nlData;
+ NanCommand *nanCommand = NULL;
+ WiFiConfigCommand *wifiConfigCommand;
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(handle);
+
+ if (iface_name == NULL) {
+ ALOGE("%s: Invalid Nan Data Interface Name. \n", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = nan_initialize_vendor_cmd(iface,
+ &nanCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ goto delete_ndi;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = nanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE) ||
+ nanCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ id) ||
+ nanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+ iface_name)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ nanCommand->attr_end(nlData);
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+
+delete_ndi:
+ if ((check_feature(QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI,
+ &info->driver_supported_features)) &&
+ if_nametoindex(iface_name)) {
+ wifiConfigCommand = new WiFiConfigCommand(handle,
+ get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+ if_nametoindex(iface_name));
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ if (wifiConfigCommand->requestEvent() != WIFI_SUCCESS) {
+ ALOGE("%s: Delete intf failed", __FUNCTION__);
+ }
+ delete wifiConfigCommand;
+ }
+
+ return ret;
+}
+
+/* Service ID using SHA256 */
+static bool
+ndp_create_service_id(const u8 *service_name,
+ u32 service_name_len, u8 *service_id)
+{
+ u8 out_service_id[NAN_SVC_HASH_SIZE] = {0};
+ u8 *mod_service_name;
+ unsigned char prop_oob_service_name[NAN_DEF_SVC_NAME_LEN + 1] =
+ "Wi-Fi Aware Data Path";
+ unsigned char prop_oob_service_name_lowercase[NAN_DEF_SVC_NAME_LEN + 1] =
+ "wi-fi aware data path";
+ bool is_default = false;
+ int i;
+
+ if (!service_name) {
+ ALOGE("%s: NULL service name", __FUNCTION__);
+ return false;
+ }
+
+ if (!service_name_len) {
+ ALOGE("%s: Zero service name length", __FUNCTION__);
+ return false;
+ }
+
+ if (!service_id) {
+ ALOGE("%s: NULL service ID", __FUNCTION__);
+ return false;
+ }
+
+ mod_service_name = (u8 *)malloc(service_name_len);
+ if (!mod_service_name) {
+ ALOGE("%s: malloc failed", __FUNCTION__);
+ return false;
+ }
+
+ memset(mod_service_name, 0, service_name_len);
+ memcpy(mod_service_name, service_name, service_name_len);
+ if ((service_name_len == NAN_DEF_SVC_NAME_LEN) &&
+ (!memcmp(mod_service_name, prop_oob_service_name, service_name_len)
+ || !memcmp(mod_service_name,
+ prop_oob_service_name_lowercase, service_name_len)))
+ is_default = true;
+
+ for (i = 0; i < service_name_len; i++) {
+ /*
+ * As per NAN spec, the only acceptable singlebyte UTF-8 symbols for a
+ * Service Name are alphanumeric values (A-Z, a-z, 0-9), the hyphen ('-'),
+ * the underscore ('_'), and the period ('.').
+ * These checks are added for all service names except the above defined
+ * default service name.
+ */
+ if (!is_default && !isalnum(mod_service_name[i]) &&
+ (mod_service_name[i] != '_') && (mod_service_name[i] != '-') &&
+ (mod_service_name[i] != '.')) {
+ free(mod_service_name);
+ return false;
+ }
+
+ if ((mod_service_name[i] == ' ') && (is_default))
+ goto end;
+
+ /*
+ * The service_name hash SHALL always be done on a lower-case
+ * version of service_name which was passed down. Therefore,
+ * before passing the service_name to the SHA256 function first
+ * run through the string and call tolower on each byte.
+ */
+ mod_service_name[i] = tolower(mod_service_name[i]);
+ }
+
+end:
+ SHA256(mod_service_name, service_name_len, out_service_id);
+ /*
+ * As per NAN spec, Service ID is the first 48 bits of the SHA-256 hash
+ * of the Service Name
+ */
+ memcpy(service_id, out_service_id, NAN_SVC_ID_SIZE);
+
+ free(mod_service_name);
+ return true;
+}
+
+/*
+ * PMK = PBKDF2(<pass phrase>, <Salt Version>||<Cipher Suite ID>||<Service ID>||
+ * <Publisher NMI>, 4096, 32)
+ * ndp_passphrase_to_pmk: API to calculate the service ID and PMK.
+ * @pmk: output value of Hash
+ * @passphrase: secret key
+ * @salt_version: 00
+ * @csid: cipher suite ID: 01
+ * As per NAN spec, below are the values defined for CSID attribute:
+ * 1 - NCS-SK-128 Cipher Suite
+ * 2 - NCS-SK-256 Cipher Suite
+ * 3 - NCS-PK-2WDH-128 Cipher Suite
+ * 4 - NCS-PK-2WDH-256 Cipher Suite
+ * Other values are reserved
+ * @service_id: Hash value of SHA256 on service_name
+ * @peer_mac: Publisher NAN Management Interface address
+ * @iterations: 4096
+ * @pmk_len: 32
+ */
+static int
+ndp_passphrase_to_pmk(u32 cipher_type, u8 *pmk, u8 *passphrase,
+ u32 passphrase_len, u8 *service_name,
+ u32 service_name_len, u8 *svc_id, u8 *peer_mac)
+{
+ int result = 0;
+ u8 pmk_hex[NAN_PMK_INFO_LEN] = {0};
+ u8 salt[NAN_SECURITY_SALT_SIZE] = {0};
+ u8 service_id[NAN_SVC_ID_SIZE] = {0};
+ unsigned char *pos = NULL;
+ unsigned char salt_version = 0;
+ u8 csid;
+ /* We read only first 3-bits, as only 1-4 values are expected currently */
+ csid = (u8)(cipher_type & 0x7);
+ if (csid == 0)
+ csid = NAN_DEFAULT_NCS_SK;
+
+ if (svc_id != NULL) {
+ ALOGV("Service ID received from the pool");
+ memcpy(service_id, svc_id, NAN_SVC_ID_SIZE);
+ } else if (ndp_create_service_id((const u8 *)service_name,
+ service_name_len, service_id) == false) {
+ ALOGE("Failed to create service ID");
+ return result;
+ }
+
+ pos = salt;
+ /* salt version */
+ *pos++ = salt_version;
+ /* CSID */
+ *pos++ = csid;
+ /* Service ID */
+ memcpy(pos, service_id, NAN_SVC_ID_SIZE);
+ pos += NAN_SVC_ID_SIZE;
+ /* Publisher NMI */
+ memcpy(pos, peer_mac, NAN_MAC_ADDR_LEN);
+ pos += NAN_MAC_ADDR_LEN;
+
+ ALOGV("salt dump");
+ hexdump(salt, NAN_SECURITY_SALT_SIZE);
+
+ result = PKCS5_PBKDF2_HMAC((const char *)passphrase, passphrase_len, salt,
+ sizeof(salt), NAN_PMK_ITERATIONS,
+ (const EVP_MD *) EVP_sha256(),
+ NAN_PMK_INFO_LEN, pmk_hex);
+ if (result)
+ memcpy(pmk, pmk_hex, NAN_PMK_INFO_LEN);
+
+ return result;
+}
+
+wifi_error nan_data_request_initiator(transaction_id id,
+ wifi_interface_handle iface,
+ NanDataPathInitiatorRequest* msg)
+{
+ ALOGV("NAN_DP_REQUEST_INITIATOR");
+ wifi_error ret;
+ struct nlattr *nlData, *nlCfgQos;
+ NanCommand *nanCommand = NULL;
+ NanCommand *t_nanCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ if (msg == NULL)
+ return WIFI_ERROR_INVALID_ARGS;
+
+ ret = nan_initialize_vendor_cmd(iface,
+ &nanCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ t_nanCommand = NanCommand::instance(wifiHandle);
+ if (t_nanCommand == NULL)
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+
+ if ((msg->cipher_type != NAN_CIPHER_SUITE_SHARED_KEY_NONE) &&
+ (msg->key_info.body.pmk_info.pmk_len == 0) &&
+ (msg->key_info.body.passphrase_info.passphrase_len == 0)) {
+ ALOGE("%s: Failed-Initiator req, missing pmk and passphrase",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if ((msg->cipher_type != NAN_CIPHER_SUITE_SHARED_KEY_NONE) &&
+ (msg->requestor_instance_id == OUT_OF_BAND_SERVICE_INSTANCE_ID) &&
+ (msg->service_name_len == 0)) {
+ ALOGE("%s: Failed-Initiator req, missing service name for out of band request",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = nanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST) ||
+ nanCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ id) ||
+ nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID,
+ msg->requestor_instance_id) ||
+ nanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR,
+ (char *)msg->peer_disc_mac_addr,
+ NAN_MAC_ADDR_LEN) ||
+ nanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+ msg->ndp_iface)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (msg->channel_request_type != NAN_DP_CHANNEL_NOT_REQUESTED) {
+ if (nanCommand->put_u32 (
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG,
+ msg->channel_request_type) ||
+ nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
+ msg->channel)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+
+ if (msg->app_info.ndp_app_info_len != 0) {
+ if (nanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO,
+ (char *)msg->app_info.ndp_app_info,
+ msg->app_info.ndp_app_info_len)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+
+ if (msg->ndp_cfg.qos_cfg == NAN_DP_CONFIG_QOS) {
+ nlCfgQos =
+ nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS);
+ if (!nlCfgQos){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ /* TBD Qos Info */
+ nanCommand->attr_end(nlCfgQos);
+ }
+ if (msg->cipher_type != NAN_CIPHER_SUITE_SHARED_KEY_NONE) {
+ if (nanCommand->put_u32(QCA_WLAN_VENDOR_ATTR_NDP_CSID,
+ msg->cipher_type)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (msg->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Invalid pmk len:%d", __FUNCTION__,
+ msg->key_info.body.pmk_info.pmk_len);
+ goto cleanup;
+ }
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+ (char *)msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.pmk_info.pmk_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ } else if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ if (msg->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ msg->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Invalid passphrase len:%d", __FUNCTION__,
+ msg->key_info.body.passphrase_info.passphrase_len);
+ goto cleanup;
+ }
+ u8 *service_id = NULL;
+
+ if (t_nanCommand != NULL)
+ service_id = t_nanCommand->getServiceId(msg->requestor_instance_id,
+ NAN_ROLE_SUBSCRIBER);
+ if (service_id == NULL)
+ ALOGE("%s: Entry not found for Instance ID:%d",
+ __FUNCTION__, msg->requestor_instance_id);
+ if (((service_id != NULL) || (msg->service_name_len)) &&
+ ndp_passphrase_to_pmk(msg->cipher_type,
+ msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len,
+ msg->service_name, msg->service_name_len,
+ service_id, msg->peer_disc_mac_addr)) {
+ msg->key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN;
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+ (char *)msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.pmk_info.pmk_len)){
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+ (char *)msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ } else if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+ (char *)msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ if (msg->service_name_len) {
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME,
+ (char *)msg->service_name, msg->service_name_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ nanCommand->attr_end(nlData);
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+wifi_error nan_data_indication_response(transaction_id id,
+ wifi_interface_handle iface,
+ NanDataPathIndicationResponse* msg)
+{
+ ALOGV("NAN_DP_INDICATION_RESPONSE");
+ wifi_error ret;
+ struct nlattr *nlData, *nlCfgQos;
+ NanCommand *nanCommand = NULL;
+ NanCommand *t_nanCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ if (msg == NULL)
+ return WIFI_ERROR_INVALID_ARGS;
+
+ ret = nan_initialize_vendor_cmd(iface,
+ &nanCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ t_nanCommand = NanCommand::instance(wifiHandle);
+ if (t_nanCommand == NULL)
+ ALOGE("%s: Error NanCommand NULL", __FUNCTION__);
+
+ if ((msg->cipher_type != NAN_CIPHER_SUITE_SHARED_KEY_NONE) &&
+ (msg->key_info.body.pmk_info.pmk_len == 0) &&
+ (msg->key_info.body.passphrase_info.passphrase_len == 0)) {
+ ALOGE("%s: Failed-Initiator req, missing pmk and passphrase",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = nanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST) ||
+ nanCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ id) ||
+ nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
+ msg->ndp_instance_id) ||
+ nanCommand->put_string(
+ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+ msg->ndp_iface) ||
+ nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE,
+ msg->rsp_code)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ if (msg->app_info.ndp_app_info_len != 0) {
+ if (nanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO,
+ (char *)msg->app_info.ndp_app_info,
+ msg->app_info.ndp_app_info_len)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ if (msg->ndp_cfg.qos_cfg == NAN_DP_CONFIG_QOS) {
+ nlCfgQos =
+ nanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS);
+ if (!nlCfgQos){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ /* TBD Qos Info */
+ nanCommand->attr_end(nlCfgQos);
+ }
+ if (msg->cipher_type != NAN_CIPHER_SUITE_SHARED_KEY_NONE) {
+ if (nanCommand->put_u32(QCA_WLAN_VENDOR_ATTR_NDP_CSID,
+ msg->cipher_type)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (msg->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Invalid pmk len:%d", __FUNCTION__,
+ msg->key_info.body.pmk_info.pmk_len);
+ goto cleanup;
+ }
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+ (char *)msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.pmk_info.pmk_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ } else if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ if (msg->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ msg->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Invalid passphrase len:%d", __FUNCTION__,
+ msg->key_info.body.passphrase_info.passphrase_len);
+ goto cleanup;
+ }
+ u8 *service_id = NULL;
+
+ if (t_nanCommand != NULL)
+ service_id = t_nanCommand->getServiceId(msg->ndp_instance_id,
+ NAN_ROLE_PUBLISHER);
+ if (service_id == NULL)
+ ALOGE("%s: Entry not found for Instance ID:%d",
+ __FUNCTION__, msg->ndp_instance_id);
+ if (((service_id != NULL) || (msg->service_name_len)) &&
+ (t_nanCommand != NULL) &&
+ ndp_passphrase_to_pmk(msg->cipher_type,
+ msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len,
+ msg->service_name, msg->service_name_len,
+ service_id, t_nanCommand->getNmi())) {
+ msg->key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN;
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+ (char *)msg->key_info.body.pmk_info.pmk,
+ msg->key_info.body.pmk_info.pmk_len))
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+ (char *)msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ } else if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+ (char *)msg->key_info.body.passphrase_info.passphrase,
+ msg->key_info.body.passphrase_info.passphrase_len)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+
+ if (msg->service_name_len) {
+ if (nanCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME,
+ (char *)msg->service_name, msg->service_name_len)){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ }
+ nanCommand->attr_end(nlData);
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+wifi_error nan_data_end(transaction_id id,
+ wifi_interface_handle iface,
+ NanDataPathEndRequest* msg)
+{
+ wifi_error ret;
+ ALOGV("NAN_DP_END");
+ struct nlattr *nlData;
+ NanCommand *nanCommand = NULL;
+
+ if (msg == NULL)
+ return WIFI_ERROR_INVALID_ARGS;
+
+ ret = nan_initialize_vendor_cmd(iface,
+ &nanCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = nanCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (nanCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST) ||
+ nanCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ id) ||
+ nanCommand->put_bytes(
+ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY,
+ (char *)msg->ndp_instance_id,
+ msg->num_ndp_instances * sizeof(u32))) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ nanCommand->attr_end(nlData);
+
+ ret = nanCommand->requestEvent();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete nanCommand;
+ return ret;
+}
+
+// Implementation related to nan class common functions
+// Constructor
+//Making the constructor private since this class is a singleton
+NanCommand::NanCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mHandler, 0,sizeof(mHandler));
+ mNanVendorEvent = NULL;
+ mNanDataLen = 0;
+ mStaParam = NULL;
+ memset(mNmiMac, 0, sizeof(mNmiMac));
+ mStorePubParams = NULL;
+ mStoreSubParams = NULL;
+ mNanMaxPublishes = 0;
+ mNanMaxSubscribes = 0;
+ mNanDiscAddrIndDisabled = false;
+}
+
+NanCommand* NanCommand::instance(wifi_handle handle)
+{
+ hal_info *info;
+
+ if (handle == NULL) {
+ ALOGE("Handle is invalid");
+ return NULL;
+ }
+ info = getHalInfo(handle);
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return NULL;
+ }
+
+ if (mNanCommandInstance == NULL) {
+ mNanCommandInstance = new NanCommand(handle, 0,
+ OUI_QCA,
+ info->support_nan_ext_cmd?
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT :
+ QCA_NL80211_VENDOR_SUBCMD_NAN);
+ ALOGV("NanCommand %p created", mNanCommandInstance);
+ return mNanCommandInstance;
+ } else {
+ if (handle != getWifiHandle(mNanCommandInstance->mInfo)) {
+ /* upper layer must have cleaned up the handle and reinitialized,
+ so we need to update the same */
+ ALOGI("Handle different, update the handle");
+ mNanCommandInstance->mInfo = (hal_info *)handle;
+ }
+ }
+ ALOGV("NanCommand %p created already", mNanCommandInstance);
+ return mNanCommandInstance;
+}
+
+void NanCommand::cleanup()
+{
+ //free the VendorData
+ if (mVendorData) {
+ free(mVendorData);
+ }
+ mVendorData = NULL;
+ //cleanup the mMsg
+ mMsg.destroy();
+}
+
+NanCommand::~NanCommand()
+{
+ ALOGV("NanCommand %p destroyed", this);
+}
+
+int NanCommand::handleResponse(WifiEvent &reply){
+ return NL_SKIP;
+}
+
+/* Save NAN Management Interface address */
+void NanCommand::saveNmi(u8 *mac)
+{
+ memcpy(mNmiMac, mac, NAN_MAC_ADDR_LEN);
+}
+
+/* Get NAN Management Interface address */
+u8 *NanCommand::getNmi()
+{
+ return mNmiMac;
+}
+
+/*
+ * Save the service ID along with Subscribe/Publish ID and Instance ID, which
+ * will be used later for Passphrase to PMK calculation.
+ *
+ * service_id - Service ID received from Firmware either in NAN/NDP Indication
+ * sub_pub_handle - Subscribe/Publish ID received in NAN/NDP Indication
+ * instance_id - Service/NDP instance ID received in NAN/NDP Indication
+ * pool - Subscriber/Publisher entry based on NAN/NDP Indication
+ */
+void NanCommand::saveServiceId(u8 *service_id, u16 sub_pub_handle,
+ u32 instance_id, NanRole pool)
+{
+ int i;
+
+ if ((service_id == NULL) || (!sub_pub_handle) || (!instance_id)) {
+ ALOGE("%s: Null Parameter received, sub_pub_handle=%d instance_id=%d",
+ __FUNCTION__, sub_pub_handle, instance_id);
+ return;
+ }
+ switch(pool) {
+ case NAN_ROLE_PUBLISHER:
+ if ((mStorePubParams == NULL) || !mNanMaxPublishes)
+ return;
+ for (i = 0; i < mNanMaxPublishes; i++) {
+ /* In 1:n case there can be multiple publish entries with same
+ * publish ID, hence save the new entry if instance ID doesn't match
+ * with the existing entries in the pool
+ */
+ if ((mStorePubParams[i].subscriber_publisher_id) &&
+ (mStorePubParams[i].instance_id != instance_id))
+ continue;
+
+ memset(&mStorePubParams[i], 0, sizeof(mStorePubParams));
+ memcpy(mStorePubParams[i].service_id, service_id, NAN_SVC_ID_SIZE);
+ mStorePubParams[i].subscriber_publisher_id = sub_pub_handle;
+ mStorePubParams[i].instance_id = instance_id;
+ ALOGV("Added new entry in Publisher pool at index=%d with "
+ "Publish ID=%d and Instance ID=%d", i,
+ mStorePubParams[i].subscriber_publisher_id,
+ mStorePubParams[i].instance_id);
+ return;
+ }
+ if (i == mNanMaxPublishes)
+ ALOGV("No empty slot found in publisher pool, entry not saved");
+ break;
+ case NAN_ROLE_SUBSCRIBER:
+ if ((mStoreSubParams == NULL) || !mNanMaxSubscribes)
+ return;
+ for (i = 0; i < mNanMaxSubscribes; i++) {
+ /* In 1:n case there can be multiple subscribe entries with same
+ * subscribe ID, hence save new entry if instance ID doesn't match
+ * with the existing entries in the pool
+ */
+ if ((mStoreSubParams[i].subscriber_publisher_id) &&
+ (mStoreSubParams[i].instance_id != instance_id))
+ continue;
+
+ memset(&mStoreSubParams[i], 0, sizeof(mStoreSubParams));
+ memcpy(mStoreSubParams[i].service_id, service_id, NAN_SVC_ID_SIZE);
+ mStoreSubParams[i].subscriber_publisher_id = sub_pub_handle;
+ mStoreSubParams[i].instance_id = instance_id;
+ ALOGV("Added new entry in Subscriber pool at index=%d with "
+ "Subscribe ID=%d and Instance ID=%d", i,
+ mStoreSubParams[i].subscriber_publisher_id,
+ mStoreSubParams[i].instance_id);
+ return;
+ }
+ if (i == mNanMaxSubscribes)
+ ALOGV("No empty slot found in subscriber pool, entry not saved");
+ break;
+ default:
+ ALOGE("Invalid Pool: %d", pool);
+ break;
+ }
+}
+
+/*
+ * Get the Service ID from the pool based on the Service/NDP instance ID that
+ * will be used for Passphrase to PMK calculation in Initiator/Responder request
+ *
+ * instance_id - Service/NDP instance ID received in NAN/NDP Indication
+ * pool - Subscriber/Publisher role based on the Initiator/Responder
+ */
+u8 *NanCommand::getServiceId(u32 instance_id, NanRole pool)
+{
+ int i;
+
+ switch(pool) {
+ case NAN_ROLE_PUBLISHER:
+ if ((mStorePubParams == NULL) || (!instance_id) || !mNanMaxPublishes)
+ return NULL;
+ ALOGV("Getting Service ID from publisher pool for instance ID=%d", instance_id);
+ for (i = 0; i < mNanMaxPublishes; i++) {
+ if (mStorePubParams[i].instance_id == instance_id)
+ return mStorePubParams[i].service_id;
+ }
+ break;
+ case NAN_ROLE_SUBSCRIBER:
+ if ((mStoreSubParams == NULL )|| (!instance_id) || !mNanMaxSubscribes)
+ return NULL;
+ ALOGV("Getting Service ID from subscriber pool for instance ID=%d", instance_id);
+ for (i = 0; i < mNanMaxSubscribes; i++) {
+ if (mStoreSubParams[i].instance_id == instance_id)
+ return mStoreSubParams[i].service_id;
+ }
+ break;
+ default:
+ ALOGE("Invalid Pool: %d", pool);
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Delete service ID entry from the pool based on the subscriber/Instance ID
+ *
+ * sub_handle - Subscriber ID received from the Subscribe Cancel
+ * instance_id - NDP Instance ID received from the NDP End Indication
+ */
+void NanCommand::deleteServiceId(u16 sub_handle,
+ u32 instance_id, NanRole pool)
+{
+ int i;
+
+ switch(pool) {
+ case NAN_ROLE_PUBLISHER:
+ if ((mStorePubParams == NULL) || (!instance_id) || !mNanMaxPublishes)
+ return;
+ for (i = 0; i < mNanMaxPublishes; i++) {
+ /* Delete all the entries that has the matching Instance ID */
+ if (mStorePubParams[i].instance_id == instance_id) {
+ ALOGV("Deleted entry at index=%d from publisher pool "
+ "with publish ID=%d and instance ID=%d", i,
+ mStorePubParams[i].subscriber_publisher_id,
+ mStorePubParams[i].instance_id);
+ memset(&mStorePubParams[i], 0, sizeof(mStorePubParams));
+ }
+ }
+ break;
+ case NAN_ROLE_SUBSCRIBER:
+ if ((mStoreSubParams == NULL) || (!sub_handle) || !mNanMaxSubscribes)
+ return;
+ for (i = 0; i < mNanMaxSubscribes; i++) {
+ /* Delete all the entries that has the matching subscribe ID */
+ if (mStoreSubParams[i].subscriber_publisher_id == sub_handle) {
+ ALOGV("Deleted entry at index=%d from subsriber pool "
+ "with subscribe ID=%d and instance ID=%d", i,
+ mStoreSubParams[i].subscriber_publisher_id,
+ mStoreSubParams[i].instance_id);
+ memset(&mStoreSubParams[i], 0, sizeof(mStoreSubParams));
+ }
+ }
+ break;
+ default:
+ ALOGE("Invalid Pool: %d", pool);
+ break;
+ }
+}
+
+/*
+ * Allocate the memory for the Subscribe and Publish pools using the Max values
+ * mStorePubParams - Points the Publish pool
+ * mStoreSubParams - Points the Subscribe pool
+ */
+void NanCommand::allocSvcParams()
+{
+ if (mNanMaxPublishes < NAN_DEF_PUB_SUB)
+ mNanMaxPublishes = NAN_DEF_PUB_SUB;
+ if (mNanMaxSubscribes < NAN_DEF_PUB_SUB)
+ mNanMaxSubscribes = NAN_DEF_PUB_SUB;
+
+ if ((mStorePubParams == NULL) && mNanMaxPublishes) {
+ mStorePubParams =
+ (NanStoreSvcParams *)malloc(mNanMaxPublishes*sizeof(NanStoreSvcParams));
+ if (mStorePubParams == NULL) {
+ ALOGE("%s: Publish pool malloc failed", __FUNCTION__);
+ deallocSvcParams();
+ return;
+ }
+ ALOGV("%s: Allocated the Publish pool for max %d entries",
+ __FUNCTION__, mNanMaxPublishes);
+ }
+ if ((mStoreSubParams == NULL) && mNanMaxSubscribes) {
+ mStoreSubParams =
+ (NanStoreSvcParams *)malloc(mNanMaxSubscribes*sizeof(NanStoreSvcParams));
+ if (mStoreSubParams == NULL) {
+ ALOGE("%s: Subscribe pool malloc failed", __FUNCTION__);
+ deallocSvcParams();
+ return;
+ }
+ ALOGV("%s: Allocated the Subscribe pool for max %d entries",
+ __FUNCTION__, mNanMaxSubscribes);
+ }
+}
+
+/*
+ * Reallocate the memory for Subscribe and Publish pools using the Max values
+ * mStorePubParams - Points the Publish pool
+ * mStoreSubParams - Points the Subscribe pool
+ */
+void NanCommand::reallocSvcParams(NanRole pool)
+{
+ switch(pool) {
+ case NAN_ROLE_PUBLISHER:
+ if ((mStorePubParams != NULL) && mNanMaxPublishes) {
+ mStorePubParams =
+ (NanStoreSvcParams *)realloc(mStorePubParams,
+ mNanMaxPublishes*sizeof(NanStoreSvcParams));
+ if (mStorePubParams == NULL) {
+ ALOGE("%s: Publish pool realloc failed", __FUNCTION__);
+ deallocSvcParams();
+ return;
+ }
+ ALOGV("%s: Reallocated the Publish pool for max %d entries",
+ __FUNCTION__, mNanMaxPublishes);
+ }
+ break;
+ case NAN_ROLE_SUBSCRIBER:
+ if ((mStoreSubParams != NULL) && mNanMaxSubscribes) {
+ mStoreSubParams =
+ (NanStoreSvcParams *)realloc(mStoreSubParams,
+ mNanMaxSubscribes*sizeof(NanStoreSvcParams));
+ if (mStoreSubParams == NULL) {
+ ALOGE("%s: Subscribe pool realloc failed", __FUNCTION__);
+ deallocSvcParams();
+ return;
+ }
+ ALOGV("%s: Reallocated the Subscribe pool for max %d entries",
+ __FUNCTION__, mNanMaxSubscribes);
+ }
+ break;
+ default:
+ ALOGE("Invalid Pool: %d", pool);
+ break;
+ }
+}
+
+/*
+ * Deallocate the Subscribe and Publish pools
+ * mStorePubParams - Points the Publish pool
+ * mStoreSubParams - Points the Subscribe pool
+ */
+void NanCommand::deallocSvcParams()
+{
+ if (mStorePubParams != NULL) {
+ free(mStorePubParams);
+ mStorePubParams = NULL;
+ ALOGV("%s: Deallocated Publish pool", __FUNCTION__);
+ }
+ if (mStoreSubParams != NULL) {
+ free(mStoreSubParams);
+ mStoreSubParams = NULL;
+ ALOGV("%s: Deallocated Subscribe pool", __FUNCTION__);
+ }
+}
+
+wifi_error NanCommand::setCallbackHandler(NanCallbackHandler nHandler)
+{
+ wifi_error res;
+ mHandler = nHandler;
+ res = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_NAN);
+ if (res != WIFI_SUCCESS) {
+ //error case should not happen print log
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x"
+ "subcmd=QCA_NL80211_VENDOR_SUBCMD_NAN", __FUNCTION__, mVendor_id);
+ return res;
+ }
+
+ res = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_NDP);
+ if (res != WIFI_SUCCESS) {
+ //error case should not happen print log
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x"
+ "subcmd=QCA_NL80211_VENDOR_SUBCMD_NDP", __FUNCTION__, mVendor_id);
+ return res;
+ }
+ return res;
+}
+
+/* This function implements creation of Vendor command */
+wifi_error NanCommand::create() {
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+ /* Insert the oui in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+ /* Insert the subcmd in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+
+out:
+ if (ret != WIFI_SUCCESS)
+ mMsg.destroy();
+ return ret;
+}
+
+// This function will be the main handler for incoming event
+// QCA_NL80211_VENDOR_SUBCMD_NAN
+//Call the appropriate callback handler after parsing the vendor data.
+int NanCommand::handleEvent(WifiEvent &event)
+{
+ WifiVendorCommand::handleEvent(event);
+ ALOGV("%s: Subcmd=%u Vendor data len received:%d",
+ __FUNCTION__, mSubcmd, mDataLen);
+ hexdump(mVendorData, mDataLen);
+
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN){
+ // Parse the vendordata and get the NAN attribute
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+ // Populating the mNanVendorEvent and mNanDataLen to point to NAN data.
+ mNanVendorEvent = (char *)nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NAN]);
+ mNanDataLen = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NAN]);
+
+ if (isNanResponse()) {
+ //handleNanResponse will parse the data and call
+ //the response callback handler with the populated
+ //NanResponseMsg
+ handleNanResponse();
+ } else {
+ //handleNanIndication will parse the data and call
+ //the corresponding Indication callback handler
+ //with the corresponding populated Indication event
+ handleNanIndication();
+ }
+ } else if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NDP) {
+ // Parse the vendordata and get the NAN attribute
+ u32 ndpCmdType;
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]) {
+ ndpCmdType =
+ nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]);
+ ALOGD("%s: NDP Cmd Type : val 0x%x",
+ __FUNCTION__, ndpCmdType);
+ switch (ndpCmdType) {
+ case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE:
+ handleNdpResponse(NAN_DP_INTERFACE_CREATE, tb_vendor);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE:
+ handleNdpResponse(NAN_DP_INTERFACE_DELETE, tb_vendor);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE:
+ handleNdpResponse(NAN_DP_INITIATOR_RESPONSE, tb_vendor);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE:
+ handleNdpResponse(NAN_DP_RESPONDER_RESPONSE, tb_vendor);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_NDP_END_RESPONSE:
+ handleNdpResponse(NAN_DP_END, tb_vendor);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND:
+ case QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND:
+ case QCA_WLAN_VENDOR_ATTR_NDP_END_IND:
+ case QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND:
+ handleNdpIndication(ndpCmdType, tb_vendor);
+ break;
+ default:
+ ALOGE("%s: Invalid NDP subcmd response received %d",
+ __FUNCTION__, ndpCmdType);
+ }
+ }
+ } else {
+ //error case should not happen print log
+ ALOGE("%s: Wrong NAN subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+ mNanVendorEvent = NULL;
+ return NL_SKIP;
+}
+
+/*Helper function to Write and Read TLV called in indication as well as request */
+u16 NANTLV_WriteTlv(pNanTlv pInTlv, u8 *pOutTlv)
+{
+ u16 writeLen = 0;
+ u16 i;
+
+ if (!pInTlv)
+ {
+ ALOGE("NULL pInTlv");
+ return writeLen;
+ }
+
+ if (!pOutTlv)
+ {
+ ALOGE("NULL pOutTlv");
+ return writeLen;
+ }
+
+ *pOutTlv++ = pInTlv->type & 0xFF;
+ *pOutTlv++ = (pInTlv->type & 0xFF00) >> 8;
+ writeLen += 2;
+
+ ALOGV("WRITE TLV type %u, writeLen %u", pInTlv->type, writeLen);
+
+ *pOutTlv++ = pInTlv->length & 0xFF;
+ *pOutTlv++ = (pInTlv->length & 0xFF00) >> 8;
+ writeLen += 2;
+
+ ALOGV("WRITE TLV length %u, writeLen %u", pInTlv->length, writeLen);
+
+ for (i=0; i < pInTlv->length; ++i)
+ {
+ *pOutTlv++ = pInTlv->value[i];
+ }
+
+ writeLen += pInTlv->length;
+ ALOGV("WRITE TLV value, writeLen %u", writeLen);
+ return writeLen;
+}
+
+u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv, int inBufferSize)
+{
+ u16 readLen = 0;
+
+ if (!pInTlv)
+ {
+ ALOGE("NULL pInTlv");
+ return readLen;
+ }
+
+ if (!pOutTlv)
+ {
+ ALOGE("NULL 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;
+
+ ALOGV("READ TLV type %u, readLen %u", pOutTlv->type, readLen);
+
+ pOutTlv->length = *pInTlv++;
+ pOutTlv->length |= *pInTlv++ << 8;
+ readLen += 2;
+
+ if(pOutTlv->length > (u16)(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) {
+ pOutTlv->value = pInTlv;
+ readLen += pOutTlv->length;
+ } else {
+ pOutTlv->value = NULL;
+ }
+
+ ALOGV("READ TLV readLen %u", readLen);
+ return readLen;
+}
+
+u8* addTlv(u16 type, u16 length, const u8* value, u8* pOutTlv)
+{
+ NanTlv nanTlv;
+ u16 len;
+
+ nanTlv.type = type;
+ nanTlv.length = length;
+ nanTlv.value = (u8*)value;
+
+ len = NANTLV_WriteTlv(&nanTlv, pOutTlv);
+ return (pOutTlv + len);
+}
diff --git a/wcn6740/qcwcn/wifi_hal/nan_cert.h b/wcn6740/qcwcn/wifi_hal/nan_cert.h
new file mode 100644
index 0000000..19b2882
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nan_cert.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016-2017, 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 __NAN_CERT_H__
+#define __NAN_CERT_H__
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+#define NAN_CERT_VERSION 5
+#define NAN_MAX_DEBUG_MESSAGE_DATA_LEN 100
+#define NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL 16
+
+typedef struct {
+ /* NAN master rank being advertised by DE */
+ u64 master_rank;
+ /* NAN master preference being advertised by DE */
+ u8 master_pref;
+ /* random value being advertised by DE */
+ u8 random_factor;
+ /* hop_count from anchor master */
+ u8 hop_count;
+ u32 beacon_transmit_time;
+ /* NDP channel Frequency */
+ u32 ndp_channel_freq;
+} NanStaParameter;
+
+/* NAN Data Path Supported Band */
+typedef enum {
+ NAN_DATA_PATH_SUPPORTED_BAND_2G = 1,
+ NAN_DATA_PATH_SUPPORTED_BAND_5G = 2,
+ NAN_DATA_PATH_SUPPORT_DUAL_BAND = 3
+} NdpSupportedBand;
+
+/* NAN Responder mode policy */
+typedef enum {
+ NAN_DATA_RESPONDER_MODE_AUTO = 0,
+ NAN_DATA_RESPONDER_MODE_ACCEPT = 1,
+ NAN_DATA_RESPONDER_MODE_REJECT = 2,
+ NAN_DATA_RESPONDER_MODE_COUNTER = 3,
+ NAN_DATA_RESPONDER_MODE_COUNTER_NO_CHANNEL_CHANGE = 4
+} NanDataResponderMode;
+
+/* NAN Data Path M4 response type */
+typedef enum {
+ NAN_DATA_PATH_M4_RESPONSE_ACCEPT = 1,
+ NAN_DATA_PATH_M4_RESPONSE_REJECT = 2,
+ NAN_DATA_PATH_M4_RESPONSE_BADMIC = 3
+} NdpM4ResponseType;
+
+/* NAN NMF Security Clear type */
+typedef enum {
+ NAN_NMF_CLEAR_DISABLE = 0,
+ NAN_NMF_CLEAR_ENABLE = 1
+} NanNmfClearConfig;
+
+/* NAN Schedule type */
+typedef enum {
+ NAN_SCHED_VALID = 0,
+ NAN_SCHED_INVALID_BAD_FA = 1,
+ NAN_SCHED_INVALID_BAD_NDC = 2,
+ NAN_SCHED_INVALID_BAD_IMMU = 3
+} NanSchedType;
+
+/* NAN device type */
+typedef enum {
+ NAN_DEVICE_TYPE_TEST_BED = 1,
+ NAN_DEVICE_TYPE_DUT = 2
+} NanDeviceType;
+
+/* NAN NDPE absent or present */
+typedef enum {
+ NAN_NDPE_ATTR_PRESENT = 0,
+ NAN_NDPE_ATTR_ABSENT = 1
+} NanNdpeAttrType;
+
+/* NAN NDP absent or present */
+typedef enum {
+ NAN_NDP_ATTR_ABSENT = 0,
+ NAN_NDP_ATTR_PRESENT = 1
+} NanNdpAttrType;
+
+/* NAN IPV6 implicit or explicit */
+typedef enum {
+ NAN_IPV6_EXPLICIT = 0,
+ NAN_IPV6_IMPLICIT = 1
+} NanIPv6Type;
+
+/* NAN IPV6 address, port number and protocol type */
+#define NAN_MSG_IPV6_INTF_ADDR_LEN 16
+
+typedef struct PACKED
+{
+ /* Presence of ipv6_intf_addr */
+ u32 ipv6_addr_present;
+ /* Presence of transport Port */
+ u32 trans_port_present;
+ /* Presence of transport Protocol */
+ u32 trans_proto_present;
+ /* ipv6 Interface address */
+ u8 ipv6_intf_addr[NAN_MSG_IPV6_INTF_ADDR_LEN];
+ /* Transport Port */
+ u32 transport_port;
+ /* Transport Protocol */
+ u32 transport_protocol;
+} NdpIpTransParams, *pNdpIpTransParams;
+
+ /*
+ * Definitions of debug subcommand type for the
+ * generic debug command.
+ */
+typedef enum {
+ NAN_TEST_MODE_CMD_NAN_AVAILABILITY = 1,
+ NAN_TEST_MODE_CMD_NDP_INCLUDE_IMMUTABLE = 2,
+ NAN_TEST_MODE_CMD_NDP_AVOID_CHANNEL = 3,
+ NAN_TEST_MODE_CMD_NAN_SUPPORTED_BANDS = 4,
+ NAN_TEST_MODE_CMD_AUTO_RESPONDER_MODE = 5,
+ NAN_TEST_MODE_CMD_M4_RESPONSE_TYPE = 6,
+ NAN_TEST_MODE_CMD_NAN_SCHED_TYPE = 7,
+ NAN_TEST_MODE_CMD_NAN_NMF_CLEAR_CONFIG = 8,
+ NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_ULW_NOTIFY = 9,
+ NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NEGOTIATE = 10,
+ NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NOTIFY = 11,
+ NAN_TEST_MODE_CMD_NAN_AVAILABILITY_MAP_ORDER = 12,
+ NAN_TEST_MODE_CMD_CONFIG_QOS = 13,
+ NAN_TEST_MODE_CMD_DEVICE_TYPE = 14,
+ NAN_TEST_MODE_CMD_DISABLE_NDPE = 15,
+ NAN_TEST_MODE_CMD_ENABLE_NDP = 16,
+ NAN_TEST_MODE_CMD_DISABLE_IPV6_LINK_LOCAL = 17,
+ NAN_TEST_MODE_CMD_TRANSPORT_IP_PARAM = 18,
+} NanDebugModeCmd;
+
+/*
+ * This debug command carries any one command type
+ * followed by corresponding command data content
+ * as indicated below.
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_AVAILABILITY
+ * content: NAN Avaiability attribute blob
+ *
+ * command: NAN_TEST_MODE_CMD_NDP_INCLUDE_IMMUTABLE
+ * content: u32 value (0 - Ignore 1 - Include immuatable,
+ * 2 - Don't include immutable)
+ *
+ * command: NAN_TEST_MODE_CMD_NDP_AVOID_CHANNEL
+ * content: u32 channel_frequency; (0 - Ignore)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_SUPPORTED_BANDS
+ * content: u32 supported_bands; (0 . Ignore, 1 . 2g,
+ * 2 . 5g, 3 . 2g & 5g)
+ *
+ * command: NAN_TEST_MODE_CMD_AUTO_RESPONDER_MODE
+ * content: u32 auto_resp_mode; (0 . Auto, 1 . Accept,
+ * 2 . Reject, 3 . Counter)
+ *
+ * command: NAN_TEST_MODE_CMD_M4_RESPONSE_TYPE
+ * content: u32 m4_response_type; (0.Ignore, 1.Accept,
+ * 2.Reject, 3.BadMic)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_SCHED_TYPE
+ * content: u32 invalid_nan_schedule; (0. Valid sched,
+ * 1.Invalid Sched bad FA,
+ * 2.Invalid schedbad NDC,
+ * 3.Invalid sched bad Immutable)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_NMF_CLEAR_CONFIG
+ * content: u32 nmf_security_config_val;(0:NAN_NMF_CLEAR_DISABLE,
+ * 1:NAN_NMF_CLEAR_ENABLE)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_ULW_NOTIFY
+ * content: u32 channel_availability;(0/1)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NEGOTIATE
+ * content: responder_nmi_mac (Responder NMI Mac Address)
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NOTIFY
+ * content: NONE
+ *
+ * command: NAN_TEST_MODE_CMD_NAN_AVAILABILITY_MAP_ORDER
+ * content: u32 map_order_val; (0/1)
+ *
+ */
+typedef struct PACKED {
+ /*
+ * To indicate the debug command type.
+ */
+ u32 cmd;
+ /*
+ * To hold the data for the above command
+ * type.
+ */
+ u8 debug_cmd_data[NAN_MAX_DEBUG_MESSAGE_DATA_LEN];
+} NanDebugParams;
+
+/*
+ Function to get the sta_parameter expected by Sigma
+ as per CAPI spec.
+*/
+wifi_error nan_get_sta_parameter(transaction_id id,
+ wifi_interface_handle iface,
+ NanStaParameter* msg);
+
+wifi_error nan_debug_command_config(transaction_id id,
+ wifi_interface_handle iface,
+ NanDebugParams msg,
+ int debug_msg_length);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __NAN_CERT_H__ */
+
diff --git a/wcn6740/qcwcn/wifi_hal/nan_i.h b/wcn6740/qcwcn/wifi_hal/nan_i.h
new file mode 100644
index 0000000..ad69e18
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nan_i.h
@@ -0,0 +1,1328 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 __NAN_I_H__
+#define __NAN_I_H__
+
+#include "common.h"
+#include "cpp_bindings.h"
+#include "wifi_hal.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+#define BIT_NONE 0x00
+#define BIT_0 0x01
+#define BIT_1 0x02
+#define BIT_2 0x04
+#define BIT_3 0x08
+#define BIT_4 0x10
+#define BIT_5 0x20
+#define BIT_6 0x40
+#define BIT_7 0x80
+#define BIT_8 0x0100
+#define BIT_9 0x0200
+#define BIT_10 0x0400
+#define BIT_11 0x0800
+#define BIT_12 0x1000
+#define BIT_13 0x2000
+#define BIT_14 0x4000
+#define BIT_15 0x8000
+#define BIT_16 0x010000
+#define BIT_17 0x020000
+#define BIT_18 0x040000
+#define BIT_19 0x080000
+#define BIT_20 0x100000
+#define BIT_21 0x200000
+#define BIT_22 0x400000
+#define BIT_23 0x800000
+#define BIT_24 0x01000000
+#define BIT_25 0x02000000
+#define BIT_26 0x04000000
+#define BIT_27 0x08000000
+#define BIT_28 0x10000000
+#define BIT_29 0x20000000
+#define BIT_30 0x40000000
+#define BIT_31 0x80000000
+
+/** macro to convert FW MAC address from WMI word format to User Space MAC char array */
+#define FW_MAC_ADDR_TO_CHAR_ARRAY(fw_mac_addr, mac_addr) do { \
+ (mac_addr)[0] = ((fw_mac_addr).mac_addr31to0) & 0xff; \
+ (mac_addr)[1] = (((fw_mac_addr).mac_addr31to0) >> 8) & 0xff; \
+ (mac_addr)[2] = (((fw_mac_addr).mac_addr31to0) >> 16) & 0xff; \
+ (mac_addr)[3] = (((fw_mac_addr).mac_addr31to0) >> 24) & 0xff; \
+ (mac_addr)[4] = ((fw_mac_addr).mac_addr47to32) & 0xff; \
+ (mac_addr)[5] = (((fw_mac_addr).mac_addr47to32) >> 8) & 0xff; \
+} while (0)
+
+/** macro to convert User space MAC address from char array to FW WMI word format */
+#define CHAR_ARRAY_TO_MAC_ADDR(mac_addr, fw_mac_addr) do { \
+ (fw_mac_addr).mac_addr31to0 = \
+ ((mac_addr)[0] | ((mac_addr)[1] << 8) \
+ | ((mac_addr)[2] << 16) | ((mac_addr)[3] << 24)); \
+ (fw_mac_addr).mac_addr47to32 = \
+ ((mac_addr)[4] | ((mac_addr)[5] << 8)); \
+} while (0)
+
+/*---------------------------------------------------------------------------
+* WLAN NAN CONSTANTS
+*--------------------------------------------------------------------------*/
+
+typedef enum
+{
+ NAN_MSG_ID_ERROR_RSP = 0,
+ NAN_MSG_ID_CONFIGURATION_REQ = 1,
+ NAN_MSG_ID_CONFIGURATION_RSP = 2,
+ NAN_MSG_ID_PUBLISH_SERVICE_REQ = 3,
+ NAN_MSG_ID_PUBLISH_SERVICE_RSP = 4,
+ NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ = 5,
+ NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_RSP = 6,
+ NAN_MSG_ID_PUBLISH_REPLIED_IND = 7,
+ NAN_MSG_ID_PUBLISH_TERMINATED_IND = 8,
+ NAN_MSG_ID_SUBSCRIBE_SERVICE_REQ = 9,
+ NAN_MSG_ID_SUBSCRIBE_SERVICE_RSP = 10,
+ NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ = 11,
+ NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_RSP = 12,
+ NAN_MSG_ID_MATCH_IND = 13,
+ NAN_MSG_ID_MATCH_EXPIRED_IND = 14,
+ NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND = 15,
+ NAN_MSG_ID_DE_EVENT_IND = 16,
+ NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ = 17,
+ NAN_MSG_ID_TRANSMIT_FOLLOWUP_RSP = 18,
+ NAN_MSG_ID_FOLLOWUP_IND = 19,
+ NAN_MSG_ID_STATS_REQ = 20,
+ NAN_MSG_ID_STATS_RSP = 21,
+ NAN_MSG_ID_ENABLE_REQ = 22,
+ NAN_MSG_ID_ENABLE_RSP = 23,
+ NAN_MSG_ID_DISABLE_REQ = 24,
+ NAN_MSG_ID_DISABLE_RSP = 25,
+ NAN_MSG_ID_DISABLE_IND = 26,
+ NAN_MSG_ID_TCA_REQ = 27,
+ NAN_MSG_ID_TCA_RSP = 28,
+ NAN_MSG_ID_TCA_IND = 29,
+ NAN_MSG_ID_BEACON_SDF_REQ = 30,
+ NAN_MSG_ID_BEACON_SDF_RSP = 31,
+ NAN_MSG_ID_BEACON_SDF_IND = 32,
+ NAN_MSG_ID_CAPABILITIES_REQ = 33,
+ NAN_MSG_ID_CAPABILITIES_RSP = 34,
+ NAN_MSG_ID_SELF_TRANSMIT_FOLLOWUP_IND = 35,
+ NAN_MSG_ID_RANGING_REQUEST_RECEVD_IND = 36,
+ NAN_MSG_ID_RANGING_RESULT_IND = 37,
+ NAN_MSG_ID_TESTMODE_REQ = 1025,
+ NAN_MSG_ID_TESTMODE_RSP = 1026
+} NanMsgId;
+
+/*
+ Various TLV Type ID sent as part of NAN Stats Response
+ or NAN TCA Indication
+*/
+typedef enum
+{
+ NAN_TLV_TYPE_FIRST = 0,
+
+ /* Service Discovery Frame types */
+ NAN_TLV_TYPE_SDF_FIRST = NAN_TLV_TYPE_FIRST,
+ NAN_TLV_TYPE_SERVICE_NAME = NAN_TLV_TYPE_SDF_FIRST,
+ NAN_TLV_TYPE_SDF_MATCH_FILTER,
+ NAN_TLV_TYPE_TX_MATCH_FILTER,
+ NAN_TLV_TYPE_RX_MATCH_FILTER,
+ NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO,
+ NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO =5,
+ NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_TRANSMIT = 6,
+ NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE = 7,
+ NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE = 8,
+ NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE = 9,
+ NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE = 10,
+ NAN_TLV_TYPE_NAN_DATA_PATH_PARAMS = 11,
+ NAN_TLV_TYPE_NAN_DATA_SUPPORTED_BAND = 12,
+ NAN_TLV_TYPE_2G_COMMITTED_DW = 13,
+ NAN_TLV_TYPE_5G_COMMITTED_DW = 14,
+ NAN_TLV_TYPE_NAN_DATA_RESPONDER_MODE = 15,
+ NAN_TLV_TYPE_NAN_DATA_ENABLED_IN_MATCH = 16,
+ NAN_TLV_TYPE_NAN_SERVICE_ACCEPT_POLICY = 17,
+ NAN_TLV_TYPE_NAN_CSID = 18,
+ NAN_TLV_TYPE_NAN_SCID = 19,
+ NAN_TLV_TYPE_NAN_PMK = 20,
+ NAN_TLV_TYPE_SDEA_CTRL_PARAMS = 21,
+ NAN_TLV_TYPE_NAN_RANGING_CFG = 22,
+ NAN_TLV_TYPE_CONFIG_DISCOVERY_INDICATIONS = 23,
+ NAN_TLV_TYPE_NAN20_RANGING_REQUEST = 24,
+ NAN_TLV_TYPE_NAN20_RANGING_RESULT = 25,
+ NAN_TLV_TYPE_NAN20_RANGING_REQUEST_RECEIVED = 26,
+ NAN_TLV_TYPE_NAN_PASSPHRASE = 27,
+ NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO = 28,
+ NAN_TLV_TYPE_DEV_CAP_ATTR_CAPABILITY = 29,
+ NAN_TLV_TYPE_IP_TRANSPORT_PARAM = 30,
+ NAN_TLV_TYPE_SERVICE_ID = 31,
+ NAN_TLV_TYPE_SDF_LAST = 4095,
+
+ /* Configuration types */
+ NAN_TLV_TYPE_CONFIG_FIRST = 4096,
+ NAN_TLV_TYPE_24G_SUPPORT = NAN_TLV_TYPE_CONFIG_FIRST,
+ NAN_TLV_TYPE_24G_BEACON,
+ NAN_TLV_TYPE_24G_SDF,
+ NAN_TLV_TYPE_24G_RSSI_CLOSE,
+ NAN_TLV_TYPE_24G_RSSI_MIDDLE = 4100,
+ NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY,
+ NAN_TLV_TYPE_5G_SUPPORT,
+ NAN_TLV_TYPE_5G_BEACON,
+ NAN_TLV_TYPE_5G_SDF,
+ NAN_TLV_TYPE_5G_RSSI_CLOSE,
+ NAN_TLV_TYPE_5G_RSSI_MIDDLE,
+ NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
+ NAN_TLV_TYPE_SID_BEACON,
+ NAN_TLV_TYPE_HOP_COUNT_LIMIT,
+ NAN_TLV_TYPE_MASTER_PREFERENCE = 4110,
+ NAN_TLV_TYPE_CLUSTER_ID_LOW,
+ NAN_TLV_TYPE_CLUSTER_ID_HIGH,
+ NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE,
+ NAN_TLV_TYPE_CLUSTER_OUI_NETWORK_ID,
+ NAN_TLV_TYPE_SOURCE_MAC_ADDRESS,
+ NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF,
+ NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
+ NAN_TLV_TYPE_DEBUGGING_FLAGS,
+ NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_TRANSMIT,
+ NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_TRANSMIT = 4120,
+ NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP,
+ NAN_TLV_TYPE_HOP_COUNT_FORCE,
+ NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
+ NAN_TLV_TYPE_RANDOM_UPDATE_TIME = 4124,
+ NAN_TLV_TYPE_EARLY_WAKEUP,
+ NAN_TLV_TYPE_PERIODIC_SCAN_INTERVAL,
+ NAN_TLV_TYPE_DW_INTERVAL = 4128,
+ NAN_TLV_TYPE_DB_INTERVAL,
+ NAN_TLV_TYPE_FURTHER_AVAILABILITY,
+ NAN_TLV_TYPE_24G_CHANNEL,
+ NAN_TLV_TYPE_5G_CHANNEL,
+ NAN_TLV_TYPE_DISC_MAC_ADDR_RANDOM_INTERVAL,
+ NAN_TLV_TYPE_RANGING_AUTO_RESPONSE_CFG = 4134,
+ NAN_TLV_TYPE_SUBSCRIBE_SID_BEACON = 4135,
+ NAN_TLV_TYPE_DW_EARLY_TERMINATION = 4136,
+ NAN_TLV_TYPE_TX_RX_CHAINS = 4137,
+ NAN_TLV_TYPE_ENABLE_DEVICE_RANGING = 4138,
+ NAN_TLV_TYPE_CONFIG_LAST = 8191,
+
+ /* Attributes types */
+ NAN_TLV_TYPE_ATTRS_FIRST = 8192,
+ NAN_TLV_TYPE_AVAILABILITY_INTERVALS_MAP = NAN_TLV_TYPE_ATTRS_FIRST,
+ NAN_TLV_TYPE_WLAN_MESH_ID,
+ NAN_TLV_TYPE_MAC_ADDRESS,
+ NAN_TLV_TYPE_RECEIVED_RSSI_VALUE,
+ NAN_TLV_TYPE_CLUSTER_ATTRIBUTE,
+ NAN_TLV_TYPE_WLAN_INFRA_SSID,
+ NAN_TLV_TYPE_ATTRS_LAST = 12287,
+
+ /* Events Type */
+ NAN_TLV_TYPE_EVENTS_FIRST = 12288,
+ NAN_TLV_TYPE_EVENT_SELF_STATION_MAC_ADDRESS = NAN_TLV_TYPE_EVENTS_FIRST,
+ NAN_TLV_TYPE_EVENT_STARTED_CLUSTER,
+ NAN_TLV_TYPE_EVENT_JOINED_CLUSTER,
+ NAN_TLV_TYPE_EVENT_CLUSTER_SCAN_RESULTS,
+ NAN_TLV_TYPE_FAW_MEM_AVAIL,
+ NAN_TLV_TYPE_EVENTS_LAST = 16383,
+
+ /* TCA types */
+ NAN_TLV_TYPE_TCA_FIRST = 16384,
+ NAN_TLV_TYPE_CLUSTER_SIZE_REQ = NAN_TLV_TYPE_TCA_FIRST,
+ NAN_TLV_TYPE_CLUSTER_SIZE_RSP,
+ NAN_TLV_TYPE_TCA_LAST = 32767,
+
+ /* Statistics types */
+ NAN_TLV_TYPE_STATS_FIRST = 32768,
+ NAN_TLV_TYPE_DE_PUBLISH_STATS = NAN_TLV_TYPE_STATS_FIRST,
+ NAN_TLV_TYPE_DE_SUBSCRIBE_STATS,
+ NAN_TLV_TYPE_DE_MAC_STATS,
+ NAN_TLV_TYPE_DE_TIMING_SYNC_STATS,
+ NAN_TLV_TYPE_DE_DW_STATS,
+ NAN_TLV_TYPE_DE_STATS,
+ NAN_TLV_TYPE_STATS_LAST = 36863,
+
+ /* Testmode types */
+ NAN_TLV_TYPE_TESTMODE_FIRST = 36864,
+ NAN_TLV_TYPE_TESTMODE_GENERIC_CMD = NAN_TLV_TYPE_TESTMODE_FIRST,
+ NAN_TLV_TYPE_TESTMODE_LAST = 37000,
+
+ NAN_TLV_TYPE_LAST = 65535
+} NanTlvType;
+
+/* 8-byte control message header used by NAN*/
+typedef struct PACKED
+{
+ u16 msgVersion:4;
+ u16 msgId:12;
+ u16 msgLen;
+ u16 handle;
+ u16 transactionId;
+} NanMsgHeader, *pNanMsgHeader;
+
+/* Enumeration for Version */
+typedef enum
+{
+ NAN_MSG_VERSION1 = 1,
+}NanMsgVersion;
+
+typedef struct PACKED
+{
+ u16 type;
+ u16 length;
+ u8* value;
+} NanTlv, *pNanTlv;
+
+#define SIZEOF_TLV_HDR (sizeof(NanTlv::type) + sizeof(NanTlv::length))
+/* NAN TLV Groups and Types */
+typedef enum
+{
+ NAN_TLV_GROUP_FIRST = 0,
+ NAN_TLV_GROUP_SDF = NAN_TLV_GROUP_FIRST,
+ NAN_TLV_GROUP_CONFIG,
+ NAN_TLV_GROUP_STATS,
+ NAN_TLV_GROUP_ATTRS,
+ NAN_TLV_NUM_GROUPS,
+ NAN_TLV_GROUP_LAST = NAN_TLV_NUM_GROUPS
+} NanTlvGroup;
+
+/* NAN Miscellaneous Constants */
+#define NAN_TTL_INFINITE 0
+#define NAN_REPLY_COUNT_INFINITE 0
+
+/* NAN Confguration 5G Channel Access Bit */
+#define NAN_5G_CHANNEL_ACCESS_UNSUPPORTED 0
+#define NAN_5G_CHANNEL_ACCESS_SUPPORTED 1
+
+/* NAN Configuration Service IDs Enclosure Bit */
+#define NAN_SIDS_NOT_ENCLOSED_IN_BEACONS 0
+#define NAN_SIBS_ENCLOSED_IN_BEACONS 1
+
+/* NAN Configuration Priority */
+#define NAN_CFG_PRIORITY_SERVICE_DISCOVERY 0
+#define NAN_CFG_PRIORITY_DATA_CONNECTION 1
+
+/* NAN Configuration 5G Channel Usage */
+#define NAN_5G_CHANNEL_USAGE_SYNC_AND_DISCOVERY 0
+#define NAN_5G_CHANNEL_USAGE_DISCOVERY_ONLY 1
+
+/* NAN Configuration TX_Beacon Content */
+#define NAN_TX_BEACON_CONTENT_OLD_AM_INFO 0
+#define NAN_TX_BEACON_CONTENT_UPDATED_AM_INFO 1
+
+/* NAN Configuration Miscellaneous Constants */
+#define NAN_MAC_INTERFACE_PERIODICITY_MIN 30
+#define NAN_MAC_INTERFACE_PERIODICITY_MAX 255
+
+#define NAN_DW_RANDOM_TIME_MIN 120
+#define NAN_DW_RANDOM_TIME_MAX 240
+
+#define NAN_INITIAL_SCAN_MIN_IDEAL_PERIOD 200
+#define NAN_INITIAL_SCAN_MAX_IDEAL_PERIOD 300
+
+#define NAN_ONGOING_SCAN_MIN_PERIOD 10
+#define NAN_ONGOING_SCAN_MAX_PERIOD 30
+
+#define NAN_HOP_COUNT_LIMIT 5
+
+#define NAN_WINDOW_DW 0
+#define NAN_WINDOW_FAW 1
+
+#define NAN_TLV_HEADER_SIZE 4
+
+/* NAN Error Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ u16 status;
+ u16 value;
+} NanErrorRspMsg, *pNanErrorRspMsg;
+
+//* NAN Publish Service Req */
+typedef struct PACKED
+{
+ u16 ttl;
+ u16 period;
+ u32 replyIndFlag:1;
+ u32 publishType:2;
+ u32 txType:1;
+ u32 rssiThresholdFlag:1;
+ u32 ota_flag:1;
+ u32 matchAlg:2;
+ u32 count:8;
+ u32 connmap:8;
+ u32 pubTerminatedIndDisableFlag:1;
+ u32 pubMatchExpiredIndDisableFlag:1;
+ u32 followupRxIndDisableFlag:1;
+ u32 reserved2:5;
+ /*
+ * Excludes TLVs
+ *
+ * Required: Service Name,
+ * Optional: Tx Match Filter, Rx Match Filter, Service Specific Info,
+ */
+} NanPublishServiceReqParams, *pNanPublishServiceReqParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanPublishServiceReqParams publishServiceReqParams;
+ u8 ptlv[];
+} NanPublishServiceReqMsg, *pNanPublishServiceReqMsg;
+
+/* NAN Publish Service Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanPublishServiceRspMsg, *pNanPublishServiceRspMsg;
+
+/* NAN Publish Service Cancel Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+} NanPublishServiceCancelReqMsg, *pNanPublishServiceCancelReqMsg;
+
+/* NAN Publish Service Cancel Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanPublishServiceCancelRspMsg, *pNanPublishServiceCancelRspMsg;
+
+/* NAN Publish Terminated Ind */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* reason for the termination */
+ u16 reason;
+ u16 reserved;
+} NanPublishTerminatedIndMsg, *pNanPublishTerminatedIndMsg;
+
+/* Params for NAN Publish Replied Ind */
+typedef struct PACKED
+{
+ u32 matchHandle;
+} NanPublishRepliedIndParams;
+
+/* NAN Publish Replied Ind */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanPublishRepliedIndParams publishRepliedIndParams;
+ /*
+ * Excludes TLVs
+ *
+ * Required: MAC Address
+ * Optional: Received RSSI Value
+ *
+ */
+ u8 ptlv[];
+} NanPublishRepliedIndMsg, *pNanPublishRepliedIndMsg;
+
+/* NAN Device Capability Attribute */
+typedef struct PACKED
+{
+ u32 dfs_master:1;
+ u32 ext_key_id:1;
+ u32 simu_ndp_data_recept:1;
+ u32 ndpe_attr_supp:1;
+ u32 reserved:28;
+} NanDevCapAttrCap, *pNanDevCapAttrCap;
+
+/* NAN Subscribe Service Req */
+typedef struct PACKED
+{
+ u16 ttl;
+ u16 period;
+ u32 subscribeType:1;
+ u32 srfAttr:1;
+ u32 srfInclude:1;
+ u32 srfSend:1;
+ u32 ssiRequired:1;
+ u32 matchAlg:2;
+ u32 xbit:1;
+ u32 count:8;
+ u32 rssiThresholdFlag:1;
+ u32 ota_flag:1;
+ u32 subTerminatedIndDisableFlag:1;
+ u32 subMatchExpiredIndDisableFlag:1;
+ u32 followupRxIndDisableFlag:1;
+ u32 reserved:3;
+ u32 connmap:8;
+ /*
+ * Excludes TLVs
+ *
+ * Required: Service Name
+ * Optional: Rx Match Filter, Tx Match Filter, Service Specific Info,
+ */
+} NanSubscribeServiceReqParams, *pNanSubscribeServiceReqParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanSubscribeServiceReqParams subscribeServiceReqParams;
+ u8 ptlv[];
+} NanSubscribeServiceReqMsg, *pNanSubscribeServiceReqMsg;
+
+/* NAN Subscribe Service Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanSubscribeServiceRspMsg, *pNanSubscribeServiceRspMsg;
+
+/* NAN Subscribe Service Cancel Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+} NanSubscribeServiceCancelReqMsg, *pNanSubscribeServiceCancelReqMsg;
+
+/* NAN Subscribe Service Cancel Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanSubscribeServiceCancelRspMsg, *pNanSubscribeServiceCancelRspMsg;
+
+/* NAN Subscribe Match Ind */
+typedef struct PACKED
+{
+ u32 matchHandle;
+ u32 matchOccuredFlag:1;
+ u32 outOfResourceFlag:1;
+ u32 reserved:30;
+} NanMatchIndParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanMatchIndParams matchIndParams;
+ u8 ptlv[];
+} NanMatchIndMsg, *pNanMatchIndMsg;
+
+/* NAN Subscribe Unmatch Ind */
+typedef struct PACKED
+{
+ u32 matchHandle;
+} NanmatchExpiredIndParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanmatchExpiredIndParams matchExpiredIndParams;
+} NanMatchExpiredIndMsg, *pNanMatchExpiredIndMsg;
+
+/* NAN Subscribe Terminated Ind */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* reason for the termination */
+ u16 reason;
+ u16 reserved;
+} NanSubscribeTerminatedIndMsg, *pNanSubscribeTerminatedIndMsg;
+
+/* Event Ind */
+typedef struct PACKED
+{
+ u32 eventId:8;
+ u32 reserved:24;
+} NanEventIndParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ u8 ptlv[];
+} NanEventIndMsg, *pNanEventIndMsg;
+
+/* NAN Transmit Followup Req */
+typedef struct PACKED
+{
+ u32 matchHandle;
+ u32 priority:4;
+ u32 window:1;
+ u32 followupTxRspDisableFlag:1;
+ u32 reserved:26;
+ /*
+ * Excludes TLVs
+ *
+ * Required: Service Specific Info or Extended Service Specific Info
+ */
+} NanTransmitFollowupReqParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanTransmitFollowupReqParams transmitFollowupReqParams;
+ u8 ptlv[];
+} NanTransmitFollowupReqMsg, *pNanTransmitFollowupReqMsg;
+
+/* NAN Transmit Followup Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanTransmitFollowupRspMsg, *pNanTransmitFollowupRspMsg;
+
+/* NAN Publish Followup Ind */
+typedef struct PACKED
+{
+ u32 matchHandle;
+ u32 window:1;
+ u32 reserved:31;
+ /*
+ * Excludes TLVs
+ *
+ * Required: Service Specific Info or Extended Service Specific Info
+ */
+} NanFollowupIndParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanFollowupIndParams followupIndParams;
+ u8 ptlv[];
+} NanFollowupIndMsg, *pNanFollowupIndMsg;
+
+/* NAN Statistics Req */
+typedef struct PACKED
+{
+ u32 statsType:8;
+ u32 clear:1;
+ u32 reserved:23;
+} NanStatsReqParams, *pNanStatsReqParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanStatsReqParams statsReqParams;
+} NanStatsReqMsg, *pNanStatsReqMsg;
+
+/* NAN Statistics Rsp */
+typedef struct PACKED
+{
+ /* status of the request */
+ u16 status;
+ u16 value;
+ u8 statsType;
+ u8 reserved;
+} NanStatsRspParams, *pNanStatsRspParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ NanStatsRspParams statsRspParams;
+ u8 ptlv[];
+} NanStatsRspMsg, *pNanStatsRspMsg;
+
+typedef struct PACKED
+{
+ u8 count:7;
+ u8 s:1;
+} NanSidAttr, *pSidAttr;
+
+
+/* NAN Configuration Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ * TLVs:
+ *
+ * Required: None.
+ * Optional: SID, Random Time, Master Preference, WLAN Intra Attr,
+ * P2P Operation Attr, WLAN IBSS Attr, WLAN Mesh Attr
+ */
+ u8 ptlv[];
+} NanConfigurationReqMsg, *pNanConfigurationReqMsg;
+
+/*
+ * Because the Configuration Req message has TLVs in it use the macro below
+ * for the size argument to buffer allocation functions (vs. sizeof(msg)).
+ */
+#define NAN_MAX_CONFIGURATION_REQ_SIZE \
+ ( \
+ sizeof(NanMsgHeader) + \
+ SIZEOF_TLV_HDR + sizeof(u8) /* SID Beacon */ + \
+ SIZEOF_TLV_HDR + sizeof(u8) /* Random Time */ + \
+ SIZEOF_TLV_HDR + sizeof(u8) /* Master Pref */ \
+ )
+
+/* NAN Configuration Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanConfigurationRspMsg, *pNanConfigurationRspMsg;
+
+/*
+ * Because the Enable Req message has TLVs in it use the macro below for
+ * the size argument to buffer allocation functions (vs. sizeof(msg)).
+ */
+#define NAN_MAX_ENABLE_REQ_SIZE \
+ ( \
+ sizeof(NanMsgHeader) + \
+ SIZEOF_TLV_HDR + sizeof(u16) /* Cluster Low */ + \
+ SIZEOF_TLV_HDR + sizeof(u16) /* Cluster High */ + \
+ SIZEOF_TLV_HDR + sizeof(u8) /* Master Pref */ \
+ )
+
+/* Config Discovery Indication */
+ typedef struct PACKED
+ {
+ u32 disableDiscoveryMacAddressEvent:1;
+ u32 disableDiscoveryStartedClusterEvent:1;
+ u32 disableDiscoveryJoinedClusterEvent:1;
+ u32 reserved:29;
+ } NanConfigDiscoveryIndications;
+
+/* NAN Enable Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ * TLVs:
+ *
+ * Required: Cluster Low, Cluster High, Master Preference,
+ * Optional: 5G Support, SID, 5G Sync Disc, RSSI Close, RSSI Medium,
+ * Hop Count Limit, Random Time, Master Preference,
+ * WLAN Intra Attr, P2P Operation Attr, WLAN IBSS Attr,
+ * WLAN Mesh Attr
+ */
+ u8 ptlv[];
+} NanEnableReqMsg, *pNanEnableReqMsg;
+
+/* NAN Enable Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanEnableRspMsg, *pNanEnableRspMsg;
+
+/* NAN Disable Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+} NanDisableReqMsg, *pNanDisableReqMsg;
+
+/* NAN Disable Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 reserved;
+} NanDisableRspMsg, *pNanDisableRspMsg;
+
+/* NAN Disable Ind */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* reason for the termination */
+ u16 reason;
+ u16 reserved;
+} NanDisableIndMsg, *pNanDisableIndMsg;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ u8 ptlv[];
+} NanTcaReqMsg, *pNanTcaReqMsg;
+
+/* NAN TCA Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 value;
+} NanTcaRspMsg, *pNanTcaRspMsg;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ * TLVs:
+ *
+ * Optional: Cluster size.
+ */
+ u8 ptlv[];
+} NanTcaIndMsg, *pNanTcaIndMsg;
+
+/*
+ * Because the TCA Ind message has TLVs in it use the macro below for the
+ * size argument to buffer allocation functions (vs. sizeof(msg)).
+ */
+#define NAN_MAX_TCA_IND_SIZE \
+ ( \
+ sizeof(NanMsgHeader) + \
+ sizeof(NanTcaIndParams) + \
+ SIZEOF_TLV_HDR + sizeof(u16) /* Cluster Size */ \
+ )
+
+/* Function Declarations */
+u8* addTlv(u16 type, u16 length, const u8* value, u8* pOutTlv);
+u16 NANTLV_ReadTlv(u8 *pInTlv, pNanTlv pOutTlv, int inBufferSize);
+u16 NANTLV_WriteTlv(pNanTlv pInTlv, u8 *pOutTlv);
+
+/* NAN Beacon Sdf Payload Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ * TLVs:
+ *
+ * Optional: Vendor specific attribute
+ */
+ u8 ptlv[];
+} NanBeaconSdfPayloadReqMsg, *pNanBeaconSdfPayloadReqMsg;
+
+/* NAN Beacon Sdf Payload Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u16 status;
+ u16 reserved;
+} NanBeaconSdfPayloadRspMsg, *pNanBeaconSdfPayloadRspMsg;
+
+/* NAN Beacon Sdf Payload Ind */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ * TLVs:
+ *
+ * Required: Mac address
+ * Optional: Vendor specific attribute, sdf payload
+ * receive
+ */
+ u8 ptlv[];
+} NanBeaconSdfPayloadIndMsg, *pNanBeaconSdfPayloadIndMsg;
+
+typedef struct PACKED
+{
+ u8 availIntDuration:2;
+ u8 mapId:4;
+ u8 reserved:2;
+} NanApiEntryCtrl;
+
+/*
+ * Valid Operating Classes were derived from IEEE Std. 802.11-2012 Annex E
+ * Table E-4 Global Operating Classe and, filtered by channel, are: 81, 83,
+ * 84, 103, 114, 115, 116, 124, 125.
+ */
+typedef struct PACKED
+{
+ NanApiEntryCtrl entryCtrl;
+ u8 opClass;
+ u8 channel;
+ u8 availIntBitmap[4];
+} NanFurtherAvailabilityChan, *pNanFurtherAvailabilityChan;
+
+typedef struct PACKED
+{
+ u8 numChan;
+ u8 pFaChan[];
+} NanFurtherAvailabilityMapAttrTlv, *pNanFurtherAvailabilityMapAttrTlv;
+
+/* Publish statistics. */
+typedef struct PACKED
+{
+ u32 validPublishServiceReqMsgs;
+ u32 validPublishServiceRspMsgs;
+ u32 validPublishServiceCancelReqMsgs;
+ u32 validPublishServiceCancelRspMsgs;
+ u32 validPublishRepliedIndMsgs;
+ u32 validPublishTerminatedIndMsgs;
+ u32 validActiveSubscribes;
+ u32 validMatches;
+ u32 validFollowups;
+ u32 invalidPublishServiceReqMsgs;
+ u32 invalidPublishServiceCancelReqMsgs;
+ u32 invalidActiveSubscribes;
+ u32 invalidMatches;
+ u32 invalidFollowups;
+ u32 publishCount;
+ u32 publishNewMatchCount;
+ u32 pubsubGlobalNewMatchCount;
+} FwNanPublishStats, *pFwNanPublishStats;
+
+/* Subscribe statistics. */
+typedef struct PACKED
+{
+ u32 validSubscribeServiceReqMsgs;
+ u32 validSubscribeServiceRspMsgs;
+ u32 validSubscribeServiceCancelReqMsgs;
+ u32 validSubscribeServiceCancelRspMsgs;
+ u32 validSubscribeTerminatedIndMsgs;
+ u32 validSubscribeMatchIndMsgs;
+ u32 validSubscribeUnmatchIndMsgs;
+ u32 validSolicitedPublishes;
+ u32 validMatches;
+ u32 validFollowups;
+ u32 invalidSubscribeServiceReqMsgs;
+ u32 invalidSubscribeServiceCancelReqMsgs;
+ u32 invalidSubscribeFollowupReqMsgs;
+ u32 invalidSolicitedPublishes;
+ u32 invalidMatches;
+ u32 invalidFollowups;
+ u32 subscribeCount;
+ u32 bloomFilterIndex;
+ u32 subscribeNewMatchCount;
+ u32 pubsubGlobalNewMatchCount;
+} FwNanSubscribeStats, *pFwNanSubscribeStats;
+
+/* NAN MAC Statistics. Used for MAC and DW statistics. */
+typedef struct PACKED
+{
+ /* RX stats */
+ u32 validFrames;
+ u32 validActionFrames;
+ u32 validBeaconFrames;
+ u32 ignoredActionFrames;
+ u32 ignoredBeaconFrames;
+ u32 invalidFrames;
+ u32 invalidActionFrames;
+ u32 invalidBeaconFrames;
+ u32 invalidMacHeaders;
+ u32 invalidPafHeaders;
+ u32 nonNanBeaconFrames;
+
+ u32 earlyActionFrames;
+ u32 inDwActionFrames;
+ u32 lateActionFrames;
+
+ /* TX stats */
+ u32 framesQueued;
+ u32 totalTRSpUpdates;
+ u32 completeByTRSp;
+ u32 completeByTp75DW;
+ u32 completeByTendDW;
+ u32 lateActionFramesTx;
+
+ /* Misc stats - ignored for DW. */
+ u32 twIncreases;
+ u32 twDecreases;
+ u32 twChanges;
+ u32 twHighwater;
+ u32 bloomFilterIndex;
+} FwNanMacStats, *pFwNanMacStats;
+
+/* NAN Sync and DW Statistics*/
+typedef struct PACKED
+{
+ u64 currTsf;
+ u64 myRank;
+ u64 currAmRank;
+ u64 lastAmRank;
+ u32 currAmBTT;
+ u32 lastAmBTT;
+ u8 currAmHopCount;
+ u8 currRole;
+ u16 currClusterId;
+ u32 reserved1;
+
+ u64 timeSpentInCurrRole;
+ u64 totalTimeSpentAsMaster;
+ u64 totalTimeSpentAsNonMasterSync;
+ u64 totalTimeSpentAsNonMasterNonSync;
+ u32 transitionsToAnchorMaster;
+ u32 transitionsToMaster;
+ u32 transitionsToNonMasterSync;
+ u32 transitionsToNonMasterNonSync;
+ u32 amrUpdateCount;
+ u32 amrUpdateRankChangedCount;
+ u32 amrUpdateBTTChangedCount;
+ u32 amrUpdateHcChangedCount;
+ u32 amrUpdateNewDeviceCount;
+ u32 amrExpireCount;
+ u32 mergeCount;
+ u32 beaconsAboveHcLimit;
+ u32 beaconsBelowRssiThresh;
+ u32 beaconsIgnoredNoSpace;
+ u32 beaconsForOurCluster;
+ u32 beaconsForOtherCluster;
+ u32 beaconCancelRequests;
+ u32 beaconCancelFailures;
+ u32 beaconUpdateRequests;
+ u32 beaconUpdateFailures;
+ u32 syncBeaconTxAttempts;
+ u32 syncBeaconTxFailures;
+ u32 discBeaconTxAttempts;
+ u32 discBeaconTxFailures;
+ u32 amHopCountExpireCount;
+ u32 ndpChannelFreq;
+ u32 ndpChannelFreq2;
+ u32 schedUpdateChannelFreq;
+} FwNanSyncStats, *pFwNanSyncStats;
+
+/* NAN Misc DE Statistics */
+typedef struct PACKED
+{
+ u32 validErrorRspMsgs;
+ u32 validTransmitFollowupReqMsgs;
+ u32 validTransmitFollowupRspMsgs;
+ u32 validFollowupIndMsgs;
+ u32 validConfigurationReqMsgs;
+ u32 validConfigurationRspMsgs;
+ u32 validStatsReqMsgs;
+ u32 validStatsRspMsgs;
+ u32 validEnableReqMsgs;
+ u32 validEnableRspMsgs;
+ u32 validDisableReqMsgs;
+ u32 validDisableRspMsgs;
+ u32 validDisableIndMsgs;
+ u32 validEventIndMsgs;
+ u32 validTcaReqMsgs;
+ u32 validTcaRspMsgs;
+ u32 validTcaIndMsgs;
+ u32 invalidTransmitFollowupReqMsgs;
+ u32 invalidConfigurationReqMsgs;
+ u32 invalidStatsReqMsgs;
+ u32 invalidEnableReqMsgs;
+ u32 invalidDisableReqMsgs;
+ u32 invalidTcaReqMsgs;
+} FwNanDeStats, *pFwNanDeStats;
+
+/*
+ Definition of various NanIndication(events)
+*/
+typedef enum {
+ NAN_INDICATION_PUBLISH_REPLIED =0,
+ NAN_INDICATION_PUBLISH_TERMINATED =1,
+ NAN_INDICATION_MATCH =2,
+ NAN_INDICATION_MATCH_EXPIRED =3,
+ NAN_INDICATION_SUBSCRIBE_TERMINATED =4,
+ NAN_INDICATION_DE_EVENT =5,
+ NAN_INDICATION_FOLLOWUP =6,
+ NAN_INDICATION_DISABLED =7,
+ NAN_INDICATION_TCA =8,
+ NAN_INDICATION_BEACON_SDF_PAYLOAD =9,
+ NAN_INDICATION_SELF_TRANSMIT_FOLLOWUP =10,
+ NAN_INDICATION_RANGING_REQUEST_RECEIVED =11,
+ NAN_INDICATION_RANGING_RESULT =12,
+ NAN_INDICATION_UNKNOWN =0xFFFF
+} NanIndicationType;
+
+/* NAN Capabilities Req */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+} NanCapabilitiesReqMsg, *pNanCapabilitiesReqMsg;
+
+/* NAN Capabilities Rsp */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /* status of the request */
+ u32 status;
+ u32 value;
+ u32 max_concurrent_nan_clusters;
+ u32 max_publishes;
+ u32 max_subscribes;
+ u32 max_service_name_len;
+ u32 max_match_filter_len;
+ u32 max_total_match_filter_len;
+ u32 max_service_specific_info_len;
+ u32 max_vsa_data_len;
+ u32 max_mesh_data_len;
+ u32 max_ndi_interfaces;
+ u32 max_ndp_sessions;
+ u32 max_app_info_len;
+ u32 max_queued_transmit_followup_msgs;
+ u32 ndp_supported_bands;
+ u32 cipher_suites_supported;
+ u32 max_scid_len;
+ u32 is_ndp_security_supported:1;
+ u32 max_sdea_service_specific_info_len:16;
+ u32 reserved1:5;
+ u32 reserved2:5;
+ u32 ndpe_attr_supported:1;
+ u32 reserved:4;
+ u32 max_subscribe_address;
+} NanCapabilitiesRspMsg, *pNanCapabilitiesRspMsg;
+
+/* NAN Self Transmit Followup */
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ u32 reason;
+} NanSelfTransmitFollowupIndMsg, *pNanSelfTransmitFollowupIndMsg;
+
+/* NAN Cipher Suite Shared Key */
+typedef struct PACKED
+{
+ u32 csid_type;
+} NanCsidType;
+
+/* Service Discovery Extended Attribute params */
+typedef struct PACKED
+{
+ u32 fsd_required:1;
+ u32 fsd_with_gas:1;
+ u32 data_path_required:1;
+ u32 data_path_type:1;
+ u32 multicast_type:1;
+ u32 qos_required:1;
+ u32 security_required:1;
+ u32 ranging_required:1;
+ u32 range_limit_present:1;
+ u32 service_update_ind_present:1;
+ u32 reserved1:6;
+ u32 range_report:1;
+ u32 reserved2:15;
+} NanFWSdeaCtrlParams;
+
+/* NAN Ranging Configuration params */
+typedef struct PACKED
+{
+ u32 inner_threshold;
+ u32 outer_threshold;
+} NanFWGeoFenceDescriptor;
+
+typedef struct PACKED
+{
+ u32 range_resolution;
+ u32 range_interval;
+ u32 ranging_indication_event;
+ NanFWGeoFenceDescriptor geo_fence_threshold;
+} NanFWRangeConfigParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*
+ Excludes TLVs
+ Optional: Nan Availability
+ */
+ u8 ptlv[];
+} NanTestModeReqMsg, *pNanTestModeReqMsg;
+
+/*
+ NAN Status codes exchanged between firmware
+ and WifiHal.
+*/
+typedef enum {
+ /* NAN Protocol Response Codes */
+ NAN_I_STATUS_SUCCESS = 0,
+ NAN_I_STATUS_TIMEOUT = 1,
+ NAN_I_STATUS_DE_FAILURE = 2,
+ NAN_I_STATUS_INVALID_MSG_VERSION = 3,
+ NAN_I_STATUS_INVALID_MSG_LEN = 4,
+ NAN_I_STATUS_INVALID_MSG_ID = 5,
+ NAN_I_STATUS_INVALID_HANDLE = 6,
+ NAN_I_STATUS_NO_SPACE_AVAILABLE = 7,
+ NAN_I_STATUS_INVALID_PUBLISH_TYPE = 8,
+ NAN_I_STATUS_INVALID_TX_TYPE = 9,
+ NAN_I_STATUS_INVALID_MATCH_ALGORITHM = 10,
+ NAN_I_STATUS_DISABLE_IN_PROGRESS = 11,
+ NAN_I_STATUS_INVALID_TLV_LEN = 12,
+ NAN_I_STATUS_INVALID_TLV_TYPE = 13,
+ NAN_I_STATUS_MISSING_TLV_TYPE = 14,
+ NAN_I_STATUS_INVALID_TOTAL_TLVS_LEN = 15,
+ NAN_I_STATUS_INVALID_REQUESTER_INSTANCE_ID= 16,
+ NAN_I_STATUS_INVALID_TLV_VALUE = 17,
+ NAN_I_STATUS_INVALID_TX_PRIORITY = 18,
+ NAN_I_STATUS_INVALID_CONNECTION_MAP = 19,
+ NAN_I_STATUS_INVALID_THRESHOLD_CROSSING_ALERT_ID = 20,
+ NAN_I_STATUS_INVALID_STATS_ID = 21,
+ NAN_I_STATUS_NAN_NOT_ALLOWED = 22,
+ NAN_I_STATUS_NO_OTA_ACK = 23,
+ NAN_I_STATUS_TX_FAIL = 24,
+ NAN_I_STATUS_NAN_ALREADY_ENABLED = 25,
+ NAN_I_STATUS_FOLLOWUP_QUEUE_FULL = 26,
+ /* 27-4095 Reserved */
+ /* NAN Configuration Response codes */
+ NAN_I_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096,
+ NAN_I_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097,
+ NAN_I_STATUS_INVALID_HOP_COUNT_LIMIT = 4098,
+ NAN_I_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099,
+ NAN_I_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100,
+ NAN_I_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101,
+ NAN_I_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102,
+ NAN_I_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103,
+ NAN_I_STATUS_INVALID_SCAN_CHANNEL = 4104,
+ NAN_I_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110,
+ NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111,
+ NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112,
+ NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113,
+ NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114,
+ NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115,
+ NAN_I_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116,
+ NAN_I_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117,
+ NAN_I_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118,
+ NAN_I_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119,
+ NAN_I_STATUS_INVALID_DW_INTERVAL_VALUE = 4120,
+ NAN_I_STATUS_INVALID_DB_INTERVAL_VALUE = 4121,
+ /* 4122-8191 RESERVED */
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_INVALID = 8192,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_TIMEOUT = 8193,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_USER_REQUEST = 8194,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_FAILURE = 8195,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_COUNT_REACHED = 8196,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_DE_SHUTDOWN = 8197,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200,
+ NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201,
+ /* 9000-9500 NDP Status type */
+ NDP_I_UNSUPPORTED_CONCURRENCY = 9000,
+ NDP_I_NAN_DATA_IFACE_CREATE_FAILED = 9001,
+ NDP_I_NAN_DATA_IFACE_DELETE_FAILED = 9002,
+ NDP_I_DATA_INITIATOR_REQUEST_FAILED = 9003,
+ NDP_I_DATA_RESPONDER_REQUEST_FAILED = 9004,
+ NDP_I_INVALID_SERVICE_INSTANCE_ID = 9005,
+ NDP_I_INVALID_NDP_INSTANCE_ID = 9006,
+ NDP_I_INVALID_RESPONSE_CODE = 9007,
+ NDP_I_INVALID_APP_INFO_LEN = 9008,
+ /* OTA failures and timeouts during negotiation */
+ NDP_I_MGMT_FRAME_REQUEST_FAILED = 9009,
+ NDP_I_MGMT_FRAME_RESPONSE_FAILED = 9010,
+ NDP_I_MGMT_FRAME_CONFIRM_FAILED = 9011,
+ NDP_I_END_FAILED = 9012,
+ NDP_I_MGMT_FRAME_END_REQUEST_FAILED = 9013,
+ NDP_I_MGMT_FRAME_SECURITY_INSTALL_FAILED = 9014,
+
+ /* 9500 onwards vendor specific error codes */
+ NDP_I_VENDOR_SPECIFIC_ERROR = 9500
+} NanInternalStatusType;
+
+/* This is the TLV used for range report */
+typedef struct PACKED
+{
+ u32 publish_id;
+ u32 event_type;
+ u32 range_measurement;
+} NanFWRangeReportParams;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*TLV Required:
+ MANDATORY
+ 1. MAC_ADDRESS
+ 2. NanFWRangeReportParams
+ OPTIONAL:
+ 1. A_UINT32 event type
+ */
+ u8 ptlv[1];
+} NanFWRangeReportInd, *pNanFWRangeReportInd;
+
+/** 2 word representation of MAC addr */
+typedef struct {
+ /** upper 4 bytes of MAC address */
+ u32 mac_addr31to0;
+ /** lower 2 bytes of MAC address */
+ u32 mac_addr47to32;
+} fw_mac_addr;
+
+/* This is the TLV used to trigger ranging requests*/
+typedef struct PACKED
+{
+ fw_mac_addr range_mac_addr;
+ u32 range_id; //Match handle in match_ind, publish_id in result ind
+ u32 ranging_accept:1;
+ u32 ranging_reject:1;
+ u32 ranging_cancel:1;
+ u32 reserved:29;
+} NanFWRangeReqMsg, *pNanFWRangeReqMsg;
+
+typedef struct PACKED
+{
+ fw_mac_addr range_mac_addr;
+ u32 range_id;//This will publish_id in case of receiving publish.
+} NanFWRangeReqRecvdMsg, *pNanFWRangeReqRecvdMsg;
+
+typedef struct PACKED
+{
+ NanMsgHeader fwHeader;
+ /*TLV Required
+ 1. t_nan_range_req_recvd_msg
+ */
+ u8 ptlv[1];
+} NanFWRangeReqRecvdInd, *pNanFWRangeReqRecvdInd;
+
+/* Function for NAN error translation
+ For NanResponse, NanPublishTerminatedInd, NanSubscribeTerminatedInd,
+ NanDisabledInd, NanTransmitFollowupInd:
+ function to translate firmware specific errors
+ to generic freamework error along with the error string
+*/
+void NanErrorTranslation(NanInternalStatusType firmwareErrorRecvd,
+ u32 valueRcvd,
+ void *pRsp,
+ bool is_ndp_rsp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __NAN_I_H__ */
+
diff --git a/wcn6740/qcwcn/wifi_hal/nan_ind.cpp b/wcn6740/qcwcn/wifi_hal/nan_ind.cpp
new file mode 100644
index 0000000..47ad8f8
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nan_ind.cpp
@@ -0,0 +1,1452 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include "sync.h"
+#include <utils/Log.h>
+#include <errno.h>
+#include "wifi_hal.h"
+#include "nan_i.h"
+#include "nancommand.h"
+#include <errno.h>
+
+//Function which calls the necessaryIndication callback
+//based on the indication type
+int NanCommand::handleNanIndication()
+{
+ //Based on the message_id in the header determine the Indication type
+ //and call the necessary callback handler
+ u16 msg_id;
+ int res = 0;
+
+ msg_id = getIndicationType();
+
+ ALOGV("handleNanIndication msg_id:%u", msg_id);
+ switch (msg_id) {
+ case NAN_INDICATION_PUBLISH_REPLIED:
+ NanPublishRepliedInd publishRepliedInd;
+ memset(&publishRepliedInd, 0, sizeof(publishRepliedInd));
+ res = getNanPublishReplied(&publishRepliedInd);
+ if (!res && mHandler.EventPublishReplied) {
+ (*mHandler.EventPublishReplied)(&publishRepliedInd);
+ }
+ break;
+
+ case NAN_INDICATION_PUBLISH_TERMINATED:
+ NanPublishTerminatedInd publishTerminatedInd;
+ memset(&publishTerminatedInd, 0, sizeof(publishTerminatedInd));
+ res = getNanPublishTerminated(&publishTerminatedInd);
+ if (!res && mHandler.EventPublishTerminated) {
+ (*mHandler.EventPublishTerminated)(&publishTerminatedInd);
+ }
+ break;
+
+ case NAN_INDICATION_MATCH:
+ NanMatchInd matchInd;
+ memset(&matchInd, 0, sizeof(matchInd));
+ res = getNanMatch(&matchInd);
+ if (!res && mHandler.EventMatch) {
+ (*mHandler.EventMatch)(&matchInd);
+ }
+ break;
+
+ case NAN_INDICATION_MATCH_EXPIRED:
+ NanMatchExpiredInd matchExpiredInd;
+ memset(&matchExpiredInd, 0, sizeof(matchExpiredInd));
+ res = getNanMatchExpired(&matchExpiredInd);
+ if (!res && mHandler.EventMatchExpired) {
+ (*mHandler.EventMatchExpired)(&matchExpiredInd);
+ }
+ break;
+
+ case NAN_INDICATION_SUBSCRIBE_TERMINATED:
+ NanSubscribeTerminatedInd subscribeTerminatedInd;
+ memset(&subscribeTerminatedInd, 0, sizeof(subscribeTerminatedInd));
+ res = getNanSubscribeTerminated(&subscribeTerminatedInd);
+ if (!res && mHandler.EventSubscribeTerminated) {
+ (*mHandler.EventSubscribeTerminated)(&subscribeTerminatedInd);
+ }
+ break;
+
+ case NAN_INDICATION_DE_EVENT:
+ NanDiscEngEventInd discEngEventInd;
+ memset(&discEngEventInd, 0, sizeof(discEngEventInd));
+ res = getNanDiscEngEvent(&discEngEventInd);
+ /* Save the self MAC address received in DE indication event to use it
+ * in Passphrase to PMK calculation. And do not call the handler if the
+ * framework has disabled the self MAC address indication.
+ */
+ if (!res &&
+ (discEngEventInd.event_type == NAN_EVENT_ID_DISC_MAC_ADDR)) {
+ mNanCommandInstance->saveNmi(discEngEventInd.data.mac_addr.addr);
+ if (mNanCommandInstance->mNanDiscAddrIndDisabled)
+ break;
+ }
+ if (!res && mHandler.EventDiscEngEvent) {
+ (*mHandler.EventDiscEngEvent)(&discEngEventInd);
+ }
+ break;
+
+ case NAN_INDICATION_FOLLOWUP:
+ NanFollowupInd followupInd;
+ memset(&followupInd, 0, sizeof(followupInd));
+ res = getNanFollowup(&followupInd);
+ if (!res && mHandler.EventFollowup) {
+ (*mHandler.EventFollowup)(&followupInd);
+ }
+ break;
+
+ case NAN_INDICATION_DISABLED:
+ NanDisabledInd disabledInd;
+ memset(&disabledInd, 0, sizeof(disabledInd));
+ res = getNanDisabled(&disabledInd);
+ if (!res && mHandler.EventDisabled) {
+ (*mHandler.EventDisabled)(&disabledInd);
+ }
+ break;
+
+ case NAN_INDICATION_TCA:
+ NanTCAInd tcaInd;
+ memset(&tcaInd, 0, sizeof(tcaInd));
+ res = getNanTca(&tcaInd);
+ if (!res && mHandler.EventTca) {
+ (*mHandler.EventTca)(&tcaInd);
+ }
+ break;
+
+ case NAN_INDICATION_BEACON_SDF_PAYLOAD:
+ NanBeaconSdfPayloadInd beaconSdfPayloadInd;
+ memset(&beaconSdfPayloadInd, 0, sizeof(beaconSdfPayloadInd));
+ res = getNanBeaconSdfPayload(&beaconSdfPayloadInd);
+ if (!res && mHandler.EventBeaconSdfPayload) {
+ (*mHandler.EventBeaconSdfPayload)(&beaconSdfPayloadInd);
+ }
+ break;
+
+ case NAN_INDICATION_SELF_TRANSMIT_FOLLOWUP:
+ NanTransmitFollowupInd transmitFollowupInd;
+ memset(&transmitFollowupInd, 0, sizeof(NanTransmitFollowupInd));
+ res = getNanTransmitFollowupInd(&transmitFollowupInd);
+ if (!res && mHandler.EventTransmitFollowup) {
+ (*mHandler.EventTransmitFollowup)(&transmitFollowupInd);
+ }
+ break;
+
+ case NAN_INDICATION_RANGING_REQUEST_RECEIVED:
+ NanRangeRequestInd rangeRequestInd;
+ memset(&rangeRequestInd, 0, sizeof(NanRangeRequestInd));
+ res = getNanRangeRequestReceivedInd(&rangeRequestInd);
+ if (!res && mHandler.EventRangeRequest) {
+ (*mHandler.EventRangeRequest)(&rangeRequestInd);
+ }
+ break;
+
+ case NAN_INDICATION_RANGING_RESULT:
+ NanRangeReportInd rangeReportInd;
+ memset(&rangeReportInd, 0, sizeof(NanRangeReportInd));
+ res = getNanRangeReportInd(&rangeReportInd);
+ if (!res && mHandler.EventRangeReport) {
+ (*mHandler.EventRangeReport)(&rangeReportInd);
+ }
+ break;
+
+ default:
+ ALOGE("handleNanIndication error invalid msg_id:%u", msg_id);
+ res = (int)WIFI_ERROR_INVALID_REQUEST_ID;
+ break;
+ }
+ return res;
+}
+
+//Function which will return the Nan Indication type based on
+//the initial few bytes of mNanVendorEvent
+NanIndicationType NanCommand::getIndicationType()
+{
+ if (mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid argument mNanVendorEvent:%p",
+ __func__, mNanVendorEvent);
+ return NAN_INDICATION_UNKNOWN;
+ }
+
+ NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
+
+ switch (pHeader->msgId) {
+ case NAN_MSG_ID_PUBLISH_REPLIED_IND:
+ return NAN_INDICATION_PUBLISH_REPLIED;
+ case NAN_MSG_ID_PUBLISH_TERMINATED_IND:
+ return NAN_INDICATION_PUBLISH_TERMINATED;
+ case NAN_MSG_ID_MATCH_IND:
+ return NAN_INDICATION_MATCH;
+ case NAN_MSG_ID_MATCH_EXPIRED_IND:
+ return NAN_INDICATION_MATCH_EXPIRED;
+ case NAN_MSG_ID_FOLLOWUP_IND:
+ return NAN_INDICATION_FOLLOWUP;
+ case NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND:
+ return NAN_INDICATION_SUBSCRIBE_TERMINATED;
+ case NAN_MSG_ID_DE_EVENT_IND:
+ return NAN_INDICATION_DE_EVENT;
+ case NAN_MSG_ID_DISABLE_IND:
+ return NAN_INDICATION_DISABLED;
+ case NAN_MSG_ID_TCA_IND:
+ return NAN_INDICATION_TCA;
+ case NAN_MSG_ID_BEACON_SDF_IND:
+ return NAN_INDICATION_BEACON_SDF_PAYLOAD;
+ case NAN_MSG_ID_SELF_TRANSMIT_FOLLOWUP_IND:
+ return NAN_INDICATION_SELF_TRANSMIT_FOLLOWUP;
+ case NAN_MSG_ID_RANGING_REQUEST_RECEVD_IND:
+ return NAN_INDICATION_RANGING_REQUEST_RECEIVED;
+ case NAN_MSG_ID_RANGING_RESULT_IND:
+ return NAN_INDICATION_RANGING_RESULT;
+ default:
+ return NAN_INDICATION_UNKNOWN;
+ }
+}
+
+int NanCommand::getNanPublishReplied(NanPublishRepliedInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanPublishRepliedIndMsg pRsp = (pNanPublishRepliedIndMsg)mNanVendorEvent;
+ event->requestor_instance_id = pRsp->publishRepliedIndParams.matchHandle;
+
+ event->rssi_value = 0;
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ if (remainingLen <= 0) {
+ ALOGI("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+ while ((remainingLen > 0) &&
+ (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv, remainingLen)))) {
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > sizeof(event->addr)) {
+ outputTlv.length = sizeof(event->addr);
+ }
+ memcpy(event->addr, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
+ if (outputTlv.length > sizeof(event->rssi_value)) {
+ outputTlv.length = sizeof(event->rssi_value);
+ }
+ memcpy(&event->rssi_value, outputTlv.value,
+ outputTlv.length);
+ break;
+ default:
+ ALOGI("Unknown TLV type skipped");
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv, 0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanPublishTerminated(NanPublishTerminatedInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanPublishTerminatedIndMsg pRsp = (pNanPublishTerminatedIndMsg)mNanVendorEvent;
+ event->publish_id = pRsp->fwHeader.handle;
+ NanErrorTranslation((NanInternalStatusType)pRsp->reason, 0,
+ (void*)event, false);
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanMatch(NanMatchInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanMatchIndMsg pRsp = (pNanMatchIndMsg)mNanVendorEvent;
+ event->publish_subscribe_id = pRsp->fwHeader.handle;
+ event->requestor_instance_id = pRsp->matchIndParams.matchHandle;
+ event->match_occured_flag = pRsp->matchIndParams.matchOccuredFlag;
+ event->out_of_resource_flag = pRsp->matchIndParams.outOfResourceFlag;
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader) + sizeof(NanMatchIndParams)));
+ int ret = 0, idx = 0;
+
+ //Has SDF match filter and service specific info TLV
+ if (remainingLen <= 0) {
+ ALOGV("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
+ if (outputTlv.length > NAN_MAX_SERVICE_NAME_LEN) {
+ outputTlv.length = NAN_MAX_SERVICE_NAME_LEN;
+ }
+ event->service_specific_info_len = outputTlv.length;
+ memcpy(event->service_specific_info, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_SDF_MATCH_FILTER:
+ if (outputTlv.length > NAN_MAX_MATCH_FILTER_LEN) {
+ outputTlv.length = NAN_MAX_MATCH_FILTER_LEN;
+ }
+ event->sdf_match_filter_len = outputTlv.length;
+ memcpy(event->sdf_match_filter, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > sizeof(event->addr)) {
+ outputTlv.length = sizeof(event->addr);
+ }
+ memcpy(event->addr, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
+ if (outputTlv.length > sizeof(event->rssi_value)) {
+ outputTlv.length = sizeof(event->rssi_value);
+ }
+ memcpy(&event->rssi_value, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
+ if (outputTlv.length != sizeof(u32)) {
+ ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
+ "Incorrect size:%d expecting %zu", outputTlv.length,
+ sizeof(u32));
+ break;
+ }
+ event->is_conn_capability_valid = 1;
+ /* Populate conn_capability from received TLV */
+ getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
+ &event->conn_capability);
+ break;
+ case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
+ /* Populate receive discovery attribute from
+ received TLV */
+ idx = event->num_rx_discovery_attr;
+ if (idx < 0 || idx >= NAN_MAX_POSTDISCOVERY_LEN) {
+ ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
+ " Incorrect index:%d >= %d", idx, NAN_MAX_POSTDISCOVERY_LEN);
+ break;
+ }
+ ret = getNanReceivePostDiscoveryVal(outputTlv.value,
+ outputTlv.length,
+ &event->discovery_attr[idx]);
+ if (ret == 0) {
+ event->num_rx_discovery_attr++;
+ } else {
+ ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
+ "Incorrect");
+ }
+ break;
+ case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
+ /* Populate further availability bitmap from
+ received TLV */
+ ret = getNanFurtherAvailabilityMap(outputTlv.value,
+ outputTlv.length,
+ &event->num_chans,
+ &event->famchan[0]);
+ if (ret < 0)
+ ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
+ "Incorrect");
+ break;
+ case NAN_TLV_TYPE_CLUSTER_ATTRIBUTE:
+ if (outputTlv.length > sizeof(event->cluster_attribute)) {
+ outputTlv.length = sizeof(event->cluster_attribute);
+ }
+ memcpy(event->cluster_attribute,
+ outputTlv.value, outputTlv.length);
+ event->cluster_attribute_len = outputTlv.length;
+ break;
+ case NAN_TLV_TYPE_NAN_CSID:
+ if (outputTlv.length > sizeof(event->peer_cipher_type)) {
+ outputTlv.length = sizeof(event->peer_cipher_type);
+ }
+ memcpy(&event->peer_cipher_type, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_NAN_SCID:
+ if (outputTlv.length > sizeof(event->scid)) {
+ outputTlv.length = sizeof(event->scid);
+ }
+ event->scid_len = outputTlv.length;
+ memcpy(event->scid, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_SDEA_CTRL_PARAMS:
+ if (outputTlv.length != sizeof(u32)) {
+ ALOGE("NAN_TLV_TYPE_SDEA_CTRL_PARAMS"
+ "Incorrect size:%d expecting %zu", outputTlv.length,
+ sizeof(u32));
+ break;
+ }
+ getNanReceiveSdeaCtrlParams(outputTlv.value,
+ &event->peer_sdea_params);
+ break;
+ case NAN_TLV_TYPE_NAN20_RANGING_RESULT:
+ if (outputTlv.length > sizeof(event->range_info)) {
+ outputTlv.length = sizeof(event->range_info);
+ }
+ memcpy(&event->range_info, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO:
+ if (outputTlv.length > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ outputTlv.length = NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN;
+ }
+ event->sdea_service_specific_info_len = outputTlv.length;
+ memcpy(event->sdea_service_specific_info, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_SERVICE_ID:
+ mNanCommandInstance->saveServiceId(outputTlv.value,
+ event->publish_subscribe_id,
+ event->requestor_instance_id,
+ NAN_ROLE_SUBSCRIBER);
+ break;
+ default:
+ ALOGV("Unknown TLV type skipped");
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv, 0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanMatchExpired(NanMatchExpiredInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanMatchExpiredIndMsg pRsp = (pNanMatchExpiredIndMsg)mNanVendorEvent;
+ event->publish_subscribe_id = pRsp->fwHeader.handle;
+ event->requestor_instance_id = pRsp->matchExpiredIndParams.matchHandle;
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanSubscribeTerminated(NanSubscribeTerminatedInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanSubscribeTerminatedIndMsg pRsp = (pNanSubscribeTerminatedIndMsg)mNanVendorEvent;
+ event->subscribe_id = pRsp->fwHeader.handle;
+ NanErrorTranslation((NanInternalStatusType)pRsp->reason, 0,
+ (void*)event, false);
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanFollowup(NanFollowupInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanFollowupIndMsg pRsp = (pNanFollowupIndMsg)mNanVendorEvent;
+ event->publish_subscribe_id = pRsp->fwHeader.handle;
+ event->requestor_instance_id = pRsp->followupIndParams.matchHandle;
+ event->dw_or_faw = pRsp->followupIndParams.window;
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader) + sizeof(NanFollowupIndParams)));
+
+ //Has service specific info and extended service specific info TLV
+ if (remainingLen <= 0) {
+ ALOGV("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
+ case NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO:
+ if (outputTlv.length > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ outputTlv.length = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN;
+ }
+ event->service_specific_info_len = outputTlv.length;
+ memcpy(event->service_specific_info, outputTlv.value,
+ outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > sizeof(event->addr)) {
+ outputTlv.length = sizeof(event->addr);
+ }
+ memcpy(event->addr, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO:
+ if (outputTlv.length > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ outputTlv.length = NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN;
+ }
+ event->sdea_service_specific_info_len = outputTlv.length;
+ memcpy(event->sdea_service_specific_info, outputTlv.value,
+ outputTlv.length);
+ break;
+ default:
+ ALOGV("Unknown TLV type skipped");
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv, 0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanEventIndMsg pRsp = (pNanEventIndMsg)mNanVendorEvent;
+ memset(&event->data, 0, sizeof(event->data));
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ //Has Self-STA Mac TLV
+ if (remainingLen <= 0) {
+ ALOGE("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_EVENT_SELF_STATION_MAC_ADDRESS:
+ if (outputTlv.length > NAN_MAC_ADDR_LEN) {
+ ALOGV("%s: Reading only first %d bytes of TLV",
+ __func__, NAN_MAC_ADDR_LEN);
+ outputTlv.length = NAN_MAC_ADDR_LEN;
+ }
+ memcpy(event->data.mac_addr.addr, outputTlv.value,
+ outputTlv.length);
+ event->event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ break;
+ case NAN_TLV_TYPE_EVENT_STARTED_CLUSTER:
+ if (outputTlv.length > NAN_MAC_ADDR_LEN) {
+ ALOGV("%s: Reading only first %d bytes of TLV",
+ __func__, NAN_MAC_ADDR_LEN);
+ outputTlv.length = NAN_MAC_ADDR_LEN;
+ }
+ memcpy(event->data.cluster.addr, outputTlv.value,
+ outputTlv.length);
+ event->event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+ break;
+ case NAN_TLV_TYPE_EVENT_JOINED_CLUSTER:
+ if (outputTlv.length > NAN_MAC_ADDR_LEN) {
+ ALOGV("%s: Reading only first %d bytes of TLV",
+ __func__, NAN_MAC_ADDR_LEN);
+ outputTlv.length = NAN_MAC_ADDR_LEN;
+ }
+ memcpy(event->data.cluster.addr, outputTlv.value,
+ outputTlv.length);
+ event->event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+ break;
+ default:
+ ALOGV("Unhandled TLV type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanDisabled(NanDisabledInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanDisableIndMsg pRsp = (pNanDisableIndMsg)mNanVendorEvent;
+ NanErrorTranslation((NanInternalStatusType)pRsp->reason, 0,
+ (void*)event, false);
+ return WIFI_SUCCESS;
+
+}
+
+int NanCommand::getNanTca(NanTCAInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanTcaIndMsg pRsp = (pNanTcaIndMsg)mNanVendorEvent;
+ memset(&event->data, 0, sizeof(event->data));
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ //Has NAN_TCA_ID_CLUSTER_SIZE
+ if (remainingLen <= 0) {
+ ALOGE("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_CLUSTER_SIZE_RSP:
+ if (outputTlv.length != 2 * sizeof(u32)) {
+ ALOGE("%s: Wrong length %d in Tca Indication expecting %zu bytes",
+ __func__, outputTlv.length, 2 * sizeof(u32));
+ break;
+ }
+ event->rising_direction_evt_flag = outputTlv.value[0] & 0x01;
+ event->falling_direction_evt_flag = (outputTlv.value[0] & 0x02) >> 1;
+ memcpy(&(event->data.cluster.cluster_size), &outputTlv.value[4],
+ sizeof(event->data.cluster.cluster_size));
+ event->tca_type = NAN_TCA_ID_CLUSTER_SIZE;
+ break;
+ default:
+ ALOGV("Unhandled TLV type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanBeaconSdfPayloadIndMsg pRsp = (pNanBeaconSdfPayloadIndMsg)mNanVendorEvent;
+ memset(&event->data, 0, sizeof(event->data));
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ //Has Mac address
+ if (remainingLen <= 0) {
+ ALOGV("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > sizeof(event->addr)) {
+ outputTlv.length = sizeof(event->addr);
+ }
+ memcpy(event->addr, outputTlv.value,
+ outputTlv.length);
+ break;
+
+ case NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE:
+ {
+ NanReceiveVendorSpecificAttribute* recvVsaattr = &event->vsa;
+ if (outputTlv.length < sizeof(u32)) {
+ ALOGE("NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE"
+ "Incorrect length:%d", outputTlv.length);
+ break;
+ }
+ event->is_vsa_received = 1;
+ recvVsaattr->vsa_received_on = (outputTlv.value[0] >> 1) & 0x07;
+ memcpy(&recvVsaattr->vendor_oui, &outputTlv.value[1],
+ 3);
+ recvVsaattr->attr_len = outputTlv.length - 4;
+ if (recvVsaattr->attr_len > NAN_MAX_VSA_DATA_LEN) {
+ recvVsaattr->attr_len = NAN_MAX_VSA_DATA_LEN;
+ }
+ if (recvVsaattr->attr_len) {
+ memcpy(recvVsaattr->vsa, &outputTlv.value[4],
+ recvVsaattr->attr_len);
+ }
+ break;
+ }
+
+ case NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE:
+ event->is_beacon_sdf_payload_received = 1;
+ event->data.frame_len = outputTlv.length;
+ if (event->data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
+ event->data.frame_len = NAN_MAX_FRAME_DATA_LEN;
+ }
+ memcpy(&event->data.frame_data, &outputTlv.value[0],
+ event->data.frame_len);
+ break;
+
+ default:
+ ALOGV("Unhandled TLV Type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+void NanCommand::getNanReceivePostConnectivityCapabilityVal(
+ const u8 *pInValue,
+ NanReceivePostConnectivityCapability *pRxCapab)
+{
+ if (pInValue && pRxCapab) {
+ pRxCapab->is_mesh_supported = (pInValue[0] & (0x01 << 5));
+ pRxCapab->is_ibss_supported = (pInValue[0] & (0x01 << 4));
+ pRxCapab->wlan_infra_field = (pInValue[0] & (0x01 << 3));
+ pRxCapab->is_tdls_supported = (pInValue[0] & (0x01 << 2));
+ pRxCapab->is_wfds_supported = (pInValue[0] & (0x01 << 1));
+ pRxCapab->is_wfd_supported = pInValue[0] & 0x01;
+ }
+}
+
+void NanCommand::getNanReceiveSdeaCtrlParams(const u8* pInValue,
+ NanSdeaCtrlParams *pPeerSdeaParams)
+{
+ if (pInValue && pPeerSdeaParams) {
+ pPeerSdeaParams->security_cfg =
+ (NanDataPathSecurityCfgStatus)((pInValue[0] & BIT_6) ?
+ NAN_DP_CONFIG_SECURITY : NAN_DP_CONFIG_NO_SECURITY);
+ pPeerSdeaParams->ranging_state =
+ (NanRangingState)((pInValue[0] & BIT_7) ?
+ NAN_RANGING_ENABLE : NAN_RANGING_DISABLE);
+#if 0
+ pPeerSdeaParams->enable_ranging_limit =
+ (NanRangingLimitState)((pInValue[0] & BIT_8) ?
+ NAN_RANGING_LIMIT_ENABLE : NAN_RANGING_LIMIT_DISABLE);
+#endif
+ }
+ return;
+}
+
+int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue,
+ u32 length,
+ NanReceivePostDiscovery *pRxDisc)
+{
+ int ret = 0;
+
+ if (length <= 8 || pInValue == NULL) {
+ ALOGE("%s: Invalid Arg TLV Len %d < 4",
+ __func__, length);
+ return -1;
+ }
+
+ pRxDisc->type = (NanConnectionType) pInValue[0];
+ pRxDisc->role = (NanDeviceRole) pInValue[1];
+ pRxDisc->duration = (NanAvailDuration) (pInValue[2] & 0x03);
+ pRxDisc->mapid = ((pInValue[2] >> 2) & 0x0F);
+ memcpy(&pRxDisc->avail_interval_bitmap,
+ &pInValue[4],
+ sizeof(pRxDisc->avail_interval_bitmap));
+
+ u8 *pInputTlv = (u8 *)&pInValue[8];
+ NanTlv outputTlv;
+ u16 readLen = 0;
+ int remainingLen = (length - 8);
+
+ //Has Mac address
+ if (remainingLen <= 0) {
+ ALOGE("%s: No TLV's present",__func__);
+ return -1;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > sizeof(pRxDisc->addr)) {
+ outputTlv.length = sizeof(pRxDisc->addr);
+ }
+ memcpy(pRxDisc->addr, outputTlv.value, outputTlv.length);
+ break;
+ case NAN_TLV_TYPE_WLAN_MESH_ID:
+ if (outputTlv.length > sizeof(pRxDisc->mesh_id)) {
+ outputTlv.length = sizeof(pRxDisc->mesh_id);
+ }
+ memcpy(pRxDisc->mesh_id, outputTlv.value, outputTlv.length);
+ pRxDisc->mesh_id_len = outputTlv.length;
+ break;
+ case NAN_TLV_TYPE_WLAN_INFRA_SSID:
+ if (outputTlv.length > sizeof(pRxDisc->infrastructure_ssid_val)) {
+ outputTlv.length = sizeof(pRxDisc->infrastructure_ssid_val);
+ }
+ memcpy(pRxDisc->infrastructure_ssid_val, outputTlv.value,
+ outputTlv.length);
+ pRxDisc->infrastructure_ssid_len = outputTlv.length;
+ break;
+ default:
+ ALOGV("Unhandled TLV Type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return ret;
+}
+
+int NanCommand::getNanFurtherAvailabilityMap(const u8 *pInValue,
+ u32 length,
+ u8 *num_chans,
+ NanFurtherAvailabilityChannel *pFac)
+{
+ int idx = 0;
+
+ if ((length == 0) || pInValue == NULL) {
+ ALOGE("%s: Invalid Arg TLV Len %d or pInValue NULL",
+ __func__, length);
+ return -1;
+ }
+
+ *num_chans = pInValue[0];
+ if (*num_chans > NAN_MAX_FAM_CHANNELS) {
+ ALOGE("%s: Unable to accommodate numchans %d",
+ __func__, *num_chans);
+ return -1;
+ }
+
+ if (length < (sizeof(u8) +
+ (*num_chans * sizeof(NanFurtherAvailabilityChan)))) {
+ ALOGE("%s: Invalid TLV Length", __func__);
+ return -1;
+ }
+
+ for (idx = 0; idx < *num_chans; idx++) {
+ pNanFurtherAvailabilityChan pRsp = \
+ (pNanFurtherAvailabilityChan)((u8 *)&pInValue[1] + \
+ (idx * sizeof(NanFurtherAvailabilityChan)));
+
+ pFac->entry_control = \
+ (NanAvailDuration)(pRsp->entryCtrl.availIntDuration);
+ pFac->mapid = pRsp->entryCtrl.mapId;
+ pFac->class_val = pRsp->opClass;
+ pFac->channel = pRsp->channel;
+ memcpy(&pFac->avail_interval_bitmap,
+ &pRsp->availIntBitmap,
+ sizeof(pFac->avail_interval_bitmap));
+ pFac++;
+ }
+ return 0;
+}
+
+wifi_error NanCommand::getNanStaParameter(wifi_interface_handle iface,
+ NanStaParameter *pRsp)
+{
+ wifi_error ret = WIFI_ERROR_NONE;
+ transaction_id id = 1;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+
+ ret = create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*
+ Construct NL message to get the sync stats parameter
+ which has all the parameter required by staparameter.
+ */
+ NanStatsRequest syncStats;
+ memset(&syncStats, 0, sizeof(syncStats));
+ syncStats.stats_type = NAN_STATS_ID_DE_TIMING_SYNC;
+ syncStats.clear = 0;
+
+ mStaParam = pRsp;
+ ret = putNanStats(id, &syncStats);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: putNanStats Error:%d",__func__, ret);
+ goto cleanup;
+ }
+ ret = requestEvent();
+ if (ret != 0) {
+ ALOGE("%s: requestEvent Error:%d",__func__, ret);
+ goto cleanup;
+ }
+
+ struct timespec abstime;
+ abstime.tv_sec = 4;
+ abstime.tv_nsec = 0;
+ ret = mCondition.wait(abstime);
+ if (ret == WIFI_ERROR_TIMED_OUT)
+ {
+ ALOGE("%s: Time out happened.", __func__);
+ goto cleanup;
+ }
+ ALOGV("%s: NanStaparameter Master_pref:%x," \
+ " Random_factor:%x, hop_count:%x " \
+ " beacon_transmit_time:%d" \
+ " ndp_channel_freq:%d", __func__,
+ pRsp->master_pref, pRsp->random_factor,
+ pRsp->hop_count, pRsp->beacon_transmit_time, pRsp->ndp_channel_freq);
+cleanup:
+ mStaParam = NULL;
+ return ret;
+}
+
+int NanCommand::getNanTransmitFollowupInd(NanTransmitFollowupInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanSelfTransmitFollowupIndMsg pRsp = (pNanSelfTransmitFollowupIndMsg)mNanVendorEvent;
+ event->id = pRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pRsp->reason, 0,
+ (void*)event, false);
+ return WIFI_SUCCESS;
+}
+
+//Function which calls the necessaryIndication callback
+//based on the indication type
+int NanCommand::handleNdpIndication(u32 ndpCmdType, struct nlattr **tb_vendor)
+{
+ //Based on the message_id in the header determine the Indication type
+ //and call the necessary callback handler
+ int res = 0;
+
+ ALOGI("handleNdpIndication msg_id:%u", ndpCmdType);
+ switch (ndpCmdType) {
+ case QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND:
+ NanDataPathRequestInd ndpRequestInd;
+ memset(&ndpRequestInd, 0, sizeof(ndpRequestInd));
+
+ res = getNdpRequest(tb_vendor, &ndpRequestInd);
+ if (!res && mHandler.EventDataRequest) {
+ (*mHandler.EventDataRequest)(&ndpRequestInd);
+ }
+ break;
+
+ case QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND:
+ NanDataPathConfirmInd ndpConfirmInd;
+ memset(&ndpConfirmInd, 0, sizeof(ndpConfirmInd));
+
+ res = getNdpConfirm(tb_vendor, &ndpConfirmInd);
+ if (!res && mHandler.EventDataConfirm) {
+ (*mHandler.EventDataConfirm)(&ndpConfirmInd);
+ }
+ break;
+
+ case QCA_WLAN_VENDOR_ATTR_NDP_END_IND:
+ {
+ NanDataPathEndInd *ndpEndInd = NULL;
+ u8 num_ndp_ids = 0;
+ u8 i;
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ num_ndp_ids = (u8)(nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY])/sizeof(u32));
+ ALOGD("%s: NDP Num Instance Ids : val %d", __FUNCTION__, num_ndp_ids);
+
+ if (num_ndp_ids) {
+ ndpEndInd =
+ (NanDataPathEndInd *)malloc(sizeof(NanDataPathEndInd)+ (sizeof(u32) * num_ndp_ids));
+ if (!ndpEndInd) {
+ ALOGE("%s: ndp_instance_id malloc Failed", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ ndpEndInd->num_ndp_instances = num_ndp_ids;
+ nla_memcpy(ndpEndInd->ndp_instance_id,
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY],
+ sizeof(u32) * ndpEndInd->num_ndp_instances);
+ }
+ for (i = 0; i < num_ndp_ids; i++) {
+ mNanCommandInstance->deleteServiceId(0,
+ ndpEndInd->ndp_instance_id[i],
+ NAN_ROLE_PUBLISHER);
+ }
+ if (mHandler.EventDataEnd) {
+ (*mHandler.EventDataEnd)(ndpEndInd);
+ }
+ free(ndpEndInd);
+ break;
+ }
+
+ case QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND:
+ {
+ NanDataPathScheduleUpdateInd *pNdpScheduleUpdateInd;
+ u32 num_channels = 0, num_ndp_ids = 0;
+
+ if ((!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY])) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS]) {
+ num_channels = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS]);
+ ALOGD("%s: num_channels = %d", __FUNCTION__, num_channels);
+ if ((num_channels > NAN_MAX_CHANNEL_INFO_SUPPORTED) &&
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO])) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+ num_ndp_ids = (u8)(nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY])/sizeof(u32));
+ ALOGD("%s: NDP Num Instance Ids : val %d", __FUNCTION__, num_ndp_ids);
+
+ pNdpScheduleUpdateInd =
+ (NanDataPathScheduleUpdateInd *)malloc(sizeof(NanDataPathScheduleUpdateInd)
+ + (sizeof(u32) * num_ndp_ids));
+ if (!pNdpScheduleUpdateInd) {
+ ALOGE("%s: NdpScheduleUpdate malloc Failed", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ pNdpScheduleUpdateInd->num_channels = num_channels;
+ pNdpScheduleUpdateInd->num_ndp_instances = num_ndp_ids;
+
+ res = getNdpScheduleUpdate(tb_vendor, pNdpScheduleUpdateInd);
+ if (!res && mHandler.EventScheduleUpdate) {
+ (*mHandler.EventScheduleUpdate)(pNdpScheduleUpdateInd);
+ }
+ free(pNdpScheduleUpdateInd);
+ break;
+ }
+ default:
+ ALOGE("handleNdpIndication error invalid ndpCmdType:%u", ndpCmdType);
+ res = (int)WIFI_ERROR_INVALID_REQUEST_ID;
+ break;
+ }
+ return res;
+}
+
+int NanCommand::getNdpRequest(struct nlattr **tb_vendor,
+ NanDataPathRequestInd *event)
+{
+ u32 len = 0;
+
+ if (event == NULL || tb_vendor == NULL) {
+ ALOGE("%s: Invalid input argument event:%p tb_vendor:%p",
+ __FUNCTION__, event, tb_vendor);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if ((!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID])) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ event->service_instance_id = nla_get_u16(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]);
+ ALOGD("%s: Service Instance id : val %d", __FUNCTION__, event->service_instance_id);
+
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]);
+ len = ((sizeof(event->peer_disc_mac_addr) <= len) ? sizeof(event->peer_disc_mac_addr) : len);
+ memcpy(&event->peer_disc_mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]), len);
+
+ event->ndp_instance_id = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]);
+ ALOGD("%s: Ndp Instance id: %d", __FUNCTION__, event->ndp_instance_id);
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) {
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
+ len = ((sizeof(event->app_info.ndp_app_info) <= len) ? sizeof(event->app_info.ndp_app_info) : len);
+ memcpy(&event->app_info.ndp_app_info[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]), len);
+ event->app_info.ndp_app_info_len = len;
+ } else {
+ ALOGD("%s: NDP App Info not present", __FUNCTION__);
+ }
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_ID]) {
+ mNanCommandInstance->saveServiceId((u8 *)nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_ID]),
+ event->service_instance_id,
+ event->ndp_instance_id,
+ NAN_ROLE_PUBLISHER);
+ } else {
+ ALOGD("%s: Service ID not present", __FUNCTION__);
+ }
+
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNdpConfirm(struct nlattr **tb_vendor,
+ NanDataPathConfirmInd *event)
+{
+ u32 len = 0;
+ NanInternalStatusType drv_reason_code;
+ struct nlattr *chInfo;
+ NanChannelInfo *pChInfo;
+ int rem;
+ u32 i = 0;
+
+ if (event == NULL || tb_vendor == NULL) {
+ ALOGE("%s: Invalid input argument event:%p tb_vendor:%p",
+ __FUNCTION__, event, tb_vendor);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if ((!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE])) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ event->ndp_instance_id = nla_get_u16(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]);
+ ALOGD("%s: Service Instance id : val %d", __FUNCTION__, event->ndp_instance_id);
+
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR]);
+ len = ((sizeof(event->peer_ndi_mac_addr) <= len) ? sizeof(event->peer_ndi_mac_addr) : len);
+ memcpy(&event->peer_ndi_mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR]), len);
+
+ event->rsp_code = (NanDataPathResponseCode)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
+ ALOGD("%s: Response code %d", __FUNCTION__, event->rsp_code);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) {
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
+ len = ((sizeof(event->app_info.ndp_app_info) <= len) ? sizeof(event->app_info.ndp_app_info) : len);
+ memcpy(&event->app_info.ndp_app_info[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]), len);
+ event->app_info.ndp_app_info_len = len;
+ } else {
+ ALOGD("%s: NDP App Info not present", __FUNCTION__);
+ }
+ drv_reason_code = (NanInternalStatusType)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE]);
+ ALOGD("%s: Drv reason code %d", __FUNCTION__, drv_reason_code);
+ switch (drv_reason_code) {
+ case NDP_I_MGMT_FRAME_REQUEST_FAILED:
+ case NDP_I_MGMT_FRAME_RESPONSE_FAILED:
+ case NDP_I_MGMT_FRAME_CONFIRM_FAILED:
+ case NDP_I_MGMT_FRAME_END_REQUEST_FAILED:
+ case NDP_I_MGMT_FRAME_SECURITY_INSTALL_FAILED:
+ event->reason_code = NAN_STATUS_PROTOCOL_FAILURE;
+ break;
+ case NDP_I_END_FAILED:
+ event->reason_code = NAN_STATUS_INTERNAL_FAILURE;
+ break;
+ default:
+ event->reason_code = (NanStatusType)drv_reason_code;
+ break;
+ }
+ ALOGD("%s: Reason code %d", __FUNCTION__, event->reason_code);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS]) {
+ event->num_channels =
+ nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS]);
+ ALOGD("%s: num_channels = %d", __FUNCTION__, event->num_channels);
+ if ((event->num_channels > NAN_MAX_CHANNEL_INFO_SUPPORTED) &&
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO])) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+
+ if (event->num_channels != 0) {
+ for (chInfo =
+ (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO]),
+ rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO]);
+ (i < NAN_MAX_CHANNEL_INFO_SUPPORTED && nla_ok(chInfo, rem));
+ chInfo = nla_next(chInfo, &(rem))) {
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
+
+ pChInfo =
+ (NanChannelInfo *) ((u8 *)event->channel_info + (i++ * (sizeof(NanChannelInfo))));
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
+ (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_CHANNEL not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->channel = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]);
+ ALOGD("%s: Channel = %d", __FUNCTION__, pChInfo->channel);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->bandwidth = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH]);
+ ALOGD("%s: Channel BW = %d", __FUNCTION__, pChInfo->bandwidth);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_NSS]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_NSS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->nss = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_NSS]);
+ ALOGD("%s: No. Spatial Stream = %d", __FUNCTION__, pChInfo->nss);
+ }
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNdpScheduleUpdate(struct nlattr **tb_vendor,
+ NanDataPathScheduleUpdateInd *event)
+{
+ u32 len = 0;
+ struct nlattr *chInfo;
+ NanChannelInfo *pChInfo;
+ int rem;
+ u32 i = 0;
+
+ len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]);
+ len = ((sizeof(event->peer_mac_addr) <= len) ? sizeof(event->peer_mac_addr) : len);
+ memcpy(&event->peer_mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]), len);
+
+ event->schedule_update_reason_code = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON]);
+ ALOGD("%s: Reason code %d", __FUNCTION__, event->schedule_update_reason_code);
+
+ if (event->num_channels != 0) {
+ for (chInfo =
+ (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO]),
+ rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO]);
+ (i < NAN_MAX_CHANNEL_INFO_SUPPORTED && nla_ok(chInfo, rem));
+ chInfo = nla_next(chInfo, &(rem))) {
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
+
+ pChInfo =
+ (NanChannelInfo *) ((u8 *)event->channel_info + (i++ * (sizeof(NanChannelInfo))));
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
+ (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_CHANNEL not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->channel = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]);
+ ALOGD("%s: Channel = %d", __FUNCTION__, pChInfo->channel);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->bandwidth = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH]);
+ ALOGD("%s: Channel BW = %d", __FUNCTION__, pChInfo->bandwidth);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_NDP_NSS]) {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP_NSS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ pChInfo->nss = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_NDP_NSS]);
+ ALOGD("%s: No. Spatial Stream = %d", __FUNCTION__, pChInfo->nss);
+ }
+ }
+
+ if (event->num_ndp_instances) {
+ nla_memcpy(event->ndp_instance_id,
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY],
+ sizeof(u32) * event->num_ndp_instances);
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanRangeRequestReceivedInd(NanRangeRequestInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanFWRangeReqRecvdInd pRsp = (pNanFWRangeReqRecvdInd)mNanVendorEvent;
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ if (remainingLen <= 0) {
+ ALOGE("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_NAN20_RANGING_REQUEST_RECEIVED:
+ NanFWRangeReqRecvdMsg fwRangeReqRecvd;
+ if (outputTlv.length > sizeof(fwRangeReqRecvd)) {
+ outputTlv.length = sizeof(fwRangeReqRecvd);
+ }
+ memcpy(&fwRangeReqRecvd, outputTlv.value, outputTlv.length);
+ FW_MAC_ADDR_TO_CHAR_ARRAY(fwRangeReqRecvd.range_mac_addr, event->range_req_intf_addr);
+ event->publish_id = fwRangeReqRecvd.range_id;
+ break;
+ default:
+ ALOGV("Unhandled TLV type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
+
+int NanCommand::getNanRangeReportInd(NanRangeReportInd *event)
+{
+ if (event == NULL || mNanVendorEvent == NULL) {
+ ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
+ __func__, event, mNanVendorEvent);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ pNanFWRangeReportInd pRsp = (pNanFWRangeReportInd)mNanVendorEvent;
+
+ u8 *pInputTlv = pRsp->ptlv;
+ NanTlv outputTlv;
+ u16 readLen = 0;
+
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader)));
+
+ if (remainingLen <= 0) {
+ ALOGE("%s: No TLV's present",__func__);
+ return WIFI_SUCCESS;
+ }
+
+ ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
+ while ((remainingLen > 0) &&
+ (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);
+ switch (outputTlv.type) {
+ case NAN_TLV_TYPE_MAC_ADDRESS:
+ if (outputTlv.length > NAN_MAC_ADDR_LEN) {
+ outputTlv.length = NAN_MAC_ADDR_LEN;
+ }
+ memcpy(event->range_req_intf_addr, outputTlv.value, outputTlv.length);
+ break;
+
+ case NAN_TLV_TYPE_NAN20_RANGING_RESULT:
+ NanFWRangeReportParams range_params;
+ if (outputTlv.length > sizeof(NanFWRangeReportParams)) {
+ outputTlv.length = sizeof(NanFWRangeReportParams);
+ }
+ memcpy(&range_params, outputTlv.value, outputTlv.length);
+ event->range_measurement_mm = range_params.range_measurement;
+ event->publish_id = range_params.publish_id;
+// event->event_type = range_params.event_type;
+ break;
+ default:
+ ALOGV("Unhandled TLV type:%d", outputTlv.type);
+ break;
+ }
+ remainingLen -= readLen;
+ pInputTlv += readLen;
+ memset(&outputTlv,0, sizeof(outputTlv));
+ }
+ return WIFI_SUCCESS;
+}
diff --git a/qcwcn/wifi_hal/nan_req.cpp b/wcn6740/qcwcn/wifi_hal/nan_req.cpp
similarity index 80%
copy from qcwcn/wifi_hal/nan_req.cpp
copy to wcn6740/qcwcn/wifi_hal/nan_req.cpp
index fd8516f..1350623 100644
--- a/qcwcn/wifi_hal/nan_req.cpp
+++ b/wcn6740/qcwcn/wifi_hal/nan_req.cpp
@@ -12,6 +12,40 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#include "sync.h"
@@ -25,12 +59,18 @@
wifi_error ret;
ALOGV("NAN_ENABLE");
size_t message_len = NAN_MAX_ENABLE_REQ_SIZE;
+ int freq_24g;
if (pReq == NULL) {
cleanup();
return WIFI_ERROR_INVALID_ARGS;
}
+ if (pReq->config_24g_channel == 0)
+ freq_24g = 2437;
+ else
+ freq_24g = pReq->channel_24g_val;
+
message_len += \
(
pReq->config_support_5g ? (SIZEOF_TLV_HDR + \
@@ -117,8 +157,8 @@
sizeof(pReq->hop_count_force_val)) : 0 \
) + \
(
- pReq->config_24g_channel ? (SIZEOF_TLV_HDR + \
- sizeof(u32)) : 0 \
+ /* always include 24g channel/freq */
+ SIZEOF_TLV_HDR + sizeof(u32) \
) + \
(
pReq->config_5g_channel ? (SIZEOF_TLV_HDR + \
@@ -159,10 +199,6 @@
(
pReq->config_dw_early_termination ? (SIZEOF_TLV_HDR + \
sizeof(u32)) : 0 \
- ) + \
- (
- pReq->config_ndpe_attr? (SIZEOF_TLV_HDR + \
- sizeof(NanDevCapAttrCap)) : 0 \
);
pNanEnableReqMsg pFwReq = (pNanEnableReqMsg)malloc(message_len);
@@ -288,11 +324,9 @@
sizeof(pReq->hop_count_force_val),
(const u8*)&pReq->hop_count_force_val, tlvs);
}
- if (pReq->config_24g_channel) {
- tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
+ tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
sizeof(u32),
- (const u8*)&pReq->channel_24g_val, tlvs);
- }
+ (const u8*)&freq_24g, tlvs);
if (pReq->config_5g_channel) {
tlvs = addTlv(NAN_TLV_TYPE_5G_CHANNEL,
sizeof(u32),
@@ -316,6 +350,17 @@
u32 config_discovery_indications;
config_discovery_indications = (u32)pReq->discovery_indication_cfg;
+ /* Save the discovery MAC indication config if it is disabled from the
+ * framework and use it later to decide if the framework to be notified of
+ * the response. And enable the self MAC discovery indication from firmware
+ * by resetting the bit in config to get the Self MAC.
+ */
+ if (config_discovery_indications & NAN_DISC_ADDR_IND_DISABLED) {
+ mNanCommandInstance->mNanDiscAddrIndDisabled = true;
+ config_discovery_indications &= ~NAN_DISC_ADDR_IND_DISABLED;
+ } else {
+ mNanCommandInstance->mNanDiscAddrIndDisabled = false;
+ }
tlvs = addTlv(NAN_TLV_TYPE_CONFIG_DISCOVERY_INDICATIONS,
sizeof(u32),
(const u8*)&config_discovery_indications, tlvs);
@@ -341,23 +386,52 @@
tlvs = addTlv(NAN_TLV_TYPE_DW_EARLY_TERMINATION, sizeof(u32),
(const u8*)&pReq->enable_dw_termination, tlvs);
}
- if (pReq->config_ndpe_attr) {
- NanDevCapAttrCap nanDevCapAttr;
- memset(&nanDevCapAttr, 0, sizeof(nanDevCapAttr));
- nanDevCapAttr.ndpe_attr_supp = pReq->use_ndpe_attr;
- tlvs = addTlv(NAN_TLV_TYPE_DEV_CAP_ATTR_CAPABILITY,
- sizeof(NanDevCapAttrCap),
- (const u8*)&nanDevCapAttr, tlvs);
- }
+
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- //Insert the vendor specific data
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ //Insert the vendor specific data
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ) ||
+ mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ,
+ freq_24g)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (pReq->config_5g_channel) {
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ,
+ pReq->channel_5g_val)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -385,11 +459,32 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ) ||
+ mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -486,10 +581,6 @@
(
pReq->config_dw_early_termination ? (SIZEOF_TLV_HDR + \
sizeof(u32)) : 0 \
- ) + \
- (
- pReq->config_ndpe_attr? (SIZEOF_TLV_HDR + \
- sizeof(NanDevCapAttrCap)) : 0 \
);
if (pReq->num_config_discovery_attr) {
@@ -617,10 +708,22 @@
u32 config_discovery_indications;
config_discovery_indications = (u32)(pReq->discovery_indication_cfg);
+ /* Save the discovery MAC indication config if it is disabled from the
+ * framework and use it later to decide if the framework to be notified of
+ * the response. And enable the self MAC discovery indication from firmware
+ * by resetting the bit in config to get the Self MAC.
+ */
+ if (config_discovery_indications & NAN_DISC_ADDR_IND_DISABLED) {
+ mNanCommandInstance->mNanDiscAddrIndDisabled = true;
+ config_discovery_indications &= ~NAN_DISC_ADDR_IND_DISABLED;
+ } else {
+ mNanCommandInstance->mNanDiscAddrIndDisabled = false;
+ }
/* Always include the discovery cfg TLV as there is no cfg flag */
tlvs = addTlv(NAN_TLV_TYPE_CONFIG_DISCOVERY_INDICATIONS,
sizeof(u32),
(const u8*)&config_discovery_indications, tlvs);
+
if (pReq->config_nss) {
tlvs = addTlv(NAN_TLV_TYPE_TX_RX_CHAINS, sizeof(u32),
(const u8*)&pReq->nss, tlvs);
@@ -633,23 +736,33 @@
tlvs = addTlv(NAN_TLV_TYPE_DW_EARLY_TERMINATION, sizeof(u32),
(const u8*)&pReq->enable_dw_termination, tlvs);
}
- if (pReq->config_ndpe_attr) {
- NanDevCapAttrCap nanDevCapAttr;
- memset(&nanDevCapAttr, 0, sizeof(nanDevCapAttr));
- nanDevCapAttr.ndpe_attr_supp = pReq->use_ndpe_attr;
- tlvs = addTlv(NAN_TLV_TYPE_DEV_CAP_ATTR_CAPABILITY,
- sizeof(NanDevCapAttrCap),
- (const u8*)&nanDevCapAttr, tlvs);
- }
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -709,7 +822,7 @@
if (pReq->publish_id == 0) {
pFwReq->fwHeader.handle = 0xFFFF;
} else {
- pFwReq->fwHeader.handle = pReq->publish_id;
+ pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
}
pFwReq->fwHeader.transactionId = id;
@@ -863,11 +976,29 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -895,17 +1026,36 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->publish_id;
+ pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -944,6 +1094,7 @@
message_len += \
(pReq->num_intf_addr_present * (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN));
+
if ((pReq->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) &&
(pReq->key_info.body.pmk_info.pmk_len == NAN_PMK_INFO_LEN))
message_len += SIZEOF_TLV_HDR + NAN_PMK_INFO_LEN;
@@ -955,6 +1106,7 @@
message_len += SIZEOF_TLV_HDR +
pReq->key_info.body.passphrase_info.passphrase_len;
+
pNanSubscribeServiceReqMsg pFwReq = (pNanSubscribeServiceReqMsg)malloc(message_len);
if (pFwReq == NULL) {
cleanup();
@@ -969,7 +1121,7 @@
if (pReq->subscribe_id == 0) {
pFwReq->fwHeader.handle = 0xFFFF;
} else {
- pFwReq->fwHeader.handle = pReq->subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
}
pFwReq->fwHeader.transactionId = id;
@@ -1123,11 +1275,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1156,16 +1327,35 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1201,7 +1391,7 @@
pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
pFwReq->fwHeader.msgId = NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ;
pFwReq->fwHeader.msgLen = message_len;
- pFwReq->fwHeader.handle = pReq->publish_subscribe_id;
+ pFwReq->fwHeader.handle = (pReq->publish_subscribe_id & 0xFF);
pFwReq->fwHeader.transactionId = id;
pFwReq->transmitFollowupReqParams.matchHandle = pReq->requestor_instance_id;
@@ -1235,11 +1425,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1276,11 +1485,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1332,11 +1560,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1399,11 +1646,30 @@
mVendorData = (char *)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1454,7 +1720,7 @@
{
wifi_error res;
int status;
- struct nl_cb * cb;
+ struct nl_cb * cb = NULL;
cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb) {
@@ -1489,6 +1755,7 @@
res = mapKernelErrortoWifiHalError(status);
out:
+ nl_cb_put(cb);
//free the VendorData
if (mVendorData) {
free(mVendorData);
@@ -1668,11 +1935,30 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
@@ -1711,12 +1997,31 @@
mVendorData = (char*)pFwReq;
mDataLen = message_len;
- /* Write the TLVs to the message. */
- ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s: put_bytes Error:%d",__func__, ret);
- cleanup();
- return ret;
+ ret = WIFI_SUCCESS;
+ if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
+ /* Write the TLVs to the message. */
+ ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: put_bytes Error:%d",__func__, ret);
+ cleanup();
+ return ret;
+ }
+ } else {
+ struct nlattr *nl_data;
+
+ nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (!nl_data) {
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
+ mVendorData, mDataLen)) {
+ ALOGE("%s: put attr error", __func__);
+ cleanup();
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ attr_end(nl_data);
}
hexdump(mVendorData, mDataLen);
return ret;
diff --git a/wcn6740/qcwcn/wifi_hal/nan_rsp.cpp b/wcn6740/qcwcn/wifi_hal/nan_rsp.cpp
new file mode 100644
index 0000000..060de7f
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nan_rsp.cpp
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include "sync.h"
+#include <utils/Log.h>
+#include "wifi_hal.h"
+#include "nan_i.h"
+#include "nancommand.h"
+
+
+int NanCommand::isNanResponse()
+{
+ if (mNanVendorEvent == NULL) {
+ ALOGE("NULL check failed");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
+
+ switch (pHeader->msgId) {
+ case NAN_MSG_ID_ERROR_RSP:
+ case NAN_MSG_ID_CONFIGURATION_RSP:
+ case NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_RSP:
+ case NAN_MSG_ID_PUBLISH_SERVICE_RSP:
+ case NAN_MSG_ID_SUBSCRIBE_SERVICE_RSP:
+ case NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_RSP:
+ case NAN_MSG_ID_TRANSMIT_FOLLOWUP_RSP:
+ case NAN_MSG_ID_STATS_RSP:
+ case NAN_MSG_ID_ENABLE_RSP:
+ case NAN_MSG_ID_DISABLE_RSP:
+ case NAN_MSG_ID_TCA_RSP:
+ case NAN_MSG_ID_BEACON_SDF_RSP:
+ case NAN_MSG_ID_CAPABILITIES_RSP:
+ case NAN_MSG_ID_TESTMODE_RSP:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+struct verboseTlv {
+ NanTlvType tlvType;
+ char strTlv[NAN_ERROR_STR_LEN];
+};
+
+struct verboseTlv tlvToStr[] = {
+ {NAN_TLV_TYPE_SDF_MATCH_FILTER, " SDF match filter"},
+ {NAN_TLV_TYPE_TX_MATCH_FILTER, " Tx match filter"},
+ {NAN_TLV_TYPE_RX_MATCH_FILTER, " Rx match filter"},
+ {NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO,
+ " Service specific info"},
+ {NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO,
+ " Extended Service specific info"},
+ {NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_TRANSMIT,
+ " Vendor specific attribute transmit"},
+ {NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE,
+ " Vendor specific attribute receive"},
+ {NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE,
+ " Post Nan connectivity capability receive"},
+ {NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE,
+ " Post Nan discovery attribute receive"},
+ {NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE,
+ " Beacon SDF payload receive"},
+
+ /* Configuration types */
+ {NAN_TLV_TYPE_CONFIG_FIRST, " Config first"},
+ {NAN_TLV_TYPE_24G_SUPPORT, " 2.4G support"},
+ {NAN_TLV_TYPE_24G_BEACON, " 2.4G beacon"},
+ {NAN_TLV_TYPE_24G_SDF, " 2.4G SDF"},
+ {NAN_TLV_TYPE_24G_RSSI_CLOSE, " 2.4G RSSI close"},
+ {NAN_TLV_TYPE_24G_RSSI_MIDDLE, " 2.4G RSSI middle"},
+ {NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY,
+ " 2.4G RSSI close proximity"},
+ {NAN_TLV_TYPE_5G_SUPPORT, " 5G support"},
+ {NAN_TLV_TYPE_5G_BEACON, " 5G beacon"},
+ {NAN_TLV_TYPE_5G_SDF, " 5G SDF"},
+ {NAN_TLV_TYPE_5G_RSSI_CLOSE, " 5G RSSI close"},
+ {NAN_TLV_TYPE_5G_RSSI_MIDDLE, " 5G RSSI middle"},
+ {NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
+ " 5G RSSI close proximity"},
+ {NAN_TLV_TYPE_SID_BEACON, " SID beacon"},
+ {NAN_TLV_TYPE_HOP_COUNT_LIMIT, " Hop count limit"},
+ {NAN_TLV_TYPE_MASTER_PREFERENCE, " Master preference"},
+ {NAN_TLV_TYPE_CLUSTER_ID_LOW, " Cluster ID low"},
+ {NAN_TLV_TYPE_CLUSTER_ID_HIGH, " Cluster ID high"},
+ {NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE,
+ " RSSI averaging window size"},
+ {NAN_TLV_TYPE_CLUSTER_OUI_NETWORK_ID,
+ " Cluster OUI network ID"},
+ {NAN_TLV_TYPE_SOURCE_MAC_ADDRESS,
+ " Source MAC address"},
+ {NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF,
+ " Cluster attribute in SDF"},
+ {NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
+ " Social channel scan params"},
+ {NAN_TLV_TYPE_DEBUGGING_FLAGS, " Debugging flags"},
+ {NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_TRANSMIT,
+ " Post nan connectivity capabilities transmit"},
+ {NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_TRANSMIT,
+ " Post nan discovery attribute transmit"},
+ {NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP,
+ " Further availability map"},
+ {NAN_TLV_TYPE_HOP_COUNT_FORCE, " Hop count force"},
+ {NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
+ " Random factor force"},
+ {NAN_TLV_TYPE_RANDOM_UPDATE_TIME,
+ " Random update time"},
+ {NAN_TLV_TYPE_EARLY_WAKEUP, " Early wakeup"},
+ {NAN_TLV_TYPE_PERIODIC_SCAN_INTERVAL,
+ " Periodic scan interval"},
+ {NAN_TLV_TYPE_DW_INTERVAL, " DW interval"},
+ {NAN_TLV_TYPE_DB_INTERVAL, " DB interval"},
+ {NAN_TLV_TYPE_FURTHER_AVAILABILITY,
+ " Further availability"},
+ {NAN_TLV_TYPE_24G_CHANNEL, " 2.4G channel"},
+ {NAN_TLV_TYPE_5G_CHANNEL, " 5G channel"},
+ {NAN_TLV_TYPE_CONFIG_LAST, " Config last"},
+
+ /* Attributes types */
+ {NAN_TLV_TYPE_ATTRS_FIRST, " Attributes first"},
+ {NAN_TLV_TYPE_AVAILABILITY_INTERVALS_MAP,
+ " Availability intervals map"},
+ {NAN_TLV_TYPE_WLAN_MESH_ID, " WLAN mesh ID"},
+ {NAN_TLV_TYPE_MAC_ADDRESS, " MAC address"},
+ {NAN_TLV_TYPE_RECEIVED_RSSI_VALUE,
+ " Received RSSI value"},
+ {NAN_TLV_TYPE_CLUSTER_ATTRIBUTE,
+ " Cluster attribute"},
+ {NAN_TLV_TYPE_WLAN_INFRA_SSID, " WLAN infra SSID"},
+ {NAN_TLV_TYPE_ATTRS_LAST, " Attributes last"},
+
+ /* Events Type */
+ {NAN_TLV_TYPE_EVENTS_FIRST, " Events first"},
+ {NAN_TLV_TYPE_EVENT_SELF_STATION_MAC_ADDRESS,
+ " Event Self station MAC address"},
+ {NAN_TLV_TYPE_EVENT_STARTED_CLUSTER,
+ " Event started cluster"},
+ {NAN_TLV_TYPE_EVENT_JOINED_CLUSTER,
+ " Event joined cluster"},
+ {NAN_TLV_TYPE_EVENT_CLUSTER_SCAN_RESULTS,
+ " Event cluster scan results"},
+ {NAN_TLV_TYPE_FAW_MEM_AVAIL,
+ " FAW memory availability"},
+ {NAN_TLV_TYPE_EVENTS_LAST, " Events last"},
+
+ /* TCA types */
+ {NAN_TLV_TYPE_TCA_FIRST, " TCA-Threshold Crossing Alert first"},
+ {NAN_TLV_TYPE_CLUSTER_SIZE_REQ,
+ " Cluster size request"},
+ {NAN_TLV_TYPE_CLUSTER_SIZE_RSP,
+ " Cluster size response"},
+ {NAN_TLV_TYPE_TCA_LAST, " TCA last"},
+
+ /* Statistics types */
+ {NAN_TLV_TYPE_STATS_FIRST, " Stats first"},
+ {NAN_TLV_TYPE_DE_PUBLISH_STATS,
+ " Discovery engine publish stats"},
+ {NAN_TLV_TYPE_DE_SUBSCRIBE_STATS,
+ " Discovery engine subscribe stats"},
+ {NAN_TLV_TYPE_DE_MAC_STATS,
+ " Discovery engine MAC stats"},
+ {NAN_TLV_TYPE_DE_TIMING_SYNC_STATS,
+ " Discovery engine timing sync stats"},
+ {NAN_TLV_TYPE_DE_DW_STATS,
+ " Discovery engine DW stats"},
+ {NAN_TLV_TYPE_DE_STATS, " Discovery engine stats"},
+ {NAN_TLV_TYPE_STATS_LAST, " Stats last"},
+
+ {NAN_TLV_TYPE_LAST, " Last"}
+};
+
+struct errorCode {
+ NanStatusType frameworkError;
+ NanInternalStatusType firmwareError;
+ char nan_error[NAN_ERROR_STR_LEN];
+};
+
+struct errorCode errorCodeTranslation[] = {
+ {NAN_STATUS_SUCCESS, NAN_I_STATUS_SUCCESS,
+ "NAN status success"},
+
+ {NAN_STATUS_INTERNAL_FAILURE, NAN_I_STATUS_DE_FAILURE,
+ "NAN Discovery engine failure"},
+
+ {NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID, NAN_I_STATUS_INVALID_HANDLE,
+ "Invalid Publish/Subscribe ID"},
+
+ {NAN_STATUS_NO_RESOURCE_AVAILABLE, NAN_I_STATUS_NO_SPACE_AVAILABLE,
+ "No space available"},
+
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_PUBLISH_TYPE,
+ "Invalid Publish type, can be 0 or 1"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TX_TYPE,
+ "Invalid Tx type"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_MSG_VERSION,
+ "Invalid internal message version"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_MSG_LEN,
+ "Invalid message length"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_MSG_ID,
+ "Invalid message ID"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_MATCH_ALGORITHM,
+ "Invalid matching algorithm, can be 0(match once), 1(match continuous) or 2(match never)"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TLV_LEN,
+ "Invalid TLV length"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TLV_TYPE,
+ "Invalid TLV type"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_MISSING_TLV_TYPE,
+ "Missing TLV type"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TOTAL_TLVS_LEN,
+ "Invalid total TLV length"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TLV_VALUE,
+ "Invalid TLV value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_TX_PRIORITY,
+ "Invalid Tx priority"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_CONNECTION_MAP,
+ "Invalid connection map"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_THRESHOLD_CROSSING_ALERT_ID,
+ "Invalid TCA-Threshold Crossing Alert ID"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_STATS_ID,
+ "Invalid STATS ID"},
+
+ {NAN_STATUS_PROTOCOL_FAILURE, NAN_I_STATUS_TX_FAIL,
+ "Tx Fail"},
+
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_RSSI_CLOSE_VALUE,
+ "Invalid RSSI close value range is 20dbm to 60dbm"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_RSSI_MIDDLE_VALUE,
+ "Invalid RSSI middle value range is 20dbm to 75dbm"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_HOP_COUNT_LIMIT,
+ "Invalid hop count limit, max hop count limit is 5"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE,
+ "Invalid cluster ID value. Please set the cluster id high greater than the cluster id low"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_BACKGROUND_SCAN_PERIOD,
+ "Invalid background scan period. The range is 10 to 30 milliseconds"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_SCAN_CHANNEL,
+ "Invalid scan channel. Only valid channels are the NAN social channels"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP,
+ "Invalid post nan connectivity bitmap"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE,
+ "Invalid further availability map number of channel value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE,
+ "Invalid further availability map duration value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE,
+ "Invalid further availability map class value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE,
+ "Invalid further availability map channel value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE,
+ "Invalid further availability map availability interval bitmap value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID,
+ "Invalid further availability map map ID"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE,
+ "Invalid post nan discovery connection type value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE,
+ "Invalid post nan discovery device role value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE,
+ "Invalid post nan discovery duration value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE,
+ "Invalid post nan discovery bitmap value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_MISSING_FUTHER_AVAILABILITY_MAP,
+ "Missing further availability map"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_BAND_CONFIG_FLAGS,
+ "Invalid band configuration flags"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE,
+ "Invalid random factor update time value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_ONGOING_SCAN_PERIOD,
+ "Invalid ongoing scan period"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_DW_INTERVAL_VALUE,
+ "Invalid DW interval value"},
+ {NAN_STATUS_INVALID_PARAM, NAN_I_STATUS_INVALID_DB_INTERVAL_VALUE,
+ "Invalid DB interval value"},
+
+ {NAN_STATUS_SUCCESS, NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_TIMEOUT,
+ "Terminated Reason: Timeout"},
+ {NAN_STATUS_SUCCESS, NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_USER_REQUEST,
+ "Terminated Reason: User Request"},
+ {NAN_STATUS_SUCCESS, NAN_I_PUBLISH_SUBSCRIBE_TERMINATED_REASON_COUNT_REACHED,
+ "Terminated Reason: Count Reached"},
+
+ {NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID, NAN_I_STATUS_INVALID_REQUESTER_INSTANCE_ID,
+ "Invalid match handle"},
+ {NAN_STATUS_NAN_NOT_ALLOWED, NAN_I_STATUS_NAN_NOT_ALLOWED,
+ "Nan not allowed"},
+ {NAN_STATUS_NO_OTA_ACK, NAN_I_STATUS_NO_OTA_ACK,
+ "No OTA ack"},
+ {NAN_STATUS_ALREADY_ENABLED, NAN_I_STATUS_NAN_ALREADY_ENABLED,
+ "NAN is Already enabled"},
+ {NAN_STATUS_FOLLOWUP_QUEUE_FULL, NAN_I_STATUS_FOLLOWUP_QUEUE_FULL,
+ "Follow-up queue full"},
+
+ {NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED, NDP_I_UNSUPPORTED_CONCURRENCY,
+ "Unsupported Concurrency"},
+
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_NAN_DATA_IFACE_CREATE_FAILED,
+ "NAN data interface create failed"},
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_NAN_DATA_IFACE_DELETE_FAILED,
+ "NAN data interface delete failed"},
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_DATA_INITIATOR_REQUEST_FAILED,
+ "NAN data initiator request failed"},
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_DATA_RESPONDER_REQUEST_FAILED,
+ "NAN data responder request failed"},
+
+ {NAN_STATUS_INVALID_NDP_ID, NDP_I_INVALID_NDP_INSTANCE_ID,
+ "Invalid NDP instance ID"},
+
+ {NAN_STATUS_INVALID_PARAM, NDP_I_INVALID_RESPONSE_CODE,
+ "Invalid response code"},
+ {NAN_STATUS_INVALID_PARAM, NDP_I_INVALID_APP_INFO_LEN,
+ "Invalid app info length"},
+
+ {NAN_STATUS_PROTOCOL_FAILURE, NDP_I_MGMT_FRAME_REQUEST_FAILED,
+ "Management frame request failed"},
+ {NAN_STATUS_PROTOCOL_FAILURE, NDP_I_MGMT_FRAME_RESPONSE_FAILED,
+ "Management frame response failed"},
+ {NAN_STATUS_PROTOCOL_FAILURE, NDP_I_MGMT_FRAME_CONFIRM_FAILED,
+ "Management frame confirm failed"},
+
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_END_FAILED,
+ "NDP end failed"},
+
+ {NAN_STATUS_PROTOCOL_FAILURE, NDP_I_MGMT_FRAME_END_REQUEST_FAILED,
+ "Management frame end request failed"},
+
+ {NAN_STATUS_INTERNAL_FAILURE, NDP_I_VENDOR_SPECIFIC_ERROR,
+ "Vendor specific error"}
+};
+
+void NanCommand::NanErrorTranslation(NanInternalStatusType firmwareErrorRecvd,
+ u32 valueRcvd,
+ void* pResponse,
+ bool is_ndp_rsp)
+{
+ int i = 0, j = 0;
+ u16 msg_id; /* Based on the message_id in the header determine the Indication type */
+ NanResponseMsg *pRsp;
+ NanPublishTerminatedInd* pRspInd;
+ NanDisabledInd* pRspdInd;
+ char tlvInfo[NAN_ERROR_STR_LEN];
+ tlvInfo[0] = '\0';
+
+ if ((is_ndp_rsp == true) || isNanResponse()) {
+ pRsp = (NanResponseMsg*)pResponse;
+ for (i = 0; i < (int)(sizeof(errorCodeTranslation)/ sizeof(errorCode)); i++) {
+ if (errorCodeTranslation[i].firmwareError == firmwareErrorRecvd) {
+ pRsp->status = errorCodeTranslation[i].frameworkError;
+ strlcpy(pRsp->nan_error, errorCodeTranslation[i].nan_error, NAN_ERROR_STR_LEN);
+ if (NAN_I_STATUS_INVALID_TLV_TYPE == firmwareErrorRecvd) {
+ for (j = 0; j < (int)(sizeof(tlvToStr)/sizeof(verboseTlv)); j++) {
+ if (tlvToStr[j].tlvType == valueRcvd) {
+ strlcpy(tlvInfo, tlvToStr[i].strTlv, NAN_ERROR_STR_LEN);
+ break;
+ }
+ }
+ }
+ strlcat(pRsp->nan_error, tlvInfo, sizeof(pRsp->nan_error));
+ break;
+ }
+ }
+ if (i == (int)(sizeof(errorCodeTranslation)/sizeof(errorCode))) {
+ pRsp->status = NAN_STATUS_INTERNAL_FAILURE;
+ strlcpy(pRsp->nan_error, "NAN Discovery engine failure", NAN_ERROR_STR_LEN);
+ }
+ ALOGD("%s: Status: %d Error Info[value %d]: %s", __FUNCTION__, pRsp->status, valueRcvd, pRsp->nan_error);
+ } else {
+ msg_id = getIndicationType();
+
+ switch(msg_id) {
+ case NAN_INDICATION_PUBLISH_TERMINATED:
+ case NAN_INDICATION_SUBSCRIBE_TERMINATED:
+ case NAN_INDICATION_SELF_TRANSMIT_FOLLOWUP:
+ pRspInd = (NanPublishTerminatedInd*)pResponse;
+ for (i = 0; i < (int)(sizeof(errorCodeTranslation)/ sizeof(errorCode)); i++) {
+ if (errorCodeTranslation[i].firmwareError == firmwareErrorRecvd) {
+ pRspInd->reason = errorCodeTranslation[i].frameworkError;
+ strlcpy(pRspInd->nan_reason, errorCodeTranslation[i].nan_error, NAN_ERROR_STR_LEN);
+ break;
+ }
+ }
+ if (i == (int)(sizeof(errorCodeTranslation)/sizeof(errorCode))) {
+ pRspInd->reason = NAN_STATUS_INTERNAL_FAILURE;
+ strlcpy(pRspInd->nan_reason, "NAN Discovery engine failure", NAN_ERROR_STR_LEN);
+ }
+ ALOGD("%s: Status: %d Error Info[value %d]: %s", __FUNCTION__, pRspInd->reason, valueRcvd, pRspInd->nan_reason);
+ break;
+ case NAN_INDICATION_DISABLED:
+ pRspdInd = (NanDisabledInd*)pResponse;
+ for (i = 0; i < (int)(sizeof(errorCodeTranslation)/ sizeof(errorCode)); i++) {
+ if (errorCodeTranslation[i].firmwareError == firmwareErrorRecvd) {
+ pRspdInd->reason = errorCodeTranslation[i].frameworkError;
+ strlcpy(pRspdInd->nan_reason, errorCodeTranslation[i].nan_error, NAN_ERROR_STR_LEN);
+ break;
+ }
+ }
+ if (i == (int)(sizeof(errorCodeTranslation)/sizeof(errorCode))) {
+ pRspdInd->reason = NAN_STATUS_INTERNAL_FAILURE;
+ strlcpy(pRspdInd->nan_reason, "NAN Discovery engine failure", NAN_ERROR_STR_LEN);
+ }
+ ALOGD("%s: Status: %d Error Info[value %d]: %s", __FUNCTION__, pRspdInd->reason, valueRcvd, pRspdInd->nan_reason);
+ break;
+ }
+ }
+}
+
+int NanCommand::getNanResponse(transaction_id *id, NanResponseMsg *pRsp)
+{
+ if (mNanVendorEvent == NULL || pRsp == NULL) {
+ ALOGE("NULL check failed");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
+
+ switch (pHeader->msgId) {
+ case NAN_MSG_ID_ERROR_RSP:
+ {
+ pNanErrorRspMsg pFwRsp = \
+ (pNanErrorRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_ERROR;
+ break;
+ }
+ case NAN_MSG_ID_CONFIGURATION_RSP:
+ {
+ pNanConfigurationRspMsg pFwRsp = \
+ (pNanConfigurationRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_CONFIG;
+ }
+ break;
+ case NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_RSP:
+ {
+ pNanPublishServiceCancelRspMsg pFwRsp = \
+ (pNanPublishServiceCancelRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_PUBLISH_CANCEL;
+ pRsp->body.publish_response.publish_id = \
+ pFwRsp->fwHeader.handle;
+ break;
+ }
+ case NAN_MSG_ID_PUBLISH_SERVICE_RSP:
+ {
+ pNanPublishServiceRspMsg pFwRsp = \
+ (pNanPublishServiceRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_PUBLISH;
+ pRsp->body.publish_response.publish_id = \
+ pFwRsp->fwHeader.handle;
+ break;
+ }
+ case NAN_MSG_ID_SUBSCRIBE_SERVICE_RSP:
+ {
+ pNanSubscribeServiceRspMsg pFwRsp = \
+ (pNanSubscribeServiceRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_SUBSCRIBE;
+ pRsp->body.subscribe_response.subscribe_id = \
+ pFwRsp->fwHeader.handle;
+ }
+ break;
+ case NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_RSP:
+ {
+ pNanSubscribeServiceCancelRspMsg pFwRsp = \
+ (pNanSubscribeServiceCancelRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_SUBSCRIBE_CANCEL;
+ pRsp->body.subscribe_response.subscribe_id = \
+ pFwRsp->fwHeader.handle;
+ break;
+ }
+ case NAN_MSG_ID_TRANSMIT_FOLLOWUP_RSP:
+ {
+ pNanTransmitFollowupRspMsg pFwRsp = \
+ (pNanTransmitFollowupRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_TRANSMIT_FOLLOWUP;
+ break;
+ }
+ case NAN_MSG_ID_STATS_RSP:
+ {
+ pNanStatsRspMsg pFwRsp = \
+ (pNanStatsRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->statsRspParams.status,
+ pFwRsp->statsRspParams.value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_STATS;
+ pRsp->body.stats_response.stats_type = \
+ (NanStatsType)pFwRsp->statsRspParams.statsType;
+ ALOGV("%s: stats_type:%d",__func__,
+ pRsp->body.stats_response.stats_type);
+ u8 *pInputTlv = pFwRsp->ptlv;
+ NanTlv outputTlv;
+ memset(&outputTlv, 0, sizeof(outputTlv));
+ u16 readLen = 0;
+ int remainingLen = (mNanDataLen - \
+ (sizeof(NanMsgHeader) + sizeof(NanStatsRspParams)));
+ if (remainingLen > 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);
+ if (outputTlv.length <= \
+ sizeof(pRsp->body.stats_response.data)) {
+ handleNanStatsResponse(pRsp->body.stats_response.stats_type,
+ (char *)outputTlv.value,
+ &pRsp->body.stats_response,
+ outputTlv.length);
+ }
+ } else
+ ALOGV("%s: No TLV's present",__func__);
+ break;
+ }
+ case NAN_MSG_ID_ENABLE_RSP:
+ {
+ pNanEnableRspMsg pFwRsp = \
+ (pNanEnableRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_ENABLED;
+ break;
+ }
+ case NAN_MSG_ID_DISABLE_RSP:
+ {
+ pNanDisableRspMsg pFwRsp = \
+ (pNanDisableRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, 0, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_DISABLED;
+ break;
+ }
+ case NAN_MSG_ID_TCA_RSP:
+ {
+ pNanTcaRspMsg pFwRsp = \
+ (pNanTcaRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_TCA;
+ break;
+ }
+ case NAN_MSG_ID_BEACON_SDF_RSP:
+ {
+ pNanBeaconSdfPayloadRspMsg pFwRsp = \
+ (pNanBeaconSdfPayloadRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, 0, pRsp, false);
+ pRsp->response_type = NAN_RESPONSE_BEACON_SDF_PAYLOAD;
+ break;
+ }
+ case NAN_MSG_ID_CAPABILITIES_RSP:
+ {
+ pNanCapabilitiesRspMsg pFwRsp = \
+ (pNanCapabilitiesRspMsg)mNanVendorEvent;
+ *id = (transaction_id)pFwRsp->fwHeader.transactionId;
+ NanErrorTranslation((NanInternalStatusType)pFwRsp->status, pFwRsp->value, pRsp, false);
+ pRsp->response_type = NAN_GET_CAPABILITIES;
+ pRsp->body.nan_capabilities.max_concurrent_nan_clusters = \
+ pFwRsp->max_concurrent_nan_clusters;
+ pRsp->body.nan_capabilities.max_publishes = \
+ pFwRsp->max_publishes;
+ pRsp->body.nan_capabilities.max_subscribes = \
+ pFwRsp->max_subscribes;
+ pRsp->body.nan_capabilities.max_service_name_len = \
+ pFwRsp->max_service_name_len;
+ pRsp->body.nan_capabilities.max_match_filter_len = \
+ pFwRsp->max_match_filter_len;
+ pRsp->body.nan_capabilities.max_total_match_filter_len = \
+ pFwRsp->max_total_match_filter_len;
+ pRsp->body.nan_capabilities.max_service_specific_info_len = \
+ pFwRsp->max_service_specific_info_len;
+ pRsp->body.nan_capabilities.max_vsa_data_len = \
+ pFwRsp->max_vsa_data_len;
+ pRsp->body.nan_capabilities.max_mesh_data_len = \
+ pFwRsp->max_mesh_data_len;
+ pRsp->body.nan_capabilities.max_ndi_interfaces = \
+ pFwRsp->max_ndi_interfaces;
+ pRsp->body.nan_capabilities.max_ndp_sessions = \
+ pFwRsp->max_ndp_sessions;
+ pRsp->body.nan_capabilities.max_app_info_len = \
+ pFwRsp->max_app_info_len;
+ pRsp->body.nan_capabilities.max_queued_transmit_followup_msgs = \
+ pFwRsp->max_queued_transmit_followup_msgs;
+ pRsp->body.nan_capabilities.ndp_supported_bands = \
+ pFwRsp->ndp_supported_bands;
+ pRsp->body.nan_capabilities.cipher_suites_supported = \
+ pFwRsp->cipher_suites_supported;
+ pRsp->body.nan_capabilities.max_scid_len = \
+ pFwRsp->max_scid_len;
+ pRsp->body.nan_capabilities.is_ndp_security_supported = \
+ pFwRsp->is_ndp_security_supported;
+ pRsp->body.nan_capabilities.max_sdea_service_specific_info_len = \
+ pFwRsp->max_sdea_service_specific_info_len;
+ pRsp->body.nan_capabilities.max_subscribe_address = \
+ pFwRsp->max_subscribe_address;
+ if (pFwRsp->max_publishes > NAN_DEF_PUB_SUB) {
+ mNanCommandInstance->mNanMaxPublishes = pFwRsp->max_publishes;
+ mNanCommandInstance->reallocSvcParams(NAN_ROLE_PUBLISHER);
+ }
+ if (pFwRsp->max_subscribes > NAN_DEF_PUB_SUB) {
+ mNanCommandInstance->mNanMaxSubscribes = pFwRsp->max_subscribes;
+ mNanCommandInstance->reallocSvcParams(NAN_ROLE_SUBSCRIBER);
+ }
+
+ break;
+ }
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int NanCommand::handleNanResponse()
+{
+ //parse the data and call
+ //the response callback handler with the populated
+ //NanResponseMsg
+ NanResponseMsg rsp_data;
+ int ret;
+ transaction_id id;
+
+ ALOGV("handleNanResponse called %p", this);
+ memset(&rsp_data, 0, sizeof(rsp_data));
+ //get the rsp_data
+ ret = getNanResponse(&id, &rsp_data);
+
+ ALOGI("handleNanResponse ret:%d status:%u value:%s response_type:%u",
+ ret, rsp_data.status, rsp_data.nan_error, rsp_data.response_type);
+ if (ret == 0 && (rsp_data.response_type == NAN_RESPONSE_STATS) &&
+ (mStaParam != NULL) &&
+ (rsp_data.body.stats_response.stats_type == NAN_STATS_ID_DE_TIMING_SYNC)) {
+ /*
+ Fill the staParam with appropriate values and return from here.
+ No need to call NotifyResponse as the request is for getting the
+ STA response
+ */
+ NanSyncStats *pSyncStats = &rsp_data.body.stats_response.data.sync_stats;
+ mStaParam->master_rank = pSyncStats->myRank;
+ mStaParam->master_pref = (pSyncStats->myRank & 0xFF00000000000000) >> 56;
+ mStaParam->random_factor = (pSyncStats->myRank & 0x00FF000000000000) >> 48;
+ mStaParam->hop_count = pSyncStats->currAmHopCount;
+ mStaParam->beacon_transmit_time = pSyncStats->currAmBTT;
+ mStaParam->ndp_channel_freq = pSyncStats->ndpChannelFreq;
+
+ ALOGI("%s:0x%02x master_pref 0x%02x random_factor 0x%02x hop_count %u Channel",
+ __func__, mStaParam->master_pref, mStaParam->random_factor,
+ mStaParam->hop_count, mStaParam->ndp_channel_freq);
+
+ return ret;
+ }
+ //Call the NotifyResponse Handler
+ if (ret == 0 && mHandler.NotifyResponse) {
+ (*mHandler.NotifyResponse)(id, &rsp_data);
+ }
+ return ret;
+}
+
+void NanCommand::handleNanStatsResponse(NanStatsType stats_type,
+ char *rspBuf,
+ NanStatsResponse *pRsp,
+ u32 message_len)
+{
+ if (stats_type == NAN_STATS_ID_DE_PUBLISH) {
+ NanPublishStats publish_stats;
+ if (message_len != sizeof(NanPublishStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanPublishStats));
+ return;
+ }
+ FwNanPublishStats *pPubStats = (FwNanPublishStats *)rspBuf;
+
+ publish_stats.validPublishServiceReqMsgs =
+ pPubStats->validPublishServiceReqMsgs;
+ publish_stats.validPublishServiceRspMsgs =
+ pPubStats->validPublishServiceRspMsgs;
+ publish_stats.validPublishServiceCancelReqMsgs =
+ pPubStats->validPublishServiceCancelReqMsgs;
+ publish_stats.validPublishServiceCancelRspMsgs =
+ pPubStats->validPublishServiceCancelRspMsgs;
+ publish_stats.validPublishRepliedIndMsgs =
+ pPubStats->validPublishRepliedIndMsgs;
+ publish_stats.validPublishTerminatedIndMsgs =
+ pPubStats->validPublishTerminatedIndMsgs;
+ publish_stats.validActiveSubscribes = pPubStats->validActiveSubscribes;
+ publish_stats.validMatches = pPubStats->validMatches;
+ publish_stats.validFollowups = pPubStats->validFollowups;
+ publish_stats.invalidPublishServiceReqMsgs =
+ pPubStats->invalidPublishServiceReqMsgs;
+ publish_stats.invalidPublishServiceCancelReqMsgs =
+ pPubStats->invalidPublishServiceCancelReqMsgs;
+ publish_stats.invalidActiveSubscribes =
+ pPubStats->invalidActiveSubscribes;
+ publish_stats.invalidMatches = pPubStats->invalidMatches;
+ publish_stats.invalidFollowups = pPubStats->invalidFollowups;
+ publish_stats.publishCount = pPubStats->publishCount;
+ publish_stats.publishNewMatchCount = pPubStats->publishNewMatchCount;
+ publish_stats.pubsubGlobalNewMatchCount =
+ pPubStats->pubsubGlobalNewMatchCount;
+ memcpy(&pRsp->data.publish_stats, &publish_stats, sizeof(NanPublishStats));
+ } else if (stats_type == NAN_STATS_ID_DE_SUBSCRIBE) {
+ NanSubscribeStats sub_stats;
+ if (message_len != sizeof(NanSubscribeStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanSubscribeStats));
+ return;
+ }
+ FwNanSubscribeStats *pSubStats = (FwNanSubscribeStats *)rspBuf;
+
+ sub_stats.validSubscribeServiceReqMsgs =
+ pSubStats->validSubscribeServiceReqMsgs;
+ sub_stats.validSubscribeServiceRspMsgs =
+ pSubStats->validSubscribeServiceRspMsgs;
+ sub_stats.validSubscribeServiceCancelReqMsgs =
+ pSubStats->validSubscribeServiceCancelReqMsgs;
+ sub_stats.validSubscribeServiceCancelRspMsgs =
+ pSubStats->validSubscribeServiceCancelRspMsgs;
+ sub_stats.validSubscribeTerminatedIndMsgs =
+ pSubStats->validSubscribeTerminatedIndMsgs;
+ sub_stats.validSubscribeMatchIndMsgs =
+ pSubStats->validSubscribeMatchIndMsgs;
+ sub_stats.validSubscribeUnmatchIndMsgs =
+ pSubStats->validSubscribeUnmatchIndMsgs;
+ sub_stats.validSolicitedPublishes =
+ pSubStats->validSolicitedPublishes;
+ sub_stats.validMatches = pSubStats->validMatches;
+ sub_stats.validFollowups = pSubStats->validFollowups;
+ sub_stats.invalidSubscribeServiceReqMsgs =
+ pSubStats->invalidSubscribeServiceReqMsgs;
+ sub_stats.invalidSubscribeServiceCancelReqMsgs =
+ pSubStats->invalidSubscribeServiceCancelReqMsgs;
+ sub_stats.invalidSubscribeFollowupReqMsgs =
+ pSubStats->invalidSubscribeFollowupReqMsgs;
+ sub_stats.invalidSolicitedPublishes =
+ pSubStats->invalidSolicitedPublishes;
+ sub_stats.invalidMatches = pSubStats->invalidMatches;
+ sub_stats.invalidFollowups = pSubStats->invalidFollowups;
+ sub_stats.subscribeCount = pSubStats->subscribeCount;
+ sub_stats.bloomFilterIndex = pSubStats->bloomFilterIndex;
+ sub_stats.subscribeNewMatchCount = pSubStats->subscribeNewMatchCount;
+ sub_stats.pubsubGlobalNewMatchCount =
+ pSubStats->pubsubGlobalNewMatchCount;
+ memcpy(&pRsp->data.subscribe_stats, &sub_stats, sizeof(NanSubscribeStats));
+ } else if (stats_type == NAN_STATS_ID_DE_DW) {
+ NanDWStats dw_stats;
+ if (message_len != sizeof(NanDWStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanDWStats));
+ return;
+ }
+ FwNanMacStats *pMacStats = (FwNanMacStats *)rspBuf;
+
+ dw_stats.validFrames = pMacStats->validFrames;
+ dw_stats.validActionFrames = pMacStats->validActionFrames;
+ dw_stats.validBeaconFrames = pMacStats->validBeaconFrames;
+ dw_stats.ignoredActionFrames = pMacStats->ignoredActionFrames;
+ dw_stats.ignoredBeaconFrames = pMacStats->ignoredBeaconFrames;
+ dw_stats.invalidFrames = pMacStats->invalidFrames;
+ dw_stats.invalidActionFrames = pMacStats->invalidActionFrames;
+ dw_stats.invalidBeaconFrames = pMacStats->invalidBeaconFrames;
+ dw_stats.invalidMacHeaders = pMacStats->invalidMacHeaders;
+ dw_stats.invalidPafHeaders = pMacStats->invalidPafHeaders;
+ dw_stats.nonNanBeaconFrames = pMacStats->nonNanBeaconFrames;
+ dw_stats.earlyActionFrames = pMacStats->earlyActionFrames;
+ dw_stats.inDwActionFrames = pMacStats->inDwActionFrames;
+ dw_stats.lateActionFrames = pMacStats->lateActionFrames;
+ dw_stats.framesQueued = pMacStats->framesQueued;
+ dw_stats.totalTRSpUpdates = pMacStats->totalTRSpUpdates;
+ dw_stats.completeByTRSp = pMacStats->completeByTRSp;
+ dw_stats.completeByTp75DW = pMacStats->completeByTp75DW;
+ dw_stats.completeByTendDW = pMacStats->completeByTendDW;
+ dw_stats.lateActionFramesTx = pMacStats->lateActionFramesTx;
+ memcpy(&pRsp->data.dw_stats, &dw_stats, sizeof(NanDWStats));
+ } else if (stats_type == NAN_STATS_ID_DE_MAC) {
+ NanMacStats mac_stats;
+ if (message_len != sizeof(NanMacStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanMacStats));
+ return;
+ }
+ FwNanMacStats *pMacStats = (FwNanMacStats *)rspBuf;
+
+ mac_stats.validFrames = pMacStats->validFrames;
+ mac_stats.validActionFrames = pMacStats->validActionFrames;
+ mac_stats.validBeaconFrames = pMacStats->validBeaconFrames;
+ mac_stats.ignoredActionFrames = pMacStats->ignoredActionFrames;
+ mac_stats.ignoredBeaconFrames = pMacStats->ignoredBeaconFrames;
+ mac_stats.invalidFrames = pMacStats->invalidFrames;
+ mac_stats.invalidActionFrames = pMacStats->invalidActionFrames;
+ mac_stats.invalidBeaconFrames = pMacStats->invalidBeaconFrames;
+ mac_stats.invalidMacHeaders = pMacStats->invalidMacHeaders;
+ mac_stats.invalidPafHeaders = pMacStats->invalidPafHeaders;
+ mac_stats.nonNanBeaconFrames = pMacStats->nonNanBeaconFrames;
+ mac_stats.earlyActionFrames = pMacStats->earlyActionFrames;
+ mac_stats.inDwActionFrames = pMacStats->inDwActionFrames;
+ mac_stats.lateActionFrames = pMacStats->lateActionFrames;
+ mac_stats.framesQueued = pMacStats->framesQueued;
+ mac_stats.totalTRSpUpdates = pMacStats->totalTRSpUpdates;
+ mac_stats.completeByTRSp = pMacStats->completeByTRSp;
+ mac_stats.completeByTp75DW = pMacStats->completeByTp75DW;
+ mac_stats.completeByTendDW = pMacStats->completeByTendDW;
+ mac_stats.lateActionFramesTx = pMacStats->lateActionFramesTx;
+ mac_stats.twIncreases = pMacStats->twIncreases;
+ mac_stats.twDecreases = pMacStats->twDecreases;
+ mac_stats.twChanges = pMacStats->twChanges;
+ mac_stats.twHighwater = pMacStats->twHighwater;
+ mac_stats.bloomFilterIndex = pMacStats->bloomFilterIndex;
+ memcpy(&pRsp->data.mac_stats, &mac_stats, sizeof(NanMacStats));
+ } else if (stats_type == NAN_STATS_ID_DE_TIMING_SYNC) {
+ NanSyncStats sync_stats;
+ if (message_len != sizeof(NanSyncStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanSyncStats));
+ return;
+ }
+ FwNanSyncStats *pSyncStats = (FwNanSyncStats *)rspBuf;
+
+ sync_stats.currTsf = pSyncStats->currTsf;
+ sync_stats.myRank = pSyncStats->myRank;
+ sync_stats.currAmRank = pSyncStats->currAmRank;
+ sync_stats.lastAmRank = pSyncStats->lastAmRank;
+ sync_stats.currAmBTT = pSyncStats->currAmBTT;
+ sync_stats.lastAmBTT = pSyncStats->lastAmBTT;
+ sync_stats.currAmHopCount = pSyncStats->currAmHopCount;
+ sync_stats.currRole = pSyncStats->currRole;
+ sync_stats.currClusterId = pSyncStats->currClusterId;
+
+ sync_stats.timeSpentInCurrRole = pSyncStats->timeSpentInCurrRole;
+ sync_stats.totalTimeSpentAsMaster = pSyncStats->totalTimeSpentAsMaster;
+ sync_stats.totalTimeSpentAsNonMasterSync =
+ pSyncStats->totalTimeSpentAsNonMasterSync;
+ sync_stats.totalTimeSpentAsNonMasterNonSync =
+ pSyncStats->totalTimeSpentAsNonMasterNonSync;
+ sync_stats.transitionsToAnchorMaster =
+ pSyncStats->transitionsToAnchorMaster;
+ sync_stats.transitionsToMaster =
+ pSyncStats->transitionsToMaster;
+ sync_stats.transitionsToNonMasterSync =
+ pSyncStats->transitionsToNonMasterSync;
+ sync_stats.transitionsToNonMasterNonSync =
+ pSyncStats->transitionsToNonMasterNonSync;
+ sync_stats.amrUpdateCount = pSyncStats->amrUpdateCount;
+ sync_stats.amrUpdateRankChangedCount =
+ pSyncStats->amrUpdateRankChangedCount;
+ sync_stats.amrUpdateBTTChangedCount =
+ pSyncStats->amrUpdateBTTChangedCount;
+ sync_stats.amrUpdateHcChangedCount =
+ pSyncStats->amrUpdateHcChangedCount;
+ sync_stats.amrUpdateNewDeviceCount =
+ pSyncStats->amrUpdateNewDeviceCount;
+ sync_stats.amrExpireCount = pSyncStats->amrExpireCount;
+ sync_stats.mergeCount = pSyncStats->mergeCount;
+ sync_stats.beaconsAboveHcLimit = pSyncStats->beaconsAboveHcLimit;
+ sync_stats.beaconsBelowRssiThresh = pSyncStats->beaconsBelowRssiThresh;
+ sync_stats.beaconsIgnoredNoSpace = pSyncStats->beaconsIgnoredNoSpace;
+ sync_stats.beaconsForOurCluster = pSyncStats->beaconsForOtherCluster;
+ sync_stats.beaconsForOtherCluster = pSyncStats->beaconsForOtherCluster;
+ sync_stats.beaconCancelRequests = pSyncStats->beaconCancelRequests;
+ sync_stats.beaconCancelFailures = pSyncStats->beaconCancelFailures;
+ sync_stats.beaconUpdateRequests = pSyncStats->beaconUpdateRequests;
+ sync_stats.beaconUpdateFailures = pSyncStats->beaconUpdateFailures;
+ sync_stats.syncBeaconTxAttempts = pSyncStats->syncBeaconTxAttempts;
+ sync_stats.syncBeaconTxFailures = pSyncStats->syncBeaconTxFailures;
+ sync_stats.discBeaconTxAttempts = pSyncStats->discBeaconTxAttempts;
+ sync_stats.discBeaconTxFailures = pSyncStats->discBeaconTxFailures;
+ sync_stats.amHopCountExpireCount = pSyncStats->amHopCountExpireCount;
+ sync_stats.ndpChannelFreq = pSyncStats->ndpChannelFreq;
+ sync_stats.ndpChannelFreq2 = pSyncStats->ndpChannelFreq2;
+ sync_stats.schedUpdateChannelFreq = pSyncStats->schedUpdateChannelFreq;
+ memcpy(&pRsp->data.sync_stats, &sync_stats, sizeof(NanSyncStats));
+ } else if (stats_type == NAN_STATS_ID_DE) {
+ NanDeStats de_stats;
+ if (message_len != sizeof(NanDeStats)) {
+ ALOGE("%s: stats_type = %d invalid stats length = %u expected length = %zu\n",
+ __func__, stats_type, message_len, sizeof(NanDeStats));
+ return;
+ }
+ FwNanDeStats *pDeStats = (FwNanDeStats *)rspBuf;
+
+ de_stats.validErrorRspMsgs = pDeStats->validErrorRspMsgs;
+ de_stats.validTransmitFollowupReqMsgs =
+ pDeStats->validTransmitFollowupReqMsgs;
+ de_stats.validTransmitFollowupRspMsgs =
+ pDeStats->validTransmitFollowupRspMsgs;
+ de_stats.validFollowupIndMsgs =
+ pDeStats->validFollowupIndMsgs;
+ de_stats.validConfigurationReqMsgs =
+ pDeStats->validConfigurationReqMsgs;
+ de_stats.validConfigurationRspMsgs =
+ pDeStats->validConfigurationRspMsgs;
+ de_stats.validStatsReqMsgs = pDeStats->validStatsReqMsgs;
+ de_stats.validStatsRspMsgs = pDeStats->validStatsRspMsgs;
+ de_stats.validEnableReqMsgs = pDeStats->validEnableReqMsgs;
+ de_stats.validEnableRspMsgs = pDeStats->validEnableRspMsgs;
+ de_stats.validDisableReqMsgs = pDeStats->validDisableReqMsgs;
+ de_stats.validDisableRspMsgs = pDeStats->validDisableRspMsgs;
+ de_stats.validDisableIndMsgs = pDeStats->validDisableIndMsgs;
+ de_stats.validEventIndMsgs = pDeStats->validEventIndMsgs;
+ de_stats.validTcaReqMsgs = pDeStats->validTcaReqMsgs;
+ de_stats.validTcaRspMsgs = pDeStats->validTcaRspMsgs;
+ de_stats.validTcaIndMsgs = pDeStats->validTcaIndMsgs;
+ de_stats.invalidTransmitFollowupReqMsgs =
+ pDeStats->invalidTransmitFollowupReqMsgs;
+ de_stats.invalidConfigurationReqMsgs =
+ pDeStats->invalidConfigurationReqMsgs;
+ de_stats.invalidStatsReqMsgs = pDeStats->invalidStatsReqMsgs;
+ de_stats.invalidEnableReqMsgs = pDeStats->invalidEnableReqMsgs;
+ de_stats.invalidDisableReqMsgs = pDeStats->invalidDisableReqMsgs;
+ de_stats.invalidTcaReqMsgs = pDeStats->invalidTcaReqMsgs;
+ memcpy(&pRsp->data.de_stats, &de_stats, sizeof(NanDeStats));
+ } else {
+ ALOGE("Unknown stats_type:%d\n", stats_type);
+ }
+}
+
+int NanCommand::handleNdpResponse(NanResponseType ndpCmdType,
+ struct nlattr **tb_vendor)
+{
+ //parse the data and call
+ //the response callback handler with the populated
+ //NanResponseMsg
+ NanResponseMsg rsp_data;
+ transaction_id id;
+
+ memset(&rsp_data, 0, sizeof(rsp_data));
+
+ if ((!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE]) ||
+ (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE]))
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ id = nla_get_u16(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
+ ALOGD("%s: Transaction id : val %d", __FUNCTION__, id);
+
+ NanErrorTranslation((NanInternalStatusType)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE]),
+ nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE]), &rsp_data, true);
+ rsp_data.response_type = ndpCmdType;
+
+ if (ndpCmdType == NAN_DP_INITIATOR_RESPONSE)
+ {
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_NDP not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rsp_data.body.data_request_response.ndp_instance_id =
+ nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]);
+ }
+ //Call the NotifyResponse Handler
+ if (mHandler.NotifyResponse) {
+ (*mHandler.NotifyResponse)(id, &rsp_data);
+ }
+ return WIFI_SUCCESS;
+}
diff --git a/wcn6740/qcwcn/wifi_hal/nancommand.h b/wcn6740/qcwcn/wifi_hal/nancommand.h
new file mode 100644
index 0000000..ac2a64b
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nancommand.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 __WIFI_HAL_NAN_COMMAND_H__
+#define __WIFI_HAL_NAN_COMMAND_H__
+
+#include "common.h"
+#include "cpp_bindings.h"
+#include "wifi_hal.h"
+#include "nan_cert.h"
+
+/*
+ * NAN Salt is a concatenation of salt_version, CSID, Service ID, PeerMac
+ * resulting in a total length of 14 bytes
+ */
+#define NAN_SECURITY_SALT_SIZE 14
+/* In Service ID calculation SHA-256 hash size is of max. 64 bytes */
+#define NAN_SVC_HASH_SIZE 64
+/* Service ID is the first 48 bits of the SHA-256 hash of the Service Name */
+#define NAN_SVC_ID_SIZE 6
+/* Default Service name length is 21 bytes */
+#define NAN_DEF_SVC_NAME_LEN 21
+/* As per NAN spec, 4096 iterations to be used for PMK calculation */
+#define NAN_PMK_ITERATIONS 4096
+/* Keep NCS-SK-128 Cipher Suite as default i.e. HMAC-SHA-256 algorithm */
+#define NAN_DEFAULT_NCS_SK NAN_CIPHER_SUITE_SHARED_KEY_128_MASK
+/* Currently by default max 6 Publishes/Subscribes are allowed */
+#define NAN_DEF_PUB_SUB 6
+/*
+ * First bit of discovery_indication_cfg in NanEnableRequest indicates
+ * disableDiscoveryAddressChangeIndication
+ */
+#define NAN_DISC_ADDR_IND_DISABLED 0x01
+
+typedef struct PACKED
+{
+ u32 instance_id;
+ u16 subscriber_publisher_id;
+ u8 service_id[NAN_SVC_ID_SIZE];
+} NanStoreSvcParams;
+
+typedef enum
+{
+ NAN_ROLE_NONE,
+ NAN_ROLE_PUBLISHER,
+ NAN_ROLE_SUBSCRIBER
+} NanRole;
+
+class NanCommand : public WifiVendorCommand
+{
+private:
+ NanCallbackHandler mHandler;
+ char *mNanVendorEvent;
+ u32 mNanDataLen;
+ NanStaParameter *mStaParam;
+ u8 mNmiMac[NAN_MAC_ADDR_LEN];
+ u32 mNanMaxPublishes;
+ u32 mNanMaxSubscribes;
+ NanStoreSvcParams *mStorePubParams;
+ NanStoreSvcParams *mStoreSubParams;
+ bool mNanDiscAddrIndDisabled;
+
+ //Function to check the initial few bytes of data to
+ //determine whether NanResponse or NanEvent
+ int isNanResponse();
+ //Function which unparses the data and calls the NotifyResponse
+ int handleNanResponse();
+ //Function which will parse the mVendorData and gets
+ // the rsp_data appropriately.
+ int getNanResponse(transaction_id *id, NanResponseMsg *pRsp);
+ //Function which will return the Nan Indication type based on
+ //the initial few bytes of mVendorData
+ NanIndicationType getIndicationType();
+ //Function which calls the necessaryIndication callback
+ //based on the indication type
+ int handleNanIndication();
+ //Various Functions to get the appropriate indications
+ int getNanPublishReplied(NanPublishRepliedInd *event);
+ int getNanPublishTerminated(NanPublishTerminatedInd *event);
+ int getNanMatch(NanMatchInd *event);
+ int getNanMatchExpired(NanMatchExpiredInd *event);
+ int getNanSubscribeTerminated(NanSubscribeTerminatedInd *event);
+ int getNanFollowup(NanFollowupInd *event);
+ int getNanDiscEngEvent(NanDiscEngEventInd *event);
+ int getNanDisabled(NanDisabledInd *event);
+ int getNanTca(NanTCAInd *event);
+ int getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event);
+ //Internal cleanup function
+ void cleanup();
+
+ static NanCommand *mNanCommandInstance;
+
+ // Other private helper functions
+ int calcNanTransmitPostDiscoverySize(
+ const NanTransmitPostDiscovery *pPostDiscovery);
+ void fillNanSocialChannelParamVal(
+ const NanSocialChannelScanParams *pScanParams,
+ u32* pChannelParamArr);
+ u32 getNanTransmitPostConnectivityCapabilityVal(
+ const NanTransmitPostConnectivityCapability *pCapab);
+ void fillNanTransmitPostDiscoveryVal(
+ const NanTransmitPostDiscovery *pTxDisc,
+ u8 *pOutValue);
+ int calcNanFurtherAvailabilityMapSize(
+ const NanFurtherAvailabilityMap *pFam);
+ void fillNanFurtherAvailabilityMapVal(
+ const NanFurtherAvailabilityMap *pFam,
+ u8 *pOutValue);
+
+ void getNanReceivePostConnectivityCapabilityVal(
+ const u8* pInValue,
+ NanReceivePostConnectivityCapability *pRxCapab);
+ void getNanReceiveSdeaCtrlParams(const u8* pInValue,
+ NanSdeaCtrlParams *pPeerSdeaParams);
+ int getNanReceivePostDiscoveryVal(const u8 *pInValue,
+ u32 length,
+ NanReceivePostDiscovery *pRxDisc);
+ int getNanFurtherAvailabilityMap(const u8 *pInValue,
+ u32 length,
+ u8* num_chans,
+ NanFurtherAvailabilityChannel *pFac);
+ void handleNanStatsResponse(NanStatsType stats_type,
+ char* rspBuf,
+ NanStatsResponse *pRsp,
+ u32 message_len);
+
+ //Function which unparses the data and calls the NotifyResponse
+ int handleNdpResponse(NanResponseType ndpCmdtyp, struct nlattr **tb_vendor);
+ int handleNdpIndication(u32 ndpCmdType, struct nlattr **tb_vendor);
+ int getNdpRequest(struct nlattr **tb_vendor, NanDataPathRequestInd *event);
+ int getNdpConfirm(struct nlattr **tb_vendor, NanDataPathConfirmInd *event);
+ int getNdpEnd(struct nlattr **tb_vendor, NanDataPathEndInd *event);
+ int getNanTransmitFollowupInd(NanTransmitFollowupInd *event);
+ int getNanRangeRequestReceivedInd(NanRangeRequestInd *event);
+ int getNanRangeReportInd(NanRangeReportInd *event);
+ int getNdpScheduleUpdate(struct nlattr **tb_vendor, NanDataPathScheduleUpdateInd *event);
+public:
+ NanCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+ static NanCommand* instance(wifi_handle handle);
+ virtual ~NanCommand();
+
+ // This function implements creation of NAN specific Request
+ // based on the request type
+ virtual wifi_error create();
+ virtual wifi_error requestEvent();
+ virtual int handleResponse(WifiEvent &reply);
+ virtual int handleEvent(WifiEvent &event);
+ wifi_error setCallbackHandler(NanCallbackHandler nHandler);
+
+
+ //Functions to fill the vendor data appropriately
+ wifi_error putNanEnable(transaction_id id, const NanEnableRequest *pReq);
+ wifi_error putNanDisable(transaction_id id);
+ wifi_error putNanPublish(transaction_id id, const NanPublishRequest *pReq);
+ wifi_error putNanPublishCancel(transaction_id id, const NanPublishCancelRequest *pReq);
+ wifi_error putNanSubscribe(transaction_id id, const NanSubscribeRequest *pReq);
+ wifi_error putNanSubscribeCancel(transaction_id id, const NanSubscribeCancelRequest *pReq);
+ wifi_error putNanTransmitFollowup(transaction_id id, const NanTransmitFollowupRequest *pReq);
+ wifi_error putNanStats(transaction_id id, const NanStatsRequest *pReq);
+ wifi_error putNanConfig(transaction_id id, const NanConfigRequest *pReq);
+ wifi_error putNanTCA(transaction_id id, const NanTCARequest *pReq);
+ wifi_error putNanBeaconSdfPayload(transaction_id id, const NanBeaconSdfPayloadRequest *pReq);
+ wifi_error getNanStaParameter(wifi_interface_handle iface, NanStaParameter *pRsp);
+ wifi_error putNanCapabilities(transaction_id id);
+ wifi_error putNanDebugCommand(NanDebugParams debug, int debug_msg_length);
+
+ /* Functions for NAN error translation
+ For NanResponse, NanPublishTerminatedInd, NanSubscribeTerminatedInd,
+ NanDisabledInd, NanTransmitFollowupInd:
+ function to translate firmware specific errors
+ to generic freamework error along with the error string
+ */
+ void NanErrorTranslation(NanInternalStatusType firmwareErrorRecvd,
+ u32 valueRcvd,
+ void *pRsp,
+ bool is_ndp_rsp);
+
+ /* Functions for NAN passphrase to PMK calculation */
+ void saveNmi(u8 *mac);
+ u8 *getNmi();
+ void saveServiceId(u8 *service_id, u16 sub_pub_handle,
+ u32 instance_id, NanRole Pool);
+ u8 *getServiceId(u32 instance_id, NanRole Pool);
+ void deleteServiceId(u16 sub_handle, u32 instance_id, NanRole pool);
+ void allocSvcParams();
+ void reallocSvcParams(NanRole pool);
+ void deallocSvcParams();
+};
+#endif /* __WIFI_HAL_NAN_COMMAND_H__ */
+
diff --git a/wcn6740/qcwcn/wifi_hal/nud_stats.h b/wcn6740/qcwcn/wifi_hal/nud_stats.h
new file mode 100644
index 0000000..c88b3a9
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/nud_stats.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017-2018, 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.
+ */
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include "wifi_hal.h"
+#include <bits/in_addr.h>
+
+#define INET6_ADDRSTRLEN 46
+
+extern "C" {
+ const char* inet_ntop(int __af, const void* __src, char* __dst, socklen_t __size);
+}
+
+typedef struct {
+ uint16_t arp_req_count_from_netdev;
+ uint16_t arp_req_count_to_lower_mac;
+ uint16_t arp_req_rx_count_by_lower_mac;
+ uint16_t arp_req_count_tx_success;
+ uint16_t arp_rsp_rx_count_by_lower_mac;
+ uint16_t arp_rsp_rx_count_by_upper_mac;
+ uint16_t arp_rsp_count_to_netdev;
+ uint16_t arp_rsp_count_out_of_order_drop;
+ uint8_t ap_link_active;
+ uint8_t is_duplicate_addr_detection;
+} nud_stats;
+
+typedef struct {
+ uint16_t pkt_req_count_from_netdev;
+ uint16_t pkt_req_count_to_lower_mac;
+ uint16_t pkt_req_rx_count_by_lower_mac;
+ uint16_t pkt_req_count_tx_success;
+ uint16_t pkt_rsp_rx_count_by_lower_mac;
+ uint16_t pkt_rsp_rx_count_by_upper_mac;
+ uint16_t pkt_rsp_count_to_netdev;
+ uint16_t pkt_rsp_count_out_of_order_drop;
+} pkt_stats;
+
+typedef struct{
+ u32 pkt_Type;
+ char* domain_name;
+ u32 src_port;
+ u32 dst_port;
+ struct in_addr ipv4_addr;
+ u8 ipv6_addr[16];
+ pkt_stats stats;
+} cmdData;
+
+/* callback for get NUD stats */
+typedef struct {
+ void (*on_pkt_stats_results) (nud_stats *stats,
+ int mnumStats, cmdData *pkt_stats);
+} pkt_stats_result_handler;
+
+wifi_error wifi_set_nud_stats(wifi_interface_handle iface, u32 gw_addr,
+ cmdData set_data);
+wifi_error wifi_get_nud_stats(wifi_interface_handle iface,
+ pkt_stats_result_handler handler);
+wifi_error wifi_clear_nud_stats(wifi_interface_handle iface,
+ cmdData set_data);
diff --git a/wcn6740/qcwcn/wifi_hal/pkt_stats.h b/wcn6740/qcwcn/wifi_hal/pkt_stats.h
new file mode 100644
index 0000000..e01da3b
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/pkt_stats.h
@@ -0,0 +1,674 @@
+/* Copyright (c) 2015, 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 _PKT_STATS_H_
+#define _PKT_STATS_H_
+
+/* Types of packet log events.
+ * Tx stats will be sent from driver with the help of multiple events.
+ * Need to parse the events PKTLOG_TYPE_TX_CTRL and PKTLOG_TYPE_TX_STAT
+ * as of now for the required stats. Rest of the events can ignored.
+ */
+#define PKTLOG_TYPE_TX_CTRL 1
+#define PKTLOG_TYPE_TX_STAT 2
+#define PKTLOG_TYPE_TX_MSDU_ID 3
+#define PKTLOG_TYPE_TX_FRM_HDR 4
+/* Rx stats will be sent from driver with event ID- PKTLOG_TYPE_RX_STAT */
+#define PKTLOG_TYPE_RX_STAT 5
+#define PKTLOG_TYPE_RC_FIND 6
+#define PKTLOG_TYPE_RC_UPDATE 7
+#define PKTLOG_TYPE_TX_VIRT_ADDR 8
+#define PKTLOG_TYPE_PKT_STATS 9
+#define PKTLOG_TYPE_PKT_DUMP 10
+#define PKTLOG_TYPE_PKT_DUMP_V2 11
+#define PKTLOG_TYPE_MAX 12
+#define BW_OFFSET 8
+#define INVALID_RSSI 255
+#define INVALID_RATE_CODE 0xff
+
+/* Based on pkt log V2, this type of event will triggered */
+#define PKTLOG_TYPE_PKT_SW_EVENT 10
+#define PKTLOG_TYPE_RX_STATBUF 22 //Full Rx pktlog stats
+#define PKTLOG_TYPE_LITE_T2H 23 //PPDU Level Tx pktlog stats
+#define PKTLOG_TYPE_LITE_RX 24 //PPDU Level Rx pktlog stats
+
+
+#define PKT_INFO_FLG_TX_LOCAL_S 0x1
+#define PKT_INFO_FLG_RX_HOST_RXD 0x2
+#define PKT_INFO_FLG_TX_REMOTE_S 0x4
+#define PKT_INFO_FLG_RX_LOCAL_S 0x8
+#define PKT_INFO_FLG_RX_REMOTE_S 0x10
+#define PKT_INFO_FLG_RX_LOCAL_DISCARD_S 0x20
+#define PKT_INFO_FLG_RX_REMOTE_DISCARD_S 0x40
+#define PKT_INFO_FLG_RX_REORDER_STORE_S 0x80
+#define PKT_INFO_FLG_RX_REORDER_DROP_S 0x100
+#define PKT_INFO_FLG_RX_PEER_INFO_S 0x200
+#define PKT_INFO_FLG_UNKNOWN_S 0x400
+#define PKT_INFO_FLG_PKT_DUMP_V2 0x8000
+
+/* Depend on packet log version V2 this
+ * offset are define, for more info need to
+ * check from firmware side.
+ */
+#define TX_SUCCESS_TMS_OFFSET 56
+#define LINK_LAYER_TX_SQN_OFFSET 66
+#define RATE_CODE_OFFSET 68
+#define TX_STATUS_OFFSET 70
+#define TX_RSSI_OFFSET 71
+#define NO_RETRIES_OFFSET 75
+#define EXT_FLAGS_OFFSET 76
+#define BMAP_FAILED_OFFSET 84
+#define BMAP_ENQUEUED_OFFSET 92
+#define FRAME_CTRL_OFFSET 216
+#define QOS_CTRL_OFFSET 218
+
+/* MAX HT/VHT mcs index */
+#define MAX_VHT_MCS_IDX 10
+#define MAX_HT_MCS_IDX 8
+
+/* MAX CCK/OFDM rate index */
+#define MAX_CCK_MCS_IDX 4
+#define MAX_OFDM_MCS_IDX 8
+
+/* MASK value of flags based on RX_STAT content.
+ * These are the events that carry Rx decriptor
+ */
+#define PKT_INFO_FLG_RX_RXDESC_MASK \
+ (PKT_INFO_FLG_RX_HOST_RXD | \
+ PKT_INFO_FLG_RX_LOCAL_S | \
+ PKT_INFO_FLG_RX_REMOTE_S | \
+ PKT_INFO_FLG_RX_LOCAL_DISCARD_S | \
+ PKT_INFO_FLG_RX_REMOTE_DISCARD_S)
+
+/* Format of the packet stats event*/
+typedef struct {
+ u16 flags;
+ u16 missed_cnt;
+ u16 log_type;
+ u16 size;
+ u32 timestamp;
+} __attribute__((packed)) wh_pktlog_hdr_t;
+
+/* Format of the v2 packet stats event*/
+typedef struct {
+ u16 flags;
+ u16 missed_cnt;
+ u16 log_type : 8; //[7:0]
+ u16 mac_id : 8; //[15:8]
+ u16 size;
+ u32 timestamp;
+ u32 reserved;
+} __attribute__((packed)) wh_pktlog_hdr_v2_t;
+
+/*Rx stats specific structures. */
+struct rx_attention {
+ u32 first_mpdu : 1; //[0]
+ u32 last_mpdu : 1; //[1]
+ u32 reserved1 : 6; //[7:2]
+ u32 mgmt_type : 1; //[8]
+ u32 ctrl_type : 1; //[9]
+ u32 reserved2 : 6; //[15:10]
+ u32 overflow_err : 1; //[16]
+ u32 msdu_length_err : 1; //[17]
+ u32 tcp_udp_chksum_fail : 1; //[18]
+ u32 ip_chksum_fail : 1; //[19]
+ u32 reserved3 : 7; //[26:20]
+ u32 mpdu_length_err : 1; //[27]
+ u32 tkip_mic_err : 1; //[28]
+ u32 decrypt_err : 1; //[29]
+ u32 fcs_err : 1; //[30]
+ u32 msdu_done : 1; //[31]
+} __attribute__((packed));
+
+struct rx_mpdu_start {
+ u32 reserved1 : 13; //[12:0]
+ u32 encrypted : 1; //[13]
+ u32 retry : 1; //[14]
+ u32 reserved2 : 1; //[15]
+ u32 seq_num : 12; //[27:16]
+ u32 reserved3 : 4; //[31:28]
+ u32 reserved4;
+ u32 reserved5 : 28; //[27:0]
+ u32 tid : 4; //[31:28]
+} __attribute__((packed));
+
+/*Indicates the decap-format of the packet*/
+enum {
+ RAW=0, // RAW: No decapsulation
+ NATIVEWIFI,
+ ETHERNET2, // (DIX)
+ ETHERNET // (SNAP/LLC)
+};
+
+struct rx_msdu_start {
+ u32 reserved1[2];
+ u32 reserved2 : 8; //[7:0]
+ u32 decap_format : 2; //[9:8]
+ u32 reserved3 : 22; //[31:10]
+} __attribute__((packed));
+
+struct rx_msdu_end {
+ u32 reserved1[4];
+ u32 reserved2 : 15;
+ u32 last_msdu : 1; //[15]
+ u32 reserved3 : 16; //[31:16]
+} __attribute__((packed));
+
+struct rx_mpdu_end {
+ u32 reserved1 : 13; //[12:0]
+ u32 overflow_err : 1; //[13]
+ u32 last_mpdu : 1; //[14]
+ u32 post_delim_err : 1; //[15]
+ u32 reserved2 : 12; //[27:16]
+ u32 mpdu_length_err : 1; //[28]
+ u32 tkip_mic_err : 1; //[29]
+ u32 decrypt_err : 1; //[30]
+ u32 fcs_err : 1; //[31]
+} __attribute__((packed));
+
+/* structure implemented w.r.t PKT_LOG_V2 Version */
+struct rx_msdu_start_v1 {
+ u32 reserved1[2];
+ u32 reserved2 : 8; //[7:0]
+ u32 decap_format : 2; //[9:8]
+ u32 reserved3 : 22; //[31:10]
+ u32 reserved4[2];
+} __attribute__((packed));
+
+struct rx_msdu_end_v1 {
+ u32 reserved1[4];
+ u32 reserved2 : 15; //[14:0]
+ u32 last_msdu : 1; //[15]
+ u32 reserved3 : 16; //[31:16]
+ u32 reserved4[9];
+} __attribute__((packed));
+/************************************************************/
+
+#define PREAMBLE_L_SIG_RATE 0x04
+#define PREAMBLE_VHT_SIG_A_1 0x08
+#define PREAMBLE_VHT_SIG_A_2 0x0c
+
+/* Wifi Logger preamble */
+#define WL_PREAMBLE_CCK 0
+#define WL_PREAMBLE_OFDM 1
+#define WL_PREAMBLE_HT 2
+#define WL_PREAMBLE_VHT 3
+
+#define BITMASK(x) ((1<<(x)) - 1 )
+#define MAX_BA_WINDOW_SIZE 64
+#define SEQ_NUM_RANGE 4096
+#define BITMAP_VAR_SIZE 32
+
+/* Contains MCS related stats */
+struct rx_ppdu_start {
+ u32 reserved1[4];
+ u32 rssi_comb : 8; //[7:0]
+ u32 reserved2 : 24; //[31:8]
+ u32 l_sig_rate : 4; //[3:0]
+ u32 l_sig_rate_select : 1; //[4]
+ u32 reserved3 : 19; //[23:5]
+ u32 preamble_type : 8; //[31:24]
+ u32 ht_sig_vht_sig_a_1 : 24; //[23:0]
+ u32 reserved4 : 8; //[31:24]
+ u32 ht_sig_vht_sig_a_2 : 24; //[23:0]
+ u32 reserved5 : 8; //[31:25]
+ u32 reserved6[2];
+} __attribute__((packed));
+
+struct rx_ppdu_end {
+ u32 reserved1[16];
+ u32 tsf_timestamp;
+ u32 reserved2[5];
+} __attribute__((packed));
+
+struct rx_ppdu_end_V1 {
+ u32 reserved1[18];
+ u32 wb_timestamp_lower_32;
+ u32 reserved2[18];
+} __attribute__((packed));
+
+#define MAX_MSDUS_PER_MPDU 3
+#define MAX_RXMPDUS_PER_AMPDU 64
+#define RX_HTT_HDR_STATUS_LEN 64
+/* RX Data length is 256 for PKT_LOG_V2 Version */
+#define RX_HTT_HDR_STATUS_LEN_V1 256
+
+typedef struct {
+ struct rx_attention attention;
+ u32 reserved1;
+ struct rx_mpdu_start mpdu_start;
+ struct rx_msdu_start msdu_start;
+ struct rx_msdu_end msdu_end;
+ struct rx_mpdu_end mpdu_end;
+ struct rx_ppdu_start ppdu_start;
+ struct rx_ppdu_end ppdu_end;
+ char rx_hdr_status[RX_HTT_HDR_STATUS_LEN];
+}__attribute__((packed)) rb_pkt_stats_t;
+
+/* structure implemented w.r.t PKT_LOG_V2 Version */
+typedef struct {
+ struct rx_attention attention;
+ u32 reserved1[2];
+ struct rx_mpdu_start mpdu_start;
+ struct rx_msdu_start_v1 msdu_start;
+ struct rx_msdu_end_v1 msdu_end;
+ struct rx_mpdu_end mpdu_end;
+ struct rx_ppdu_start ppdu_start;
+ struct rx_ppdu_end_V1 ppdu_end;
+ char rx_hdr_status[RX_HTT_HDR_STATUS_LEN_V1];
+}__attribute__((packed)) rb_pkt_stats_t_v1;
+/************************************************************/
+
+/*Tx stats specific structures. */
+struct ppdu_status {
+ u32 ba_start_seq_num : 12; //[11:0]
+ u32 reserved1 : 3; //[14:12]
+ u32 ba_status : 1; //[15]
+ u32 reserved2 : 15; //[30:16]
+ u32 tx_ok : 1; //[31]
+ u32 ba_bitmap_31_0 : 32; //[31:0]
+ u32 ba_bitmap_63_32 : 32; //[31:0]
+ u32 reserved3[8];
+ u32 ack_rssi_ave : 8; //[7:0]
+ u32 reserved4 : 16; //[23:8]
+ u32 total_tries : 5; //[28:24]
+ u32 reserved5 : 3; //[31:29]
+ u32 reserved6[4];
+} __attribute__((packed));
+
+/*Contains tx timestamp*/
+struct try_status {
+ u32 timestamp : 23; //[22:0]
+ u32 reserved1 : 1; //[23]
+ u32 series : 1; //[24]
+ u32 reserved2 : 3; //[27:25]
+ u32 packet_bw : 2; //[29:28]
+ u32 reserved3 : 1; //[30]
+ u32 tx_packet : 1; //[31]
+} __attribute__((packed));
+
+struct try_list {
+ struct try_status try_st[16];
+} __attribute__((packed));
+
+
+struct tx_ppdu_end {
+ struct try_list try_list;
+ struct ppdu_status stat;
+} __attribute__((packed));
+
+/*Tx MCS and data rate ralated stats */
+struct series_bw {
+ u32 reserved1 : 28; //[27:0]
+ u32 short_gi : 1; //[28]
+ u32 reserved2 : 3; //[31:29]
+ u32 reserved3 : 24; //[23:21]
+ u32 rate : 4; //[27:24]
+ u32 nss : 2; //[29:28]
+ u32 preamble_type : 2; //[31:30]
+ u32 reserved4[2];
+} __attribute__((packed));
+
+enum tx_bw {
+ BW_20_MHZ,
+ BW_40_MHZ,
+ BW_80_MHZ,
+ BW_160_MHZ
+};
+
+#define DATA_PROTECTED 14
+struct tx_ppdu_start {
+ u32 reserved1[2];
+ u32 start_seq_num : 12; //[11:0]
+ u32 reserved2 : 20; //[31:12]
+ u32 seqnum_bitmap_31_0 : 32; //[31:0]
+ u32 seqnum_bitmap_63_32 : 32; //[31:0]
+ u32 reserved3[8];
+ u32 reserved4 : 15; //[14:0]
+ u32 ampdu : 1; //[15]
+ u32 no_ack : 1; //[16]
+ u32 reserved5 : 15; //[31:17]
+ u32 reserved6 : 16; //[15:0]
+ u32 frame_control : 16; //[31:16]
+ u32 reserved7 : 16; //[23:21]
+ u32 qos_ctl : 16; //[31:16]
+ u32 reserved8[4];
+ u32 reserved9 : 24; //[23:21]
+ u32 valid_s0_bw20 : 1; //[24]
+ u32 valid_s0_bw40 : 1; //[25]
+ u32 valid_s0_bw80 : 1; //[26]
+ u32 valid_s0_bw160 : 1; //[27]
+ u32 valid_s1_bw20 : 1; //[28]
+ u32 valid_s1_bw40 : 1; //[29]
+ u32 valid_s1_bw80 : 1; //[30]
+ u32 valid_s1_bw160 : 1; //[31]
+ struct series_bw s0_bw20;
+ struct series_bw s0_bw40;
+ struct series_bw s0_bw80;
+ struct series_bw s0_bw160;
+ struct series_bw s1_bw20;
+ struct series_bw s1_bw40;
+ struct series_bw s1_bw80;
+ struct series_bw s1_bw160;
+ u32 reserved10[3];
+} __attribute__((packed));
+
+#define PKTLOG_MAX_TXCTL_WORDS 57 /* +2 words for bitmap */
+typedef struct {
+ u32 reserved1[3];
+ union {
+ u32 txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS];
+ struct tx_ppdu_start ppdu_start;
+ }u;
+} __attribute__((packed)) wh_pktlog_txctl;
+
+/* Required stats are spread across multiple
+ * events(PKTLOG_TYPE_TX_CTRL and PKTLOG_TYPE_TX_STAT here).
+ * Need to aggregate the stats collected in each event and write to the
+ * ring buffer only after receiving all the expected stats.
+ * Need to preserve the stats in hal_info till then and use tx_stats_events
+ * flag to track the events.
+ * prev_seq_no: Can used to track the events that come from driver and identify
+ * if any event is missed.
+ */
+
+/* PKT_LOG_V2 Base strcuture used to parse buffer */
+typedef struct {
+ u16 frm_ctrl;
+ u8 tx_ok;
+ u16 qos_ctrl;
+ u64 bmap_failed;
+ u64 bmap_enqueued;
+} __attribute__((packed)) node_pkt_stats;
+
+typedef u8 A_RATECODE;
+
+/* Rate Code as per PKT_LOG_V2 Version */
+typedef struct {
+ A_RATECODE rateCode;
+ u8 flags;
+} RATE_CODE;
+
+/* bandwidht type*/
+typedef enum {
+ BW_20MHZ,
+ BW_40MHZ,
+ BW_80MHZ,
+ BW_160MHZ,
+} bandwidth;
+
+/* Preamble type*/
+typedef enum {
+ WIFI_HW_RATECODE_PREAM_OFDM = 0,
+ WIFI_HW_RATECODE_PREAM_CCK = 1,
+ WIFI_HW_RATECODE_PREAM_HT = 2,
+ WIFI_HW_RATECODE_PREAM_VHT = 3,
+ WIFI_HW_RATECODE_PREAM_COUNT,
+} WIFI_HW_RATECODE_PREAM_TYPE;
+
+/**
+ * struct index_data_rate_type - non vht data rate type
+ * @rate_index: cck rate index
+ * @cck_rate: CCK supported rate table
+ */
+struct index_data_rate_cck_type {
+ uint8_t rate_index;
+ uint16_t cck_rate[2];
+};
+
+/**
+ * struct index_data_rate_type - non vht data rate type
+ * @rate_index: ofdm rate index
+ * @ofdm__rate: OFDM supported rate table
+ */
+struct index_data_rate_ofdm_type {
+ uint8_t rate_index;
+ uint16_t ofdm_rate[2];
+};
+
+/*Below CCK/OFDM table refer from firmware Arch */
+/* Rate Table Based on CCK */
+static struct index_data_rate_cck_type cck_mcs_nss1[] = {
+ /*RC LKbps SKbps */
+ {0x40, {11000, 11000} },
+ {0x41, {5500, 5500} },
+ {0x42, {2000, 2000} },
+ {0x43, {1000, 1000} }
+};
+
+/* Rate Table Based on OFDM */
+static struct index_data_rate_ofdm_type ofdm_mcs_nss1[] = {
+ /*RC LKbps SKbps */
+ {0x00, {48000, 48000} },
+ {0x01, {34000, 24000} },
+ {0x02, {12000, 12000} },
+ {0x03, {6000, 6000} },
+ {0x04, {54000, 54000} },
+ {0x05, {36000, 36000} },
+ {0x06, {18000, 18000} },
+ {0x07, {9000, 9000} }
+};
+
+/**
+ * struct index_data_rate_type - non vht data rate type
+ * @mcs_index: mcs rate index
+ * @ht20_rate: HT20 supported rate table
+ * @ht40_rate: HT40 supported rate table
+ */
+struct index_data_rate_type {
+ uint8_t mcs_index;
+ uint16_t ht20_rate[2];
+ uint16_t ht40_rate[2];
+};
+
+/**
+ * struct index_vht_data_rate_type - vht data rate type
+ * @mcs_index: mcs rate index
+ * @ht20_rate: VHT20 supported rate table
+ * @ht40_rate: VHT40 supported rate table
+ * @ht80_rate: VHT80 supported rate table
+ */
+struct index_vht_data_rate_type {
+ uint8_t mcs_index;
+ uint16_t ht20_rate[2];
+ uint16_t ht40_rate[2];
+ uint16_t ht80_rate[2];
+};
+
+/*Below HT/VHT table refer from Host Driver
+ * MCS Based rate table
+ * HT MCS parameters with Nss = 1
+ */
+static struct index_data_rate_type mcs_nss1[] = {
+ /* MCS L20 S20 L40 S40 */
+ {0, {65, 72}, {135, 150 } },
+ {1, {130, 144}, {270, 300 } },
+ {2, {195, 217}, {405, 450 } },
+ {3, {260, 289}, {540, 600 } },
+ {4, {390, 433}, {815, 900 } },
+ {5, {520, 578}, {1080, 1200} },
+ {6, {585, 650}, {1215, 1350} },
+ {7, {650, 722}, {1350, 1500} }
+};
+
+/* HT MCS parameters with Nss = 2 */
+static struct index_data_rate_type mcs_nss2[] = {
+ /* MCS L20 S20 L40 S40 */
+ {0, {130, 144}, {270, 300 } },
+ {1, {260, 289}, {540, 600 } },
+ {2, {390, 433}, {810, 900 } },
+ {3, {520, 578}, {1080, 1200} },
+ {4, {780, 867}, {1620, 1800} },
+ {5, {1040, 1156}, {2160, 2400} },
+ {6, {1170, 1300}, {2430, 2700} },
+ {7, {1300, 1440}, {2700, 3000} }
+};
+
+/* MCS Based VHT rate table
+ * MCS parameters with Nss = 1
+ */
+static struct index_vht_data_rate_type vht_mcs_nss1[] = {
+ /* MCS L20 S20 L40 S40 L80 S80 */
+ {0, {65, 72 }, {135, 150}, {293, 325} },
+ {1, {130, 144}, {270, 300}, {585, 650} },
+ {2, {195, 217}, {405, 450}, {878, 975} },
+ {3, {260, 289}, {540, 600}, {1170, 1300} },
+ {4, {390, 433}, {810, 900}, {1755, 1950} },
+ {5, {520, 578}, {1080, 1200}, {2340, 2600} },
+ {6, {585, 650}, {1215, 1350}, {2633, 2925} },
+ {7, {650, 722}, {1350, 1500}, {2925, 3250} },
+ {8, {780, 867}, {1620, 1800}, {3510, 3900} },
+ {9, {865, 960}, {1800, 2000}, {3900, 4333} }
+};
+
+/*MCS parameters with Nss = 2*/
+static struct index_vht_data_rate_type vht_mcs_nss2[] = {
+ /* MCS L20 S20 L40 S40 L80 S80 */
+ {0, {130, 144}, {270, 300}, { 585, 650} },
+ {1, {260, 289}, {540, 600}, {1170, 1300} },
+ {2, {390, 433}, {810, 900}, {1755, 1950} },
+ {3, {520, 578}, {1080, 1200}, {2340, 2600} },
+ {4, {780, 867}, {1620, 1800}, {3510, 3900} },
+ {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
+ {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
+ {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
+ {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
+ {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
+};
+/*********************************************************/
+
+#define RING_BUF_ENTRY_SIZE 512
+#define PKT_STATS_BUF_SIZE 128
+struct pkt_stats_s {
+ u8 tx_stats_events;
+ /* TODO: Need to handle the case if size of the stats are more
+ * than 512 bytes. Currently, the tx size is 34 bytes and ring buffer entry
+ * size is 12 bytes.
+ */
+ u8 tx_stats[PKT_STATS_BUF_SIZE];
+ u8 num_msdu;
+ u16 start_seq_num;
+ u16 ba_seq_num;
+ u32 ba_bitmap_31_0;
+ u32 ba_bitmap_63_32;
+ u32 tx_seqnum_bitmap_31_0;
+ u32 tx_seqnum_bitmap_63_32;
+ u32 shifted_bitmap_31_0;
+ u32 shifted_bitmap_63_32;
+ bool isBlockAck;
+ u8 tx_bandwidth;
+ u8 series;
+};
+
+typedef union {
+ struct {
+ u16 rate : 4;
+ u16 nss : 2;
+ u16 preamble : 2;
+ u16 bw : 2;
+ u16 short_gi : 1;
+ u16 reserved : 5;
+ } mcs_s;
+ u16 mcs;
+} MCS;
+
+typedef struct {
+ MCS RxMCS;
+ u16 last_transmit_rate;
+ u16 rssi;
+ u32 timestamp;
+ u8 tid;
+} rx_aggr_stats;
+
+
+typedef struct drv_msg_s
+{
+ u16 length;
+ u16 event_type;
+ u32 timestamp_low;
+ u32 timestamp_high;
+ union {
+ struct {
+ u32 version;
+ u32 msg_seq_no;
+ u32 payload_len;
+ u8 payload[0];
+ } __attribute__((packed)) pkt_stats_event;
+ } u;
+} __attribute__((packed)) drv_msg_t;
+
+typedef enum {
+ START_MONITOR = 1,
+ STOP_MONITOR,
+ TX_MGMT_PKT,
+ TX_DATA_PKT,
+ RX_MGMT_PKT,
+ RX_DATA_PKT,
+} pktdump_event_type;
+
+typedef struct {
+ u8 status;
+ u8 type;
+ u32 driver_ts;
+ u16 fw_ts;
+} __attribute__((packed)) pktdump_hdr;
+
+typedef struct {
+ frame_type payload_type;
+ u32 driver_timestamp_usec;
+ u32 firmware_timestamp_usec;
+ size_t frame_len;
+ char *frame_content;
+} frame_info_i;
+
+typedef struct {
+ // Prefix of MD5 hash of |frame_inf.frame_content|. If frame
+ // content is not provided, prefix of MD5 hash over the same data
+ // that would be in frame_content, if frame content were provided.
+ char md5_prefix[MD5_PREFIX_LEN]; // Prefix of MD5 hash of packet bytes
+ wifi_tx_packet_fate fate;
+ frame_info_i frame_inf;
+} wifi_tx_report_i;
+
+typedef struct {
+ // Prefix of MD5 hash of |frame_inf.frame_content|. If frame
+ // content is not provided, prefix of MD5 hash over the same data
+ // that would be in frame_content, if frame content were provided.
+ char md5_prefix[MD5_PREFIX_LEN];
+ wifi_rx_packet_fate fate;
+ frame_info_i frame_inf;
+} wifi_rx_report_i;
+
+typedef struct {
+ wifi_tx_report_i tx_fate_stats[MAX_FATE_LOG_LEN];
+ size_t n_tx_stats_collected;
+ wifi_rx_report_i rx_fate_stats[MAX_FATE_LOG_LEN];
+ size_t n_rx_stats_collected;
+} packet_fate_monitor_info;
+
+#endif
diff --git a/qcwcn/wifi_hal/qca-vendor_copy.h b/wcn6740/qcwcn/wifi_hal/qca-vendor_copy.h
similarity index 66%
copy from qcwcn/wifi_hal/qca-vendor_copy.h
copy to wcn6740/qcwcn/wifi_hal/qca-vendor_copy.h
index 11442ee..1faccff 100644
--- a/qcwcn/wifi_hal/qca-vendor_copy.h
+++ b/wcn6740/qcwcn/wifi_hal/qca-vendor_copy.h
@@ -1,10 +1,41 @@
/*
* Qualcomm Atheros OUI and vendor specific assignments
* Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
- * Copyright (c) 2018-2019, The Linux Foundation
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 QCA_VENDOR_H
@@ -512,7 +543,9 @@
* @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
* configure parameters per peer to capture Channel Frequency Response
* (CFR) and enable Periodic CFR capture. The attributes for this command
- * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command
+ * can also be used to send CFR data from the driver to userspace when
+ * netlink events are used to send CFR data.
*
* @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
* in throughput dynamically. The driver estimates the throughput based on
@@ -620,7 +653,14 @@
* This new command is alternative to existing command
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
* is using stream of bytes instead of structured data using vendor
- * attributes.
+ * attributes. User space sends unsafe frequency ranges to the driver using
+ * a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
+ * reception of this command, the driver shall check if an interface is
+ * operating on an unsafe frequency and the driver shall try to move to a
+ * safe channel when needed. If the driver is not able to find a safe
+ * channel the interface can keep operating on an unsafe channel with the
+ * TX power limit derived based on internal configurations like
+ * regulatory/SAR rules.
*
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
* add the STA node details in driver/firmware. Attributes for this event
@@ -664,36 +704,212 @@
* qca_wlan_vendor_attr_driver_disconnect_reason.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to
- * add/delete TSPEC for each AC. One command is for one specific AC only.
- * This command can only be used in STA mode and the STA must be
- * associated with an AP when the command is issued. Uses attributes
- * defined in enum qca_wlan_vendor_attr_config_tspec.
+ * add/delete TSPEC for each AC. One command is for one specific AC only.
+ * This command can only be used in STA mode and the STA must be
+ * associated with an AP when the command is issued. Uses attributes
+ * defined in enum qca_wlan_vendor_attr_config_tspec.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT.
- * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
*
* @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from
- * the driver. The band configurations obtained are referred through
- * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
+ * the driver. The band configurations obtained are referred through
+ * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
*
* @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium
- * assessment.
- * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
+ * assessment.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
*
* @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is
- * used to update SSID information in hostapd when it is updated in the
- * driver. Uses the attribute NL80211_ATTR_SSID.
+ * used to update SSID information in hostapd when it is updated in the
+ * driver. Uses the attribute NL80211_ATTR_SSID.
*
* @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by
- * the driver to send opaque data from the firmware to userspace. The
- * driver sends an event to userspace whenever such data is received from
- * the firmware.
+ * the driver to send opaque data from the firmware to userspace. The
+ * driver sends an event to userspace whenever such data is received from
+ * the firmware.
*
- * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
- * send this opaque data for this event.
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
+ * send this opaque data for this event.
*
- * The format of the opaque data is specific to the particular firmware
- * version and there is no guarantee of the format remaining same.
+ * The format of the opaque data is specific to the particular firmware
+ * version and there is no guarantee of the format remaining same.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event.
+ * The host driver selects Tx VDEV, and notifies user. The attributes
+ * used with this event are defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_status.
+ * This event contains Tx VDEV group information, other VDEVs
+ * interface index, and status information.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY: Vendor command to
+ * configure the concurrent session policies when multiple interfaces
+ * are (getting) active. The attributes used by this command are defined
+ * in enum qca_wlan_vendor_attr_concurrent_policy.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command
+ * to query usable channels for different interface types such as STA,
+ * AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable
+ * channels in the response based on country code, different static
+ * configurations, concurrency combinations, etc. The attributes used
+ * with this command are defined in
+ * enum qca_wlan_vendor_attr_usable_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used
+ * to get DFS radar history from the driver to userspace. The driver
+ * returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an
+ * array of nested entries.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to
+ * enable/disable mDNS offload to the firmware. The attributes used with
+ * this command are defined in enum qca_wlan_vendor_attr_mdns_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used
+ * to set packet monitor mode that aims to send the specified set of TX and
+ * RX frames on the current client interface to an active monitor
+ * interface. If this monitor mode is set, the driver will send the
+ * configured frames, from the interface on which the command is issued, to
+ * an active monitor interface. The attributes used with this command are
+ * defined in enum qca_wlan_vendor_attr_set_monitor_mode.
+ *
+ * Though the monitor mode is configured for the respective
+ * Data/Management/Control frames, it is up to the respective WLAN
+ * driver/firmware/hardware designs to consider the possibility of sending
+ * these frames over the monitor interface. For example, the Control frames
+ * are handled within the hardware and thus passing such frames over the
+ * monitor interface is left to the respective designs.
+ *
+ * Also, this monitor mode is governed to behave accordingly in
+ * suspend/resume states. If the firmware handles any of such frames in
+ * suspend state without waking up the host and if the monitor mode is
+ * configured to notify all such frames, the firmware is expected to resume
+ * the host and forward the respective frames to the monitor interface.
+ * Please note that such a request to get the frames over the monitor
+ * interface will have a definite power implication.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both
+ * as a request to set the driver/firmware with the parameters to trigger
+ * the roaming events, and also used by the driver/firmware to pass on the
+ * various roam events to userspace.
+ * Applicable only for the STA mode. The attributes used with this command
+ * are defined in enum qca_wlan_vendor_attr_roam_events.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG: Subcommand to set or reset the
+ * rate mask config for a list of PHY types. Userspace shall provide an
+ * array of the vendor attributes defined in
+ * enum qca_wlan_vendor_attr_ratemask_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA: Multi-channel Concurrency (MCC) occurs
+ * when two interfaces are active on the same band, using two different
+ * home channels, and only supported by a single radio. In this scenario
+ * the device must split the use of the radio between the two interfaces.
+ * The percentage of time allocated to a given interface is the quota.
+ * Depending on the configuration, the quota can either be fixed or
+ * dynamic.
+ *
+ * When used as an event, the device will report the quota type, and for
+ * all interfaces operating in MCC it will report the current quota.
+ * When used as a command, the device can be configured for a specific
+ * quota type, and in the case of a fixed quota, the quota to apply to one
+ * of the interfaces.
+ *
+ * Applications can use the event to do TX bitrate control based on the
+ * information, and can use the command to explicitly set the quota to
+ * enhance performance in specific scenarios.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_mcc_quota.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX: Vendor command to
+ * get the WLAN radio combinations matrix supported by the device which
+ * provides the device simultaneous radio configurations such as
+ * standalone, dual band simultaneous, and single band simultaneous.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_radio_combination_matrix.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY: Event indicating to the user space
+ * that the driver is ready for operations again after recovering from
+ * internal failures. This occurs following a failure that was indicated by
+ * @QCA_NL80211_VENDOR_SUBCMD_HANG.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PASN: Subcommand used to offload preassociation
+ * security negotiation and key generation to user space.
+ *
+ * When used as an event, the driver requests userspace to trigger the PASN
+ * authentication or dropping of a PTKSA for the indicated peer devices.
+ * When used as a command response, userspace indicates a consolidated
+ * status report for all the peers that were requested for.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_pasn.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT: Subcommand used to set
+ * secure ranging context such as TK and LTF keyseed for each peer
+ * requested by the driver with a @QCA_NL80211_VENDOR_SUBCMD_PASN event.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_secure_ranging_ctx.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_COAP_OFFLOAD: This vendor subcommand is used to
+ * enable/disable offload processing in firmware during system/runtime
+ * suspend for CoAP messages (see RFC7252: The Constrained Application
+ * Protocol) and fetch information of the CoAP messages cached during
+ * offload processing.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_coap_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SCS_RULE_CONFIG: Subcommand to configure
+ * (add, remove, or change) a Stream Classification Service (SCS) rule.
+ *
+ * The attributes used with this event are defined in
+ * enum qca_wlan_vendor_attr_scs_rule_config.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY: Fetch SAR capabilities
+ * supported by the WLAN firmware.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_sar_capability.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SR: Subcommand used to implement Spatial Reuse
+ * (SR) feature. This command is used by userspace to configure SR
+ * parameters to the driver and to get the SR related parameters and
+ * statistics with synchronous responses from the driver.
+ * The driver also uses this command to send asynchronous events to
+ * userspace to indicate suspend/resume of SR feature and changes
+ * in SR parameters.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_sr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MLO_PEER_PRIM_NETDEV_EVENT: Subcommand used to
+ * notify application layer about the primary netdev of an MLO connection.
+ * In some implementations, MLO has multiple netdevs out of which one
+ * netdev is designated as primary to provide a unified interface to the
+ * bridge. In those implementations this event is sent on every MLO peer
+ * connection.
+ *
+ * The attributes used with this event are defined in
+ * enum qca_wlan_vendor_attr_mlo_peer_prim_netdev_event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AFC_EVENT: This vendor command is used by the
+ * driver to notify different AFC events to userspace. The attributes used
+ * with this command are defined in enum qca_wlan_vendor_attr_afc_event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AFC_RESPONSE: This vendor command is used by
+ * userspace to deliver AFC response data to driver. The attributes used
+ * with this command are defined in enum qca_wlan_vendor_attr_afc_response.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DOZED_AP: Subcommand to configure AP interface to
+ * operate in doze mode.
+ *
+ * Userspace uses this command to configure the AP interface to enter or
+ * exit from doze mode. The driver sends this event after it enters or
+ * exits the doze mode with the updated AP doze mode settings.
+ *
+ * The attributes used with this subcommand are defined in
+ * enum qca_wlan_vendor_attr_dozed_ap.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -879,8 +1095,37 @@
QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193,
QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194,
QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195,
+ QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196,
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY = 197,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199,
+ QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200,
+ /* 201 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203,
+ QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG = 204,
+ QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA = 205,
+ /* 206..212 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX = 213,
+ QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY = 214,
+ QCA_NL80211_VENDOR_SUBCMD_PASN = 215,
+ QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT = 216,
+ QCA_NL80211_VENDOR_SUBCMD_COAP_OFFLOAD = 217,
+ QCA_NL80211_VENDOR_SUBCMD_SCS_RULE_CONFIG = 218,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY = 219,
+ QCA_NL80211_VENDOR_SUBCMD_SR = 220,
+ QCA_NL80211_VENDOR_SUBCMD_MLO_PEER_PRIM_NETDEV_EVENT = 221,
+ QCA_NL80211_VENDOR_SUBCMD_AFC_EVENT = 222,
+ QCA_NL80211_VENDOR_SUBCMD_AFC_RESPONSE = 223,
+ QCA_NL80211_VENDOR_SUBCMD_DOZED_AP = 224,
};
+/* Compatibility defines for previously used subcmd names.
+ * These values should not be used in any new implementation.
+ */
+#define QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY \
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY
+
enum qca_wlan_vendor_attr {
QCA_WLAN_VENDOR_ATTR_INVALID = 0,
/* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
@@ -1117,7 +1362,7 @@
* @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
* or environment being very noisy or congested.
*
- * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
* from the user (user space).
*
* @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
@@ -1125,6 +1370,26 @@
*
* @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
* breaching out the configured threshold.
+ *
+ * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
+ * transition request.
+ *
+ * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no
+ * data activity with the AP and the current RSSI falls below a certain
+ * threshold.
+ *
+ * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or
+ * Disassociation frames received from the connected AP.
+ *
+ * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan
+ * that happens when there is no candidate AP found during the poor RSSI scan
+ * trigger.
+ *
+ * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results
+ * obtained from an external scan (not aimed at roaming).
+ *
+ * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is
+ * established when the station is connected in the 2.4 GHz band.
*/
enum qca_roam_reason {
QCA_ROAM_REASON_UNKNOWN,
@@ -1136,10 +1401,19 @@
QCA_ROAM_REASON_USER_TRIGGER,
QCA_ROAM_REASON_BTM,
QCA_ROAM_REASON_BSS_LOAD,
+ QCA_ROAM_REASON_WTC,
+ QCA_ROAM_REASON_IDLE,
+ QCA_ROAM_REASON_DISCONNECTION,
+ QCA_ROAM_REASON_PERIODIC_TIMER,
+ QCA_ROAM_REASON_BACKGROUND_SCAN,
+ QCA_ROAM_REASON_BT_ACTIVITY,
};
enum qca_wlan_vendor_attr_roam_auth {
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
+ /* Indicates BSSID of the roamed AP for non-MLO roaming and MLD address
+ * of the roamed AP for MLO roaming.
+ */
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
@@ -1184,6 +1458,11 @@
* Defined by enum qca_roam_reason.
*/
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON = 14,
+ /* A nested attribute containing per-link information of all the links
+ * of MLO connection done while roaming. The attributes used inside this
+ * nested attribute are defined in enum qca_wlan_vendor_attr_mlo_links.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MLO_LINKS = 15,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
@@ -1355,6 +1634,22 @@
* Used with event to notify the EDMG channel number selected in ACS
* operation.
* EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16).
+ * Used with event to notify the puncture pattern selected in ACS operation.
+ * Encoding for this attribute will follow the convention used in the Disabled
+ * Subchannel Bitmap field of the EHT Operation IE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute.
+ * Used with command to configure ACS operation for EHT mode.
+ * Disable (flag attribute not present) - EHT disabled and
+ * Enable (flag attribute present) - EHT enabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME: Optional (u32).
+ * Used with command to configure how older scan can be considered for ACS
+ * scoring. In case scan was performed on a partial set of channels configured
+ * with this command within last QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME
+ * (in ms), scan only the remaining channels.
*/
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1375,6 +1670,9 @@
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
+ QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
+ QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
+ QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME = 20,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -1438,6 +1736,61 @@
* %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and
* %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from
* userspace.
+ * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r.
+ * With Adaptive 11r feature, access points advertise the vendor
+ * specific IEs and MDE but do not include FT AKM in the RSNE.
+ * The Adaptive 11r supported stations are expected to identify
+ * such vendor specific IEs and connect to the AP in FT mode though
+ * the profile is configured in non-FT mode.
+ * The driver-based SME cases also need to have this support for
+ * Adaptive 11r to handle the connection and roaming scenarios.
+ * This flag indicates the support for the same to the user space.
+ * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports
+ * concurrent network sessions on different Wi-Fi bands. This feature
+ * capability is attributed to the hardware's capability to support
+ * the same (e.g., DBS).
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT: Flag indicating whether the
+ * responses for the respective TWT operations are asynchronous (separate
+ * event message) from the driver. If not specified, the responses are
+ * synchronous (in vendor command reply) to the request. Each TWT
+ * operation is specifically mentioned (against its respective
+ * documentation) to support either of these or both modes.
+ * @QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI: Flag indicates
+ * that the driver requires add/del virtual interface path using the
+ * generic nl80211 commands for NDP interface create/delete and to
+ * register/unregister the netdev instead of creating/deleting the NDP
+ * interface using the vendor commands
+ * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE and
+ * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE. With the latest kernel
+ * (5.12 version onward), interface creation/deletion is not allowed using
+ * vendor commands as it leads to a deadlock while acquiring the RTNL_LOCK
+ * during the register/unregister of netdev. Create and delete NDP
+ * interface using NL80211_CMD_NEW_INTERFACE and NL80211_CMD_DEL_INTERFACE
+ * commands respectively if the driver advertises this capability set.
+ * @QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_STA: Flag indicates that the device in
+ * station mode supports secure LTF. If NL80211_EXT_FEATURE_SECURE_LTF is
+ * set, then QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_STA will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_AP: Flag indicates that the device in AP
+ * mode supports secure LTF. If NL80211_EXT_FEATURE_SECURE_LTF is set, then
+ * QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_AP will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_STA: Flag indicates that the device in
+ * station mode supports secure RTT measurement exchange. If
+ * NL80211_EXT_FEATURE_SECURE_RTT is set,
+ * QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_STA will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_AP: Flag indicates that the device in AP
+ * mode supports secure RTT measurement exchange. If
+ * NL80211_EXT_FEATURE_SECURE_RTT is set,
+ * QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_AP will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_STA: Flag indicates that
+ * the device in station mode supports protection of range negotiation and
+ * measurement management frames. If
+ * NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE is set, then
+ * QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_STA will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP: Flag indicates that
+ * the device in AP mode supports protection of range negotiation and
+ * measurement management frames. If
+ * NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE is set, then
+ * QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP will be ignored.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
@@ -1449,10 +1802,20 @@
QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5,
QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6,
QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7,
- QCA_WLAN_VENDOR_FEATURE_TWT = 8,
+ QCA_WLAN_VENDOR_FEATURE_TWT = 8,
QCA_WLAN_VENDOR_FEATURE_11AX = 9,
QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10,
QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11,
+ QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12,
+ QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13,
+ QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT = 14,
+ QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI = 15,
+ QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_STA = 16,
+ QCA_WLAN_VENDOR_FEATURE_SECURE_LTF_AP = 17,
+ QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_STA = 18,
+ QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_AP = 19,
+ QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_STA = 20,
+ QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP = 21,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -1658,32 +2021,62 @@
};
/**
- * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
- * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
- * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
- * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
- * SOC timer value at TSF capture
+ * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32)
+ * Specify the TSF command. Possible values are defined in
+ * &enum qca_tsf_cmd.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
+ * This attribute contains TSF timer value. This attribute is only available
+ * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
+ * This attribute contains SOC timer value at TSF capture. This attribute is
+ * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32)
+ * This attribute is used to provide TSF sync interval and only applicable when
+ * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the
+ * driver will use the default value. Time unit is in milliseconds.
*/
enum qca_vendor_attr_tsf_cmd {
QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_TSF_CMD,
QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL,
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TSF_MAX =
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
};
/**
- * enum qca_tsf_operation: TSF driver commands
+ * enum qca_tsf_cmd: TSF driver commands
* @QCA_TSF_CAPTURE: Initiate TSF Capture
* @QCA_TSF_GET: Get TSF capture value
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
+ * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically
+ * fetches TSF and host time mapping from the firmware with interval configured
+ * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the
+ * interval value is not provided the driver will use the default value. The
+ * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
+ * command.
+ * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
*/
enum qca_tsf_cmd {
QCA_TSF_CAPTURE,
QCA_TSF_GET,
QCA_TSF_SYNC_GET,
+ QCA_TSF_AUTO_REPORT_ENABLE,
+ QCA_TSF_AUTO_REPORT_DISABLE,
+ QCA_TSF_SYNC_START,
+ QCA_TSF_SYNC_STOP,
};
/**
@@ -1777,6 +2170,23 @@
};
/**
+ * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the
+ * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take.
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority
+ */
+enum qca_wlan_vendor_scan_priority {
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4,
+};
+
+/**
* enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
*
* @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
@@ -1801,6 +2211,11 @@
* @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in
* microseconds. This is a common value which applies across all
* frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to
+ * other scan requests. It is a u32 attribute and takes values from enum
+ * qca_wlan_vendor_scan_priority. This is an optional attribute.
+ * If this attribute is not configured, the driver shall use
+ * QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
*/
enum qca_wlan_vendor_attr_scan {
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -1816,6 +2231,7 @@
QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
+ QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -2173,7 +2589,10 @@
QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES = 58,
/* 8-bit unsigned value for ELNA bypass.
- * 1-Enable, 0-Disable
+ * 0 - Disable eLNA bypass.
+ * 1 - Enable eLNA bypass.
+ * 2 - Reset eLNA bypass configuration, the driver should
+ * revert to the default configuration of eLNA bypass.
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS = 59,
@@ -2278,6 +2697,10 @@
* frame. The updated NSS value after the connection shall not be
* greater than the one negotiated during the connection. Any such
* higher value configuration shall be returned with a failure.
+ * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done
+ * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to
+ * configure the asymmetric NSS configuration (such as 1X2).
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70,
/* 8-bit unsigned value to trigger Optimized Power Management:
@@ -2295,6 +2718,14 @@
* Set the value to QCA_WLAN_AC_BK if the QoS upgrade needs to be
* disabled, as BK is of the lowest priority and an upgrade to it does
* not result in any changes for the frames.
+ *
+ * If only UDP frames of BE or BK access category needs to be upgraded
+ * without changing the access category of VO or VI UDP frames, refer to
+ * attribute QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK.
+ *
+ * This attribute is not recommended to be used as it blindly forces all
+ * UDP packets to a higher access category which could impact the
+ * traffic pattern of all apps using UDP and can cause unknown behavior.
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72,
@@ -2326,6 +2757,145 @@
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76,
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for transmitting the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The TX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver
+ * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77,
+
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for receiving the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The RX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver
+ * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78,
+
+ /*
+ * 8-bit unsigned value. This attribute, when set, indicates whether the
+ * specified interface is the primary STA interface when there are more
+ * than one STA interfaces concurrently active.
+ *
+ * This configuration helps the firmware/hardware to support certain
+ * features (e.g., roaming) on this primary interface, if the same
+ * cannot be supported on the concurrent STA interfaces simultaneously.
+ *
+ * This configuration is only applicable for a single STA interface on
+ * a device and gives the priority for it only over other concurrent STA
+ * interfaces.
+ *
+ * If the device is a multi wiphy/soc, this configuration applies to a
+ * single STA interface across the wiphys.
+ *
+ * 1-Enable (is the primary STA), 0-Disable (is not the primary STA)
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * driver to enable/disable FT-over-DS feature. Possible values for
+ * this attribute are 1-Enable and 0-Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * firmware to enable/disable ARP/NS offload feature. Possible values
+ * for this attribute are 0-Disable and 1-Enable.
+ *
+ * This attribute is only applicable for STA/P2P-Client interface,
+ * and is optional, default behavior is ARP/NS offload enabled.
+ *
+ * This attribute can be set in disconnected and connected state, and
+ * will restore to the default behavior if the interface is closed.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * data path mode to be followed for audio traffic. Possible values
+ * are defined in enum qca_wlan_audio_data_path.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AUDIO_DATA_PATH = 82,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * Dedicated Bluetooth Antenna Mode (DBAM) feature. Possible values for
+ * this attribute are defined in the enum qca_wlan_dbam_config.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM = 83,
+
+ /* 8-bit unsigned value. This attribute takes the QoS/access category
+ * value represented by the enum qca_wlan_ac_type and expects the driver
+ * to upgrade the UDP frames of BE or BK access category to this access
+ * category. This attribute will not modify UDP frames of VO or VI
+ * access category. The value of QCA_WLAN_AC_ALL is invalid for this
+ * attribute.
+ *
+ * This will override the DSCP value configured in the frame with the
+ * intention to only upgrade the access category. That said, it is not
+ * intended to downgrade the access category for the frames.
+ * Set the value to QCA_WLAN_AC_BK if the QoS upgrade needs to be
+ * disabled, as BK is of the lowest priority and an upgrade to it does
+ * not result in any changes for the frames.
+ *
+ * This attribute behavior is similar to
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE with the difference that
+ * only UDP frames of BE or BK access category are upgraded and not
+ * UDP frames of VI or VO access category.
+ *
+ * This attribute is not recommended to be used as it blindly forces all
+ * UDP packets of BE or BK access category to a higher access category
+ * which could impact the traffic pattern of all apps using UDP and can
+ * cause unknown behavior.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK = 84,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * periodic sounding for Tx beamformer functionality. The default
+ * behavior uses algorithm to do sounding based on packet stats.
+ *
+ * 0 - Default behavior.
+ * 1 - Enable the periodic sounding for Tx beamformer.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING = 85,
+
+ /* 8-bit unsigned value, whenever wifi calling (wfc) begins or ends,
+ * userspace sends this information to the driver/firmware to configure
+ * wfc state. The driver/firmware uses this information to
+ * optimize power savings, rate adaption, roaming, etc.
+ *
+ * 1 - wfc is on.
+ * 0 - wfc is off.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE = 86,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -2341,6 +2911,19 @@
QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL
/**
+ * enum qca_dbam_config - Specifies DBAM config mode
+ * @QCA_DBAM_DISABLE: Firmware disables DBAM
+ * @QCA_DBAM_ENABLE: Firmware enables DBAM opportunistically when
+ * internal criteria are met.
+ * @QCA_DBAM_FORCE_ENABLE: Firmware enables DBAM forcefully.
+ */
+enum qca_dbam_config {
+ QCA_DBAM_DISABLE = 0,
+ QCA_DBAM_ENABLE = 1,
+ QCA_DBAM_FORCE_ENABLE = 2,
+};
+
+/**
* enum qca_wlan_ani_setting - ANI setting type
* @QCA_WLAN_ANI_SETTING_AUTO: Automatically determine ANI level
* @QCA_WLAN_ANI_SETTING_FIXED: Fix ANI level to the dBm parameter
@@ -2421,23 +3004,50 @@
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
* %QCA_WLAN_VENDOR_GPIO_OUTPUT.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32)
* value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32)
* value to specify the GPIO interrupt mode. Please refer to enum
* qca_gpio_interrupt_mode for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32)
* value to specify the GPIO direction. Please refer to enum qca_gpio_direction
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32)
+ * Value to specify the mux config. Meaning of a given value is dependent
+ * on the target chipset and GPIO pin. Must be of the range 0-15.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32)
+ * Value to specify the drive, refer to enum qca_gpio_drive.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag)
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all
+ * other parameters for the given GPIO will be obtained from internal
+ * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be
+ * specified to indicate the GPIO pin being configured.
*/
enum qca_wlan_gpio_attr {
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
@@ -2453,6 +3063,12 @@
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5,
/* Unsigned 32-bit attribute for GPIO direction to configure */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6,
+ /* Unsigned 32-bit attribute for GPIO mux config */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7,
+ /* Unsigned 32-bit attribute for GPIO drive */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8,
+ /* Flag attribute for using internal GPIO configuration */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
@@ -2528,6 +3144,30 @@
};
/**
+ * enum qca_gpio_drive - GPIO drive
+ * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA
+ * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA
+ * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA
+ * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA
+ * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA
+ * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA
+ * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA
+ * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA
+ * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive
+ */
+enum qca_gpio_drive {
+ QCA_WLAN_GPIO_DRIVE_2MA = 0,
+ QCA_WLAN_GPIO_DRIVE_4MA = 1,
+ QCA_WLAN_GPIO_DRIVE_6MA = 2,
+ QCA_WLAN_GPIO_DRIVE_8MA = 3,
+ QCA_WLAN_GPIO_DRIVE_10MA = 4,
+ QCA_WLAN_GPIO_DRIVE_12MA = 5,
+ QCA_WLAN_GPIO_DRIVE_14MA = 6,
+ QCA_WLAN_GPIO_DRIVE_16MA = 7,
+ QCA_WLAN_GPIO_DRIVE_MAX,
+};
+
+/**
* qca_wlan_set_qdepth_thresh_attr - Parameters for setting
* MSDUQ depth threshold per peer per tid in the target
*
@@ -3688,6 +4328,30 @@
* QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+ /* u8 value representing the channel load percentage. Possible values
+ * are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
+ /* u8 value representing the time slicing duty cycle percentage.
+ * Possible values are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
+ /* Unsigned 32 bit value. The number of Beacon frames which are received
+ * from the associated AP and indicate buffered unicast frame(s) for us
+ * in the TIM element.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_TIM_BEACON = 88,
+ /* Unsigned 32 bit value. The total number of Beacon frames received
+ * from the associated AP that have wrongly indicated buffered unicast
+ * traffic in the TIM element for us.
+ * Below scenarios will be considered as wrong TIM element beacon:
+ * 1) The related TIM element is set in the beacon for STA but STA
+ * doesn’t receive any unicast data after this beacon.
+ * 2) The related TIM element is still set in the beacon for STA
+ * after STA has indicated power save exit by QoS Null Data frame.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_TIM_BEACON_ERR = 89,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4035,6 +4699,30 @@
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1,
};
+/**
+ * enum qca_roam_scan_scheme: Scan scheme
+ *
+ * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan.
+ * Indicates the driver to not scan on a Roam Trigger scenario, but
+ * disconnect. E.g., on a BTM request from the AP the driver/firmware shall
+ * disconnect from the current connected AP by notifying a failure
+ * code in the BTM response.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to
+ * trigger partial frequency scans. These frequencies are the ones learned
+ * or maintained by the driver based on the probability of finding the
+ * BSSIDs in the ESS for which the roaming is triggered.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to
+ * trigger the scan on all the valid frequencies to find better
+ * candidates to roam.
+ */
+enum qca_roam_scan_scheme {
+ QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0,
+ QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1,
+ QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2,
+};
+
/*
* enum qca_vendor_roam_triggers: Bitmap of roaming triggers
*
@@ -4055,6 +4743,18 @@
* when BTM Request frame is received from the connected AP.
* @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered
* when the channel utilization is goes above the configured threshold.
+ * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered
+ * based on the request from the user (space).
+ * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when
+ * device receives Deauthentication/Disassociation frame from connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the
+ * device is in idle state (no TX/RX) and suspend mode, if the current RSSI
+ * is determined to be a poor one.
+ * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered
+ * based on continuous TX Data frame failures to the connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered
+ * based on the scan results obtained from an external scan (not triggered
+ * to aim roaming).
*
* Set the corresponding roam trigger reason bit to consider it for roam
* trigger.
@@ -4070,6 +4770,144 @@
QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5,
QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6,
QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7,
+ QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8,
+ QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9,
+ QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10,
+ QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11,
+ QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12,
+};
+
+/*
+ * enum qca_vendor_roam_fail_reasons: Defines the various roam
+ * fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED: Roam module in the firmware is not
+ * able to trigger the scan.
+ * @QCA_ROAM_FAIL_REASON_NO_AP_FOUND: No roamable APs found during roam scan.
+ * @QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND: No candidate APs found during roam
+ * scan.
+ * @QCA_ROAM_FAIL_REASON_HOST: Roam fail due to disconnect issued from host.
+ * @QCA_ROAM_FAIL_REASON_AUTH_SEND: Unable to send Authentication frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_RECV: Received Authentication frame with error
+ * status code.
+ * @QCA_ROAM_FAIL_REASON_NO_AUTH_RESP: Authentication frame not received.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_SEND: Unable to send Reassociation Request
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_RECV: Received Reassociation Response frame
+ * with error status code.
+ * @QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP: Reassociation Response frame not
+ * received.
+ * @QCA_ROAM_FAIL_REASON_SCAN_FAIL: Scan module not able to start scan.
+ * @QCA_ROAM_FAIL_REASON_AUTH_NO_ACK: No ACK is received for Authentication
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP: Authentication frame is dropped
+ * internally before transmission.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK: No ACK is received for Reassociation
+ * Request frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP: Reassociation Request frame is
+ * dropped internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT: EAPOL-Key M1 is not received and
+ * times out.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND: Unable to send EAPOL-Key M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP: EAPOL-Key M2 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK: No ACK is received for EAPOL-Key
+ * M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT: EAPOL-Key M3 frame is not received.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND: Unable to send EAPOL-Key M4 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP: EAPOL-Key M4 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK: No ACK is received for EAPOL-Key M4
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS: Roam scan is not
+ * started for final beacon miss case.
+ * @QCA_ROAM_FAIL_REASON_DISCONNECT: Deauthentication or Disassociation frame
+ * received from the AP during roaming handoff.
+ * @QCA_ROAM_FAIL_REASON_RESUME_ABORT: Firmware roams to the AP when the Apps
+ * or host is suspended and gives the indication of the last roamed AP only
+ * when the Apps is resumed. If the Apps is resumed while the roaming is in
+ * progress, this ongoing roaming is aborted and the last roamed AP is
+ * indicated to host.
+ * @QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID: WPA3-SAE invalid PMKID.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT: WPA3-SAE pre-authentication times
+ * out.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL: WPA3-SAE pre-authentication fails.
+ */
+enum qca_vendor_roam_fail_reasons {
+ QCA_ROAM_FAIL_REASON_NONE = 0,
+ QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED = 1,
+ QCA_ROAM_FAIL_REASON_NO_AP_FOUND = 2,
+ QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND = 3,
+ QCA_ROAM_FAIL_REASON_HOST = 4,
+ QCA_ROAM_FAIL_REASON_AUTH_SEND = 5,
+ QCA_ROAM_FAIL_REASON_AUTH_RECV = 6,
+ QCA_ROAM_FAIL_REASON_NO_AUTH_RESP = 7,
+ QCA_ROAM_FAIL_REASON_REASSOC_SEND = 8,
+ QCA_ROAM_FAIL_REASON_REASSOC_RECV = 9,
+ QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP = 10,
+ QCA_ROAM_FAIL_REASON_SCAN_FAIL = 11,
+ QCA_ROAM_FAIL_REASON_AUTH_NO_ACK = 12,
+ QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP = 13,
+ QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK = 14,
+ QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP = 15,
+ QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT = 16,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND = 17,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP = 18,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK = 19,
+ QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT = 20,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND = 21,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP = 22,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK = 23,
+ QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS = 24,
+ QCA_ROAM_FAIL_REASON_DISCONNECT = 25,
+ QCA_ROAM_FAIL_REASON_RESUME_ABORT = 26,
+ QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID = 27,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT = 28,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL = 29,
+};
+
+/*
+ * enum qca_vendor_roam_invoke_fail_reasons: Defines the various roam
+ * invoke fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_INVOKE_STATUS_IFACE_INVALID: Invalid interface ID is passed
+ * in roam invoke command.
+ * @QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE: Roam offload in firmware is not
+ * enabled.
+ * @QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID: Connected AP profile SSID
+ * length is invalid.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW: Firmware internal roaming is already
+ * in progress.
+ * @QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP: Host sends the Beacon/Probe Response
+ * of the AP in the roam invoke command to firmware. This reason is sent by the
+ * firmware when the given AP is configured to be ignored or SSID/security
+ * does not match.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL: Roam handoff failed because of
+ * firmware internal reasons.
+ * @QCA_ROAM_INVOKE_STATUS_DISALLOW: Roam invoke trigger is not enabled.
+ * @QCA_ROAM_INVOKE_STATUS_SCAN_FAIL: Scan start fail for roam invoke.
+ * @QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL: Roam handoff start fail.
+ * @QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS: Roam invoke parameters are invalid.
+ * @QCA_ROAM_INVOKE_STATUS_NO_CAND_AP: No candidate AP found to roam to.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_FAIL: Roam handoff failed.
+ */
+enum qca_vendor_roam_invoke_fail_reasons {
+ QCA_ROAM_INVOKE_STATUS_NONE = 0,
+ QCA_ROAM_INVOKE_STATUS_IFACE_INVALID = 1,
+ QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE = 2,
+ QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID = 3,
+ QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW = 4,
+ QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP = 5,
+ QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL = 6,
+ QCA_ROAM_INVOKE_STATUS_DISALLOW = 7,
+ QCA_ROAM_INVOKE_STATUS_SCAN_FAIL = 8,
+ QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL = 9,
+ QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS = 10,
+ QCA_ROAM_INVOKE_STATUS_NO_CAND_AP = 11,
+ QCA_ROAM_INVOKE_STATUS_ROAM_FAIL = 12,
+
};
/**
@@ -4127,7 +4965,7 @@
/**
* enum qca_vendor_attr_roam_control - Attributes to carry roam configuration
- * The following attributes are used to set/get/clear the respective
+ * The following attributes are used to set/get/clear the respective
* configurations to/from the driver.
* For the get, the attribute for the configuration to be queried shall
* carry any of its acceptable values to the driver. In return, the driver
@@ -4226,6 +5064,151 @@
*
* Clears the selection criteria configured in the driver when specified
* with clear command.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value.
+ * Represents value of the scan frequency scheme from enum
+ * qca_roam_scan_scheme.
+ * It's an optional attribute. If this attribute is not configured, the
+ * driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the current connected AP, indicating
+ * the driver to trigger roam only when the current connected AP's RSSI
+ * is less than this threshold.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the candidate AP, indicating
+ * the driver to trigger roam only to the candidate AP with RSSI
+ * better than this threshold. If RSSI thresholds for candidate APs found
+ * in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ,
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will
+ * take precedence over the value configured using the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the
+ * user defined reason code to be sent to the AP in response to AP's
+ * request to trigger the roam if the roaming cannot be triggered.
+ * Applies to all the scenarios of AP assisted roaming (e.g., BTM).
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value.
+ * Carries a bitmap of the roam triggers specified in
+ * enum qca_vendor_roam_triggers.
+ * Represents the roam triggers for which the specific scan scheme from
+ * enum qca_roam_scan_scheme has to be applied.
+ * It's an optional attribute. If this attribute is not configured, but
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme
+ * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for
+ * all the roams.
+ * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the
+ * driver shall proceed with the default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value
+ * in dBm, signifying the RSSI threshold of the candidate AP found in the
+ * 2.4 GHz band. The driver/firmware shall trigger roaming to the candidate
+ * AP found in the 2.4 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 5
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 5 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by tge
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 6
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 6 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value.
+ * Carries bitmask value of bits from &enum qca_set_band and represents
+ * all the bands in which roaming is allowed. The configuration is valid
+ * until next disconnection. If this attribute is not present, the
+ * existing configuration shall be used. By default, roaming is allowed on
+ * all bands supported by the local device. When the value is set to
+ * %QCA_SETBAND_AUTO, all supported bands shall be enabled.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz
+ * bands. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for passive channels in the 5 GHz
+ * band. If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds.
+ * Optional parameter. The minimum duration to stay on the connected AP
+ * channel during the channel scanning. If this attribute is not
+ * configured, the driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds.
+ * Optional parameter. The maximum duration for which the radio can scan
+ * foreign channels consecutively without coming back to home channel. If
+ * this attribute is not configured, the driver shall proceed with default
+ * behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Preferred Scanning Channels.
+ * If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Non Preferred Scanning
+ * Channels. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD: u16 value in Mbps.
+ * Optional parameter. RX link speed threshold to disable roaming.
+ * If the current RX link speed is above the threshold, roaming is not
+ * needed. If this attribute is not configured, or if it is set to 0, the
+ * driver will not consider the RX link speed in the roaming decision.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX: u16 value in milliseconds.
+ * Optional parameter. This configuration delays hand-off by the
+ * specified duration to receive pending RX frames from the current BSS.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ: Unsigned 8-bit
+ * value.
+ * During the roam scan, if there are no desired APs found in the partial
+ * frequency list, an immediate full scan on all the supported frequencies
+ * is initiated as a fallback. This flag controls the frequency list
+ * creation for the full scan on the following lines.
+ * 1 - Full scan to exclude the frequencies that were already scanned by
+ * the previous partial scan.
+ * 0 - Full scan to include all the supported frequencies irrespective of
+ * the ones part of the earlier partial scan.
+ * If this flag is not specified, a full scan shall include all the
+ * supported frequencies irrespective of the ones part of an earlier
+ * partial scan.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY: Unsigned 8-bit
+ * value.
+ * During the roam scan, if there are no desired APs found in the partial
+ * frequency list, an immediate full scan on all the supported frequencies
+ * is initiated as a fallback. This full scan would add the 2.4/5/6 GHz
+ * frequencies, including all PSC frequencies by default. This attribute
+ * controls the inclusion of the 6 GHz PSC frequencies for the full scan
+ * as following.
+ * 1 - Full scan to include the supported 6 GHz PSC frequencies only on the
+ * prior discovery of any 6 GHz frequency support in the environment.
+ * This discovery can happen through a prior RNR, 11k neighbor
+ * request, 11v BTM request, host scan, etc.
+ * 0 - Default behavior. Full scan to include all the supported 6 GHz
+ * PSC frequencies regardless of whether 6 GHz BSSs have been
+ * discovered.
+ * The default behavior if this flag is not specified is to include all
+ * the supported 6 GHz PSC frequencies in the roam full scan.
*/
enum qca_vendor_attr_roam_control {
QCA_ATTR_ROAM_CONTROL_ENABLE = 1,
@@ -4236,6 +5219,25 @@
QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6,
QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7,
QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9,
+ QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11,
+ QCA_ATTR_ROAM_CONTROL_USER_REASON = 12,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16,
+ QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17,
+ QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18,
+ QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19,
+ QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20,
+ QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23,
+ QCA_ATTR_ROAM_CONTROL_LINKSPEED_THRESHOLD = 24,
+ QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX = 25,
+ QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ = 26,
+ QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY = 27,
/* keep last */
QCA_ATTR_ROAM_CONTROL_AFTER_LAST,
@@ -4258,14 +5260,14 @@
* ignored BSSIDs and accordingly clear the respective ones with the
* matching ID.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned
- * 32-bit value.Represents the number of whitelist SSIDs configured.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS: Unsigned
+ * 32-bit value. Represents the number of allowlist SSIDs configured.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute
- * to carry the list of Whitelist SSIDs.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST: Nested attribute
+ * to carry the list of allowlist SSIDs.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute,
- * 0..32 octets). Represents the white list SSID. Whitelist SSIDs
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID: SSID (binary attribute,
+ * 0..32 octets). Represents the allow list SSID. Allowlist SSIDs
* represent the list of SSIDs to which the firmware/driver can consider
* to roam to.
*
@@ -4303,7 +5305,7 @@
*
* @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit
* value. 1-Enable, 0-Disable. Represents "Lazy" mode, where
- * firmware is hunting for a better BSSID or white listed SSID even though
+ * firmware is hunting for a better BSSID or allow listed SSID even though
* the RSSI of the link is good. The parameters enabling the roaming are
* configured through the PARAM_A_BAND_XX attrbutes.
*
@@ -4345,10 +5347,10 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1,
QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2,
- /* Attributes for wifi_set_ssid_white_list */
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5,
+ /* Attributes for wifi_set_ssid_allow_list */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID = 5,
/* Attributes for set_roam_params */
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6,
@@ -4383,16 +5385,24 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
+
/*
* enum qca_wlan_vendor_roaming_subcmd: Referred by
* QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to
- * configure the white list SSIDs. These are configured through
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST: Sub command to
+ * configure the allow list SSIDs. These are configured through
* the following attributes.
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
*
* @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to
* configure the Roam params. These parameters are evaluated on the GScan
@@ -4408,7 +5418,7 @@
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID
* preference.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID: Sets the list of BSSIDs
* to ignore in roaming decision. Uses
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list.
*
@@ -4432,17 +5442,23 @@
*/
enum qca_wlan_vendor_roaming_subcmd {
QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST = 1,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID = 6,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID
+
enum qca_wlan_vendor_attr_gscan_config_params {
QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0,
@@ -4801,7 +5817,7 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
= 43,
/* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
- QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
= 44,
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45,
@@ -4809,10 +5825,10 @@
/* Unsigned 32-bit value; a GSCAN Capabilities attribute.
* This is used to limit the maximum number of BSSIDs while sending
* the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd
- * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute
+ * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID and attribute
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID.
*/
- QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46,
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID = 46,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST,
@@ -4820,6 +5836,12 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID
+
enum qca_wlan_vendor_attr_pno_config_params {
QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0,
/* Attributes for data used by
@@ -4949,6 +5971,8 @@
* current channel.
*/
QCA_WLAN_VENDOR_ACS_SELECT_REASON_JAMMER_INTERFERENCE,
+ /* Represents the reason that ACS triggered by AFC */
+ QCA_WLAN_VENDOR_ACS_SELECT_REASON_AFC_TRIGGER,
};
/**
@@ -5031,7 +6055,7 @@
/* HE 40 with extension channel below */
QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40MINUS = 1 << 30,
/* HE 40 intolerant */
- QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOL = 1 << 31,
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOL = 1U << 31,
};
/**
@@ -5117,6 +6141,22 @@
QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2 = 11,
/*
+ * Segment 0 in MHz (u32).
+ *
+ * For 20/40/80 MHz bandwidth, this indicates the channel center
+ * frequency index for the 20/40/80 MHz operating channel.
+ * For 160 MHz bandwidth, this indicates the channel center
+ * frequency of the primary 80 MHz channel.
+ * For 320 MHz bandwidth, indicates the channel center frequency
+ * of the primary 160 MHz channel.
+ *
+ * To maintain backward compatibility,
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
+ * is also maintained.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_0 = 12,
+ /* Legacy alias for the Segment 0 attribute.
+ *
* VHT segment 0 in MHz (u32) and the attribute is mandatory.
* Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes
* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
@@ -5134,9 +6174,25 @@
* is still used if either of the driver or user space application
* doesn't support the 6 GHz band.
*/
- QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 = 12,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 =
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_0,
/*
+ * Segment 1 in MHz (u32).
+ *
+ * For 20/40/80 MHz bandwidth, this is set to 0.
+ * For 160 MHz bandwidth, indicates the channel center frequency of the
+ * 160 MHz channel.
+ * For 320 MHz bandwidth, indicates the channel center frequency of the
+ * 320 MHz channel.
+ *
+ * To maintain backward compatibility,
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
+ * is also maintained.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_1 = 13,
+ /* Legacy alias for the Segment 1 attribute.
+ *
* VHT segment 1 in MHz (u32) and the attribute is mandatory.
* Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes
* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
@@ -5154,7 +6210,50 @@
* is still used if either of the driver or user space application
* doesn't support the 6 GHz band.
*/
- QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 = 13,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 =
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_1,
+
+ /*
+ * 16-bit attribute of bits indicating the AP power modes supported by
+ * the channel (u16).
+ * Note: Currently, only 3 bits are used in the attribute and each bit
+ * corresponds to the power mode mentioned in enum
+ * qca_wlan_vendor_external_acs_chan_power_mode and a given bit is
+ * set if the associated mode is supported.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_SUPP_POWER_MODES
+ = 14,
+ /* Array of nested attributes for each power mode. It takes attr as
+ * defined in enum
+ * qca_wlan_vendor_external_acs_event_chan_power_info_attr.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR = 15,
+ /*
+ * This indicates the overlapping 320 MHz center frequency in MHz
+ * (u32), if the given primary channel supports more than one
+ * 320 MHz channel bonding.
+ *
+ * Example:
+ * For 6 GHz, channel frequency 6115 MHz (channel number 33) segment 0
+ * center frequency (primary 160 MHz) is 6185 MHz and there can be two
+ * possible segment 2 frequencies for this (320 MHz center
+ * frequencies):
+ *
+ * 1) Center frequency 6105 MHz (channel 31): 320 MHz channel bonding
+ * from frequency 5945 MHz - 6265 MHz
+ * 2) Center frequency 6265 MHz (channel 63): 320 MHz channel bonding
+ * from frequency 6105 MHz - 6425 MHz
+ *
+ * In this case,
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_0 will
+ * return 6185 MHz.
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_SEG_1 will
+ * return 6105 MHz.
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_OVERLAP_SEG_1
+ * will return 6265 MHz.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_OVERLAP_SEG_1
+ = 16,
/* keep last */
QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST,
@@ -5163,6 +6262,56 @@
};
/**
+ * qca_wlan_vendor_external_acs_chan_power_mode - Specifies the valid
+ * values that the vendor external ACS channel power attribute
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE can
+ * take.
+ * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_LOW_POWER: Low power/Indoor mode
+ * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_STANDARD_POWER: Standard power mode
+ * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_VERY_LOW_POWER: Very low power mode
+ */
+enum qca_wlan_vendor_external_acs_chan_power_level {
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_LOW_POWER = 0,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_STANDARD_POWER = 1,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_VERY_LOW_POWER = 2,
+};
+
+/**
+ * qca_wlan_vendor_external_acs_event_chan_power_info_attr: Represents nested
+ * attributes for power mode type and power values corresponding to that.
+ * These attributes are sent as part of
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR.
+ */
+enum qca_wlan_vendor_external_acs_event_chan_power_info_attr {
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_INVALID = 0,
+ /*
+ * Power mode (u8) takes the values defined in enum
+ * qca_wlan_vendor_external_acs_chan_power_mode
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE
+ = 1,
+ /*
+ * Indicates if power value is a PSD/EIRP value (flag). If flag is
+ * present, it indicates a PSD value.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_PSD_FLAG = 2,
+ /*
+ * Power value (u32) PSD/EIRP as indicated by
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_PSD_FLAG,
+ * for power mode corresponding to the
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE.
+ * Units for PSD - dBm/MHz
+ * Units for EIRP - dBm
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_VALUE
+ = 3,
+ /* keep last */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_LAST,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_MAX =
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_LAST - 1,
+};
+
+/**
* qca_wlan_vendor_attr_pcl: Represents attributes for
* preferred channel list (PCL). These attributes are sent as part of
* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL and
@@ -5186,6 +6335,10 @@
* bit 3 set: channel should be excluded in GO negotiation
*/
QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_PCL_LAST,
+ QCA_WLAN_VENDOR_ATTR_PCL_MAX = QCA_WLAN_VENDOR_ATTR_PCL_LAST - 1
};
/**
@@ -5248,6 +6401,10 @@
* qca_wlan_vendor_attr_rropavail_info.
*/
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14,
+ /* Flag attribute to indicate if driver supports 6 GHz AFC trigger
+ * for External ACS
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AFC_CAPABILITY = 15,
/* keep last */
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
@@ -5350,6 +6507,11 @@
* VHT seg1 channel frequency in MHz
* Note: If user-space application has no support of the 6 GHz band, this
* attribute is optional.
+ * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_PUNCTURE_BITMAP: Required (u16)
+ * Puncture Bitmap for selected primary channel. Optional if no support
+ * for EHT (IEEE 802.11be). Encoding for this attribute follows the
+ * convention used in the Disabled Subchannel Bitmap field of the EHT Operation
+ * element.
*/
enum qca_wlan_vendor_attr_external_acs_channels {
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0,
@@ -5385,6 +6547,7 @@
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY = 11,
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0 = 12,
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1 = 13,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_PUNCTURE_BITMAP = 14,
/* keep last */
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST,
@@ -5843,6 +7006,20 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29,
+ /* This attribute specifies the bandwidth to be used for spectral scan
+ * operation. This is an u8 attribute and uses the values in enum
+ * nl80211_chan_width. This is an optional attribute.
+ * If this attribute is not populated, the driver should configure the
+ * spectral scan bandwidth to the maximum value supported by the target
+ * for the current operating bandwidth.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30,
+ /* Spectral FFT recapture flag attribute, to enable FFT recapture.
+ * Recapture can only be enabled for scan period greater than 52 us.
+ * If this attribute is enabled, re-triggers will be enabled when AGC
+ * gain changes.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE = 31,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -5953,6 +7130,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18,
+ /* Flag attribute to indicate agile spectral scan capability
+ * for 320 MHz mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19,
+ /* Number of spectral detectors used for scan in 320 MHz.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
@@ -6135,6 +7320,16 @@
* the FW on a specific VDEV.
*/
QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22,
+ /* WMI sequence mismatch between WMI command and Tx completion */
+ QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23,
+ /* Write to Device HAL register failed */
+ QCA_WLAN_HANG_REG_WRITE_FAILURE = 24,
+ /* No credit left to send the wow_wakeup_from_sleep to firmware */
+ QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25,
+ /* Bus failure */
+ QCA_WLAN_HANG_BUS_FAILURE = 26,
+ /* tasklet/credit latency found */
+ QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27,
};
/**
@@ -6160,6 +7355,28 @@
};
/**
+ * enum qca_wlan_vendor_flush_pending_policy: Represents values for
+ * the policy to flush pending frames, configured via
+ * %QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING. This enumeration defines the
+ * valid values for %QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY.
+ *
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE: This value clears all
+ * the flush policy configured before. This command basically disables the
+ * flush config set by the user.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE: This value configures
+ * the flush policy to be immediate. All pending packets for the peer/TID are
+ * flushed when this command/policy is received.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END: This value configures
+ * the flush policy to the end of TWT SP. All pending packets for the peer/TID
+ * are flushed when the end of TWT SP is reached.
+ */
+enum qca_wlan_vendor_flush_pending_policy {
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE = 0,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE = 1,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_flush_pending - Attributes for
* flushing pending traffic in firmware.
*
@@ -6167,12 +7384,25 @@
* @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending
* packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK,
* AC_VI, AC_VO respectively. Set the corresponding bit to 1 to
- * flush packets with access category.
+ * flush packets with access category. This is optional. See below.
+ * @QCA_WLAN_VENDOR_ATTR_TID_MASK: Configure TID mask of the pending packets.
+ * It is a u32 value with bit 0-7 representing TID 0-7. Set corresponding
+ * bit to 1 to act upon the TID. This is optional. Either this attribute or
+ * %QCA_WLAN_VENDOR_ATTR_AC must be provided. If both are provided,
+ * %QCA_WLAN_VENDOR_ATTR_TID_MASK takes precedence. If neither are provided
+ * it is an error.
+ * @QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY: Policy of flushing the pending
+ * packets corresponding to the peer/TID provided. It is a u32 value,
+ * represented by %enum qca_wlan_vendor_flush_pending_policy. This
+ * value is honored only when TID mask is provided. This is not honored when AC
+ * mask is provided.
*/
enum qca_wlan_vendor_attr_flush_pending {
QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1,
QCA_WLAN_VENDOR_ATTR_AC = 2,
+ QCA_WLAN_VENDOR_ATTR_TID_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
@@ -6289,10 +7519,11 @@
*
* @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
* Default WLAN operation level which throughput orientated.
- * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
- * Use moderate level to improve latency by limit scan duration.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
+ * Use XR level to benefit XR (extended reality) application to achieve
+ * latency and power by via constraint scan/roaming/adaptive PS.
* @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
- * Use low latency level to benifit application like concurrent
+ * Use low latency level to benefit application like concurrent
* downloading or video streaming via constraint scan/adaptive PS.
* @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
* Use ultra low latency level to benefit for gaming/voice
@@ -6301,7 +7532,10 @@
enum qca_wlan_vendor_attr_config_latency_level {
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1,
- QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR = 2,
+ /* legacy name */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
@@ -6613,6 +7847,14 @@
* 1:support 0:not support
*/
QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30,
+ /* As per Wi-Fi Aware Specification v3.2 Service Id is the first
+ * 48 bits of the SHA-256 hash of the Service Name.
+ * A lower-case representation of the Service Name shall be used to
+ * calculate the Service ID.
+ * Array of u8: length is 6 bytes
+ * This attribute is used and optional for ndp indication.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_ID = 31,
/* keep last */
QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST,
@@ -6622,9 +7864,24 @@
enum qca_wlan_ndp_sub_cmd {
QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0,
- /* Command to create a NAN data path interface */
+ /* Command to create a NAN data path interface.
+ * This command was initially designed to both create and start a NAN
+ * data path interface. However, changes to Linux 5.12 no longer allow
+ * interface creation via vendor commands. When the driver advertises
+ * QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI
+ * userspace must explicitly first create the interface using
+ * NL80211_CMD_NEW_INTERFACE before subsequently invoking this command
+ * to start the interface.
+ */
QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1,
- /* Command to delete a NAN data path interface */
+ /* Command to delete a NAN data path interface.
+ * This command was initially designed to both stop and delete a NAN
+ * data path interface. However, changes to Linux 5.12 no longer allow
+ * interface deletion via vendor commands. When the driver advertises
+ * QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI
+ * userspace must explicitly delete the interface using
+ * NL80211_CMD_DEL_INTERFACE after calling this command.
+ */
QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2,
/* Command to initiate a NAN data path session */
QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3,
@@ -6801,8 +8058,9 @@
/**
* enum qca_wlan_vendor_thermal_level - Defines various thermal levels
- * configured by userspace to the driver/firmware. The values will be
- * encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL attribute.
+ * configured by userspace to the driver/firmware.
+ * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute.
* The driver/firmware takes actions requested by userspace such as throttling
* wifi TX etc. in order to mitigate high temperature.
*
@@ -6836,8 +8094,9 @@
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1,
/* Userspace uses this attribute to configure thermal level to the
- * driver/firmware. Used in request, u32 attribute, possible values
- * are defined in enum qca_wlan_vendor_thermal_level.
+ * driver/firmware, or get thermal level from the driver/firmware.
+ * Used in request or response, u32 attribute,
+ * possible values are defined in enum qca_wlan_vendor_thermal_level.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2,
/* Userspace uses this attribute to configure the time in which the
@@ -6850,6 +8109,15 @@
* there is any critical ongoing operation.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3,
+ /* Nested attribute, the driver/firmware uses this attribute to report
+ * thermal statistics of different thermal levels to userspace when
+ * requested using the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command
+ * type. This attribute contains a nested array of records of thermal
+ * statistics of multiple levels. The attributes used inside this nested
+ * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
@@ -6875,6 +8143,16 @@
* resume action.
* @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to
* the driver/firmware.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current
+ * thermal level from the driver/firmware. The driver should respond with a
+ * thermal level defined in enum qca_wlan_vendor_thermal_level.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the
+ * current thermal statistics from the driver/firmware. The driver should
+ * respond with statistics of all thermal levels encapsulated in the attribute
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear
+ * the current thermal statistics for all thermal levels maintained in the
+ * driver/firmware and start counting from zero again.
*/
enum qca_wlan_vendor_attr_thermal_cmd_type {
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
@@ -6882,6 +8160,9 @@
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS,
};
/**
@@ -6964,6 +8245,11 @@
* NLA_FLAG attribute.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE,
+ /* Thermal level from the driver.
+ * u32 attribute. Possible values are defined in
+ * enum qca_wlan_vendor_thermal_level.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST,
@@ -6972,6 +8258,35 @@
};
/**
+ * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes
+ * to get thermal status from the driver/firmware.
+ * enum values are used for NL attributes encapsulated inside the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute.
+ *
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each
+ * thermal level in milliseconds. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number
+ * of times the temperature crossed into the temperature range defined by the
+ * thermal level from both higher and lower directions. u32 size.
+ */
+enum qca_wlan_vendor_attr_thermal_stats {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST - 1,
+};
+
+/**
* enum he_fragmentation_val - HE fragmentation support values
* Indicates level of dynamic fragmentation that is supported by
* a STA as a recipient.
@@ -7130,6 +8445,21 @@
};
/**
+ * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration
+ *
+ * Indicates the frame types to use for keep alive data.
+ *
+ * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive.
+ */
+enum qca_wlan_keep_alive_data_type {
+ QCA_WLAN_KEEP_ALIVE_DEFAULT = 0,
+ QCA_WLAN_KEEP_ALIVE_DATA = 1,
+ QCA_WLAN_KEEP_ALIVE_MGMT = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
* HE operating mode control transmit request. These attributes are
* sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
@@ -7577,6 +8907,150 @@
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43,
+ /* 8-bit unsigned value to configure the driver/firmware to start or
+ * stop transmitting FILS discovery frames.
+ * 0 - Stop transmitting FILS discovery frames
+ * 1 - Start transmitting FILS discovery frames
+ * This attribute is used to configure the testbed device.
+ * This attribute can be configured only in AP mode and the
+ * configuration is valid until AP restart.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable full bandwidth UL MU-MIMO subfield
+ * 1 - Enable full bandwidth UL MU-MIMO subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45,
+
+ /* 16-bit unsigned value to configure the driver with a specific BSS
+ * max idle period to advertise in the BSS Max Idle Period element
+ * (IEEE Std 802.11-2016, 9.4.2.79) in (Re)Association Request frames.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD = 46,
+
+ /* 8-bit unsigned value to configure the driver to use only RU 242 tone
+ * for data transmission.
+ * 0 - Default behavior, 1 - Configure RU 242 tone for data Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX = 47,
+
+ /* 8-bit unsigned value to configure the driver to disable data and
+ * management response frame transmission to test the BSS max idle
+ * feature.
+ * 0 - Default behavior, 1 - Disable data and management response Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX = 48,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Punctured Preamble Rx subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable Punctured Preamble Rx subfield
+ * 1 - Enable Punctured Preamble Rx subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49,
+
+ /* 8-bit unsigned value to configure the driver to ignore the SAE H2E
+ * requirement mismatch for 6 GHz connection.
+ * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50,
+
+ /* 8-bit unsigned value to configure the driver to allow 6 GHz
+ * connection with all security modes.
+ * 0 - Default behavior, 1 - Allow 6 GHz connection with all security
+ * modes.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51,
+
+ /* 8-bit unsigned value to configure the driver to transmit data with
+ * ER SU PPDU type.
+ *
+ * 0 - Default behavior, 1 - Enable ER SU PPDU type TX.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52,
+
+ /* 8-bit unsigned value to configure the driver to use Data or
+ * Management frame type for keep alive data.
+ * Uses enum qca_wlan_keep_alive_data_type values.
+ *
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+
+ /* 8-bit unsigned value to configure the driver to use scan request
+ * BSSID value in Probe Request frame RA(A1) during the scan. The
+ * driver saves this configuration and applies this setting to all user
+ * space scan requests until the setting is cleared. If this
+ * configuration is set, the driver uses the BSSID value from the scan
+ * request to set the RA(A1) in the Probe Request frames during the
+ * scan.
+ *
+ * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+ * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * BSS max idle period support.
+ *
+ * 0 - Disable the BSS max idle support.
+ * 1 - Enable the BSS max idle support.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Rx control frame to MultiBSS subfield in the HE MAC
+ * capabilities information field.
+ * 0 - Disable Rx control frame to MultiBSS subfield
+ * 1 - Enable Rx control frame to MultiBSS subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Broadcast TWT support subfield in the HE MAC capabilities
+ * information field.
+ * 0 - Disable Broadcast TWT support subfield
+ * 1 - Enable Broadcast TWT support subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57,
+
+ /* 8-bit unsigned value to configure the driver/firmware to allow eMLSR
+ * mode for IEEE 802.11be MLO capable devices. If the attribute is set
+ * to 1, and if the firmware supports this capability too, the STA
+ * advertises this capability to the AP over Association Request frame.
+ * This attribute will not have any effect on legacy devices with no
+ * IEEE 802.11be support.
+ * 0 - Default behavior
+ * 1 - Enable eMLSR (Enhanced Multi-link Single-Radio) mode
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE = 58,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * periodic sounding for Tx beamformer functionality. The default
+ * behavior uses algorithm to do sounding based on packet stats.
+ *
+ * 0 - Default behavior.
+ * 1 - Enable the periodic sounding for Tx beamformer.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING = 59,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -7586,26 +9060,78 @@
/**
* enum qca_wlan_twt_operation - Operation of the config TWT request
* Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION.
+ * The response for the respective operations can be either synchronous or
+ * asynchronous (wherever specified). If synchronous, the response to this
+ * operation is obtained in the corresponding vendor command reply to the user
+ * space. For the asynchronous case the response is obtained as an event with
+ * the same operation type.
+ *
+ * Drivers shall support either of these modes but not both simultaneously.
+ * This support for asynchronous mode is advertised through the flag
+ * QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT. If this flag is not advertised,
+ * the driver shall support synchronous mode.
*
* @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured
* through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. Depending upon the
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, this is either a
+ * synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. This is a synchronous operation.
*
* @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * This terminate can either get triggered by the user space or can as well be
+ * a notification from the firmware if it initiates a terminate.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * the request from user space can either be a synchronous or asynchronous
+ * operation.
*
* @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * this is either a synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are
* configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup.
+ * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE
+ * request. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a
+ * combination of suspend and resume in a single request. Required parameters
+ * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the
+ * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is
+ * setup. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information.
+ * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT
+ * session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information.
+ * Valid only after the TWT session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its
+ * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous
+ * operation.
+ *
+ * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmware is
+ * ready for a new TWT session setup after it issued a TWT teardown.
+ *
+ * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required
+ * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer
+ * the enum qca_wlan_vendor_attr_twt_set_param.
+ *
+ * @QCA_WLAN_TWT_NOTIFY: Used to notify userspace about changes in TWT
+ * related information for example TWT required bit in AP capabilities etc.
+ * The reason for the notification is sent using
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS.
*/
enum qca_wlan_twt_operation {
QCA_WLAN_TWT_SET = 0,
@@ -7613,6 +9139,13 @@
QCA_WLAN_TWT_TERMINATE = 2,
QCA_WLAN_TWT_SUSPEND = 3,
QCA_WLAN_TWT_RESUME = 4,
+ QCA_WLAN_TWT_NUDGE = 5,
+ QCA_WLAN_TWT_GET_STATS = 6,
+ QCA_WLAN_TWT_CLEAR_STATS = 7,
+ QCA_WLAN_TWT_GET_CAPABILITIES = 8,
+ QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9,
+ QCA_WLAN_TWT_SET_PARAM = 10,
+ QCA_WLAN_TWT_NOTIFY = 11,
};
/**
@@ -7626,13 +9159,20 @@
*
* @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the
* parameters configured for TWT. These parameters are represented by
- * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume
- * based on the operation.
+ * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume,
+ * enum qca_wlan_vendor_attr_twt_set_param, or
+ * enum qca_wlan_vendor_attr_twt_stats based on the operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS: Size is u8, mandatory when
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to QCA_WLAN_TWT_NOTIFY.
+ * The values used by this attribute are defined in
+ * enum qca_wlan_vendor_twt_status.
*/
enum qca_wlan_vendor_attr_config_twt {
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1,
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS = 3,
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST,
@@ -7788,6 +9328,19 @@
};
/**
+ * qca_wlan_twt_setup_state: Represents the TWT session states.
+ *
+ * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established.
+ * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active.
+ * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state.
+ */
+enum qca_wlan_twt_setup_state {
+ QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0,
+ QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1,
+ QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_twt_setup: Represents attributes for
* TWT (Target Wake Time) setup request. These attributes are sent as part of
* %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and
@@ -7837,6 +9390,14 @@
* 2. TWT GET Request and Response
* 3. TWT TERMINATE Request and Response
* 4. TWT SUSPEND Request and Response
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions for the following
+ * 1. TWT TERMINATE Request and Response
+ * 2. TWT SUSPEND Request and Response
+ * 4. TWT CLEAR STATISTICS request
+ * 5. TWT GET STATISTICS request and response
+ * If an invalid dialog ID is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8)
* This attribute (exp) is used along with the mantissa to derive the
@@ -7887,6 +9448,7 @@
* 2. TWT TERMINATE Response
* 3. TWT SUSPEND Response
* 4. TWT RESUME Response
+ * 5. TWT NUDGE Response
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8)
* This field is applicable for TWT response only.
@@ -7896,9 +9458,13 @@
* response.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64)
- * This field is applicable for TWT response only.
- * This field contains absolute TSF value of the wake time received
- * from the TWT responder and is passed to the userspace.
+ * In TWT setup command this field contains absolute TSF that will
+ * be used by TWT requester during setup.
+ * In TWT response this field contains absolute TSF value of the
+ * wake time received from the TWT responder and is passed to
+ * the userspace.
+ * This is an optional parameter for
+ * 1. TWT SET Request
* This is a required parameter for
* 1. TWT SET Response
* 2. TWT GET Response
@@ -7915,14 +9481,87 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer for which the TWT session
* is being configured. This is used in AP mode to represent the respective
- * client. In AP mode, this is an optional parameter for response and is
- * a required parameter for
- * 1. TWT SET Request
- * 2. TWT GET Request
- * 3. TWT TERMINATE Request
- * 4. TWT SUSPEND Request
+ * client.
+ * In AP mode, this is a required parameter in response for
+ * 1. TWT SET
+ * 2. TWT GET
+ * 3. TWT TERMINATE
+ * 4. TWT SUSPEND
* In STA mode, this is an optional parameter in request and response for
* the above four TWT operations.
+ * In AP mode, this is a required parameter in request for
+ * 1. TWT GET
+ * 2. TWT TERMINATE
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32)
+ * Minimum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32)
+ * Maximum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32)
+ * Minimum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32)
+ * Maximum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32)
+ * TWT state for the given dialog id. The values for this are represented
+ * by enum qca_wlan_twt_setup_state.
+ * This is obtained through TWT GET operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The unit is microseconds. This attribute, when specified, takes
+ * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA.
+ * This parameter is used for
+ * 1. TWT SET Request and Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
+ * This attribute is used to configure Broadcast TWT ID.
+ * The Broadcast TWT ID indicates a specific Broadcast TWT for which the
+ * transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
+ * This parameter is used for
+ * 1. TWT SET Request
+ * 2. TWT TERMINATE Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
+ * This attribute is used to configure Broadcast TWT recommendation.
+ * The Broadcast TWT Recommendation subfield contains a value that indicates
+ * recommendations on the types of frames that are transmitted by TWT
+ * scheduled STAs and scheduling AP during the broadcast TWT SP.
+ * The allowed values are 0 - 3.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
+ * This attribute is used to configure Broadcast TWT Persistence.
+ * The Broadcast TWT Persistence subfield indicates the number of
+ * TBTTs during which the Broadcast TWT SPs corresponding to this
+ * broadcast TWT Parameter set are present. The number of beacon intervals
+ * during which the Broadcast TWT SPs are present is equal to the value in the
+ * Broadcast TWT Persistence subfield plus 1 except that the value 255
+ * indicates that the Broadcast TWT SPs are present until explicitly terminated.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8)
+ * This attribute contains the value of the Responder PM Mode subfield (0 or 1)
+ * from TWT response frame.
+ * This parameter is used for
+ * 1. TWT SET Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32)
+ * This attribute is used to configure the announce timeout value (in us) in
+ * the firmware. This timeout value is only applicable for the announced TWT. If
+ * the timeout value is non-zero the firmware waits up to the timeout value to
+ * use Data frame as an announcement frame. If the timeout value is 0 the
+ * firmware sends an explicit QoS NULL frame as the announcement frame on SP
+ * start. The default value in the firmware is 0.
+ * This parameter is used for
+ * 1. TWT SET Request
*/
enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@@ -7944,6 +9583,20 @@
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
@@ -7971,6 +9624,34 @@
* @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request
* @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an
* unknown reason
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in
+ * suspend state
+ * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to
+ * invalid IE in the received TWT frame
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from
+ * the responder are not in the specified range
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to request from the responder. Used on the TWT_TERMINATE
+ * notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to roaming. Used on the TWT_TERMINATE notification from the
+ * firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
+ * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
+ * Concurrency). Used on the TWT_TERMINATE notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
+ * request due to roaming in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
+ * setup request due to channel switch in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup
+ * request due to scan in progress.
+ * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to
+ * terminate an existing TWT session on power save exit request from userspace.
+ * Used on the TWT_TERMINATE notification from the driver/firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_REQUIRED: The peer has set the TWT
+ * required bit in its capabilities.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED: The peer has cleared
+ * the TWT required bit(1->0) in its capabilities.
*/
enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@@ -7986,6 +9667,18 @@
QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10,
QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11,
QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12,
+ QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13,
+ QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14,
+ QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
+ QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
+ QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21,
+ QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22,
+ QCA_WLAN_VENDOR_TWT_STATUS_TWT_REQUIRED = 23,
+ QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED = 24,
};
/**
@@ -8012,6 +9705,10 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8).
* Flow ID is the unique identifier for each TWT session. This attribute
* represents the respective TWT session to resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer to which TWT Resume is
@@ -8034,6 +9731,240 @@
};
/**
+ * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for
+ * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend
+ * and resume in a single request. These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session to suspend and resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request
+ * and response.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32)
+ * This attribute is used as the SP offset which is the offset from
+ * TSF after which the wake happens. The units are in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32)
+ * This attribute represents the next TWT subfield size.
+ * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits,
+ * and 4 for 64 bits.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer to which TWT Suspend and Resume is
+ * being sent. This is used in AP mode to represent the respective
+ * client and is a required parameter. In STA mode, this is an optional
+ * parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64)
+ * This field contains absolute TSF value of the time at which the TWT
+ * session will be resumed.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_SP_START_OFFSET: Optional (s32)
+ * This field will be used when device supports Flexible TWT.
+ * This field contains an offset value by which to shift the starting time
+ * of the next service period. The value of offset can be negative or positive.
+ * If provided, this attribute will override
+ * QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME. The units are in microseconds.
+ *
+ */
+enum qca_wlan_vendor_attr_twt_nudge {
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_SP_START_OFFSET = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for
+ * TWT (Target Wake Time) get statistics and clear statistics request.
+ * These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session for get and clear TWT statistics.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which TWT Statistics
+ * is required.
+ * In AP mode this is used to represent the respective
+ * client and is a required parameter for
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request and response
+ * In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32)
+ * This is the duration of the service period in microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32)
+ * Average of the actual wake duration observed so far. Unit is microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32)
+ * The number of TWT service periods elapsed so far.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32)
+ * This is the minimum value of the wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32)
+ * This is the maximum value of wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32)
+ * Average number of MPDUs transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32)
+ * Average number of MPDUs received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32)
+ * Average number of bytes transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32)
+ * Average number of bytes received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32)
+ * Status of the TWT GET STATISTICS request.
+ * This contains status values in enum qca_wlan_vendor_twt_status
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ */
+enum qca_wlan_vendor_attr_twt_stats {
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities
+ * supported by the device and the peer.
+ * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by
+ * TWT non-scheduling STA. This capability is advertised in the HE
+ * Capability/Extended Capabilities information element in the
+ * Association Request frame by the device.
+ *
+ * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by
+ * the TWT scheduling AP. This capability is advertised in the Extended
+ * Capabilities/HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support
+ * for the broadcast TWT functionality. On the responder side, this indicates
+ * support for the role of broadcast TWT scheduling functionality. This
+ * capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule.
+ * This capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate
+ * that it mandates the associated HE STAs to support TWT. This capability is
+ * advertised by AP in the HE Operation Parameters field of the HE Operation
+ * information element.
+ */
+enum qca_wlan_twt_capa {
+ QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0),
+ QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1),
+ QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2),
+ QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3),
+ QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT
+ * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT
+ * operation.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which the TWT capabilities
+ * are being queried. This is used in AP mode to represent the respective
+ * client. In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16).
+ * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16).
+ * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ */
+enum qca_wlan_vendor_attr_twt_capability {
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for
+ * TWT (Target Wake Time) related parameters. It is used when
+ * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM.
+ * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8)
+ * This attribute configures AC parameters to be used for all TWT
+ * sessions in AP mode.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+enum qca_wlan_vendor_attr_twt_set_param {
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1,
+};
+
+/**
* enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by
* the TWT responder
*
@@ -8124,6 +10055,22 @@
};
/**
+ * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data
+ * transport modes and is used by the attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data.
+ * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR
+ * data. The data shall be encapsulated within
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event.
+ */
+enum qca_wlan_vendor_cfr_data_transport_modes {
+ QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0,
+ QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1,
+};
+
+/**
* enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
* attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
* command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
@@ -8313,6 +10260,27 @@
* MAC for CFR capture. This is a bitmask in which each bit represents the
* corresponding Data frame subtype value per IEEE Std 802.11-2016,
* 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8)
+ * Userspace can use this attribute to specify the driver about which transport
+ * mode shall be used by the driver to send CFR data to userspace. Uses values
+ * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is
+ * not present, the driver shall use the default transport mechanism which is
+ * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32)
+ * Userspace can use this attribute to specify the nl port id of the application
+ * which receives the CFR data and processes it further so that the drivers can
+ * unicast the netlink events to a specific application. Optionally included
+ * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to
+ * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers
+ * shall multicast the netlink events when this attribute is not included.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY).
+ * This attribute will be used by the driver to encapsulate and send CFR data
+ * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an
+ * asynchronous event when the driver is configured to send CFR data using
+ * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS.
*/
enum qca_wlan_vendor_peer_cfr_capture_attr {
QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
@@ -8341,6 +10309,9 @@
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28,
/* Keep last */
QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
@@ -8562,7 +10533,6 @@
* has priority over BT_A2DP and ZB_HIGH.
* 3: BT_A2DP has priority over ZB_HIGH.
*/
-
enum qca_vendor_attr_coex_config_three_way {
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0,
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1,
@@ -9027,20 +10997,48 @@
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
* Nested attribute containing multiple ranges with following attributes:
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
* Starting center frequency in MHz.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
* Ending center frequency in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
+ * s32 attribute, optional. It is a per frequency range attribute.
+ * The maximum TX power limit from user space is to be applied on an
+ * unrestricted interface for corresponding frequency range. It is also
+ * possible that the actual TX power may be even lower than this cap due to
+ * other considerations such as regulatory compliance, SAR, etc. In absence of
+ * this attribute the driver shall follow current behavior which means
+ * interface (SAP/P2P) function can keep operating on an unsafe channel with TX
+ * power derived by the driver based on regulatory/SAR during interface up.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
+ * u32 attribute, optional. Indicates all the interface types which are
+ * restricted for all frequency ranges provided in
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * This attribute encapsulates bitmasks of interface types defined in
+ * enum nl80211_iftype. If an interface is marked as restricted the driver must
+ * move to a safe channel and if no safe channel is available the driver shall
+ * terminate that interface functionality. In absence of this attribute,
+ * interface (SAP/P2P) can still continue operating on an unsafe channel with
+ * TX power limit derived from either
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
+ * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
+ * is not provided.
*/
enum qca_wlan_vendor_attr_avoid_frequency_ext {
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -9072,14 +11070,21 @@
* These values are used by attribute %QCA_VENDOR_ATTR_BTC_CHAIN_MODE of
* %QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE.
*
- * @QCA_BTC_CHAIN_SHARED: chains of BT and WLAN 2.4G are shared.
- * @QCA_BTC_CHAIN_SEPARATED: chains of BT and WLAN 2.4G are separated.
+ * @QCA_BTC_CHAIN_SHARED: chains of BT and WLAN 2.4 GHz are shared.
+ * @QCA_BTC_CHAIN_SEPARATED_HYBRID: chains of BT and WLAN 2.4 GHz are
+ * separated, hybrid mode.
+ * @QCA_BTC_CHAIN_SEPARATED_FDD: chains of BT and WLAN 2.4 GHz are
+ * separated, fixed FDD mode.
*/
enum qca_btc_chain_mode {
QCA_BTC_CHAIN_SHARED = 0,
- QCA_BTC_CHAIN_SEPARATED = 1,
+ QCA_BTC_CHAIN_SEPARATED_HYBRID = 1,
+ QCA_BTC_CHAIN_SEPARATED_FDD = 2,
};
+/* deprecated legacy name */
+#define QCA_BTC_CHAIN_SEPARATED QCA_BTC_CHAIN_SEPARATED_HYBRID
+
/**
* enum qca_vendor_attr_btc_chain_mode - Specifies attributes for BT coex
* chain mode.
@@ -9366,7 +11371,68 @@
* @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode
* only. This represents number of Beacon frames received from this station with
* the packet number less than or equal to the last received packet number when
- * beacon protection is enabled.
+ * beacon protection is enabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in
+ * STA mode only. The driver uses this attribute to populate the connection
+ * failure reason codes and the values are defined in
+ * enum qca_sta_connect_fail_reason_codes. Userspace applications can send
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving
+ * a connection failure indication from the driver. The driver shall not
+ * include this attribute in response to the
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection
+ * failure observed in the last attempted connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE: u32, latest TX rate (Kbps)
+ * used by the station in its last TX frame while communicating to the AP in the
+ * connected state. When queried in the disconnected state, this represents the
+ * rate used by the STA in the last TX frame to the AP when it was connected.
+ * This attribute is used for STA mode only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX: u32, used in STA mode only.
+ * This represents the rate index used by the STA for the last TX frame to the
+ * AP. When queried in the disconnected state, this gives the last RIX used by
+ * the STA in the last TX frame to the AP when it was connected.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT: u32, used in STA
+ * mode only. This represents the number of times the STA TSF goes out of sync
+ * from the AP after the connection. If queried in the disconnected state, this
+ * gives the count of TSF out of sync for the last connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. This can be queried either in connected state or
+ * disconnected state. Each bit of this attribute represents the different
+ * roam trigger reason code which are defined in enum qca_vendor_roam_triggers.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON: u32, used in STA mode
+ * only. This represents the roam fail reason for the last failed roaming
+ * attempt by the firmware. Different roam failure reason codes are specified
+ * in enum qca_vendor_roam_fail_reasons. This can be queried either in
+ * connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
+ * queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_TX_PACKETS: Array of u32 nested
+ * values, used in AP mode. This represents the MPDU packet count per MCS
+ * rate value of TX packets. Every index of this nested attribute corresponds
+ * to MCS index, e.g., Index 0 represents MCS0 TX rate. This can be
+ * queried in connected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_RX_PACKETS: Array of u32 nested
+ * values, used in AP mode. This represents the MPDU packet count per MCS
+ * rate value of RX packets. Every index of this nested attribute corresponds
+ * to MCS index, e.g., Index 0 represents MCS0 RX rate. This can be
+ * queried in connected state.
*/
enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -9412,6 +11478,16 @@
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE = 44,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX = 45,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT = 46,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_TX_PACKETS = 51,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_RX_PACKETS = 52,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
@@ -9842,4 +11918,2364 @@
QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL:
+ * u8 attribute. Notify the TX VDEV status. Possible values 0, 1
+ * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV,
+ * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT:
+ * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID:
+ * u8 attribute, required. Indicates group id of Tx VDEV.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * group information. The attributes defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info
+ * are nested in this attribute.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_status {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX:
+ * u32 attribute, required. Contains interface index.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS:
+ * u8 attribute, required. 0 - means vdev is in down state.
+ * 1 - means vdev is in up state.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary
+ * STA interface has to be given while selecting the connection policies
+ * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface.
+ * An interface is set as primary through the attribute
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not
+ * applicable if the primary interface has not been set earlier.
+ *
+ * The intention is not to downgrade the primary STA performance, such as:
+ * - Do not reduce the number of TX/RX chains of primary connection.
+ * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of
+ * chains.
+ * - If using MCC, should set the MCC duty cycle of the primary connection to
+ * be higher than the secondary connection.
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the
+ * subsequent STA connection shall be chosen to balance with the existing
+ * concurrent STA's performance.
+ * Such as
+ * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware
+ * capability.
+ * - If using MCC, set the MCC duty cycle of the primary connection to be equal
+ * to the secondary.
+ * - Prefer BSSID candidates which will help provide the best "overall"
+ * performance for all the STA connections.
+ */
+enum qca_wlan_concurrent_sta_policy_config {
+ QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0,
+ QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_ap_policy_config - Concurrent AP policies
+ *
+ * @QCA_WLAN_CONCURRENT_AP_POLICY_UNSPECIFIED: No specific policy for this AP
+ * interface.
+ *
+ * @QCA_WLAN_CONCURRENT_AP_POLICY_GAMING_AUDIO: Select interface concurrencies
+ * to meet gaming audio latency requirements.
+ *
+ * @QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING: Select interface
+ * concurrencies to meet lossless audio streaming requirements.
+ */
+enum qca_wlan_concurrent_ap_policy_config {
+ QCA_WLAN_CONCURRENT_AP_POLICY_UNSPECIFIED = 0,
+ QCA_WLAN_CONCURRENT_AP_POLICY_GAMING_AUDIO = 1,
+ QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_concurrent_policy - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG:
+ * u8 attribute. Configures the concurrent STA policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config.
+
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG:
+ * u8 attribute. Configures the concurrent AP policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_ap_policy_config.
+ */
+enum qca_wlan_vendor_attr_concurrent_policy {
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG = 1,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AFTER_LAST - 1,
+
+};
+
+/* Compatibility defines for previously used enum
+ * qca_wlan_vendor_attr_concurrent_policy names. These values should not be used
+ * in any new implementation.
+ */
+#define QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG \
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG
+#define QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX \
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX
+#define qca_wlan_vendor_attr_concurrent_sta_policy \
+ qca_wlan_vendor_attr_concurrent_policy
+
+/**
+ * enum qca_sta_connect_fail_reason_codes - Defines values carried
+ * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor
+ * attribute.
+ * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received
+ * for unicast Probe Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for
+ * auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not
+ * received from AP.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response
+ * frame is not received from AP.
+ */
+enum qca_sta_connect_fail_reason_codes {
+ QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
+};
+
+/**
+ * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different
+ * filters defined in this enum are used in attribute
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK.
+ *
+ * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver
+ * shall filter the channels which are not usable because of coexistence with
+ * cellular radio.
+ * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver
+ * shall filter the channels which are not usable because of existing active
+ * interfaces in the driver and will result in Multi Channel Concurrency, etc.
+ *
+ */
+enum qca_wlan_vendor_usable_channels_filter {
+ QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0,
+ QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_chan_info - Attributes used inside
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ:
+ * u32 attribute, required. Indicates the center frequency of the primary
+ * channel in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ:
+ * u32 attribute. Indicates the center frequency of the primary segment of the
+ * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz,
+ * 160 MHz, and 320 MHz channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ:
+ * u32 attribute. Indicates the center frequency of the secondary segment of
+ * 80+80 channel in MHz. This attribute is required only when
+ * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH:
+ * u32 attribute, required. Indicates the bandwidth of the channel, possible
+ * values are defined in enum nl80211_chan_width.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK:
+ * u32 attribute, required. Indicates all the interface types for which this
+ * channel is usable. This attribute encapsulates bitmasks of interface types
+ * defined in enum nl80211_iftype.
+ *
+ */
+enum qca_wlan_vendor_attr_chan_info {
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_usable_channels - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK:
+ * u32 attribute. Indicates the bands from which the channels should be reported
+ * in response. This attribute encapsulates bit masks of bands defined in enum
+ * nl80211_band. Optional attribute, if not present in the request the driver
+ * shall return channels from all supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK:
+ * u32 attribute. Indicates all the interface types for which the usable
+ * channels information is requested. This attribute encapsulates bitmasks of
+ * interface types defined in enum nl80211_iftype. Optional attribute, if not
+ * present in the request the driver shall send information of all supported
+ * interface modes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK:
+ * u32 attribute. This attribute carries information of all filters that shall
+ * be applied while populating usable channels information by the driver. This
+ * attribute carries bit masks of different filters defined in enum
+ * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present
+ * in the request the driver shall send information of channels without applying
+ * any of the filters that can be configured through this attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * usability information of each channel. The attributes defined in enum
+ * qca_wlan_vendor_attr_chan_info are used inside this attribute.
+ */
+enum qca_wlan_vendor_attr_usable_channels {
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX =
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry
+ * the list of radar history entries.
+ * Each entry contains freq, timestamp, and radar signal detect flag.
+ * The driver shall add an entry when CAC has finished, or radar signal
+ * has been detected post AP beaconing. The driver shall maintain at least
+ * 8 entries in order to save CAC result for a 160 MHz channel.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute.
+ * Channel frequency in MHz.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds.
+ * CLOCK_BOOTTIME timestamp when this entry is updated due to CAC
+ * or radar detection.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute.
+ * This flag indicates radar signal has been detected.
+ */
+enum qca_wlan_vendor_attr_radar_history {
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_mcc_quota_type: MCC channel time quota type
+ *
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR: In the event, it indicates that the
+ * target exited MCC state and cleared the quota information. In the
+ * command it clears MCC quota setting and restores adaptive scheduling.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED: Channel time quota is fixed and
+ * will not be changed.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC: Channel time quota is dynamic
+ * and the target may change the quota based on the data activity.
+ */
+enum qca_wlan_vendor_mcc_quota_type {
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR = 0,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED = 1,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mcc_quota: Used by the vendor event
+ * QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA to indicate MCC channel
+ * quota information or as a command to set the required MCC quota for an
+ * interface.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE: u32 attribute.
+ * The type is defined in enum qca_wlan_vendor_mcc_quota_type.
+ * In a command this specifies the MCC quota type to be set for the interface.
+ * In an event this provides the current quota type in force.
+ * This is required in a command and an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES: Nested attribute to carry
+ * the list of channel quota entries.
+ * In an event each entry contains the frequency and respective time quota for
+ * all the MCC interfaces.
+ * In a command it specifies the interface index and respective time quota.
+ * In a command only one entry (ifindex, quota pair) may be specified.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ: u32 attribute.
+ * Channel frequency in MHz. This is present only in an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE: u32 attribute.
+ * Channel time quota expressed as percentage.
+ * This is present in an event and a command.
+ * In an command, the user shall specify the quota to be allocated for the
+ * interface represented by %QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX.
+ * In an event this provides the existing quota for the channel.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX: u32 attribute.
+ * Specifies the interface index (netdev) for which the corresponding
+ * configurations are applied. This is required in a command only. Only one
+ * interface index may be specified. If not specified, the configuration is
+ * rejected.
+ */
+enum qca_wlan_vendor_attr_mcc_quota {
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES = 2,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE = 4,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX =
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_supported_radio_cfg - Attributes for
+ * radio configurations present in each radio combination.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND: u32 attribute indicates
+ * the band info in the radio configuration. Uses the enum qca_set_band values.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA: u8 attribute indicates
+ * the number of antennas info in the radio configuration.
+ */
+enum qca_wlan_vendor_attr_supported_radio_cfg {
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND = 1,
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_LAST,
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radio_combination - Attributes for
+ * radio combinations supported by the device.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS: Nested attribute
+ * provides the radio configurations present in the radio combination.
+ * Uses the enum qca_wlan_vendor_attr_supported_radio_cfg attributes.
+ * This attribute provides the values for radio combination matrix.
+ * For standalone config, the number of config values is one and the config
+ * carries the band and antenna information for standalone configuration. For
+ * Dual Band Simultaneous (DBS)/Single Band Simultaneous (SBS) mode
+ * configuration the number of config values is two and the config carries the
+ * band and antenna information for each simultaneous radio.
+ */
+enum qca_wlan_vendor_attr_radio_combination {
+ QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radio_combination_matrix - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS: Nested attribute
+ * provides the radio combinations supported by the device.
+ * Uses the enum qca_wlan_vendor_attr_radio_combination attributes.
+ * For example, in the radio combination matrix for a device which has two
+ * radios, where one radio is capable of 2.4 GHz 2X2 only and another radio is
+ * capable of either 5 GHz or 6 GHz 2X2, the possible number of radio
+ * combinations is 5 and the radio combinations are
+ * {{{2.4 GHz 2X2}}, //Standalone 2.4 GHz
+ * {{5 GHz 2X2}}, //Standalone 5 GHz
+ * {{6 GHz 2X2}}, //Standalone 6 GHz
+ * {{2.4 GHz 2X2}, {5 GHz 2X2}}, //2.4 GHz + 5 GHz DBS
+ * {{2.4 GHz 2X2}, {6 GHz 2X2}}} //2.4 GHz + 6 GHz DBS
+ * The band and antenna info together as nested data provides one radio config.
+ * Standalone configuration has one config with band and antenna nested data.
+ * Dual Band Simultaneous (DBS)/Single Band Simultaneous (SBS) configuration
+ * have two nested band and antenna info data.
+ */
+enum qca_wlan_vendor_attr_radio_combination_matrix {
+ QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag)
+ * Enable mDNS offload. This attribute is mandatory to enable
+ * mDNS offload feature. If this attribute is not present, mDNS offload
+ * is disabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing
+ * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This
+ * attribute is mandatory when enabling the feature, and not required when
+ * disabling the feature.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing
+ * the following attributes:
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute.
+ * It consists of a hostname and ".local" as the domain name. The character
+ * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes.
+ * It is used to compare the domain in the "QU" query. Only 1 FQDN is
+ * supported per vdev.
+ * For example: myphone.local
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required
+ * u16 attribute. It specifies the total number of resource records present
+ * in the answer section of the answer payload. This attribute is needed by the
+ * firmware to populate the mDNS response frame for mDNS queries without having
+ * to parse the answer payload.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob
+ * attribute sent by the mdnsResponder from userspace. It contains resource
+ * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This
+ * payload is passed down to the firmware and is transmitted in response to
+ * mDNS queries.
+ * The maximum supported size of the answer payload is 512 bytes.
+ */
+enum qca_wlan_vendor_attr_mdns_offload {
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_monitor_data_frame_type - Represent the various
+ * Data frame types to be sent over the monitor interface.
+ */
+enum qca_wlan_vendor_monitor_data_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17),
+};
+
+/**
+ * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various
+ * Management frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames
+ * except the Beacon frame.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected
+ * BSSID Beacon frames. Valid only in the connected state.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents
+ * the Beacon frames obtained during the scan (off channel and connected
+ * channel), when in connected state.
+ */
+enum qca_wlan_vendor_monitor_mgmt_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3),
+};
+
+/**
+ * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various
+ * Control frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame
+ */
+enum qca_wlan_vendor_monitor_ctrl_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the
+ * monitor mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32
+ * attribute.
+ * Represents the interval in milliseconds only for the connected Beacon frames,
+ * expecting the connected BSS's Beacon frames to be sent on the monitor
+ * interface at this specific interval.
+ */
+enum qca_wlan_vendor_attr_set_monitor_mode {
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX =
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags.
+ * Bits will be set to 1 if the corresponding state is enabled.
+ *
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start.
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end.
+ */
+enum qca_wlan_vendor_roam_scan_state {
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_roam_event_type - Roam event type flags.
+ * Bits will be set to 1 if the corresponding event is notified.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event
+ * carries the trigger reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries
+ * the BSSID, RSSI, frequency info of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event
+ * carries the roam fail reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the
+ * BSSID, RSSI, frequency info of the AP to which the roam was attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam
+ * event carries the roam invoke fail reason. When set, it is expected that
+ * the roam event carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event
+ * carries the roam scan state. When set, it is expected that the roam event
+ * carries the respective scan state via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding
+ * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST.
+ */
+enum qca_wlan_vendor_roam_event_type {
+ QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1),
+ QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2),
+ QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info.
+ * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address
+ * representing the BSSID of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value
+ * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is
+ * attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz
+ * on which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam fail reason for the last failed
+ * roaming attempt by the firmware for the specific BSSID. Different roam
+ * failure reason codes are specified in enum qca_vendor_roam_fail_reasons.
+ */
+enum qca_wlan_vendor_attr_roam_events_candidate_info {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the
+ * roam events to the driver or notify these events from the driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the
+ * driver/firmware to enable/disable the notification of roam events. It's a
+ * mandatory attribute and used only in the request from the userspace to the
+ * host driver. 1-Enable, 0-Disable.
+ * If the roaming is totally offloaded to the firmware, this request when
+ * enabled shall mandate the firmware to notify all the relevant roam events
+ * represented by the below attributes. If the host is in the suspend mode,
+ * the behavior of the firmware to notify these events is guided by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get
+ * these events in the suspend state, the firmware is expected to wake up the
+ * host before the respective events are notified. Please note that such a
+ * request to get the events in the suspend state will have a definite power
+ * implication.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents
+ * that the roam events need to be notified in the suspend state too. By
+ * default, these roam events are notified in the resume state. With this flag,
+ * the roam events are notified in both resume and suspend states.
+ * This attribute is used in the request from the userspace to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only.
+ * Represents the different roam event types, signified by the enum
+ * qca_wlan_vendor_roam_event_type.
+ * Each bit of this attribute represents the different roam even types reported
+ * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. Each bit of this attribute represents the
+ * different roam trigger reason code which are defined in enum
+ * qca_vendor_roam_triggers.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info
+ * for which the roam is attempted. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_roam_events_candidate_info.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents
+ * the scan state on which the roam events need to be notified. The values for
+ * this attribute are referred from enum qca_wlan_vendor_roam_scan_state.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of
+ * u32 values. List of frequencies in MHz considered for a roam scan.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ */
+enum qca_wlan_vendor_attr_roam_events {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1,
+};
+
+/**
+ * enum qca_wlan_ratemask_params_type - Rate mask config type
+ *
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM: CCK/OFDM rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
+ */
+enum qca_wlan_ratemask_params_type {
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ratemask_params - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG.
+ * This is used to set the rate mask value to be used in rate selection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST:
+ * Array of nested containing attributes
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE and
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE: u8, represents
+ * the different PHY types to which the rate mask config is to be applied.
+ * The values for this attribute are referred from enum
+ * qca_wlan_vendor_ratemask_params_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap.
+ * A bit value of 1 represents rate is enabled and a value of 0
+ * represents rate is disabled.
+ * For HE targets, 12 bits correspond to one NSS setting.
+ * b0-13 => NSS1, MCS 0-13
+ * b14-27 => NSS2, MCS 0-13 and so on for other NSS.
+ * For VHT targets, 10 bits correspond to one NSS setting.
+ * b0-9 => NSS1, MCS 0-9
+ * b10-19 => NSS2, MCS 0-9 and so on for other NSS.
+ * For HT targets, 8 bits correspond to one NSS setting.
+ * b0-7 => NSS1, MCS 0-7
+ * b8-15 => NSS2, MCS 0-7 and so on for other NSS.
+ * For OFDM/CCK targets, 8 bits correspond to one NSS setting.
+ */
+enum qca_wlan_vendor_attr_ratemask_params {
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_audio_data_path - Defines the data path to be used for audio
+ * traffic.
+ *
+ * @QCA_WLAN_AUDIO_DATA_PATH_VIA_HOST_PROCESSOR:
+ * Send audio traffic through the host processor.
+ * @QCA_WLAN_AUDIO_DATA_PATH_VIA_LOW_POWER_DSP:
+ * Send audio traffic using the low power DSP to/from the encoder.
+ */
+enum qca_wlan_audio_data_path {
+ QCA_WLAN_AUDIO_DATA_PATH_VIA_HOST_PROCESSOR = 0,
+ QCA_WLAN_AUDIO_DATA_PATH_VIA_LOW_POWER_DSP = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_pasn_action - Action to authenticate (and generate keys
+ * for) or drop existing PASN security association for the listed the
+ * peers. Used by QCA_WLAN_VENDOR_ATTR_PASN_ACTION and sent from the driver
+ * to userspace.
+ *
+ * @QCA_WLAN_VENDOR_PASN_ACTION_AUTH: Initiate PASN handshake with the peer
+ * devices indicated with %QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR.
+ * @QCA_WLAN_VENDOR_PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT: Indication from
+ * the driver to userspace to inform that the existing PASN keys of the
+ * peer devices specified with %QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR are
+ * not valid anymore.
+ */
+enum qca_wlan_vendor_pasn_action {
+ QCA_WLAN_VENDOR_PASN_ACTION_AUTH,
+ QCA_WLAN_VENDOR_PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_pasn_peer: Defines the nested attributes used in
+ * QCA_WLAN_VENDOR_ATTR_PASN_PEERS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR: This attribute is optional in the
+ * event from the driver to userspace and represents the local MAC address
+ * to be used for PASN handshake. When this attribute is present, userspace
+ * shall use the source address specified in this attribute by the driver
+ * for PASN handshake with peer device.
+ * This attribute is required in a command response from userspace to the
+ * driver and represents the MAC address that was used in PASN handshake
+ * with the peer device.
+ * @QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR: Indicates the MAC address of the
+ * peer device to which PASN handshake is requested in an event from the
+ * driver to userspace when QCA_WLAN_VENDOR_ATTR_PASN_ACTION is set to
+ * QCA_WLAN_VENDOR_PASN_ACTION_AUTH.
+ * Indicates the MAC address of the peer device for which the keys are to
+ * be invalidated in an event from the driver to userspace when
+ * QCA_WLAN_VENDOR_ATTR_PASN_ACTION is set to
+ * QCA_WLAN_VENDOR_PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT.
+ * Indicates the MAC address of the peer device for which the status is
+ * being sent in a status report from userspace to the driver.
+ * @QCA_WLAN_VENDOR_ATTR_PASN_PEER_LTF_KEYSEED_REQUIRED: NLA_FLAG attribute used
+ * in the event from the driver to userspace. When set, userspace is
+ * required to derive LTF key seed from KDK and set it to the driver.
+ * @QCA_WLAN_VENDOR_ATTR_PASN_PEER_STATUS_SUCCESS: NLA_FLAG attribute. This
+ * attribute is used in the command response from userspace to the driver.
+ * If present, it indicates the successful PASN handshake with the peer. If
+ * this flag is not present, it indicates that the PASN handshake with the
+ * peer device failed.
+ */
+enum qca_wlan_vendor_attr_pasn_peer {
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_LTF_KEYSEED_REQUIRED = 3,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_STATUS_SUCCESS = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX =
+ QCA_WLAN_VENDOR_ATTR_PASN_PEER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_pasn: Defines the attributes used in the
+ * QCA_NL80211_VENDOR_SUBCMD_PASN command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PASN_ACTION: u32 attribute, possible values are
+ * defined in enum qca_wlan_vendor_pasn_action and used only in an event
+ * from the driver to userspace.
+ * @QCA_WLAN_VENDOR_ATTR_PASN_PEERS: Nested attribute, used to pass PASN peer
+ * details for each peer and used in both an event and a command response.
+ * The nested attributes used inside QCA_WLAN_VENDOR_ATTR_PASN_PEERS are
+ * defined in enum qca_wlan_vendor_attr_pasn_peer.
+ */
+enum qca_wlan_vendor_attr_pasn {
+ QCA_WLAN_VENDOR_ATTR_PASN_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_PASN_ACTION = 1,
+ QCA_WLAN_VENDOR_ATTR_PASN_PEERS = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_PASN_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PASN_MAX =
+ QCA_WLAN_VENDOR_ATTR_PASN_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_secure_ranging_ctx_action - Used to add or delete
+ * the ranging security context derived from PASN for each peer. Used in
+ * QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION.
+ *
+ * @QCA_WLAN_VENDOR_SECURE_RANGING_CTX_ACTION_ADD: Add the secure ranging
+ * context for the peer.
+ * @QCA_WLAN_VENDOR_SECURE_RANGING_CTX_ACTION_DELETE: Delete the secure ranging
+ * context for the peer.
+ */
+enum qca_wlan_vendor_secure_ranging_ctx_action {
+ QCA_WLAN_VENDOR_SECURE_RANGING_CTX_ACTION_ADD,
+ QCA_WLAN_VENDOR_SECURE_RANGING_CTX_ACTION_DELETE,
+};
+
+/**
+ * enum qca_wlan_vendor_sha_type - SHA types. Used to configure the SHA type
+ * used for deriving PASN keys to the driver. Used in
+ * QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE
+ * @QCA_WLAN_VENDOR_SHA_256: SHA-256
+ * @QCA_WLAN_VENDOR_SHA_384: SHA-384
+ */
+enum qca_wlan_vendor_sha_type {
+ QCA_WLAN_VENDOR_SHA_256,
+ QCA_WLAN_VENDOR_SHA_384,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_secure_ranging_ctx: Defines the attributes used
+ * to set security context for the PASN peer from userspace to the driver.
+ * Used with QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION: u32 attribute, possible
+ * values are defined in enum qca_wlan_vendor_secure_ranging_ctx_action
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR: The local MAC address that
+ * was used during the PASN handshake.
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR: The MAC address of
+ * the peer device for which secure ranging context is being configured.
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE: u32 attribute, defines the
+ * hash algorithm to be used, possible values are defined in enum
+ * qca_wlan_vendor_sha_type.
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK: Variable length attribute, holds
+ * the temporal key generated from the PASN handshake. The length of this
+ * attribute is dependent on the value of
+ * %QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER.
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER: cipher suite to use with the
+ * TK, u32, as defined in IEEE Std 802.11-2020, 9.4.2.24.2 (Cipher suites)
+ * (e.g., 0x000FAC04).
+ * @QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED: Variable length
+ * attribute, holds the LTF keyseed derived from KDK of PASN handshake.
+ * The length of this attribute is dependent on the value of
+ * %QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE.
+
+ */
+enum qca_wlan_vendor_attr_secure_ranging_ctx {
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION = 1,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR = 3,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK = 5,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER = 6,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX =
+ QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_filter - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_FILTER
+ * nested attribute. The packets that match a filter will be replied with
+ * attributes configured in %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4:
+ * u32 attribute. Destination IPv4 address in network byte order, the
+ * IPv4 packets with different address will be filtered out.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4_IS_BC:
+ * Flag attribute. If it's present, indicates that
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4 is a broadcast
+ * address; while if not, indicates that the address is a unicast/multicast
+ * address.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV6:
+ * NLA_BINARY attribute, length is 16 bytes.
+ * Destination IPv6 address in network byte order, the IPv6 packets
+ * with different destination address will be filtered out.
+ * This attribute is optional.
+ *
+ * At least one of %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4 and
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV6 must be configured.
+ * Packets on both IPv4 and IPv6 will be processed if both are configured.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_PORT:
+ * u16 attribute. Destination UDP port, the packets with different destination
+ * UDP port will be filtered out.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MATCH_OFFSET:
+ * u32 attribute. Represents the offset (in UDP payload) of the data
+ * to be matched.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MATCH_DATA:
+ * NLA_BINARY attribute, the maximum allowed size is 16 bytes.
+ * Binary data that is compared bit-by-bit against the data (specified
+ * by %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MATCH_OFFSET) in UDP
+ * payload, the packets don't match will be filtered out.
+ * This attribute is mandatory.
+ */
+enum qca_wlan_vendor_attr_coap_offload_filter {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4 = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV4_IS_BC = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_IPV6 = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_DEST_PORT = 4,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MATCH_OFFSET = 5,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MATCH_DATA = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_FILTER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_reply - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV4:
+ * u32 attribute. Source address (in network byte order) for replying
+ * the matching broadcast/multicast IPv4 packets.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV6:
+ * NLA_BINARY attribute, length is 16 bytes.
+ * Source address (in network byte order) for replying the matching
+ * multicast IPv6 packets.
+ * This attribute is optional.
+ *
+ * For broadcast/multicast offload reply, one of
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV4 and
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV6 or both must be
+ * configured according to version of the IP address(es) configured in
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_FILTER;
+ * while for unicast case, firmware will take the destination IP address
+ * in the received matching packet as the source address for replying.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_FILTER:
+ * Nested attribute. Filter for the received UDP packets, only the matching
+ * packets will be replied and cached.
+ * See enum qca_wlan_vendor_attr_coap_offload_filter for list of supported
+ * attributes.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_MSG:
+ * NLA_BINARY attribute, the maximum allowed size is 1152 bytes.
+ * CoAP message (UDP payload) to be sent upon receiving matching packets.
+ * Firmware is responsible for adding any necessary protocol headers.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_CACHE_EXPTIME:
+ * u32 attribute. Expiration time in milliseconds of the cached CoAP messages.
+ * A cached message will be dropped by firmware if it's expired.
+ * This attribute is optional. A default value of 40000 will be used in the
+ * absence of it.
+ */
+enum qca_wlan_vendor_attr_coap_offload_reply {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV4 = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_SRC_IPV6 = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_FILTER = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_MSG = 4,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_CACHE_EXPTIME = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_tx_ipv4 - Represents parameters for
+ * CoAP message (UDP) transmitting on IPv4.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_SRC_ADDR:
+ * u32 attribute. Source address (in network byte order) for transmitting
+ * packets on IPv4.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_SRC_PORT:
+ * u16 attribute. Source UDP port.
+ * This attribute is optional, a random port is taken if it's not present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_ADDR:
+ * u32 attribute. Destination IPv4 address (in network byte order).
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_IS_BC:
+ * Flag attribute. If it's present, indicates that
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_ADDR is a broadcast
+ * address; while if not, indicates that the address is unicast/multicast
+ * address.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_PORT:
+ * u16 attribute. Destination UDP port.
+ * This attribute is mandatory.
+ */
+enum qca_wlan_vendor_attr_coap_offload_tx_ipv4 {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_SRC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_SRC_PORT = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_ADDR = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_IS_BC = 4,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_DEST_PORT = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV4_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_tx_ipv6 - Represents parameters for
+ * CoAP message (UDP) transmitting on IPv6.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_SRC_ADDR:
+ * NLA_BINARY attribute, length is 16 bytes.
+ * Source address (in network byte order) for transmitting packets on IPv6.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_SRC_PORT:
+ * u16 attribute. Source UDP port.
+ * This attribute is optional, a random port is taken if it's not present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_DEST_ADDR:
+ * NLA_BINARY attribute, length is 16 bytes.
+ * Destination IPv6 address (in network byte order).
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_DEST_PORT:
+ * u16 attribute. Destination UDP port.
+ * This attribute is mandatory.
+ */
+enum qca_wlan_vendor_attr_coap_offload_tx_ipv6 {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_SRC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_SRC_PORT = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_DEST_ADDR = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_DEST_PORT = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_TX_IPV6_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_periodic_tx - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV4:
+ * Nested attribute. The IPv4 source/destination address/port for offload
+ * transmitting. See enum qca_wlan_vendor_attr_coap_offload_tx_ipv4 for the list
+ * of supported attributes.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV6:
+ * Nested attribute. The IPv6 source/destination address/port for offload
+ * transmitting. See enum qca_wlan_vendor_attr_coap_offload_tx_ipv6 for the list
+ * of supported attributes.
+ * This attribute is optional.
+ *
+ * At least one of %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV4 and
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV6 must be configured.
+ * Firmware will transmit the packets on both IPv4 and IPv6 if both are
+ * configured.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_PERIOD:
+ * u32 attribute. Period in milliseconds for the periodic transmitting.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_MSG:
+ * NLA_BINARY attribute, the maximum allowed size is 1152 bytes.
+ * CoAP message (UDP payload) to be periodically transmitted. Firmware
+ * is responsible for adding any necessary protocol headers.
+ * This attribute is mandatory.
+ */
+enum qca_wlan_vendor_attr_coap_offload_periodic_tx {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV4 = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_IPV6 = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_PERIOD = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_MSG = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload_cache_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHES nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_TS:
+ * u64 attribute. Received time (since system booted in microseconds) of
+ * the cached CoAP message.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV4:
+ * u32 attribute. Source IPv4 address (in network byte order) of the cached
+ * CoAP message.
+ * This attribute is optional.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV6:
+ * NLA_BINARY attribute, length is 16 bytes.
+ * Source IPv6 address (in network byte order) of the cached CoAP message.
+ * This attribute is optional.
+ *
+ * At most and at least one of
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV4 and
+ * %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV6 is given for
+ * an entry.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_MSG:
+ * NLA_BINARY attribute, the maximum allowed size is 1152 bytes.
+ * The cached CoAP message (UDP payload). If the actual message size is
+ * greater than the maximum size, it will be truncated and leaving only
+ * the first 1152 bytes.
+ * This attribute is mandatory.
+ */
+enum qca_wlan_vendor_attr_coap_offload_cache_info {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_TS = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV4 = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_SRC_IPV6 = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_MSG = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_coap_offload_action - Actions for
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_COAP_OFFLOAD.
+ *
+ * @QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_ENABLE:
+ * Enable CoAP offload reply.
+ * If it's enabled, firmware will start offload processing on each suspend
+ * and stop on each resume.
+ *
+ * Offload reply on match works as follows:
+ * Reply the packets that match the filter with the given CoAP
+ * message (with necessary protocol headers), increase the CoAP message
+ * ID in the given CoAP message by one for the next use after each successful
+ * transmission, and try to store the information of the received packet,
+ * including the received time, source IP address, and CoAP message (UDP
+ * payload).
+ *
+ * Firmware has a limit to the maximum stored entries, it takes the source IP
+ * address as the key of an entry, and keeps at most one entry for each key.
+ * A packet won't be stored if no entry for the same key is present and the
+ * total number of the existing unexpired entries reaches the maximum value.
+ *
+ * If any configured item is changed, user space should disable offload reply
+ * first and then issue a new enable request.
+ *
+ * @QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_DISABLE:
+ * Disable CoAP offload reply and return information of any cached CoAP
+ * messages.
+ *
+ * @QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_PERIODIC_TX_ENABLE:
+ * Enable CoAP offload periodic transmitting.
+ * If it's enabled, firmware will start offload periodic transmitting on
+ * each suspend and stop on each resume.
+ *
+ * Offload periodic transmitting works as follows:
+ * Send the given CoAP message (with necessary protocol headers) with the given
+ * source/destination IP address/UDP port periodically based on the given
+ * period and increase the CoAP message ID in the given CoAP message by one
+ * for the next use after each successful transmission.
+ *
+ * If any configured item is changed, user space should disable offload
+ * periodic transmitting first and then issue a new enable request.
+ *
+ * @QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_PERIODIC_TX_DISABLE:
+ * Disable CoAP offload periodic transmitting.
+ *
+ * @QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_CACHE_GET:
+ * Get information of the CoAP messages cached during offload reply
+ * processing. The cache is cleared after retrieval.
+ */
+enum qca_wlan_vendor_coap_offload_action {
+ QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_ENABLE = 0,
+ QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_DISABLE = 1,
+ QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_PERIODIC_TX_ENABLE = 2,
+ QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_PERIODIC_TX_DISABLE = 3,
+ QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_CACHE_GET = 4,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_coap_offload - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_COAP_OFFLOAD.
+ * This is used to set parameters for CoAP offload processing, or get
+ * cached CoAP messages from firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_ACTION:
+ * u32 attribute. Action to take in this vendor command.
+ * See enum qca_wlan_vendor_coap_offload_action for supported actions.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REQ_ID:
+ * u32 attribute. Represents the Request ID for the CoAP offload
+ * configuration, which can help to identify the user entity starting
+ * the CoAP offload processing and accordingly stop the respective
+ * ones/get the cached CoAP messages with the matching ID.
+ * This attribute is mandatory.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY:
+ * Nested attribute. Parameters for offload reply.
+ * See enum qca_wlan_vendor_attr_coap_offload_reply for the list of
+ * supported attributes.
+ * This attribute is mandatory if %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_ACTION
+ * is QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_ENABLE, and is ignored
+ * otherwise.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX:
+ * Nested attribute. Parameters for offload periodic transmitting.
+ * See enum qca_wlan_vendor_attr_coap_offload_periodic_tx for the list of
+ * supported attributes.
+ * This attribute is mandatory if %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_ACTION is
+ * QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_PERIODIC_TX_ENABLE, and is ignored
+ * otherwise.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHES:
+ * Array of nested attributes. Information of the cached CoAP messages,
+ * where each entry is taken from
+ * enum qca_wlan_vendor_attr_coap_offload_cache_info.
+ * This attribute is used for reporting the cached CoAP messages
+ * in reply for command in which %QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_ACTION
+ * is QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_CACHE_GET or
+ * QCA_WLAN_VENDOR_COAP_OFFLOAD_ACTION_REPLY_DISABLE. It means there is no
+ * cached item if this attribute is not present.
+ */
+enum qca_wlan_vendor_attr_coap_offload {
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_ACTION = 1,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REQ_ID = 2,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_REPLY = 3,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_PERIODIC_TX = 4,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_CACHES = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_COAP_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_scs_rule_config - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SCS_RULE_CONFIG to configure Stream Classification
+ * Service (SCS) rule.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_RULE_ID: Mandatory u32 attribute.
+ * Represents the unique id of SCS rule to be configured.
+
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_REQUEST_TYPE: Mandatory u8 attribute.
+ * Represents the request type: add, remove, or change.
+ * Values as defined in IEEE Std 802.11-2020, Table 9-246 (SCS Request
+ * Type definitions).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_OUTPUT_TID: Mandatory u8 attribute
+ * in case of add/change request type.
+ * Represents the output traffic identifier (TID) to be assigned to the flow
+ * matching the rule.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_CLASSIFIER_TYPE: Mandatory u8
+ * attribute in case of add/change request type.
+ * Represents type of classifier parameters present in SCS rule.
+ * Refer IEEE Std 802.11-2020 Table 9-164 (Frame classifier type).
+ * Only classifier types 4 and 10 are supported for SCS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_VERSION: Mandatory u8 attribute
+ * in case of add/change request type when classifier type is TCLAS4.
+ * Represents the IP version (4: IPv4, 6: IPv6) of the rule.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_IPV4_ADDR: Optional
+ * attribute in case of add/change request type when classifier type is TCLAS4
+ * and version attribute is IPv4.
+ * Represents the source IPv4 address in the rule which is to be compared
+ * against the source IP address in the IPv4 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_IPV4_ADDR: Optional
+ * attribute in case of add/change request type when classifier type is TCLAS4
+ * and version attribute is IPv4.
+ * Represents the destination IPv4 address in the rule which is to be compared
+ * against the destination IP address in the IPv4 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_IPV6_ADDR: Optional
+ * attribute in case of add/change request type when classifier type is TCLAS4
+ * and version attribute is IPv6.
+ * Represents the source IPv6 address in the rule which is to be compared
+ * against the source IP address in the IPv6 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_IPV6_ADDR: Optional
+ * attribute in case of add/change request type when classifier type is TCLAS4
+ * and version attribute is IPv6.
+ * Represents the destination IPv6 address in the rule which is to be compared
+ * against the destination IP address in the IPv6 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_PORT: Optional u16 attribute
+ * in case of add/change request type when classifier type is TCLAS4.
+ * Represents the source port number in the rule which is to be compared against
+ * the source port number in the protocol header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_PORT: Optional u16 attribute
+ * in case of add/change request type when classifier type is TCLAS4.
+ * Represents the destination port number in the rule which is to be compared
+ * against the destination port number in the protocol header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DSCP: Optional u8 attribute
+ * in case of add/change request type when classifier type is TCLAS4.
+ * Represents the DSCP value in the rule which is to be compared against the
+ * DSCP field present in the IP header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_NEXT_HEADER: Optional u8
+ * attribute in case of add/change request type when classifier type is TCLAS4.
+ * Represents the protocol/next header in the rule which is to be compared
+ * against the protocol/next header field present in the IPv4/IPv6 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_FLOW_LABEL: Optional
+ * attribute of size 3 bytes present in case of add/change request type
+ * when classifier type is TCLAS4 and version is IPv6.
+ * Represents the flow label value in the rule which is to be compared against
+ * the flow label field present in the IPv6 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_PROTOCOL_INSTANCE: Optional u8
+ * attribute in case of add/change request type when classifier type is TCLAS10.
+ * Represents the protocol instance number in the rule.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_NEXT_HEADER: Optional u8
+ * attribute in case of add/change request type when classifier type is TCLAS10.
+ * Represents the protocol/next header in the rule which is to be compared
+ * against the protocol/next header field present in the IPv4/IPv6 header.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_FILTER_MASK: Optional
+ * attribute of variable length present when request type is add/change and
+ * classifier type is TCLAS10.
+ * Represents the mask to be used for masking the header contents of the header
+ * specified by QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_NEXT_HEADER
+ * attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_FILTER_VALUE: Optional
+ * attribute of variable length present when request type is add/change and
+ * classifier type is TCLAS10.
+ * Represents the value to be compared against after masking the header contents
+ * of the header specified by the
+ * QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_NEXT_HEADER attribute with the
+ * filter mask specified by the
+ * QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_FILTER_MASK attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_SERVICE_CLASS_ID: Optional u16
+ * attribute.
+ * Represents the service class id of the configured SCS rule.
+ */
+enum qca_wlan_vendor_attr_scs_rule_config {
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_RULE_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_REQUEST_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_OUTPUT_TID = 3,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_CLASSIFIER_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_VERSION = 5,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_IPV4_ADDR = 6,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_IPV4_ADDR = 7,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_IPV6_ADDR = 8,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_IPV6_ADDR = 9,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_SRC_PORT = 10,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DST_PORT = 11,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_DSCP = 12,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_NEXT_HEADER = 13,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS4_FLOW_LABEL = 14,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_PROTOCOL_INSTANCE = 15,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_NEXT_HEADER = 16,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_FILTER_MASK = 17,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_TCLAS10_FILTER_VALUE = 18,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_SERVICE_CLASS_ID = 19,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SCS_RULE_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mlo_links - Definition of attributes used inside
+ * nested attribute QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MLO_LINKS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID: u8 attribute, link ID of this MLO link.
+ * @QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR: Own MAC address of this MLO link.
+ * @QCA_WLAN_VENDOR_ATTR_MLO_LINK_BSSID: AP link MAC address of this MLO link.
+ */
+enum qca_wlan_vendor_attr_mlo_links {
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_BSSID = 3,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAX =
+ QCA_WLAN_VENDOR_ATTR_MLO_LINK_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_sar_version - This describes the current SAR version
+ * used in the firmware.
+ *
+ * @QCA_WLAN_VENDOR_SAR_VERSION_1: The firmware supports legacy SAR.
+ * In legacy SAR, the firmware supports 5 static and 1 user defined SAR limits.
+ *
+ * @QCA_WLAN_VENDOR_SAR_VERSION_2: The firmware supports SAR version 2,
+ * i.e., SAR Non DBS mode. In SAR version 2, the firmware has 6 SAR tables for
+ * each CTL group. So user can select up to 6 SAR indexes from the current CTL
+ * groups.
+ *
+ * @QCA_WLAN_VENDOR_SAR_VERSION_3: The firmware supports SAR version 3,
+ * i.e., SAR DBS mode. In SAR version 3, the firmware has 6 SAR tables for each
+ * CTL group but user can choose up to 3 SAR set index only, as the top half
+ * of the SAR index (0 to 2) is used for non DBS purpose and the bottom half of
+ * the SAR index (3 to 5) is used for DBS mode.
+ */
+enum qca_wlan_vendor_sar_version {
+ QCA_WLAN_VENDOR_SAR_VERSION_INVALID = 0,
+ QCA_WLAN_VENDOR_SAR_VERSION_1 = 1,
+ QCA_WLAN_VENDOR_SAR_VERSION_2 = 2,
+ QCA_WLAN_VENDOR_SAR_VERSION_3 = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_sar_ctl_group_state - This describes whether
+ * CTL grouping is enabled or disabled in the firmware.
+ *
+ * @QCA_WLAN_VENDOR_SAR_CTL_GROUP_STATE_ENABLED: CTL grouping
+ * is enabled in firmware.
+ *
+ * @QCA_WLAN_VENDOR_SAR_CTL_GROUP_STATE_DISABLED: CTL grouping
+ * is disabled in firmware.
+ *
+ */
+enum qca_wlan_vendor_sar_ctl_group_state {
+ QCA_WLAN_VENDOR_SAR_CTL_GROUP_STATE_INVALID = 0,
+ QCA_WLAN_VENDOR_SAR_CTL_GROUP_STATE_ENABLED = 1,
+ QCA_WLAN_VENDOR_SAR_CTL_GROUP_STATE_DISABLED = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sar_capability - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY to get SAR capabilities
+ * supported by the firmware.
+
+ * @QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION:
+ * u32 attribute. This field describes current SAR version supported by the
+ * firmware.
+ * See enum qca_wlan_vendor_sar_version for more information.
+ * This attribute is mandatory.
+
+ * @QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_CTL_GROUP_STATE:
+ * u32 attribute. This field describes whether CTL groups are enabled
+ * or disabled in the firmware.
+ * See enum qca_wlan_vendor_sar_ctl_group_state for more information.
+ * This attribute is optional.
+ */
+
+enum qca_wlan_vendor_attr_sar_capability {
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION = 1,
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_CTL_GROUP_STATE = 2,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sr_stats - Attributes for Spatial Reuse statistics.
+ * These statistics are sent from the driver in a response when userspace
+ * queries to get the statistics using the operation
+ * %QCA_WLAN_SR_OPERATION_GET_STATS. These statistics are reset
+ * by the driver when the SR feature is enabled, when the driver receives
+ * %QCA_WLAN_SR_OPERATION_CLEAR_STATS operation, or when disconnected.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_OPPORTUNITIES_COUNT: u32 attribute.
+ * Mandatory only when non-SRG is supported by the AP and optional otherwise.
+ * This represents the number of non-SRG TX opportunities.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_TRIED_COUNT: u32 attribute.
+ * Mandatory only when non-SRG is supported by the AP and optional otherwise.
+ * This represents the number of non-SRG PPDUs tried to transmit.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_SUCCESS_COUNT: u32 attribute.
+ * Mandatory only when non-SRG is supported by the AP and optional otherwise.
+ * This represents the number of non-SRG PPDUs successfully transmitted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_OPPORTUNITIES_COUNT: u32 attribute.
+ * Mandatory only when SRG is supported by the AP and optional otherwise.
+ * This represents the number of SRG TX opportunities.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_TRIED_COUNT: u32 attribute.
+ * Mandatory only when SRG is supported by the AP and optional otherwise.
+ * This represents the number of SRG PPDUs tried to transmit.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_SUCCESS_COUNT: u32 attribute.
+ * Mandatory only when SRG is supported by the AP and optional otherwise.
+ * This represents the number of SRG PPDUs successfully transmitted.
+ */
+enum qca_wlan_vendor_attr_sr_stats {
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_OPPORTUNITIES_COUNT = 1,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_TRIED_COUNT = 2,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_SUCCESS_COUNT = 3,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_OPPORTUNITIES_COUNT = 4,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_TRIED_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_SUCCESS_COUNT = 6,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_SR_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_sr_reason_code - Defines the different reason codes used in
+ * Spatial Reuse feature.
+ *
+ * @QCA_WLAN_SR_REASON_CODE_ROAMING: The SR feature is disabled/enabled due to
+ * roaming to an AP that doesn't support/supports SR feature, respectively.
+ *
+ * @QCA_WLAN_SR_REASON_CODE_CONCURRENCY: The SR feature is disabled/enabled due
+ * to change in concurrent interfaces that are supported by the driver.
+ */
+enum qca_wlan_sr_reason_code {
+ QCA_WLAN_SR_REASON_CODE_ROAMING = 0,
+ QCA_WLAN_SR_REASON_CODE_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_sr_operation - Defines the different types of SR operations.
+ * The values are used inside attribute %QCA_WLAN_VENDOR_ATTR_SR_OPERATION.
+ *
+ * @QCA_WLAN_SR_OPERATION_SR_ENABLE: Userspace sends this operation to the
+ * driver to enable the Spatial Reuse feature. Attributes
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD and
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD are used with this
+ * operation.
+ *
+ * @QCA_WLAN_SR_OPERATION_SR_DISABLE: Userspace sends this operation to the
+ * driver to disable the Spatial Reuse feature.
+ *
+ * @QCA_WLAN_SR_OPERATION_SR_SUSPEND: The driver uses this operation in an
+ * asynchronous event sent to userspace when the SR feature is disabled.
+ * The disable reason is encoded in QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE
+ * and sent along with the asynchronous event.
+ *
+ * @QCA_WLAN_SR_OPERATION_SR_RESUME: The driver uses this operation in an
+ * asynchronous event when the SR feature is enabled again after the SR feature
+ * was suspended by the driver earlier. The enable reason is
+ * encoded in QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE. Attributes used are
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD and
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD.
+ *
+ * @QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT: This operation is
+ * used to prohibit PSR-based spatial reuse and non-SRG OBSS PD-based spatial
+ * reuse transmissions. Userspace sends this operation to the driver.
+ * The driver/firmware upon receiving this operation shall prohibit PSR-based
+ * spatial reuse and non-SRG OBSS PD-based spatial reuse transmissions.
+ *
+ * @QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW: This operation is
+ * used to allow PSR-based spatial reuse and non-SRG OBSS PD-based spatial
+ * reuse transmissions. Userspace sends this operation to the driver.
+ * The driver/firmware upon receiving this operation shall allow PSR-based
+ * spatial reuse and non-SRG OBSS PD-based spatial reuse transmissions.
+ *
+ * @QCA_WLAN_SR_OPERATION_GET_STATS: Userspace sends this operation to the
+ * driver to get the SR statistics and the driver sends a synchronous response
+ * with the attributes defined in enum qca_wlan_vendor_attr_sr_stats using the
+ * nested attribute %QCA_WLAN_VENDOR_ATTR_SR_STATS.
+ *
+ * @QCA_WLAN_SR_OPERATION_CLEAR_STATS: Userspace sends this operation to the
+ * driver to clear the SR statistics and upon receiving this operation
+ * the driver/firmware shall clear the SR statistics.
+ *
+ * @QCA_WLAN_SR_OPERATION_GET_PARAMS: Userspace sends this operation to the
+ * driver to get the SR parameters and the driver sends the synchronous response
+ * with the following required attributes:
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW.
+ *
+ * @QCA_WLAN_SR_OPERATION_UPDATE_PARAMS: The driver uses this operation in an
+ * asynchronous event to userspace to update any changes in SR parameters.
+ * The following attributes are used with this operation:
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE,
+ * %QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW.
+ */
+enum qca_wlan_sr_operation {
+ QCA_WLAN_SR_OPERATION_SR_ENABLE = 0,
+ QCA_WLAN_SR_OPERATION_SR_DISABLE = 1,
+ QCA_WLAN_SR_OPERATION_SR_SUSPEND = 2,
+ QCA_WLAN_SR_OPERATION_SR_RESUME = 3,
+ QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT = 4,
+ QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW = 5,
+ QCA_WLAN_SR_OPERATION_GET_STATS = 6,
+ QCA_WLAN_SR_OPERATION_CLEAR_STATS = 7,
+ QCA_WLAN_SR_OPERATION_GET_PARAMS = 8,
+ QCA_WLAN_SR_OPERATION_UPDATE_PARAMS = 9,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sr_params - Defines attributes for SR configuration
+ * parameters used by attribute %QCA_WLAN_VENDOR_ATTR_SR_PARAMS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE: Flag attribute.
+ * This attribute is optionally set in response to
+ * %QCA_WLAN_SR_OPERATION_GET_PARAMS and in request when operation is set to
+ * %QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT. Refer IEEE Std
+ * 802.11ax-2021 Figure 9-788r-SR Control field format to understand more
+ * about HESIGA_Spatial_reuse_value15_allowed.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW: Flag attribute.
+ * This attribute is used in response to %QCA_WLAN_SR_OPERATION_GET_PARAMS
+ * operation. This indicates whether non-SRG OBSS PD SR transmissions are
+ * allowed or not at non-AP STAs that are associated with the AP. If present
+ * non-SRG OBSS PD SR transmissions are not allowed else are allowed.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET: Optional u8
+ * attribute. This attribute is used in response to
+ * %QCA_WLAN_SR_OPERATION_GET_PARAMS operation. This indicates the SRG OBSS PD
+ * Min Offset field which contains an unsigned integer that is added to -82 dBm
+ * to generate the value of the SRG OBSS PD Min parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET: Optional u8
+ * attribute. This attribute is used in response to
+ * %QCA_WLAN_SR_OPERATION_GET_PARAMS operation. This indicates the SRG OBSS PD
+ * Max Offset field which contains an unsigned integer that is added to -82 dBm
+ * to generate the value of the SRG OBSS PD Max parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET: Optional u8
+ * attribute. This attribute is used in response to
+ * %QCA_WLAN_SR_OPERATION_GET_PARAMS operation. This indicates the Non-SRG OBSS
+ * PD Max Offset field which contains an unsigned integer that is added to -82
+ * dBm to generate the value of the Non-SRG OBSS PD Max parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD: s32 attribute (in dBm).
+ * Userspace optionally sends this attribute with
+ * %QCA_WLAN_SR_OPERATION_SR_ENABLE operation to the driver to specify the
+ * preferred SRG PD threshold. The driver shall send this attribute to
+ * userspace in SR resume event to indicate the PD threshold being used for SR.
+ * When there is change in SRG PD threshold (for example, due to roaming, etc.)
+ * the driver shall indicate the userspace the newly configured SRG PD threshold
+ * using an asynchronous event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD: s32 attribute (in dBm).
+ * Userspace optionally sends this attribute with
+ * %QCA_WLAN_SR_OPERATION_SR_ENABLE operation to the driver to specify the
+ * preferred non-SRG PD threshold. The driver shall send this attribute to
+ * userspace in SR resume event to indicate the PD threshold being used for SR.
+ * When there is change in non-SRG PD threshold (for example, due to roaming,
+ * etc.) the driver shall indicate the userspace the newly configured non-SRG PD
+ * threshold using an asynchronous event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE: u32 attribute. The possible
+ * values are defined in enum qca_wlan_sr_reason_code. This
+ * attribute is used with %QCA_WLAN_SR_OPERATION_SR_RESUME and
+ * %QCA_WLAN_SR_OPERATION_SR_SUSPEND operations.
+ */
+enum qca_wlan_vendor_attr_sr_params {
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW = 2,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET = 3,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET = 4,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET = 5,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD = 6,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD = 7,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sr - Defines the attributes used by the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_SR.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_OPERATION: Mandatory u8 attribute for all requests
+ * from userspace to the driver. Possible values are defined in enum
+ * qca_wlan_sr_operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_PARAMS: Nested attribute, contains the SR
+ * configuration parameters. The possible attributes inside this attribute are
+ * defined in enum qca_wlan_vendor_attr_sr_params.
+ * This attribute is used when QCA_WLAN_VENDOR_ATTR_SR_OPERATION is set to
+ * %QCA_WLAN_SR_OPERATION_SR_ENABLE in requests from userspace to the driver and
+ * also in response from the driver to userspace when the response is sent for
+ * %QCA_WLAN_SR_OPERATION_GET_PARAMS.
+ * The driver uses this attribute in asynchronous events in which the operation
+ * is set to %QCA_WLAN_SR_OPERATION_SR_RESUME,
+ * %QCA_WLAN_SR_OPERATION_SR_SUSPEND or %QCA_WLAN_SR_OPERATION_UPDATE_PARAMS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SR_STATS: Nested attribute, contains the SR
+ * statistics. These attributes used inside this are defined in enum
+ * qca_wlan_vendor_attr_sr_stats.
+ * This attribute is used in response from the driver to a command in which
+ * %QCA_WLAN_VENDOR_ATTR_SR_OPERATION is set to
+ * %QCA_WLAN_SR_OPERATION_GET_STATS.
+ */
+enum qca_wlan_vendor_attr_sr {
+ QCA_WLAN_VENDOR_ATTR_SR_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SR_OPERATION = 1,
+ QCA_WLAN_VENDOR_ATTR_SR_PARAMS = 2,
+ QCA_WLAN_VENDOR_ATTR_SR_STATS = 3,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_SR_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SR_MAX =
+ QCA_WLAN_VENDOR_ATTR_SR_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mlo_peer_prim_netdev_event - Defines the attributes
+ * used in the QCA_NL80211_VENDOR_SUBCMD_MLO_PEER_PRIM_NETDEV_EVENT subcommand.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_MACADDR: 6 byte MAC address
+ * used by the peer on the link that corresponds to the link used for sending
+ * the event notification.
+ * @QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_MLD_MAC_ADDR: 6 byte
+ * MLD MAC address of the peer.
+ * @QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_PRIM_IFINDEX: u32 attribute,
+ * used to pass ifindex of the primary netdev.
+ */
+enum qca_wlan_vendor_attr_mlo_peer_prim_netdev_event {
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_MACADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_MLD_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_PRIM_IFINDEX = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_MAX =
+ QCA_WLAN_VENDOR_ATTR_MLO_PEER_PRIM_NETDEV_EVENT_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_afc_freq_psd_info: This enum is used with
+ * nested attributes QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO and
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST to update the frequency range
+ * and PSD information.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START: Required and type is
+ * u32. This attribute is used to indicate the start of the queried frequency
+ * range in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END: Required and type is u32.
+ * This attribute is used to indicate the end of the queried frequency range
+ * in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_PSD: Required and type is u32.
+ * This attribute will contain the PSD information for a single range as
+ * specified by the QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START and
+ * QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END attributes.
+ *
+ * The PSD power info (dBm/MHz) from user space should be multiplied
+ * by a factor of 100 when sending to the driver to preserve granularity
+ * up to 2 decimal places.
+ * Example:
+ * PSD power value: 10.21 dBm/MHz
+ * Value to be updated in QCA_WLAN_VENDOR_ATTR_AFC_PSD_INFO: 1021.
+ *
+ * Note: QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_PSD attribute will be used only
+ * with nested attribute QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO and with
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE.
+ *
+ * The following set of attributes will be used to exchange frequency and
+ * corresponding PSD information for AFC between the user space and the driver.
+ */
+enum qca_wlan_vendor_attr_afc_freq_psd_info {
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START = 1,
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END = 2,
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_PSD = 3,
+
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_afc_chan_eirp_info: This enum is used with
+ * nested attribute QCA_WLAN_VENDOR_ATTR_AFC_CHAN_LIST_INFO to update the
+ * channel list and corresponding EIRP information.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM: Required and type is u8.
+ * This attribute is used to indicate queried channel from
+ * the operating class indicated in QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP: Optional and type is u32.
+ * This attribute is used to configure the EIRP power info corresponding
+ * to the channel number indicated in QCA_WLAN_VENDOR_ATTR_AFC_CHAN_NUM.
+ * The EIRP power info(dBm) from user space should be multiplied
+ * by a factor of 100 when sending to Driver to preserve granularity up to
+ * 2 decimal places.
+ * Example:
+ * EIRP power value: 34.23 dBm
+ * Value to be updated in QCA_WLAN_VENDOR_ATTR_AFC_EIRP_INFO: 3423.
+ *
+ * Note: QCA_WLAN_VENDOR_ATTR_AFC_EIRP_INFO attribute will only be used with
+ * nested attribute QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO and
+ * with QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_LIST when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE:
+ *
+ * The following set of attributes will be used to exchange Channel and
+ * corresponding EIRP information for AFC between the user space and Driver.
+ */
+enum qca_wlan_vendor_attr_afc_chan_eirp_info {
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM = 1,
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP = 2,
+
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_afc_opclass_info: This enum is used with nested
+ * attributes QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO and
+ * QCA_WLAN_VENDOR_ATTR_AFC_REQ_OPCLASS_CHAN_INFO to update the operating class,
+ * channel, and EIRP related information.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS: Required and type is u8.
+ * This attribute is used to indicate the operating class, as listed under
+ * IEEE Std 802.11-2020 Annex E Table E-4, for the queried channel list.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST: Array of nested attributes
+ * for updating the channel number and EIRP power information.
+ * It uses the attributes defined in
+ * enum qca_wlan_vendor_attr_afc_chan_eirp_info.
+ *
+ * Operating class information packing format for
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_INFO when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE_EXPIRY.
+ *
+ * m - Total number of operating classes.
+ * n, j - Number of queried channels for the corresponding operating class.
+ *
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[0]
+ * .....
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[n - 1]
+ * ....
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS[m]
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST[m]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[0]
+ * ....
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[j - 1]
+ *
+ * Operating class information packing format for
+ * QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO and
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_INFO when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE.
+ *
+ * m - Total number of operating classes.
+ * n, j - Number of channels for the corresponding operating class.
+ *
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP[0]
+ * .....
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[n - 1]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP[n - 1]
+ * ....
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS[m]
+ * QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST[m]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[0]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP[0]
+ * ....
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM[j - 1]
+ * QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP[j - 1]
+ *
+ * The following set of attributes will be used to exchange operating class
+ * information for AFC between the user space and the driver.
+ */
+enum qca_wlan_vendor_attr_afc_opclass_info {
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS = 1,
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST = 2,
+
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_afc_event_type: Defines values for AFC event type.
+ * Attribute used by QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE attribute.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY: AFC expiry event sent from the
+ * driver to userspace in order to query the new AFC power values.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE: Power update
+ * complete event will be sent from the driver to userspace to indicate
+ * processing of the AFC response.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVENT_TYPE_PAYLOAD_RESET: AFC payload reset event
+ * will be sent from the driver to userspace to indicate last received
+ * AFC response data has been cleared on the AP due to invalid data
+ * in the QCA_NL80211_VENDOR_SUBCMD_AFC_RESPONSE.
+ *
+ * The following enum defines the different event types that will be
+ * used by the driver to help trigger corresponding AFC functionality in user
+ * space.
+ */
+enum qca_wlan_vendor_afc_event_type {
+ QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY = 0,
+ QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE = 1,
+ QCA_WLAN_VENDOR_AFC_EVENT_TYPE_PAYLOAD_RESET = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_afc_ap_deployment_type: Defines values for AP
+ * deployment type.
+ * Attribute used by QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AP_DEPLOYMENT attribute.
+ *
+ * @QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_UNKNOWN: Unknown AP deployment.
+ *
+ * @QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_INDOOR: Indoor AP deployment.
+ *
+ * @QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_OUTDOOR: Outdoor AP deployment.
+ *
+ * The following enum defines different deployment modes that the AP might
+ * come up in. This information will be essential to retrieve deployment-type
+ * specific SP power values for AFC operation.
+ */
+enum qca_wlan_vendor_afc_ap_deployment_type {
+ QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_UNKNOWN = 0,
+ QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_INDOOR = 1,
+ QCA_WLAN_VENDOR_AFC_AP_DEPLOYMENT_TYPE_OUTDOOR = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_afc_evt_status_code: Defines values AP will use to
+ * indicate AFC response status.
+ * Enum used by QCA_WLAN_VENDOR_ATTR_AFC_EVENT_STATUS_CODE attribute.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_SUCCESS: Success
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_TIMEOUT: Indicates AFC indication
+ * command was not received within the expected time of the AFC expiry event
+ * being triggered.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_PARSING_ERROR: Indicates AFC data
+ * parsing error by the driver.
+ *
+ * @QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_LOCAL_ERROR: Indicates any other local
+ * error.
+ *
+ * The following enum defines the status codes that the driver will use to
+ * indicate whether the AFC data is valid or not.
+ */
+enum qca_wlan_vendor_afc_evt_status_code {
+ QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_SUCCESS = 0,
+ QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_TIMEOUT = 1,
+ QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_PARSING_ERROR = 2,
+ QCA_WLAN_VENDOR_AFC_EVT_STATUS_CODE_LOCAL_ERROR = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_afc_event: Defines attributes to be used with
+ * vendor event QCA_NL80211_VENDOR_SUBCMD_AFC_EVENT. These attributes will
+ * support sending only a single request to the user space at a time.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE: Required u8 attribute.
+ * Used with event to notify the type of AFC event received.
+ * Valid values are defined in enum qca_wlan_vendor_afc_event_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AP_DEPLOYMENT: u8 attribute. Required when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY,
+ * otherwise unused.
+ *
+ * This attribute is used to indicate the AP deployment type in the AFC request.
+ * Valid values are defined in enum qca_wlan_vendor_afc_ap_deployment_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID: Required u32 attribute.
+ * Unique request identifier generated by the AFC client for every
+ * AFC expiry event trigger. See also QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID.
+ * The user space application is responsible for ensuring no duplicate values
+ * are in-flight with the server, e.g., by delaying a request, should the same
+ * value be received from different radios in parallel.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AFC_WFA_VERSION: u32 attribute. Optional.
+ * It is used when the QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY, otherwise unused.
+ *
+ * This attribute indicates the AFC spec version information. This will
+ * indicate the AFC version AFC client must use to query the AFC data.
+ * Bits 15:0 - Minor version
+ * Bits 31:16 - Major version
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_MIN_DES_POWER: u16 attribute. Required when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY,
+ * otherwise unused.
+ * This attribute indicates the minimum desired power (in dBm) for
+ * the queried spectrum.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_STATUS_CODE: u8 attribute. Required when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ *
+ * Valid values are defined in enum qca_wlan_vendor_afc_evt_status_code.
+ * This attribute is used to indicate if there were any errors parsing the
+ * AFC response.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_SERVER_RESP_CODE: s32 attribute. Required
+ * when QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ *
+ * This attribute indicates the AFC response code. The AFC response codes are
+ * in the following categories:
+ * -1: General Failure.
+ * 0: Success.
+ * 100 - 199: General errors related to protocol.
+ * 300 - 399: Error events specific to message exchange
+ * for the Available Spectrum Inquiry.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_DATE: u32 attribute. Required when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ *
+ * This attribute indicates the date until which the current response is
+ * valid for in UTC format.
+ * Date format: bits 7:0 - DD (Day 1-31)
+ * bits 15:8 - MM (Month 1-12)
+ * bits 31:16 - YYYY (Year)
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_TIME: u32 attribute. Required when
+ * QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ *
+ * This attribute indicates the time until which the current response is
+ * valid for in UTC format.
+ * Time format: bits 7:0 - SS (Seconds 0-59)
+ * bits 15:8 - MM (Minutes 0-59)
+ * bits 23:16 - HH (Hours 0-23)
+ * bits 31:24 - Reserved
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST: Array of nested attributes
+ * for updating the list of frequency ranges to be queried.
+ * Required when QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY or
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ * It uses the attributes defined in
+ * enum qca_wlan_vendor_attr_afc_freq_psd_info.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_LIST: Array of nested attributes
+ * for updating the list of operating classes and corresponding channels to be
+ * queried.
+ * Required when QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE is
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY or
+ * QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE, otherwise unused.
+ * It uses the attributes defined in enum qca_wlan_vendor_attr_afc_opclass_info.
+ */
+enum qca_wlan_vendor_attr_afc_event {
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AP_DEPLOYMENT = 2,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AFC_WFA_VERSION = 4,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_MIN_DES_POWER = 5,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_STATUS_CODE = 6,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_SERVER_RESP_CODE = 7,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_DATE = 8,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_TIME = 9,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST = 10,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_LIST = 11,
+
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_MAX =
+ QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_afc_response: Defines attributes to be used
+ * with vendor command QCA_NL80211_VENDOR_SUBCMD_AFC_RESPONSE. These attributes
+ * will support sending only a single AFC response to the driver at a time.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_DATA: Type is NLA_STRING. Required attribute.
+ * This attribute will be used to send a single Spectrum Inquiry response object
+ * from the 'availableSpectrumInquiryResponses' array object from the response
+ * JSON.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_TIME_TO_LIVE: Required u32 attribute.
+ *
+ * This attribute indicates the period (in seconds) for which the response
+ * data received is valid for.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID: Required u32 attribute.
+ *
+ * This attribute indicates the request ID for which the corresponding
+ * response is being sent for. See also QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_DATE: Required u32 attribute.
+ *
+ * This attribute indicates the date until which the current response is
+ * valid for in UTC format.
+ * Date format: bits 7:0 - DD (Day 1-31)
+ * bits 15:8 - MM (Month 1-12)
+ * bits 31:16 - YYYY (Year)
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_TIME: Required u32 attribute.
+ *
+ * This attribute indicates the time until which the current response is
+ * valid for in UTC format.
+ * Time format: bits 7:0 - SS (Seconds 0-59)
+ * bits 15:8 - MM (Minutes 0-59)
+ * bits 23:16 - HH (Hours 0-23)
+ * bits 31:24 - Reserved
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFC_SERVER_RESP_CODE: Required s32 attribute.
+ *
+ * This attribute indicates the AFC response code. The AFC response codes are
+ * in the following categories:
+ * -1: General Failure.
+ * 0: Success.
+ * 100 - 199: General errors related to protocol.
+ * 300 - 399: Error events specific to message exchange
+ * for the Available Spectrum Inquiry.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO: Array of nested attributes
+ * for PSD info of all the queried frequency ranges. It uses the attributes
+ * defined in enum qca_wlan_vendor_attr_afc_freq_psd_info. Required attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO: Array of nested
+ * attributes for EIRP info of all queried operating class/channels. It uses
+ * the attributes defined in enum qca_wlan_vendor_attr_afc_opclass_info and
+ * enum qca_wlan_vendor_attr_afc_chan_eirp_info. Required attribute.
+ *
+ */
+enum qca_wlan_vendor_attr_afc_response {
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_DATA = 1,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_TIME_TO_LIVE = 2,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_DATE = 4,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_TIME = 5,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFC_SERVER_RESP_CODE = 6,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO = 7,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO = 8,
+
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_MAX =
+ QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_dozed_ap_state - Doze states for AP interface
+ *
+ * @QCA_WLAN_DOZED_AP_DISABLE: Disable doze state on the AP interface.
+ *
+ * @QCA_WLAN_DOZED_AP_ENABLE: Enable doze state on the AP interface. AP starts
+ * beaconing at higher beacon interval with Rx disabled.
+ */
+enum qca_wlan_dozed_ap_state {
+ QCA_WLAN_DOZED_AP_DISABLE = 0,
+ QCA_WLAN_DOZED_AP_ENABLE = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_dozed_ap - Used by the vendor command
+ * @QCA_NL80211_VENDOR_SUBCMD_DOZED_AP to configure or receive dozed AP mode
+ * configuration.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DOZED_AP_STATE: u8 attribute.
+ * Configures the doze state for an AP interface. Possible values are defined
+ * in enum qca_wlan_dozed_ap_state. @QCA_NL80211_VENDOR_SUBCMD_DOZED_AP event
+ * gets triggered asynchronously to provide updated AP interface configuration.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DOZED_AP_COOKIE: Unsigned 64-bit cookie provided by
+ * the driver in the response to specific @QCA_NL80211_VENDOR_SUBCMD_DOZED_AP
+ * command, which is used later to maintain synchronization between commands
+ * and asynchronous events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DOZED_AP_NEXT_TSF: u64 attribute.
+ * Used in event to indicate the next TBTT TSF timer value after applying the
+ * doze mode configuration. Next TBTT TSF is the time at which the AP sends
+ * the first beacon after entering or exiting dozed mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DOZED_AP_BI_MULTIPLIER: u16 attribute.
+ * Used with event to inform the periodicity of beacon transmission that would
+ * be skipped at all TBTTs in between.
+ */
+enum qca_wlan_vendor_attr_dozed_ap {
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_STATE = 1,
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_COOKIE = 2,
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_NEXT_TSF = 3,
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_BI_MULTIPLIER = 4,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_MAX =
+ QCA_WLAN_VENDOR_ATTR_DOZED_AP_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/wcn6740/qcwcn/wifi_hal/radio_mode.cpp b/wcn6740/qcwcn/wifi_hal/radio_mode.cpp
new file mode 100644
index 0000000..267d3f4
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/radio_mode.cpp
@@ -0,0 +1,321 @@
+/* Copyright (c) 2017-2018, 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "radio_mode.h"
+#include "vendor_definitions.h"
+#include <netlink/genl/genl.h>
+#include <string.h>
+#include <net/if.h>
+
+/* Used to handle radio command events from driver/firmware. */
+typedef struct radio_event_handler_s {
+ RADIOModeCommand* mRADIOModeCommandInstance;
+} radio_event_handlers;
+
+wifi_error initializeRadioHandler(hal_info *info)
+{
+ info->radio_handlers = (radio_event_handlers *)malloc(
+ sizeof(radio_event_handlers));
+ if (info->radio_handlers) {
+ memset(info->radio_handlers, 0, sizeof(radio_event_handlers));
+ } else {
+ ALOGE("%s: Allocation of radio event handlers failed",
+ __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error cleanupRadioHandler(hal_info *info) {
+ radio_event_handlers* event_handlers;
+ if (info && info->radio_handlers) {
+ event_handlers = (radio_event_handlers*) info->radio_handlers;
+ if (event_handlers->mRADIOModeCommandInstance) {
+ delete event_handlers->mRADIOModeCommandInstance;
+ }
+ memset(event_handlers, 0, sizeof(radio_event_handlers));
+ free(info->radio_handlers);
+ info->radio_handlers = NULL;
+ return WIFI_SUCCESS;
+ }
+ ALOGE ("%s: info or info->radio_handlers NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+}
+
+/* Used to handle radio mode command events from driver/firmware.*/
+void RADIOModeCommand::setCallbackHandler(wifi_radio_mode_change_handler handler)
+{
+ mHandler = handler;
+}
+
+void RADIOModeCommand::setReqId(wifi_request_id id)
+{
+ mreqId = id;
+}
+
+RADIOModeCommand::RADIOModeCommand(wifi_handle handle, int id,
+ u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mHandler, 0, sizeof(mHandler));
+ if (registerVendorHandler(vendor_id, subcmd)) {
+ /* Error case should not happen print log */
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
+ __FUNCTION__, vendor_id, subcmd);
+ }
+}
+
+RADIOModeCommand::~RADIOModeCommand()
+{
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+}
+
+
+RADIOModeCommand* RADIOModeCommand::instance(wifi_handle handle,
+ wifi_request_id id)
+{
+ if (handle == NULL) {
+ ALOGE("Interface Handle is invalid");
+ return NULL;
+ }
+ hal_info *info = getHalInfo(handle);
+ if (!info) {
+ ALOGE("hal_info is invalid");
+ return NULL;
+ }
+ RADIOModeCommand* instance = info->radio_handlers->mRADIOModeCommandInstance;
+ if (instance) {
+ if (handle != getWifiHandle(instance->mInfo)) {
+ ALOGV("%s - Handle different, update the handle", __FUNCTION__);
+ instance->mInfo = (hal_info *)handle;
+ }
+ instance->setReqId(id);
+ } else {
+ info->radio_handlers->mRADIOModeCommandInstance =
+ new RADIOModeCommand(handle, id, OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO);
+ instance = info->radio_handlers->mRADIOModeCommandInstance;
+ }
+ return instance;
+}
+
+/* This function will be the main handler for incoming event.
+ * Call the appropriate callback handler after parsing the vendor data.
+ */
+int RADIOModeCommand::handleEvent(WifiEvent &event)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ int num_of_mac = 0;
+ wifi_mac_info mode_info;
+ memset(&mode_info, 0, sizeof(mode_info));
+
+ WifiVendorCommand::handleEvent(event);
+
+ /* Parse the vendordata and get the attribute */
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO:
+ {
+ struct nlattr *mtb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_MAX + 1];
+ struct nlattr *modeInfo;
+ int rem;
+
+ nla_parse(mtb_vendor, QCA_WLAN_VENDOR_ATTR_MAC_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (mtb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_INFO])
+ {
+ for (modeInfo = (struct nlattr *) nla_data(mtb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_INFO]),
+ rem = nla_len(mtb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_INFO]);
+ nla_ok(modeInfo, rem);modeInfo = nla_next(modeInfo, &(rem))) {
+
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX+ 1];
+ nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX,
+ (struct nlattr *) nla_data(modeInfo), nla_len(modeInfo), NULL);
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID"
+ " not found", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ mode_info.wlan_mac_id = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID]);
+ ALOGV("mac_id[%d]: %d ", num_of_mac, mode_info.wlan_mac_id);
+
+ if (!tb2[QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND"
+ " NOT FOUND", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ mode_info.mac_band = (wlan_mac_band) nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND]);
+ ALOGV("mac_band[%d]: %d ", num_of_mac, mode_info.mac_band);
+
+ if (tb2[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO])
+ {
+ int num_of_iface = 0;
+ struct nlattr *tb_iface;
+ int rem_info;
+
+ for (tb_iface = (struct nlattr *) nla_data(tb2[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO]),
+ rem_info = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO]);
+ nla_ok(tb_iface, rem_info);tb_iface = nla_next(tb_iface, &(rem_info))) {
+
+ struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX+ 1];
+ wifi_iface_info miface_info;
+
+ nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX,
+ (struct nlattr *) nla_data(tb_iface), nla_len(tb_iface), NULL);
+
+ if (!tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX"
+ " NOT FOUND", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ if (if_indextoname(nla_get_u32(tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX]),
+ miface_info.iface_name) == NULL)
+ {
+ ALOGE("%s: Failed to convert %d IFINDEX to IFNAME", __FUNCTION__,
+ nla_get_u32(tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX]));
+ }
+ ALOGV("ifname[%d]: %s ", num_of_iface, miface_info.iface_name);
+
+ if (!tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ"
+ " NOT FOUND", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ miface_info.channel = nla_get_u32(tb3[QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ]);
+ ALOGV("channel[%d]: %d ", num_of_iface, miface_info.channel);
+
+ if (!num_of_iface)
+ mode_info.iface_info = (wifi_iface_info *)
+ malloc(sizeof(wifi_iface_info));
+ else
+ mode_info.iface_info = (wifi_iface_info *)
+ realloc(mode_info.iface_info, (num_of_iface + 1) * sizeof(wifi_iface_info));
+
+ if (mode_info.iface_info != NULL) {
+ memcpy(&mode_info.iface_info[num_of_iface], &miface_info, sizeof(wifi_iface_info));
+ num_of_iface++;
+ mode_info.num_iface = num_of_iface;
+ }
+ }
+ }
+ if (!num_of_mac)
+ mwifi_iface_mac_info = (wifi_mac_info *)
+ malloc(sizeof(wifi_mac_info));
+ else
+ mwifi_iface_mac_info = (wifi_mac_info *)
+ realloc(mwifi_iface_mac_info, (num_of_mac + 1) * (sizeof(wifi_mac_info)));
+
+ if (mwifi_iface_mac_info != NULL) {
+ memcpy(&mwifi_iface_mac_info[num_of_mac], &mode_info, sizeof(wifi_mac_info));
+ num_of_mac++;
+ }
+ }
+ }
+
+ if (mHandler.on_radio_mode_change && num_of_mac) {
+ (*mHandler.on_radio_mode_change)(mreqId, num_of_mac, mwifi_iface_mac_info);
+ }
+ else {
+ ALOGE("No Callback registered: on radio mode change");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ret = WIFI_SUCCESS;
+ }
+ break;
+
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+
+cleanup:
+ if (mode_info.iface_info != NULL) {
+ free(mode_info.iface_info);
+ mode_info.iface_info = NULL;
+ }
+ if (mwifi_iface_mac_info != NULL) {
+ free(mwifi_iface_mac_info);
+ mwifi_iface_mac_info = NULL;
+ }
+
+ return ret;
+}
+
+wifi_error wifi_set_radio_mode_change_handler(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_radio_mode_change_handler eh)
+{
+ wifi_error ret;
+ WifiVendorCommand *vCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ RADIOModeCommand *radiomodeCommand;
+
+ ret = initialize_vendor_cmd(iface, id,
+ QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
+ &vCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ radiomodeCommand = RADIOModeCommand::instance(wifiHandle, id);
+ if (radiomodeCommand == NULL) {
+ ALOGE("%s: Error RadioModeCommand NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ radiomodeCommand->setCallbackHandler(eh);
+ radiomodeCommand->setReqId(id);
+
+cleanup:
+ delete vCommand;
+ return mapKernelErrortoWifiHalError(ret);
+}
diff --git a/wcn6740/qcwcn/wifi_hal/radio_mode.h b/wcn6740/qcwcn/wifi_hal/radio_mode.h
new file mode 100644
index 0000000..d6a4e92
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/radio_mode.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2017-2018, 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 __WIFI_HAL_RADIO_MODE_COMMAND_H__
+#define __WIFI_HAL_RADIO_MODE_COMMAND_H__
+
+#include "cpp_bindings.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+class RADIOModeCommand: public WifiVendorCommand
+{
+private:
+ static RADIOModeCommand *mRADIOModeCommandInstance;
+ wifi_radio_mode_change_handler mHandler;
+ wifi_request_id mreqId;
+ wifi_mac_info *mwifi_iface_mac_info;
+ RADIOModeCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+
+public:
+ virtual ~RADIOModeCommand();
+ static RADIOModeCommand* instance(wifi_handle handle, wifi_request_id id);
+ virtual int handleEvent(WifiEvent &event);
+ virtual void setReqId(wifi_request_id reqid);
+ virtual void setCallbackHandler(wifi_radio_mode_change_handler nHandler);
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/qcwcn/wifi_hal/rb_wrapper.cpp b/wcn6740/qcwcn/wifi_hal/rb_wrapper.cpp
similarity index 96%
copy from qcwcn/wifi_hal/rb_wrapper.cpp
copy to wcn6740/qcwcn/wifi_hal/rb_wrapper.cpp
index 4c9e475..9083725 100644
--- a/qcwcn/wifi_hal/rb_wrapper.cpp
+++ b/wcn6740/qcwcn/wifi_hal/rb_wrapper.cpp
@@ -106,7 +106,11 @@
return WIFI_ERROR_UNKNOWN;
}
- rb_info->written_records += no_of_records;
+ if (rb_info->written_records < (UINT_MAX - 1))
+ rb_info->written_records += no_of_records;
+ else
+ rb_info->written_records = 0;
+
return WIFI_SUCCESS;
}
@@ -117,7 +121,7 @@
wifi_ring_buffer_status rbs;
wifi_ring_buffer_data_handler handler;
- while (1) {
+ while (info && !info->clean_up) {
size_t length = 0;
u8 *buf;
diff --git a/qcwcn/wifi_hal/rb_wrapper.h b/wcn6740/qcwcn/wifi_hal/rb_wrapper.h
similarity index 100%
copy from qcwcn/wifi_hal/rb_wrapper.h
copy to wcn6740/qcwcn/wifi_hal/rb_wrapper.h
diff --git a/qcwcn/wifi_hal/ring_buffer.cpp b/wcn6740/qcwcn/wifi_hal/ring_buffer.cpp
similarity index 90%
copy from qcwcn/wifi_hal/ring_buffer.cpp
copy to wcn6740/qcwcn/wifi_hal/ring_buffer.cpp
index d78bd62..5918923 100644
--- a/qcwcn/wifi_hal/ring_buffer.cpp
+++ b/wcn6740/qcwcn/wifi_hal/ring_buffer.cpp
@@ -70,9 +70,9 @@
void (*threshold_cb)(void *);
void *cb_ctx;
- u32 total_bytes_written;
- u32 total_bytes_read;
- u32 total_bytes_overwritten;
+ u64 total_bytes_written;
+ u64 total_bytes_read;
+ u64 total_bytes_overwritten;
u32 cur_valid_bytes;
enum rb_bool threshold_reached;
} rbc_t;
@@ -160,7 +160,7 @@
// write in current buffer
unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
- if (record_length > rbc->each_buf_size) {
+ if (record_length > rbc->each_buf_size || length > rbc->each_buf_size) {
return RB_FAILURE;
}
@@ -279,6 +279,17 @@
}
}
rb_unlock(&rbc->rb_rw_lock);
+ if(rbc->bufs[rbc->wr_buf_no].data == NULL || (rbc->bufs[rbc->wr_buf_no].data + rbc->cur_wr_buf_idx) == NULL ||
+ buf == NULL || buf + bytes_written == NULL) {
+ ALOGE("The read or Write buffer is null");
+ return RB_FAILURE;
+ }
+ if (((bytes_written + cur_copy_len) > length
+ || (rbc->cur_wr_buf_idx + cur_copy_len) > rbc->each_buf_size)) {
+ ALOGE("LOG_RB rb_write overflow - cur_copy_len=%d wr_buf[max=%zu no=%d idx=%d] buf[max=%zu accessed=%d]",
+ cur_copy_len, rbc->each_buf_size, rbc->wr_buf_no, rbc->cur_wr_buf_idx, length, bytes_written + cur_copy_len);
+ return RB_FAILURE;
+ }
/* don't use lock while doing memcpy, so that we don't block the read
* context for too long. There is no harm while writing the memory if
@@ -476,15 +487,33 @@
cur_read_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
} else {
/* write is rolled over and just behind the read */
- cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ if (rbc->bufs[rbc->rd_buf_no].last_wr_index >= rbc->cur_rd_buf_idx) {
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ } else {
+ ALOGE("Alert: cur_read_len=%u invalid, rd_buf[no=%d rd_idx=%d wr_index=%d]",cur_read_len, rbc->rd_buf_no, rbc->cur_rd_buf_idx, rbc->bufs[rbc->rd_buf_no].last_wr_index);
+ rb_unlock(&rbc->rb_rw_lock);
+ return NULL;
+ }
}
} else {
if (rbc->cur_rd_buf_idx == 0) {
/* The complete buffer can be read out */
cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index;
} else {
- /* Read the remaining bytes in this buffer */
- cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ if ( rbc->bufs[rbc->rd_buf_no].last_wr_index >= rbc->cur_rd_buf_idx) {
+ /* Read the remaining bytes in this buffer */
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+ }
+ else {
+ ALOGE("Alert: cur_read_len invalid cur_read_len = %u, cur_rd_buf_idx = %u, last_write_index = %u, read_buf_no = %u, max_num_bufs = %u", cur_read_len, rbc->cur_rd_buf_idx, rbc->bufs[rbc->rd_buf_no].last_wr_index, rbc->rd_buf_no,rbc->max_num_bufs);
+ /* Move to the next buffer */
+ rbc->bufs[rbc->rd_buf_no].full = 0;
+ rbc->rd_buf_no++;
+ if (rbc->rd_buf_no == rbc->max_num_bufs) {
+ ALOGV("Read rolling over to the start of ring buffer");
+ rbc->rd_buf_no = 0;
+ }
+ }
}
}
diff --git a/qcwcn/wifi_hal/ring_buffer.h b/wcn6740/qcwcn/wifi_hal/ring_buffer.h
similarity index 100%
copy from qcwcn/wifi_hal/ring_buffer.h
copy to wcn6740/qcwcn/wifi_hal/ring_buffer.h
diff --git a/wcn6740/qcwcn/wifi_hal/roam.cpp b/wcn6740/qcwcn/wifi_hal/roam.cpp
new file mode 100644
index 0000000..bd93c3d
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/roam.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include <errno.h>
+
+#include "common.h"
+#include "roamcommand.h"
+
+#define WLAN_ROAM_MAX_NUM_WHITE_LIST 8
+#define WLAN_ROAM_MAX_NUM_BLACK_LIST 16
+
+RoamCommand::RoamCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+}
+
+RoamCommand::~RoamCommand()
+{
+}
+
+/* This function implements creation of Vendor command */
+wifi_error RoamCommand::create() {
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ /* Insert the oui in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+ /* Insert the subcmd in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
+ __FUNCTION__, mVendor_id, mSubcmd);
+ return ret;
+}
+
+wifi_error RoamCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+wifi_error wifi_set_bssid_blacklist(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_bssid_params params)
+{
+ wifi_error ret;
+ int i;
+ RoamCommand *roamCommand;
+ struct nlattr *nlData, *nlBssids;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_CONTROL_ROAMING)) {
+ ALOGE("%s: Roaming is not supported by driver",
+ __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ for (i = 0; i < params.num_bssid; i++) {
+ ALOGV("BSSID: %d : %02x:%02x:%02x:%02x:%02x:%02x", i,
+ params.bssids[i][0], params.bssids[i][1],
+ params.bssids[i][2], params.bssids[i][3],
+ params.bssids[i][4], params.bssids[i][5]);
+ }
+
+ roamCommand =
+ new RoamCommand(wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM);
+ if (roamCommand == NULL) {
+ ALOGE("%s: Error roamCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = roamCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = roamCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = roamCommand->put_u32( QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID, id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = roamCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
+ params.num_bssid);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ nlBssids = roamCommand->attr_start(
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
+ for (i = 0; i < params.num_bssid; i++) {
+ struct nlattr *nl_ssid = roamCommand->attr_start(i);
+
+ ret = roamCommand->put_addr(
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
+ (u8 *)params.bssids[i]);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ roamCommand->attr_end(nl_ssid);
+ }
+ roamCommand->attr_end(nlBssids);
+
+ roamCommand->attr_end(nlData);
+
+ ret = roamCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("wifi_set_bssid_blacklist(): requestResponse Error:%d", ret);
+
+cleanup:
+ delete roamCommand;
+ return ret;
+
+}
+
+wifi_error wifi_set_ssid_white_list(wifi_request_id id, wifi_interface_handle iface,
+ int num_networks, ssid_t *ssid_list)
+{
+ wifi_error ret;
+ int i;
+ RoamCommand *roamCommand;
+ struct nlattr *nlData, *nlSsids;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ char ssid[MAX_SSID_LENGTH + 1];
+
+ ALOGV("%s: Number of SSIDs : %d", __FUNCTION__, num_networks);
+
+ roamCommand = new RoamCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM);
+ if (roamCommand == NULL) {
+ ALOGE("%s: Failed to create object of RoamCommand class", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = roamCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create NL message, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = roamCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set interface Id of message, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID, id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
+ num_networks);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ nlSsids = roamCommand->attr_start(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST);
+ for (i = 0; i < num_networks; i++) {
+ struct nlattr *nl_ssid = roamCommand->attr_start(i);
+
+ memcpy(ssid, ssid_list[i].ssid_str, ssid_list[i].length);
+ ssid[ssid_list[i].length] = '\0';
+ ALOGV("ssid[%d] : %s", i, ssid);
+
+ ret = roamCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID,
+ ssid, (ssid_list[i].length + 1));
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to add ssid atribute, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ roamCommand->attr_end(nl_ssid);
+ }
+ roamCommand->attr_end(nlSsids);
+
+ roamCommand->attr_end(nlData);
+
+ ret = roamCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete roamCommand;
+ return ret;
+}
+
+wifi_error wifi_get_roaming_capabilities(wifi_interface_handle iface,
+ wifi_roaming_capabilities *caps)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!caps) {
+ ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!info) {
+ ALOGE("%s: hal_info is NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ // Per WiFi HAL design, roaming feature should have nothing to do with Gscan
+ // But for current driver impl, roaming_capa is provided as part of
+ // GSCAN_GET_CAPABILITY query, so if Gscan is not supported, roaming_capa
+ // is not set (uses initial value 0).
+ // To de-couple roaming with Gscan, set default values for roaming_capa
+ // if Gscan is not supported.
+ // TODO: removes below if driver has new API to get roaming_capa.
+ if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
+ info->capa.roaming_capa.max_whitelist_size = WLAN_ROAM_MAX_NUM_WHITE_LIST;
+ info->capa.roaming_capa.max_blacklist_size = WLAN_ROAM_MAX_NUM_BLACK_LIST;
+ }
+ memcpy(caps, &info->capa.roaming_capa, sizeof(wifi_roaming_capabilities));
+
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_configure_roaming(wifi_interface_handle iface, wifi_roaming_config *roaming_config)
+{
+ wifi_error ret;
+ int requestId;
+ wifi_bssid_params bssid_params;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (!roaming_config) {
+ ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate it randomly.
+ */
+ requestId = get_requestid();
+
+ /* Set bssid blacklist */
+ if (roaming_config->num_blacklist_bssid > info->capa.roaming_capa.max_blacklist_size) {
+ ALOGE("%s: Number of blacklist bssids(%d) provided is more than maximum blacklist bssids(%d)"
+ " supported", __FUNCTION__, roaming_config->num_blacklist_bssid,
+ info->capa.roaming_capa.max_blacklist_size);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ bssid_params.num_bssid = roaming_config->num_blacklist_bssid;
+
+ memcpy(bssid_params.bssids, roaming_config->blacklist_bssid,
+ (bssid_params.num_bssid * sizeof(mac_addr)));
+
+ ret = wifi_set_bssid_blacklist(requestId, iface, bssid_params);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to configure blacklist bssids", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Set ssid whitelist */
+ if (roaming_config->num_whitelist_ssid > info->capa.roaming_capa.max_whitelist_size) {
+ ALOGE("%s: Number of whitelist ssid(%d) provided is more than maximum whitelist ssids(%d) "
+ "supported", __FUNCTION__, roaming_config->num_whitelist_ssid,
+ info->capa.roaming_capa.max_whitelist_size);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ // Framework is always sending SSID length as 32 though null terminated lengths
+ // are lesser. Thus update correct lengths before sending to driver.
+ for (int i = 0; i < roaming_config->num_whitelist_ssid; i++) {
+ int j;
+
+ for (j = 0; j < roaming_config->whitelist_ssid[i].length; j++) {
+ if (roaming_config->whitelist_ssid[i].ssid_str[j] == '\0')
+ break;
+ }
+
+ if (roaming_config->whitelist_ssid[i].length == j)
+ continue;
+
+ ALOGI("%s: ssid_str %s reported length = %d , null terminated length = %d", __FUNCTION__,
+ roaming_config->whitelist_ssid[i].ssid_str,
+ roaming_config->whitelist_ssid[i].length, j);
+ roaming_config->whitelist_ssid[i].length = j;
+ }
+
+ ret = wifi_set_ssid_white_list(requestId, iface, roaming_config->num_whitelist_ssid,
+ roaming_config->whitelist_ssid);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Failed to configure whitelist ssids", __FUNCTION__);
+
+ return ret;
+}
+
+/* Enable/disable firmware roaming */
+wifi_error wifi_enable_firmware_roaming(wifi_interface_handle iface, fw_roaming_state_t state)
+{
+ int requestId;
+ wifi_error ret;
+ RoamCommand *roamCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ qca_roaming_policy policy;
+
+ ALOGV("%s: set firmware roam state : %d", __FUNCTION__, state);
+
+ if (state == ROAMING_ENABLE) {
+ policy = QCA_ROAMING_ALLOWED_WITHIN_ESS;
+ } else if(state == ROAMING_DISABLE) {
+ policy = QCA_ROAMING_NOT_ALLOWED;
+ } else {
+ ALOGE("%s: Invalid state provided: %d. Exit \n", __FUNCTION__, state);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate it randomly.
+ */
+ requestId = get_requestid();
+
+ roamCommand =
+ new RoamCommand(wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_ROAMING);
+ if (roamCommand == NULL) {
+ ALOGE("%s: Failed to create object of RoamCommand class", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = roamCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create NL message, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = roamCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to set interface Id of message, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = roamCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = roamCommand->put_u32(QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY, policy);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to add roaming policy atribute, Error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ roamCommand->attr_end(nlData);
+
+ ret = roamCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete roamCommand;
+ return ret;
+}
diff --git a/qcwcn/wifi_hal/roamcommand.h b/wcn6740/qcwcn/wifi_hal/roamcommand.h
similarity index 100%
copy from qcwcn/wifi_hal/roamcommand.h
copy to wcn6740/qcwcn/wifi_hal/roamcommand.h
diff --git a/wcn6740/qcwcn/wifi_hal/rssi_monitor.cpp b/wcn6740/qcwcn/wifi_hal/rssi_monitor.cpp
new file mode 100644
index 0000000..a2038f8
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/rssi_monitor.cpp
@@ -0,0 +1,380 @@
+/* Copyright (c) 2015, 2018 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "rssi_monitor.h"
+
+/* Used to handle rssi command events from driver/firmware.*/
+typedef struct rssi_monitor_event_handler_s {
+ RSSIMonitorCommand* mRSSIMonitorCommandInstance;
+} rssi_monitor_event_handlers;
+
+wifi_error initializeRSSIMonitorHandler(hal_info *info)
+{
+ info->rssi_handlers = (rssi_monitor_event_handlers *)malloc(sizeof(
+ rssi_monitor_event_handlers));
+ if (info->rssi_handlers) {
+ memset(info->rssi_handlers, 0, sizeof(rssi_monitor_event_handlers));
+ }
+ else {
+ ALOGE("%s: Allocation of RSSI event handlers failed",
+ __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error cleanupRSSIMonitorHandler(hal_info *info)
+{
+ rssi_monitor_event_handlers* event_handlers;
+ if (info && info->rssi_handlers) {
+ event_handlers = (rssi_monitor_event_handlers*) info->rssi_handlers;
+ if (event_handlers->mRSSIMonitorCommandInstance) {
+ delete event_handlers->mRSSIMonitorCommandInstance;
+ }
+ memset(event_handlers, 0, sizeof(rssi_monitor_event_handlers));
+ free(info->rssi_handlers);
+ info->rssi_handlers = NULL;
+ return WIFI_SUCCESS;
+ }
+ ALOGE ("%s: info or info->rssi_handlers NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+}
+
+void RSSIMonitorCommand::enableEventHandling()
+{
+ pthread_mutex_lock(&rm_lock);
+ mEventHandlingEnabled = true;
+ pthread_mutex_unlock(&rm_lock);
+}
+
+void RSSIMonitorCommand::disableEventHandling()
+{
+ pthread_mutex_lock(&rm_lock);
+ mEventHandlingEnabled = false;
+ pthread_mutex_unlock(&rm_lock);
+}
+
+bool RSSIMonitorCommand::isEventHandlingEnabled()
+{
+ bool eventHandlingEnabled;
+ pthread_mutex_lock(&rm_lock);
+ eventHandlingEnabled = mEventHandlingEnabled;
+ pthread_mutex_unlock(&rm_lock);
+
+ return eventHandlingEnabled;
+}
+
+void RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler handler)
+{
+ mHandler = handler;
+}
+
+RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id,
+ u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mHandler, 0, sizeof(mHandler));
+ if (registerVendorHandler(vendor_id, subcmd)) {
+ /* Error case should not happen print log */
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
+ __FUNCTION__, vendor_id, subcmd);
+ }
+ pthread_mutex_init(&rm_lock, NULL);
+ disableEventHandling();
+}
+
+RSSIMonitorCommand::~RSSIMonitorCommand()
+{
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+ pthread_mutex_destroy(&rm_lock);
+}
+
+void RSSIMonitorCommand::setReqId(wifi_request_id reqid)
+{
+ mId = reqid;
+}
+
+RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle,
+ wifi_request_id id)
+{
+ if (handle == NULL) {
+ ALOGE("Interface Handle is invalid");
+ return NULL;
+ }
+ hal_info *info = getHalInfo(handle);
+ if (!info || !info->rssi_handlers) {
+ ALOGE("rssi_handlers is invalid");
+ return NULL;
+ }
+
+ RSSIMonitorCommand* mRSSIMonitorCommandInstance =
+ info->rssi_handlers->mRSSIMonitorCommandInstance;
+
+ if (mRSSIMonitorCommandInstance == NULL) {
+ mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI);
+ info->rssi_handlers->mRSSIMonitorCommandInstance = mRSSIMonitorCommandInstance;
+ return mRSSIMonitorCommandInstance;
+ }
+ else
+ {
+ if (handle != getWifiHandle(mRSSIMonitorCommandInstance->mInfo))
+ {
+ /* upper layer must have cleaned up the handle and reinitialized,
+ so we need to update the same */
+ ALOGV("Handle different, update the handle");
+ mRSSIMonitorCommandInstance->mInfo = (hal_info *)handle;
+ }
+ mRSSIMonitorCommandInstance->setReqId(id);
+ }
+ return mRSSIMonitorCommandInstance;
+}
+
+/* This function will be the main handler for incoming event.
+ * Call the appropriate callback handler after parsing the vendor data.
+ */
+int RSSIMonitorCommand::handleEvent(WifiEvent &event)
+{
+ int ret = WIFI_SUCCESS;
+
+ if (isEventHandlingEnabled() == false) {
+ ALOGE("%s: RSSI monitor isn't running or already stopped. "
+ "Nothing to do. Exit", __FUNCTION__);
+ return ret;
+ }
+
+ WifiVendorCommand::handleEvent(event);
+
+ /* Parse the vendordata and get the attribute */
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI:
+ {
+ mac_addr addr;
+ s8 rssi;
+ wifi_request_id reqId;
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
+ + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ memset(addr, 0, sizeof(mac_addr));
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID])
+ {
+ ALOGE("%s: ATTR_RSSI_MONITORING_REQUEST_ID not found. Exit.",
+ __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ reqId = nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID]
+ );
+ /* If event has a different request_id, ignore that and use the
+ * request_id value which we're maintaining.
+ */
+ if (reqId != id()) {
+ ALOGV("%s: Event has Req. ID:%d <> Ours:%d, continue...",
+ __FUNCTION__, reqId, id());
+ reqId = id();
+ }
+ ret = get_mac_addr(tb_vendor,
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
+ addr);
+ if (ret != WIFI_SUCCESS) {
+ return ret;
+ }
+ ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr));
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = get_s8(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]);
+ ALOGV("Current RSSI : %d ", rssi);
+
+ if (mHandler.on_rssi_threshold_breached)
+ (*mHandler.on_rssi_threshold_breached)(reqId, addr, rssi);
+ else
+ ALOGE("RSSI Monitoring: No Callback registered: ");
+ }
+ break;
+
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+
+ return ret;
+}
+
+wifi_error wifi_start_rssi_monitoring(wifi_request_id id,
+ wifi_interface_handle iface,
+ s8 max_rssi,
+ s8 min_rssi,
+ wifi_rssi_event_handler eh)
+{
+ wifi_error ret;
+ struct nlattr *nlData;
+ WifiVendorCommand *vCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ RSSIMonitorCommand *rssiCommand;
+
+ ret = initialize_vendor_cmd(iface, id,
+ QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
+ &vCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ ALOGV("%s: Max RSSI:%d Min RSSI:%d", __FUNCTION__,
+ max_rssi, min_rssi);
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
+ QCA_WLAN_RSSI_MONITORING_START);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
+ id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = vCommand->put_s8(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI,
+ max_rssi);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = vCommand->put_s8(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI,
+ min_rssi);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ vCommand->attr_end(nlData);
+
+ rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id);
+ if (rssiCommand == NULL) {
+ ALOGE("%s: Error rssiCommand NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ rssiCommand->setCallbackHandler(eh);
+
+ ret = vCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ rssiCommand->enableEventHandling();
+
+cleanup:
+ delete vCommand;
+ return ret;
+}
+
+wifi_error wifi_stop_rssi_monitoring(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret;
+ struct nlattr *nlData;
+ WifiVendorCommand *vCommand = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ RSSIMonitorCommand *rssiCommand;
+ rssi_monitor_event_handlers* event_handlers;
+ hal_info *info = getHalInfo(wifiHandle);
+
+ event_handlers = info->rssi_handlers;
+ rssiCommand = event_handlers->mRSSIMonitorCommandInstance;
+
+ if (rssiCommand == NULL ||
+ rssiCommand->isEventHandlingEnabled() == false) {
+ ALOGE("%s: RSSI monitor isn't running or already stopped. "
+ "Nothing to do. Exit", __FUNCTION__);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ ret = initialize_vendor_cmd(iface, id,
+ QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
+ &vCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return ret;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
+ QCA_WLAN_RSSI_MONITORING_STOP);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
+ id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ vCommand->attr_end(nlData);
+
+ ret = vCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ rssiCommand->disableEventHandling();
+
+cleanup:
+ delete vCommand;
+ return ret;
+}
diff --git a/qcwcn/wifi_hal/rssi_monitor.h b/wcn6740/qcwcn/wifi_hal/rssi_monitor.h
similarity index 100%
copy from qcwcn/wifi_hal/rssi_monitor.h
copy to wcn6740/qcwcn/wifi_hal/rssi_monitor.h
diff --git a/wcn6740/qcwcn/wifi_hal/rtt.cpp b/wcn6740/qcwcn/wifi_hal/rtt.cpp
new file mode 100644
index 0000000..785af6d
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/rtt.cpp
@@ -0,0 +1,383 @@
+/* Copyright (c) 2014, 2018 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.
+ */
+
+#define LOG_TAG "WifiHAL"
+#include <cutils/sched_policy.h>
+#include <unistd.h>
+
+#include <utils/Log.h>
+#include <time.h>
+
+#include "common.h"
+#include "cpp_bindings.h"
+#include "rtt.h"
+#include "wifi_hal.h"
+#include "wifihal_internal.h"
+
+/* Implementation of the API functions exposed in rtt.h */
+wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
+ wifi_rtt_capabilities *capabilities)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (capabilities == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* RTT commands are diverted through LOWI interface. */
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
+ * LOWI if it isn't up yet.
+ */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->get_rtt_capabilities == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.");
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = (wifi_error)lowiWifiHalApi->get_rtt_capabilities(iface, capabilities);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("wifi_get_rtt_capabilities: lowi_wifihal_get_rtt_capabilities "
+ "returned error:%d. Exit.", ret);
+
+ return ret;
+}
+
+/* API to request RTT measurement */
+wifi_error wifi_rtt_range_request(wifi_request_id id,
+ wifi_interface_handle iface,
+ unsigned num_rtt_config,
+ wifi_rtt_config rtt_config[],
+ wifi_rtt_event_handler handler)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+ hal_info *info = NULL;
+
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ info = getHalInfo(wifiHandle);
+ if (!info)
+ {
+ ALOGE("%s: hal_info is null ", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_D2AP_RTT)) {
+ ALOGE("%s: RTT is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (rtt_config == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL rtt_config pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (num_rtt_config <= 0) {
+ ALOGE("wifi_rtt_range_request: number of destination BSSIDs to "
+ "measure RTT on = 0. Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (handler.on_rtt_results == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* RTT commands are diverted through LOWI interface. */
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
+ * LOWI if it isn't up yet.
+ */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->rtt_range_request == NULL) {
+ ALOGE("wifi_rtt_range_request: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.");
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = (wifi_error)lowiWifiHalApi->rtt_range_request(id, iface,
+ num_rtt_config,
+ rtt_config, handler);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("wifi_rtt_range_request: lowi_wifihal_rtt_range_request "
+ "returned error:%d. Exit.", ret);
+
+ return ret;
+}
+
+/* API to cancel RTT measurements */
+wifi_error wifi_rtt_range_cancel(wifi_request_id id,
+ wifi_interface_handle iface,
+ unsigned num_devices,
+ mac_addr addr[])
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (addr == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL addr pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (num_devices <= 0) {
+ ALOGE("wifi_rtt_range_cancel: number of destination BSSIDs to "
+ "measure RTT on = 0. Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* RTT commands are diverted through LOWI interface. */
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
+ * LOWI if it isn't up yet.
+ */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->rtt_range_cancel == NULL) {
+ ALOGE("wifi_rtt_range_cancel: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.");
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = (wifi_error)lowiWifiHalApi->rtt_range_cancel(id, num_devices, addr);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("wifi_rtt_range_cancel: lowi_wifihal_rtt_range_cancel "
+ "returned error:%d. Exit.", ret);
+
+ return ret;
+}
+
+// API to configure the LCI. Used in RTT Responder mode only
+wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface,
+ wifi_lci_information *lci)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL) {
+ ALOGE("%s: NULL iface pointer provided."
+ " Exit.", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (lci == NULL) {
+ ALOGE("%s: NULL lci pointer provided."
+ " Exit.", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* RTT commands are diverted through LOWI interface. */
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
+ * LOWI if it isn't up yet.
+ */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->rtt_set_lci == NULL) {
+ ALOGE("%s: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = lowiWifiHalApi->rtt_set_lci(id, iface, lci);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
+
+ return ret;
+}
+
+// API to configure the LCR. Used in RTT Responder mode only.
+wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface,
+ wifi_lcr_information *lcr)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL) {
+ ALOGE("%s: NULL iface pointer provided."
+ " Exit.", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (lcr == NULL) {
+ ALOGE("%s: NULL lcr pointer provided."
+ " Exit.", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* RTT commands are diverted through LOWI interface. */
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
+ * LOWI if it isn't up yet.
+ */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->rtt_set_lcr == NULL) {
+ ALOGE("%s: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = lowiWifiHalApi->rtt_set_lcr(id, iface, lcr);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
+
+ return ret;
+}
+
+/*
+ * Get RTT responder information e.g. WiFi channel to enable responder on.
+ */
+wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
+ wifi_rtt_responder *responder_info)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL || responder_info == NULL) {
+ ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface,
+ responder_info);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->rtt_get_responder_info == NULL) {
+ ALOGE("%s: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = lowiWifiHalApi->rtt_get_responder_info(iface, responder_info);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
+
+ return ret;
+}
+
+/**
+ * Enable RTT responder mode.
+ * channel_hint - hint of the channel information where RTT responder should
+ * be enabled on.
+ * max_duration_seconds - timeout of responder mode.
+ * responder_info - responder information e.g. channel used for RTT responder,
+ * NULL if responder is not enabled.
+ */
+wifi_error wifi_enable_responder(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_channel_info channel_hint,
+ unsigned max_duration_seconds,
+ wifi_rtt_responder *responder_info)
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL || responder_info == NULL) {
+ ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface, responder_info);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->enable_responder == NULL) {
+ ALOGE("%s: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = lowiWifiHalApi->enable_responder(id, iface, channel_hint,
+ max_duration_seconds,
+ responder_info);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
+
+ return ret;
+}
+
+
+/**
+ * Disable RTT responder mode.
+ */
+wifi_error wifi_disable_responder(wifi_request_id id,
+ wifi_interface_handle iface)
+
+{
+ wifi_error ret;
+ lowi_cb_table_t *lowiWifiHalApi = NULL;
+
+ if (iface == NULL) {
+ ALOGE("%s: iface : %p", __FUNCTION__, iface);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
+ lowiWifiHalApi = getLowiCallbackTable(
+ ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ if (lowiWifiHalApi == NULL ||
+ lowiWifiHalApi->disable_responder == NULL) {
+ ALOGE("%s: getLowiCallbackTable returned NULL or "
+ "the function pointer is NULL. Exit.", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = lowiWifiHalApi->disable_responder(id, iface);
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
+
+ return ret;
+}
diff --git a/qcwcn/wifi_hal/sync.h b/wcn6740/qcwcn/wifi_hal/sync.h
similarity index 100%
copy from qcwcn/wifi_hal/sync.h
copy to wcn6740/qcwcn/wifi_hal/sync.h
diff --git a/wcn6740/qcwcn/wifi_hal/tcp_params_update.cpp b/wcn6740/qcwcn/wifi_hal/tcp_params_update.cpp
new file mode 100644
index 0000000..c2c21e9
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/tcp_params_update.cpp
@@ -0,0 +1,374 @@
+/* Copyright (c) 2018-2019, 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "vendor_definitions.h"
+#include <netlink/genl/genl.h>
+#include <string.h>
+#include <net/if.h>
+#include "tcp_params_update.h"
+
+TCPParamCommand::TCPParamCommand(wifi_handle handle, int id,
+ u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ if (registerVendorHandler(vendor_id, subcmd)) {
+ /* Error case should not happen print log */
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
+ __FUNCTION__, vendor_id, subcmd);
+ }
+ memset(def_tcp_limit_output_bytes, 0, SIZE_TCP_PARAM);
+ memset(def_tcp_adv_win_scale, 0, SIZE_TCP_PARAM);
+ def_tcp_limit_output_bytes_valid = false;
+ def_tcp_adv_win_scale_valid = false;
+}
+
+TCPParamCommand::~TCPParamCommand()
+{
+ unregisterVendorHandler(OUI_QCA, QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT);
+}
+
+TCPParamCommand *TCPParamCommand::instance(wifi_handle handle, wifi_request_id id)
+{
+ TCPParamCommand* mTCPParamCommandInstance;
+
+ mTCPParamCommandInstance = new TCPParamCommand(handle, id, OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT);
+ return mTCPParamCommandInstance;
+}
+
+/* This function will be the main handler for incoming event.
+ * Call the appropriate callback handler after parsing the vendor data.
+ */
+int TCPParamCommand::handleEvent(WifiEvent &event)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ WifiVendorCommand::handleEvent(event);
+
+ u8 tpDirection, tpLevel;
+ u32 tcpLimitOutputBytes;
+ u8 tcpLimitOutputBytesFlag = 0;
+ s8 tcpAdvWinScale;
+ u8 tcpAdvWinScaleFlag = 0;
+ u32 tcpDelackSeg;
+ u8 tcpDelackSegFlag = 0;
+ char value_to_str[100];
+ int ret_val = 0;
+
+ /* Parse the vendordata and get the attribute */
+ switch(mSubcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT:
+ {
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX + 1];
+
+ nla_parse(tb, QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL);
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION] ||
+ !tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL]) {
+ ALOGE("Invalid event, didn't receive mandatory attributes");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ tpDirection = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION]);
+ tpLevel = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL]);
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES]) {
+ tcpLimitOutputBytes = nla_get_u32(tb[
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES]);
+ tcpLimitOutputBytesFlag = 1;
+ }
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE]) {
+ tcpAdvWinScale = *(s8 *)nla_data(tb[
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE]);
+ tcpAdvWinScaleFlag = 1;
+ }
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG]) {
+ tcpDelackSeg = nla_get_u32(tb[
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG]);
+ tcpDelackSegFlag = 1;
+ }
+ if (tpDirection == TP_CHANGE_RX) {
+ switch(tpLevel) {
+ case QCA_WLAN_THROUGHPUT_LEVEL_LOW:
+ {
+ if (def_tcp_adv_win_scale_valid)
+ wlan_service_set_tcp_adv_win_scale(def_tcp_adv_win_scale);
+ wlan_service_set_tcp_use_userconfig("0");
+ }
+ break;
+ case QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM:
+ case QCA_WLAN_THROUGHPUT_LEVEL_HIGH:
+ {
+ if (tcpAdvWinScaleFlag) {
+ ret_val = snprintf(value_to_str, sizeof(value_to_str), "%d",
+ tcpAdvWinScale);
+ if (ret_val < 0 || ret_val >= (int)sizeof(value_to_str)) {
+ ALOGE("Error in converting value to string: %d", ret_val);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ wlan_service_set_tcp_adv_win_scale(value_to_str);
+ }
+ if (tcpDelackSegFlag && wlan_service_set_tcp_use_userconfig("1") == 0) {
+ ret_val = snprintf(value_to_str, sizeof(value_to_str), "%d",
+ tcpDelackSeg);
+ if (ret_val < 0 || ret_val >= (int)sizeof(value_to_str)) {
+ ALOGE("Error in converting value to string: %d", ret_val);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ wlan_service_set_tcp_delack_seg(value_to_str);
+ }
+ }
+ break;
+ default:
+ {
+ /* Error case should not happen print log */
+ ALOGE("%s: Invalid throughput level value", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+ } else if (tpDirection == TP_CHANGE_TX) {
+ switch(tpLevel) {
+ case QCA_WLAN_THROUGHPUT_LEVEL_LOW:
+ {
+ if (def_tcp_limit_output_bytes_valid)
+ wlan_service_set_tcp_limit_output_bytes(
+ def_tcp_limit_output_bytes);
+ }
+ break;
+ case QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM:
+ case QCA_WLAN_THROUGHPUT_LEVEL_HIGH:
+ {
+ if (tcpLimitOutputBytesFlag) {
+ ret_val = snprintf(value_to_str, sizeof(value_to_str), "%d",
+ tcpLimitOutputBytes);
+ if (ret_val < 0 || ret_val >= (int)sizeof(value_to_str)) {
+ ALOGE("Error in converting value to string: %d", ret_val);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ wlan_service_set_tcp_limit_output_bytes(value_to_str);
+ }
+ }
+ break;
+ default:
+ {
+ /* Error case should not happen print log */
+ ALOGE("%s: Invalid throughput level value", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ }
+ } else {
+ /* Error case should not happen print log */
+ ALOGE("%s: Invalid throughput change direction", __FUNCTION__);
+ return ret;
+ }
+ ret = WIFI_SUCCESS;
+ }
+ break;
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd);
+ break;
+ }
+
+ return ret;
+
+cleanup:
+ return ret;
+}
+
+wifi_error wifi_init_tcp_param_change_event_handler(wifi_interface_handle iface)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ TCPParamCommand *tcpParamCommand;
+
+ if (wifiHandle == NULL) {
+ ALOGE("%s: Interface Handle is invalid", __func__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ hal_info *info = getHalInfo(wifiHandle);
+ if (!info)
+ return WIFI_ERROR_UNKNOWN;
+
+ tcpParamCommand = TCPParamCommand::instance(wifiHandle, 0);
+ if (tcpParamCommand == NULL) {
+ ALOGE("%s: Error TcpParamCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ info->tcp_param_handler = (tcp_param_cmd_handler *)malloc(sizeof(tcp_param_cmd_handler));
+ if (info->tcp_param_handler == NULL) {
+ ALOGE("%s: Allocation of tcp handler failed",__FUNCTION__);
+ delete tcpParamCommand;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ info->tcp_param_handler->tcpParamCommand = tcpParamCommand;
+
+ if (wlan_service_read_sys_param("/proc/sys/net/ipv4/tcp_limit_output_bytes",
+ tcpParamCommand->def_tcp_limit_output_bytes,
+ SIZE_TCP_PARAM) == 0) {
+ tcpParamCommand->def_tcp_limit_output_bytes_valid = true;
+ }
+
+ if (wlan_service_read_sys_param("/proc/sys/net/ipv4/tcp_adv_win_scale",
+ tcpParamCommand->def_tcp_adv_win_scale,
+ SIZE_TCP_PARAM) == 0) {
+ tcpParamCommand->def_tcp_adv_win_scale_valid = true;
+ }
+
+ return WIFI_SUCCESS;
+}
+
+void cleanupTCPParamCommand(hal_info *info) {
+
+ TCPParamCommand *tcpParamCommand;
+
+ if (info == NULL || info->tcp_param_handler == NULL)
+ return;
+
+ tcpParamCommand = info->tcp_param_handler->tcpParamCommand;
+
+ if (tcpParamCommand) {
+ if (tcpParamCommand->def_tcp_limit_output_bytes_valid)
+ wlan_service_update_sys_param("/proc/sys/net/ipv4/tcp_limit_output_bytes",
+ tcpParamCommand->def_tcp_limit_output_bytes);
+ wlan_service_update_sys_param("/proc/sys/net/ipv4/tcp_use_userconfig", "0");
+ if (tcpParamCommand->def_tcp_adv_win_scale_valid)
+ wlan_service_update_sys_param("/proc/sys/net/ipv4/tcp_adv_win_scale",
+ tcpParamCommand->def_tcp_adv_win_scale);
+ delete tcpParamCommand;
+ }
+
+ free(info->tcp_param_handler);
+
+ return;
+}
+
+/**
+ * wlan_service_update_sys_param()
+ * @path: path on the file system to be modified
+ * @str: value to be written to the path
+ *
+ * Generic function to update a system parameter
+ * Return: WIFI_SUCCESS code if read is successful
+ * Eror code if read is failure
+ */
+wifi_error wlan_service_update_sys_param(const char *path, const char *str)
+{
+ int ret;
+ FILE *fp;
+ fp = fopen(path, "w");
+
+ if (fp == NULL) {
+ ALOGE("%s: unable to open %s", __FUNCTION__, path);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: %s %s", __FUNCTION__, path, str);
+
+ ret = fputs(str, fp);
+ fclose(fp);
+
+ if (ret < 0) {
+ ALOGE("%s: failed to write %s to %s with err %d", __FUNCTION__, str, path, ret);
+ return mapKernelErrortoWifiHalError(ret);
+ }
+
+ return WIFI_SUCCESS;
+}
+
+/**
+ * wlan_service_read_sys_param()
+ * @path: path on the file system to be read
+ * @str: value read from the path
+ *
+ * Generic function to read a system parameter
+ * Return: WIFI_SUCCESS code if read is successful
+ * Eror code if read is failure
+ */
+wifi_error wlan_service_read_sys_param(const char *path, char *str, size_t max_size)
+{
+ size_t ret_len;
+ FILE *fp = fopen(path, "r");
+
+ if (fp == NULL) {
+ ALOGE("%s: unable to open %s", __FUNCTION__, path);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret_len = fread(str, 1, max_size, fp);
+ fclose(fp);
+
+ if (ret_len == 0 || ret_len == max_size) {
+ ALOGE("Faild to read %s, ret_len = %zu", path, ret_len);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: %s %s", __FUNCTION__, path, str);
+ return WIFI_SUCCESS;
+}
+
+int TCPParamCommand::wlan_service_set_tcp_adv_win_scale(char *str)
+{
+ return wlan_service_update_sys_param(
+ "/proc/sys/net/ipv4/tcp_adv_win_scale", str);
+}
+
+int TCPParamCommand::wlan_service_set_tcp_use_userconfig(const char *str)
+{
+ return wlan_service_update_sys_param(
+ "/proc/sys/net/ipv4/tcp_use_userconfig", str);
+}
+
+int TCPParamCommand::wlan_service_set_tcp_delack_seg(char *str)
+{
+ return wlan_service_update_sys_param(
+ "/proc/sys/net/ipv4/tcp_delack_seg", str);
+}
+
+int TCPParamCommand::wlan_service_set_tcp_limit_output_bytes(char *str)
+{
+ return wlan_service_update_sys_param (
+ "/proc/sys/net/ipv4/tcp_limit_output_bytes", str);
+}
diff --git a/wcn6740/qcwcn/wifi_hal/tcp_params_update.h b/wcn6740/qcwcn/wifi_hal/tcp_params_update.h
new file mode 100644
index 0000000..184372d
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/tcp_params_update.h
@@ -0,0 +1,81 @@
+/* Copyright (c) 2018-2019, 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 __WIFI_HAL_TCP_PARAM_UPDATE_COMMAND_H__
+#define __WIFI_HAL_TCP_PARAM_UPDATE_COMMAND_H__
+
+#include "cpp_bindings.h"
+#include "common.h"
+#include <errno.h>
+
+#define SIZE_TCP_PARAM 100
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/* Indicates the direction of throughput in which the change is being
+ * reported. u8 attribute. Value is 0 for TX and 1 for RX.
+ */
+typedef enum {
+ TP_CHANGE_TX = 0,
+ TP_CHANGE_RX = 1
+} TpChangeDirection;
+
+wifi_error wlan_service_update_sys_param(const char *path, const char *str);
+wifi_error wlan_service_read_sys_param(const char *path, char *str, size_t max_size);
+void cleanupTCPParamCommand(hal_info *info);
+
+class TCPParamCommand: public WifiVendorCommand
+{
+private:
+ TCPParamCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+ int wlan_service_set_tcp_adv_win_scale(char *str);
+ int wlan_service_set_tcp_use_userconfig(const char *str);
+ int wlan_service_set_tcp_delack_seg(char *str);
+ int wlan_service_set_tcp_limit_output_bytes(char *str);
+
+public:
+ virtual ~TCPParamCommand();
+ static TCPParamCommand *instance(wifi_handle handle,
+ wifi_request_id id);
+ virtual int handleEvent(WifiEvent &event);
+ char def_tcp_limit_output_bytes[SIZE_TCP_PARAM];
+ bool def_tcp_limit_output_bytes_valid;
+ char def_tcp_adv_win_scale[SIZE_TCP_PARAM];
+ bool def_tcp_adv_win_scale_valid;
+};
+
+/* Used to clean TCPParam object*/
+typedef struct tcp_param_cmd_handler_s {
+ TCPParamCommand *tcpParamCommand;
+} tcp_param_cmd_handler;
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/wcn6740/qcwcn/wifi_hal/tdls.cpp b/wcn6740/qcwcn/wifi_hal/tdls.cpp
new file mode 100644
index 0000000..2082fef
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/tdls.cpp
@@ -0,0 +1,583 @@
+/* Copyright (c) 2014, 2018 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "tdlsCommand.h"
+#include "vendor_definitions.h"
+
+/* Singleton Static Instance */
+TdlsCommand* TdlsCommand::mTdlsCommandInstance = NULL;
+TdlsCommand::TdlsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mHandler, 0, sizeof(mHandler));
+ memset(&mTDLSgetStatusRspParams, 0, sizeof(wifi_tdls_status));
+ mRequestId = 0;
+}
+
+TdlsCommand::~TdlsCommand()
+{
+ mTdlsCommandInstance = NULL;
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+}
+
+TdlsCommand* TdlsCommand::instance(wifi_handle handle)
+{
+ if (handle == NULL) {
+ ALOGE("Interface Handle is invalid");
+ return NULL;
+ }
+ if (mTdlsCommandInstance == NULL) {
+ mTdlsCommandInstance = new TdlsCommand(handle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE);
+ ALOGV("TdlsCommand %p created", mTdlsCommandInstance);
+ return mTdlsCommandInstance;
+ }
+ else
+ {
+ if (handle != getWifiHandle(mTdlsCommandInstance->mInfo))
+ {
+ /* upper layer must have cleaned up the handle and reinitialized,
+ so we need to update the same */
+ ALOGV("Handle different, update the handle");
+ mTdlsCommandInstance->mInfo = (hal_info *)handle;
+ }
+ }
+ ALOGV("TdlsCommand %p created already", mTdlsCommandInstance);
+ return mTdlsCommandInstance;
+}
+
+void TdlsCommand::setSubCmd(u32 subcmd)
+{
+ mSubcmd = subcmd;
+}
+
+/* This function will be the main handler for incoming event SUBCMD_TDLS
+ * Call the appropriate callback handler after parsing the vendor data.
+ */
+int TdlsCommand::handleEvent(WifiEvent &event)
+{
+ ALOGV("Got a TDLS message from Driver");
+ WifiVendorCommand::handleEvent(event);
+
+ /* Parse the vendordata and get the attribute */
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE:
+ {
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX
+ + 1];
+ mac_addr addr;
+ wifi_tdls_status status;
+
+ memset(&addr, 0, sizeof(mac_addr));
+ memset(&status, 0, sizeof(wifi_tdls_status));
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ ALOGV("QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE Received");
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_MAC_ADDR])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_MAC_ADDR not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ memcpy(addr,
+ (u8 *)nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_MAC_ADDR]),
+ nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_MAC_ADDR]));
+
+ ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr));
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_STATE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_STATE not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ status.state = (wifi_tdls_state)
+ get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_STATE]);
+ ALOGV("TDLS: State New : %d ", status.state);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_REASON])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_REASON not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ status.reason = (wifi_tdls_reason)
+ get_s32(tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_REASON]);
+ ALOGV("TDLS: Reason : %d ", status.reason);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_CHANNEL])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_CHANNEL not found",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ status.channel =
+ get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_CHANNEL]);
+ ALOGV("TDLS: channel : %d ", status.channel);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GLOBAL_OPERATING_CLASS])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GLOBAL_OPERATING_CLASS"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ status.global_operating_class = get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GLOBAL_OPERATING_CLASS]);
+ ALOGV("TDLS: global_operating_class: %d ",
+ status.global_operating_class);
+
+ if (mHandler.on_tdls_state_changed)
+ (*mHandler.on_tdls_state_changed)(addr, status);
+ else
+ ALOGE("TDLS: No Callback registered: ");
+ }
+ break;
+
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong TDLS subcmd received %d", __FUNCTION__, mSubcmd);
+ }
+
+ return NL_SKIP;
+}
+
+int TdlsCommand::handleResponse(WifiEvent &reply)
+{
+ WifiVendorCommand::handleResponse(reply);
+
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ ALOGV("QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS Received");
+ memset(&mTDLSgetStatusRspParams, 0, sizeof(wifi_tdls_status));
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetStatusRspParams.state = (wifi_tdls_state)get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE]);
+ ALOGV("TDLS: State : %u ", mTDLSgetStatusRspParams.state);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetStatusRspParams.reason = (wifi_tdls_reason)get_s32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON]);
+ ALOGV("TDLS: Reason : %d ", mTDLSgetStatusRspParams.reason);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetStatusRspParams.channel = get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL]);
+ ALOGV("TDLS: channel : %d ", mTDLSgetStatusRspParams.channel);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS])
+ {
+ ALOGE("%s:"
+ "QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetStatusRspParams.global_operating_class =
+ get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS]);
+ ALOGV("TDLS: global_operating_class: %d ",
+ mTDLSgetStatusRspParams.global_operating_class);
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ memset(&mTDLSgetCaps, 0, sizeof(wifiTdlsCapabilities));
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS]
+ )
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_"
+ "MAX_CONC_SESSIONS not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetCaps.maxConcurrentTdlsSessionNum = get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS]);
+
+ if (!tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_"
+ "FEATURES_SUPPORTED not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ mTDLSgetCaps.tdlsSupportedFeatures = get_u32(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED]);
+ }
+ break;
+ default :
+ ALOGE("%s: Wrong TDLS subcmd response received %d",
+ __FUNCTION__, mSubcmd);
+ }
+ return NL_SKIP;
+}
+
+
+wifi_error TdlsCommand::setCallbackHandler(wifi_tdls_handler nHandler, u32 event)
+{
+ wifi_error res;
+ mHandler = nHandler;
+
+ res = registerVendorHandler(mVendor_id, event);
+ if (res != WIFI_SUCCESS) {
+ /* Error case should not happen print log */
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
+ __FUNCTION__, mVendor_id, mSubcmd);
+ }
+ return res;
+}
+
+void TdlsCommand::unregisterHandler(u32 subCmd)
+{
+ unregisterVendorHandler(mVendor_id, subCmd);
+}
+
+void TdlsCommand::getStatusRspParams(wifi_tdls_status *status)
+{
+ status->channel = mTDLSgetStatusRspParams.channel;
+ status->global_operating_class =
+ mTDLSgetStatusRspParams.global_operating_class;
+ status->state = mTDLSgetStatusRspParams.state;
+ status->reason = mTDLSgetStatusRspParams.reason;
+}
+
+wifi_error TdlsCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+void TdlsCommand::getCapsRspParams(wifi_tdls_capabilities *caps)
+{
+ caps->max_concurrent_tdls_session_num =
+ mTDLSgetCaps.maxConcurrentTdlsSessionNum;
+ caps->is_global_tdls_supported =
+ !!(mTDLSgetCaps.tdlsSupportedFeatures & IS_GLOBAL_TDLS_SUPPORTED);
+ caps->is_per_mac_tdls_supported =
+ !!(mTDLSgetCaps.tdlsSupportedFeatures & IS_PER_MAC_TDLS_SUPPORTED);
+ caps->is_off_channel_tdls_supported =
+ !!(mTDLSgetCaps.tdlsSupportedFeatures & IS_OFF_CHANNEL_TDLS_SUPPORTED);
+ ALOGV("TDLS capabilities:");
+ ALOGV("max_concurrent_tdls_session_numChannel : %d\n",
+ caps->max_concurrent_tdls_session_num);
+ ALOGV("is_global_tdls_supported : %d\n",
+ caps->is_global_tdls_supported);
+ ALOGV("is_per_mac_tdls_supported : %d\n",
+ caps->is_per_mac_tdls_supported);
+ ALOGV("is_off_channel_tdls_supported : %d \n",
+ caps->is_off_channel_tdls_supported);
+}
+
+/* wifi_enable_tdls - enables TDLS-auto mode for a specific route
+ *
+ * params specifies hints, which provide more information about
+ * why TDLS is being sought. The firmware should do its best to
+ * honor the hints before downgrading regular AP link
+ *
+ * On successful completion, must fire on_tdls_state_changed event
+ * to indicate the status of TDLS operation.
+ */
+wifi_error wifi_enable_tdls(wifi_interface_handle iface,
+ mac_addr addr,
+ wifi_tdls_params *params,
+ wifi_tdls_handler handler)
+{
+ wifi_error ret;
+ TdlsCommand *pTdlsCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ pTdlsCommand = TdlsCommand::instance(handle);
+
+ if (pTdlsCommand == NULL) {
+ ALOGE("%s: Error TdlsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ pTdlsCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE);
+
+ /* Create the message */
+ ret = pTdlsCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the attributes */
+ nl_data = pTdlsCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ALOGV("%s: MAC_ADDR: " MAC_ADDR_STR, __FUNCTION__, MAC_ADDR_ARRAY(addr));
+ ret = pTdlsCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR,
+ (char *)addr, 6);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ if (params != NULL) {
+ ALOGV("%s: Channel: %d, Global operating class: %d, "
+ "Max Latency: %dms, Min Bandwidth: %dKbps",
+ __FUNCTION__, params->channel, params->global_operating_class,
+ params->max_latency_ms, params->min_bandwidth_kbps);
+ ret = pTdlsCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL,
+ params->channel);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = pTdlsCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS,
+ params->global_operating_class);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = pTdlsCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS,
+ params->max_latency_ms);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ret = pTdlsCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS,
+ params->min_bandwidth_kbps);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ }
+
+ pTdlsCommand->attr_end(nl_data);
+
+ ret = pTdlsCommand->setCallbackHandler(handler,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ return ret;
+}
+
+/* wifi_disable_tdls - disables TDLS-auto mode for a specific route
+ *
+ * This terminates any existing TDLS with addr device, and frees the
+ * device resources to make TDLS connections on new routes.
+ *
+ * DON'T fire any more events on 'handler' specified in earlier call to
+ * wifi_enable_tdls after this action.
+ */
+wifi_error wifi_disable_tdls(wifi_interface_handle iface, mac_addr addr)
+{
+ wifi_error ret;
+ TdlsCommand *pTdlsCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ pTdlsCommand = TdlsCommand::instance(handle);
+
+ if (pTdlsCommand == NULL) {
+ ALOGE("%s: Error TdlsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ pTdlsCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE);
+
+ /* Create the message */
+ ret = pTdlsCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ALOGV("%s: ifindex obtained:%d", __FUNCTION__, ret);
+ ALOGV("%s: MAC_ADDR: " MAC_ADDR_STR, __FUNCTION__, MAC_ADDR_ARRAY(addr));
+
+ /* Add the attributes */
+ nl_data = pTdlsCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ret = pTdlsCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR,
+ (char *)addr, 6);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ pTdlsCommand->attr_end(nl_data);
+
+ ret = pTdlsCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
+
+cleanup:
+ delete pTdlsCommand;
+ return ret;
+}
+
+/* wifi_get_tdls_status - allows getting the status of TDLS for a specific
+ * route
+ */
+wifi_error wifi_get_tdls_status(wifi_interface_handle iface, mac_addr addr,
+ wifi_tdls_status *status)
+{
+ wifi_error ret;
+ TdlsCommand *pTdlsCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ pTdlsCommand = TdlsCommand::instance(handle);
+
+ if (pTdlsCommand == NULL) {
+ ALOGE("%s: Error TdlsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ pTdlsCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS);
+
+ /* Create the message */
+ ret = pTdlsCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ ALOGV("%s: ifindex obtained:%d", __FUNCTION__, ret);
+
+ /* Add the attributes */
+ nl_data = pTdlsCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ ret = pTdlsCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR,
+ (char *)addr, 6);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ pTdlsCommand->attr_end(nl_data);
+
+ ret = pTdlsCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
+
+ pTdlsCommand->getStatusRspParams(status);
+
+cleanup:
+ return ret;
+}
+
+/* return the current HW + Firmware combination's TDLS capabilities */
+wifi_error wifi_get_tdls_capabilities(wifi_interface_handle iface,
+ wifi_tdls_capabilities *capabilities)
+{
+ wifi_error ret;
+ TdlsCommand *pTdlsCommand;
+
+ if (capabilities == NULL) {
+ ALOGE("%s: capabilities is NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ pTdlsCommand = TdlsCommand::instance(handle);
+
+ if (pTdlsCommand == NULL) {
+ ALOGE("%s: Error TdlsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ pTdlsCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES);
+
+ /* Create the message */
+ ret = pTdlsCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = pTdlsCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ pTdlsCommand->getCapsRspParams(capabilities);
+
+cleanup:
+ if (ret != WIFI_SUCCESS)
+ memset(capabilities, 0, sizeof(wifi_tdls_capabilities));
+ delete pTdlsCommand;
+ return ret;
+}
diff --git a/qcwcn/wifi_hal/tdlsCommand.h b/wcn6740/qcwcn/wifi_hal/tdlsCommand.h
old mode 100755
new mode 100644
similarity index 100%
copy from qcwcn/wifi_hal/tdlsCommand.h
copy to wcn6740/qcwcn/wifi_hal/tdlsCommand.h
diff --git a/qcwcn/wifi_hal/vendor_definitions.h b/wcn6740/qcwcn/wifi_hal/vendor_definitions.h
similarity index 100%
copy from qcwcn/wifi_hal/vendor_definitions.h
copy to wcn6740/qcwcn/wifi_hal/vendor_definitions.h
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
similarity index 75%
copy from qcwcn/wifi_hal/wifi_hal.cpp
copy to wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
index 372d9e1..73e102a 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/wcn6740/qcwcn/wifi_hal/wifi_hal.cpp
@@ -12,6 +12,40 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#include <stdint.h>
@@ -25,7 +59,7 @@
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/errqueue.h>
-
+#include <linux-private/linux/fib_rules.h>
#include <linux/pkt_sched.h>
#include <netlink/object-api.h>
#include <netlink/netlink.h>
@@ -54,6 +88,7 @@
#include "cpp_bindings.h"
#include "ifaceeventhandler.h"
#include "wifiloggercmd.h"
+#include "tcp_params_update.h"
/*
BUGBUG: normally, libnl allocates ports for all connections it makes; but
@@ -106,6 +141,12 @@
u8 enable);
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle handle);
+
+wifi_error
+ wifi_init_tcp_param_change_event_handler(wifi_interface_handle iface);
+
+wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode);
/* Initialize/Cleanup */
@@ -376,6 +417,28 @@
return ret;
}
+static wifi_error wifi_get_sar_version(wifi_interface_handle handle)
+{
+ wifi_error ret;
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ WifihalGeneric *sarVersion = new WifihalGeneric(
+ wifiHandle,
+ 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SAR_CAPABILITY);
+ if (!sarVersion) {
+ ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ ret = sarVersion->getSarVersion(handle);
+
+ delete sarVersion;
+ return ret;
+}
+
static wifi_error get_firmware_bus_max_size_supported(
wifi_interface_handle iface)
{
@@ -473,6 +536,256 @@
return WIFI_SUCCESS;
}
+static uint32_t get_frequency_from_channel(uint32_t channel, wlan_mac_band band)
+{
+ uint32_t freq = 0;
+
+ switch (band)
+ {
+ case WLAN_MAC_2_4_BAND:
+ if (!(channel >= 1 && channel <= 14))
+ goto failure;
+ //special handling for channel 14 by filling freq here
+ if (channel == 14)
+ freq = 2484;
+ else
+ freq = 2407 + (channel * 5);
+ break;
+ case WLAN_MAC_5_0_BAND:
+ if (!((channel >= 34 && channel < 65) ||
+ (channel > 99 && channel <= 196)))
+ goto failure;
+ freq = 5000 + (channel * 5);
+ break;
+ case WLAN_MAC_6_0_BAND:
+ if (!(channel >= 1 && channel <= 233))
+ goto failure;
+ freq = 5950 + (channel * 5);
+ break;
+ default:
+ break;
+ }
+
+failure:
+ return freq;
+}
+
+static u32 get_nl_ifmask_from_coex_restriction_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (!in_mask)
+ return op_mask;
+ if (in_mask & SOFTAP)
+ op_mask |= BIT(NL80211_IFTYPE_AP);
+ if (in_mask & WIFI_DIRECT)
+ op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
+ if (in_mask & WIFI_AWARE)
+ op_mask |= BIT(NL80211_IFTYPE_NAN);
+
+ return op_mask;
+}
+
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
+ wifi_coex_unsafe_channel *unsafeChannels,
+ u32 restrictions)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ WifihalGeneric *cmd = NULL;
+ struct nlattr *nl_data = NULL;
+ struct nlattr *nl_attr_unsafe_chan = NULL;
+ struct nlattr *unsafe_channels_attr = NULL;
+ hal_info *info = NULL;
+ int freq_cnt = 0;
+ u32 *freq = (u32 *) malloc(sizeof(u32) * num_channels);
+ u32 *power_cap_dbm = (u32 *) malloc(sizeof(u32) * num_channels);
+
+ if (!freq || !power_cap_dbm) {
+ ALOGE("%s: Failed to allocate memory", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
+ goto cleanup;
+ }
+
+ info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT);
+ if (cmd == NULL) {
+ ALOGE("%s: Error, created command NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ /* Create the NL message. */
+ ret = cmd->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg due to error: (%d)",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ ALOGE("%s: failed attr_start for NL80211_ATTR_VENDOR_DATA",
+ __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ nl_attr_unsafe_chan = cmd->attr_start(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE);
+ if (!nl_attr_unsafe_chan) {
+ ALOGE("%s: failed attr_start for"
+ " QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ ALOGD("%s: num_channels:%d, restrictions:%x", __FUNCTION__, num_channels,
+ restrictions);
+ for (int i = 0; i < num_channels; i++)
+ {
+ u32 frequency = get_frequency_from_channel(unsafeChannels[i].channel,
+ unsafeChannels[i].band);
+ if (frequency != 0)
+ {
+ freq[freq_cnt] = frequency;
+ power_cap_dbm[freq_cnt] = unsafeChannels[i].power_cap_dbm;
+ freq_cnt++;
+ ALOGV("%s: channel:%d, freq:%d, power_cap_dbm:%d, band:%d",
+ __FUNCTION__, unsafeChannels[i].channel, frequency,
+ unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
+ }
+ else {
+ ALOGV("%s: Invalid channel found, channel:%d, power_cap_dbm:%d, band:%d",
+ __FUNCTION__, unsafeChannels[i].channel,
+ unsafeChannels[i].power_cap_dbm, unsafeChannels[i].band);
+ }
+ }
+ if (num_channels == 0) {
+ unsafe_channels_attr = cmd->attr_start(0);
+ if (!unsafe_channels_attr) {
+ ALOGE("%s: failed attr_start for unsafe_channels_attr when"
+ " trying to clear usafe channels clear", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, 0);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency start, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, 0);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency end, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ cmd->attr_end(unsafe_channels_attr);
+ }
+ else {
+ if (!unsafeChannels) {
+ ALOGE("%s: unsafe channels buffer should not be NULL when"
+ " there are unsafe channels", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ if(freq_cnt == 0)
+ {
+ ALOGE("%s: No valid frequency, ignore channel list", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ for (int i = 0; i < freq_cnt; i++) {
+ unsafe_channels_attr = cmd->attr_start(i);
+ if (!unsafe_channels_attr) {
+ ALOGE("%s: failed attr_start for unsafe_channels_attr of"
+ " index:%d", __FUNCTION__, i);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, freq[i]);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency start, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ ret = cmd->put_u32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, freq[i]);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put frequency end, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ /**
+ * WIFI_COEX_NO_POWER_CAP (0x7FFFFFF) is specific to android
+ * framework, this value denotes that framework/wifihal is not
+ * providing any power cap and allow driver/firmware to operate on
+ * current power cap dbm. As driver is supposed to work on with
+ * LA/LE etc, we are skipping to send 0x7FFFFFF down to driver,
+ * hence driver will be operating as per current power cap calculated
+ * based on regulatory or other constraints.
+ */
+ if (power_cap_dbm[i] != WIFI_COEX_NO_POWER_CAP) {
+ ret = cmd->put_s32(
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM,
+ power_cap_dbm[i]);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put power_cap_dbm, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ }
+ ALOGD("%s: freq:%d, power_cap_dbm:%d",
+ __FUNCTION__, freq[i], power_cap_dbm[i]);
+ cmd->attr_end(unsafe_channels_attr);
+ }
+ }
+ cmd->attr_end(nl_attr_unsafe_chan);
+ if (num_channels > 0) {
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK,
+ get_nl_ifmask_from_coex_restriction_mask(restrictions));
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to put restrictions mask, ret:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ }
+ cmd->attr_end(nl_data);
+
+ /* Send the msg and wait for a response. */
+ ret = cmd->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ if (cmd)
+ delete cmd;
+ if (freq)
+ free (freq);
+ if (power_cap_dbm)
+ free (power_cap_dbm);
+ return ret;
+}
+
wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
{
wifi_error ret = WIFI_ERROR_INVALID_ARGS;
@@ -543,6 +856,161 @@
return ret;
}
+static u32 get_nl_band_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & WLAN_MAC_2_4_BAND)
+ op_mask |= BIT(NL80211_BAND_2GHZ);
+ if (in_mask & WLAN_MAC_5_0_BAND)
+ op_mask |= BIT(NL80211_BAND_5GHZ);
+ if (in_mask & WLAN_MAC_6_0_BAND)
+ op_mask |= BIT(NL80211_BAND_6GHZ);
+ if (in_mask & WLAN_MAC_60_0_BAND)
+ op_mask |= BIT(NL80211_BAND_60GHZ);
+
+ return op_mask;
+}
+
+static u32 get_nl_iftype_mode_masks(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & BIT(WIFI_INTERFACE_STA) ||
+ in_mask & BIT(WIFI_INTERFACE_TDLS))
+ op_mask |= BIT(NL80211_IFTYPE_STATION);
+ if (in_mask & BIT(WIFI_INTERFACE_SOFTAP))
+ op_mask |= BIT(NL80211_IFTYPE_AP);
+ if (in_mask & BIT(WIFI_INTERFACE_P2P_CLIENT))
+ op_mask |= BIT(NL80211_IFTYPE_P2P_CLIENT);
+ if (in_mask & BIT(WIFI_INTERFACE_P2P_GO))
+ op_mask |= BIT(NL80211_IFTYPE_P2P_GO);
+ if (in_mask & BIT(WIFI_INTERFACE_NAN))
+ op_mask |= BIT(NL80211_IFTYPE_NAN);
+
+ return op_mask;
+}
+
+static u32 get_vendor_filter_mask(u32 in_mask)
+{
+ u32 op_mask = 0;
+
+ if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE)
+ op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX);
+ if (in_mask & WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY)
+ op_mask |= BIT(QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY);
+
+ return op_mask;
+}
+
+wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask,
+ u32 iface_mode_mask, u32 filter_mask,
+ u32 max_size, u32* size,
+ wifi_usable_channel* channels)
+{
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
+ WifihalGeneric *cmd = NULL;
+ struct nlattr *nl_data = NULL;
+ hal_info *info = NULL;
+ u32 band = 0, iface_mask = 0, filter = 0;
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
+ goto cleanup;
+ }
+
+ info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error, wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ if (!max_size) {
+ ALOGE("%s: max channel size is zero", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ if (!channels) {
+ ALOGE("%s: user input channel buffer NULL", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ cmd = new WifihalGeneric(handle, get_requestid(), OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS);
+ if (cmd == NULL) {
+ ALOGE("%s: Error, created command NULL", __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ /* Create the NL message. */
+ ret = cmd->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg due to error: (%d)",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nl_data = cmd->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data) {
+ ALOGE("%s: failed attr_start for VENDOR_DATA due to error",
+ __FUNCTION__);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ band = get_nl_band_mask(band_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK,
+ band);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ iface_mask = get_nl_iftype_mode_masks(iface_mode_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK,
+ iface_mask);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ filter = get_vendor_filter_mask(filter_mask);
+ ret = cmd->put_u32(QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK,
+ filter);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: failed to put vendor data due to error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ cmd->attr_end(nl_data);
+
+ /* Populate the input received from caller/framework. */
+ cmd->setMaxSetSize(max_size);
+ cmd->set_channels_buff(channels);
+
+ /* Send the msg and wait for a response. */
+ ret = cmd->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Error %d waiting for response.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ *size = cmd->get_results_size();
+
+cleanup:
+ if (cmd)
+ delete cmd;
+ return ret;
+}
+
/*initialize function pointer table with Qualcomm HAL API*/
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
if (fn == NULL) {
@@ -640,11 +1108,18 @@
fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
+ /* Customers will uncomment when they want to set qpower*/
+ //fn->wifi_set_qpower = wifi_set_qpower;
fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
+ fn->wifi_multi_sta_set_primary_connection = wifi_multi_sta_set_primary_connection;
+ fn->wifi_multi_sta_set_use_case = wifi_multi_sta_set_use_case;
+ fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
fn->wifi_set_dtim_config = wifi_set_dtim_config;
+ fn->wifi_set_voip_mode = wifi_set_voip_mode;
+ fn->wifi_get_usable_channels = wifi_get_usable_channels;
return WIFI_SUCCESS;
}
@@ -675,7 +1150,7 @@
wifi_error wifi_initialize(wifi_handle *handle)
{
- wifi_error ret = WIFI_SUCCESS;
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
wifi_interface_handle iface_handle;
struct nl_sock *cmd_sock = NULL;
struct nl_sock *event_sock = NULL;
@@ -850,6 +1325,7 @@
free(info->interfaces[i]);
}
ALOGE("%s no iface with wlan0", __func__);
+ ret = WIFI_ERROR_UNKNOWN;
goto unload;
}
iface_handle = (wifi_interface_handle)info->interfaces[index];
@@ -952,8 +1428,35 @@
goto unload;
}
+ ret = initializeRadioHandler(info);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Initializing Radio Event handler Failed");
+ goto unload;
+ }
+
+ ret = wifi_init_tcp_param_change_event_handler(iface_handle);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Initializing TCP param change event Handler Failed");
+ goto unload;
+ }
+
ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
- " features : 0x%" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
+ " features : %" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
+
+ if (wifi_is_nan_ext_cmd_supported(iface_handle))
+ info->support_nan_ext_cmd = true;
+ else
+ info->support_nan_ext_cmd = false;
+
+ ALOGV("support_nan_ext_cmd is %d",
+ info->support_nan_ext_cmd);
+
+ ret = wifi_get_sar_version(iface_handle);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to get SAR Version, Setting it to default.");
+ info->sar_version = QCA_WLAN_VENDOR_SAR_VERSION_1;
+ ret = WIFI_SUCCESS;
+ }
cld80211_cleanup:
if (status != 0 || ret != WIFI_SUCCESS) {
@@ -974,9 +1477,12 @@
}
if (info->pkt_stats) free(info->pkt_stats);
if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
+ if (info->wifihal_ctrl_sock.s) close(info->wifihal_ctrl_sock.s);
wifi_logger_ring_buffers_deinit(info);
cleanupGscanHandlers(info);
cleanupRSSIMonitorHandler(info);
+ cleanupRadioHandler(info);
+ cleanupTCPParamCommand(info);
free(info->event_cb);
if (info->driver_supported_features.flags) {
free(info->driver_supported_features.flags);
@@ -995,7 +1501,6 @@
int len, fd, ret = 0, count = 5;
ts.tv_sec = 0;
ts.tv_nsec = 200 * 1000000L;
-
do {
if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
break;
@@ -1006,21 +1511,20 @@
strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
return -1;
}
-
fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
if (fd < 0) {
ALOGE("Failed to open driver state control param at %s",
WIFI_DRIVER_STATE_CTRL_PARAM);
+ close(fd);
return -1;
}
-
len = strlen(state) + 1;
if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
ALOGE("Failed to write driver state control param at %s",
WIFI_DRIVER_STATE_CTRL_PARAM);
+ close(fd);
ret = -1;
}
-
close(fd);
return ret;
}
@@ -1090,9 +1594,7 @@
list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
del_from_list(®->list);
- if(reg) {
- free(reg);
- }
+ free(reg);
}
if (info->interfaces) {
@@ -1115,6 +1617,8 @@
wifi_logger_ring_buffers_deinit(info);
cleanupGscanHandlers(info);
cleanupRSSIMonitorHandler(info);
+ cleanupRadioHandler(info);
+ cleanupTCPParamCommand(info);
if (info->num_event_cb)
ALOGE("%d events were leftover without being freed",
@@ -1156,12 +1660,13 @@
hal_info *info = getHalInfo(handle);
info->cleaned_up_handler = handler;
- info->clean_up = true;
// Remove the dynamically created interface during wifi cleanup.
wifi_cleanup_dynamic_ifaces(handle);
-
TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
+
+ // Ensure wifi_event_loop() exits by setting clean_up to true.
+ info->clean_up = true;
ALOGI("Sent msg on exit sock to unblock poll()");
}
@@ -1263,7 +1768,7 @@
ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
goto nl_out;
}
-
+ ALOGI("%s: sent gennl msg of len: %d to driver\n", __FUNCTION__, ctrl_msg->data_len);
retval = internal_pollin_handler(handle, info->event_sock);
}
else if (ctrl_msg->family_name == CLD80211_FAMILY)
@@ -1282,7 +1787,7 @@
ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
goto nl_out;
}
- ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
+ ALOGI("%s: sent cld80211 msg of len: %d to driver\n", __FUNCTION__, ctrl_msg->data_len);
}
else
{
@@ -1354,9 +1859,6 @@
list_for_each_entry(reg, &info->monitor_sockets, list) {
- if(reg == NULL)
- break;
-
int mlen = min(match_len, reg->match_len);
if (reg->match_len == 0)
@@ -1405,8 +1907,6 @@
//! if sock is not present, return error -2.
//! if sock is present, and cmd_id does not match, return error -2.
//! if sock is present, and cmd_id matches, delete entry and return 0.
- if(reg == NULL)
- break;
if (ctrl_msg->monsock_len != reg->monsock_len)
continue;
@@ -1584,6 +2084,19 @@
}
}
+static bool exit_event_handler(int fd) {
+ char buf[4];
+ memset(buf, 0, sizeof(buf));
+
+ TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
+ ALOGI("exit_event_handler, buf=%s", buf);
+ if (strncmp(buf, "E", 1) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
/* Run event handler */
void wifi_event_loop(wifi_handle handle)
{
@@ -1631,10 +2144,16 @@
if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
}
+ if (pfd[2].revents & POLLIN) {
+ if (exit_event_handler(pfd[2].fd)) {
+ break;
+ }
+ }
}
rb_timerhandler(info);
} while (!info->clean_up);
internal_cleaned_up_handler(handle);
+ ALOGI("wifi_event_loop() exits success");
}
static int user_sock_message_handler(nl_msg *msg, void *arg)
@@ -1709,14 +2228,12 @@
list_for_each_entry(reg, &info->monitor_sockets, list) {
- if(reg == NULL)
- break;
-
if (memcmp(reg->match, buff, reg->match_len))
continue;
/* found match! */
/* Indicate the received Action frame to respective client */
+ ALOGI("send gennl msg of len : %d to apps", ctrl_evt->data_len);
if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
sizeof(*ctrl_evt) + ctrl_evt->data_len,
0, (struct sockaddr *)®->monsock, reg->monsock_len) < 0)
@@ -1863,8 +2380,14 @@
static bool is_wifi_interface(const char *name)
{
+ // filter out bridge interface
+ if (strstr(name, "br") != NULL) {
+ return false;
+ }
+
if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
- && strncmp(name, "wifi", 4) != 0) {
+ && strncmp(name, "wifi", 4) != 0
+ && strncmp(name, "swlan", 5) != 0) {
/* not a wifi interface; ignore it */
return false;
} else {
@@ -1957,8 +2480,6 @@
for (int i = 0; i < info->num_interfaces; i++)
free(info->interfaces[i]);
free(info->interfaces);
- info->interfaces = NULL;
- info->num_interfaces = 0;
}
wifi_error ret = wifi_init_interfaces(handle);
@@ -1993,10 +2514,10 @@
ret = acquire_supported_features(iface, set);
if (ret != WIFI_SUCCESS) {
*set = info->supported_feature_set;
- ALOGV("Supported feature set acquired at initialization : 0x%" PRIx64, *set);
+ ALOGV("Supported feature set acquired at initialization : %" PRIx64, *set);
} else {
info->supported_feature_set = *set;
- ALOGV("Supported feature set acquired : 0x%" PRIx64, *set);
+ ALOGV("Supported feature set acquired : %" PRIx64, *set);
}
return WIFI_SUCCESS;
}
@@ -2036,8 +2557,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(
QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
@@ -2091,8 +2614,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
/* Add the fixed part of the mac_oui to the nl command */
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
@@ -2139,8 +2664,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(
QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
@@ -2212,8 +2739,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(
QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
@@ -2268,8 +2797,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
QCA_WLAN_SET_PACKET_FILTER);
@@ -2358,8 +2889,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
QCA_WLAN_GET_PACKET_FILTER);
@@ -2410,8 +2943,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
if (ret != WIFI_SUCCESS)
@@ -2479,8 +3014,10 @@
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
QCA_WLAN_WRITE_PACKET_FILTER);
@@ -2518,7 +3055,7 @@
vCommand->attr_end(nlData);
ret = vCommand->requestResponse();
- if (ret != WIFI_SUCCESS) {
+ if (ret != WIFI_SUCCESS) {
ALOGE("%s: requestResponse Error:%d",__func__, ret);
goto cleanup;
}
@@ -2557,8 +3094,10 @@
}
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
- if (!nlData)
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
goto cleanup;
+ }
subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
QCA_WLAN_DISABLE_PACKET_FILTER;
@@ -2578,8 +3117,7 @@
info->apf_enabled = !!enable;
cleanup:
- if (vCommand)
- delete vCommand;
+ delete vCommand;
return ret;
}
@@ -2605,7 +3143,7 @@
static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
u32 src_offset, u8 *host_dst, u32 length)
{
- wifi_error ret = WIFI_SUCCESS;
+ wifi_error ret = WIFI_ERROR_UNKNOWN;
struct nlattr *nlData;
WifihalGeneric *vCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(handle);
@@ -2711,3 +3249,270 @@
delete vCommand;
return ret;
}
+
+class GetSupportedVendorCmd : public WifiCommand
+{
+private:
+ u32 mVendorCmds[256];
+ int mNumOfVendorCmds;
+
+public:
+ GetSupportedVendorCmd(wifi_handle handle) : WifiCommand(handle, 0)
+ {
+ mNumOfVendorCmds = 0;
+ memset(mVendorCmds, 0, 256);
+ }
+
+ virtual wifi_error create() {
+ int nl80211_id = genl_ctrl_resolve(mInfo->cmd_sock, "nl80211");
+ wifi_error ret = mMsg.create(nl80211_id, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
+ mMsg.put_flag(NL80211_ATTR_SPLIT_WIPHY_DUMP);
+
+ return ret;
+ }
+
+ virtual wifi_error requestResponse() {
+ return WifiCommand::requestResponse(mMsg);
+ }
+ virtual wifi_error set_iface_id(const char* name) {
+ unsigned ifindex = if_nametoindex(name);
+ return mMsg.set_iface_id(ifindex);
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ struct nlattr **tb = reply.attributes();
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ struct nlattr *nl;
+ int rem, i = 0;
+
+ for_each_attr(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
+ struct nl80211_vendor_cmd_info *vinfo;
+ if (nla_len(nl) != sizeof(*vinfo)) {
+ ALOGE("Unexpected vendor data info found in attribute");
+ continue;
+ }
+ vinfo = (struct nl80211_vendor_cmd_info *)nla_data(nl);
+ if (vinfo->vendor_id == OUI_QCA) {
+ mVendorCmds[i] = vinfo->subcmd;
+ i++;
+ }
+ }
+ mNumOfVendorCmds = i;
+ }
+ return NL_SKIP;
+ }
+
+ int isVendorCmdSupported(u32 cmdId) {
+ int i, ret;
+
+ ret = 0;
+ for (i = 0; i < mNumOfVendorCmds; i++) {
+ if (cmdId == mVendorCmds[i]) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+ }
+};
+
+static int wifi_is_nan_ext_cmd_supported(wifi_interface_handle iface_handle)
+{
+ wifi_error ret;
+ wifi_handle handle = getWifiHandle(iface_handle);
+ interface_info *info = getIfaceInfo(iface_handle);
+ GetSupportedVendorCmd cmd(handle);
+
+ ret = cmd.create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: create command failed", __func__);
+ return 0;
+ }
+
+ ret = cmd.set_iface_id(info->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: set iface id failed", __func__);
+ return 0;
+ }
+
+ ret = cmd.requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to query nan_ext command support, ret=%d", ret);
+ return 0;
+ } else {
+ return cmd.isVendorCmdSupported(QCA_NL80211_VENDOR_SUBCMD_NAN_EXT);
+ }
+}
+
+wifi_error wifi_get_radar_history(wifi_interface_handle handle,
+ radar_history_result *resultBuf, int resultBufSize, int *numResults)
+{
+ wifi_error ret;
+ struct nlattr *nlData;
+ WifihalGeneric *vCommand = NULL;
+ interface_info *ifaceInfo = NULL;
+ wifi_handle wifiHandle = NULL;
+
+ ALOGI("%s: enter", __FUNCTION__);
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ifaceInfo = getIfaceInfo(handle);
+ if (!ifaceInfo) {
+ ALOGE("%s: Error, interface_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ wifiHandle = getWifiHandle(handle);
+ if (!wifiHandle) {
+ ALOGE("%s: Error, wifi_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (resultBuf == NULL || numResults == NULL) {
+ ALOGE("%s: Error, resultsBuf/numResults NULL pointer", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ vCommand = new WifihalGeneric(wifiHandle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY);
+ if (vCommand == NULL) {
+ ALOGE("%s: Error vCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Create the message */
+ ret = vCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = vCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ vCommand->attr_end(nlData);
+
+ ret = vCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* No more data, copy the parsed results into the caller's results buffer */
+ ret = vCommand->copyCachedRadarHistory(
+ resultBuf, resultBufSize, numResults);
+
+cleanup:
+ vCommand->freeCachedRadarHistory();
+ delete vCommand;
+ return ret;
+}
+
+#define SIZEOF_TLV_HDR 4
+#define OEM_DATA_TLV_TYPE_HEADER 1
+#define OEM_DATA_CMD_SET_SKIP_CAC 18
+
+struct oem_data_header {
+ u16 cmd_id;
+ u16 request_idx;
+};
+
+static int wifi_add_oem_data_head(int cmd_id, u8* oem_buf, size_t max)
+{
+ struct oem_data_header oem_hdr;
+ oem_hdr.cmd_id = cmd_id;
+ oem_hdr.request_idx = 0;
+
+ if ((SIZEOF_TLV_HDR + sizeof(oem_hdr)) > max) {
+ return 0;
+ }
+
+ wifi_put_le16(oem_buf, OEM_DATA_TLV_TYPE_HEADER);
+ oem_buf += 2;
+ wifi_put_le16(oem_buf, sizeof(oem_hdr));
+ oem_buf += 2;
+ memcpy(oem_buf, (u8 *)&oem_hdr, sizeof(oem_hdr));
+ oem_buf += sizeof(oem_hdr);
+
+ return (SIZEOF_TLV_HDR + sizeof(oem_hdr));
+}
+
+
+/**
+ * This cmd takes effect on the interface the cmd is sent to.
+ * This cmd loses effect when interface is down. (i.e. set mac addr)
+ */
+wifi_error wifi_disable_next_cac(wifi_interface_handle handle) {
+ wifi_error ret;
+ interface_info *ifaceInfo = NULL;
+ struct nlattr *nlData;
+ WifiVendorCommand *vCommand = NULL;
+ u8 oem_buf[16];
+ int oem_buf_len = 0;
+
+ if (!handle) {
+ ALOGE("%s: Error, wifi_interface_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ifaceInfo = getIfaceInfo(handle);
+ if (!ifaceInfo) {
+ ALOGE("%s: Error, interface_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("%s: enter - iface=%s", __FUNCTION__, ifaceInfo->name);
+ oem_buf_len = wifi_add_oem_data_head(
+ OEM_DATA_CMD_SET_SKIP_CAC, oem_buf, sizeof(oem_buf));
+ if (oem_buf_len <= 0) {
+ ALOGE("%s: fill oem data head failed, cmd=%d", __func__,
+ OEM_DATA_CMD_SET_SKIP_CAC);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = initialize_vendor_cmd(handle, get_requestid(),
+ QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
+ &vCommand);
+
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __func__);
+ return ret;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ ret = vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
+ (char *)oem_buf, oem_buf_len);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ vCommand->attr_end(nlData);
+ ret = vCommand->requestResponse();
+
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete vCommand;
+ return ret;
+}
diff --git a/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c b/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c
new file mode 100644
index 0000000..2ad9c38
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name(s) of the above-listed copyright holder(s) 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE 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.
+ */
+
+#include "wifi_hal_ctrl.h"
+
+struct wifihal_ctrl * wifihal_ctrl_open2(const char *ctrl_path,
+ const char *cli_path)
+{
+ struct wifihal_ctrl *ctrl;
+ static int counter = 0;
+ int retval;
+ size_t res;
+ int tries = 0;
+ int flags;
+#ifdef ANDROID
+ struct group *grp_wifi;
+ gid_t gid_wifi;
+ struct passwd *pwd_system;
+ uid_t uid_system;
+#endif
+
+ if (ctrl_path == NULL)
+ return NULL;
+
+ ctrl = malloc(sizeof(*ctrl));
+ if (ctrl == NULL) {
+ return NULL;
+ }
+
+ memset(ctrl, 0, sizeof(*ctrl));
+ ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (ctrl->s < 0) {
+ free(ctrl);
+ return NULL;
+ }
+
+ ctrl->local.sun_family = AF_UNIX;
+
+try_again:
+ if (cli_path && cli_path[0] == '/') {
+ res = strlcpy(ctrl->local.sun_path, cli_path,
+ sizeof(ctrl->local.sun_path));
+
+ if (res >= sizeof(ctrl->local.sun_path)) {
+ close(ctrl->s);
+ free(ctrl);
+ return NULL;
+ }
+
+ } else {
+ counter++;
+ retval = snprintf(ctrl->local.sun_path,
+ sizeof(ctrl->local.sun_path),
+ CONFIG_CTRL_IFACE_CLIENT_DIR "/"
+ CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
+ (int) getpid(), counter);
+ }
+ tries++;
+ if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
+ sizeof(ctrl->local)) < 0) {
+ if (errno == EADDRINUSE && tries < 2) {
+ /*
+ * getpid() returns unique identifier for this instance
+ * of wifihal_ctrl, so the existing socket file must have
+ * been left by unclean termination of an earlier run.
+ * Remove the file and try again.
+ */
+ unlink(ctrl->local.sun_path);
+ goto try_again;
+ }
+ close(ctrl->s);
+ free(ctrl);
+ return NULL;
+ }
+
+#ifdef ANDROID
+ chmod(ctrl->local.sun_path, S_IRWXU | S_IRWXG );
+
+ /* Set group even if we do not have privileges to change owner */
+ grp_wifi = getgrnam("wifi");
+ gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
+ pwd_system = getpwnam("system");
+ uid_system = pwd_system ? pwd_system->pw_uid : 0;
+ if (!gid_wifi || !uid_system) {
+ wifihal_ctrl_close(ctrl);
+ return NULL;
+ }
+ chown(ctrl->local.sun_path, -1, gid_wifi);
+ chown(ctrl->local.sun_path, uid_system, gid_wifi);
+
+
+ if (*ctrl_path != '/') {
+ wifihal_ctrl_close(ctrl);
+ return NULL;
+ }
+#endif /* ANDROID */
+
+ ctrl->dest.sun_family = AF_UNIX;
+ res = strlcpy(ctrl->dest.sun_path, ctrl_path,
+ sizeof(ctrl->dest.sun_path));
+ if (res >= sizeof(ctrl->dest.sun_path)) {
+ wifihal_ctrl_close(ctrl);
+ return NULL;
+ }
+ if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
+ sizeof(ctrl->dest)) < 0) {
+ wifihal_ctrl_close(ctrl);
+ return NULL;
+ }
+ /*
+ * Make socket non-blocking so that we don't hang forever if
+ * target dies unexpectedly.
+ */
+ flags = fcntl(ctrl->s, F_GETFL);
+ if (flags >= 0) {
+ flags |= O_NONBLOCK;
+ if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
+ perror("fcntl(ctrl->s, O_NONBLOCK)");
+ /* Not fatal, continue on.*/
+ }
+ }
+ return ctrl;
+}
+
+struct wifihal_ctrl * wifihal_ctrl_open(const char *ctrl_path)
+{
+ return wifihal_ctrl_open2(ctrl_path, NULL);
+}
+
+void wifihal_ctrl_close(struct wifihal_ctrl *ctrl)
+{
+ if (ctrl == NULL)
+ return;
+ unlink(ctrl->local.sun_path);
+ if (ctrl->s >= 0)
+ close(ctrl->s);
+ free(ctrl);
+}
+
+int wifihal_ctrl_request2(struct wifihal_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len, time_t sec, suseconds_t usec)
+{
+ struct timeval tv;
+ int counter = 0, res;
+ fd_set rfds;
+ const char *_cmd;
+ size_t _cmd_len;
+ char *cmd_buf = NULL;
+
+ _cmd = cmd;
+ _cmd_len = cmd_len;
+
+ errno = 0;
+retry_send:
+ if (sendto(ctrl->s, _cmd, _cmd_len, 0, (struct sockaddr *)&ctrl->dest, sizeof(ctrl->dest)) < 0) {
+ if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK)
+ {
+ /*
+ * Must be a non-blocking socket... Try for a bit
+ * longer before giving up.
+ */
+ if(counter == 5) {
+ goto send_err;
+ } else {
+ counter++;
+ }
+ sleep(1);
+ goto retry_send;
+ }
+ send_err:
+ free(cmd_buf);
+ return -1;
+ }
+ free(cmd_buf);
+
+ for (;;) {
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
+ FD_ZERO(&rfds);
+ FD_SET(ctrl->s, &rfds);
+ res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+ if (res < 0 && errno == EINTR)
+ continue;
+ if (res < 0)
+ return res;
+ if (FD_ISSET(ctrl->s, &rfds)) {
+ res = recv(ctrl->s, reply, *reply_len, 0);
+ if (res < 0)
+ return res;
+ *reply_len = res;
+ break;
+ } else {
+ return -2;
+ }
+ }
+ return 0;
+}
+
+
+int wifihal_ctrl_request(struct wifihal_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len)
+{
+ return wifihal_ctrl_request2(ctrl, cmd, cmd_len, reply, reply_len, 1, 0);
+}
diff --git a/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h b/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h
new file mode 100644
index 0000000..f0cdaa3
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifi_hal_ctrl/wifi_hal_ctrl.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name(s) of the above-listed copyright holder(s) 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE 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 WIFIHAL_CTRL_H
+#define WIFIHAL_CTRL_H
+
+#include <sys/un.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "stdlib.h"
+
+#ifdef ANDROID
+#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <cutils/sockets.h>
+#endif /* ANDROID */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct wifihal_ctrl - Internal structure for control interface library
+ *
+ * This structure is used by the clients to interface with WiFi Hal
+ * library to store internal data. Programs using the library should not touch
+ * this data directly. They can only use the pointer to the data structure as
+ * an identifier for the control interface connection and use this as one of
+ * the arguments for most of the control interface library functions.
+ */
+
+struct wifihal_ctrl {
+ int s;
+ struct sockaddr_un local;
+ struct sockaddr_un dest;
+};
+
+#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
+#define CONFIG_CTRL_IFACE_CLIENT_DIR "/dev/socket/wifihal"
+#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
+#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
+#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wifihal_ctrl_cli_"
+#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
+
+#define DEFAULT_PAGE_SIZE 4096
+
+enum nl_family_type
+{
+ //! gen netlink family
+ GENERIC_NL_FAMILY = 1,
+ //! Cld80211 family
+ CLD80211_FAMILY
+};
+
+
+enum wifihal_ctrl_cmd
+{
+ /** attach monitor sock */
+ WIFIHAL_CTRL_MONITOR_ATTACH,
+ /** dettach monitor sock */
+ WIFIHAL_CTRL_MONITOR_DETTACH,
+ /** Send data over Netlink Sock */
+ WIFIHAL_CTRL_SEND_NL_DATA,
+};
+
+//! WIFIHAL Control Request
+typedef struct wifihal_ctrl_req_s {
+ //! ctrl command
+ uint32_t ctrl_cmd;
+ //! Family name
+ uint32_t family_name;
+ //! command ID
+ uint32_t cmd_id;
+ //! monitor sock len
+ uint32_t monsock_len;
+ //! monitor sock
+ struct sockaddr_un monsock;
+ //! data buff length
+ uint32_t data_len;
+ //! reserved
+ uint32_t reserved[4];
+ //! data
+ char data[0];
+}wifihal_ctrl_req_t;
+
+
+//! WIFIHAL Sync Response
+typedef struct wifihal_ctrl_sync_rsp_s {
+ //! ctrl command
+ uint32_t ctrl_cmd;
+ //! Family name
+ uint32_t family_name;
+ //! command ID
+ uint32_t cmd_id;
+ //! status for the request
+ int status;
+ //! reserved
+ uint32_t reserved[4];
+}wifihal_ctrl_sync_rsp_t;
+
+//! WIFIHAL Async Response
+typedef struct wifihal_ctrl_event_s {
+ //! Family name
+ uint32_t family_name;
+ //! command ID
+ uint32_t cmd_id;
+ //! data buff length
+ uint32_t data_len;
+ //! reserved
+ uint32_t reserved;
+ //! data
+ char data[0];
+}wifihal_ctrl_event_t;
+
+/* WiFi Hal control interface access */
+
+/**
+ * wifihal_ctrl_open - Open a control interface to WiFi-Hal
+ * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
+ * Returns: Pointer to abstract control interface data or %NULL on failure
+ *
+ * This function is used to open a control interface to WiFi-Hal.
+ * ctrl_path is usually /var/run/wifihal. This path
+ * is configured in WiFi-Hal and other programs using the control
+ * interface need to use matching path configuration.
+ */
+struct wifihal_ctrl * wifihal_ctrl_open(const char *ctrl_path);
+
+/**
+ * wifihal_ctrl_open2 - Open a control interface to wifihal
+ * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
+ * @cli_path: Path for client UNIX domain sockets; ignored if UDP socket
+ * is used.
+ * Returns: Pointer to abstract control interface data or %NULL on failure
+ *
+ * This function is used to open a control interface to wifihal
+ * when the socket path for client need to be specified explicitly. Default
+ * ctrl_path is usually /var/run/wifihal and client
+ * socket path is /tmp.
+ */
+struct wifihal_ctrl * wifihal_ctrl_open2(const char *ctrl_path, const char *cli_path);
+
+
+/**
+ * wifihal_ctrl_close - Close a control interface to wifihal
+ * @ctrl: Control interface data from wifihal_ctrl_open()
+ *
+ * This function is used to close a control interface.
+ */
+void wifihal_ctrl_close(struct wifihal_ctrl *ctrl);
+
+
+/**
+ * wifihal_ctrl_request2 - Send a command to wifihal
+ * @ctrl: Control interface data from wifihal_ctrl_open()
+ * @cmd: Command; usually, hexadecimal data
+ * @cmd_len: Length of the cmd in bytes
+ * @reply: Buffer for the response
+ * @reply_len: Reply buffer length
+ * @sec: time in secs
+ * @usec: time in micro secs
+ * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
+ *
+ * This function is used to send commands to wifihal. Received
+ * response will be written to reply and reply_len is set to the actual length
+ * of the reply. This function will block for up to two seconds while waiting
+ * for the reply. If unsolicited messages are received, the blocking time may
+ * be longer.
+ *
+ */
+int wifihal_ctrl_request2(struct wifihal_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len, time_t sec, suseconds_t usec);
+
+/**
+ * wifihal_ctrl_request - Send a command to wifihal
+ * @ctrl: Control interface data from wifihal_ctrl_open()
+ * @cmd: Command; usually, hexadecimal data
+ * @cmd_len: Length of the cmd in bytes
+ * @reply: Buffer for the response
+ * @reply_len: Reply buffer length
+ * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
+ *
+ * This function is used to send commands to wifihal. Received
+ * response will be written to reply and reply_len is set to the actual length
+ * of the reply. This function will block for up to two seconds while waiting
+ * for the reply. If unsolicited messages are received, the blocking time may
+ * be longer.
+ *
+ */
+int wifihal_ctrl_request(struct wifihal_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/wcn6740/qcwcn/wifi_hal/wificonfig.cpp b/wcn6740/qcwcn/wifi_hal/wificonfig.cpp
new file mode 100644
index 0000000..5aec138
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wificonfig.cpp
@@ -0,0 +1,1530 @@
+/* Copyright (c) 2015, 2018 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+#define LOG_TAG "WifiHAL"
+#include <utils/Log.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string>
+#include <net/if.h>
+#include <vector>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include "wificonfigcommand.h"
+#include "ifaceeventhandler.h"
+
+#define NUM_OF_SAR_LIMITS_SPECS 2
+#define NUM_OF_SPEC_CHAINS 2
+
+/* Implementation of the API functions exposed in wifi_config.h */
+wifi_error wifi_extended_dtim_config_set(wifi_request_id id,
+ wifi_interface_handle iface,
+ int extended_dtim)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ ALOGV("%s: extended_dtim:%d", __FUNCTION__, extended_dtim);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_extended_dtim_config_set: failed to create NL msg. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_extended_dtim_config_set: failed to set iface id. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_extended_dtim_config_set: failed attr_start for "
+ "VENDOR_DATA. Error:%d", ret);
+ goto cleanup;
+ }
+
+ ret = wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM, extended_dtim);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_extended_dtim_config_set(): failed to put vendor data. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_extended_dtim_config_set(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+int check_feature(enum qca_wlan_vendor_features feature, features_info *info)
+{
+ size_t idx = feature / 8;
+
+ return (idx < info->flags_len) &&
+ (info->flags[idx] & BIT(feature % 8));
+}
+
+/* Set the country code to driver. */
+wifi_error wifi_set_country_code(wifi_interface_handle iface,
+ const char* country_code)
+{
+ int requestId;
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ ALOGV("%s: %s", __FUNCTION__, country_code);
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate it randomly.
+ */
+ requestId = get_requestid();
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message with NL80211_CMD_REQ_SET_REG NL cmd. */
+ ret = wifiConfigCommand->create_generic(NL80211_CMD_REQ_SET_REG);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_country_code: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ ret = wifiConfigCommand->put_string(NL80211_ATTR_REG_ALPHA2, country_code);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_country_code: put country code failed. Error:%d", ret);
+ goto cleanup;
+ }
+
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY,
+ &info->driver_supported_features)) {
+ ret = wifiConfigCommand->put_u32(NL80211_ATTR_USER_REG_HINT_TYPE,
+ NL80211_USER_REG_HINT_CELL_BASE);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_country_code: put reg hint type failed. Error:%d",
+ ret);
+ goto cleanup;
+ }
+ }
+
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_country_code(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+ usleep(WAIT_TIME_FOR_SET_REG_DOMAIN);
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+/*
+ * Set the powersave to driver.
+ */
+wifi_error wifi_set_qpower(wifi_interface_handle iface,
+ u8 powersave)
+{
+ int requestId, ret = 0;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ //hal_info *info = getHalInfo(wifiHandle);
+
+ ALOGD("%s: %d", __FUNCTION__, powersave);
+
+ requestId = get_requestid();
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret < 0) {
+ ALOGE("wifi_set_qpower: failed to create NL msg. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret < 0) {
+ ALOGE("wifi_set_qpower: failed to set iface id. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_qpower: failed attr_start for "
+ "VENDOR_DATA. Error:%d", ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER, powersave)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_qpower(): failed to put vendor data. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != 0) {
+ ALOGE("wifi_set_qpower(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return (wifi_error)ret;
+
+}
+
+wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor(
+ wifi_request_id id,
+ wifi_interface_handle iface,
+ u16 factor)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ ALOGV("%s factor:%u", __FUNCTION__, factor);
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to "
+ "create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed to "
+ "set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor: failed "
+ "attr_start for VENDOR_DATA. Error:%d", ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, factor)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): failed to "
+ "put vendor data. Error:%d", ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_beacon_wifi_iface_stats_averaging_factor(): "
+ "requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_set_guard_time(wifi_request_id id,
+ wifi_interface_handle iface,
+ u32 guard_time)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ ALOGV("%s : guard_time:%u", __FUNCTION__, guard_time);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ id,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_guard_time: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_guard_time: failed to set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_guard_time: failed attr_start for VENDOR_DATA. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, guard_time)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_set_guard_time: failed to add vendor data.");
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_set_guard_time(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_select_SARv01_tx_power_scenario(wifi_interface_handle handle,
+ wifi_power_scenario scenario)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ u32 bdf_file = 0;
+
+ ALOGV("%s : power scenario:%d", __FUNCTION__, scenario);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ 1,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ switch (scenario) {
+ /* WIFI_POWER_SCENARIO_VOICE_CALL is used by VTS test to check this API.
+ * We should not remove this scenario even we don't use it in new projects.
+ */
+ case WIFI_POWER_SCENARIO_VOICE_CALL:
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF:
+ case WIFI_POWER_SCENARIO_ON_BODY_BT:
+ bdf_file = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
+ break;
+
+ default:
+ ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
+ bdf_file)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_ENABLE");
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_select_SARv02_tx_power_scenario(wifi_interface_handle handle,
+ wifi_power_scenario scenario)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData, *nlSpecList, *nlSpec;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ u32 power_lim_idx = 0;
+
+ ALOGV("%s : power scenario SARV2:%d", __FUNCTION__, scenario);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ 1,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario: failed to set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_select_tx_power_scenario: failed attr_start for VENDOR_DATA.");
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_ENABLE");
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS,
+ NUM_OF_SAR_LIMITS_SPECS)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_LIMITS_NUM_SPECS");
+ goto cleanup;
+ }
+
+ switch (scenario) {
+ case WIFI_POWER_SCENARIO_VOICE_CALL:
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW:
+
+ power_lim_idx = 0;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF:
+ power_lim_idx = 1;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW:
+ case WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW:
+ power_lim_idx = 2;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON:
+ power_lim_idx = 3;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT:
+ power_lim_idx = 4;
+ break;
+
+ case WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF:
+ case WIFI_POWER_SCENARIO_ON_BODY_BT:
+ power_lim_idx = 5;
+ break;
+ default:
+ ALOGE("wifi_select_tx_power_scenario: invalid scenario %d", scenario);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+
+
+ nlSpecList = wifiConfigCommand->attr_start(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC);
+ if (!nlSpecList)
+ {
+ ALOGE("Cannot create spec list");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+
+ for (int i = 0; i < NUM_OF_SPEC_CHAINS; i++) {
+ nlSpec = wifiConfigCommand->attr_start(0);
+ if (!nlSpec) {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN,
+ i))
+ {
+ ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX,
+ power_lim_idx))
+ {
+ ALOGE("Failed to put: QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX");
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ wifiConfigCommand->attr_end(nlSpec);
+ }
+
+
+
+ wifiConfigCommand->attr_end(nlSpecList);
+
+ wifiConfigCommand->attr_end(nlData);
+ ALOGV("wifi_select_tx_power_scenario %u selected", power_lim_idx);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_select_tx_power_scenario(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+
+wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
+ wifi_power_scenario scenario)
+{
+
+ wifi_handle wifiHandle = getWifiHandle(handle);
+ hal_info *info = getHalInfo(wifiHandle);
+ if (info == NULL) {
+ ALOGE("%s: Error hal_info NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ ALOGV("wifi_select_tx_power_scenario: sarVer%u", (u32)info->sar_version);
+ if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_1)
+ return wifi_select_SARv01_tx_power_scenario(handle,scenario);
+ else if (info->sar_version == QCA_WLAN_VENDOR_SAR_VERSION_2)
+ return wifi_select_SARv02_tx_power_scenario(handle,scenario);
+ else {
+ ALOGE("wifi_select_tx_power_scenario %u invalid or not supported", (u32)info->sar_version);
+ return WIFI_ERROR_UNKNOWN;
+ }
+}
+
+
+wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ 1,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_reset_tx_power_scenario: failed to create NL msg. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_reset_tx_power_scenario: failed to set iface id. Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("wifi_reset_tx_power_scenario: failed attr_start for VENDOR_DATA. "
+ "Error:%d", ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("failed to put SAR_ENABLE or NUM_SPECS");
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("wifi_reset_tx_power_scenario(): requestEvent Error:%d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle,
+ wifi_thermal_mode mode,
+ u32 completion_window)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ u32 qca_vendor_thermal_level;
+ hal_info *info = getHalInfo(handle);
+
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error wifi_handle NULL or base wlan interface not present",
+ __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ handle,
+ 1,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error, Failed to create wifiConfigCommand", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to create thermal vendor command, Error:%d", ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ if (wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+ info->interfaces[0]->id)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to put iface id", __FUNCTION__);
+ goto cleanup;
+ }
+
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed in attr_start for VENDOR_DATA, Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("Failed to put THERMAL_LEVEL command type");
+ goto cleanup;
+ }
+
+ switch(mode) {
+ case WIFI_MITIGATION_NONE:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE;
+ break;
+ case WIFI_MITIGATION_LIGHT:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT;
+ break;
+ case WIFI_MITIGATION_MODERATE:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE;
+ break;
+ case WIFI_MITIGATION_SEVERE:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE;
+ break;
+ case WIFI_MITIGATION_CRITICAL:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL;
+ break;
+ case WIFI_MITIGATION_EMERGENCY:
+ qca_vendor_thermal_level = QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY;
+ break;
+ default:
+ ALOGE("Unknown thermal mitigation level %d", mode);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL,
+ qca_vendor_thermal_level)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("Failed to put thermal level");
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW,
+ completion_window)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("Failed to put thermal completion window");
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to set thermal level with Error: %d", ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+WiFiConfigCommand::WiFiConfigCommand(wifi_handle handle,
+ int id, u32 vendor_id,
+ u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ /* Initialize the member data variables here */
+ mWaitforRsp = false;
+ mRequestId = id;
+}
+
+WiFiConfigCommand::~WiFiConfigCommand()
+{
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+}
+
+/* This function implements creation of Vendor command */
+wifi_error WiFiConfigCommand::create()
+{
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ /* Insert the oui in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+ /* Insert the subcmd in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+
+ return ret;
+}
+
+/* This function implements creation of generic NL command */
+wifi_error WiFiConfigCommand::create_generic(u8 cmdId)
+{
+ wifi_error ret = mMsg.create(cmdId, 0, 0);
+ return ret;
+}
+
+void WiFiConfigCommand::waitForRsp(bool wait)
+{
+ mWaitforRsp = wait;
+}
+
+/* Callback handlers registered for nl message send */
+static int error_handler_wifi_config(struct sockaddr_nl *nla,
+ struct nlmsgerr *err,
+ void *arg)
+{
+ struct sockaddr_nl *tmp;
+ int *ret = (int *)arg;
+ tmp = nla;
+ *ret = err->error;
+ ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
+ return NL_STOP;
+}
+
+/* Callback handlers registered for nl message send */
+static int ack_handler_wifi_config(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ struct nl_msg * a;
+
+ a = msg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+/* Callback handlers registered for nl message send */
+static int finish_handler_wifi_config(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ struct nl_msg * a;
+
+ a = msg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+/*
+ * Override base class requestEvent and implement little differently here.
+ * This will send the request message.
+ * We don't wait for any response back in case of wificonfig,
+ * thus no wait for condition.
+ */
+wifi_error WiFiConfigCommand::requestEvent()
+{
+ int status;
+ wifi_error res = WIFI_SUCCESS;
+ struct nl_cb *cb = NULL;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ ALOGE("%s: Callback allocation failed",__FUNCTION__);
+ res = WIFI_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
+ if (status < 0) {
+ res = mapKernelErrortoWifiHalError(status);
+ goto out;
+ }
+ status = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_config, &status);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_config,
+ &status);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_config, &status);
+
+ /* Err is populated as part of finish_handler. */
+ while (status > 0) {
+ nl_recvmsgs(mInfo->cmd_sock, cb);
+ }
+
+ if (status < 0) {
+ res = mapKernelErrortoWifiHalError(status);
+ goto out;
+ }
+
+ if (mWaitforRsp == true) {
+ struct timespec abstime;
+ abstime.tv_sec = 4;
+ abstime.tv_nsec = 0;
+ res = mCondition.wait(abstime);
+ if (res == WIFI_ERROR_TIMED_OUT)
+ ALOGE("%s: Time out happened.", __FUNCTION__);
+
+ ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d",
+ __FUNCTION__, res, mWaitforRsp);
+ }
+out:
+ nl_cb_put(cb);
+ /* Cleanup the mMsg */
+ mMsg.destroy();
+ return res;
+}
+
+
+
+static std::vector<std::string> added_ifaces;
+
+static bool is_dynamic_interface(const char * ifname)
+{
+ for (const auto& iface : added_ifaces) {
+ if (iface == std::string(ifname))
+ return true;
+ }
+ return false;
+}
+
+void wifi_cleanup_dynamic_ifaces(wifi_handle handle)
+{
+ int len = added_ifaces.size();
+ while (len--) {
+ wifi_virtual_interface_delete(handle, added_ifaces.front().c_str());
+ }
+ added_ifaces.clear(); // could be redundent. But to be on safe side.
+}
+
+static wifi_error wifi_set_interface_mode(wifi_handle handle,
+ const char* ifname,
+ u32 iface_type)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+
+ ALOGD("%s: ifname=%s iface_type=%u", __FUNCTION__, ifname, iface_type);
+
+ wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nl80211_iftype type;
+ switch(iface_type) {
+ case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */
+ type = NL80211_IFTYPE_STATION;
+ break;
+ case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */
+ type = NL80211_IFTYPE_AP;
+ break;
+ case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */
+ type = NL80211_IFTYPE_P2P_DEVICE;
+ break;
+ case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */
+ type = NL80211_IFTYPE_NAN;
+ break;
+ default:
+ ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto done;
+ break;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_SET_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+ }
+
+done:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_virtual_interface_create(wifi_handle handle,
+ const char* ifname,
+ wifi_interface_type iface_type)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ hal_info *info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error wifi_handle NULL or base wlan interface not present", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ // Already exists and set interface mode only
+ if (if_nametoindex(ifname) != 0) {
+ return wifi_set_interface_mode(handle, ifname, iface_type);
+ }
+
+ ALOGD("%s: ifname=%s create", __FUNCTION__, ifname);
+
+ wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ nl80211_iftype type;
+ switch(iface_type) {
+ case WIFI_INTERFACE_TYPE_STA: /* IfaceType:STA */
+ type = NL80211_IFTYPE_STATION;
+ break;
+ case WIFI_INTERFACE_TYPE_AP: /* IfaceType:AP */
+ type = NL80211_IFTYPE_AP;
+ break;
+ case WIFI_INTERFACE_TYPE_P2P: /* IfaceType:P2P */
+ type = NL80211_IFTYPE_P2P_DEVICE;
+ break;
+ case WIFI_INTERFACE_TYPE_NAN: /* IfaceType:NAN */
+ type = NL80211_IFTYPE_NAN;
+ break;
+ default:
+ ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto done;
+ break;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,info->interfaces[0]->id);
+ wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+ }
+ // Update dynamic interface list
+ added_ifaces.push_back(std::string(ifname));
+ if (iface_type == WIFI_INTERFACE_TYPE_STA) {
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if(sock < 0) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s :socket error, Failed to bring up iface \n", __func__);
+ goto done;
+ }
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s :Could not read interface %s flags \n", __func__, ifname);
+ goto done;
+ }
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s :Could not bring iface %s up \n", __func__, ifname);
+ }
+ }
+
+done:
+ delete wifiConfigCommand;
+ return ret;
+}
+
+wifi_error wifi_virtual_interface_delete(wifi_handle handle,
+ const char* ifname)
+{
+ wifi_error ret;
+ WiFiConfigCommand *wifiConfigCommand;
+ if (!handle) {
+ ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: ifname=%s delete", __FUNCTION__, ifname);
+ if (if_nametoindex(ifname) && !is_dynamic_interface(ifname)) {
+ // Do not remove interface if it was not added dynamically.
+ return WIFI_SUCCESS;
+ }
+ wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+ wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+ }
+ // Update dynamic interface list
+ added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
+ added_ifaces.end());
+
+ delete wifiConfigCommand;
+ return ret;
+}
+
+/**
+ * Set latency level
+ */
+wifi_error wifi_set_latency_mode(wifi_interface_handle iface,
+ wifi_latency_mode mode)
+{
+ int requestId, ret = 0;
+ u16 level;
+ WiFiConfigCommand *wifiConfigCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ ALOGD("%s: %d", __FUNCTION__, mode);
+
+ if (!(info->supported_feature_set & WIFI_FEATURE_SET_LATENCY_MODE)) {
+ ALOGE("%s: Latency Mode is not supported by driver", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ };
+
+ switch (mode) {
+ case WIFI_LATENCY_MODE_NORMAL:
+ level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
+ break;
+ case WIFI_LATENCY_MODE_LOW:
+ level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW;
+ break;
+ default:
+ ALOGI("%s: Unsupported latency mode=%d, resetting to NORMAL!", __FUNCTION__, mode);
+ level = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL;
+ break;
+ }
+
+ requestId = get_requestid();
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret < 0) {
+ ALOGE("%s: failed to set iface id. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u16(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL, level)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed to put vendor data. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != 0) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return (wifi_error)ret;
+}
+
+/**
+ * Set STA + STA primary iface connection
+ */
+wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle,
+ wifi_interface_handle iface)
+{
+ int requestId, ret = 0;
+ WiFiConfigCommand *wifiConfigCommand;
+ if (!handle) {
+ ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+
+ requestId = get_requestid();
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ handle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret < 0) {
+ ALOGE("%s: failed to set iface id. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY, 1)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed to put vendor data. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != 0) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return (wifi_error)ret;
+}
+
+/**
+ * Set STA + STA use case
+ */
+wifi_error wifi_multi_sta_set_use_case(wifi_handle handle,
+ wifi_multi_sta_use_case case_info)
+{
+ int requestId, ret = 0;
+ u8 use_case;
+ WiFiConfigCommand *wifiConfigCommand;
+ if (!handle) {
+ ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ struct nlattr *nlData;
+ hal_info *info = getHalInfo(handle);
+ if (!info || info->num_interfaces < 1) {
+ ALOGE("%s: Error wifi_handle NULL or base wlan interface not present", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGD("%s: %d", __FUNCTION__, case_info);
+
+ switch (case_info) {
+ case WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY:
+ use_case = QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY;
+ break;
+ case WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED:
+ use_case = QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED;
+ break;
+ default:
+ ALOGE("%s: Unknown use case %d", __FUNCTION__, case_info);
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;;
+ }
+
+ requestId = get_requestid();
+
+ wifiConfigCommand = new WiFiConfigCommand(
+ handle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ if (wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+ info->interfaces[0]->id)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: Failed to put iface id", __FUNCTION__);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG, use_case)) {
+ ret = WIFI_ERROR_UNKNOWN;
+ ALOGE("%s: failed to put use_case. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != 0) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return (wifi_error)ret;
+}
+
+/**
+ * Invoked to set voip optimization mode for the provided STA iface
+ */
+ wifi_error wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode)
+{
+ int requestId, ret = 0;
+ WiFiConfigCommand *wifiConfigCommand;
+
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ if (!wifiHandle) {
+ ALOGE("%s: Error wifi_handle NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ requestId = get_requestid();
+ ALOGV("%s: voip mode=%d", __FUNCTION__, mode);
+ wifiConfigCommand = new WiFiConfigCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+
+ if (wifiConfigCommand == NULL) {
+ ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiConfigCommand->create();
+ if (ret < 0) {
+ ALOGE("%s: failed to create NL msg. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Set the interface Id of the message. */
+ ret = wifiConfigCommand->set_iface_id(ifaceInfo->name);
+ if (ret < 0) {
+ ALOGE("%s: failed to set iface id. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiConfigCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData) {
+ ALOGE("%s: failed attr_start for VENDOR_DATA. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ if (wifiConfigCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE, (u8)mode)) {
+ ALOGE("%s: failed to put vendor data. Error:%d",
+ __FUNCTION__, ret);
+ goto cleanup;
+ }
+ wifiConfigCommand->attr_end(nlData);
+
+ /* Send the NL msg. */
+ wifiConfigCommand->waitForRsp(false);
+ ret = wifiConfigCommand->requestEvent();
+ if (ret != 0) {
+ ALOGE("%s: requestEvent Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ delete wifiConfigCommand;
+ return (wifi_error)ret;
+}
diff --git a/wcn6740/qcwcn/wifi_hal/wificonfigcommand.h b/wcn6740/qcwcn/wifi_hal/wificonfigcommand.h
new file mode 100644
index 0000000..cc0f9e0
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wificonfigcommand.h
@@ -0,0 +1,111 @@
+/* Copyright (c) 2014, 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.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 __WIFI_HAL_WIFI_CONFIG_COMMAND_H__
+#define __WIFI_HAL_WIFI_CONFIG_COMMAND_H__
+
+#include "common.h"
+#include "cpp_bindings.h"
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
+#include "wifi_config.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+int check_feature(enum qca_wlan_vendor_features feature, features_info *info);
+
+class WiFiConfigCommand: public WifiVendorCommand
+{
+private:
+ int mRequestId;
+ bool mWaitforRsp;
+
+public:
+ WiFiConfigCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+ virtual ~WiFiConfigCommand();
+
+ /*
+ * This function implements creation of WiFiConfigCommand specific Request
+ * based on the QCA vendor specific request type.
+ */
+ virtual wifi_error create();
+ /*
+ * This function implements creation of WiFiConfigCommand specific Request
+ * based on the generic NL request type.
+ */
+ virtual wifi_error create_generic(u8 cmdId);
+ virtual void waitForRsp(bool wait);
+ virtual wifi_error requestEvent();
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/qcwcn/wifi_hal/wifihal_internal.h b/wcn6740/qcwcn/wifi_hal/wifihal_internal.h
old mode 100755
new mode 100644
similarity index 100%
copy from qcwcn/wifi_hal/wifihal_internal.h
copy to wcn6740/qcwcn/wifi_hal/wifihal_internal.h
diff --git a/wcn6740/qcwcn/wifi_hal/wifihal_vendor.cpp b/wcn6740/qcwcn/wifi_hal/wifihal_vendor.cpp
new file mode 100644
index 0000000..4837e63
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifihal_vendor.cpp
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2017-2018, 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.
+
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "wifihal_vendorcommand.h"
+
+#define MAX_INFO 1
+//Singleton Static Instance
+NUDStatsCommand* NUDStatsCommand::mNUDStatsCommandInstance = NULL;
+
+// This function implements creation of Vendor command
+// For NUDStats just call base Vendor command create
+wifi_error NUDStatsCommand::create() {
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS) {
+ return ret;
+ }
+ // insert the oui in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+ // insert the subcmd in the msg
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+out:
+ return ret;
+}
+
+NUDStatsCommand::NUDStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ memset(&mStats, 0,sizeof(nud_stats));
+ mpktInfo = NULL;
+ mnumStats = 0;
+}
+
+NUDStatsCommand::~NUDStatsCommand()
+{
+ mNUDStatsCommandInstance = NULL;
+}
+
+NUDStatsCommand* NUDStatsCommand::instance(wifi_handle handle)
+{
+ if (handle == NULL) {
+ ALOGE("Interface Handle is invalid");
+ return NULL;
+ }
+ if (mNUDStatsCommandInstance == NULL) {
+ mNUDStatsCommandInstance = new NUDStatsCommand(handle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET);
+ return mNUDStatsCommandInstance;
+ }
+ else
+ {
+ if (handle != getWifiHandle(mNUDStatsCommandInstance->mInfo))
+ {
+ /* upper layer must have cleaned up the handle and reinitialized,
+ so we need to update the same */
+ ALOGE("Handle different, update the handle");
+ mNUDStatsCommandInstance->mInfo = (hal_info *)handle;
+ }
+ }
+ return mNUDStatsCommandInstance;
+}
+
+void NUDStatsCommand::setSubCmd(u32 subcmd)
+{
+ mSubcmd = subcmd;
+}
+
+void NUDStatsCommand::setHandler(pkt_stats_result_handler handler)
+{
+ mHandler = handler;
+}
+
+wifi_error NUDStatsCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+wifi_error NUDStatsCommand::notifyResponse()
+{
+ wifi_error ret = WIFI_SUCCESS;
+
+ if (mHandler.on_pkt_stats_results) {
+ mHandler.on_pkt_stats_results(&mStats, mnumStats,
+ mpktInfo);
+ } else {
+ ret = WIFI_ERROR_INVALID_ARGS;
+ }
+ return ret;
+}
+
+int NUDStatsCommand::handleResponse(WifiEvent &reply)
+{
+ wifi_error status = WIFI_ERROR_NONE;
+ WifiVendorCommand::handleResponse(reply);
+
+ // Parse the vendordata and get the attribute
+
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET:
+ {
+ struct nlattr *tb_vendor[QCA_ATTR_NUD_STATS_GET_MAX + 1];
+ nud_stats *stats = &mStats;
+
+ memset(stats, 0, sizeof(nud_stats));
+ nla_parse(tb_vendor, QCA_ATTR_NUD_STATS_GET_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_req_count_from_netdev = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_req_count_to_lower_mac = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_req_rx_count_by_lower_mac = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_req_count_tx_success = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_rsp_rx_count_by_lower_mac = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_rsp_rx_count_by_upper_mac = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_rsp_count_to_netdev = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV]);
+
+ if (!tb_vendor[QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP])
+ {
+ ALOGE("%s: QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP"
+ " not found", __FUNCTION__);
+ status = WIFI_ERROR_INVALID_ARGS;
+ goto cleanup;
+ }
+ stats->arp_rsp_count_out_of_order_drop = nla_get_u16(tb_vendor[
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP]);
+
+ if (tb_vendor[QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE])
+ stats->ap_link_active = 1;
+
+ if (tb_vendor[QCA_ATTR_NUD_STATS_IS_DAD])
+ stats->is_duplicate_addr_detection = 1;
+
+ ALOGV(" req_from_netdev %d count_to_lower :%d"
+ " count_by_lower :%d"
+ " count_tx_succ :%d rsp_count_lower :%d"
+ " rsp_count_upper :%d rsp_count_netdev :%d"
+ " out_of_order_drop :%d active_aplink %d"
+ " DAD %d ",
+ stats->arp_req_count_from_netdev,
+ stats->arp_req_count_to_lower_mac,
+ stats->arp_req_rx_count_by_lower_mac,
+ stats->arp_req_count_tx_success,
+ stats->arp_rsp_rx_count_by_lower_mac,
+ stats->arp_rsp_rx_count_by_upper_mac,
+ stats->arp_rsp_count_to_netdev,
+ stats->arp_rsp_count_out_of_order_drop,
+ stats->ap_link_active,
+ stats->is_duplicate_addr_detection);
+
+ if (tb_vendor[QCA_ATTR_NUD_STATS_DATA_PKT_STATS]) {
+ mNUDStatsCommandInstance->GetPktInfo(tb_vendor);
+ }
+ }
+ }
+cleanup:
+ if (status == WIFI_ERROR_INVALID_ARGS)
+ memset(&mStats,0,sizeof(nud_stats));
+ if(mpktInfo != NULL)
+ free(mpktInfo);
+
+ return status;
+}
+
+void NUDStatsCommand::GetPktInfo(struct nlattr **tbvendor)
+{
+ struct nlattr *tb;
+ int rem;
+ cmdData *pkt_stats;
+ char ipv6_address[INET6_ADDRSTRLEN];
+ cmdData pktstats;
+ int nbuff = 0;
+
+ for (tb = (struct nlattr *) nla_data(tbvendor[QCA_ATTR_NUD_STATS_DATA_PKT_STATS]),
+ rem = nla_len(tbvendor[QCA_ATTR_NUD_STATS_DATA_PKT_STATS]);
+ nla_ok(tb, rem); tb = nla_next(tb, &(rem)))
+ {
+ struct nlattr *tb2[QCA_ATTR_NUD_DATA_STATS_MAX + 1];
+ nla_parse(tb2, QCA_ATTR_NUD_DATA_STATS_MAX,
+ (struct nlattr *) nla_data(tb), nla_len(tb), NULL);
+
+ memset(&pktstats, 0, sizeof(cmdData));
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_TYPE])
+ {
+ pktstats.pkt_Type = nla_get_u32(tb2[QCA_ATTR_NUD_STATS_PKT_TYPE]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME])
+ {
+ pktstats.domain_name = nla_get_string(tb2[QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_SRC_PORT])
+ {
+ pktstats.src_port = nla_get_u32(tb2[QCA_ATTR_NUD_STATS_PKT_SRC_PORT]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_DEST_PORT])
+ {
+ pktstats.dst_port = nla_get_u32(tb2[QCA_ATTR_NUD_STATS_PKT_DEST_PORT]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_DEST_IPV4])
+ {
+ pktstats.ipv4_addr.s_addr = nla_get_u32(tb2[QCA_ATTR_NUD_STATS_PKT_DEST_IPV4]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_DEST_IPV6])
+ {
+ memcpy(pktstats.ipv6_addr, nla_data(tb2[QCA_ATTR_NUD_STATS_PKT_DEST_IPV6]),
+ sizeof(pktstats.ipv6_addr));
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV])
+ {
+ pktstats.stats.pkt_req_count_from_netdev = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC])
+ {
+ pktstats.stats.pkt_req_count_to_lower_mac = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC])
+ {
+ pktstats.stats.pkt_req_rx_count_by_lower_mac = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS])
+ {
+ pktstats.stats.pkt_req_count_tx_success = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC])
+ {
+ pktstats.stats.pkt_rsp_rx_count_by_lower_mac = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC])
+ {
+ pktstats.stats.pkt_rsp_rx_count_by_upper_mac = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV])
+ {
+ pktstats.stats.pkt_rsp_count_to_netdev = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV]);
+ }
+
+ if (tb2[QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP])
+ {
+ pktstats.stats.pkt_rsp_count_out_of_order_drop = nla_get_u16(tb2[
+ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP]);
+ }
+
+ if (inet_ntop(AF_INET6, pktstats.ipv6_addr, ipv6_address,
+ INET6_ADDRSTRLEN) == NULL) {
+ ALOGE("%s: failed to convert ipv6 address format", __FUNCTION__);
+ }
+
+ ALOGV(" pkt_type %d domain_name :%s"
+ " src_port %d dst_port :%d"
+ " ipv4_address :%x ipv6_address %s"
+ " req_from_netdev %d count_to_lower :%d"
+ " count_by_lower :%d"
+ " count_tx_succ :%d rsp_count_lower :%d"
+ " rsp_count_upper :%d rsp_count_netdev :%d"
+ " out_of_order_drop :%d ",
+ pktstats.pkt_Type, pktstats.domain_name,
+ pktstats.src_port, pktstats.dst_port,
+ pktstats.ipv4_addr.s_addr, ipv6_address,
+ pktstats.stats.pkt_req_count_from_netdev,
+ pktstats.stats.pkt_req_count_to_lower_mac,
+ pktstats.stats.pkt_req_rx_count_by_lower_mac,
+ pktstats.stats.pkt_req_count_tx_success,
+ pktstats.stats.pkt_rsp_rx_count_by_lower_mac,
+ pktstats.stats.pkt_rsp_rx_count_by_upper_mac,
+ pktstats.stats.pkt_rsp_count_to_netdev,
+ pktstats.stats.pkt_rsp_count_out_of_order_drop);
+
+ if (nbuff == 0)
+ pkt_stats = (cmdData *)malloc(sizeof(cmdData));
+ else
+ pkt_stats = (cmdData *)realloc(pkt_stats,sizeof(cmdData) * (nbuff + 1));
+
+ mpktInfo = pkt_stats;
+ if (pkt_stats != NULL) {
+ memcpy(&pkt_stats[nbuff], &pktstats,sizeof(cmdData));
+ nbuff++;
+ mnumStats = nbuff;
+ }
+ }
+}
+
+void NUDStatsCommand::copyStats(nud_stats *stats, cmdData *pktstats)
+{
+ memcpy(stats, &mStats, sizeof(nud_stats));
+ pktstats = mpktInfo;
+}
+
+wifi_error wifi_set_nud_stats(wifi_interface_handle iface,
+ u32 gw_addr, cmdData Data)
+{
+ wifi_error ret;
+ NUDStatsCommand *NUDCommand;
+ struct nlattr *nl_data,*nl_pktInfo;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ cmdData mData = Data;
+ cmdData pktstats = Data;
+
+ ALOGV("gw_addr : %x", gw_addr);
+ NUDCommand = NUDStatsCommand::instance(handle);
+ if (NUDCommand == NULL) {
+ ALOGE("%s: Error NUDStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ NUDCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET);
+
+ /* create the message */
+ ret = NUDCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = NUDCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the attributes*/
+ nl_data = NUDCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data)
+ goto cleanup;
+ /**/
+ ret = NUDCommand->put_flag(QCA_ATTR_NUD_STATS_SET_START);
+
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_GW_IPV4, gw_addr);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ if (mData.pkt_Type) {
+ /*start the packet info attributes in nested*/
+ nl_pktInfo = NUDCommand->attr_start(QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO);
+ if (!nl_pktInfo)
+ goto cleanup;
+ else {
+ ALOGV(" pkt_type %d domain_name :%s"
+ " src_port %d dst_port :%d"
+ " ipv4_address :%x ipv6_address %s",
+ pktstats.pkt_Type, pktstats.domain_name,
+ pktstats.src_port, pktstats.dst_port,
+ pktstats.ipv4_addr.s_addr,pktstats.ipv6_addr);
+
+ for (int i=0; i < MAX_INFO ; i++) {
+ /*add the packet type attributes*/
+ struct nlattr *tb_tmp;
+ tb_tmp = NUDCommand->attr_start(i);
+
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE,mData.pkt_Type);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ if (mData.domain_name) {
+ /*add the domain name attributes*/
+ ret = NUDCommand->put_string(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DNS_DOMAIN_NAME,
+ mData.domain_name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ }
+ /*add the source port attributes*/
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_SRC_PORT,
+ mData.src_port);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the dest port attributes*/
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_PORT,
+ mData.dst_port);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the ipv4 address attributes*/
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV4,
+ mData.ipv4_addr.s_addr);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the ipv6 address attributes*/
+ ret = NUDCommand->put_ipv6_addr(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV6,
+ mData.ipv6_addr);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ NUDCommand->attr_end(tb_tmp);
+ }
+ }
+ NUDCommand->attr_end(nl_pktInfo);
+ }
+ NUDCommand->attr_end(nl_data);
+
+ ret = NUDCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ }
+
+cleanup:
+ return ret;
+}
+
+
+wifi_error wifi_get_nud_stats(wifi_interface_handle iface,
+ pkt_stats_result_handler handler)
+{
+ wifi_error ret;
+ NUDStatsCommand *NUDCommand;
+ struct nlattr *nl_data;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+
+ NUDCommand = NUDStatsCommand::instance(handle);
+ if (NUDCommand == NULL) {
+ ALOGE("%s: Error NUDStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ NUDCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET);
+
+ NUDCommand->setHandler(handler);
+
+ /* create the message */
+ ret = NUDCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = NUDCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+ /*add the attributes*/
+ nl_data = NUDCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ /**/
+ NUDCommand->attr_end(nl_data);
+
+ ret = NUDCommand->requestResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+ ret = NUDCommand->notifyResponse();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+ goto cleanup;
+ }
+
+cleanup:
+ return ret;
+}
+
+
+wifi_error wifi_clear_nud_stats(wifi_interface_handle iface,
+ cmdData Data)
+{
+ wifi_error ret;
+ NUDStatsCommand *NUDCommand;
+ struct nlattr *nl_data,*nl_pktInfo;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ cmdData mData = Data;
+
+ NUDCommand = NUDStatsCommand::instance(handle);
+ if (NUDCommand == NULL) {
+ ALOGE("%s: Error NUDStatsCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ NUDCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET);
+
+ /* create the message */
+ ret = NUDCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = NUDCommand->set_iface_id(iinfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /*add the attributes*/
+ nl_data = NUDCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nl_data){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ if (mData.pkt_Type) {
+ /*set the packet info attributes in nested*/
+ nl_pktInfo = NUDCommand->attr_start(QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO);
+ if (!nl_pktInfo){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ else {
+ ALOGV(" %s: pkt_type %d domain_name :%s"
+ " src_port %d dst_port :%d"
+ " ipv4_address :%x ipv6_address %s",
+ __FUNCTION__,mData.pkt_Type, mData.domain_name,
+ mData.src_port, mData.dst_port,
+ mData.ipv4_addr.s_addr,mData.ipv6_addr);
+
+ for (int i=0; i < MAX_INFO ; i++) {
+ /*add the packet type attributes*/
+ struct nlattr *tb_tmp;
+ tb_tmp = NUDCommand->attr_start(i);
+
+ ret = NUDCommand->put_u32(QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE,mData.pkt_Type);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ NUDCommand->attr_end(tb_tmp);
+ }
+ }
+ NUDCommand->attr_end(nl_pktInfo);
+ }
+ NUDCommand->attr_end(nl_data);
+
+ ret = NUDCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
+
+cleanup:
+ return ret;
+}
diff --git a/wcn6740/qcwcn/wifi_hal/wifihal_vendorcommand.h b/wcn6740/qcwcn/wifi_hal/wifihal_vendorcommand.h
new file mode 100644
index 0000000..123fe1e
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifihal_vendorcommand.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2018, 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 __WIFI_HAL_NUDSTATSCOMMAND_H__
+#define __WIFI_HAL_NUDSTATSCOMMAND_H__
+
+#include "nud_stats.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+class NUDStatsCommand: public WifiVendorCommand
+{
+private:
+ static NUDStatsCommand *mNUDStatsCommandInstance;
+
+ pkt_stats_result_handler mHandler;
+ nud_stats mStats;
+ cmdData *mpktInfo;
+ int mnumStats;
+ NUDStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+
+public:
+ static NUDStatsCommand* instance(wifi_handle handle);
+
+ virtual ~NUDStatsCommand();
+
+ // This function implements creation of NUDStats specific Request
+ // based on the request type
+ virtual wifi_error create();
+
+ virtual void setSubCmd(u32 subcmd);
+
+ virtual wifi_error requestResponse();
+
+ virtual wifi_error notifyResponse();
+
+ virtual int handleResponse(WifiEvent &reply);
+
+ virtual void setHandler(pkt_stats_result_handler handler);
+
+ void copyStats(nud_stats *stats, cmdData *pktdstats);
+
+ void GetPktInfo(struct nlattr **tbvendor);
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/wcn6740/qcwcn/wifi_hal/wifilogger.cpp b/wcn6740/qcwcn/wifi_hal/wifilogger.cpp
new file mode 100644
index 0000000..384633a
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifilogger.cpp
@@ -0,0 +1,1529 @@
+/* Copyright (c) 2015, 2018 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.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include "sync.h"
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include <errno.h>
+#include <utils/Log.h>
+#include "wifiloggercmd.h"
+#include "rb_wrapper.h"
+#include <stdlib.h>
+
+#define LOGGER_MEMDUMP_FILENAME "/proc/debug/fwdump"
+#define DRIVER_MEMDUMP_FILENAME "/proc/debugdriver/driverdump"
+#define LOGGER_MEMDUMP_CHUNKSIZE (4 * 1024)
+#define DRIVER_MEMDUMP_MAX_FILESIZE (16 * 1024)
+
+char power_events_ring_name[] = "power_events_rb";
+char connectivity_events_ring_name[] = "connectivity_events_rb";
+char pkt_stats_ring_name[] = "pkt_stats_rb";
+char driver_prints_ring_name[] = "driver_prints_rb";
+char firmware_prints_ring_name[] = "firmware_prints_rb";
+
+static int get_ring_id(hal_info *info, char *ring_name)
+{
+ int rb_id;
+
+ for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
+ if (is_rb_name_match(&info->rb_infos[rb_id], ring_name)) {
+ return rb_id;
+ }
+ }
+ return -1;
+}
+
+//Implementation of the functions exposed in wifi_logger.h
+
+/* Function to intiate logging */
+wifi_error wifi_start_logging(wifi_interface_handle iface,
+ u32 verbose_level, u32 flags,
+ u32 max_interval_sec, u32 min_data_size,
+ char *buffer_name)
+{
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand = NULL;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ int ring_id = 0;
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set & LOGGER_RING_BUFFER)) {
+ ALOGE("%s: Ring buffer logging feature not supported %x", __FUNCTION__,
+ info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ /*
+ * No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid();
+
+ if (buffer_name == NULL) {
+ ALOGE("%s: Invalid Ring Name. \n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ring_id = get_ring_id(info, buffer_name);
+ if (ring_id < 0) {
+ ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START);
+
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = wifiLoggerCommand->put_u32(QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID,
+ ring_id);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = wifiLoggerCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL,
+ verbose_level);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ ret = wifiLoggerCommand->put_u32(QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS,
+ flags);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ wifiLoggerCommand->attr_end(nlData);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+ ALOGV("%s: Logging Started for %s. with verboselevel %d",
+ __FUNCTION__, buffer_name,verbose_level);
+ rb_start_logging(&info->rb_infos[ring_id], verbose_level,
+ flags, max_interval_sec, min_data_size);
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+/* Function to get each ring related info */
+wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
+ u32 *num_buffers,
+ wifi_ring_buffer_status *status)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ wifi_ring_buffer_status *rbs;
+ struct rb_info *rb_info;
+ int rb_id;
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set & LOGGER_RING_BUFFER)) {
+ ALOGE("%s: Ring buffer logging feature not supported %x", __FUNCTION__,
+ info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if ((*num_buffers) < NUM_RING_BUFS) {
+ ALOGE("%s: Input num_buffers:%u cannot be accommodated, "
+ "Total ring buffer num:%d", __FUNCTION__, *num_buffers,
+ NUM_RING_BUFS);
+ *num_buffers = 0;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
+ rb_info = &info->rb_infos[rb_id];
+ rbs = status + rb_id;
+
+ get_rb_status(rb_info, rbs);
+ }
+ *num_buffers = NUM_RING_BUFS;
+ return WIFI_SUCCESS;
+}
+
+void push_out_all_ring_buffers(hal_info *info)
+{
+ int rb_id;
+
+ for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
+ push_out_rb_data(&info->rb_infos[rb_id]);
+ }
+}
+
+void send_alert(hal_info *info, int reason_code)
+{
+ wifi_alert_handler handler;
+ char alert_msg[20] = "Fatal Event";
+ pthread_mutex_lock(&info->ah_lock);
+ handler.on_alert = info->on_alert;
+ pthread_mutex_unlock(&info->ah_lock);
+
+ if (handler.on_alert) {
+ handler.on_alert(0, alert_msg, strlen(alert_msg), reason_code);
+ }
+}
+
+void WifiLoggerCommand::setFeatureSet(u32 *support) {
+ mSupportedSet = support;
+}
+
+/* Function to get the supported feature set for logging.*/
+wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
+ u32 *support)
+{
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid();
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET);
+
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = wifiLoggerCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
+ requestId);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ wifiLoggerCommand->attr_end(nlData);
+
+ wifiLoggerCommand->setFeatureSet(support);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+/* Function to get the data in each ring for the given ring ID.*/
+wifi_error wifi_get_ring_data(wifi_interface_handle iface,
+ char *ring_name)
+{
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ int ring_id = 0;
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set & LOGGER_RING_BUFFER)) {
+ ALOGE("%s: Ring buffer logging feature not supported %x", __FUNCTION__,
+ info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ring_id = get_ring_id(info, ring_name);
+ if (ring_id < 0) {
+ ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ requestId = get_requestid();
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA);
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ if (wifiLoggerCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
+ {
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+ wifiLoggerCommand->attr_end(nlData);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+void WifiLoggerCommand::setVersionInfo(char *buffer, int buffer_size) {
+ mVersion = buffer;
+ mVersionLen = buffer_size;
+}
+
+/* Function to send enable request to the wifi driver.*/
+wifi_error wifi_get_firmware_version(wifi_interface_handle iface,
+ char *buffer, int buffer_size)
+{
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid_u8();
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData)
+ goto cleanup;
+
+ ret = wifiLoggerCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION, requestId);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ wifiLoggerCommand->attr_end(nlData);
+
+ wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+
+}
+
+/* Function to get wlan driver version.*/
+wifi_error wifi_get_driver_version(wifi_interface_handle iface,
+ char *buffer, int buffer_size)
+{
+
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid_u8();
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ ret = wifiLoggerCommand->put_u8(
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION, requestId);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ wifiLoggerCommand->attr_end(nlData);
+
+ wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+
+/* Function to get the Firmware memory dump. */
+wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface,
+ wifi_firmware_memory_dump_handler handler)
+{
+ wifi_error ret;
+ int requestId;
+ WifiLoggerCommand *wifiLoggerCommand;
+ struct nlattr *nlData;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set &
+ WIFI_LOGGER_MEMORY_DUMP_SUPPORTED)) {
+ ALOGE("%s: Firmware memory dump logging feature not supported %x",
+ __FUNCTION__, info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate one randomly.
+ */
+ requestId = get_requestid();
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP);
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData){
+ ret = WIFI_ERROR_UNKNOWN;
+ goto cleanup;
+ }
+
+ wifiLoggerCommand->attr_end(nlData);
+
+ /* copy the callback into callback handler */
+ WifiLoggerCallbackHandler callbackHandler;
+ memset(&callbackHandler, 0, sizeof(callbackHandler));
+ callbackHandler.on_firmware_memory_dump = \
+ handler.on_firmware_memory_dump;
+
+ ret = wifiLoggerCommand->setCallbackHandler(callbackHandler);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Send the msg and wait for the memory dump response */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+wifi_error wifi_set_log_handler(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler handler)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ pthread_mutex_lock(&info->lh_lock);
+ info->on_ring_buffer_data = handler.on_ring_buffer_data;
+ pthread_mutex_unlock(&info->lh_lock);
+ if (handler.on_ring_buffer_data == NULL) {
+ ALOGE("Set log handler is NULL");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_reset_log_handler(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ pthread_mutex_lock(&info->lh_lock);
+ info->on_ring_buffer_data = NULL;
+ pthread_mutex_unlock(&info->lh_lock);
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_set_alert_handler(wifi_request_id id,
+ wifi_interface_handle iface,
+ wifi_alert_handler handler)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ if (handler.on_alert == NULL) {
+ ALOGE("Set alert handler is NULL");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ pthread_mutex_lock(&info->ah_lock);
+ info->on_alert = handler.on_alert;
+ pthread_mutex_unlock(&info->ah_lock);
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_reset_alert_handler(wifi_request_id id,
+ wifi_interface_handle iface)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ pthread_mutex_lock(&info->ah_lock);
+ info->on_alert = NULL;
+ pthread_mutex_unlock(&info->ah_lock);
+ return WIFI_SUCCESS;
+}
+
+
+/**
+ API to start packet fate monitoring.
+ - Once stared, monitoring should remain active until HAL is unloaded.
+ - When HAL is unloaded, all packet fate buffers should be cleared.
+*/
+wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle iface)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set &
+ WIFI_LOGGER_PACKET_FATE_SUPPORTED)) {
+ ALOGE("%s: packet fate logging feature not supported %x",
+ __FUNCTION__, info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (info->fate_monitoring_enabled == true) {
+ ALOGV("Packet monitoring is already enabled");
+ return WIFI_SUCCESS;
+ }
+
+ info->pkt_fate_stats = (packet_fate_monitor_info *) malloc (
+ sizeof(packet_fate_monitor_info));
+ if (info->pkt_fate_stats == NULL) {
+ ALOGE("Failed to allocate memory for : %zu bytes",
+ sizeof(packet_fate_monitor_info));
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(info->pkt_fate_stats, 0, sizeof(packet_fate_monitor_info));
+
+ pthread_mutex_lock(&info->pkt_fate_stats_lock);
+ info->fate_monitoring_enabled = true;
+ pthread_mutex_unlock(&info->pkt_fate_stats_lock);
+
+ return WIFI_SUCCESS;
+}
+
+
+/**
+ API to retrieve fates of outbound packets.
+ - HAL implementation should fill |tx_report_bufs| with fates of
+ _first_ min(n_requested_fates, actual packets) frames
+ transmitted for the most recent association. The fate reports
+ should follow the same order as their respective packets.
+ - Packets reported by firmware, but not recognized by driver
+ should be included. However, the ordering of the corresponding
+ reports is at the discretion of HAL implementation.
+ - Framework may call this API multiple times for the same association.
+ - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|.
+ - Framework will allocate and free the referenced storage.
+*/
+wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle iface,
+ wifi_tx_report *tx_report_bufs,
+ size_t n_requested_fates,
+ size_t *n_provided_fates)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ wifi_tx_report_i *tx_fate_stats;
+ size_t i;
+
+ if (info->fate_monitoring_enabled != true) {
+ ALOGE("Packet monitoring is not yet triggered");
+ return WIFI_ERROR_UNINITIALIZED;
+ }
+ pthread_mutex_lock(&info->pkt_fate_stats_lock);
+
+ tx_fate_stats = &info->pkt_fate_stats->tx_fate_stats[0];
+
+ *n_provided_fates = min(n_requested_fates,
+ info->pkt_fate_stats->n_tx_stats_collected);
+
+ for (i=0; i < *n_provided_fates; i++) {
+ memcpy(tx_report_bufs[i].md5_prefix,
+ tx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN);
+ tx_report_bufs[i].fate = tx_fate_stats[i].fate;
+ tx_report_bufs[i].frame_inf.payload_type =
+ tx_fate_stats[i].frame_inf.payload_type;
+ tx_report_bufs[i].frame_inf.driver_timestamp_usec =
+ tx_fate_stats[i].frame_inf.driver_timestamp_usec;
+ tx_report_bufs[i].frame_inf.firmware_timestamp_usec =
+ tx_fate_stats[i].frame_inf.firmware_timestamp_usec;
+ tx_report_bufs[i].frame_inf.frame_len =
+ tx_fate_stats[i].frame_inf.frame_len;
+
+ if (tx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II)
+ memcpy(tx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes,
+ tx_fate_stats[i].frame_inf.frame_content,
+ min(tx_fate_stats[i].frame_inf.frame_len,
+ MAX_FRAME_LEN_ETHERNET));
+ else if (tx_report_bufs[i].frame_inf.payload_type ==
+ FRAME_TYPE_80211_MGMT)
+ memcpy(
+ tx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes,
+ tx_fate_stats[i].frame_inf.frame_content,
+ min(tx_fate_stats[i].frame_inf.frame_len,
+ MAX_FRAME_LEN_80211_MGMT));
+ else
+ /* Currently framework is interested only two types(
+ * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so
+ * ignore the all other types of packets received from driver */
+ ALOGI("Unknown format packet");
+ }
+ pthread_mutex_unlock(&info->pkt_fate_stats_lock);
+
+ return WIFI_SUCCESS;
+}
+
+/**
+ API to retrieve fates of inbound packets.
+ - HAL implementation should fill |rx_report_bufs| with fates of
+ _first_ min(n_requested_fates, actual packets) frames
+ received for the most recent association. The fate reports
+ should follow the same order as their respective packets.
+ - Packets reported by firmware, but not recognized by driver
+ should be included. However, the ordering of the corresponding
+ reports is at the discretion of HAL implementation.
+ - Framework may call this API multiple times for the same association.
+ - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|.
+ - Framework will allocate and free the referenced storage.
+*/
+wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle iface,
+ wifi_rx_report *rx_report_bufs,
+ size_t n_requested_fates,
+ size_t *n_provided_fates)
+{
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+ wifi_rx_report_i *rx_fate_stats;
+ size_t i;
+
+ if (info->fate_monitoring_enabled != true) {
+ ALOGE("Packet monitoring is not yet triggered");
+ return WIFI_ERROR_UNINITIALIZED;
+ }
+ pthread_mutex_lock(&info->pkt_fate_stats_lock);
+
+ rx_fate_stats = &info->pkt_fate_stats->rx_fate_stats[0];
+
+ *n_provided_fates = min(n_requested_fates,
+ info->pkt_fate_stats->n_rx_stats_collected);
+
+ for (i=0; i < *n_provided_fates; i++) {
+ memcpy(rx_report_bufs[i].md5_prefix,
+ rx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN);
+ rx_report_bufs[i].fate = rx_fate_stats[i].fate;
+ rx_report_bufs[i].frame_inf.payload_type =
+ rx_fate_stats[i].frame_inf.payload_type;
+ rx_report_bufs[i].frame_inf.driver_timestamp_usec =
+ rx_fate_stats[i].frame_inf.driver_timestamp_usec;
+ rx_report_bufs[i].frame_inf.firmware_timestamp_usec =
+ rx_fate_stats[i].frame_inf.firmware_timestamp_usec;
+ rx_report_bufs[i].frame_inf.frame_len =
+ rx_fate_stats[i].frame_inf.frame_len;
+
+ if (rx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II)
+ memcpy(rx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes,
+ rx_fate_stats[i].frame_inf.frame_content,
+ min(rx_fate_stats[i].frame_inf.frame_len,
+ MAX_FRAME_LEN_ETHERNET));
+ else if (rx_report_bufs[i].frame_inf.payload_type ==
+ FRAME_TYPE_80211_MGMT)
+ memcpy(
+ rx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes,
+ rx_fate_stats[i].frame_inf.frame_content,
+ min(rx_fate_stats[i].frame_inf.frame_len,
+ MAX_FRAME_LEN_80211_MGMT));
+ else
+ /* Currently framework is interested only two types(
+ * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so
+ * ignore the all other types of packets received from driver */
+ ALOGI("Unknown format packet");
+ }
+ pthread_mutex_unlock(&info->pkt_fate_stats_lock);
+
+ return WIFI_SUCCESS;
+}
+
+WifiLoggerCommand::WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
+ : WifiVendorCommand(handle, id, vendor_id, subcmd)
+{
+ mVersion = NULL;
+ mVersionLen = 0;
+ mRequestId = id;
+ memset(&mHandler, 0,sizeof(mHandler));
+ mWaitforRsp = false;
+ mMoreData = false;
+ mSupportedSet = NULL;
+}
+
+WifiLoggerCommand::~WifiLoggerCommand()
+{
+ unregisterVendorHandler(mVendor_id, mSubcmd);
+}
+
+/* This function implements creation of Vendor command */
+wifi_error WifiLoggerCommand::create() {
+ wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
+ if (ret != WIFI_SUCCESS)
+ return ret;
+
+ /* Insert the oui in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+ /* Insert the subcmd in the msg */
+ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
+ if (ret != WIFI_SUCCESS)
+ goto out;
+
+ ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
+ __FUNCTION__, mVendor_id, mSubcmd);
+
+out:
+ return ret;
+}
+
+void rb_timerhandler(hal_info *info)
+{
+ struct timeval now;
+ int rb_id;
+
+ gettimeofday(&now,NULL);
+ for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
+ rb_check_for_timeout(&info->rb_infos[rb_id], &now);
+ }
+}
+
+wifi_error wifi_logger_ring_buffers_init(hal_info *info)
+{
+ wifi_error ret;
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set & LOGGER_RING_BUFFER)) {
+ ALOGE("%s: Ring buffer logging feature not supported %x", __FUNCTION__,
+ info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = rb_init(info, &info->rb_infos[POWER_EVENTS_RB_ID],
+ POWER_EVENTS_RB_ID,
+ POWER_EVENTS_RB_BUF_SIZE,
+ POWER_EVENTS_NUM_BUFS,
+ power_events_ring_name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to initialize power events ring buffer");
+ goto cleanup;
+ }
+
+ ret = rb_init(info, &info->rb_infos[CONNECTIVITY_EVENTS_RB_ID],
+ CONNECTIVITY_EVENTS_RB_ID,
+ CONNECTIVITY_EVENTS_RB_BUF_SIZE,
+ CONNECTIVITY_EVENTS_NUM_BUFS,
+ connectivity_events_ring_name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to initialize connectivity events ring buffer");
+ goto cleanup;
+ }
+
+ ret = rb_init(info, &info->rb_infos[PKT_STATS_RB_ID],
+ PKT_STATS_RB_ID,
+ PKT_STATS_RB_BUF_SIZE,
+ PKT_STATS_NUM_BUFS,
+ pkt_stats_ring_name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to initialize per packet stats ring buffer");
+ goto cleanup;
+ }
+
+ ret = rb_init(info, &info->rb_infos[DRIVER_PRINTS_RB_ID],
+ DRIVER_PRINTS_RB_ID,
+ DRIVER_PRINTS_RB_BUF_SIZE,
+ DRIVER_PRINTS_NUM_BUFS,
+ driver_prints_ring_name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to initialize driver prints ring buffer");
+ goto cleanup;
+ }
+
+ ret = rb_init(info, &info->rb_infos[FIRMWARE_PRINTS_RB_ID],
+ FIRMWARE_PRINTS_RB_ID,
+ FIRMWARE_PRINTS_RB_BUF_SIZE,
+ FIRMWARE_PRINTS_NUM_BUFS,
+ firmware_prints_ring_name);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to initialize firmware prints ring buffer");
+ goto cleanup;
+ }
+
+ pthread_mutex_init(&info->lh_lock, NULL);
+ pthread_mutex_init(&info->ah_lock, NULL);
+
+ return ret;
+
+cleanup:
+ wifi_logger_ring_buffers_deinit(info);
+ return ret;
+}
+
+void wifi_logger_ring_buffers_deinit(hal_info *info)
+{
+ int i;
+
+ if (!(info->supported_logger_feature_set & LOGGER_RING_BUFFER))
+ return;
+
+ for (i = 0; i < NUM_RING_BUFS; i++) {
+ rb_deinit(&info->rb_infos[i]);
+ }
+ pthread_mutex_destroy(&info->lh_lock);
+ pthread_mutex_destroy(&info->ah_lock);
+}
+
+
+/* Callback handlers registered for nl message send */
+static int error_handler_wifi_logger(struct sockaddr_nl *nla,
+ struct nlmsgerr *err,
+ void *arg)
+{
+ struct sockaddr_nl *tmp;
+ int *ret = (int *)arg;
+ tmp = nla;
+ *ret = err->error;
+ ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
+ return NL_STOP;
+}
+
+/* Callback handlers registered for nl message send */
+static int ack_handler_wifi_logger(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ struct nl_msg * a;
+
+ a = msg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+/* Callback handlers registered for nl message send */
+static int finish_handler_wifi_logger(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ struct nl_msg * a;
+
+ a = msg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+wifi_error WifiLoggerCommand::requestEvent()
+{
+ int status;
+ wifi_error res = WIFI_SUCCESS;
+ struct nl_cb *cb = NULL;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ ALOGE("%s: Callback allocation failed",__FUNCTION__);
+ res = WIFI_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /* Send message */
+ status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
+ if (status < 0) {
+ res = mapKernelErrortoWifiHalError(status);
+ goto out;
+ }
+
+ status = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_logger, &status);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_logger, &status);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_logger, &status);
+
+ /* Err is populated as part of finish_handler. */
+ while (status > 0){
+ nl_recvmsgs(mInfo->cmd_sock, cb);
+ }
+
+ ALOGV("%s: Msg sent, status=%d, mWaitForRsp=%d", __FUNCTION__, status, mWaitforRsp);
+ /* Only wait for the asynchronous event if HDD returns success, res=0 */
+ if (!status && (mWaitforRsp == true)) {
+ struct timespec abstime;
+ abstime.tv_sec = 4;
+ abstime.tv_nsec = 0;
+ res = mCondition.wait(abstime);
+ if (res == WIFI_ERROR_TIMED_OUT)
+ ALOGE("%s: Time out happened.", __FUNCTION__);
+
+ ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d",
+ __FUNCTION__, res, mWaitforRsp);
+ }
+out:
+ nl_cb_put(cb);
+ /* Cleanup the mMsg */
+ mMsg.destroy();
+ return res;
+}
+
+wifi_error WifiLoggerCommand::requestResponse()
+{
+ return WifiCommand::requestResponse(mMsg);
+}
+
+int WifiLoggerCommand::handleResponse(WifiEvent &reply) {
+ int len = 0, version;
+ char version_type[20];
+ char* memBuffer = NULL;
+ FILE* memDumpFilePtr = NULL;
+ WifiVendorCommand::handleResponse(reply);
+
+ memset(version_type, 0, 20);
+ switch(mSubcmd)
+ {
+ case QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO:
+ {
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
+ len = nla_len(tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]);
+ memcpy(version_type, "Driver", strlen("Driver"));
+ version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
+ } else if (
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
+ len = nla_len(
+ tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]);
+ memcpy(version_type, "Firmware", strlen("Firmware"));
+ version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
+ }
+ if (len && mVersion && mVersionLen) {
+ memset(mVersion, 0, mVersionLen);
+ /* if len is greater than the incoming length then
+ accommodate 1 lesser than mVersionLen to have the
+ string terminated with '\0' */
+ len = (len > mVersionLen)? (mVersionLen - 1) : len;
+ memcpy(mVersion, nla_data(tb_vendor[version]), len);
+ ALOGV("%s: WLAN %s version : %s ", __FUNCTION__,
+ version_type, mVersion);
+ }
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET:
+ {
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LOGGER_MAX + 1];
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LOGGER_MAX,
+ (struct nlattr *)mVendorData, mDataLen, NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED]) {
+ *mSupportedSet =
+ nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED]);
+#ifdef QC_HAL_DEBUG
+ ALOGV("%s: Supported Feature Set : val 0x%x",
+ __FUNCTION__, *mSupportedSet);
+#endif
+ }
+ }
+ break;
+
+ case QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP:
+ {
+ u32 memDumpSize = 0;
+ int numRecordsRead = 0;
+ u32 remaining = 0;
+ char* buffer = NULL;
+ struct nlattr *tbVendor[
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX + 1];
+
+ nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]) {
+ ALOGE("%s: LOGGER_RESULTS_MEMDUMP_SIZE not"
+ "found", __FUNCTION__);
+ break;
+ }
+
+ memDumpSize = nla_get_u32(
+ tbVendor[QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]
+ );
+
+ /* Allocate the memory indicated in memDumpSize */
+ memBuffer = (char*) malloc(sizeof(char) * memDumpSize);
+ if (memBuffer == NULL) {
+ ALOGE("%s: No Memory for allocating Buffer size of %d",
+ __func__, memDumpSize);
+ break;
+ }
+ memset(memBuffer, 0, sizeof(char) * memDumpSize);
+
+ ALOGI("%s: Memory Dump size: %u", __func__,
+ memDumpSize);
+
+ /* Open the proc or debugfs filesystem */
+ memDumpFilePtr = fopen(LOGGER_MEMDUMP_FILENAME, "r");
+ if (memDumpFilePtr == NULL) {
+ ALOGE("Failed to open %s file", LOGGER_MEMDUMP_FILENAME);
+ break;
+ }
+
+ /* Read the memDumpSize value at once */
+ numRecordsRead = fread(memBuffer, 1, memDumpSize,
+ memDumpFilePtr);
+ if (numRecordsRead <= 0 ||
+ numRecordsRead != (int) memDumpSize) {
+ ALOGE("%s: Read %d failed for reading at once.",
+ __func__, numRecordsRead);
+ /* Lets try to read in chunks */
+ rewind(memDumpFilePtr);
+ remaining = memDumpSize;
+ buffer = memBuffer;
+ while (remaining) {
+ u32 readSize = 0;
+ if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) {
+ readSize = LOGGER_MEMDUMP_CHUNKSIZE;
+ }
+ else {
+ readSize = remaining;
+ }
+ numRecordsRead = fread(buffer, 1,
+ readSize, memDumpFilePtr);
+ if (numRecordsRead) {
+ remaining -= readSize;
+ buffer += readSize;
+ ALOGV("%s: Read successful for size:%u "
+ "remaining:%u", __func__, readSize,
+ remaining);
+ }
+ else {
+ ALOGE("%s: Chunk read failed for size:%u",
+ __func__, readSize);
+ break;
+ }
+ }
+ }
+
+ /* After successful read, call the callback handler*/
+ if (mHandler.on_firmware_memory_dump) {
+ mHandler.on_firmware_memory_dump(memBuffer,
+ memDumpSize);
+
+ }
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS:
+ {
+ struct nlattr *tbVendor[QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX+1];
+
+ /* parse and extract wake reason stats */
+ nla_parse(tbVendor, QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ mGetWakeStats->cmd_event_wake_cnt_used = 0;
+
+ mGetWakeStats->driver_fw_local_wake_cnt_used = 0;
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]) {
+ ALOGE("%s: TOTAL_RX_DATA_WAKE not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->total_rx_data_wake = nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]) {
+ ALOGE("%s: RX_UNICAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_details.rx_unicast_cnt = nla_get_u32(
+ tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]) {
+ ALOGE("%s: RX_MULTICAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_details.rx_multicast_cnt = nla_get_u32(
+ tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]) {
+ ALOGE("%s: RX_BROADCAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_details.rx_broadcast_cnt = nla_get_u32(
+ tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]) {
+ ALOGE("%s: ICMP_PKT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_pkt_classification_info.icmp_pkt =
+ nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]) {
+ ALOGE("%s: ICMP6_PKT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_pkt_classification_info.icmp6_pkt =
+ nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]) {
+ ALOGE("%s: ICMP6_RA not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ra =
+ nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]) {
+ ALOGE("%s: ICMP6_NA not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_pkt_classification_info.icmp6_na =
+ nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]);
+
+ if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]) {
+ ALOGE("%s: ICMP6_NS not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ns =
+ nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]);
+
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]) {
+ ALOGE("%s: ICMP4_RX_MULTICAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
+ nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]);
+
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]) {
+ ALOGE("%s: ICMP6_RX_MULTICAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
+ nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]);
+
+ if (!tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]) {
+ ALOGE("%s: OTHER_RX_MULTICAST_CNT not found", __FUNCTION__);
+ break;
+ }
+ mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
+ nla_get_u32(tbVendor[
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]);
+
+ }
+ break;
+
+ default :
+ ALOGE("%s: Wrong Wifi Logger subcmd response received %d",
+ __FUNCTION__, mSubcmd);
+ }
+
+ /* free the allocated memory */
+ if (memBuffer) {
+ free(memBuffer);
+ }
+ if (memDumpFilePtr) {
+ fclose(memDumpFilePtr);
+ }
+ return NL_SKIP;
+}
+
+/* This function will be the main handler for incoming (from driver)
+ * WIFI_LOGGER_SUBCMD.
+ * Calls the appropriate callback handler after parsing the vendor data.
+ */
+int WifiLoggerCommand::handleEvent(WifiEvent &event)
+{
+ WifiVendorCommand::handleEvent(event);
+
+ switch(mSubcmd)
+ {
+ default:
+ /* Error case should not happen print log */
+ ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd);
+ break;
+ }
+
+ return NL_SKIP;
+}
+
+wifi_error WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler)
+{
+ wifi_error res;
+ mHandler = nHandler;
+ res = registerVendorHandler(mVendor_id, mSubcmd);
+ if (res != WIFI_SUCCESS) {
+ ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
+ __FUNCTION__, mVendor_id, mSubcmd);
+ }
+ return res;
+}
+
+void WifiLoggerCommand::unregisterHandler(u32 subCmd)
+{
+ unregisterVendorHandler(mVendor_id, subCmd);
+}
+
+wifi_error WifiLoggerCommand::timed_wait(u16 wait_time)
+{
+ struct timespec absTime;
+ absTime.tv_sec = wait_time;
+ absTime.tv_nsec = 0;
+ return mCondition.wait(absTime);
+}
+
+void WifiLoggerCommand::waitForRsp(bool wait)
+{
+ mWaitforRsp = wait;
+}
+
+/* Function to get Driver memory dump */
+wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
+ wifi_driver_memory_dump_callbacks callback)
+{
+ FILE *fp;
+ size_t fileSize, remaining, readSize;
+ size_t numRecordsRead;
+ char *memBuffer = NULL, *buffer = NULL;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set &
+ WIFI_LOGGER_DRIVER_DUMP_SUPPORTED)) {
+ ALOGE("%s: Driver memory dump logging feature not supported %x",
+ __FUNCTION__, info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ /* Open File */
+ fp = fopen(DRIVER_MEMDUMP_FILENAME, "r");
+ if (fp == NULL) {
+ ALOGE("Failed to open %s file", DRIVER_MEMDUMP_FILENAME);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ memBuffer = (char *) malloc(DRIVER_MEMDUMP_MAX_FILESIZE);
+ if (memBuffer == NULL) {
+ ALOGE("%s: malloc failed for size %d", __FUNCTION__,
+ DRIVER_MEMDUMP_MAX_FILESIZE);
+ fclose(fp);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Read the DRIVER_MEMDUMP_MAX_FILESIZE value at once */
+ numRecordsRead = fread(memBuffer, 1, DRIVER_MEMDUMP_MAX_FILESIZE, fp);
+ if (feof(fp))
+ fileSize = numRecordsRead;
+ else if (numRecordsRead == DRIVER_MEMDUMP_MAX_FILESIZE) {
+ ALOGE("%s: Reading only first %zu bytes from file", __FUNCTION__,
+ numRecordsRead);
+ fileSize = numRecordsRead;
+ } else {
+ ALOGE("%s: Read failed for reading at once, ret: %zu. Trying to read in"
+ "chunks", __FUNCTION__, numRecordsRead);
+ /* Lets try to read in chunks */
+ rewind(fp);
+ remaining = DRIVER_MEMDUMP_MAX_FILESIZE;
+ buffer = memBuffer;
+ fileSize = 0;
+ while (remaining) {
+ readSize = 0;
+ if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE)
+ readSize = LOGGER_MEMDUMP_CHUNKSIZE;
+ else
+ readSize = remaining;
+
+ numRecordsRead = fread(buffer, 1, readSize, fp);
+ fileSize += numRecordsRead;
+ if (feof(fp))
+ break;
+ else if (numRecordsRead == readSize) {
+ remaining -= readSize;
+ buffer += readSize;
+ ALOGV("%s: Read successful for size:%zu remaining:%zu",
+ __FUNCTION__, readSize, remaining);
+ } else {
+ ALOGE("%s: Chunk read failed for size:%zu", __FUNCTION__,
+ readSize);
+ free(memBuffer);
+ memBuffer = NULL;
+ fclose(fp);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ }
+ }
+ ALOGV("%s filename: %s fileSize: %zu", __FUNCTION__, DRIVER_MEMDUMP_FILENAME,
+ fileSize);
+ /* After successful read, call the callback function*/
+ callback.on_driver_memory_dump(memBuffer, fileSize);
+
+ /* free the allocated memory */
+ free(memBuffer);
+ fclose(fp);
+ return WIFI_SUCCESS;
+}
+
+/* Function to get wake lock stats */
+wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
+{
+ int requestId;
+ wifi_error ret;
+ WifiLoggerCommand *wifiLoggerCommand;
+ interface_info *ifaceInfo = getIfaceInfo(iface);
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ /* Check Supported logger capability */
+ if (!(info->supported_logger_feature_set &
+ WIFI_LOGGER_WAKE_LOCK_SUPPORTED)) {
+ ALOGE("%s: Wake lock logging feature not supported %x",
+ __FUNCTION__, info->supported_logger_feature_set);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ /* No request id from caller, so generate one and pass it on to the driver.
+ * Generate it randomly.
+ */
+ requestId = get_requestid();
+
+ if (!wifi_wake_reason_cnt) {
+ ALOGE("%s: Invalid buffer provided. Exit.",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ wifiLoggerCommand = new WifiLoggerCommand(
+ wifiHandle,
+ requestId,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS);
+ if (wifiLoggerCommand == NULL) {
+ ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Create the NL message. */
+ ret = wifiLoggerCommand->create();
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ /* Set the interface Id of the message. */
+ ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
+ if (ret != WIFI_SUCCESS)
+ goto cleanup;
+
+ wifiLoggerCommand->getWakeStatsRspParams(wifi_wake_reason_cnt);
+
+ /* Send the msg and wait for a response. */
+ ret = wifiLoggerCommand->requestResponse();
+ if (ret != WIFI_SUCCESS)
+ ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
+
+cleanup:
+ delete wifiLoggerCommand;
+ return ret;
+}
+
+void WifiLoggerCommand::getWakeStatsRspParams(
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
+{
+ mGetWakeStats = wifi_wake_reason_cnt;
+}
diff --git a/qcwcn/wifi_hal/wifilogger_diag.cpp b/wcn6740/qcwcn/wifi_hal/wifilogger_diag.cpp
similarity index 93%
copy from qcwcn/wifi_hal/wifilogger_diag.cpp
copy to wcn6740/qcwcn/wifi_hal/wifilogger_diag.cpp
index bdc9c7f..f026a78 100644
--- a/qcwcn/wifi_hal/wifilogger_diag.cpp
+++ b/wcn6740/qcwcn/wifi_hal/wifilogger_diag.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 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
@@ -24,6 +24,40 @@
* 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.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
/* Suppress -Waddress-of-packed-member for new toolchain update.
@@ -47,6 +81,7 @@
#include <errno.h>
#include "wifi_hal_ctrl.h"
+#define MAX_EVENT_REASON_CODE 1024
static uint32_t get_le32(const uint8_t *pos)
{
return pos[0] | (pos[1] << 8) | (pos[2] << 16) | (pos[3] << 24);
@@ -110,7 +145,7 @@
RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
rbe->type = ENTRY_TYPE_CONNECT_EVENT;
gettimeofday(&time,NULL);
- rbe->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ rbe->timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
/* Write if verbose level and handler are set */
if (info->rb_infos[CONNECTIVITY_EVENTS_RB_ID].verbose_level >= 1 &&
@@ -131,6 +166,8 @@
wlan_ext_scan_capabilities_payload_type *pScanCapabilities;
wifi_gscan_capabilities gscan_cap;
gscan_capabilities_vendor_data_t cap_vendor_data;
+ memset(&cap_vendor_data, 0, sizeof(cap_vendor_data));
+
tlv_log *pTlv;
int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
u8 out_buf[SCAN_CAP_ENTRY_SIZE];
@@ -138,7 +175,6 @@
pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
memset(pRingBufferEntry, 0, SCAN_CAP_ENTRY_SIZE);
- memset(&cap_vendor_data, 0, sizeof(gscan_capabilities_vendor_data_t));
pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
(pRingBufferEntry + 1);
@@ -702,10 +738,10 @@
{
wlan_roam_candidate_found_payload_type *pRoamCandidateFound;
roam_candidate_found_vendor_data_t roamCandidateFoundVendata;
+ memset(&roamCandidateFoundVendata, 0,
+ sizeof(roamCandidateFoundVendata));
pConnectEvent->event = WIFI_EVENT_ROAM_CANDIDATE_FOUND;
pRoamCandidateFound = (wlan_roam_candidate_found_payload_type *)buf;
- memset(&roamCandidateFoundVendata, 0,
- sizeof(roam_candidate_found_vendor_data_t));
pTlv = &pConnectEvent->tlvs[0];
pTlv = addLoggerTlv(WIFI_TAG_CHANNEL,
sizeof(pRoamCandidateFound->channel),
@@ -782,13 +818,17 @@
rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
rb_entry_hdr.type = ENTRY_TYPE_DATA;
gettimeofday(&time, NULL);
- rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ rb_entry_hdr.timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
/* Write if verbose and handler is set */
if (info->rb_infos[FIRMWARE_PRINTS_RB_ID].verbose_level >= 1 &&
info->on_ring_buffer_data) {
/* Write header and payload separately to avoid
* complete payload memcpy */
+ if (sizeof(wifi_ring_buffer_entry) + length > 2000) {
+ ALOGE("Invalid length of buffer wifi_ring_buffer_entry size: %zu length %u ",sizeof(wifi_ring_buffer_entry), length);
+ return WIFI_ERROR_UNKNOWN;
+ }
status = ring_buffer_write(&info->rb_infos[FIRMWARE_PRINTS_RB_ID],
(u8*)&rb_entry_hdr,
sizeof(wifi_ring_buffer_entry),
@@ -848,10 +888,10 @@
return status;
}
-static wifi_error process_fw_diag_msg(hal_info *info, u8* buf, u16 length)
+static wifi_error process_fw_diag_msg(hal_info *info, u8* buf, u32 length)
{
- u16 count = 0, id;
- u16 payloadlen = 0;
+ u32 count = 0, id;
+ u32 payloadlen = 0;
u16 hdr_size = 0;
wifi_error status;
fw_diag_msg_fixed_hdr_t *diag_msg_fixed_hdr;
@@ -862,8 +902,23 @@
buf += 4;
length -= 4;
- while (length > (count + sizeof(fw_diag_msg_fixed_hdr_t))) {
+ while ((info && !info->clean_up)
+ && (length > (count + sizeof(fw_diag_msg_fixed_hdr_t)))) {
diag_msg_fixed_hdr = (fw_diag_msg_fixed_hdr_t *)(buf + count);
+
+ if (diag_msg_fixed_hdr->diag_event_type > WLAN_DIAG_TYPE_LEGACY_MSG) {
+ hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
+ } else {
+ hdr_size = sizeof(fw_diag_msg_hdr_t);
+ }
+
+ if ((count + hdr_size) > length)
+ {
+ ALOGE("process_fw_diag_msg (%d) - possible buffer over access, length=%d count=%d hdr_size=%d",
+ diag_msg_fixed_hdr->diag_event_type, length, count, hdr_size);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (diag_msg_fixed_hdr->diag_event_type) {
case WLAN_DIAG_TYPE_EVENT:
case WLAN_DIAG_TYPE_EVENT_V2:
@@ -883,6 +938,12 @@
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
}
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_EVENT - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (id) {
case EVENT_WLAN_BT_COEX_BT_SCO_START:
case EVENT_WLAN_BT_COEX_BT_SCO_STOP:
@@ -980,6 +1041,12 @@
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
}
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_LOG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
switch (id) {
case LOG_WLAN_EXTSCAN_CAPABILITIES:
status = process_log_extscan_capabilities(info,
@@ -1002,6 +1069,11 @@
payloadlen = diag_msg_hdr->u.msg_hdr.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_t);
payload = diag_msg_hdr->payload;
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_MSG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
payloadlen + hdr_size);
break;
@@ -1012,6 +1084,11 @@
payloadlen = diag_msg_hdr_v2->u.msg_hdr.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
payload = diag_msg_hdr_v2->payload;
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_MSG_V2 - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
payloadlen + hdr_size);
break;
@@ -1023,6 +1100,11 @@
payload = diag_msg_hdr->payload;
payloadlen = diag_msg_hdr->u.payload_len;
hdr_size = sizeof(fw_diag_msg_hdr_t);
+ if ((count + hdr_size + payloadlen) > length) {
+ ALOGE("WLAN_DIAG_TYPE_CONFIG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+ length, count, hdr_size, payloadlen);
+ return WIFI_ERROR_UNKNOWN;
+ }
process_firmware_prints(info, (u8 *)diag_msg_hdr,
payloadlen + hdr_size);
}
@@ -1201,7 +1283,7 @@
RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
pRingBufferEntry->type = ENTRY_TYPE_POWER_EVENT;
gettimeofday(&time, NULL);
- pRingBufferEntry->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ pRingBufferEntry->timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
/* Write if verbose and handler is set */
if (info->rb_infos[POWER_EVENTS_RB_ID].verbose_level >= 1 &&
@@ -1245,11 +1327,17 @@
int length)
{
wlan_data_stall_event_t *event;
+ int reason_code = 0;
ALOGV("Received Data Stall Event from Driver");
event = (wlan_data_stall_event_t *)buf;
ALOGE("Received Data Stall event, sending alert %d", event->reason);
- send_alert(info, DATA_STALL_OFFSET_REASON_CODE + event->reason);
+ if(event->reason >= MAX_EVENT_REASON_CODE)
+ reason_code = 0;
+ else
+ reason_code = event->reason;
+
+ send_alert(info, DATA_STALL_OFFSET_REASON_CODE + reason_code);
}
static void process_wlan_low_resource_failure(hal_info *info,
@@ -1294,7 +1382,6 @@
}
}
-
static wifi_error update_stats_to_ring_buf(hal_info *info,
u8 *rb_entry, u32 size)
{
@@ -1308,10 +1395,10 @@
RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
pRingBufferEntry->type = ENTRY_TYPE_PKT;
gettimeofday(&time,NULL);
- pRingBufferEntry->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ pRingBufferEntry->timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
// Write if verbose and handler is set
- if ((info->rb_infos[PKT_STATS_RB_ID].verbose_level >= VERBOSE_REPRO_PROBLEM)
+ if ((info->rb_infos[PKT_STATS_RB_ID].verbose_level >= VERBOSE_DEBUG_PROBLEM)
&& info->on_ring_buffer_data) {
ring_buffer_write(&info->rb_infos[PKT_STATS_RB_ID],
(u8*)pRingBufferEntry,
@@ -1510,7 +1597,7 @@
wifi_ring_per_packet_status_entry *pps_entry;
u32 index = 0;
- while (index < info->rx_buf_size_occupied) {
+ while (!info->clean_up && (index < info->rx_buf_size_occupied)) {
pps_entry = (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
pps_entry->MCS = info->aggr_stats.RxMCS.mcs;
@@ -2109,10 +2196,10 @@
rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
rb_entry_hdr.type = ENTRY_TYPE_PKT;
gettimeofday(&time, NULL);
- rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ rb_entry_hdr.timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
/* Write if verbose and handler is set */
- if (info->rb_infos[PKT_STATS_RB_ID].verbose_level >= VERBOSE_REPRO_PROBLEM &&
+ if (info->rb_infos[PKT_STATS_RB_ID].verbose_level >= 3 &&
info->on_ring_buffer_data) {
/* Write header and payload separately to avoid
* complete payload memcpy */
@@ -2290,9 +2377,12 @@
u8 *data;
u8 *node_pkt_data;
wh_pktlog_hdr_v2_t *pkt_stats_node_header;
- int node_pkt_type,pkt_sub_type,node_pkt_len,i;
+ int node_pkt_type,pkt_sub_type,i;
+ int node_pkt_len = 0;
wifi_error status = WIFI_SUCCESS;
node_pkt_stats node_pkt_t;
+ node_pkt_t.bmap_enqueued = 0;
+ node_pkt_t.bmap_failed = 0;
wifi_ring_buffer_entry *pRingBufferEntry =
(wifi_ring_buffer_entry *)info->pkt_stats->tx_stats;
@@ -2347,6 +2437,9 @@
rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_80211_HEADER;
}
break;
+ default:
+ // TODO: Unexpected PKTLOG types
+ break;
}
if (info->pkt_stats->tx_stats_events & BIT(PKTLOG_TYPE_TX_STAT)) {
/* if bmap_enqueued is 1 ,Handle non aggregated cases */
@@ -2384,8 +2477,12 @@
pkt_stats_len = (pkt_stats_len - (sizeof(wh_pktlog_hdr_v2_t) + node_pkt_len));
data = (u8*) (data + sizeof(wh_pktlog_hdr_v2_t) + node_pkt_len);
info->pkt_stats->tx_stats_events = 0;
+ } else {
+ //TODO parsing of unknown packet sub type
+ status = WIFI_ERROR_INVALID_ARGS;
+ break;
}
- } while (pkt_stats_len > 0);
+ } while (!info->clean_up && (pkt_stats_len > 0));
return status;
}
@@ -2417,9 +2514,14 @@
pthread_mutex_unlock(&info->pkt_fate_stats_lock);
} else if (pkt_stats_header->log_type == PKTLOG_TYPE_PKT_SW_EVENT) {
status = parse_stats_sw_event(info, pkt_stats_header);
- } else
- ALOGE("%s: invalid log_type %d",__FUNCTION__, pkt_stats_header->log_type);
-
+ } else if (pkt_stats_header->log_type == PKTLOG_TYPE_TX_STAT ||
+ pkt_stats_header->log_type == PKTLOG_TYPE_RX_STATBUF ||
+ pkt_stats_header->log_type == PKTLOG_TYPE_LITE_T2H ||
+ pkt_stats_header->log_type == PKTLOG_TYPE_LITE_RX) {
+ //TODO Parsing of per packet log.
+ } else {
+ //No Parsing on Default packet log type.
+ }
return status;
}
@@ -2522,7 +2624,7 @@
data += record_len;
buflen -= record_len;
- } while (buflen > 0);
+ } while (!info->clean_up && (buflen > 0));
return status;
}
@@ -2537,7 +2639,7 @@
rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
rb_entry_hdr.type = ENTRY_TYPE_DATA;
gettimeofday(&time, NULL);
- rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
+ rb_entry_hdr.timestamp = (u64)time.tv_usec + (u64)time.tv_sec * 1000 * 1000;
/* Write if verbose and handler is set */
if (info->rb_infos[DRIVER_PRINTS_RB_ID].verbose_level >= 1 &&
@@ -2596,15 +2698,23 @@
if (tb_vendor[CLD80211_ATTR_DATA]) {
clh = (tAniCLDHdr *)nla_data(tb_vendor[CLD80211_ATTR_DATA]);
}
+ } else {
+ ALOGE("Invalid data received");
+ return WIFI_ERROR_UNKNOWN;
}
- if (!clh) {
+ if (genlh->cmd != WLAN_NL_MSG_OEM && !clh) {
ALOGE("Invalid data received from driver");
- return WIFI_SUCCESS;
+ return WIFI_ERROR_UNKNOWN;
}
+
if((info->wifihal_ctrl_sock.s > 0) && (genlh->cmd == WLAN_NL_MSG_OEM)) {
wifihal_ctrl_event_t *ctrl_evt;
wifihal_mon_sock_t *reg;
+ if (!(tb_vendor[CLD80211_ATTR_DATA] || tb_vendor[CLD80211_ATTR_CMD])) {
+ ALOGE("Invalid oem data received from driver");
+ return WIFI_ERROR_UNKNOWN;
+ }
ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
if(ctrl_evt == NULL)
@@ -2623,9 +2733,6 @@
list_for_each_entry(reg, &info->monitor_sockets, list) {
- if(reg == NULL)
- break;
-
if (reg->family_name != CLD80211_FAMILY || reg->cmd_id != WLAN_NL_MSG_OEM)
continue;
@@ -2633,6 +2740,7 @@
/* Indicate the received OEM msg to respective client
it is responsibility of the registered client to check
the oem_msg is meant for them or not based on oem_msg sub type */
+ ALOGI("send oem msg of len : %d to apps",ctrl_evt->data_len);
if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
sizeof(*ctrl_evt) + ctrl_evt->data_len, 0,
(struct sockaddr *)®->monsock, reg->monsock_len) < 0)
@@ -2653,6 +2761,7 @@
}
}
free(ctrl_evt);
+ return WIFI_SUCCESS;
}
}
} else {
@@ -2707,6 +2816,12 @@
case EVENT_WLAN_STA_DATA_STALL:
process_wlan_data_stall_event(info, buf, event_hdr->length);
break;
+ case EVENT_WLAN_POWERSAVE_WOW:
+ case EVENT_WLAN_POWERSAVE_WOW_STATS:
+ case EVENT_WLAN_STA_KICKOUT:
+ case EVENT_WLAN_BRINGUP_STATUS:
+ /* Handle DIAG events properly */
+ break;
default:
return WIFI_SUCCESS;
}
@@ -2790,20 +2905,20 @@
diag_fw_type = event_hdr->diag_type;
if (diag_fw_type == DIAG_TYPE_FW_MSG) {
dbglog_slot *slot;
- u16 length = 0;
+ u32 length = 0;
slot = (dbglog_slot *)buf;
+ length = get_le32((u8 *)&slot->length);
if (nlh->nlmsg_len < (NLMSG_HDRLEN + sizeof(dbglog_slot) +
- slot->length)) {
+ length)) {
ALOGE("Received CNSS_DIAG message with insufficent length: %d:"
" expected: %zu, %s:%d",
nlh->nlmsg_len,
- (NLMSG_HDRLEN + sizeof(dbglog_slot) +slot->length),
+ (NLMSG_HDRLEN + sizeof(dbglog_slot) +length),
__FUNCTION__,
__LINE__);
return WIFI_ERROR_UNKNOWN;
}
- length = get_le32((u8 *)&slot->length);
process_fw_diag_msg(info, &slot->payload[0], length);
}
}
diff --git a/qcwcn/wifi_hal/wifilogger_diag.h b/wcn6740/qcwcn/wifi_hal/wifilogger_diag.h
similarity index 100%
copy from qcwcn/wifi_hal/wifilogger_diag.h
copy to wcn6740/qcwcn/wifi_hal/wifilogger_diag.h
diff --git a/wcn6740/qcwcn/wifi_hal/wifilogger_event_defs.h b/wcn6740/qcwcn/wifi_hal/wifilogger_event_defs.h
new file mode 100644
index 0000000..86b198c
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifilogger_event_defs.h
@@ -0,0 +1,516 @@
+/* Copyright (c) 2015, 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 WIFILOGGER_EVENT_DEFS_H
+#define WIFILOGGER_EVENT_DEFS_H
+
+typedef enum {
+ EVENT_DROP_ID = 0,
+
+ EVENT_WLAN_PE = 0x67A, /* 16 byte payload */
+
+ /* Events between 0x67b to 0x67f are not used */
+
+ EVENT_WLAN_ADD_BLOCK_ACK_SUCCESS = 0x67B, /* 11 byte payload */
+ EVENT_WLAN_ADD_BLOCK_ACK_FAILED = 0x67C, /* 9 byte payload */
+ EVENT_WLAN_BRINGUP_STATUS = 0x680, /* 12 byte payload */
+ EVENT_WLAN_POWERSAVE_WOW = 0x682, /* 11 byte payload */
+
+ EVENT_WLAN_EXTSCAN_FEATURE_STARTED = 0xA8E, /* 240 byte payload */
+ EVENT_WLAN_EXTSCAN_FEATURE_CHANNEL_CONFIG = 0xA8F, /* 243 byte payload */
+ EVENT_WLAN_EXTSCAN_CYCLE_STARTED = 0xA90, /* 12 byte payload */
+ EVENT_WLAN_EXTSCAN_CYCLE_COMPLETED = 0xA91, /* 12 byte payload */
+ EVENT_WLAN_EXTSCAN_BUCKET_STARTED = 0xA92, /* 1 byte payload */
+ EVENT_WLAN_EXTSCAN_BUCKET_COMPLETED = 0xA93, /* 4 byte payload */
+ EVENT_WLAN_ROAM_SCAN_STARTED = 0xA94, /* 128 byte payload */
+
+
+ EVENT_WLAN_ROAM_SCAN_COMPLETE = 0xA95,
+ EVENT_WLAN_ROAM_CANDIDATE_FOUND = 0xA96,
+ EVENT_WLAN_ROAM_SCAN_CONFIG = 0xA97,
+ EVENT_WLAN_BT_COEX_BT_SCO_START = 0xA98,
+ EVENT_WLAN_BT_COEX_BT_SCO_STOP = 0xA99,
+ EVENT_WLAN_BT_COEX_BT_SCAN_START = 0xA9A,
+ EVENT_WLAN_BT_COEX_BT_SCAN_STOP = 0xA9B,
+ EVENT_WLAN_BT_COEX_BT_HID_START = 0xA9C,
+ EVENT_WLAN_BT_COEX_BT_HID_STOP = 0xA9D,
+ EVENT_WLAN_WAKE_LOCK = 0xAA2, /* 96 bytes payload */
+ EVENT_WLAN_EAPOL = 0xA8D, /* 96 bytes payload */
+ EVENT_WLAN_EXTSCAN_FEATURE_STOP = 0xAA3,
+ EVENT_WLAN_EXTSCAN_RESULTS_AVAILABLE = 0xAA4,
+ EVENT_WLAN_BEACON_EVENT = 0xAA6,
+ EVENT_WLAN_LOG_COMPLETE = 0xAA7,
+ EVENT_WLAN_LOW_RESOURCE_FAILURE = 0xABB,
+ EVENT_WLAN_POWERSAVE_WOW_STATS = 0xB33, /* 76 bytes payload */
+ EVENT_WLAN_STA_KICKOUT = 0xB39, /* 11 bytes payload */
+ EVENT_WLAN_STA_DATA_STALL = 0xB3A,
+
+ EVENT_MAX_ID = 0x0FFF
+} event_id_enum_type;
+
+typedef enum {
+ LOG_DROP_ID = 0,
+ LOG_WLAN_EXTSCAN_CAPABILITIES = 0x18F1,
+ LOG_WLAN_EXTSCAN_FEATURE_STARTED = 0x18F2,
+} log_id_enum_type;
+
+typedef enum
+{
+ WLAN_PE_DIAG_SCAN_REQ_EVENT = 0,
+ WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT,
+ WLAN_PE_DIAG_SCAN_RSP_EVENT,
+ WLAN_PE_DIAG_JOIN_REQ_EVENT,
+ WLAN_PE_DIAG_JOIN_RSP_EVENT,
+ WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT,
+ WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT,
+ WLAN_PE_DIAG_REASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_REASSOC_RSP_EVENT,
+ WLAN_PE_DIAG_AUTH_REQ_EVENT,
+ WLAN_PE_DIAG_AUTH_RSP_EVENT = 10,
+ WLAN_PE_DIAG_DISASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_DISASSOC_RSP_EVENT,
+ WLAN_PE_DIAG_DISASSOC_IND_EVENT,
+ WLAN_PE_DIAG_DISASSOC_CNF_EVENT,
+ WLAN_PE_DIAG_DEAUTH_REQ_EVENT,
+ WLAN_PE_DIAG_DEAUTH_RSP_EVENT,
+ WLAN_PE_DIAG_DEAUTH_IND_EVENT,
+ WLAN_PE_DIAG_START_BSS_REQ_EVENT,
+ WLAN_PE_DIAG_START_BSS_RSP_EVENT,
+ WLAN_PE_DIAG_AUTH_IND_EVENT = 20,
+ WLAN_PE_DIAG_ASSOC_IND_EVENT,
+ WLAN_PE_DIAG_ASSOC_CNF_EVENT,
+ WLAN_PE_DIAG_REASSOC_IND_EVENT,
+ WLAN_PE_DIAG_SWITCH_CHL_REQ_EVENT,
+ WLAN_PE_DIAG_SWITCH_CHL_RSP_EVENT,
+ WLAN_PE_DIAG_STOP_BSS_REQ_EVENT,
+ WLAN_PE_DIAG_STOP_BSS_RSP_EVENT,
+ WLAN_PE_DIAG_DEAUTH_CNF_EVENT,
+ WLAN_PE_DIAG_ADDTS_REQ_EVENT,
+ WLAN_PE_DIAG_ADDTS_RSP_EVENT = 30,
+ WLAN_PE_DIAG_DELTS_REQ_EVENT,
+ WLAN_PE_DIAG_DELTS_RSP_EVENT,
+ WLAN_PE_DIAG_DELTS_IND_EVENT,
+ WLAN_PE_DIAG_ENTER_BMPS_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_BMPS_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT,
+ WLAN_PE_DIAG_ENTER_IMPS_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_IMPS_RSP_EVENT = 40,
+ WLAN_PE_DIAG_EXIT_IMPS_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_IMPS_RSP_EVENT,
+ WLAN_PE_DIAG_ENTER_UAPSD_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_UAPSD_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_UAPSD_RSP_EVENT,
+ WLAN_PE_DIAG_WOWL_ADD_BCAST_PTRN_EVENT,
+ WLAN_PE_DIAG_WOWL_DEL_BCAST_PTRN_EVENT,
+ WLAN_PE_DIAG_ENTER_WOWL_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_WOWL_RSP_EVENT = 50,
+ WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_WOWL_RSP_EVENT,
+ WLAN_PE_DIAG_HAL_ADDBA_REQ_EVENT,
+ WLAN_PE_DIAG_HAL_ADDBA_RSP_EVENT,
+ WLAN_PE_DIAG_HAL_DELBA_IND_EVENT,
+ WLAN_PE_DIAG_HB_FAILURE_TIMEOUT,
+ WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT,
+ WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT,
+ WLAN_PE_DIAG_PREAUTH_DONE,
+ WLAN_PE_DIAG_REASSOCIATING = 60,
+ WLAN_PE_DIAG_CONNECTED,
+ WLAN_PE_DIAG_ASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_AUTH_COMP_EVENT,
+ WLAN_PE_DIAG_ASSOC_COMP_EVENT,
+ WLAN_PE_DIAG_AUTH_START_EVENT,
+ WLAN_PE_DIAG_ASSOC_START_EVENT,
+ WLAN_PE_DIAG_REASSOC_START_EVENT,
+ WLAN_PE_DIAG_ROAM_AUTH_START_EVENT,
+ WLAN_PE_DIAG_ROAM_AUTH_COMP_EVENT,
+ WLAN_PE_DIAG_ROAM_ASSOC_START_EVENT = 70,
+ WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
+ WLAN_PE_DIAG_SCAN_COMP_EVENT,
+ WLAN_PE_DIAG_SCAN_RES_FOUND_EVENT,
+ WLAN_PE_DIAG_ASSOC_TIMEOUT,
+ WLAN_PE_DIAG_AUTH_TIMEOUT,
+} wlan_host_diag_event_type;
+
+typedef struct wlan_pe_event {
+ char bssid[6];
+ u16 event_type;
+ u16 sme_state;
+ u16 mlm_state;
+ u16 status;
+ u16 reason_code;
+} __attribute__((packed)) wlan_pe_event_t;
+
+typedef enum {
+ WLAN_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED = 0,
+ WLAN_DRIVER_EAPOL_FRAME_RECEIVED,
+} wlan_eapol_event_type;
+
+#define EAPOL_MASK 0x8013
+#define EAPOL_M1_MASK 0x8000
+#define EAPOL_M2_MASK 0x0001
+#define EAPOL_M3_MASK 0x8013
+#define EAPOL_M4_MASK 0x0003
+
+typedef struct wlan_eapol_event {
+ u8 event_sub_type;
+ u8 eapol_packet_type;
+ u16 eapol_key_info;
+ u16 eapol_rate;
+ u8 dest_addr[6];
+ u8 src_addr[6];
+} __attribute__((packed)) wlan_eapol_event_t;
+
+/*EVENT_WLAN_EXTSCAN_FEATURE_STARTED */
+typedef struct wlan_ext_bucket {
+ u8 bucket_id;
+ u8 base_period_multiplier;
+ u16 min_dwell_time_active;
+ u16 max_dwell_time_active;
+ u16 min_dwell_time_passive;
+ u16 max_dwell_time_passive;
+ u8 num_channels;
+ u8 channel_offset;
+ u8 forwarding_flags;
+ u8 channel_band;
+ u32 notify_extscan_events;
+} __attribute__((packed)) wlan_ext_bucket_t;
+
+typedef struct {
+ u32 base_period;
+ u32 max_iterations;
+ u32 forwarding_flags;
+ u32 configuration_flags;
+ u32 notify_extscan_events;
+ u32 scan_priority;
+ u32 max_bssids_per_scan_cycle;
+ u32 min_rssi;
+ u32 max_table_usage;
+ u32 min_dwell_time_active;
+ u32 max_dwell_time_active;
+ u32 min_dwell_time_passive;
+ u32 max_dwell_time_passive;
+ u32 min_rest_time;
+ u32 max_rest_time;
+ u32 n_probes;
+ u32 repeat_probe_time;
+ u32 probe_spacing_time;
+ u32 idle_time;
+ u32 max_scan_time;
+ u32 probe_delay;
+ u32 scan_ctrl_flags;
+ u32 burst_duration;
+ u32 num_buckets;
+ wlan_ext_bucket bucket_list[8];
+} __attribute__((packed)) wlan_ext_scan_feature_started_payload_type;
+/*End EVENT_WLAN_EXTSCAN_FEATURE_STARTED*/
+
+/*EVENT_WLAN_EXTSCAN_FEATURE_CHANNEL_CONFIG*/
+typedef struct {
+ u8 bucket_id;
+ u16 scan_channels[40];
+} __attribute__((packed)) wlan_ext_bucket_channels;
+
+typedef struct {
+ wlan_ext_bucket_channels bucket_list[3];
+} __attribute__((packed)) wlan_ext_bucket_channel_config_payload_type;
+
+/*End EVENT_WLAN_EXTSCAN_FEATURE_CHANNEL_CONFIG*/
+
+/*EVENT_WLAN_EXTSCAN_CYCLE_STARTED*/
+typedef struct {
+ u32 scan_id;
+ u32 timer_tick;
+ u32 scheduled_bucket_mask;
+ u32 scan_cycle_count;
+} __attribute__((packed)) wlan_ext_scan_cycle_started_payload_type;
+/*End EVENT_WLAN_EXTSCAN_CYCLE_STARTED*/
+
+/*EVENT_WLAN_EXTSCAN_CYCLE_COMPLETED*/
+typedef struct {
+ u32 scan_id;
+ u32 timer_tick;
+ u32 scheduled_bucket_mask;
+ u32 scan_cycle_count;
+} __attribute__((packed)) wlan_ext_scan_cycle_completed_payload_type;
+/*End EVENT_WLAN_EXTSCAN_CYCLE_COMPLETED*/
+
+/*EVENT_WLAN_EXTSCAN_BUCKET_STARTED*/
+typedef struct {
+ u8 bucket_id;
+} __attribute__((packed)) wlan_ext_scan_bucket_started_payload_type;
+/*End EVENT_WLAN_EXTSCAN_BUCKET_STARTED*/
+
+/*EVENT_WLAN_EXTSCAN_BUCKET_COMPLETED*/
+typedef struct {
+ u8 bucket_id;
+} __attribute__((packed)) wlan_ext_scan_bucket_completed_payload_type;
+/*End EVENT_WLAN_EXTSCAN_BUCKET_COMPLETED*/
+
+/*EVENT_WLAN_ROAM_SCAN_STARTED*/
+typedef struct {
+ u32 scan_id;
+ u32 roam_scan_flags;
+ u32 cur_rssi;
+ u16 scan_params[18];
+ u16 scan_channels[40]; // first 40 channels only
+} __attribute__((packed)) wlan_roam_scan_started_payload_type;
+/*End EVENT_WLAN_ROAM_SCAN_STARTED*/
+
+/*EVENT_WLAN_ROAM_SCAN_COMPLETE*/
+typedef struct {
+ u32 scan_id;
+ u32 reason;
+ u32 completion_flags;
+ u32 num_candidate;
+ u32 flags;
+} __attribute__((packed)) wlan_roam_scan_complete_payload_type;
+/*End EVENT_WLAN_ROAM_SCAN_COMPLETE*/
+
+/*EVENT_WLAN_ROAM_CANDIDATE_FOUND*/
+typedef struct {
+ u8 channel;
+ u8 rssi;
+ u8 bssid[6];
+ u8 ssid[33];
+ u8 auth_mode;
+ u8 ucast_cipher;
+ u8 mcast_cipher;
+} __attribute__((packed)) wlan_roam_candidate_found_payload_type;
+/*End EVENT_WLAN_ROAM_CANDIDATE_FOUND*/
+
+/*EVENT_WLAN_ROAM_SCAN_CONFIG*/
+typedef struct {
+ u32 flags;
+ u32 roam_scan_config[8];
+} __attribute__((packed)) wlan_roam_scan_config_payload_type;
+/*End EVENT_WLAN_ROAM_SCAN_CONFIG*/
+
+/* EVENT_WLAN_BT_COEX_BT_SCO_START */
+typedef struct {
+ u8 link_id;
+ u8 link_state;
+ u8 link_role;
+ u8 link_type;
+ u16 Tsco;
+ u8 Rsco;
+} __attribute__((packed)) wlan_bt_coex_bt_sco_start_payload_type;
+/* End EVENT_WLAN_BT_COEX_BT_SCO_START */
+
+/* EVENT_WLAN_BT_COEX_BT_SCO_STOP */
+typedef struct {
+ u8 link_id;
+ u8 link_state;
+ u8 link_role;
+ u8 link_type;
+ u16 Tsco;
+ u8 Rsco;
+} __attribute__((packed)) wlan_bt_coex_bt_sco_stop_payload_type;
+/* End EVENT_WLAN_BT_COEX_BT_SCO_STOP */
+
+/* EVENT_WLAN_BT_COEX_BT_SCAN_START */
+typedef struct {
+ u8 scan_type;
+ u8 scan_bitmap;
+} __attribute__((packed)) wlan_bt_coex_bt_scan_start_payload_type;
+
+/* End EVENT_WLAN_BT_COEX_BT_SCAN_START */
+
+/* EVENT_WLAN_BT_COEX_BT_SCAN_STOP */
+typedef struct {
+ u8 scan_type;
+ u8 scan_bitmap;
+} __attribute__((packed)) wlan_bt_coex_bt_scan_stop_payload_type;
+/* End EVENT_WLAN_BT_COEX_BT_SCAN_STOP */
+
+/* EVENT_WIFI_BT_COEX_BT_HID_START */
+typedef struct {
+ u8 link_id;
+ u8 link_state;
+ u8 link_role;
+ u8 Tsniff;
+ u8 attempts;
+} __attribute__((packed)) wlan_bt_coex_bt_hid_start_payload_type;
+/* End EVENT_WIFI_BT_COEX_BT_HID_START */
+
+/* EVENT_WIFI_BT_COEX_BT_HID_STOP */
+typedef struct {
+ u8 link_id;
+ u8 link_state;
+ u8 link_role;
+ u8 Tsniff;
+ u8 attempts;
+} __attribute__((packed)) wlan_bt_coex_bt_hid_stop_payload_type;
+/* End EVENT_WIFI_BT_COEX_BT_HID_STOP */
+
+/* EVENT_WLAN_EXTSCAN_FEATURE_STOP */
+typedef struct {
+ u32 request_id;
+} __attribute__((packed)) wlan_ext_scan_feature_stop_payload_type;
+/* End EVENT_WLAN_EXTSCAN_FEATURE_STOP */
+
+/* EVENT_WLAN_EXTSCAN_RESULTS_AVAILABLE */
+typedef struct {
+ u32 request_id;
+ u32 table_type;
+ u32 entries_in_use;
+ u32 maximum_entries;
+ u32 scan_count_after_getResults;
+ u8 threshold_num_scans;
+} __attribute__((packed)) wlan_ext_scan_results_available_payload_type;
+/* End EVENT_WLAN_EXTSCAN_RESULTS_AVAILABLE */
+
+/* Log LOG_WLAN_EXTSCAN_CAPABILITIES */
+typedef struct {
+ u32 header;
+ u32 request_id;
+ u32 requestor_id;
+ u32 vdev_id;
+ u32 num_extscan_cache_tables;
+ u32 num_wlan_change_monitor_tables;
+ u32 num_hotlist_monitor_tables;
+ u32 rtt_one_sided_supported;
+ u32 rtt_11v_supported;
+ u32 rtt_ftm_supported;
+ u32 num_extscan_cache_capabilities;
+ u32 num_extscan_wlan_change_capabilities;
+ u32 num_extscan_hotlist_capabilities;
+ u32 num_roam_ssid_whitelist;
+ u32 num_roam_bssid_blacklist;
+ u32 num_roam_bssid_preferred_list;
+ u32 num_extscan_hotlist_ssid;
+ u32 num_epno_networks;
+} __attribute__((packed)) wlan_extscan_capabilities_event_fixed_param;
+
+typedef struct {
+ u32 header;
+ u32 table_id;
+ u32 scan_cache_entry_size;
+ u32 max_scan_cache_entries;
+ u32 max_buckets;
+ u32 max_bssid_per_scan;
+ u32 max_table_usage_threshold;
+} __attribute__((packed)) wlan_extscan_cache_capabilities;
+
+typedef struct {
+ u32 tlv_header;
+ u32 table_id;
+ u32 wlan_hotlist_entry_size;
+ u32 max_hotlist_entries;
+} __attribute__((packed)) wlan_extscan_hotlist_monitor_capabilities;
+
+typedef struct {
+ u32 request_id;
+ wlan_extscan_capabilities_event_fixed_param extscan_capabilities;
+ wlan_extscan_cache_capabilities extscan_cache_capabilities;
+ wlan_extscan_hotlist_monitor_capabilities extscan_hotlist_monitor_capabilities;
+} __attribute__((packed)) wlan_ext_scan_capabilities_payload_type;
+/* End LOG_WLAN_EXTSCAN_CAPABILITIES */
+
+/* EVENT_WLAN_BEACON_RECEIVED */
+typedef struct {
+ u8 bssid[6];
+ u32 beacon_rssi;
+} __attribute__((packed)) wlan_beacon_received_payload_type;
+/* End EVENT_WLAN_BEACON_RECEIVED */
+
+typedef struct {
+ u8 ucBaPeerMac[6];
+ u8 ucBaTid;
+ u8 ucBaBufferSize;
+ u16 ucBaSSN;
+ u8 fInitiator;
+} __attribute__((packed)) wlan_add_block_ack_success_payload_type;
+
+/* EVENT_WLAN_ADD_BLOCK_ACK_FAILED */
+typedef struct {
+ u8 ucBaPeerMac[6];
+ u8 ucBaTid;
+ u8 ucReasonCode;
+ u8 fInitiator;
+} __attribute__((packed)) wlan_add_block_ack_failed_payload_type;
+
+typedef enum
+{
+ WIFI_EVENT_MEMORY_FAILURE,
+} resource_failure_type;
+
+typedef struct wlan_low_resource_failure_event
+{
+ resource_failure_type event_sub_type;
+} __attribute__((packed)) wlan_low_resource_failure_event_t;
+
+/* EVENT_WLAN_POWERSAVE_WOW */
+typedef struct {
+ u8 event_subtype;
+ u8 wow_type;
+ u8 wow_magic_pattern[6];
+ u8 wow_del_ptrn_id;
+ u8 wow_wakeup_cause;
+ u8 wow_wakeup_cause_pbm_ptrn_id;
+} __attribute__((packed)) wlan_wow_payload_t;
+
+/* EVENT_WLAN_POWERSAVE_WOW_STATS */
+typedef struct {
+ u32 wow_ucast_wake_up_count;
+ u32 wow_bcast_wake_up_count;
+ u32 wow_ipv4_mcast_wake_up_count;
+ u32 wow_ipv6_mcast_wake_up_count;
+ u32 wow_ipv6_mcast_ra_stats;
+ u32 wow_ipv6_mcast_ns_stats;
+ u32 wow_ipv6_mcast_na_stats;
+ u32 wow_pno_match_wake_up_count;
+ u32 wow_pno_complete_wake_up_count;
+ u32 wow_gscan_wake_up_count;
+ u32 wow_low_rssi_wake_up_count;
+ u32 wow_rssi_breach_wake_up_count;
+ u32 wow_icmpv4_count;
+ u32 wow_icmpv6_count;
+ u32 wow_oem_response_wake_up_count;
+ u32 Reserved_1;
+ u32 Reserved_2;
+ u32 Reserved_3;
+ u32 Reserved_4;
+} __attribute__((packed)) wlan_wow_stats_t;
+
+/* EVENT_WLAN_STA_KICKOUT */
+typedef struct {
+ u32 reasoncode;
+ u8 peer_mac[6];
+ u8 vdev_id;
+} __attribute__((packed)) wlan_kickout_t;
+
+/* EVENT_WLAN_BRINGUP_STATUS */
+typedef struct {
+ u16 wlan_status;
+ u8 driver_version[10];
+} __attribute__((packed)) wlan_status_payload_t;
+
+#endif /* WIFILOGGER_EVENT_DEFS_H */
diff --git a/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h b/wcn6740/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
similarity index 100%
copy from qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
copy to wcn6740/qcwcn/wifi_hal/wifilogger_vendor_tag_defs.h
diff --git a/wcn6740/qcwcn/wifi_hal/wifiloggercmd.h b/wcn6740/qcwcn/wifi_hal/wifiloggercmd.h
new file mode 100644
index 0000000..9361821
--- /dev/null
+++ b/wcn6740/qcwcn/wifi_hal/wifiloggercmd.h
@@ -0,0 +1,120 @@
+/* Copyright (c) 2015, 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 __WIFI_HAL_WIFILOGGER_COMMAND_H__
+#define __WIFI_HAL_WIFILOGGER_COMMAND_H__
+
+#include "common.h"
+#include "cpp_bindings.h"
+#include "wifi_logger.h"
+#include "wifilogger_diag.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#define POWER_EVENTS_RB_BUF_SIZE 2048
+#define POWER_EVENTS_NUM_BUFS 4
+
+#define CONNECTIVITY_EVENTS_RB_BUF_SIZE 4096
+#define CONNECTIVITY_EVENTS_NUM_BUFS 4
+
+#define PKT_STATS_RB_BUF_SIZE 4096
+#define PKT_STATS_NUM_BUFS 32
+
+#define DRIVER_PRINTS_RB_BUF_SIZE 4096
+#define DRIVER_PRINTS_NUM_BUFS 128
+
+#define FIRMWARE_PRINTS_RB_BUF_SIZE 32768
+#define FIRMWARE_PRINTS_NUM_BUFS 16
+
+#define LOGGER_RING_BUFFER (WIFI_LOGGER_CONNECT_EVENT_SUPPORTED \
+ | WIFI_LOGGER_POWER_EVENT_SUPPORTED \
+ | WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED)
+
+enum rb_info_indices {
+ POWER_EVENTS_RB_ID = 0,
+ CONNECTIVITY_EVENTS_RB_ID = 1,
+ PKT_STATS_RB_ID = 2,
+ DRIVER_PRINTS_RB_ID = 3,
+ FIRMWARE_PRINTS_RB_ID = 4,
+};
+
+typedef struct {
+ void (*on_firmware_memory_dump) (char *buffer,
+ int buffer_size);
+
+} WifiLoggerCallbackHandler;
+
+
+class WifiLoggerCommand : public WifiVendorCommand
+{
+private:
+ WifiLoggerCallbackHandler mHandler;
+ char *mVersion;
+ int mVersionLen;
+ u32 *mSupportedSet;
+ int mRequestId;
+ bool mWaitforRsp;
+ bool mMoreData;
+ WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;
+public:
+
+ WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
+
+ static WifiLoggerCommand* instance(wifi_handle handle);
+ virtual ~WifiLoggerCommand();
+
+ // This function implements creation of WifiLogger specific Request
+ // based on the request type
+ virtual wifi_error create();
+ virtual wifi_error requestEvent();
+ virtual wifi_error requestResponse();
+ virtual int handleResponse(WifiEvent &reply);
+ virtual int handleEvent(WifiEvent &event);
+ wifi_error setCallbackHandler(WifiLoggerCallbackHandler nHandler);
+ virtual void unregisterHandler(u32 subCmd);
+
+ /* Takes wait time in seconds. */
+ virtual wifi_error timed_wait(u16 wait_time);
+ virtual void waitForRsp(bool wait);
+ virtual void setVersionInfo(char *buffer, int buffer_size);
+ virtual void setFeatureSet(u32 *support);
+ virtual void getWakeStatsRspParams(
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+};
+void rb_timerhandler(hal_info *info);
+wifi_error wifi_logger_ring_buffers_init(hal_info *info);
+void wifi_logger_ring_buffers_deinit(hal_info *info);
+void push_out_all_ring_buffers(hal_info *info);
+void send_alert(hal_info *info, int reason_code);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __WIFI_HAL_WIFILOGGER_COMMAND_H__ */
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/Android.mk b/wcn6740/qcwcn/wpa_supplicant_8_lib/Android.mk
new file mode 100644
index 0000000..8e2ab2d
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/Android.mk
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
+
+ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
+ CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
+endif
+
+WPA_SUPPL_DIR := external/wpa_supplicant_8
+WPA_SRC_FILE :=
+
+include $(WPA_SUPPL_DIR)/wpa_supplicant/android.config
+
+WPA_SUPPL_DIR_INCLUDE := $(WPA_SUPPL_DIR)/src \
+ $(WPA_SUPPL_DIR)/src/common \
+ $(WPA_SUPPL_DIR)/src/drivers \
+ $(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
+WPA_SUPPL_DIR_INCLUDE += external/libnl/include
+WPA_SRC_FILE += driver_cmd_nl80211_extn.c \
+ driver_cmd_nl80211.c
+endif
+
+ifeq ($(TARGET_ARCH),arm)
+# To force sizeof(enum) = 4
+L_CFLAGS += -mabi=aapcs-linux
+endif
+
+ifdef CONFIG_ANDROID_LOG
+L_CFLAGS += -DCONFIG_ANDROID_LOG
+endif
+
+ifdef CONFIG_P2P
+L_CFLAGS += -DCONFIG_P2P
+endif
+
+L_CFLAGS += -Werror
+
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := lib_driver_cmd_qcwcn
+LOCAL_SHARED_LIBRARIES := libc libcutils
+ifneq ($(wildcard external/libnl),)
+LOCAL_SHARED_LIBRARIES += libnl
+endif
+LOCAL_SHARED_LIBRARIES += libdl
+LOCAL_CFLAGS := $(L_CFLAGS) -Wall
+LOCAL_SRC_FILES := $(WPA_SRC_FILE)
+LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE)
+LOCAL_VENDOR_MODULE := true
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+include $(BUILD_STATIC_LIBRARY)
+
+########################
+
+endif
diff --git a/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD b/wcn6740/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
similarity index 100%
copy from qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
copy to wcn6740/qcwcn/wpa_supplicant_8_lib/MODULE_LICENSE_BSD
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/Makefile.am b/wcn6740/qcwcn/wpa_supplicant_8_lib/Makefile.am
new file mode 100644
index 0000000..8c09e3e
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/Makefile.am
@@ -0,0 +1,37 @@
+# Makefile.am - Automake script for wpa_supplicant_8_lib
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS = -Wall
+
+if DEBUG
+AM_CFLAGS += -g
+else
+AM_CFLAGS += -O2
+endif
+
+AM_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast \
+ -Wno-maybe-uninitialized -Wno-parentheses \
+ -DCONFIG_P2P
+
+h_sources = driver_cmd_nl80211_extn.h
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(h_sources)
+
+libwpa_supplicant_8_lib_la_SOURCES = driver_cmd_nl80211.c
+libwpa_supplicant_8_lib_la_SOURCES += driver_cmd_nl80211_extn.c
+libwpa_supplicant_8_lib_la_CFLAGS = ${AM_CFLAGS} ${LIBNL_CFLAGS}
+
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src/common"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src/drivers"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src/l2_packet"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src/utils"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/src/wps"
+libwpa_supplicant_8_lib_la_CFLAGS += "-I${WPA_SUPPLICANT_DIR}/wpa_supplicant"
+libwpa_supplicant_8_lib_la_CFLAGS += "-DLINUX_EMBEDDED"
+
+
+libwpa_supplicant_8_lib_la_LIBADD = ${LIBNL_LIBS}
+lib_LTLIBRARIES = libwpa_supplicant_8_lib.la
+
+pkgconfigdir = $(libdir)/pkgconfig
diff --git a/qcwcn/wpa_supplicant_8_lib/NOTICE b/wcn6740/qcwcn/wpa_supplicant_8_lib/NOTICE
similarity index 100%
copy from qcwcn/wpa_supplicant_8_lib/NOTICE
copy to wcn6740/qcwcn/wpa_supplicant_8_lib/NOTICE
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/configure.ac b/wcn6740/qcwcn/wpa_supplicant_8_lib/configure.ac
new file mode 100644
index 0000000..76eda02
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/configure.ac
@@ -0,0 +1,72 @@
+# -*- Autoconf -*-
+# configure.ac -- Autoconf script for qcacld-tools
+#
+
+AC_PREREQ(2.61)
+AC_INIT([wpa_supplicant_8_lib], 1.0.0)
+AM_INIT_AUTOMAKE([foreign])
+AM_MAINTAINER_MODE
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+LT_INIT
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+AC_ARG_ENABLE([debug],
+ [ --enable-debug Turn on debugging],
+ [case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+ esac],[debug=false])
+AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
+
+has_libnl_ver=0
+# libnl-2 provides only libnl-2.0.pc file, so we check for separate libnl-genl-3.0.pc
+# pkg-config file just for libnl-3.0 case.
+#
+PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.0 libnl-genl-3.0 >= 3.0], [has_libnl_ver=3], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-2.0 >= 2.0], [has_libnl_ver=2], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-1], [has_libnl_ver=1], [has_libnl_ver=0])])])
+
+if (test "$has_libnl_ver" -eq 0); then
+ AC_MSG_ERROR(libnl and libnl-genl are required but were not found)
+fi
+
+
+AC_ARG_VAR(WPA_SUPPLICANT_DIR,[Path to Wpa-supplicant-dir ])
+AS_IF([test "${WPA_SUPPLICANT_DIR}" = ""],[AC_MSG_ERROR("Provide WPA_SUPPLICANT_DIR=path to wpa_supplicant dir")])
+
+AC_SUBST([LIBNL_CFLAGS])
+AC_SUBST([LIBNL_LIBS])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_HEADER_STDC
+AC_C_INLINE
+AC_TYPE_INT64_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+
+AC_CONFIG_FILES([ \
+ Makefile
+])
+AC_OUTPUT
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
new file mode 100644
index 0000000..9656710
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -0,0 +1,5924 @@
+/*
+ * Driver interaction with extended Linux CFG8021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include "includes.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/object-api.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/pkt_sched.h>
+
+#include "common.h"
+#include "linux_ioctl.h"
+#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
+#if defined(ANDROID) || defined(LINUX_EMBEDDED)
+#include "android_drv.h"
+#endif
+#include "driver_cmd_nl80211_extn.h"
+
+#define WPA_PS_ENABLED 0
+#define WPA_PS_DISABLED 1
+#define UNUSED(x) (void)(x)
+#define NL80211_ATTR_MAX_INTERNAL 256
+#define CSI_STATUS_REJECTED -1
+#define CSI_STATUS_SUCCESS 0
+#define ENHANCED_CFR_VER 2
+#define CSI_GROUP_BITMAP 1
+#define CSI_DEFAULT_GROUP_ID 0
+#define CSI_FC_STYPE_BEACON 8
+#define CSI_MGMT_BEACON (1<<WLAN_FC_STYPE_BEACON)
+
+#define TWT_SETUP_WAKE_INTVL_MANTISSA_MAX 0xFFFF
+#define TWT_SETUP_WAKE_DURATION_MAX 0xFF
+#define TWT_SETUP_WAKE_INTVL_EXP_MAX 31
+#define TWT_WAKE_INTERVAL_TU_FACTOR 1024
+
+#define TWT_SETUP_STR "twt_session_setup"
+#define TWT_TERMINATE_STR "twt_session_terminate"
+#define TWT_PAUSE_STR "twt_session_pause"
+#define TWT_RESUME_STR "twt_session_resume"
+#define TWT_NUDGE_STR "twt_session_nudge"
+#define TWT_GET_PARAMS_STR "twt_session_get_params"
+#define TWT_GET_STATS_STR "twt_session_get_stats"
+#define TWT_CLEAR_STATS_STR "twt_session_clear_stats"
+#define TWT_GET_CAP_STR "twt_get_capability"
+#define TWT_SET_PARAM_STR "twt_set_param"
+
+#define TWT_SETUP_STRLEN strlen(TWT_SETUP_STR)
+#define TWT_TERMINATE_STR_LEN strlen(TWT_TERMINATE_STR)
+#define TWT_PAUSE_STR_LEN strlen(TWT_PAUSE_STR)
+#define TWT_RESUME_STR_LEN strlen(TWT_RESUME_STR)
+#define TWT_NUDGE_STR_LEN strlen(TWT_NUDGE_STR)
+#define TWT_GET_PARAMS_STR_LEN strlen(TWT_GET_PARAMS_STR)
+#define TWT_GET_STATS_STR_LEN strlen(TWT_GET_STATS_STR)
+#define TWT_CLEAR_STATS_STR_LEN strlen(TWT_CLEAR_STATS_STR)
+#define TWT_GET_CAP_STR_LEN strlen(TWT_GET_CAP_STR)
+#define TWT_SET_PARAM_STR_LEN strlen(TWT_SET_PARAM_STR)
+
+#define TWT_CMD_NOT_EXIST -EINVAL
+#define DEFAULT_IFNAME "wlan0"
+#define TWT_RESP_BUF_LEN 512
+
+#define SINGLE_SPACE_LEN 1
+#define SINGLE_DIGIT_LEN 1
+
+#define DIALOG_ID_STR "dialog_id"
+#define REQ_TYPE_STR "req_type"
+#define TRIG_TYPE_STR "trig_type"
+#define FLOW_TYPE_STR "flow_type"
+#define WAKE_INTR_EXP_STR "wake_intr_exp"
+#define PROTECTION_STR "protection"
+#define WAKE_TIME_STR "wake_time"
+#define WAKE_DUR_STR "wake_dur"
+#define WAKE_INTR_MANTISSA_STR "wake_intr_mantissa"
+#define BROADCAST_STR "broadcast"
+#define MIN_WAKE_INTVL_STR "min_wake_intvl"
+#define MAX_WAKE_INTVL_STR "max_wake_intvl"
+#define MIN_WAKE_DUR_STR "min_wake_duration"
+#define MAX_WAKE_DUR_STR "max_wake_duration"
+#define NEXT_TWT_STR "next_twt"
+#define NEXT2_TWT_STR "next2_twt"
+#define NEXT_TWT_SIZE_STR "next_twt_size"
+#define PAUSE_DURATION_STR "pause_duration"
+#define WAKE_TSF_STR "wake_tsf"
+#define ANNOUNCE_TIMEOUT_STR "announce_timeout"
+#define AP_AC_VALUE_STR "ap_ac_value"
+#define MAC_ADDRESS_STR "mac_addr"
+
+#define DIALOG_ID_STR_LEN strlen(DIALOG_ID_STR)
+#define REQ_TYPE_STR_LEN strlen(REQ_TYPE_STR)
+#define TRIG_TYPE_STR_LEN strlen(TRIG_TYPE_STR)
+#define FLOW_TYPE_STR_LEN strlen(FLOW_TYPE_STR)
+#define WAKE_INTR_EXP_STR_LEN strlen(WAKE_INTR_EXP_STR)
+#define PROTECTION_STR_LEN strlen(PROTECTION_STR)
+#define WAKE_TIME_STR_LEN strlen(WAKE_TIME_STR)
+#define WAKE_DUR_STR_LEN strlen(WAKE_DUR_STR)
+#define WAKE_INTR_MANTISSA_STR_LEN strlen(WAKE_INTR_MANTISSA_STR)
+#define BROADCAST_STR_LEN strlen(BROADCAST_STR)
+#define MIN_WAKE_INTVL_STR_LEN strlen(MIN_WAKE_INTVL_STR)
+#define MAX_WAKE_INTVL_STR_LEN strlen(MAX_WAKE_INTVL_STR)
+#define MIN_WAKE_DUR_STR_LEN strlen(MIN_WAKE_DUR_STR)
+#define MAX_WAKE_DUR_STR_LEN strlen(MAX_WAKE_DUR_STR)
+#define NEXT_TWT_STR_LEN strlen(NEXT_TWT_STR)
+#define NEXT2_TWT_STR_LEN strlen(NEXT2_TWT_STR)
+#define NEXT_TWT_SIZE_STR_LEN strlen(NEXT_TWT_SIZE_STR)
+#define PAUSE_DURATION_STR_LEN strlen(PAUSE_DURATION_STR)
+#define WAKE_TSF_STR_LEN strlen(WAKE_TSF_STR)
+#define ANNOUNCE_TIMEOUT_STR_LEN strlen(ANNOUNCE_TIMEOUT_STR)
+#define AP_AC_VALUE_STR_LEN strlen(AP_AC_VALUE_STR)
+#define MAC_ADDR_STR_LEN strlen(MAC_ADDRESS_STR)
+
+#define MAC_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+
+#define TWT_CTRL_EVENT "CTRL-EVENT-TWT"
+#define TWT_SETUP_RESP "CTRL-EVENT-TWT SETUP"
+#define TWT_TEARDOWN_RESP "CTRL-EVENT-TWT TERMINATE"
+#define TWT_PAUSE_RESP "CTRL-EVENT-TWT PAUSE"
+#define TWT_RESUME_RESP "CTRL-EVENT-TWT RESUME"
+#define TWT_NOTIFY_RESP "CTRL-EVENT-TWT NOTIFY"
+#define TWT_SETUP_RESP_LEN strlen(TWT_SETUP_RESP)
+#define TWT_TEARDOWN_RESP_LEN strlen(TWT_TEARDOWN_RESP)
+#define TWT_PAUSE_RESP_LEN strlen(TWT_PAUSE_RESP)
+#define TWT_RESUME_RESP_LEN strlen(TWT_RESUME_RESP)
+#define TWT_NOTIFY_RESP_LEN strlen(TWT_NOTIFY_RESP)
+
+static int twt_async_support = -1;
+
+struct twt_setup_parameters {
+ u8 dialog_id;
+ u8 req_type;
+ u8 trig_type;
+ u8 flow_type;
+ u8 wake_intr_exp;
+ u8 protection;
+ u32 wake_time;
+ u32 wake_dur;
+ u32 wake_intr_mantissa;
+ u8 bcast;
+ u32 min_wake_intvl;
+ u32 max_wake_intvl;
+ u32 min_wake_duration;
+ u32 max_wake_duration;
+ u64 wake_tsf;
+ u32 announce_timeout_us;
+};
+
+struct twt_resume_parameters {
+ u8 dialog_id;
+ u8 next_twt;
+ u32 next2_twt;
+ u32 next_twt_size;
+};
+
+struct twt_nudge_parameters {
+ u8 dialog_id;
+ u32 wake_time;
+ u32 next_twt_size;
+};
+
+struct twt_set_parameters {
+ u8 ap_ac_value;
+};
+
+struct twt_resp_info {
+ char *reply_buf;
+ int reply_buf_len;
+ enum qca_wlan_twt_operation twt_oper;
+ struct wpa_driver_nl80211_data *drv;
+};
+
+
+static int wpa_driver_twt_async_resp_event(struct wpa_driver_nl80211_data *drv,
+ u32 vendor_id, u32 subcmd, u8 *data, size_t len);
+
+/* ============ nl80211 driver extensions =========== */
+enum csi_state {
+ CSI_STATE_STOP = 0,
+ CSI_STATE_START,
+};
+
+struct csi_global_params {
+ struct i802_bss *bss;
+ enum csi_state current_state;
+ char connected_bssid[MAC_ADDR_LEN];
+ int transport_mode;
+};
+
+static struct csi_global_params g_csi_param = {0};
+
+static wpa_driver_oem_cb_table_t *oem_cb_table = NULL;
+
+#define MCC_QUOTA_MIN 10
+#define MCC_QUOTA_MAX 90
+/* Only one quota entry for now */
+#define MCC_QUOTA_ENTRIES_MAX 1
+
+struct mcc_quota {
+ uint32_t if_idx;
+ uint32_t quota;
+};
+
+
+static char *get_next_arg(char *cmd)
+{
+ char *pos = cmd;
+
+ while (*pos != ' ' && *pos != '\0')
+ pos++;
+
+ return pos;
+}
+
+static int wpa_driver_cmd_set_ani_level(struct i802_bss *bss, int mode, int ofdmlvl)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg = NULL;
+ struct nlattr *params = NULL;
+ int ret = 0;
+
+ 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_SET_WIFI_CONFIGURATION) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING, mode)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+ if(mode == QCA_WLAN_ANI_SETTING_FIXED) {
+ if(nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL, sizeof(int32_t), &ofdmlvl)){
+ nlmsg_free(msg);
+ return -1;
+ }
+ }
+ nla_nest_end(msg, params);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (!ret)
+ return 0;
+ wpa_printf(MSG_ERROR, "%s: Failed set_ani_level, ofdmlvl=%d, ret=%d",
+ __FUNCTION__, ofdmlvl, ret);
+ 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 > 30)) {
+ wpa_printf(MSG_ERROR, "%s: args less or invalid", __FUNCTION__);
+ nlmsg_free(msg);
+ 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, 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;
+ struct nl_msg *msg;
+ char *endptr = NULL;
+ int ret;
+ int dbm, mbm;
+
+ wpa_printf(MSG_INFO, "%s enter: dbm=%s", __FUNCTION__, cmd);
+
+ dbm = strtol(cmd, &endptr, 10);
+ if (*endptr || dbm < 0) {
+ wpa_printf(MSG_ERROR, "%s: invalid dbm %d", __FUNCTION__, dbm);
+ return -EINVAL;
+ }
+ mbm = dbm * 100;
+ if (mbm < 0) { // integer overflow
+ wpa_printf(MSG_ERROR, "%s: invalid mbm %d", __FUNCTION__, mbm);
+ return -EINVAL;
+ }
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+ NL80211_TX_POWER_LIMITED) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm)) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (!ret)
+ return 0;
+
+ wpa_printf(MSG_ERROR, "%s: Failed set_tx_power dbm=%d, ret=%d",
+ __FUNCTION__, dbm, ret);
+ return ret;
+}
+
+/* Return type for setBand*/
+enum {
+ SEND_CHANNEL_CHANGE_EVENT = 0,
+ DO_NOT_SEND_CHANNEL_CHANGE_EVENT,
+};
+
+typedef struct android_wifi_priv_cmd {
+ char *buf;
+ int used_len;
+ int total_len;
+} android_wifi_priv_cmd;
+
+static int drv_errors = 0;
+
+static void wpa_driver_notify_country_change(void *ctx, char *cmd)
+{
+ if ((os_strncasecmp(cmd, "COUNTRY", 7) == 0) ||
+ (os_strncasecmp(cmd, "SETBAND", 7) == 0)) {
+ union wpa_event_data event;
+
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
+ event.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
+ if (os_strlen(cmd) > 9) {
+ event.channel_list_changed.alpha2[0] = cmd[8];
+ event.channel_list_changed.alpha2[1] = cmd[9];
+ }
+ } else {
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ }
+ wpa_supplicant_event(ctx, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+}
+
+static struct remote_sta_info g_sta_info = {0};
+static struct bss_info g_bss_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(DEFAULT_IFNAME);
+
+ 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 nlattr *tb_vendor[GET_STATION_INFO_MAX + 1];
+ struct nlattr *attr, *attr1, *attr2;
+ u8 *beacon_ies = NULL;
+ size_t beacon_ies_len = 0;
+ u8 seg1;
+
+ g_bss_info.oui[0] = (OUI_QCA) & 0xFF;
+ g_bss_info.oui[1] = ((OUI_QCA)>>8) & 0xFF;
+ g_bss_info.oui[2] = ((OUI_QCA)>>16) & 0xFF;
+
+ nla_parse(tb_vendor, 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(g_bss_info.ssid, nla_data(tb1[NL80211_ATTR_SSID]),
+ nla_len(tb1[NL80211_ATTR_SSID]));
+ g_bss_info.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(g_bss_info.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]) {
+ g_bss_info.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]) {
+ g_bss_info.noise =
+ nla_get_u8(tb2[NL80211_SURVEY_INFO_NOISE]);
+ g_bss_info.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]) {
+ g_bss_info.rssi =
+ nla_get_u8(tb2[NL80211_STA_INFO_SIGNAL]);
+ g_bss_info.rssi -= 100;
+ } else {
+ wpa_printf(MSG_ERROR,"NL80211_STA_INFO_SIGNAL not found");
+ }
+ g_bss_info.snr = g_bss_info.rssi - g_bss_info.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]) {
+ g_bss_info.data_rate = nla_get_u32(
+ tb3[NL80211_RATE_INFO_BITRATE32])/10;
+ } else if (tb3[NL80211_RATE_INFO_BITRATE]) {
+ g_bss_info.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[GET_STATION_INFO_AKM]) {
+ g_bss_info.akm = nla_get_u32(
+ tb_vendor[GET_STATION_INFO_AKM]);
+ }
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE])
+ g_bss_info.mode_80211 = nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_802_11_MODE]);
+
+ 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);
+
+ switch (info->vht_op_info_chwidth) {
+ case CHANWIDTH_USE_HT:
+ if (attr1) {
+ struct ieee80211_ht_operation *info;
+
+ info = nla_data(attr1);
+ g_bss_info.bw = info->ht_param ? 40:20;
+ }
+ break;
+ case CHANWIDTH_80MHZ:
+ seg1 = info->vht_op_info_chan_center_freq_seg1_idx;
+ if (seg1)
+ /* Notifying 80P80 also as bandwidth = 160 */
+ g_bss_info.bw = 160;
+ else
+ g_bss_info.bw = 80;
+ break;
+ case CHANWIDTH_160MHZ:
+ g_bss_info.bw = 160;
+ break;
+ case CHANWIDTH_80P80MHZ:
+ g_bss_info.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);
+
+ g_bss_info.bw = info->ht_param ? 40:20;
+ } else
+ g_bss_info.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];
+ switch (ch_bw) {
+ case CHANWIDTH_USE_HT:
+ /* TO DO */
+ break;
+ case CHANWIDTH_80MHZ:
+ seg1 = opr[HE_OPER_VHT_CENTER_FRQ_SEG1_OFFSET];
+ if (seg1)
+ /* Notifying 80P80 also as bandwidth = 160 */
+ g_bss_info.bw = 160;
+ else
+ g_bss_info.bw = 80;
+ break;
+ case CHANWIDTH_160MHZ:
+ g_bss_info.bw = 160;
+ break;
+ case CHANWIDTH_80P80MHZ:
+ g_bss_info.bw = 160;
+ break;
+ default:
+ break;
+ }
+ 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 HE_CHANWIDTH_20MHZ:
+ g_bss_info.bw = 20;
+ break;
+ case HE_CHANWIDTH_40MHZ:
+ g_bss_info.bw = 40;
+ break;
+ case HE_CHANWIDTH_80MHZ:
+ g_bss_info.bw = 80;
+ break;
+ case HE_CHANWIDTH_160MHZ:
+ /* Notifying 80P80 also as bandwidth = 160 */
+ g_bss_info.bw = 160;
+ break;
+ default:
+ wpa_printf(MSG_ERROR,"Invalid channel width received : %u", ch_bw);
+ }
+ }
+
+ }
+
+parse_beacon_ies:
+ attr = tb_vendor[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[GET_STATION_INFO_DRIVER_DISCONNECT_REASON]) {
+ g_bss_info.disc_reasn_code = nla_get_u32(tb_vendor[
+ 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 %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ g_bss_info.oui[0],
+ g_bss_info.oui[1],
+ g_bss_info.oui[2],
+ g_bss_info.ssid,
+ g_bss_info.channel,
+ g_bss_info.bw,
+ g_bss_info.rssi,
+ g_bss_info.data_rate,
+ g_bss_info.mode_80211,
+ -1,
+ -1,
+ -1,
+ g_bss_info.snr,
+ g_bss_info.noise,
+ g_bss_info.akm,
+ g_bss_info.roaming_count,
+ -1,
+ -1,
+ -1,
+ -1,
+ g_bss_info.disc_reasn_code,
+ info->country,
+ g_bss_info.ani_level,
+ -1,
+ -1,
+ -1,
+ g_bss_info.roam_trigger_reason,
+ g_bss_info.roam_fail_reason,
+ g_bss_info.roam_invoke_fail_reason,
+ g_bss_info.tsf_out_of_sync_count,
+ g_bss_info.latest_tx_power,
+ g_bss_info.latest_tx_rate,
+ g_bss_info.target_power_24g_1mbps,
+ g_bss_info.target_power_24g_6mbps,
+ g_bss_info.target_power_5g_6mbps);
+
+ return 0;
+}
+
+static int parse_get_feature_info(struct resp_info *info, struct nlattr *vendata,
+ int datalen)
+{
+ struct nlattr *tb_vendor[NUM_QCA_WLAN_VENDOR_FEATURES + 1];
+ struct nlattr *attr;
+ nla_parse(tb_vendor, NUM_QCA_WLAN_VENDOR_FEATURES,
+ vendata, datalen, NULL);
+ attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
+ if (attr) {
+ snprintf(info->reply_buf, info->reply_buf_len, "%u",
+ nla_get_u32(attr));
+ wpa_printf(MSG_DEBUG, "%s: driver supported feature info = %s",
+ __func__, info->reply_buf);
+ } else {
+ snprintf(info->reply_buf, info->reply_buf_len, "FAIL");
+ return -1;
+ }
+ 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;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
+ os_memset(info->reply_buf, 0, info->reply_buf_len);
+ parse_get_feature_info(info, vendata, datalen);
+ 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;
+}
+
+int wpa_driver_nl80211_oem_event(struct wpa_driver_nl80211_data *drv,
+ u32 vendor_id, u32 subcmd,
+ u8 *data, size_t len)
+{
+ int ret = -1, lib_n;
+ if (wpa_driver_oem_initialize(&oem_cb_table) != WPA_DRIVER_OEM_STATUS_FAILURE &&
+ oem_cb_table) {
+ for (lib_n = 0;
+ oem_cb_table[lib_n].wpa_driver_driver_cmd_oem_cb != NULL;
+ lib_n++) {
+ if(oem_cb_table[lib_n].wpa_driver_nl80211_driver_oem_event) {
+ ret = oem_cb_table[lib_n].wpa_driver_nl80211_driver_oem_event(
+ drv, vendor_id,subcmd, data, len);
+ if (ret == WPA_DRIVER_OEM_STATUS_SUCCESS ) {
+ break;
+ } else if (ret == WPA_DRIVER_OEM_STATUS_ENOSUPP) {
+ continue;
+ } else if (ret == WPA_DRIVER_OEM_STATUS_FAILURE) {
+ wpa_printf(MSG_DEBUG, "%s: Received error: %d",
+ __func__, ret);
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int wpa_driver_restart_csi(struct i802_bss *bss, int *status);
+
+int wpa_driver_nl80211_driver_event(struct wpa_driver_nl80211_data *drv,
+ u32 vendor_id, u32 subcmd,
+ u8 *data, size_t len)
+{
+ int ret = -1;
+ int status = -1;
+ struct i802_bss *bss;
+
+ ret = wpa_driver_nl80211_oem_event(drv, vendor_id, subcmd,
+ data, len);
+
+ if(ret != WPA_DRIVER_OEM_STATUS_ENOSUPP)
+ return ret;
+
+ switch(subcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT:
+ ret = wpa_driver_twt_async_resp_event(drv, vendor_id, subcmd,
+ data, len);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH:
+ if(g_csi_param.current_state == CSI_STATE_START) {
+ bss = get_bss_ifindex(drv, drv->ifindex);
+ if(bss == NULL) {
+ wpa_printf(MSG_DEBUG, "%s: bss is NULL",
+ __func__);
+ break;
+ }
+ if(wpa_driver_restart_csi(bss, &status))
+ wpa_printf(MSG_DEBUG, "csi_restart failed %d",
+ status);
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+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;
+}
+
+/*
+ * Client can send the cell switch mode in below format
+ *
+ * SETCELLSWITCHMODE <cs mode>
+ *
+ * examples:
+ * For Default Mode - "SETCELLSWITCHMODE 0"
+ * To Disable Roaming - "SETCELLSWITCHMODE 1"
+ * For Partial Scan - "SETCELLSWITCHMODE 2"
+ */
+static int parse_and_populate_setcellswitchmode(struct nl_msg *nlmsg,
+ char *cmd)
+{
+ uint32_t all_trigger_bitmap, scan_scheme_bitmap;
+ uint32_t cellswm;
+ struct nlattr *config;
+
+ cellswm = atoi(cmd);
+ if (cellswm < 0 || cellswm > 2) {
+ wpa_printf(MSG_ERROR,"Invalid cell switch mode: %d", cellswm);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "cell switch mode: %d", cellswm);
+
+ all_trigger_bitmap = QCA_ROAM_TRIGGER_REASON_PER |
+ QCA_ROAM_TRIGGER_REASON_BEACON_MISS |
+ QCA_ROAM_TRIGGER_REASON_POOR_RSSI |
+ QCA_ROAM_TRIGGER_REASON_BETTER_RSSI |
+ QCA_ROAM_TRIGGER_REASON_PERIODIC |
+ QCA_ROAM_TRIGGER_REASON_DENSE |
+ QCA_ROAM_TRIGGER_REASON_BTM |
+ QCA_ROAM_TRIGGER_REASON_BSS_LOAD |
+ QCA_ROAM_TRIGGER_REASON_USER_TRIGGER |
+ QCA_ROAM_TRIGGER_REASON_DEAUTH |
+ QCA_ROAM_TRIGGER_REASON_IDLE |
+ QCA_ROAM_TRIGGER_REASON_TX_FAILURES |
+ QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN;
+
+ scan_scheme_bitmap = QCA_ROAM_TRIGGER_REASON_PER |
+ QCA_ROAM_TRIGGER_REASON_BEACON_MISS |
+ QCA_ROAM_TRIGGER_REASON_POOR_RSSI |
+ QCA_ROAM_TRIGGER_REASON_BSS_LOAD |
+ QCA_ROAM_TRIGGER_REASON_BTM;
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET) ||
+ nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID, 1)) {
+ wpa_printf(MSG_ERROR,"Failed to put: roam_subcmd/REQ_ID");
+ }
+
+ config = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL);
+ if (config == NULL)
+ goto fail;
+
+ switch (cellswm){
+ case 0:
+ if (nla_put_u32(nlmsg, QCA_ATTR_ROAM_CONTROL_TRIGGERS, all_trigger_bitmap)) {
+ wpa_printf(MSG_ERROR,"Failed to set: ROAM_CONTROL_TRIGGERS");
+ goto fail;
+ }
+ break;
+ case 1:
+ if (nla_put_u32(nlmsg, QCA_ATTR_ROAM_CONTROL_TRIGGERS, 0)) {
+ wpa_printf(MSG_ERROR,"Failed to unset: ROAM_CONTROL_TRIGGERS");
+ goto fail;
+ }
+ break;
+ case 2:
+ if (nla_put_u32(nlmsg, QCA_ATTR_ROAM_CONTROL_TRIGGERS, all_trigger_bitmap) ||
+ nla_put_u32(nlmsg, QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS, scan_scheme_bitmap)) {
+ wpa_printf(MSG_ERROR,"Failed to set: ROAM_CONTROL_TRIGGERS_SCAN_SCHEME");
+ goto fail;
+ }
+ break;
+ }
+ nla_nest_end(nlmsg, config);
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+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;
+ case SETCELLSWITCHMODE:
+ if (parse_and_populate_setcellswitchmode(nlmsg, cmd) != 0) {
+ wpa_printf(MSG_ERROR, "Failed to populate nlmsg");
+ 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_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;
+
+ 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;
+ 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;
+ }
+
+ left -= ie_len;
+ pos += ie_len;
+ }
+
+ if (left)
+ wpa_printf(MSG_ERROR,"parse error, left = %d", left);
+}
+
+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 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 %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ 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,
+ sta_info->ani_level,
+ -1,
+ -1,
+ -1,
+ sta_info->roam_trigger_reason,
+ sta_info->roam_fail_reason,
+ sta_info->roam_invoke_fail_reason,
+ sta_info->tsf_out_of_sync_count,
+ sta_info->latest_tx_power,
+ sta_info->latest_tx_rate,
+ sta_info->target_power_24g_1mbps,
+ sta_info->target_power_24g_6mbps,
+ sta_info->target_power_5g_6mbps);
+ 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 %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ 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,
+ sta_info->ani_level,
+ -1,
+ -1,
+ -1,
+ sta_info->roam_trigger_reason,
+ sta_info->roam_fail_reason,
+ sta_info->roam_invoke_fail_reason,
+ sta_info->tsf_out_of_sync_count,
+ sta_info->latest_tx_power,
+ sta_info->latest_tx_rate,
+ sta_info->target_power_24g_1mbps,
+ sta_info->target_power_24g_6mbps,
+ sta_info->target_power_5g_6mbps);
+ } 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];
+ 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) {
+ wpa_printf(MSG_ERROR,"Invalid arg");
+ 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 parse error");
+ 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[GET_STATION_INFO_REMOTE_LAST_RX_RATE]) {
+ g_sta_info.data_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[GET_STATION_INFO_REMOTE_RX_RETRY_COUNT]) {
+ g_sta_info.rx_retry_pkts +=
+ 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[GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT]) {
+ g_sta_info.rx_bcmc_pkts +=
+ 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[GET_STATION_INFO_REMOTE_CH_WIDTH]) {
+ g_sta_info.bandwidth =
+ nla_get_u8(tb_vendor[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[GET_STATION_INFO_REMOTE_SUPPORTED_MODE]) {
+ g_sta_info.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[GET_STATION_INFO_ASSOC_REQ_IES]) {
+ assoc_req_ie =
+ nla_data(tb_vendor[GET_STATION_INFO_ASSOC_REQ_IES]);
+ assoc_req_ie_len =
+ 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_vendor_sta_info++;
+
+ 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, GET_STA_INFO_MAX,
+ 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);
+ }
+
+ 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);
+ }
+
+ if (tb_vendor[GET_STA_INFO_ANI_LEVEL]) {
+ g_sta_info.ani_level =
+ nla_get_u32(tb_vendor[GET_STA_INFO_ANI_LEVEL]);
+ wpa_printf(MSG_INFO,"ani_level %d", g_sta_info.ani_level);
+ }
+
+ if (tb_vendor[GET_STA_INFO_ROAM_TRIGGER_REASON]) {
+ g_sta_info.roam_trigger_reason =
+ nla_get_u32(tb_vendor[GET_STA_INFO_ROAM_TRIGGER_REASON]);
+ wpa_printf(MSG_INFO,"roam_trigger_reason %d", g_sta_info.roam_trigger_reason);
+ }
+
+ if (tb_vendor[GET_STA_INFO_ROAM_FAIL_REASON]) {
+ g_sta_info.roam_fail_reason =
+ nla_get_u32(tb_vendor[GET_STA_INFO_ROAM_FAIL_REASON]);
+ wpa_printf(MSG_INFO,"roam_fail_reason %d", g_sta_info.roam_fail_reason);
+ }
+
+ if (tb_vendor[GET_STA_INFO_ROAM_INVOKE_FAIL_REASON]) {
+ g_sta_info.roam_invoke_fail_reason =
+ nla_get_u32(tb_vendor[GET_STA_INFO_ROAM_INVOKE_FAIL_REASON]);
+ wpa_printf(MSG_INFO,"roam_invoke_fail_reason %d", g_sta_info.roam_invoke_fail_reason);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT]) {
+ g_sta_info.tsf_out_of_sync_count =
+ nla_get_u32(tb_vendor[GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT]);
+ wpa_printf(MSG_INFO,"tsf_out_of_sync_count %d", g_sta_info.tsf_out_of_sync_count);
+ }
+
+ if (tb_vendor[GET_STA_INFO_LATEST_TX_POWER]) {
+ g_sta_info.latest_tx_power =
+ nla_get_u32(tb_vendor[GET_STA_INFO_LATEST_TX_POWER]);
+ wpa_printf(MSG_INFO,"latest_tx_power %d", g_sta_info.latest_tx_power);
+ }
+
+ if (tb_vendor[GET_STA_INFO_LATEST_TX_RATE]) {
+ g_sta_info.latest_tx_rate =
+ nla_get_u32(tb_vendor[GET_STA_INFO_LATEST_TX_RATE]);
+ wpa_printf(MSG_INFO,"latest_tx_rate %d", g_sta_info.latest_tx_rate);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TARGET_POWER_24G_1MBPS]) {
+ g_sta_info.target_power_24g_1mbps =
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_POWER_24G_1MBPS]);
+ wpa_printf(MSG_INFO,"target_power_24g_1mbps %d", g_sta_info.target_power_24g_1mbps);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TARGET_POWER_24G_6MBPS]) {
+ g_sta_info.target_power_24g_6mbps =
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_POWER_24G_6MBPS]);
+ wpa_printf(MSG_INFO,"target_power_24g_6mbps %d", g_sta_info.target_power_24g_6mbps);
+ }
+
+ if (tb_vendor[GET_STA_INFO_TARGET_POWER_5G_6MBPS]) {
+ g_sta_info.target_power_5g_6mbps =
+ nla_get_u32(tb_vendor[GET_STA_INFO_TARGET_POWER_5G_6MBPS]);
+ wpa_printf(MSG_INFO,"target_power_5g_6mbps %d", g_sta_info.target_power_5g_6mbps);
+ }
+
+ if (tb_vendor[GET_STA_INFO_LATEST_RIX]) {
+ g_sta_info.latest_rix =
+ nla_get_u32(tb_vendor[GET_STA_INFO_LATEST_RIX]);
+ wpa_printf(MSG_INFO,"latest_rix %d", g_sta_info.latest_rix);
+ }
+
+
+ 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;
+}
+
+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);
+ os_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,
+ int *status, bool *new_cmd)
+{
+ 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);
+
+ *new_cmd = true;
+
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO);
+ 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, GET_STA_INFO_MAC,
+ MAC_ADDR_LEN, mac)) {
+ wpa_printf(MSG_ERROR,"Failed to put GET_STA_INFO_MAC");
+ 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, retrying with legacy command", *status);
+ *new_cmd = false;
+ return wpa_driver_send_get_sta_info_legacy_cmd(bss,mac,status);
+ }
+
+ 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;
+ }
+
+ 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_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;
+ int ret, total_ret = 0;
+
+ if(bss->drv && bss->drv->nlmode != NL80211_IFTYPE_AP) {
+ wpa_printf(MSG_ERROR,"Not a hapd interface");
+ return -1;
+ }
+
+ 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_get_sta_info(bss, sta->addr, status);
+ if (ret < 0)
+ return ret;
+ sta = sta->next;
+ total_ret += ret;
+ }
+
+ wpa_printf(MSG_INFO,"All STAs information completed");
+
+ 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];
+ int ret;
+
+ 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;
+ 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;
+ }
+
+ 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)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ int *param = arg;
+ struct nlattr *nl_vendor;
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ nl_vendor = tb[NL80211_ATTR_VENDOR_DATA];
+ if (!nl_vendor || nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
+ nla_data(nl_vendor), nla_len(nl_vendor), NULL)) {
+ wpa_printf(MSG_ERROR, "%s: No vendor data found", __func__);
+ return NL_SKIP;
+ }
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA])
+ *param = (int) nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA]);
+ else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL])
+ *param = (int) nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]);
+ else
+ wpa_printf(MSG_ERROR, "%s: failed to parse data", __func__);
+
+ return NL_SKIP;
+}
+
+static int wpa_driver_cmd_get_thermal_info(struct i802_bss *bss, int *result, int attr)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg = NULL;
+ struct nlattr *params = NULL;
+ int ret = 0;
+
+ 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_THERMAL_CMD) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE, attr)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+
+ nla_nest_end(msg, params);
+ ret = send_and_recv_msgs(drv, msg, thermal_info_handler, result, NULL, NULL);
+ if (!ret)
+ return 0;
+ wpa_printf(MSG_ERROR, "%s: Failed get thermal info, ret=%d(%s)",
+ __func__, ret, strerror(-ret));
+ return ret;
+}
+
+static int get_scan_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *msg_hdr;
+ struct nlattr *attr[NL80211_ATTR_MAX + 1];
+ struct resp_info *info = (struct resp_info *)arg;
+ struct nlattr *bss_attr[NL80211_BSS_MAX + 1];
+ char *bssid;
+ static struct nla_policy get_scan_policy[NL80211_BSS_MAX + 1] = {
+ [NL80211_BSS_BSSID] = {},
+ [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+ [NL80211_BSS_STATUS] = { .type = NLA_U32 },
+ [NL80211_BSS_CHAN_WIDTH] = { .type = NLA_U32 },
+ };
+
+ if (!info) {
+ wpa_printf(MSG_DEBUG, "resp_info is NULL");
+ return NL_SKIP;
+ }
+
+ msg_hdr = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
+ nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(msg_hdr, 0),
+ genlmsg_attrlen(msg_hdr, 0), NULL);
+
+ if (!attr[NL80211_ATTR_BSS]) {
+ wpa_printf(MSG_DEBUG, "no bss info");
+ return NL_SKIP;
+ }
+
+ if (nla_parse_nested(bss_attr, NL80211_BSS_MAX,
+ attr[NL80211_ATTR_BSS],
+ get_scan_policy)) {
+ wpa_printf(MSG_DEBUG, "parse bss attr fail");
+ return NL_SKIP;
+ }
+
+ if (!bss_attr[NL80211_BSS_BSSID])
+ return NL_SKIP;
+
+ if (!bss_attr[NL80211_BSS_STATUS])
+ return NL_SKIP;
+
+ if (nla_get_u32(bss_attr[NL80211_BSS_STATUS]) !=
+ NL80211_BSS_STATUS_ASSOCIATED)
+ return NL_SKIP;
+
+ bssid = nla_data(bss_attr[NL80211_BSS_BSSID]);
+ os_memcpy(g_csi_param.connected_bssid, bssid, MAC_ADDR_LEN);
+
+ wpa_printf(MSG_DEBUG, "get connected bss");
+ if (bss_attr[NL80211_BSS_FREQUENCY])
+ wpa_printf(MSG_DEBUG, "freq %d", nla_get_u32(bss_attr[NL80211_BSS_FREQUENCY]));
+
+ if (bss_attr[NL80211_BSS_CHAN_WIDTH])
+ wpa_printf(MSG_DEBUG, "BW %d", nla_get_u32(bss_attr[NL80211_BSS_CHAN_WIDTH]));
+
+ return 0;
+}
+
+static int wpa_driver_send_get_scan_cmd(struct i802_bss *bss, int *status)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *nlmsg;
+ struct resp_info info;
+
+ os_memset(g_csi_param.connected_bssid, 0xff, MAC_ADDR_LEN);
+ nlmsg = prepare_nlmsg(drv, bss->ifname, NL80211_CMD_GET_SCAN, 0, NLM_F_DUMP);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "Failed to allocate nl message");
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+ get_scan_handler, &info);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nl message with err %d", *status);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
+
+static int wpa_driver_start_csi_capture(struct i802_bss *bss, int *status,
+ int transport_mode)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *nlmsg;
+ struct nlattr *attr, *attr_table, *attr_entry;
+ char ta_mask[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "Failed to allocate nl message");
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!attr) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION,
+ ENHANCED_CFR_VER)) {
+ wpa_printf(MSG_ERROR, "Failed to csi version");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE,
+ transport_mode)) {
+ wpa_printf(MSG_ERROR, "Failed to set transport mode");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_flag(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE)) {
+ wpa_printf(MSG_ERROR, "Failed to csi enable flag");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP,
+ CSI_GROUP_BITMAP)) {
+ wpa_printf(MSG_ERROR, "Failed to csi group bitmap");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE,
+ QCA_WLAN_VENDOR_CFR_TA_RA)) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ attr_table = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE);
+ if (!attr_table) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ attr_entry = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY);
+ if (!attr_entry) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER,
+ CSI_DEFAULT_GROUP_ID)) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER,
+ CSI_MGMT_BEACON)) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA,
+ MAC_ADDR_LEN, g_csi_param.connected_bssid)) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK,
+ MAC_ADDR_LEN, ta_mask)) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+ nla_nest_end(nlmsg, attr_entry);
+ nla_nest_end(nlmsg, attr_table);
+ nla_nest_end(nlmsg, attr);
+
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nl message with err %d", *status);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ g_csi_param.current_state = CSI_STATE_START;
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
+
+static int wpa_driver_stop_csi_capture(struct i802_bss *bss, int *status)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *nlmsg;
+ struct nlattr *attr;
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "Failed to allocate nl message");
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!attr) {
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION,
+ ENHANCED_CFR_VER)) {
+ wpa_printf(MSG_ERROR, "Failed to csi version");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ wpa_printf(MSG_DEBUG, "send stop csi cmd");
+ nla_nest_end(nlmsg, attr);
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nl message with err %d", *status);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ g_csi_param.current_state = CSI_STATE_STOP;
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
+
+static void stop_csi_callback(int nsec)
+{
+ int status = 0;
+
+ wpa_printf(MSG_DEBUG, "enter %s, nsec %d", __func__, nsec);
+
+ wpa_driver_stop_csi_capture(g_csi_param.bss, &status);
+ if (status)
+ wpa_printf(MSG_ERROR, "Stop CSI failed");
+}
+
+static int wpa_driver_handle_csi_cmd(struct i802_bss *bss, char *cmd,
+ char *buf, size_t buf_len,
+ int *status)
+{
+ int csi_duration = -1;
+ int transport_mode = -1;
+ char *next_arg;
+
+ cmd = skip_white_space(cmd);
+ wpa_printf(MSG_DEBUG, "cmd:%s", cmd);
+ if (os_strncasecmp(cmd, "start", 5) == 0) {
+ next_arg = get_next_arg(cmd);
+ csi_duration = atoi(next_arg);
+
+ if (csi_duration < 0) {
+ wpa_printf(MSG_ERROR, "Invalid duration");
+ snprintf(buf, buf_len, "FAIL, Invalid duration");
+ *status = CSI_STATUS_REJECTED;
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ wpa_driver_send_get_scan_cmd(bss, status);
+ if (g_csi_param.connected_bssid[0] == 0xff) {
+ wpa_printf(MSG_DEBUG, "Not connected");
+ snprintf(buf, buf_len, "FAIL, Not connected");
+ *status = CSI_STATUS_REJECTED;
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (g_csi_param.current_state == CSI_STATE_START) {
+ wpa_driver_stop_csi_capture(bss, status);
+ alarm(0);
+ }
+
+ g_csi_param.bss = bss;
+ cmd += 6;
+ next_arg = get_next_arg(cmd);
+ if (*next_arg != '\0' && *next_arg == ' ')
+ transport_mode = atoi(next_arg);
+
+ if (transport_mode == 1 || transport_mode == -1)
+ transport_mode = 1;
+ g_csi_param.transport_mode = transport_mode;
+
+ wpa_driver_start_csi_capture(bss, status, transport_mode);
+ if (*status == 0 && csi_duration > 0) {
+ signal(SIGALRM, stop_csi_callback);
+ alarm(csi_duration);
+ wpa_printf(MSG_DEBUG, "set alarm %ds done", csi_duration);
+ }
+ } else if (os_strncasecmp(cmd, "stop", 4) == 0) {
+ if (g_csi_param.current_state != CSI_STATE_START)
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+
+ wpa_driver_stop_csi_capture(bss, status);
+ wpa_printf(MSG_DEBUG, "stop csi cmd");
+ } else {
+ wpa_printf(MSG_ERROR, "invalid command");
+ *status = CSI_STATUS_REJECTED;
+ snprintf(buf, buf_len, "FAIL, Invalid command");
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
+
+static int wpa_driver_restart_csi(struct i802_bss *bss, int *status)
+{
+ wpa_driver_send_get_scan_cmd(bss, status);
+ if (g_csi_param.connected_bssid[0] == 0xff) {
+ wpa_printf(MSG_DEBUG, "%s: Not connected", __func__);
+ *status = CSI_STATUS_REJECTED;
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+ /* Stop CSI capture on previous bss */
+ if(wpa_driver_stop_csi_capture(g_csi_param.bss, status)) {
+ wpa_printf(MSG_DEBUG, "%s: csi stop failed", __func__);
+ }
+ g_csi_param.bss = bss;
+ if(wpa_driver_start_csi_capture(g_csi_param.bss, status,
+ g_csi_param.transport_mode)) {
+ *status = CSI_STATUS_REJECTED;
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+ *status = CSI_STATUS_SUCCESS;
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
+
+/**
+ * twt_status_to_string() - Mapping twt response status into string
+ * @status: enum qca_wlan_vendor_twt_status values
+ *
+ * This function will map the twt response status into corresponding
+ * string.
+ *
+ * Return: pointer to the string
+ */
+static const char *twt_status_to_string(enum qca_wlan_vendor_twt_status status)
+{
+ switch (status) {
+ case QCA_WLAN_VENDOR_TWT_STATUS_OK:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_OK";
+ case QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED";
+ case QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID";
+ case QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY";
+ case QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST";
+ case QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED";
+ case QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM";
+ case QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY";
+ case QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE";
+ case QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK";
+ case QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE";
+ case QCA_WLAN_VENDOR_TWT_STATUS_DENIED:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_DENIED";
+ case QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR";
+ case QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED";
+ case QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID";
+ case QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE";
+ case QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE";
+ case QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE:
+ return "QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE";
+ default:
+ return "INVALID TWT STATUS";
+ }
+}
+
+/**
+ * check_for_twt_cmd() - Check if the command string is a TWT command
+ * @cmd: Command string
+ *
+ * This function will identify a TWT operation in the command string
+ * and return one of the values in enum qca_wlan_twt_operation.
+ *
+ * Return: A valid TWT opertion if found, or error if not found
+ *
+ */
+static int check_for_twt_cmd(char **cmd)
+{
+ if (os_strncasecmp(*cmd, TWT_SETUP_STR, TWT_SETUP_STRLEN) == 0) {
+ *cmd += (TWT_SETUP_STRLEN + 1);
+ return QCA_WLAN_TWT_SET;
+ } else if (os_strncasecmp(*cmd, TWT_TERMINATE_STR,
+ TWT_TERMINATE_STR_LEN) == 0) {
+ *cmd += (TWT_TERMINATE_STR_LEN + 1);
+ return QCA_WLAN_TWT_TERMINATE;
+ } else if (os_strncasecmp(*cmd, TWT_PAUSE_STR, TWT_PAUSE_STR_LEN) == 0) {
+ *cmd += (TWT_PAUSE_STR_LEN + 1);
+ return QCA_WLAN_TWT_SUSPEND;
+ } else if (os_strncasecmp(*cmd, TWT_RESUME_STR, TWT_RESUME_STR_LEN) == 0) {
+ *cmd += (TWT_RESUME_STR_LEN + 1);
+ return QCA_WLAN_TWT_RESUME;
+ } else if (os_strncasecmp(*cmd, TWT_GET_PARAMS_STR,
+ TWT_GET_PARAMS_STR_LEN) == 0) {
+ *cmd += (TWT_GET_PARAMS_STR_LEN + 1);
+ return QCA_WLAN_TWT_GET;
+ } else if (os_strncasecmp(*cmd, TWT_NUDGE_STR,
+ TWT_NUDGE_STR_LEN) == 0) {
+ *cmd += (TWT_NUDGE_STR_LEN + 1);
+ return QCA_WLAN_TWT_NUDGE;
+ } else if (os_strncasecmp(*cmd, TWT_GET_STATS_STR,
+ TWT_GET_STATS_STR_LEN) == 0) {
+ *cmd += (TWT_GET_STATS_STR_LEN + 1);
+ return QCA_WLAN_TWT_GET_STATS;
+ } else if (os_strncasecmp(*cmd, TWT_CLEAR_STATS_STR,
+ TWT_CLEAR_STATS_STR_LEN) == 0) {
+ *cmd += (TWT_CLEAR_STATS_STR_LEN + 1);
+ return QCA_WLAN_TWT_CLEAR_STATS;
+ } else if (os_strncasecmp(*cmd, TWT_GET_CAP_STR,
+ TWT_GET_CAP_STR_LEN) == 0) {
+ *cmd += (TWT_GET_CAP_STR_LEN + 1);
+ return QCA_WLAN_TWT_GET_CAPABILITIES;
+ } else if (os_strncasecmp(*cmd, TWT_SET_PARAM_STR,
+ TWT_SET_PARAM_STR_LEN) == 0) {
+ *cmd += (TWT_SET_PARAM_STR_LEN + 1);
+ return QCA_WLAN_TWT_SET_PARAM;
+ } else {
+ wpa_printf(MSG_DEBUG, "Not a TWT command");
+ return TWT_CMD_NOT_EXIST;
+ }
+}
+
+static u64 get_u64_from_string(char *cmd_string, int *ret)
+{
+ u64 val = 0;
+ char *cmd = cmd_string;
+
+ while (*cmd != ' ')
+ cmd++;
+
+ *ret = 0;
+ errno = 0;
+ val = strtoll(cmd_string, NULL, 10);
+ if (errno == ERANGE || (errno != 0 && val == 0)) {
+ wpa_printf(MSG_ERROR, "invalid value");
+ *ret = -EINVAL;
+ }
+ return val;
+}
+
+
+static u32 get_u32_from_string(char *cmd_string, int *ret)
+{
+ u32 val = 0;
+ char *cmd = cmd_string;
+
+ while (*cmd != ' ')
+ cmd++;
+
+ *ret = 0;
+ errno = 0;
+ val = strtol(cmd_string, NULL, 10);
+ if (errno == ERANGE || (errno != 0 && val == 0)) {
+ wpa_printf(MSG_ERROR, "invalid value");
+ *ret = -EINVAL;
+ }
+ return val;
+}
+
+static u8 get_u8_from_string(char *cmd_string, int *ret)
+{
+ char *cmd = cmd_string;
+ u8 val = 0;
+
+ while (*cmd != ' ')
+ cmd++;
+
+ *ret = 0;
+ errno = 0;
+ val = strtol(cmd_string, NULL, 10) & 0xFF;
+ if (errno == ERANGE || (errno != 0 && val == 0)) {
+ wpa_printf(MSG_ERROR, "invalid value");
+ *ret = -EINVAL;
+ }
+ return val;
+}
+
+char *move_to_next_str(char *cmd)
+{
+ if (*cmd == '\0')
+ return cmd;
+
+ while (*cmd != ' ') {
+ cmd++;
+ if (*cmd == '\0')
+ return cmd;
+ }
+
+ while (*cmd == ' ')
+ cmd++;
+
+ return cmd;
+}
+
+static int is_binary(u8 value) {
+ if(value == 0 || value == 1)
+ return 0;
+ return -1;
+}
+
+static
+void print_setup_cmd_values(struct twt_setup_parameters *twt_setup_params)
+{
+ wpa_printf(MSG_DEBUG, "TWT: setup dialog_id: %x",
+ twt_setup_params->dialog_id);
+ wpa_printf(MSG_DEBUG, "TWT: setup req type: %d ",
+ twt_setup_params->req_type);
+ wpa_printf(MSG_DEBUG, "TWT: setup trig type: %d ",
+ twt_setup_params->trig_type);
+ wpa_printf(MSG_DEBUG, "TWT: setup flow type: 0x%x",
+ twt_setup_params->flow_type);
+ wpa_printf(MSG_DEBUG, "TWT: setup wake exp: 0x%x",
+ twt_setup_params->wake_intr_exp);
+ wpa_printf(MSG_DEBUG, "TWT: setup protection: 0x%x",
+ twt_setup_params->protection);
+ wpa_printf(MSG_DEBUG, "TWT: setup wake time: 0x%x",
+ twt_setup_params->wake_time);
+ wpa_printf(MSG_DEBUG, "TWT: setup wake dur: 0x%x",
+ twt_setup_params->wake_dur);
+ wpa_printf(MSG_DEBUG, "TWT: setup wake intr mantissa: 0x%x",
+ twt_setup_params->wake_intr_mantissa);
+ wpa_printf(MSG_DEBUG, "TWT: setup bcast: %d ",
+ twt_setup_params->bcast);
+ wpa_printf(MSG_DEBUG, "TWT: min wake intvl: %d ",
+ twt_setup_params->min_wake_intvl);
+ wpa_printf(MSG_DEBUG, "TWT: max wake intvl: %d ",
+ twt_setup_params->max_wake_intvl);
+ wpa_printf(MSG_DEBUG, "TWT: min wake duration: %d ",
+ twt_setup_params->min_wake_duration);
+ wpa_printf(MSG_DEBUG, "TWT: max wake duration: %d ",
+ twt_setup_params->max_wake_duration);
+ wpa_printf(MSG_DEBUG, "TWT: wake tsf: 0x%lx ",
+ twt_setup_params->wake_tsf);
+ wpa_printf(MSG_DEBUG, "TWT: announce timeout(in us): %u",
+ twt_setup_params->announce_timeout_us);
+}
+
+static int check_cmd_input(char *cmd_string)
+{
+ u32 cmd_string_len;
+
+ if (!cmd_string) {
+ wpa_printf(MSG_ERROR, "cmd string null");
+ return -EINVAL;
+ }
+
+ cmd_string_len = strlen(cmd_string);
+
+ wpa_printf(MSG_DEBUG, "TWT: cmd string - %s len = %u", cmd_string,
+ cmd_string_len);
+ if (cmd_string_len < DIALOG_ID_STR_LEN + SINGLE_SPACE_LEN +
+ SINGLE_DIGIT_LEN) {
+ wpa_printf(MSG_ERROR, "TWT: Dialog_id parameter missing");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * process_twt_setup_cmd_string() - Process a TWT setup command string
+ * @cmd: Command string
+ * @twt_setup_params: TWT setup parameters to fill
+ *
+ * This function parses the TWT setup command and populates twt_setup_params.
+ *
+ * Return: 0 on successs, error if invalid params are found
+ *
+ */
+static
+int process_twt_setup_cmd_string(char *cmd,
+ struct twt_setup_parameters *twt_setup_params)
+{
+ int ret = 0;
+
+ if (!twt_setup_params) {
+ wpa_printf(MSG_ERROR, "cmd or twt_setup_params null");
+ return -EINVAL;
+ }
+
+ if (check_cmd_input(cmd))
+ return -EINVAL;
+
+ wpa_printf(MSG_DEBUG, "process twt setup command string: %s", cmd);
+ while (*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += (DIALOG_ID_STR_LEN + 1);
+ twt_setup_params->dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (os_strncasecmp(cmd, REQ_TYPE_STR, REQ_TYPE_STR_LEN) == 0) {
+ cmd += (REQ_TYPE_STR_LEN + 1);
+ twt_setup_params->req_type = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (os_strncasecmp(cmd, TRIG_TYPE_STR, TRIG_TYPE_STR_LEN) == 0) {
+ cmd += (TRIG_TYPE_STR_LEN + 1);
+ twt_setup_params->trig_type = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (is_binary(twt_setup_params->trig_type)) {
+ wpa_printf(MSG_ERROR, "Invalid trigger type");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, FLOW_TYPE_STR, FLOW_TYPE_STR_LEN) == 0) {
+ cmd += (FLOW_TYPE_STR_LEN + 1);
+ twt_setup_params->flow_type = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (is_binary(twt_setup_params->flow_type)) {
+ wpa_printf(MSG_ERROR, "Invalid flow type");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, WAKE_INTR_EXP_STR, WAKE_INTR_EXP_STR_LEN) == 0) {
+ cmd += (WAKE_INTR_EXP_STR_LEN + 1);
+ twt_setup_params->wake_intr_exp = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (twt_setup_params->wake_intr_exp >
+ TWT_SETUP_WAKE_INTVL_EXP_MAX) {
+ wpa_printf(MSG_DEBUG, "Invalid wake_intr_exp %u",
+ twt_setup_params->wake_intr_exp);
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, PROTECTION_STR, PROTECTION_STR_LEN) == 0) {
+ cmd += (PROTECTION_STR_LEN + 1);
+ twt_setup_params->protection = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (is_binary(twt_setup_params->protection)) {
+ wpa_printf(MSG_ERROR, "Invalid protection value");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, WAKE_TIME_STR, WAKE_TIME_STR_LEN) == 0) {
+ cmd += (WAKE_TIME_STR_LEN + 1);
+ twt_setup_params->wake_time = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, WAKE_DUR_STR, WAKE_DUR_STR_LEN) == 0) {
+ cmd += (WAKE_DUR_STR_LEN + 1);
+ twt_setup_params->wake_dur = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (twt_setup_params->wake_dur == 0 ||
+ twt_setup_params->wake_dur > TWT_SETUP_WAKE_DURATION_MAX) {
+ wpa_printf(MSG_ERROR, "Invalid wake_dura_us %u",
+ twt_setup_params->wake_dur);
+ return -EINVAL;
+ }
+
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, WAKE_INTR_MANTISSA_STR,
+ WAKE_INTR_MANTISSA_STR_LEN) == 0) {
+ cmd += (WAKE_INTR_MANTISSA_STR_LEN + 1);
+ twt_setup_params->wake_intr_mantissa = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ if (twt_setup_params->wake_intr_mantissa >
+ TWT_SETUP_WAKE_INTVL_MANTISSA_MAX) {
+ wpa_printf(MSG_ERROR, "Invalid wake_intr_mantissa %u",
+ twt_setup_params->wake_intr_mantissa);
+ return -EINVAL;
+ }
+
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, BROADCAST_STR, BROADCAST_STR_LEN) == 0) {
+ cmd += (BROADCAST_STR_LEN + 1);
+ twt_setup_params->bcast = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (is_binary(twt_setup_params->bcast)) {
+ wpa_printf(MSG_ERROR, "Invalid broadcast value");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, MIN_WAKE_INTVL_STR, MIN_WAKE_INTVL_STR_LEN) == 0) {
+ cmd += (MIN_WAKE_INTVL_STR_LEN + 1);
+ twt_setup_params->min_wake_intvl = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, MAX_WAKE_INTVL_STR, MAX_WAKE_INTVL_STR_LEN) == 0) {
+ cmd += (MAX_WAKE_INTVL_STR_LEN + 1);
+ twt_setup_params->max_wake_intvl = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, MIN_WAKE_DUR_STR, MIN_WAKE_DUR_STR_LEN) == 0) {
+ cmd += (MIN_WAKE_DUR_STR_LEN + 1);
+ twt_setup_params->min_wake_duration = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, MAX_WAKE_DUR_STR, MAX_WAKE_DUR_STR_LEN) == 0) {
+ cmd += (MAX_WAKE_DUR_STR_LEN + 1);
+ twt_setup_params->max_wake_duration = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, WAKE_TSF_STR, WAKE_TSF_STR_LEN) == 0) {
+ cmd += (WAKE_TSF_STR_LEN + 1);
+ twt_setup_params->wake_tsf = get_u64_from_string(cmd, &ret);
+ if(ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (strncmp(cmd, ANNOUNCE_TIMEOUT_STR, ANNOUNCE_TIMEOUT_STR_LEN) == 0) {
+ cmd += (ANNOUNCE_TIMEOUT_STR_LEN + 1);
+ twt_setup_params->announce_timeout_us =
+ get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ print_setup_cmd_values(twt_setup_params);
+
+ return 0;
+}
+
+static
+int prepare_twt_setup_nlmsg(struct nl_msg *nlmsg,
+ struct twt_setup_parameters *twt_setup_params)
+{
+ struct nlattr *twt_attr;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_SET)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_SET");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ goto fail;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID,
+ twt_setup_params->dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ goto fail;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE,
+ twt_setup_params->req_type)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put req type");
+ goto fail;
+ }
+
+ if (twt_setup_params->trig_type) {
+ if (nla_put_flag(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER)
+ ) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put trig type");
+ goto fail;
+ }
+ }
+
+ /*0 - Announced/ 1 - Unannounced*/
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE,
+ twt_setup_params->flow_type)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put flow type");
+ goto fail;
+ }
+
+ if (nla_put_u8(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP,
+ twt_setup_params->wake_intr_exp)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake exp");
+ goto fail;
+ }
+
+ if (twt_setup_params->protection) {
+ if (nla_put_flag(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION)) {
+ wpa_printf(MSG_DEBUG,
+ "TWT: Failed to add protection");
+ goto fail;
+ }
+ }
+
+ /*offset to add with TBTT after which 1st SP will start*/
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME,
+ twt_setup_params->wake_time)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake time");
+ goto fail;
+ }
+
+ /*TWT Wake Duration in units of us, must be <= 65280*/
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION,
+ twt_setup_params->wake_dur)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake dur");
+ goto fail;
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA,
+ twt_setup_params->wake_intr_mantissa)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake intr mantissa");
+ goto fail;
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA,
+ twt_setup_params->wake_intr_mantissa/TWT_WAKE_INTERVAL_TU_FACTOR)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake intr mantissa");
+ goto fail;
+ }
+
+ if (twt_setup_params->bcast) {
+ if (nla_put_flag(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put bcast");
+ goto fail;
+ }
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL,
+ twt_setup_params->min_wake_intvl)) {
+ wpa_printf(MSG_ERROR, "TWT: Failed to put min wake intr ");
+ goto fail;
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL,
+ twt_setup_params->max_wake_intvl)) {
+ wpa_printf(MSG_ERROR,"TWT: Failed to put max wake intr");
+ goto fail;
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION,
+ twt_setup_params->min_wake_duration)) {
+ wpa_printf(MSG_ERROR,"TWT: Failed to put min wake dur");
+ goto fail;
+ }
+
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION,
+ twt_setup_params->max_wake_duration)) {
+ wpa_printf(MSG_ERROR,"TWT: Failed to put max wake dur");
+ goto fail;
+ }
+
+ if (twt_setup_params->wake_tsf) {
+ if (nla_put_u64(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF,
+ twt_setup_params->wake_tsf)) {
+ wpa_printf(MSG_ERROR,"TWT: Failed to put wake time tsf value");
+ goto fail;
+ }
+ }
+
+ if (twt_setup_params->announce_timeout_us) {
+ if (nla_put_u32(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT,
+ twt_setup_params->announce_timeout_us)) {
+ wpa_printf(MSG_ERROR, "TWT: Failed to put announce timeout value");
+ goto fail;
+ }
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ wpa_printf(MSG_DEBUG, "TWT: setup command nla end");
+ return 0;
+
+fail:
+ return -EINVAL;
+}
+
+static int prepare_twt_terminate_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ u8 dialog_id;
+ struct nlattr *twt_attr;
+ int ret = 0;
+
+ if(check_cmd_input(cmd))
+ return -EINVAL;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += (DIALOG_ID_STR_LEN + 1);
+ dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ } else {
+ wpa_printf(MSG_ERROR, "TWT: no dialog_id found");
+ goto fail;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_TERMINATE)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_TERMINATE");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ goto fail;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID,
+ dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ goto fail;
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ wpa_printf(MSG_DEBUG, "TWT: terminate sent with dialog_id: %x",
+ dialog_id);
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static int prepare_twt_pause_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ u8 dialog_id;
+ struct nlattr *twt_attr;
+ int ret = 0;
+
+ if(check_cmd_input(cmd))
+ return -EINVAL;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += (DIALOG_ID_STR_LEN + 1);
+ dialog_id = get_u8_from_string(cmd, &ret);
+ if(ret < 0)
+ return ret;
+ } else {
+ wpa_printf(MSG_ERROR, "TWT: no dialog_id found");
+ goto fail;
+ }
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_SUSPEND)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_TERMINATE");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ goto fail;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID,
+ dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ goto fail;
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ wpa_printf(MSG_DEBUG, "TWT: pause sent with dialog_id: %x", dialog_id);
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+/**
+ * process_twt_resume_cmd_string() - Process a TWT resume command string
+ * @cmd: Command string
+ * @resume_params: TWT resume parameters to fill
+ *
+ * This function parses the TWT resume command and populates resume_params.
+ *
+ * Return: 0 on successs, error if invalid params are found
+ *
+ */
+static
+int process_twt_resume_cmd_string(char *cmd,
+ struct twt_resume_parameters *resume_params)
+{
+ int ret = 0;
+
+ if (!resume_params) {
+ wpa_printf(MSG_ERROR, "TWT: cmd or resume_params null");
+ return -EINVAL;
+ }
+
+ if(check_cmd_input(cmd))
+ return -EINVAL;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) != 0) {
+ wpa_printf(MSG_ERROR, "TWT: dialog ID parameter is required");
+ return -EINVAL;
+ }
+ cmd += (DIALOG_ID_STR_LEN + 1);
+ resume_params->dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+
+ if (os_strncasecmp(cmd, NEXT_TWT_STR, NEXT_TWT_STR_LEN) == 0) {
+ cmd += (NEXT_TWT_STR_LEN + 1);
+ resume_params->next_twt = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ wpa_printf(MSG_DEBUG, "TWT: NEXT TWT %d", resume_params->next_twt);
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (os_strncasecmp(cmd, NEXT2_TWT_STR, NEXT2_TWT_STR_LEN) == 0) {
+ cmd += (NEXT2_TWT_STR_LEN + 1);
+ resume_params->next2_twt = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ wpa_printf(MSG_DEBUG, "TWT: NEXT2 TWT %d", resume_params->next2_twt);
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (os_strncasecmp(cmd, NEXT_TWT_SIZE_STR, NEXT_TWT_SIZE_STR_LEN) != 0) {
+ wpa_printf(MSG_ERROR, "TWT: next_twt_size parameter is required");
+ return -EINVAL;
+ }
+ cmd += (NEXT_TWT_SIZE_STR_LEN + 1);
+ resume_params->next_twt_size = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static
+int prepare_twt_resume_nlmsg(struct nl_msg *nlmsg,
+ struct twt_resume_parameters *resume_params)
+{
+ struct nlattr *twt_attr;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_RESUME)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_RESUME");
+ return -EINVAL;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ return -EINVAL;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID,
+ resume_params->dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ return -EINVAL;
+ }
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT,
+ resume_params->next_twt)) {
+ wpa_printf(MSG_DEBUG, "TWT: next_twt");
+ return -EINVAL;
+ }
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT,
+ resume_params->next2_twt)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put next2_twt");
+ return -EINVAL;
+ }
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE,
+ resume_params->next_twt_size)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put next_twt_size");
+ return -EINVAL;
+ }
+ nla_nest_end(nlmsg, twt_attr);
+
+ wpa_printf(MSG_DEBUG,"TWT: resume dialog_id: 0x%x next_twt (us): 0x%x next2_twt (us): 0x%x next_twt_size: %u",
+ resume_params->dialog_id, resume_params->next_twt,
+ resume_params->next2_twt,resume_params->next_twt_size);
+
+ return 0;
+}
+
+/**
+ * process_twt_nudge_cmd_string()- processes command string for nudge command.
+ *
+ * @Param cmd: expects the command
+ * @Param nudge_params: return parsed nudge parameters
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static
+int process_twt_nudge_cmd_string(char *cmd,
+ struct twt_nudge_parameters *nudge_params)
+{
+ int ret = 0;
+
+ if (!nudge_params) {
+ wpa_printf(MSG_ERROR, "TWT: nudge_params null");
+ return -EINVAL;
+ }
+
+ if(check_cmd_input(cmd))
+ return -EINVAL;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) != 0) {
+ wpa_printf(MSG_ERROR, "TWT: dialog_id parameter is required");
+ return -EINVAL;
+ }
+ cmd += (DIALOG_ID_STR_LEN + 1);
+ nudge_params->dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+
+ if (os_strncasecmp(cmd, PAUSE_DURATION_STR, PAUSE_DURATION_STR_LEN) == 0) {
+ cmd += (PAUSE_DURATION_STR_LEN + 1);
+ nudge_params->wake_time = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ wpa_printf(MSG_DEBUG, "TWT: WAKE TIME %d", nudge_params->wake_time);
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (os_strncasecmp(cmd, NEXT_TWT_SIZE_STR, NEXT_TWT_SIZE_STR_LEN) != 0) {
+ wpa_printf(MSG_ERROR, "TWT: next_twt_size parameter is required");
+ return -EINVAL;
+ }
+ cmd += (NEXT_TWT_SIZE_STR_LEN + 1);
+ nudge_params->next_twt_size = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * prepare_twt_nudge_nlmsg()- prepare twt_session_nudge command .
+ *
+ * @Param nlmsg: nl command buffer
+ * @Param nudge_params: nudge parameters to prepare command
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static
+int prepare_twt_nudge_nlmsg(struct nl_msg *nlmsg,
+ struct twt_nudge_parameters *nudge_params)
+{
+ struct nlattr *twt_attr;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_NUDGE)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put twt operation");
+ return -EINVAL;
+ }
+
+ twt_attr = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ return -EINVAL;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID,
+ nudge_params->dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ return -EINVAL;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME,
+ nudge_params->wake_time)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put wake_time");
+ return -EINVAL;
+ }
+
+ if (nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE,
+ nudge_params->next_twt_size)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put next_twt_size");
+ return -EINVAL;
+ }
+ nla_nest_end(nlmsg, twt_attr);
+
+ wpa_printf(MSG_DEBUG,"TWT: nudge dialog_id: 0x%x wake_time(us): 0x%x next_twt_size: %u",
+ nudge_params->dialog_id, nudge_params->wake_time,
+ nudge_params->next_twt_size);
+
+ return 0;
+}
+
+/**
+ * process_twt_set_param_cmd_string()- processes command
+ * string for set parameters command.
+ *
+ * @Param cmd: expects the command
+ * @Param set_params: return parsed TWT set parameters
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static
+int process_twt_set_param_cmd_string(char *cmd,
+ struct twt_set_parameters *set_params)
+{
+ int ret = -EINVAL;
+
+ if (!set_params) {
+ wpa_printf(MSG_ERROR, "TWT: set_params null");
+ return -EINVAL;
+ }
+
+ if (check_cmd_input(cmd))
+ return -EINVAL;
+
+ while (*cmd == ' ')
+ cmd++;
+
+ if (os_strncasecmp(cmd, AP_AC_VALUE_STR, AP_AC_VALUE_STR_LEN) == 0) {
+ cmd += (AP_AC_VALUE_STR_LEN + 1);
+ set_params->ap_ac_value = get_u8_from_string(cmd, &ret);
+ wpa_printf(MSG_DEBUG, "TWT: AP AC VALUE: %d", set_params->ap_ac_value);
+ if (ret < 0)
+ return ret;
+ cmd = move_to_next_str(cmd);
+ }
+
+ return ret;
+}
+
+/**
+ * prepare_twt_set_param_nlmsg()- prepare twt_set_param command .
+ *
+ * @Param nlmsg: nl command buffer
+ * @Param set_params: set parameters to prepare command
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static
+int prepare_twt_set_param_nlmsg(struct nl_msg *nlmsg,
+ struct twt_set_parameters *set_params)
+{
+ struct nlattr *twt_attr;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_SET_PARAM)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put twt operation");
+ return -EINVAL;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (!twt_attr)
+ return -EINVAL;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE,
+ set_params->ap_ac_value)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put ap_ac_value");
+ return -EINVAL;
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+
+ wpa_printf(MSG_DEBUG, "TWT: set parameters - ap_ac_value: %d",
+ set_params->ap_ac_value);
+
+ return 0;
+}
+
+/**
+ * prepare_twt_clear_stats_nlmsg()- prepare twt_session_clear_stats command.
+ *
+ * @Param nlmsg: nl command buffer
+ * @Param cmd: command string
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static int prepare_twt_clear_stats_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ struct nlattr *twt_attr;
+ u8 dialog_id;
+ int ret = 0;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_CLEAR_STATS)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_CLEAR_STATS");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (!twt_attr)
+ return -EINVAL;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += DIALOG_ID_STR_LEN + 1;
+
+ dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID,
+ dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ return -EINVAL;
+ }
+ wpa_printf(MSG_DEBUG, "TWT: clear_stats dialog_id:%d", dialog_id);
+ cmd = move_to_next_str(cmd);
+ } else {
+ wpa_printf(MSG_DEBUG, "TWT: dialog_id not found");
+ goto fail;
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+/**
+ * prepare_twt_get_stats_nlmsg()- prepare twt_session_get_stats command.
+ *
+ * @Param nlmsg: nl command buffer
+ * @Param cmd: command string
+ *
+ * @Returns 0 on Success, -EINVAL on Failure
+ */
+static int prepare_twt_get_stats_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ struct nlattr *twt_attr;
+ u8 dialog_id;
+ int ret = 0;
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_GET_STATS)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_GET_STATS");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (!twt_attr)
+ return -EINVAL;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += DIALOG_ID_STR_LEN + 1;
+
+ dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID,
+ dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ return -EINVAL;
+ }
+ wpa_printf(MSG_DEBUG, "TWT: get_stats dialog_id:%d", dialog_id);
+ cmd = move_to_next_str(cmd);
+ } else {
+ wpa_printf(MSG_DEBUG, "TWT: dialog_id not found");
+ goto fail;
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static int prepare_twt_get_params_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ struct nlattr *twt_attr;
+ u8 dialog_id;
+ int ret = 0;
+ uint8_t peer_mac[MAC_ADDR_LEN];
+
+ while(*cmd == ' ')
+ cmd++;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_GET)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put QCA_WLAN_TWT_GET");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (!twt_attr)
+ return -EINVAL;
+
+ if (os_strncasecmp(cmd, DIALOG_ID_STR, DIALOG_ID_STR_LEN) == 0) {
+ cmd += DIALOG_ID_STR_LEN + 1;
+
+ dialog_id = get_u8_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID,
+ dialog_id)) {
+ wpa_printf(MSG_DEBUG, "TWT: Failed to put dialog_id");
+ return -EINVAL;
+ }
+ wpa_printf(MSG_DEBUG, "TWT: get_param dialog_id:%d", dialog_id);
+ cmd = move_to_next_str(cmd);
+ } else {
+ wpa_printf(MSG_ERROR, "TWT: dialog_id not found");
+ goto fail;
+ }
+
+
+ if (os_strncasecmp(cmd, MAC_ADDRESS_STR, MAC_ADDR_STR_LEN) == 0) {
+ cmd += MAC_ADDR_STR_LEN + 1;
+
+ if (convert_string_to_bytes(peer_mac, cmd, MAC_ADDR_LEN) !=
+ MAC_ADDR_LEN) {
+ wpa_printf(MSG_ERROR, "TWT: invalid mac address");
+ goto fail;
+ }
+
+ if (nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR,
+ MAC_ADDR_LEN, peer_mac)) {
+ wpa_printf(MSG_ERROR, "TWT: Failed to put mac address");
+ goto fail;
+ }
+ }
+
+ nla_nest_end(nlmsg, twt_attr);
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+/**
+* prepare_twt_get_cap_nlmsg()- processes and packs get capability command.
+* The command is expected in below format:
+* TWT_GET_CAP
+*
+* @Param nlmsg: stores the nlmsg
+* @Param cmd: expects the command
+*
+* @Returns 0 on Success, -EINVAL on Failure
+*/
+static int prepare_twt_get_cap_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+ struct nlattr *twt_attr;
+
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
+ QCA_WLAN_TWT_GET_CAPABILITIES)) {
+ wpa_printf(MSG_ERROR,"TWT: Failed to put QCA_WLAN_TWT_GET_CAPABILITIES");
+ goto fail;
+ }
+
+ twt_attr = nla_nest_start(nlmsg,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
+ if (twt_attr == NULL)
+ goto fail;
+ nla_nest_end(nlmsg, twt_attr);
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static int pack_nlmsg_twt_params(struct nl_msg *twt_nl_msg, char *cmd,
+ enum qca_wlan_twt_operation type)
+{
+ struct nlattr *attr;
+ int ret = 0;
+
+ attr = nla_nest_start(twt_nl_msg, NL80211_ATTR_VENDOR_DATA);
+ if (attr == NULL)
+ return -EINVAL;
+
+ switch (type) {
+ case QCA_WLAN_TWT_SET:
+ {
+ struct twt_setup_parameters setup_params = {0};
+
+ if (process_twt_setup_cmd_string(cmd, &setup_params))
+ return -EINVAL;
+ ret = prepare_twt_setup_nlmsg(twt_nl_msg, &setup_params);
+ break;
+ }
+ case QCA_WLAN_TWT_TERMINATE:
+ ret = prepare_twt_terminate_nlmsg(twt_nl_msg, cmd);
+ break;
+ case QCA_WLAN_TWT_SUSPEND:
+ ret = prepare_twt_pause_nlmsg(twt_nl_msg, cmd);
+ break;
+ case QCA_WLAN_TWT_RESUME:
+ {
+ struct twt_resume_parameters resume_params = {0};
+
+ if (process_twt_resume_cmd_string(cmd, &resume_params))
+ return -EINVAL;
+ ret = prepare_twt_resume_nlmsg(twt_nl_msg, &resume_params);
+ break;
+ }
+ case QCA_WLAN_TWT_NUDGE:
+ {
+ struct twt_nudge_parameters nudge_params = {0};
+
+ if (process_twt_nudge_cmd_string(cmd, &nudge_params))
+ return -EINVAL;
+ ret = prepare_twt_nudge_nlmsg(twt_nl_msg, &nudge_params);
+ break;
+ }
+ case QCA_WLAN_TWT_SET_PARAM:
+ {
+ struct twt_set_parameters set_params = {0};
+
+ if (process_twt_set_param_cmd_string(cmd, &set_params))
+ return -EINVAL;
+ ret = prepare_twt_set_param_nlmsg(twt_nl_msg, &set_params);
+ break;
+ }
+ case QCA_WLAN_TWT_GET_CAPABILITIES:
+ ret = prepare_twt_get_cap_nlmsg(twt_nl_msg, cmd);
+ break;
+ case QCA_WLAN_TWT_CLEAR_STATS:
+ ret = prepare_twt_clear_stats_nlmsg(twt_nl_msg, cmd);
+ break;
+ case QCA_WLAN_TWT_GET_STATS:
+ ret = prepare_twt_get_stats_nlmsg(twt_nl_msg, cmd);
+ break;
+ case QCA_WLAN_TWT_GET:
+ ret = prepare_twt_get_params_nlmsg(twt_nl_msg, cmd);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "Unsupported command: %d", type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret)
+ nla_nest_end(twt_nl_msg, attr);
+
+ return ret;
+}
+
+char *result_copy_to_buf(char *src, char *dst_buf, int *dst_len)
+{
+ int str_len, remaining = 0;
+
+ remaining = *dst_len;
+ str_len = strlen(src);
+ remaining = remaining - (str_len + 1);
+
+ if (remaining <= 0) {
+ wpa_printf(MSG_ERROR, "destination buffer length not enough");
+ return NULL;
+ }
+ os_memcpy(dst_buf, src, str_len);
+
+ *dst_len = remaining;
+ *(dst_buf + str_len) = ' ';
+
+ return (dst_buf + str_len + 1);
+}
+
+static int
+unpack_twt_get_params_resp(struct nlattr **tb, char *buf, int buf_len)
+{
+ int cmd_id, val, len;
+ uint8_t exp;
+ uint32_t value;
+ unsigned long wake_tsf;
+ char temp[TWT_RESP_BUF_LEN];
+ char *start = buf;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+
+ /* Mac Address */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no mac_addr");
+ return -EINVAL;
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "<mac_addr " MAC_ADDR_STR,
+ MAC_ADDR_ARRAY((char *)nla_data(tb[cmd_id])));
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Flow Id */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no dialog_id");
+ return -EINVAL;
+ }
+ val = nla_get_u8(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "dialog_id %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+
+ /* Broadcast */
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
+ if (tb[cmd_id])
+ val = nla_get_flag(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "bcast %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Trigger Type */
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
+ if (tb[cmd_id])
+ val = nla_get_flag(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "trig_type %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Announce */
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
+ if (tb[cmd_id])
+ val = nla_get_flag(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "flow_type %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Protection */
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
+ if (tb[cmd_id])
+ val = nla_get_flag(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "protection %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* info */
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED;
+ if (tb[cmd_id])
+ val = nla_get_flag(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "info_enabled %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Wake Duration */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no wake duration");
+ return -EINVAL;
+ }
+ value = nla_get_u32(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_dur %d", value);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Wake Interval Mantissa */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA;
+ if (!tb[cmd_id]) {
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no wake mantissa");
+ return -EINVAL;
+ }
+ value = nla_get_u32(tb[cmd_id]);
+ value = value * TWT_WAKE_INTERVAL_TU_FACTOR;
+ } else {
+ value = nla_get_u32(tb[cmd_id]);
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_intvl_mantis %d", value);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* Wake Interval Exponent */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no wake intvl exp");
+ return -EINVAL;
+ }
+ exp = nla_get_u8(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_intvl_exp %d", exp);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* TSF Value */
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no wake time tsf");
+ return -EINVAL;
+ }
+ wake_tsf = nla_get_u64(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_time_tsf 0x%lx>", wake_tsf);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE;
+ if (!tb[cmd_id]) {
+ wpa_printf(MSG_ERROR, "twt_get_params resp: no state info");
+ return -EINVAL;
+ }
+ value = nla_get_u32(tb[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "state %d", value);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE;
+ if (tb[cmd_id]) {
+ val = nla_get_u8(tb[cmd_id]);
+
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "responder_pm %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+
+ len = (buf - start);
+ *buf = '\0';
+
+ return len;
+}
+
+static int wpa_get_twt_setup_resp_val(struct nlattr **tb2, char *buf,
+ int buf_len)
+{
+ uint32_t wake_intvl_exp = 0, wake_intvl_mantis = 0;
+ int cmd_id, val;
+ uint32_t value;
+ unsigned long wake_tsf;
+ char temp[TWT_RESP_BUF_LEN];
+
+ buf = result_copy_to_buf(TWT_SETUP_RESP, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT dialog id missing");
+ return -EINVAL;
+ }
+
+ val = nla_get_u8(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "dialog_id %d ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT resp status missing");
+ return -EINVAL;
+ }
+
+ val = nla_get_u8(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "status %d ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "(%s)", twt_status_to_string(val));
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ /* In case of failure only status is updated */
+ if (val != QCA_WLAN_VENDOR_TWT_STATUS_OK) {
+ *buf = '\0';
+ return 0;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT resp type missing");
+ return -EINVAL;
+ }
+ val = nla_get_u8(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "resp_reason %d ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT_SETUP_WAKE_INTVL_EXP is must");
+ return -EINVAL;
+ }
+ wake_intvl_exp = nla_get_u8(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_intvl_exp %d ",
+ wake_intvl_exp);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
+ if (tb2[cmd_id])
+ val = nla_get_flag(tb2[cmd_id]);
+
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "bcast %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
+ if (tb2[cmd_id])
+ val = nla_get_flag(tb2[cmd_id]);
+
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "trig_type %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT_SETUP_FLOW_TYPE is must");
+ return -EINVAL;
+ }
+ val = nla_get_u8(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "flow_type %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
+ if (tb2[cmd_id])
+ val = nla_get_flag(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "protection %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ value = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
+ if (tb2[cmd_id])
+ value = nla_get_u32(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_time 0x%x", value);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "TWT_SETUP_WAKE_DURATION is must");
+ return -EINVAL;
+ }
+ value = nla_get_u32(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_dur %d", value);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA;
+ if (!tb2[cmd_id]) {
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "SETUP_WAKE_INTVL_MANTISSA is must");
+ return -EINVAL;
+ }
+ wake_intvl_mantis = nla_get_u32(tb2[cmd_id]);
+ wake_intvl_mantis = wake_intvl_mantis * TWT_WAKE_INTERVAL_TU_FACTOR;
+ } else {
+ wake_intvl_mantis = nla_get_u32(tb2[cmd_id]);
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_intvl %d", wake_intvl_mantis);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ wake_tsf = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF;
+ if (tb2[cmd_id])
+ wake_tsf = nla_get_u64(tb2[cmd_id]);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "wake_tsf 0x%lx", wake_tsf);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED;
+ if (tb2[cmd_id])
+ val = nla_get_flag(tb2[cmd_id]);
+
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "info_enabled %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ val = 0;
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE;
+ if (tb2[cmd_id]) {
+ val = nla_get_u8(tb2[cmd_id]);
+
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "responder_pm %d", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+
+ *buf = '\0';
+
+ return 0;
+}
+
+/**
+ * unpack_twt_get_params_nlmsg()- unpacks and prints the twt get_param
+ * response recieved from driver synchronously for twt_session_get_params.
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -1 on Failure
+ */
+static int unpack_twt_get_params_nlmsg(struct nl_msg **tb, char *buf, int buf_len)
+{
+ int ret, rem, id, len = 0, num_twt_sessions = 0;
+ struct nlattr *config_attr[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1];
+ struct nlattr *setup_attr[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+ struct nlattr *attr;
+
+ if (nla_parse_nested(config_attr, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX,
+ tb[NL80211_ATTR_VENDOR_DATA], NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_params: nla_parse_nested fail");
+ return -EINVAL;
+ }
+
+ id = QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS;
+ attr = config_attr[id];
+ if (!attr) {
+ wpa_printf(MSG_ERROR, "twt_get_params: config_twt_params fail");
+ return -EINVAL;
+ }
+
+ num_twt_sessions = 0;
+ nla_for_each_nested(attr, config_attr[id], rem) {
+ num_twt_sessions++;
+ if (nla_parse(setup_attr, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ nla_data(attr), nla_len(attr), NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_params: nla_parse fail");
+ return -EINVAL;
+ }
+ ret = unpack_twt_get_params_resp(setup_attr, buf + len,
+ buf_len - len);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
+
+ wpa_printf(MSG_ERROR, "twt_get_params: number of twt sessions = %d",
+ num_twt_sessions);
+
+ return 0;
+}
+
+/**
+ * wpa_get_twt_stats_resp_val()- parse twt get_stats response
+ * recieved from driver synchronously for twt_session_get_stats.
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -1 on Failure
+ */
+static int wpa_get_twt_stats_resp_val(struct nlattr **tb2, char *buf,
+ int buf_len)
+{
+ int cmd_id, len;
+ u32 val = 0;
+ u8 val1 = 0;
+ char temp[TWT_RESP_BUF_LEN];
+ char *start = buf;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats flow id missing", __func__);
+ } else {
+ val1 = nla_get_u8(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "flow_id %u", val1);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats flow id : %u", val1);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats num sp iterations missing", __func__);
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "num_sp_iteration %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT num sp Iterations : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats min wake duration missing", __func__);
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "min_wake_dur %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT min wake duration : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats max wake duration missing", __func__);
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "max_wake_dur %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT Max wake duration : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats sess_wake_dur missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "session_wake_dur %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats session wake duration : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats avg_wake_dur missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "avg_wake_dur %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats avg wake duration : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats average tx mpdu missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "tx_mpdu %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats average tx mpdu : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats average rx mpdu missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "rx_mpdu %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats average rx mpdu : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats average tx packet size missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "tx_pkt_size %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats average tx packet size : %u", val);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR,"%s TWT stats average rx packet size missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u32(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "rx_pkt_size %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ wpa_printf(MSG_INFO,"TWT stats average rx packet size : %u", val);
+ }
+ len = (buf - start);
+ *buf = '\0';
+
+ return len;
+}
+
+/**
+ * unpack_twt_get_stats_nlmsg()- unpacks and prints the twt get_stats
+ * response recieved from driver synchronously for twt_session_get_stats.
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -1 on Failure
+ */
+static
+int unpack_twt_get_stats_nlmsg(struct nl_msg **tb, char *buf, int buf_len)
+{
+ int ret, rem, id, len = 0, num_twt_sessions = 0;
+ struct nlattr *config_attr[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1];
+ struct nlattr *setup_attr[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+ struct nlattr *attr;
+
+ if (nla_parse_nested(config_attr, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX,
+ tb[NL80211_ATTR_VENDOR_DATA], NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_stats: nla_parse_nested fail");
+ return -EINVAL;
+ }
+
+ id = QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS;
+ attr = config_attr[id];
+ if (!attr) {
+ wpa_printf(MSG_ERROR, "twt_get_stats: config_twt_params fail");
+ return -EINVAL;
+ }
+
+ num_twt_sessions = 0;
+ nla_for_each_nested(attr, config_attr[id], rem) {
+ num_twt_sessions++;
+ if (nla_parse(setup_attr, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ nla_data(attr), nla_len(attr), NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_stats: nla_parse fail");
+ return -EINVAL;
+ }
+ ret = wpa_get_twt_stats_resp_val(setup_attr, buf + len,
+ buf_len - len);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
+ wpa_printf(MSG_INFO,"twt_get_stats: number of twt sessions = %d", num_twt_sessions);
+
+ return 0;
+}
+
+static int wpa_get_twt_capabilities_resp_val(struct nlattr **tb2, char *buf,
+ int buf_len)
+{
+ int cmd_id;
+ u16 msb, lsb;
+ u32 val;
+ char temp[TWT_RESP_BUF_LEN];
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_INFO,"%s TWT self capabilities missing", __func__);
+ return -EINVAL;
+ } else {
+ msb = nla_get_u16(tb2[cmd_id]);
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_INFO,"%s TWT peer capabilities missing", __func__);
+ return -EINVAL;
+ } else {
+ lsb = nla_get_u16(tb2[cmd_id]);
+ }
+ wpa_printf(MSG_INFO,"TWT self_capab:%d, TWT peer_capab:%d", msb, lsb);
+ val = (msb << 16) | lsb;
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "0x%x", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ *buf = '\0';
+
+ return 0;
+}
+
+/**
+ * unpack_twt_get_capab_nlmsg()- unpacks and prints the twt get capabilities
+ * response recieved from driver synchronously for TWT_GET_CAP command.
+ * The response is printed in below hex-format:
+ * 0xHIGHLOW
+ * HIGH: Self capabilities
+ * LOW: Peer capabilities
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -1 on Failure
+ */
+static int unpack_twt_get_capab_nlmsg(struct nl_msg **tb, char *buf, int buf_len)
+{
+ int ret, id;
+ struct nlattr *config_attr[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1];
+ struct nlattr *setup_attr[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+ struct nlattr *attr;
+
+ if (nla_parse_nested(config_attr, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX,
+ tb[NL80211_ATTR_VENDOR_DATA], NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_capability: nla_parse_nested fail");
+ return -EINVAL;
+ }
+
+ id = QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS;
+ attr = config_attr[id];
+ if (!attr) {
+ wpa_printf(MSG_ERROR, "twt_get_capability: config_twt_params fail");
+ return -EINVAL;
+ }
+
+ if (nla_parse(setup_attr, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ nla_data(attr), nla_len(attr), NULL)) {
+ wpa_printf(MSG_ERROR, "twt_get_capability: nla_parse fail");
+ return -EINVAL;
+ }
+
+ ret = wpa_get_twt_capabilities_resp_val(setup_attr, buf, buf_len);
+ return ret;
+}
+
+/**
+ * unpack_twt_setup_nlmsg()- unpacks twt_session_setup response recieved
+ * The response is printed in below format:
+ * CTRL-EVENT-TWT SETUP dialog_id <dialog_id> status <status> ..
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -EINVAL on invalid response
+ */
+static int unpack_twt_setup_nlmsg(struct nlattr **tb, char *buf, int buf_len)
+{
+ int ret = 0;
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+
+ if (nla_parse_nested(tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS], NULL)) {
+ wpa_printf(MSG_ERROR, "nla_parse failed\n");
+ return -EINVAL;
+ }
+
+ ret = wpa_get_twt_setup_resp_val(tb2, buf, buf_len);
+
+ return ret;
+}
+
+static int unpack_nlmsg_twt_params(struct nl_msg *twt_nl_msg,
+ enum qca_wlan_twt_operation type,
+ char *buf, int buf_len)
+{
+ int ret = 0;
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(twt_nl_msg));
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ switch (type) {
+ case QCA_WLAN_TWT_GET:
+ ret = unpack_twt_get_params_nlmsg(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_GET_STATS:
+ ret = unpack_twt_get_stats_nlmsg(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_GET_CAPABILITIES:
+ ret = unpack_twt_get_capab_nlmsg(tb, buf, buf_len);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "Unsupported command: %d", type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int twt_response_handler(struct nl_msg *msg, void *arg)
+{
+ struct twt_resp_info *info = (struct twt_resp_info *) arg;
+ struct wpa_driver_nl80211_data *drv = NULL;
+ int ret;
+
+ drv = info->drv;
+ ret = unpack_nlmsg_twt_params(msg, info->twt_oper, info->reply_buf,
+ info->reply_buf_len);
+ wpa_printf(MSG_DEBUG, "%s - twt_oper %d", __func__, info->twt_oper);
+ if (!ret)
+ wpa_msg(drv->ctx, MSG_INFO,
+ TWT_CTRL_EVENT " %s : OK", info->reply_buf);
+ else
+ wpa_msg(drv->ctx, MSG_INFO,
+ TWT_CTRL_EVENT " %s : Error = %d",
+ info->reply_buf, ret);
+
+ return ret;
+}
+
+struct features_info {
+ u8 *flags;
+ size_t flags_len;
+};
+
+static
+int check_feature(enum qca_wlan_vendor_features feature,
+ struct features_info *info)
+{
+ size_t idx = feature / 8;
+
+ return (idx < info->flags_len) &&
+ (info->flags[idx] & BIT(feature % 8));
+}
+
+/* features_info_handler() - parse sync response for get_feature cmd
+ *
+ * @param msg: nl_msg buffer
+ * @Param arg: feature infor
+ *
+ * @Returns 0 on Success, error code on invalid response
+ */
+static
+int features_info_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *mHeader;
+ struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
+ struct nlattr *vendata, *attr;
+ int datalen;
+
+ struct features_info *info = (struct features_info *) arg;
+ int status = 0;
+
+
+ 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;
+ }
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
+ vendata, datalen, NULL);
+
+ attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
+ if (attr) {
+ int len = nla_len(attr);
+ info->flags = os_malloc(len);
+ if (info->flags != NULL) {
+ os_memcpy(info->flags, nla_data(attr), len);
+ info->flags_len = len;
+ }
+ } else {
+ wpa_printf(MSG_ERROR,"VENDOR_ATTR_FEATURE_FLAGS not found");
+ }
+ } else {
+ wpa_printf(MSG_ERROR,"NL80211_ATTR_VENDOR_DATA not found");
+ status = -1;
+ }
+
+ return status;
+}
+
+/* pack_nlmsg_vendor_feature_hdr() - pack get_features command
+ *
+ * @param drv_nl_msg: nl_msg buffer
+ * @Param drv: nl data
+ * @Param ifname: interface name
+ *
+ * @Returns 0 on Success, error code on invalid response
+ */
+static
+int pack_nlmsg_vendor_feature_hdr(struct nl_msg *drv_nl_msg,
+ struct wpa_driver_nl80211_data *drv,
+ char *ifname)
+{
+ int ret;
+ int ifindex;
+
+ genlmsg_put(drv_nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ,
+ drv->global->nl80211_id, 0, 0,
+ NL80211_CMD_VENDOR, 0);
+
+ ret = nla_put_u32(drv_nl_msg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Failed to put vendor id");
+ return ret;
+ }
+
+ ret = nla_put_u32(drv_nl_msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "nl put twt vendor subcmd failed");
+ return ret;
+ }
+
+ if (ifname && (strlen(ifname) > 0))
+ ifindex = if_nametoindex(ifname);
+ else
+ ifindex = if_nametoindex(DEFAULT_IFNAME);
+
+ ret = nla_put_u32(drv_nl_msg, NL80211_ATTR_IFINDEX, ifindex);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "nl put iface: %s failed", ifname);
+ return ret;
+ }
+ return ret;
+}
+
+/* check_wifi_twt_async_feature() - check if driver supports twt async feature
+ *
+ * @Param drv: nl data
+ * @Param ifname: interface name
+ *
+ * @Returns 1 if twt async feature is supported, 0 otherwise
+ */
+static int check_wifi_twt_async_feature(struct wpa_driver_nl80211_data *drv,
+ char *ifname)
+{
+ struct nl_msg *nlmsg;
+ struct features_info info;
+ int ret;
+
+ if (twt_async_support != -1) {
+ return twt_async_support;
+ }
+
+ nlmsg = nlmsg_alloc();
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "nlmg alloc failure");
+ return -ENOMEM;
+ }
+
+ pack_nlmsg_vendor_feature_hdr(nlmsg, drv, ifname);
+ os_memset(&info, 0, sizeof(info));
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+ features_info_handler, &info);
+
+ if (ret || !info.flags) {
+ nlmsg_free(nlmsg);
+ return 0;
+ }
+
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT, &info)) {
+ twt_async_support = 1;
+ } else {
+ twt_async_support = 0;
+ }
+
+ os_free(info.flags);
+ return twt_async_support;
+}
+
+static int wpa_driver_twt_cmd_handler(struct wpa_driver_nl80211_data *drv,
+ char *ifname,
+ enum qca_wlan_twt_operation twt_oper,
+ char *param, char *buf,
+ size_t buf_len, int *status)
+{
+ struct nl_msg *twt_nl_msg;
+ struct twt_resp_info reply_info;
+ int ret = 0;
+
+ if (!param) {
+ wpa_printf(MSG_ERROR, "%s:TWT cmd args missing\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!buf) {
+ wpa_printf(MSG_ERROR, "buf is NULL");
+ return -EINVAL;
+ }
+
+ wpa_printf(MSG_DEBUG, "TWT DRIVER cmd: %s", param);
+
+ memset(&reply_info, 0, sizeof(struct twt_resp_info));
+ os_memset(buf, 0, buf_len);
+
+ reply_info.twt_oper = twt_oper;
+ reply_info.reply_buf = buf;
+ reply_info.reply_buf_len = buf_len;
+ reply_info.drv = drv;
+
+ twt_nl_msg = prepare_nlmsg(drv, ifname, NL80211_CMD_VENDOR,
+ QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT, 0);
+ if (!twt_nl_msg) {
+ ret = -EINVAL;
+ goto err_msg;
+ }
+
+ ret = pack_nlmsg_twt_params(twt_nl_msg, param, twt_oper);
+ if (ret) {
+ nlmsg_free(twt_nl_msg);
+ goto err_msg;
+ }
+
+ switch(twt_oper) {
+ case QCA_WLAN_TWT_GET:
+ case QCA_WLAN_TWT_GET_CAPABILITIES:
+ case QCA_WLAN_TWT_GET_STATS:
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl,
+ twt_nl_msg, twt_response_handler,
+ &reply_info);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
+ ret = -EINVAL;
+ }
+ break;
+ case QCA_WLAN_TWT_CLEAR_STATS:
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl,
+ twt_nl_msg, NULL, NULL);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
+ ret = -EINVAL;
+ }
+ break;
+ case QCA_WLAN_TWT_SET:
+ case QCA_WLAN_TWT_TERMINATE:
+ case QCA_WLAN_TWT_SUSPEND:
+ case QCA_WLAN_TWT_RESUME:
+ case QCA_WLAN_TWT_NUDGE:
+ case QCA_WLAN_TWT_SET_PARAM:
+ if(check_wifi_twt_async_feature(drv, ifname) == 0) {
+ wpa_printf(MSG_ERROR, "Asynchronous TWT Feature is missing");
+ ret = -EINVAL;
+ } else {
+ *status = send_nlmsg((struct nl_sock *)drv->global->nl,
+ twt_nl_msg, NULL, NULL);
+ if (*status != 0) {
+ wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
+ ret = -EINVAL;
+ }
+ }
+ break;
+ default:
+ wpa_printf(MSG_ERROR, "nlmg send failure");
+ ret = -EINVAL;
+ goto err_msg;
+ }
+
+err_msg:
+ wpa_printf(MSG_ERROR, "sent nlmsg - status %d", *status);
+ return ret;
+}
+
+/**
+ * unpack_twt_terminate_event()- unpacks twt_session_terminate response recieved
+ * The response is printed in below format:
+ * CTRL-EVENT-TWT TERMINATE dialog_id <dialog_id> status <status>
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -EINVAL on invalid response
+ */
+static
+int unpack_twt_terminate_event(struct nlattr **tb, char *buf, int buf_len)
+{
+ int cmd_id;
+ u8 val;
+ char temp[TWT_RESP_BUF_LEN];
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+
+ if (nla_parse_nested(tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS], NULL)) {
+ wpa_printf(MSG_ERROR, "nla_parse failed");
+ return -EINVAL;
+ }
+
+ buf = result_copy_to_buf(TWT_TEARDOWN_RESP, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_TEARDOWN_RESP_LEN);
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT dialog id missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ if(val == 255) {
+ val = 0;
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "dialog_id %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT resp status missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "status %u ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "(%s)", twt_status_to_string(val));
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+ *buf = '\0';
+
+ return 0;
+}
+
+/**
+ * unpack_twt_suspend_event()- unpacks twt_session_pause response recieved
+ * The response is printed in below format:
+ * CTRL-EVENT-TWT PAUSE dialog_id <dialog_id> status <status>
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -EINVAL on invalid response
+ */
+static
+int unpack_twt_suspend_event(struct nlattr **tb, char *buf, int buf_len)
+{
+ int cmd_id;
+ u8 val;
+ char temp[TWT_RESP_BUF_LEN];
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+
+ if (nla_parse_nested(tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS], NULL)) {
+ wpa_printf(MSG_ERROR, "nla_parse failed");
+ return -1;
+ }
+
+ buf = result_copy_to_buf(TWT_PAUSE_RESP, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_PAUSE_RESP_LEN);
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT dialog id missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ if(val == 255) {
+ val = 0;
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "dialog_id %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT resp status missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "status %u ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "(%s)", twt_status_to_string(val));
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+ *buf = '\0';
+
+ return 0;
+}
+
+/**
+ * unpack_twt_resume_event()- unpacks twt_session_resume response recieved
+ * The response is printed in below format:
+ * CTRL-EVENT-TWT RESUME dialog_id <dialog_id> status <status>
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -EINVAL on invalid response
+ */
+static
+int unpack_twt_resume_event(struct nlattr **tb, char *buf, int buf_len)
+{
+ int cmd_id;
+ u8 val;
+ char temp[TWT_RESP_BUF_LEN];
+ struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
+
+ if (nla_parse_nested(tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
+ tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS], NULL)) {
+ wpa_printf(MSG_ERROR, "nla_parse failed");
+ return -1;
+ }
+
+ buf = result_copy_to_buf(TWT_RESUME_RESP, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESUME_RESP_LEN);
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT dialog id missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ if(val == 255) {
+ val = 0;
+ }
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "dialog_id %u", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
+ if (!tb2[cmd_id]) {
+ wpa_printf(MSG_ERROR, "%s TWT resp status missing", __func__);
+ return -EINVAL;
+ } else {
+ val = nla_get_u8(tb2[cmd_id]);
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "status %u ", val);
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+ os_snprintf(temp, TWT_RESP_BUF_LEN, "(%s)", twt_status_to_string(val));
+ buf = result_copy_to_buf(temp, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+ }
+ *buf = '\0';
+
+ return 0;
+}
+
+/**
+ * unpack_twt_notify_event()- prints the twt notify response recieved from driver
+ * asynchronously for QCA_WLAN_TWT_SETUP_READY_NOTIFY event.
+ * The response is printed in below format:
+ * CTRL-EVENT-TWT NOTIFY
+ *
+ * @Param tb: vendor nl data
+ * @Param buf: stores the response
+ * @Param buf_len: length of the response buffer
+ *
+ * @Returns 0 on Success, -EINVAL on invalid response
+ */
+int unpack_twt_notify_event(struct nlattr **tb, char *buf, int buf_len)
+{
+ char temp[TWT_RESP_BUF_LEN];
+
+ os_memset(temp, 0, TWT_RESP_BUF_LEN);
+
+ buf = result_copy_to_buf(TWT_NOTIFY_RESP, buf, &buf_len);
+ if (!buf)
+ return -EINVAL;
+
+ *buf = '\0';
+ return 0;
+}
+
+/**
+ * wpa_driver_twt_async_resp_handler()- handler for asynchronous twt vendor event
+ * recieved from the driver.
+ *
+ * @Param drv- wpa_driver_nl80211_data
+ * @Param vendor_id- vendor id for vendor specific command
+ * @Param subcmd- subcmd as defined by enum qca_nl80211_vendor_subcmds
+ * @Param data- vendor data
+ * @Param len- vendor data length
+ *
+ * @Returns 0 for Success, -1 for Failure
+ */
+static int wpa_driver_twt_async_resp_event(struct wpa_driver_nl80211_data *drv,
+ u32 vendor_id, u32 subcmd, u8 *data, size_t len)
+{
+ int ret = 0;
+ char *buf;
+ buf = (char *)malloc(TWT_RESP_BUF_LEN);
+ int buf_len = TWT_RESP_BUF_LEN;
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1];
+ u8 twt_operation_type;
+
+ if (!buf)
+ return -1;
+
+ ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX,
+ (struct nlattr *) data, len, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "nla_parse failed %d", ret);
+ goto fail;
+ }
+
+ if (!buf) {
+ wpa_printf(MSG_ERROR, "buf not allocated");
+ return -1;
+ }
+
+ memset(buf, 0, TWT_RESP_BUF_LEN);
+
+ twt_operation_type = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION]);
+
+ switch(twt_operation_type) {
+ case QCA_WLAN_TWT_SET:
+ ret = unpack_twt_setup_nlmsg(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_TERMINATE:
+ ret = unpack_twt_terminate_event(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_SUSPEND:
+ ret = unpack_twt_suspend_event(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_RESUME:
+ ret = unpack_twt_resume_event(tb, buf, buf_len);
+ break;
+ case QCA_WLAN_TWT_SETUP_READY_NOTIFY:
+ ret = unpack_twt_notify_event(tb, buf, buf_len);
+ break;
+ default:
+ ret = -1;
+ }
+
+ if(ret) {
+ wpa_printf(MSG_ERROR, "Async event parsing failed for operation %d",
+ twt_operation_type);
+ goto fail;
+ }
+ wpa_printf(MSG_ERROR,"%s", buf);
+ wpa_msg(drv->ctx, MSG_INFO, "%s", buf);
+fail:
+ free(buf);
+ return ret;
+}
+
+static int wpa_driver_form_clear_mcc_quota_msg(struct i802_bss *bss,
+ char *cmd)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nlattr *nl_attr;
+ struct nl_msg *nlmsg;
+ uint32_t if_index = 0;
+ int ret;
+
+ /* First comes interface name - optional */
+ if (os_strncasecmp(cmd, "iface", 5) == 0) {
+ char *iface;
+ cmd = move_to_next_str(cmd);
+ /* null terminate the iface name in the cmd string */
+ iface = strchr(cmd, ' ');
+ if (iface == NULL) {
+ wpa_printf(MSG_ERROR, "mcc_quota: iface is not found"
+ " in cmd string");
+ return -EINVAL;
+ }
+ *iface = '\0';
+ iface = cmd;
+ errno = 0;
+ if_index = if_nametoindex(cmd);
+ if (if_index == 0) {
+ wpa_printf(MSG_ERROR, "mcc_quota: iface %s not found %d",
+ cmd, errno);
+ return -EINVAL;
+ }
+ wpa_printf(MSG_INFO, "mcc_quota: ifindex %u", if_index);
+ cmd += strlen(iface) + 1;
+ }
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to allocate nl message");
+ return -ENOMEM;
+ }
+
+ nl_attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!nl_attr) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to alloc nlattr");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ /* Put the quota type */
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to add type attr %d", ret);
+ goto fail;
+ }
+
+ if (if_index) {
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX, if_index);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to add if_index attr %d", ret);
+ goto fail;
+ }
+ }
+ nla_nest_end(nlmsg, nl_attr);
+
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Error sending nlmsg %d", ret);
+ return ret;
+ }
+
+ return 0;
+fail:
+ nlmsg_free(nlmsg);
+ return ret;
+}
+
+static int wpa_driver_form_set_mcc_quota_msg(struct i802_bss *bss,
+ char *cmd)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct mcc_quota mccquota[MCC_QUOTA_ENTRIES_MAX];
+ uint32_t if_index, quota;
+ struct nlattr *nl_attr, *mcc_attr_list;
+ struct nlattr *mcc_attr;
+ struct nl_msg *nlmsg;
+ int ret, entry, i;
+
+ wpa_printf(MSG_INFO, "mcc_quota: %s", cmd);
+
+ entry = 0;
+ while (*cmd != '\0') {
+ if (entry >= MCC_QUOTA_ENTRIES_MAX) {
+ wpa_printf(MSG_INFO, "mcc_quota: Only %d entries accepted", entry);
+ break;
+ }
+ /* First comes interface name */
+ if (os_strncasecmp(cmd, "iface", 5) == 0) {
+ char *iface;
+ cmd = move_to_next_str(cmd);
+ /* null terminate the iface name in the cmd string */
+ iface = strchr(cmd, ' ');
+ if (iface == NULL) {
+ wpa_printf(MSG_ERROR, "mcc_quota: iface is not"
+ " found in cmd string");
+ return -EINVAL;
+ }
+ *iface = '\0';
+ iface = cmd;
+ errno = 0;
+ if_index = if_nametoindex(cmd);
+ if (if_index == 0) {
+ wpa_printf(MSG_ERROR, "mcc_quota: iface %s not found %d",
+ cmd, errno);
+ return -EINVAL;
+ }
+ wpa_printf(MSG_INFO, "mcc_quota: ifindex %u", if_index);
+ cmd += strlen(iface) + 1;
+ } else {
+ wpa_printf(MSG_ERROR, "mcc_quota: Iface name not in order");
+ return -EINVAL;
+ }
+
+ /* Second comes quota value */
+ if (os_strncasecmp(cmd, "quota", 5) == 0) {
+ cmd = move_to_next_str(cmd);
+ quota = get_u32_from_string(cmd, &ret);
+ if (ret < 0)
+ return ret;
+ } else {
+ wpa_printf(MSG_ERROR, "mcc_quota: Quota not in order");
+ return -EINVAL;
+ }
+
+ if (quota < MCC_QUOTA_MIN || quota > MCC_QUOTA_MAX) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Invalid quota value %u", quota);
+ return -EINVAL;
+ }
+
+ mccquota[entry].if_idx = if_index;
+ mccquota[entry].quota = quota;
+ cmd = move_to_next_str(cmd);
+ entry++;
+ }
+ wpa_printf(MSG_INFO, "mcc_quota: Entries : %d", entry);
+ if (entry < 1) {
+ wpa_printf(MSG_ERROR, "mcc_quota: No valid entries?");
+ return -EINVAL;
+ }
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR,"mcc_quota: Failed to allocate nl message");
+ return -ENOMEM;
+ }
+
+ nl_attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (nl_attr == NULL) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to alloc nlattr");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* Put the quota type */
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to add type attr %d", ret);
+ goto fail;
+ }
+
+ mcc_attr_list = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES);
+ if (!mcc_attr_list) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to alloc mcc_attr_list");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ for (i = 0; i < entry && entry <= MCC_QUOTA_ENTRIES_MAX; i++) {
+ /* Nest the (iface ,quota) */
+ mcc_attr = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES);
+ if (mcc_attr == NULL) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to alloc mccattr");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX, mccquota[i].if_idx);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to add if_index attr %d", ret);
+ goto fail;
+ }
+
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE, mccquota[i].quota);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Failed to add quota attr %d", ret);
+ goto fail;
+ }
+
+ nla_nest_end(nlmsg, mcc_attr);
+ }
+ nla_nest_end(nlmsg, mcc_attr_list);
+
+ nla_nest_end(nlmsg, nl_attr);
+
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+
+ if (ret) {
+ wpa_printf(MSG_ERROR, "mcc_quota: Error sending nlmsg %d", ret);
+ return ret;
+ }
+
+ return 0;
+fail:
+ nlmsg_free(nlmsg);
+ return ret;
+}
+
+int wpa_driver_cmd_send_mcc_quota(struct i802_bss *bss,
+ char *cmd)
+{
+ int ret;
+
+ wpa_printf(MSG_INFO, "mcc_quota: %s", cmd);
+
+ if (os_strncasecmp(cmd, "set", 3) == 0) {
+ cmd = move_to_next_str(cmd);
+ ret = wpa_driver_form_set_mcc_quota_msg(bss, cmd);
+ return ret;
+ }
+
+ if (os_strncasecmp(cmd, "clear", 5) == 0) {
+ cmd = move_to_next_str(cmd);
+ ret = wpa_driver_form_clear_mcc_quota_msg(bss, cmd);
+ return ret;
+ }
+
+ wpa_printf(MSG_ERROR, "mcc_quota: Unknown operation");
+ return -EINVAL;
+}
+
+static int wpa_driver_form_flush_queue_config_msg(struct i802_bss *bss, char *cmd)
+{
+ uint32_t tid_mask = 0, flush_policy = 0;
+ u8 mac[MAC_ADDR_LEN], ac_mask = 0;
+ struct nl_msg *nlmsg = NULL;
+ struct nlattr *nl_attr;
+ char *ptr = cmd;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "flush_queue_config: %s", cmd);
+
+ /* First parameter: MAC address of peer */
+ if (os_strncasecmp(cmd, "peer", 4) == 0) {
+ cmd = move_to_next_str(cmd);
+ if ((strlen(cmd) < (MAC_ADDR_LEN * 2 + MAC_ADDR_LEN - 1)) ||
+ convert_string_to_bytes(mac, cmd, MAC_ADDR_LEN) !=
+ MAC_ADDR_LEN) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Invalid MAC address");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ } else {
+ wpa_printf(MSG_ERROR, "flush_queue_config: peer MAC address is missing");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return -EINVAL;
+ }
+
+ /* Second parameter: flush config */
+ if (os_strncasecmp(cmd, "policy", 6) == 0) {
+ cmd = move_to_next_str(cmd);
+ flush_policy = get_u32_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Invalid flush policy");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return ret;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ /* Third parameter: Follow QCA_WLAN_VENDOR_ATTR_AC for ac bit mask */
+ if (os_strncasecmp(cmd, "ac", 2) == 0) {
+ cmd = move_to_next_str(cmd);
+ ac_mask = get_u8_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: AC mask error");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return ret;
+ }
+
+ if (!(ac_mask & (BIT(QCA_WLAN_VENDOR_TOS_BK) | BIT(QCA_WLAN_VENDOR_TOS_BE) |
+ BIT(QCA_WLAN_VENDOR_TOS_VI) | BIT(QCA_WLAN_VENDOR_TOS_VO)))) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Invalid AC mask");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ /* Fourth parameter: tid mask */
+ if (os_strncasecmp(cmd, "tid", 3) == 0) {
+ cmd = move_to_next_str(cmd);
+ tid_mask = get_u32_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: TID mask error");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return ret;
+ }
+ cmd = move_to_next_str(cmd);
+ }
+
+ if (!tid_mask && !ac_mask) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Neither TID not AC mask provided");
+ wpa_printf(MSG_ERROR, "flush_queue_config cmd: %s", ptr);
+ return -EINVAL;
+ }
+
+ nlmsg =
+ prepare_vendor_nlmsg(bss->drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Failed to allocate nl message");
+ return -ENOMEM;
+ }
+
+ nl_attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!nl_attr) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Failed to alloc nlattr");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* Put the peer MAC address */
+ ret = nla_put(nlmsg, QCA_WLAN_VENDOR_ATTR_PEER_ADDR, MAC_ADDR_LEN, mac);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Error add hw addr attr %d", ret);
+ goto fail;
+ }
+
+ /* Put the flush_policy */
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY,
+ flush_policy);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "flush_queue_config: Error add policy attr %d", ret);
+ goto fail;
+ }
+
+ if (tid_mask) {
+ /* Put the tid mask */
+ ret = nla_put_u32(nlmsg, QCA_WLAN_VENDOR_ATTR_TID_MASK,
+ tid_mask);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Error add tid mask attr %d", ret);
+ goto fail;
+ }
+ } else {
+ /* Put the ac mask */
+ ret = nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_AC, ac_mask);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Error add ac attr %d", ret);
+ goto fail;
+ }
+ }
+
+ nla_nest_end(nlmsg, nl_attr);
+ ret = send_nlmsg((struct nl_sock *)bss->drv->global->nl, nlmsg,
+ NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "flush_queue_config: Error sending nlmsg %d", ret);
+ return ret;
+ }
+ return 0;
+fail:
+ if (nlmsg)
+ nlmsg_free(nlmsg);
+ return ret;
+}
+
+int wpa_driver_cmd_send_peer_flush_queue_config(struct i802_bss *bss, char *cmd)
+{
+ int ret;
+
+ if (os_strncasecmp(cmd, "set", 3) == 0) {
+ cmd = move_to_next_str(cmd);
+ ret = wpa_driver_form_flush_queue_config_msg(bss, cmd);
+ return ret;
+ }
+
+ wpa_printf(MSG_ERROR, "peer_flush_config: Unknown operation");
+ return -EINVAL;
+}
+
+int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
+ size_t buf_len )
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = NULL;
+ struct wpa_driver_nl80211_data *driver;
+ struct ifreq ifr;
+ android_wifi_priv_cmd priv_cmd;
+ int ret = 0, status = 0, lib_n = 0;
+
+ if (bss) {
+ drv = bss->drv;
+ } else {
+ if (os_strncasecmp(cmd, "SET_AP_SUSPEND", 14)) {
+ wpa_printf(MSG_ERROR, "%s: bss is NULL for cmd %s\n",
+ __func__, cmd);
+ return -EINVAL;
+ }
+ }
+
+ if (wpa_driver_oem_initialize(&oem_cb_table) != WPA_DRIVER_OEM_STATUS_FAILURE &&
+ oem_cb_table) {
+
+ for (lib_n = 0;
+ oem_cb_table[lib_n].wpa_driver_driver_cmd_oem_cb != NULL;
+ lib_n++)
+ {
+ ret = oem_cb_table[lib_n].wpa_driver_driver_cmd_oem_cb(
+ priv, cmd, buf, buf_len, &status);
+ if (ret == WPA_DRIVER_OEM_STATUS_SUCCESS ) {
+ return strlen(buf);
+ } else if (ret == WPA_DRIVER_OEM_STATUS_ENOSUPP) {
+ continue;
+ } else if ((ret == WPA_DRIVER_OEM_STATUS_FAILURE) &&
+ (status != 0)) {
+ wpa_printf(MSG_DEBUG, "%s: Received error: %d",
+ __func__, status);
+ return status;
+ }
+ }
+ /* else proceed with legacy handling as below */
+ }
+
+ if (!drv) {
+ wpa_printf(MSG_ERROR, "%s: drv is NULL for cmd %s\n",
+ __func__, cmd);
+ return -EINVAL;
+ }
+
+ if (os_strcasecmp(cmd, "START") == 0) {
+ dl_list_for_each(driver, &drv->global->interfaces, struct wpa_driver_nl80211_data, list) {
+ linux_set_iface_flags(drv->global->ioctl_sock, driver->first_bss->ifname, 1);
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+ }
+ } else if (os_strcasecmp(cmd, "MACADDR") == 0) {
+ u8 macaddr[ETH_ALEN] = {};
+
+ ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr);
+ 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, "CSI", 3) == 0) {
+ cmd += 3;
+ return wpa_driver_handle_csi_cmd(bss, cmd, buf, buf_len, &status);
+ } else if(os_strncasecmp(cmd, "GETSTATSBSSINFO", 15) == 0) {
+
+ struct resp_info info,info2;
+ struct nl_msg *nlmsg;
+ struct nlattr *attr;
+
+ os_memset(&g_bss_info, 0, sizeof(struct bss_info));
+
+ memset(&info, 0, sizeof(struct resp_info));
+ memset(&info2, 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);
+
+ u8 mac[MAC_ADDR_LEN];
+
+ 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) {
+ wpa_printf(MSG_INFO,"invoking QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO to retrieve new attributes");
+ os_memcpy(&info2.mac_addr[0], mac, MAC_ADDR_LEN);
+ nlmsg = prepare_vendor_nlmsg(bss->drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO);
+ 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, GET_STA_INFO_MAC,
+ MAC_ADDR_LEN, mac)) {
+ wpa_printf(MSG_ERROR,"Failed to put GET_STA_INFO_MAC");
+ nlmsg_free(nlmsg);
+ return -1;
+ }
+
+ nla_nest_end(nlmsg, attr);
+
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+ get_sta_info_handler, &info2);
+ if (ret != 0) {
+ if (ret == -EOPNOTSUPP) {
+ wpa_printf(MSG_INFO,"Command is not supported, sending -1 for all new vendor attributes");
+ } else {
+ wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", ret);
+ return -1;
+ }
+ g_bss_info.ani_level = -1;
+ g_bss_info.roam_trigger_reason = -1;
+ g_bss_info.roam_fail_reason = -1;
+ g_bss_info.roam_invoke_fail_reason = -1;
+ g_bss_info.tsf_out_of_sync_count = -1;
+ g_bss_info.latest_tx_power = -1;
+ g_bss_info.latest_tx_rate = -1;
+ g_bss_info.target_power_24g_1mbps = -1;
+ g_bss_info.target_power_24g_6mbps = -1;
+ g_bss_info.target_power_5g_6mbps = -1;
+ } else {
+ wpa_printf(MSG_INFO,"Command successfully invoked");
+ g_bss_info.ani_level = g_sta_info.ani_level;
+ g_bss_info.roam_trigger_reason = g_sta_info.roam_trigger_reason;
+ g_bss_info.roam_fail_reason = g_sta_info.roam_fail_reason;
+ g_bss_info.roam_invoke_fail_reason = g_sta_info.roam_invoke_fail_reason;
+ g_bss_info.tsf_out_of_sync_count = g_sta_info.tsf_out_of_sync_count;
+ g_bss_info.latest_tx_power = g_sta_info.latest_tx_power;
+ g_bss_info.latest_tx_rate = g_sta_info.latest_tx_rate;
+ g_bss_info.target_power_24g_1mbps = g_sta_info.target_power_24g_1mbps;
+ g_bss_info.target_power_24g_6mbps = g_sta_info.target_power_24g_6mbps;
+ g_bss_info.target_power_5g_6mbps = g_sta_info.target_power_5g_6mbps;
+ }
+ }
+
+ 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 if (os_strncasecmp(cmd, "SETCELLSWITCHMODE", 17) == 0) {
+ cmd += 17;
+ struct resp_info info;
+ struct nl_msg *nlmsg;
+
+ memset(&info, 0, sizeof(struct resp_info));
+
+ info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM;
+ info.cmd_type = SETCELLSWITCHMODE;
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ info.subcmd);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR,"Failed to allocate nl message");
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ if (populate_nlmsg(nlmsg, cmd, info.cmd_type)) {
+ wpa_printf(MSG_ERROR,"Failed to populate nl message");
+ nlmsg_free(nlmsg);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
+ NULL, NULL);
+ if (status != 0) {
+ wpa_printf(MSG_ERROR,"Failed to send nl message with err %d", status);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+ } else if (os_strncasecmp(cmd, "SET_ANI_LEVEL ", 14) == 0) {
+ char *endptr = NULL;
+ int mode = 0;
+ int ofdmlvl = 0;
+ mode = strtol(cmd + 14, &endptr, 10);
+ if (mode == 1) {
+ if(!(*endptr)) {
+ wpa_printf(MSG_ERROR, "%s: failed to set ani setting,\
+ invalid cmd: %s\n", __func__, cmd);
+ return -EINVAL;
+ }
+ ofdmlvl = strtol(endptr, NULL, 10);
+ }
+ return wpa_driver_cmd_set_ani_level(priv, mode, ofdmlvl);
+ } else if (os_strncasecmp(cmd, "GET_THERMAL_INFO", 16) == 0) {
+ int temperature = -1;
+ int thermal_state = -1;
+ int ret, ret2;
+
+ ret = wpa_driver_cmd_get_thermal_info(priv, &temperature,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE);
+ if (ret)
+ return -1;
+ ret2 = wpa_driver_cmd_get_thermal_info(priv, &thermal_state,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL);
+ if (ret2)
+ return -1;
+
+ snprintf(buf, buf_len, "%d %d", temperature, thermal_state);
+ return strlen(buf);
+ } else if (os_strncasecmp(cmd, "GET_DRIVER_SUPPORTED_FEATURES", 29) == 0) {
+ struct resp_info info;
+ struct nl_msg *nlmsg;
+ memset(&info, 0, sizeof(struct resp_info));
+ info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES;
+ 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;
+ }
+
+ 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 WPA_DRIVER_OEM_STATUS_SUCCESS;
+ } else if ((ret = check_for_twt_cmd(&cmd)) != TWT_CMD_NOT_EXIST) {
+ enum qca_wlan_twt_operation twt_oper = ret;
+ u8 is_twt_feature_supported = 0;
+
+ if (oem_cb_table) {
+ for (lib_n = 0;
+ oem_cb_table[lib_n].wpa_driver_driver_cmd_oem_cb != NULL;
+ lib_n++)
+ {
+ if (oem_cb_table[lib_n].wpa_driver_oem_feature_check_cb) {
+ if (oem_cb_table[lib_n].wpa_driver_oem_feature_check_cb(FEATURE_TWT_SUPPORT))
+ is_twt_feature_supported = 1;
+ break;
+ }
+ }
+ }
+
+ if (is_twt_feature_supported) {
+ wpa_printf(MSG_ERROR, "%s: TWT feature already supported by oem lib %d\n", __func__, lib_n);
+ ret = -EINVAL;
+ } else {
+ ret = wpa_driver_twt_cmd_handler(drv, bss->ifname, twt_oper, cmd, buf, buf_len,
+ &status);
+ if (ret)
+ ret = os_snprintf(buf, buf_len, "TWT failed for operation %d", twt_oper);
+ }
+ } else if (os_strncasecmp(cmd, "MCC_QUOTA", 9) == 0) {
+ /* DRIVER MCC_QUOTA set iface <name> quota <val>
+ * DRIVER MCC_QUOTA clear iface <name>
+ */
+ /* Move cmd by string len and space */
+ cmd += 10;
+ return wpa_driver_cmd_send_mcc_quota(priv, cmd);
+ } else if (os_strncasecmp(cmd, "FLUSH_QUEUE_CONFIG", 18) == 0) {
+ /* DRIVER FLUSH_QUEUE_CONFIG set peer <mac addr> policy <val>
+ * tid <tid mask> ac <ac mask>
+ */
+ /* Move cmd by string len and space */
+ cmd += 19;
+ return wpa_driver_cmd_send_peer_flush_queue_config(priv, cmd);
+ } else { /* Use private command */
+ memset(&ifr, 0, sizeof(ifr));
+ memset(&priv_cmd, 0, sizeof(priv_cmd));
+ os_memcpy(buf, cmd, strlen(cmd) + 1);
+ os_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 ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) {
+ wpa_printf(MSG_ERROR, "%s: failed to issue private commands, ret:%d, errno:%d\n", __func__, ret, errno);
+ } else {
+ drv_errors = 0;
+ if((os_strncasecmp(cmd, "SETBAND", 7) == 0) &&
+ ret == DO_NOT_SEND_CHANNEL_CHANGE_EVENT) {
+ return 0;
+ }
+
+ ret = 0;
+ if ((os_strcasecmp(cmd, "LINKSPEED") == 0) ||
+ (os_strcasecmp(cmd, "RSSI") == 0) ||
+ (os_strstr(cmd, "GET") != NULL))
+ ret = strlen(buf);
+ else if (os_strcasecmp(cmd, "P2P_DEV_ADDR") == 0)
+ wpa_printf(MSG_DEBUG, "%s: P2P: Device address ("MACSTR")",
+ __func__, MAC2STR(buf));
+ else if (os_strcasecmp(cmd, "P2P_SET_PS") == 0)
+ wpa_printf(MSG_DEBUG, "%s: P2P: %s ", __func__, buf);
+ else if (os_strcasecmp(cmd, "P2P_SET_NOA") == 0)
+ wpa_printf(MSG_DEBUG, "%s: P2P: %s ", __func__, buf);
+ else if (os_strcasecmp(cmd, "STOP") == 0) {
+ wpa_printf(MSG_DEBUG, "%s: %s ", __func__, buf);
+ dl_list_for_each(driver, &drv->global->interfaces, struct wpa_driver_nl80211_data, list) {
+ linux_set_iface_flags(drv->global->ioctl_sock, driver->first_bss->ifname, 0);
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
+ }
+ }
+ else
+ wpa_printf(MSG_DEBUG, "%s %s len = %d, %zu", __func__, buf, ret, buf_len);
+ wpa_driver_notify_country_change(drv->ctx, cmd);
+ }
+ }
+ return ret;
+}
+
+int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
+{
+ char buf[MAX_DRV_CMD_SIZE];
+ char reply_buf[MAX_DRV_CMD_SIZE];
+
+ memset(buf, 0, sizeof(buf));
+ memset(reply_buf, 0, sizeof(reply_buf));
+ wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+ snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration);
+ return wpa_driver_nl80211_driver_cmd(priv, buf, reply_buf, sizeof(reply_buf));
+}
+
+int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
+{
+ UNUSED(priv), UNUSED(buf), UNUSED(len);
+ /* Return 0 till we handle p2p_presence request completely in the driver */
+ return 0;
+}
+
+int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
+{
+ char buf[MAX_DRV_CMD_SIZE];
+ char reply_buf[MAX_DRV_CMD_SIZE];
+
+ memset(buf, 0, sizeof(buf));
+ memset(reply_buf, 0, sizeof(reply_buf));
+ wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
+ snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow);
+ return wpa_driver_nl80211_driver_cmd(priv, buf, reply_buf, sizeof(reply_buf));
+}
+
+int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
+ const struct wpabuf *proberesp,
+ const struct wpabuf *assocresp)
+{
+ UNUSED(priv), UNUSED(beacon), UNUSED(proberesp), UNUSED(assocresp);
+ return 0;
+}
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.c b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.c
new file mode 100644
index 0000000..7df7166
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.c
@@ -0,0 +1,185 @@
+/* Copyright (c) 2016, 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.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+ */
+
+#include <netlink/object-api.h>
+#include <linux/pkt_sched.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <string.h>
+#include "common.h"
+#include "driver_cmd_nl80211_extn.h"
+
+#define QCA_NL80211_VENDOR_SUBCMD_DIAG_DATA 201
+#define MAX_OEM_LIBS 5
+#define MAX_LIB_NAME_SIZE 30
+#define CB_SUFFIX "_cb"
+static wpa_driver_oem_cb_table_t oem_cb_array[MAX_OEM_LIBS + 1];
+
+void wpa_msg_handler(struct wpa_driver_nl80211_data *drv, char *msg, u32 subcmd) {
+ if (subcmd == QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) {
+ wpa_msg(drv->ctx, MSG_INFO, "%s", msg);
+ }
+}
+
+int wpa_driver_oem_initialize(wpa_driver_oem_cb_table_t **oem_cb_table)
+{
+ wpa_driver_oem_get_cb_table_t *get_oem_table;
+ wpa_driver_oem_cb_table_t *oem_cb_table_local;
+ struct dirent *entry;
+ void *oem_handle_n;
+ char cb_sym_name[MAX_LIB_NAME_SIZE], *tmp;
+ DIR *oem_lib_dir;
+ unsigned int lib_n;
+#ifdef ANDROID
+#if __WORDSIZE == 64
+ char *oem_lib_path = "/vendor/lib64/";
+#else
+ char *oem_lib_path = "/vendor/lib/";
+#endif
+#else
+ char *oem_lib_path = "/usr/lib/";
+#endif
+ /* Return the callback table if it is already initialized*/
+ if (*oem_cb_table)
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+
+ for (lib_n = 0; lib_n < MAX_OEM_LIBS; lib_n++) {
+ oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb = NULL;
+ oem_cb_array[lib_n].wpa_driver_nl80211_driver_oem_event = NULL;
+ oem_cb_array[lib_n].wpa_driver_oem_feature_check_cb = NULL;
+ }
+
+ oem_lib_dir = opendir(oem_lib_path);
+ if (!oem_lib_dir) {
+ wpa_printf(MSG_ERROR, "%s: Unable to open %s", __FUNCTION__, oem_lib_path);
+ return WPA_DRIVER_OEM_STATUS_FAILURE;
+ }
+
+ lib_n = 0;
+ while((entry = readdir(oem_lib_dir)) != NULL) {
+ if (strncmp(entry->d_name, "libwpa_drv_oem", 14))
+ continue;
+
+ wpa_printf(MSG_DEBUG, "%s: Opening lib %s", __FUNCTION__, entry->d_name);
+ oem_handle_n = dlopen(entry->d_name, RTLD_NOW);
+
+ if (!oem_handle_n) {
+ wpa_printf(MSG_ERROR, "%s: Could not load %s", __FUNCTION__, entry->d_name);
+ /* let's not worry much, continue with others */
+ continue;
+ }
+
+ if (strlen(entry->d_name) >= (sizeof(cb_sym_name) - sizeof(CB_SUFFIX))) {
+ wpa_printf(MSG_ERROR, "%s: libname (%s) too lengthy", __FUNCTION__, entry->d_name);
+ continue;
+ }
+
+ os_strlcpy(cb_sym_name, entry->d_name, sizeof(cb_sym_name));
+ tmp = strchr(cb_sym_name, '.');
+ if (!tmp) {
+ wpa_printf(MSG_ERROR, "%s: libname (%s) incorrect?", __FUNCTION__, entry->d_name);
+ continue;
+ }
+
+ os_strlcpy(tmp, CB_SUFFIX, sizeof(CB_SUFFIX));
+ wpa_printf(MSG_DEBUG, "%s: Loading sym %s", __FUNCTION__, cb_sym_name);
+
+ /* Get the lib's function table callback */
+ get_oem_table = (wpa_driver_oem_get_cb_table_t *)dlsym(oem_handle_n,
+ cb_sym_name);
+
+ if (!get_oem_table) {
+ wpa_printf(MSG_ERROR, "%s: Could not get sym table", __FUNCTION__);
+ continue;
+ }
+
+ oem_cb_table_local = get_oem_table();
+
+ oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb =
+ oem_cb_table_local->wpa_driver_driver_cmd_oem_cb;
+ oem_cb_array[lib_n].wpa_driver_nl80211_driver_oem_event =
+ oem_cb_table_local->wpa_driver_nl80211_driver_oem_event;
+ oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb =
+ oem_cb_table_local->wpa_driver_driver_wpa_msg_oem_cb;
+ oem_cb_array[lib_n].wpa_driver_oem_feature_check_cb =
+ oem_cb_table_local->wpa_driver_oem_feature_check_cb;
+
+ /* Register wpa message callback with the oem library */
+ if(oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb) {
+ oem_cb_array[lib_n].wpa_driver_driver_wpa_msg_oem_cb(wpa_msg_handler);
+ }
+
+ lib_n++;
+
+ if (lib_n == MAX_OEM_LIBS) {
+ wpa_printf(MSG_DEBUG, "%s: Exceeded max libs %d", __FUNCTION__, lib_n);
+ break;
+ }
+ }
+
+ oem_cb_array[lib_n].wpa_driver_driver_cmd_oem_cb = NULL;
+ *oem_cb_table = oem_cb_array;
+ wpa_printf(MSG_DEBUG, "%s: OEM lib initialized\n", __func__);
+ closedir(oem_lib_dir);
+
+ return WPA_DRIVER_OEM_STATUS_SUCCESS;
+}
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.h b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.h
new file mode 100755
index 0000000..6246602
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_extn.h
@@ -0,0 +1,99 @@
+/* Copyright (c) 2016, 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.
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 __DRIVER_CMD_NL80211_EXTN__
+#define __DRIVER_CMD_NL80211_EXTN__
+
+#include "qca-vendor_copy.h"
+#include <stdbool.h>
+#include <sys/types.h>
+#include "driver_nl80211.h"
+
+
+#define IFNAMSIZ 16
+
+enum wpa_driver_oem_status {
+ WPA_DRIVER_OEM_STATUS_SUCCESS = 0,
+ WPA_DRIVER_OEM_STATUS_FAILURE = -1,
+ WPA_DRIVER_OEM_STATUS_ENOSUPP = -2,
+};
+
+#define FEATURE_TWT_SUPPORT 0x0001
+
+/*
+ * This structure is a table of function pointers to the functions
+ * used by the wpa_supplicant_lib to interface with oem specific APIs
+ */
+typedef struct
+{
+ int (*wpa_driver_driver_cmd_oem_cb)(void *priv,
+ char *cmd, char *buf, size_t buf_len, int *status);
+ int (*wpa_driver_nl80211_driver_oem_event)(struct wpa_driver_nl80211_data *drv,
+ u32 vendor_id, u32 subcmd, u8 *data, size_t len);
+ void (*wpa_driver_driver_wpa_msg_oem_cb)(void(*)(struct wpa_driver_nl80211_data *drv,
+ char *msg, u32 subcmd));
+ int (*wpa_driver_oem_feature_check_cb)(u32 feature);
+} wpa_driver_oem_cb_table_t;
+
+typedef wpa_driver_oem_cb_table_t* (wpa_driver_oem_get_cb_table_t)();
+
+int wpa_driver_oem_initialize(wpa_driver_oem_cb_table_t **oem_lib_params);
+#endif
diff --git a/qcwcn/wifi_hal/qca-vendor_copy.h b/wcn6740/qcwcn/wpa_supplicant_8_lib/qca-vendor_copy.h
similarity index 79%
copy from qcwcn/wifi_hal/qca-vendor_copy.h
copy to wcn6740/qcwcn/wpa_supplicant_8_lib/qca-vendor_copy.h
index 11442ee..40b0cd4 100644
--- a/qcwcn/wifi_hal/qca-vendor_copy.h
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/qca-vendor_copy.h
@@ -1,7 +1,7 @@
/*
* Qualcomm Atheros OUI and vendor specific assignments
* Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
- * Copyright (c) 2018-2019, The Linux Foundation
+ * Copyright (c) 2018-2021, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -512,7 +512,9 @@
* @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
* configure parameters per peer to capture Channel Frequency Response
* (CFR) and enable Periodic CFR capture. The attributes for this command
- * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command
+ * can also be used to send CFR data from the driver to userspace when
+ * netlink events are used to send CFR data.
*
* @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
* in throughput dynamically. The driver estimates the throughput based on
@@ -620,7 +622,14 @@
* This new command is alternative to existing command
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
* is using stream of bytes instead of structured data using vendor
- * attributes.
+ * attributes. User space sends unsafe frequency ranges to the driver using
+ * a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
+ * reception of this command, the driver shall check if an interface is
+ * operating on an unsafe frequency and the driver shall try to move to a
+ * safe channel when needed. If the driver is not able to find a safe
+ * channel the interface can keep operating on an unsafe channel with the
+ * TX power limit derived based on internal configurations like
+ * regulatory/SAR rules.
*
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
* add the STA node details in driver/firmware. Attributes for this event
@@ -664,36 +673,121 @@
* qca_wlan_vendor_attr_driver_disconnect_reason.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to
- * add/delete TSPEC for each AC. One command is for one specific AC only.
- * This command can only be used in STA mode and the STA must be
- * associated with an AP when the command is issued. Uses attributes
- * defined in enum qca_wlan_vendor_attr_config_tspec.
+ * add/delete TSPEC for each AC. One command is for one specific AC only.
+ * This command can only be used in STA mode and the STA must be
+ * associated with an AP when the command is issued. Uses attributes
+ * defined in enum qca_wlan_vendor_attr_config_tspec.
*
* @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT.
- * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt.
*
* @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from
- * the driver. The band configurations obtained are referred through
- * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
+ * the driver. The band configurations obtained are referred through
+ * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK.
*
* @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium
- * assessment.
- * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
+ * assessment.
+ * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess.
*
* @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is
- * used to update SSID information in hostapd when it is updated in the
- * driver. Uses the attribute NL80211_ATTR_SSID.
+ * used to update SSID information in hostapd when it is updated in the
+ * driver. Uses the attribute NL80211_ATTR_SSID.
*
* @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by
- * the driver to send opaque data from the firmware to userspace. The
- * driver sends an event to userspace whenever such data is received from
- * the firmware.
+ * the driver to send opaque data from the firmware to userspace. The
+ * driver sends an event to userspace whenever such data is received from
+ * the firmware.
*
- * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
- * send this opaque data for this event.
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to
+ * send this opaque data for this event.
*
- * The format of the opaque data is specific to the particular firmware
- * version and there is no guarantee of the format remaining same.
+ * The format of the opaque data is specific to the particular firmware
+ * version and there is no guarantee of the format remaining same.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event.
+ * The host driver selects Tx VDEV, and notifies user. The attributes
+ * used with this event are defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_status.
+ * This event contains Tx VDEV group information, other VDEVs
+ * interface index, and status information.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY: Vendor command to
+ * configure the concurrent session policies when multiple STA interfaces
+ * are (getting) active. The attributes used by this command are defined
+ * in enum qca_wlan_vendor_attr_concurrent_sta_policy.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command
+ * to query usable channels for different interface types such as STA,
+ * AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable
+ * channels in the response based on country code, different static
+ * configurations, concurrency combinations, etc. The attributes used
+ * with this command are defined in
+ * enum qca_wlan_vendor_attr_usable_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used
+ * to get DFS radar history from the driver to userspace. The driver
+ * returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an
+ * array of nested entries.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to
+ * enable/disable mDNS offload to the firmware. The attributes used with
+ * this command are defined in enum qca_wlan_vendor_attr_mdns_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used
+ * to set packet monitor mode that aims to send the specified set of TX and
+ * RX frames on the current client interface to an active monitor
+ * interface. If this monitor mode is set, the driver will send the
+ * configured frames, from the interface on which the command is issued, to
+ * an active monitor interface. The attributes used with this command are
+ * defined in enum qca_wlan_vendor_attr_set_monitor_mode.
+ *
+ * Though the monitor mode is configured for the respective
+ * Data/Management/Control frames, it is up to the respective WLAN
+ * driver/firmware/hardware designs to consider the possibility of sending
+ * these frames over the monitor interface. For example, the Control frames
+ * are handled within the hardware and thus passing such frames over the
+ * monitor interface is left to the respective designs.
+ *
+ * Also, this monitor mode is governed to behave accordingly in
+ * suspend/resume states. If the firmware handles any of such frames in
+ * suspend state without waking up the host and if the monitor mode is
+ * configured to notify all such frames, the firmware is expected to resume
+ * the host and forward the respective frames to the monitor interface.
+ * Please note that such a request to get the frames over the monitor
+ * interface will have a definite power implication.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both
+ * as a request to set the driver/firmware with the parameters to trigger
+ * the roaming events, and also used by the driver/firmware to pass on the
+ * various roam events to userspace.
+ * Applicable only for the STA mode. The attributes used with this command
+ * are defined in enum qca_wlan_vendor_attr_roam_events.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG: Subcommand to set or reset the
+ * rate mask config for a list of PHY types. Userspace shall provide an
+ * array of the vendor attributes defined in
+ * enum qca_wlan_vendor_attr_ratemask_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA: Multi-channel Concurrency (MCC) occurs
+ * when two interfaces are active on the same band, using two different
+ * home channels, and only supported by a single radio. In this scenario
+ * the device must split the use of the radio between the two interfaces.
+ * The percentage of time allocated to a given interface is the quota.
+ * Depending on the configuration, the quota can either be fixed or
+ * dynamic.
+ *
+ * When used as an event, the device will report the quota type, and for
+ * all interfaces operating in MCC it will report the current quota.
+ * When used as a command, the device can be configured for a specific
+ * quota type, and in the case of a fixed quota, the quota to apply to one
+ * of the interfaces.
+ *
+ * Applications can use the event to do TX bitrate control based on the
+ * information, and can use the command to explicitly set the quota to
+ * enhance performance in specific scenarios.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_mcc_quota.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -879,6 +973,16 @@
QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193,
QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194,
QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195,
+ QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196,
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199,
+ QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200,
+ /* 201 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203,
+ QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG = 204,
+ QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA = 205,
};
enum qca_wlan_vendor_attr {
@@ -1117,7 +1221,7 @@
* @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
* or environment being very noisy or congested.
*
- * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
* from the user (user space).
*
* @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
@@ -1125,6 +1229,26 @@
*
* @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
* breaching out the configured threshold.
+ *
+ * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
+ * transition request.
+ *
+ * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no
+ * data activity with the AP and the current RSSI falls below a certain
+ * threshold.
+ *
+ * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or
+ * Disassociation frames received from the connected AP.
+ *
+ * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan
+ * that happens when there is no candidate AP found during the poor RSSI scan
+ * trigger.
+ *
+ * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results
+ * obtained from an external scan (not aimed at roaming).
+ *
+ * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is
+ * established when the station is connected in the 2.4 GHz band.
*/
enum qca_roam_reason {
QCA_ROAM_REASON_UNKNOWN,
@@ -1136,6 +1260,12 @@
QCA_ROAM_REASON_USER_TRIGGER,
QCA_ROAM_REASON_BTM,
QCA_ROAM_REASON_BSS_LOAD,
+ QCA_ROAM_REASON_WTC,
+ QCA_ROAM_REASON_IDLE,
+ QCA_ROAM_REASON_DISCONNECTION,
+ QCA_ROAM_REASON_PERIODIC_TIMER,
+ QCA_ROAM_REASON_BACKGROUND_SCAN,
+ QCA_ROAM_REASON_BT_ACTIVITY,
};
enum qca_wlan_vendor_attr_roam_auth {
@@ -1355,6 +1485,16 @@
* Used with event to notify the EDMG channel number selected in ACS
* operation.
* EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16).
+ * Used with event to notify the puncture pattern selected in ACS operation.
+ * Encoding for this attribute will follow the convention used in the Disabled
+ * Subchannel Bitmap field of the EHT Operation IE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute.
+ * Used with command to configure ACS operation for EHT mode.
+ * Disable (flag attribute not present) - EHT disabled and
+ * Enable (flag attribute present) - EHT enabled.
*/
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1375,6 +1515,8 @@
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
+ QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
+ QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -1438,6 +1580,25 @@
* %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and
* %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from
* userspace.
+ * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r.
+ * With Adaptive 11r feature, access points advertise the vendor
+ * specific IEs and MDE but do not include FT AKM in the RSNE.
+ * The Adaptive 11r supported stations are expected to identify
+ * such vendor specific IEs and connect to the AP in FT mode though
+ * the profile is configured in non-FT mode.
+ * The driver-based SME cases also need to have this support for
+ * Adaptive 11r to handle the connection and roaming scenarios.
+ * This flag indicates the support for the same to the user space.
+ * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports
+ * concurrent network sessions on different Wi-Fi bands. This feature
+ * capability is attributed to the hardware's capability to support
+ * the same (e.g., DBS).
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT: Flag indicating whether the
+ * responses for the respective TWT operations are asynchronous (separate
+ * event message) from the driver. If not specified, the responses are
+ * synchronous (in vendor command reply) to the request. Each TWT
+ * operation is specifically mentioned (against its respective
+ * documentation) to support either of these or both modes.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
@@ -1453,6 +1614,9 @@
QCA_WLAN_VENDOR_FEATURE_11AX = 9,
QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10,
QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11,
+ QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12,
+ QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13,
+ QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT = 14,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -1658,32 +1822,62 @@
};
/**
- * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
- * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
- * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
- * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
- * SOC timer value at TSF capture
+ * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32)
+ * Specify the TSF command. Possible values are defined in
+ * &enum qca_tsf_cmd.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
+ * This attribute contains TSF timer value. This attribute is only available
+ * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
+ * This attribute contains SOC timer value at TSF capture. This attribute is
+ * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32)
+ * This attribute is used to provide TSF sync interval and only applicable when
+ * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the
+ * driver will use the default value. Time unit is in milliseconds.
*/
enum qca_vendor_attr_tsf_cmd {
QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_TSF_CMD,
QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL,
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TSF_MAX =
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
};
/**
- * enum qca_tsf_operation: TSF driver commands
+ * enum qca_tsf_cmd: TSF driver commands
* @QCA_TSF_CAPTURE: Initiate TSF Capture
* @QCA_TSF_GET: Get TSF capture value
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
+ * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically
+ * fetches TSF and host time mapping from the firmware with interval configured
+ * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the
+ * interval value is not provided the driver will use the default value. The
+ * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
+ * command.
+ * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
*/
enum qca_tsf_cmd {
QCA_TSF_CAPTURE,
QCA_TSF_GET,
QCA_TSF_SYNC_GET,
+ QCA_TSF_AUTO_REPORT_ENABLE,
+ QCA_TSF_AUTO_REPORT_DISABLE,
+ QCA_TSF_SYNC_START,
+ QCA_TSF_SYNC_STOP,
};
/**
@@ -1777,6 +1971,23 @@
};
/**
+ * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the
+ * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take.
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority
+ */
+enum qca_wlan_vendor_scan_priority {
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4,
+};
+
+/**
* enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
*
* @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
@@ -1801,6 +2012,11 @@
* @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in
* microseconds. This is a common value which applies across all
* frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to
+ * other scan requests. It is a u32 attribute and takes values from enum
+ * qca_wlan_vendor_scan_priority. This is an optional attribute.
+ * If this attribute is not configured, the driver shall use
+ * QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
*/
enum qca_wlan_vendor_attr_scan {
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -1816,6 +2032,7 @@
QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
+ QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -2278,6 +2495,10 @@
* frame. The updated NSS value after the connection shall not be
* greater than the one negotiated during the connection. Any such
* higher value configuration shall be returned with a failure.
+ * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done
+ * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to
+ * configure the asymmetric NSS configuration (such as 1X2).
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70,
/* 8-bit unsigned value to trigger Optimized Power Management:
@@ -2326,6 +2547,86 @@
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76,
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for transmitting the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The TX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver
+ * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77,
+
+ /* 8-bit unsigned value. This attribute is used to dynamically configure
+ * the number of spatial streams used for receiving the data. When
+ * configured in the disconnected state, the configured value will
+ * be considered for the following connection attempt.
+ * If the NSS is updated after the connection, the updated NSS value
+ * is notified to the peer using the Operating Mode Notification/Spatial
+ * Multiplexing Power Save frame.
+ * The RX NSS value configured after the connection shall not be greater
+ * than the value negotiated during the connection. Any such higher
+ * value configuration shall be treated as invalid configuration by
+ * the driver. This attribute shall be configured along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric
+ * configuration (such as 2X2 or 1X1) or the asymmetric
+ * configuration (such as 1X2).
+ * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along
+ * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver
+ * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78,
+
+ /*
+ * 8-bit unsigned value. This attribute, when set, indicates whether the
+ * specified interface is the primary STA interface when there are more
+ * than one STA interfaces concurrently active.
+ *
+ * This configuration helps the firmware/hardware to support certain
+ * features (e.g., roaming) on this primary interface, if the same
+ * cannot be supported on the concurrent STA interfaces simultaneously.
+ *
+ * This configuration is only applicable for a single STA interface on
+ * a device and gives the priority for it only over other concurrent STA
+ * interfaces.
+ *
+ * If the device is a multi wiphy/soc, this configuration applies to a
+ * single STA interface across the wiphys.
+ *
+ * 1-Enable (is the primary STA), 0-Disable (is not the primary STA)
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * driver to enable/disable FT-over-DS feature. Possible values for
+ * this attribute are 1-Enable and 0-Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * firmware to enable/disable ARP/NS offload feature. Possible values
+ * for this attribute are 0-Disable and 1-Enable.
+ *
+ * This attribute is only applicable for STA/P2P-Client interface,
+ * and is optional, default behavior is ARP/NS offload enabled.
+ *
+ * This attribute can be set in disconnected and connected state, and
+ * will restore to the default behavior if the interface is closed.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -2421,23 +2722,50 @@
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
* %QCA_WLAN_VENDOR_GPIO_OUTPUT.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32)
* value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32)
* value to specify the GPIO interrupt mode. Please refer to enum
* qca_gpio_interrupt_mode for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
*
- * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Required (u32)
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32)
* value to specify the GPIO direction. Please refer to enum qca_gpio_direction
* for the available values.
* This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
- * %QCA_WLAN_VENDOR_GPIO_CONFIG.
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG and
+ * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG
+ * attribute is present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32)
+ * Value to specify the mux config. Meaning of a given value is dependent
+ * on the target chipset and GPIO pin. Must be of the range 0-15.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32)
+ * Value to specify the drive, refer to enum qca_gpio_drive.
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag)
+ * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is
+ * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all
+ * other parameters for the given GPIO will be obtained from internal
+ * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be
+ * specified to indicate the GPIO pin being configured.
*/
enum qca_wlan_gpio_attr {
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
@@ -2453,6 +2781,12 @@
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5,
/* Unsigned 32-bit attribute for GPIO direction to configure */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6,
+ /* Unsigned 32-bit attribute for GPIO mux config */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7,
+ /* Unsigned 32-bit attribute for GPIO drive */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8,
+ /* Flag attribute for using internal GPIO configuration */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
@@ -2528,6 +2862,30 @@
};
/**
+ * enum qca_gpio_drive - GPIO drive
+ * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA
+ * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA
+ * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA
+ * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA
+ * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA
+ * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA
+ * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA
+ * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA
+ * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive
+ */
+enum qca_gpio_drive {
+ QCA_WLAN_GPIO_DRIVE_2MA = 0,
+ QCA_WLAN_GPIO_DRIVE_4MA = 1,
+ QCA_WLAN_GPIO_DRIVE_6MA = 2,
+ QCA_WLAN_GPIO_DRIVE_8MA = 3,
+ QCA_WLAN_GPIO_DRIVE_10MA = 4,
+ QCA_WLAN_GPIO_DRIVE_12MA = 5,
+ QCA_WLAN_GPIO_DRIVE_14MA = 6,
+ QCA_WLAN_GPIO_DRIVE_16MA = 7,
+ QCA_WLAN_GPIO_DRIVE_MAX,
+};
+
+/**
* qca_wlan_set_qdepth_thresh_attr - Parameters for setting
* MSDUQ depth threshold per peer per tid in the target
*
@@ -3688,6 +4046,14 @@
* QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+ /* u8 value representing the channel load percentage. Possible values
+ * are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
+ /* u8 value representing the time slicing duty cycle percentage.
+ * Possible values are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4035,6 +4401,30 @@
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1,
};
+/**
+ * enum qca_roam_scan_scheme: Scan scheme
+ *
+ * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan.
+ * Indicates the driver to not scan on a Roam Trigger scenario, but
+ * disconnect. E.g., on a BTM request from the AP the driver/firmware shall
+ * disconnect from the current connected AP by notifying a failure
+ * code in the BTM response.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to
+ * trigger partial frequency scans. These frequencies are the ones learned
+ * or maintained by the driver based on the probability of finding the
+ * BSSIDs in the ESS for which the roaming is triggered.
+ *
+ * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to
+ * trigger the scan on all the valid frequencies to find better
+ * candidates to roam.
+ */
+enum qca_roam_scan_scheme {
+ QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0,
+ QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1,
+ QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2,
+};
+
/*
* enum qca_vendor_roam_triggers: Bitmap of roaming triggers
*
@@ -4055,6 +4445,18 @@
* when BTM Request frame is received from the connected AP.
* @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered
* when the channel utilization is goes above the configured threshold.
+ * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered
+ * based on the request from the user (space).
+ * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when
+ * device receives Deauthentication/Disassociation frame from connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the
+ * device is in idle state (no TX/RX) and suspend mode, if the current RSSI
+ * is determined to be a poor one.
+ * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered
+ * based on continuous TX Data frame failures to the connected AP.
+ * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered
+ * based on the scan results obtained from an external scan (not triggered
+ * to aim roaming).
*
* Set the corresponding roam trigger reason bit to consider it for roam
* trigger.
@@ -4070,6 +4472,144 @@
QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5,
QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6,
QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7,
+ QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8,
+ QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9,
+ QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10,
+ QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11,
+ QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12,
+};
+
+/*
+ * enum qca_vendor_roam_fail_reasons: Defines the various roam
+ * fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED: Roam module in the firmware is not
+ * able to trigger the scan.
+ * @QCA_ROAM_FAIL_REASON_NO_AP_FOUND: No roamable APs found during roam scan.
+ * @QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND: No candidate APs found during roam
+ * scan.
+ * @QCA_ROAM_FAIL_REASON_HOST: Roam fail due to disconnect issued from host.
+ * @QCA_ROAM_FAIL_REASON_AUTH_SEND: Unable to send Authentication frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_RECV: Received Authentication frame with error
+ * status code.
+ * @QCA_ROAM_FAIL_REASON_NO_AUTH_RESP: Authentication frame not received.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_SEND: Unable to send Reassociation Request
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_RECV: Received Reassociation Response frame
+ * with error status code.
+ * @QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP: Reassociation Response frame not
+ * received.
+ * @QCA_ROAM_FAIL_REASON_SCAN_FAIL: Scan module not able to start scan.
+ * @QCA_ROAM_FAIL_REASON_AUTH_NO_ACK: No ACK is received for Authentication
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP: Authentication frame is dropped
+ * internally before transmission.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK: No ACK is received for Reassociation
+ * Request frame.
+ * @QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP: Reassociation Request frame is
+ * dropped internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT: EAPOL-Key M1 is not received and
+ * times out.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND: Unable to send EAPOL-Key M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP: EAPOL-Key M2 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK: No ACK is received for EAPOL-Key
+ * M2 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT: EAPOL-Key M3 frame is not received.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND: Unable to send EAPOL-Key M4 frame.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP: EAPOL-Key M4 frame dropped
+ * internally.
+ * @QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK: No ACK is received for EAPOL-Key M4
+ * frame.
+ * @QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS: Roam scan is not
+ * started for final beacon miss case.
+ * @QCA_ROAM_FAIL_REASON_DISCONNECT: Deauthentication or Disassociation frame
+ * received from the AP during roaming handoff.
+ * @QCA_ROAM_FAIL_REASON_RESUME_ABORT: Firmware roams to the AP when the Apps
+ * or host is suspended and gives the indication of the last roamed AP only
+ * when the Apps is resumed. If the Apps is resumed while the roaming is in
+ * progress, this ongoing roaming is aborted and the last roamed AP is
+ * indicated to host.
+ * @QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID: WPA3-SAE invalid PMKID.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT: WPA3-SAE pre-authentication times
+ * out.
+ * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL: WPA3-SAE pre-authentication fails.
+ */
+enum qca_vendor_roam_fail_reasons {
+ QCA_ROAM_FAIL_REASON_NONE = 0,
+ QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED = 1,
+ QCA_ROAM_FAIL_REASON_NO_AP_FOUND = 2,
+ QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND = 3,
+ QCA_ROAM_FAIL_REASON_HOST = 4,
+ QCA_ROAM_FAIL_REASON_AUTH_SEND = 5,
+ QCA_ROAM_FAIL_REASON_AUTH_RECV = 6,
+ QCA_ROAM_FAIL_REASON_NO_AUTH_RESP = 7,
+ QCA_ROAM_FAIL_REASON_REASSOC_SEND = 8,
+ QCA_ROAM_FAIL_REASON_REASSOC_RECV = 9,
+ QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP = 10,
+ QCA_ROAM_FAIL_REASON_SCAN_FAIL = 11,
+ QCA_ROAM_FAIL_REASON_AUTH_NO_ACK = 12,
+ QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP = 13,
+ QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK = 14,
+ QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP = 15,
+ QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT = 16,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND = 17,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP = 18,
+ QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK = 19,
+ QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT = 20,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND = 21,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP = 22,
+ QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK = 23,
+ QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS = 24,
+ QCA_ROAM_FAIL_REASON_DISCONNECT = 25,
+ QCA_ROAM_FAIL_REASON_RESUME_ABORT = 26,
+ QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID = 27,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT = 28,
+ QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL = 29,
+};
+
+/*
+ * enum qca_vendor_roam_invoke_fail_reasons: Defines the various roam
+ * invoke fail reasons. This enum value is used in
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON attribute.
+ *
+ * @QCA_ROAM_INVOKE_STATUS_IFACE_INVALID: Invalid interface ID is passed
+ * in roam invoke command.
+ * @QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE: Roam offload in firmware is not
+ * enabled.
+ * @QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID: Connected AP profile SSID
+ * length is invalid.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW: Firmware internal roaming is already
+ * in progress.
+ * @QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP: Host sends the Beacon/Probe Response
+ * of the AP in the roam invoke command to firmware. This reason is sent by the
+ * firmware when the given AP is configured to be ignored or SSID/security
+ * does not match.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL: Roam handoff failed because of
+ * firmware internal reasons.
+ * @QCA_ROAM_INVOKE_STATUS_DISALLOW: Roam invoke trigger is not enabled.
+ * @QCA_ROAM_INVOKE_STATUS_SCAN_FAIL: Scan start fail for roam invoke.
+ * @QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL: Roam handoff start fail.
+ * @QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS: Roam invoke parameters are invalid.
+ * @QCA_ROAM_INVOKE_STATUS_NO_CAND_AP: No candidate AP found to roam to.
+ * @QCA_ROAM_INVOKE_STATUS_ROAM_FAIL: Roam handoff failed.
+ */
+enum qca_vendor_roam_invoke_fail_reasons {
+ QCA_ROAM_INVOKE_STATUS_NONE = 0,
+ QCA_ROAM_INVOKE_STATUS_IFACE_INVALID = 1,
+ QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE = 2,
+ QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID = 3,
+ QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW = 4,
+ QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP = 5,
+ QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL = 6,
+ QCA_ROAM_INVOKE_STATUS_DISALLOW = 7,
+ QCA_ROAM_INVOKE_STATUS_SCAN_FAIL = 8,
+ QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL = 9,
+ QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS = 10,
+ QCA_ROAM_INVOKE_STATUS_NO_CAND_AP = 11,
+ QCA_ROAM_INVOKE_STATUS_ROAM_FAIL = 12,
+
};
/**
@@ -4226,6 +4766,109 @@
*
* Clears the selection criteria configured in the driver when specified
* with clear command.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value.
+ * Represents value of the scan frequency scheme from enum
+ * qca_roam_scan_scheme.
+ * It's an optional attribute. If this attribute is not configured, the
+ * driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the current connected AP, indicating
+ * the driver to trigger roam only when the current connected AP's RSSI
+ * is less than this threshold.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm,
+ * signifying the RSSI threshold of the candidate AP, indicating
+ * the driver to trigger roam only to the candidate AP with RSSI
+ * better than this threshold. If RSSI thresholds for candidate APs found
+ * in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ,
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will
+ * take precedence over the value configured using the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the
+ * user defined reason code to be sent to the AP in response to AP's
+ * request to trigger the roam if the roaming cannot be triggered.
+ * Applies to all the scenarios of AP assisted roaming (e.g., BTM).
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value.
+ * Carries a bitmap of the roam triggers specified in
+ * enum qca_vendor_roam_triggers.
+ * Represents the roam triggers for which the specific scan scheme from
+ * enum qca_roam_scan_scheme has to be applied.
+ * It's an optional attribute. If this attribute is not configured, but
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme
+ * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for
+ * all the roams.
+ * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and
+ * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the
+ * driver shall proceed with the default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value
+ * in dBm, signifying the RSSI threshold of the candidate AP found in the
+ * 2.4 GHz band. The driver/firmware shall trigger roaming to the candidate
+ * AP found in the 2.4 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 5
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 5 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by tge
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 6
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 6 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value.
+ * Carries bitmask value of bits from &enum qca_set_band and represents
+ * all the bands in which roaming is allowed. The configuration is valid
+ * until next disconnection. If this attribute is not present, the
+ * existing configuration shall be used. By default, roaming is allowed on
+ * all bands supported by the local device. When the value is set to
+ * %QCA_SETBAND_AUTO, all supported bands shall be enabled.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz
+ * bands. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for passive channels in the 5 GHz
+ * band. If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds.
+ * Optional parameter. The minimum duration to stay on the connected AP
+ * channel during the channel scanning. If this attribute is not
+ * configured, the driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds.
+ * Optional parameter. The maximum duration for which the radio can scan
+ * foreign channels consecutively without coming back to home channel. If
+ * this attribute is not configured, the driver shall proceed with default
+ * behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Preferred Scanning Channels.
+ * If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Non Preferred Scanning
+ * Channels. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
*/
enum qca_vendor_attr_roam_control {
QCA_ATTR_ROAM_CONTROL_ENABLE = 1,
@@ -4236,6 +4879,21 @@
QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6,
QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7,
QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9,
+ QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11,
+ QCA_ATTR_ROAM_CONTROL_USER_REASON = 12,
+ QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16,
+ QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17,
+ QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18,
+ QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19,
+ QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20,
+ QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23,
/* keep last */
QCA_ATTR_ROAM_CONTROL_AFTER_LAST,
@@ -4258,14 +4916,14 @@
* ignored BSSIDs and accordingly clear the respective ones with the
* matching ID.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned
- * 32-bit value.Represents the number of whitelist SSIDs configured.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS: Unsigned
+ * 32-bit value. Represents the number of allowlist SSIDs configured.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute
- * to carry the list of Whitelist SSIDs.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST: Nested attribute
+ * to carry the list of allowlist SSIDs.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute,
- * 0..32 octets). Represents the white list SSID. Whitelist SSIDs
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID: SSID (binary attribute,
+ * 0..32 octets). Represents the allow list SSID. Allowlist SSIDs
* represent the list of SSIDs to which the firmware/driver can consider
* to roam to.
*
@@ -4303,7 +4961,7 @@
*
* @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit
* value. 1-Enable, 0-Disable. Represents "Lazy" mode, where
- * firmware is hunting for a better BSSID or white listed SSID even though
+ * firmware is hunting for a better BSSID or allow listed SSID even though
* the RSSI of the link is good. The parameters enabling the roaming are
* configured through the PARAM_A_BAND_XX attrbutes.
*
@@ -4345,10 +5003,10 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1,
QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2,
- /* Attributes for wifi_set_ssid_white_list */
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5,
+ /* Attributes for wifi_set_ssid_allow_list */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID = 5,
/* Attributes for set_roam_params */
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6,
@@ -4383,16 +5041,24 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
+
/*
* enum qca_wlan_vendor_roaming_subcmd: Referred by
* QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to
- * configure the white list SSIDs. These are configured through
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST: Sub command to
+ * configure the allow list SSIDs. These are configured through
* the following attributes.
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
*
* @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to
* configure the Roam params. These parameters are evaluated on the GScan
@@ -4408,7 +5074,7 @@
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID
* preference.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID: Sets the list of BSSIDs
* to ignore in roaming decision. Uses
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list.
*
@@ -4432,17 +5098,23 @@
*/
enum qca_wlan_vendor_roaming_subcmd {
QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST = 1,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID = 6,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID
+
enum qca_wlan_vendor_attr_gscan_config_params {
QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0,
@@ -4801,7 +5473,7 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
= 43,
/* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
- QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
= 44,
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45,
@@ -4809,10 +5481,10 @@
/* Unsigned 32-bit value; a GSCAN Capabilities attribute.
* This is used to limit the maximum number of BSSIDs while sending
* the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd
- * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute
+ * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID and attribute
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID.
*/
- QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46,
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID = 46,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST,
@@ -4820,6 +5492,12 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID
+
enum qca_wlan_vendor_attr_pno_config_params {
QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0,
/* Attributes for data used by
@@ -5186,6 +5864,10 @@
* bit 3 set: channel should be excluded in GO negotiation
*/
QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_PCL_LAST,
+ QCA_WLAN_VENDOR_ATTR_PCL_MAX = QCA_WLAN_VENDOR_ATTR_PCL_LAST - 1
};
/**
@@ -5843,6 +6525,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29,
+ /* This attribute specifies the bandwidth to be used for spectral scan
+ * operation. This is an u8 attribute and uses the values in enum
+ * nl80211_chan_width. This is an optional attribute.
+ * If this attribute is not populated, the driver should configure the
+ * spectral scan bandwidth to the maximum value supported by the target
+ * for the current operating bandwidth.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -5953,6 +6643,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18,
+ /* Flag attribute to indicate agile spectral scan capability
+ * for 320 MHz mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19,
+ /* Number of spectral detectors used for scan in 320 MHz.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
@@ -6135,6 +6833,16 @@
* the FW on a specific VDEV.
*/
QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22,
+ /* WMI sequence mismatch between WMI command and Tx completion */
+ QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23,
+ /* Write to Device HAL register failed */
+ QCA_WLAN_HANG_REG_WRITE_FAILURE = 24,
+ /* No credit left to send the wow_wakeup_from_sleep to firmware */
+ QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25,
+ /* Bus failure */
+ QCA_WLAN_HANG_BUS_FAILURE = 26,
+ /* tasklet/credit latency found */
+ QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27,
};
/**
@@ -6160,6 +6868,28 @@
};
/**
+ * enum qca_wlan_vendor_flush_pending_policy: Represents values for
+ * the policy to flush pending frames, configured via
+ * %QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING. This enumeration defines the
+ * valid values for %QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY.
+ *
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE: This value clears all
+ * the flush policy configured before. This command basically disables the
+ * flush config set by the user.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE: This value configures
+ * the flush policy to be immediate. All pending packets for the peer/TID are
+ * flushed when this command/policy is received.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END: This value configures
+ * the flush policy to the end of TWT SP. All pending packets for the peer/TID
+ * are flushed when the end of TWT SP is reached.
+ */
+enum qca_wlan_vendor_flush_pending_policy {
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE = 0,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE = 1,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_flush_pending - Attributes for
* flushing pending traffic in firmware.
*
@@ -6167,12 +6897,25 @@
* @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending
* packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK,
* AC_VI, AC_VO respectively. Set the corresponding bit to 1 to
- * flush packets with access category.
+ * flush packets with access category. This is optional. See below.
+ * @QCA_WLAN_VENDOR_ATTR_TID_MASK: Configure TID mask of the pending packets.
+ * It is a u32 value with bit 0-7 representing TID 0-7. Set corresponding
+ * bit to 1 to act upon the TID. This is optional. Either this attribute or
+ * %QCA_WLAN_VENDOR_ATTR_AC must be provided. If both are provided,
+ * %QCA_WLAN_VENDOR_ATTR_TID_MASK takes precedence. If neither are provided
+ * it is an error.
+ * @QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY: Policy of flushing the pending
+ * packets corresponding to the peer/TID provided. It is a u32 value,
+ * represented by %enum qca_wlan_vendor_flush_pending_policy. This
+ * value is honored only when TID mask is provided. This is not honored when AC
+ * mask is provided.
*/
enum qca_wlan_vendor_attr_flush_pending {
QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1,
QCA_WLAN_VENDOR_ATTR_AC = 2,
+ QCA_WLAN_VENDOR_ATTR_TID_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
@@ -6289,8 +7032,9 @@
*
* @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
* Default WLAN operation level which throughput orientated.
- * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
- * Use moderate level to improve latency by limit scan duration.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
+ * Use XR level to benefit XR (extended reality) application to achieve
+ * latency and power by via constraint scan/roaming/adaptive PS.
* @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
* Use low latency level to benifit application like concurrent
* downloading or video streaming via constraint scan/adaptive PS.
@@ -6301,7 +7045,10 @@
enum qca_wlan_vendor_attr_config_latency_level {
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1,
- QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR = 2,
+ /* legacy name */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
@@ -6801,8 +7548,9 @@
/**
* enum qca_wlan_vendor_thermal_level - Defines various thermal levels
- * configured by userspace to the driver/firmware. The values will be
- * encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL attribute.
+ * configured by userspace to the driver/firmware.
+ * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute.
* The driver/firmware takes actions requested by userspace such as throttling
* wifi TX etc. in order to mitigate high temperature.
*
@@ -6836,8 +7584,9 @@
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1,
/* Userspace uses this attribute to configure thermal level to the
- * driver/firmware. Used in request, u32 attribute, possible values
- * are defined in enum qca_wlan_vendor_thermal_level.
+ * driver/firmware, or get thermal level from the driver/firmware.
+ * Used in request or response, u32 attribute,
+ * possible values are defined in enum qca_wlan_vendor_thermal_level.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2,
/* Userspace uses this attribute to configure the time in which the
@@ -6850,6 +7599,15 @@
* there is any critical ongoing operation.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3,
+ /* Nested attribute, the driver/firmware uses this attribute to report
+ * thermal statistics of different thermal levels to userspace when
+ * requested using the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command
+ * type. This attribute contains a nested array of records of thermal
+ * statistics of multiple levels. The attributes used inside this nested
+ * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
@@ -6875,6 +7633,16 @@
* resume action.
* @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to
* the driver/firmware.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current
+ * thermal level from the driver/firmware. The driver should respond with a
+ * thermal level defined in enum qca_wlan_vendor_thermal_level.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the
+ * current thermal statistics from the driver/firmware. The driver should
+ * respond with statistics of all thermal levels encapsulated in the attribute
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear
+ * the current thermal statistics for all thermal levels maintained in the
+ * driver/firmware and start counting from zero again.
*/
enum qca_wlan_vendor_attr_thermal_cmd_type {
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
@@ -6882,6 +7650,9 @@
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS,
};
/**
@@ -6964,6 +7735,11 @@
* NLA_FLAG attribute.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE,
+ /* Thermal level from the driver.
+ * u32 attribute. Possible values are defined in
+ * enum qca_wlan_vendor_thermal_level.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST,
@@ -6972,6 +7748,35 @@
};
/**
+ * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes
+ * to get thermal status from the driver/firmware.
+ * enum values are used for NL attributes encapsulated inside the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute.
+ *
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each
+ * thermal level in milliseconds. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number
+ * of times the temperature crossed into the temperature range defined by the
+ * thermal level from both higher and lower directions. u32 size.
+ */
+enum qca_wlan_vendor_attr_thermal_stats {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST - 1,
+};
+
+/**
* enum he_fragmentation_val - HE fragmentation support values
* Indicates level of dynamic fragmentation that is supported by
* a STA as a recipient.
@@ -7130,6 +7935,21 @@
};
/**
+ * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration
+ *
+ * Indicates the frame types to use for keep alive data.
+ *
+ * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive.
+ */
+enum qca_wlan_keep_alive_data_type {
+ QCA_WLAN_KEEP_ALIVE_DEFAULT = 0,
+ QCA_WLAN_KEEP_ALIVE_DATA = 1,
+ QCA_WLAN_KEEP_ALIVE_MGMT = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
* HE operating mode control transmit request. These attributes are
* sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
@@ -7577,6 +8397,128 @@
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43,
+ /* 8-bit unsigned value to configure the driver/firmware to start or
+ * stop transmitting FILS discovery frames.
+ * 0 - Stop transmitting FILS discovery frames
+ * 1 - Start transmitting FILS discovery frames
+ * This attribute is used to configure the testbed device.
+ * This attribute can be configured only in AP mode and the
+ * configuration is valid until AP restart.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable full bandwidth UL MU-MIMO subfield
+ * 1 - Enable full bandwidth UL MU-MIMO subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45,
+
+ /* 16-bit unsigned value to configure the driver with a specific BSS
+ * max idle period to advertise in the BSS Max Idle Period element
+ * (IEEE Std 802.11-2016, 9.4.2.79) in (Re)Association Request frames.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD = 46,
+
+ /* 8-bit unsigned value to configure the driver to use only RU 242 tone
+ * for data transmission.
+ * 0 - Default behavior, 1 - Configure RU 242 tone for data Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX = 47,
+
+ /* 8-bit unsigned value to configure the driver to disable data and
+ * management response frame transmission to test the BSS max idle
+ * feature.
+ * 0 - Default behavior, 1 - Disable data and management response Tx.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX = 48,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Punctured Preamble Rx subfield in the HE PHY capabilities
+ * information field.
+ * 0 - Disable Punctured Preamble Rx subfield
+ * 1 - Enable Punctured Preamble Rx subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49,
+
+ /* 8-bit unsigned value to configure the driver to ignore the SAE H2E
+ * requirement mismatch for 6 GHz connection.
+ * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50,
+
+ /* 8-bit unsigned value to configure the driver to allow 6 GHz
+ * connection with all security modes.
+ * 0 - Default behavior, 1 - Allow 6 GHz connection with all security
+ * modes.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51,
+
+ /* 8-bit unsigned value to configure the driver to transmit data with
+ * ER SU PPDU type.
+ *
+ * 0 - Default behavior, 1 - Enable ER SU PPDU type TX.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52,
+
+ /* 8-bit unsigned value to configure the driver to use Data or
+ * Management frame type for keep alive data.
+ * Uses enum qca_wlan_keep_alive_data_type values.
+ *
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+
+ /* 8-bit unsigned value to configure the driver to use scan request
+ * BSSID value in Probe Request frame RA(A1) during the scan. The
+ * driver saves this configuration and applies this setting to all user
+ * space scan requests until the setting is cleared. If this
+ * configuration is set, the driver uses the BSSID value from the scan
+ * request to set the RA(A1) in the Probe Request frames during the
+ * scan.
+ *
+ * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+ * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * BSS max idle period support.
+ *
+ * 0 - Disable the BSS max idle support.
+ * 1 - Enable the BSS max idle support.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Rx control frame to MultiBSS subfield in the HE MAC
+ * capabilities information field.
+ * 0 - Disable Rx control frame to MultiBSS subfield
+ * 1 - Enable Rx control frame to MultiBSS subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Broadcast TWT support subfield in the HE MAC capabilities
+ * information field.
+ * 0 - Disable Broadcast TWT support subfield
+ * 1 - Enable Broadcast TWT support subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -7586,26 +8528,73 @@
/**
* enum qca_wlan_twt_operation - Operation of the config TWT request
* Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION.
+ * The response for the respective operations can be either synchronous or
+ * asynchronous (wherever specified). If synchronous, the response to this
+ * operation is obtained in the corresponding vendor command reply to the user
+ * space. For the asynchronous case the response is obtained as an event with
+ * the same operation type.
+ *
+ * Drivers shall support either of these modes but not both simultaneously.
+ * This support for asynchronous mode is advertised through the flag
+ * QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT. If this flag is not advertised,
+ * the driver shall support synchronous mode.
*
* @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured
* through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. Depending upon the
+ * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, this is either a
+ * synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
- * qca_wlan_vendor_attr_twt_setup.
+ * qca_wlan_vendor_attr_twt_setup. This is a synchronous operation.
*
* @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * This terminate can either get triggered by the user space or can as well be
+ * a notification from the firmware if it initiates a terminate.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * the request from user space can either be a synchronous or asynchronous
+ * operation.
*
* @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are
* obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup.
+ * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability,
+ * this is either a synchronous or asynchronous operation.
*
* @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are
* configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum
* qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup.
+ * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE
+ * request. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a
+ * combination of suspend and resume in a single request. Required parameters
+ * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the
+ * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is
+ * setup. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT
+ * capability, this is either a synchronous or asynchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information.
+ * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT
+ * session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information.
+ * Valid only after the TWT session is setup. It's a synchronous operation.
+ *
+ * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its
+ * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous
+ * operation.
+ *
+ * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is
+ * ready for a new TWT session setup after it issued a TWT teardown.
+ *
+ * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required
+ * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer
+ * the enum qca_wlan_vendor_attr_twt_set_param.
*/
enum qca_wlan_twt_operation {
QCA_WLAN_TWT_SET = 0,
@@ -7613,6 +8602,12 @@
QCA_WLAN_TWT_TERMINATE = 2,
QCA_WLAN_TWT_SUSPEND = 3,
QCA_WLAN_TWT_RESUME = 4,
+ QCA_WLAN_TWT_NUDGE = 5,
+ QCA_WLAN_TWT_GET_STATS = 6,
+ QCA_WLAN_TWT_CLEAR_STATS = 7,
+ QCA_WLAN_TWT_GET_CAPABILITIES = 8,
+ QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9,
+ QCA_WLAN_TWT_SET_PARAM = 10,
};
/**
@@ -7626,8 +8621,9 @@
*
* @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the
* parameters configured for TWT. These parameters are represented by
- * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume
- * based on the operation.
+ * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume,
+ * enum qca_wlan_vendor_attr_twt_set_param, or
+ * enum qca_wlan_vendor_attr_twt_stats based on the operation.
*/
enum qca_wlan_vendor_attr_config_twt {
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0,
@@ -7788,6 +8784,19 @@
};
/**
+ * qca_wlan_twt_setup_state: Represents the TWT session states.
+ *
+ * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established.
+ * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active.
+ * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state.
+ */
+enum qca_wlan_twt_setup_state {
+ QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0,
+ QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1,
+ QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_twt_setup: Represents attributes for
* TWT (Target Wake Time) setup request. These attributes are sent as part of
* %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and
@@ -7837,6 +8846,14 @@
* 2. TWT GET Request and Response
* 3. TWT TERMINATE Request and Response
* 4. TWT SUSPEND Request and Response
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions for the following
+ * 1. TWT TERMINATE Request and Response
+ * 2. TWT SUSPEND Request and Response
+ * 4. TWT CLEAR STATISTICS request
+ * 5. TWT GET STATISTICS request and response
+ * If an invalid dialog ID is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8)
* This attribute (exp) is used along with the mantissa to derive the
@@ -7887,6 +8904,7 @@
* 2. TWT TERMINATE Response
* 3. TWT SUSPEND Response
* 4. TWT RESUME Response
+ * 5. TWT NUDGE Response
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8)
* This field is applicable for TWT response only.
@@ -7896,9 +8914,13 @@
* response.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64)
- * This field is applicable for TWT response only.
- * This field contains absolute TSF value of the wake time received
- * from the TWT responder and is passed to the userspace.
+ * In TWT setup command this field contains absolute TSF that will
+ * be used by TWT requester during setup.
+ * In TWT response this field contains absolute TSF value of the
+ * wake time received from the TWT responder and is passed to
+ * the userspace.
+ * This is an optional parameter for
+ * 1. TWT SET Request
* This is a required parameter for
* 1. TWT SET Response
* 2. TWT GET Response
@@ -7915,14 +8937,87 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer for which the TWT session
* is being configured. This is used in AP mode to represent the respective
- * client. In AP mode, this is an optional parameter for response and is
- * a required parameter for
- * 1. TWT SET Request
- * 2. TWT GET Request
- * 3. TWT TERMINATE Request
- * 4. TWT SUSPEND Request
+ * client.
+ * In AP mode, this is a required parameter in response for
+ * 1. TWT SET
+ * 2. TWT GET
+ * 3. TWT TERMINATE
+ * 4. TWT SUSPEND
* In STA mode, this is an optional parameter in request and response for
* the above four TWT operations.
+ * In AP mode, this is a required parameter in request for
+ * 1. TWT GET
+ * 2. TWT TERMINATE
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32)
+ * Minimum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32)
+ * Maximum tolerance limit of wake interval parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32)
+ * Minimum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32)
+ * Maximum tolerance limit of wake duration parameter in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32)
+ * TWT state for the given dialog id. The values for this are represented
+ * by enum qca_wlan_twt_setup_state.
+ * This is obtained through TWT GET operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The unit is microseconds. This attribute, when specified, takes
+ * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA.
+ * This parameter is used for
+ * 1. TWT SET Request and Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
+ * This attribute is used to configure Broadcast TWT ID.
+ * The Broadcast TWT ID indicates a specific Broadcast TWT for which the
+ * transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
+ * This parameter is used for
+ * 1. TWT SET Request
+ * 2. TWT TERMINATE Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
+ * This attribute is used to configure Broadcast TWT recommendation.
+ * The Broadcast TWT Recommendation subfield contains a value that indicates
+ * recommendations on the types of frames that are transmitted by TWT
+ * scheduled STAs and scheduling AP during the broadcast TWT SP.
+ * The allowed values are 0 - 3.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
+ * This attribute is used to configure Broadcast TWT Persistence.
+ * The Broadcast TWT Persistence subfield indicates the number of
+ * TBTTs during which the Broadcast TWT SPs corresponding to this
+ * broadcast TWT Parameter set are present. The number of beacon intervals
+ * during which the Broadcast TWT SPs are present is equal to the value in the
+ * Broadcast TWT Persistence subfield plus 1 except that the value 255
+ * indicates that the Broadcast TWT SPs are present until explicitly terminated.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8)
+ * This attribute contains the value of the Responder PM Mode subfield (0 or 1)
+ * from TWT response frame.
+ * This parameter is used for
+ * 1. TWT SET Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32)
+ * This attribute is used to configure the announce timeout value (in us) in
+ * the firmware. This timeout value is only applicable for the announced TWT. If
+ * the timeout value is non-zero the firmware waits up to the timeout value to
+ * use Data frame as an announcement frame. If the timeout value is 0 the
+ * firmware sends an explicit QoS NULL frame as the announcement frame on SP
+ * start. The default value in the firmware is 0.
+ * This parameter is used for
+ * 1. TWT SET Request
*/
enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@@ -7944,6 +9039,20 @@
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
@@ -7971,6 +9080,30 @@
* @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request
* @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an
* unknown reason
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in
+ * suspend state
+ * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to
+ * invalid IE in the received TWT frame
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from
+ * the responder are not in the specified range
+ * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to request from the responder. Used on the TWT_TERMINATE
+ * notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
+ * session due to roaming. Used on the TWT_TERMINATE notification from the
+ * firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
+ * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
+ * Concurrency). Used on the TWT_TERMINATE notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
+ * request due to roaming in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
+ * setup request due to channel switch in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup
+ * request due to scan in progress.
+ * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to
+ * terminate an existing TWT session on power save exit request from userspace.
+ * Used on the TWT_TERMINATE notification from the driver/firmware.
*/
enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@@ -7986,6 +9119,16 @@
QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10,
QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11,
QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12,
+ QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13,
+ QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14,
+ QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
+ QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
+ QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21,
+ QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22,
};
/**
@@ -8012,6 +9155,10 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8).
* Flow ID is the unique identifier for each TWT session. This attribute
* represents the respective TWT session to resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer to which TWT Resume is
@@ -8034,6 +9181,231 @@
};
/**
+ * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for
+ * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend
+ * and resume in a single request. These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session to suspend and resume.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request
+ * and response.
+ * If an invalid dialog id is provided, status
+ * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32)
+ * This attribute is used as the SP offset which is the offset from
+ * TSF after which the wake happens. The units are in microseconds.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32)
+ * This attribute represents the next TWT subfield size.
+ * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits,
+ * and 4 for 64 bits.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer to which TWT Suspend and Resume is
+ * being sent. This is used in AP mode to represent the respective
+ * client and is a required parameter. In STA mode, this is an optional
+ * parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64)
+ * This field contains absolute TSF value of the time at which the TWT
+ * session will be resumed.
+ */
+enum qca_wlan_vendor_attr_twt_nudge {
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for
+ * TWT (Target Wake Time) get statistics and clear statistics request.
+ * These attributes are sent as part of
+ * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8)
+ * Flow ID is the unique identifier for each TWT session. This attribute
+ * represents the respective TWT session for get and clear TWT statistics.
+ * Flow ID values from 0 to 254 represent a single TWT session
+ * Flow ID value of 255 represents all TWT sessions in
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which TWT Statistics
+ * is required.
+ * In AP mode this is used to represent the respective
+ * client and is a required parameter for
+ * 1) TWT GET STATISTICS request and response
+ * 2) TWT CLEAR STATISTICS request and response
+ * In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32)
+ * This is the duration of the service period in microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32)
+ * Average of the actual wake duration observed so far. Unit is microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32)
+ * The number of TWT service periods elapsed so far.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32)
+ * This is the minimum value of the wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32)
+ * This is the maximum value of wake duration observed across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is
+ * microseconds.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32)
+ * Average number of MPDUs transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32)
+ * Average number of MPDUs received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32)
+ * Average number of bytes transmitted successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32)
+ * Average number of bytes received successfully across
+ * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS.
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32)
+ * Status of the TWT GET STATISTICS request.
+ * This contains status values in enum qca_wlan_vendor_twt_status
+ * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware.
+ */
+enum qca_wlan_vendor_attr_twt_stats {
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities
+ * supported by the device and the peer.
+ * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by
+ * TWT non-scheduling STA. This capability is advertised in the HE
+ * Capability/Extended Capabilities information element in the
+ * Association Request frame by the device.
+ *
+ * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by
+ * the TWT scheduling AP. This capability is advertised in the Extended
+ * Capabilities/HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support
+ * for the broadcast TWT functionality. On the responder side, this indicates
+ * support for the role of broadcast TWT scheduling functionality. This
+ * capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule.
+ * This capability is advertised in the HE Capabilities information element.
+ *
+ * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate
+ * that it mandates the associated HE STAs to support TWT. This capability is
+ * advertised by AP in the HE Operation Parameters field of the HE Operation
+ * information element.
+ */
+enum qca_wlan_twt_capa {
+ QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0),
+ QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1),
+ QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2),
+ QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3),
+ QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT
+ * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT
+ * operation.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address
+ * Represents the MAC address of the peer for which the TWT capabilities
+ * are being queried. This is used in AP mode to represent the respective
+ * client. In STA mode, this is an optional parameter.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16).
+ * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16).
+ * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in
+ * enum qca_wlan_twt_capa.
+ */
+enum qca_wlan_vendor_attr_twt_capability {
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for
+ * TWT (Target Wake Time) related parameters. It is used when
+ * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM.
+ * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8)
+ * This attribute configures AC parameters to be used for all TWT
+ * sessions in AP mode.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+enum qca_wlan_vendor_attr_twt_set_param {
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1,
+};
+
+/**
* enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by
* the TWT responder
*
@@ -8124,6 +9496,22 @@
};
/**
+ * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data
+ * transport modes and is used by the attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data.
+ * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR
+ * data. The data shall be encapsulated within
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event.
+ */
+enum qca_wlan_vendor_cfr_data_transport_modes {
+ QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0,
+ QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1,
+};
+
+/**
* enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
* attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
* command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
@@ -8313,6 +9701,27 @@
* MAC for CFR capture. This is a bitmask in which each bit represents the
* corresponding Data frame subtype value per IEEE Std 802.11-2016,
* 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8)
+ * Userspace can use this attribute to specify the driver about which transport
+ * mode shall be used by the driver to send CFR data to userspace. Uses values
+ * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is
+ * not present, the driver shall use the default transport mechanism which is
+ * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32)
+ * Userspace can use this attribute to specify the nl port id of the application
+ * which receives the CFR data and processes it further so that the drivers can
+ * unicast the netlink events to a specific application. Optionally included
+ * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to
+ * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers
+ * shall multicast the netlink events when this attribute is not included.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY).
+ * This attribute will be used by the driver to encapsulate and send CFR data
+ * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an
+ * asynchronous event when the driver is configured to send CFR data using
+ * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS.
*/
enum qca_wlan_vendor_peer_cfr_capture_attr {
QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
@@ -8341,6 +9750,9 @@
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28,
/* Keep last */
QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
@@ -8562,7 +9974,6 @@
* has priority over BT_A2DP and ZB_HIGH.
* 3: BT_A2DP has priority over ZB_HIGH.
*/
-
enum qca_vendor_attr_coex_config_three_way {
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0,
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1,
@@ -9027,20 +10438,48 @@
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
* Nested attribute containing multiple ranges with following attributes:
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
* Starting center frequency in MHz.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
* Ending center frequency in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
+ * s32 attribute, optional. It is a per frequency range attribute.
+ * The maximum TX power limit from user space is to be applied on an
+ * unrestricted interface for corresponding frequency range. It is also
+ * possible that the actual TX power may be even lower than this cap due to
+ * other considerations such as regulatory compliance, SAR, etc. In absence of
+ * this attribute the driver shall follow current behavior which means
+ * interface (SAP/P2P) function can keep operating on an unsafe channel with TX
+ * power derived by the driver based on regulatory/SAR during interface up.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
+ * u32 attribute, optional. Indicates all the interface types which are
+ * restricted for all frequency ranges provided in
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * This attribute encapsulates bitmasks of interface types defined in
+ * enum nl80211_iftype. If an interface is marked as restricted the driver must
+ * move to a safe channel and if no safe channel is available the driver shall
+ * terminate that interface functionality. In absence of this attribute,
+ * interface (SAP/P2P) can still continue operating on an unsafe channel with
+ * TX power limit derived from either
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
+ * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
+ * is not provided.
*/
enum qca_wlan_vendor_attr_avoid_frequency_ext {
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -9366,7 +10805,56 @@
* @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode
* only. This represents number of Beacon frames received from this station with
* the packet number less than or equal to the last received packet number when
- * beacon protection is enabled.
+ * beacon protection is enabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in
+ * STA mode only. The driver uses this attribute to populate the connection
+ * failure reason codes and the values are defined in
+ * enum qca_sta_connect_fail_reason_codes. Userspace applications can send
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving
+ * a connection failure indication from the driver. The driver shall not
+ * include this attribute in response to the
+ * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection
+ * failure observed in the last attempted connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE: u32, latest TX rate (Kbps)
+ * used by the station in its last TX frame while communicating to the AP in the
+ * connected state. When queried in the disconnected state, this represents the
+ * rate used by the STA in the last TX frame to the AP when it was connected.
+ * This attribute is used for STA mode only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX: u32, used in STA mode only.
+ * This represents the rate index used by the STA for the last TX frame to the
+ * AP. When queried in the disconnected state, this gives the last RIX used by
+ * the STA in the last TX frame to the AP when it was connected.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT: u32, used in STA
+ * mode only. This represents the number of times the STA TSF goes out of sync
+ * from the AP after the connection. If queried in the disconnected state, this
+ * gives the count of TSF out of sync for the last connection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. This can be queried either in connected state or
+ * disconnected state. Each bit of this attribute represents the different
+ * roam trigger reason code which are defined in enum qca_vendor_roam_triggers.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON: u32, used in STA mode
+ * only. This represents the roam fail reason for the last failed roaming
+ * attempt by the firmware. Different roam failure reason codes are specified
+ * in enum qca_vendor_roam_fail_reasons. This can be queried either in
+ * connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
+ * queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
*/
enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -9412,6 +10900,14 @@
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE = 44,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX = 45,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT = 46,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
@@ -9842,4 +11338,718 @@
QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL:
+ * u8 attribute. Notify the TX VDEV status. Possible values 0, 1
+ * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV,
+ * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT:
+ * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID:
+ * u8 attribute, required. Indicates group id of Tx VDEV.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * group information. The attributes defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info
+ * are nested in this attribute.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_status {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX:
+ * u32 attribute, required. Contains interface index.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS:
+ * u8 attribute, required. 0 - means vdev is in down state.
+ * 1 - means vdev is in up state.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary
+ * STA interface has to be given while selecting the connection policies
+ * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface.
+ * An interface is set as primary through the attribute
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not
+ * applicable if the primary interface has not been set earlier.
+ *
+ * The intention is not to downgrade the primary STA performance, such as:
+ * - Do not reduce the number of TX/RX chains of primary connection.
+ * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of
+ * chains.
+ * - If using MCC, should set the MCC duty cycle of the primary connection to
+ * be higher than the secondary connection.
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the
+ * subsequent STA connection shall be chosen to balance with the existing
+ * concurrent STA's performance.
+ * Such as
+ * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware
+ * capability.
+ * - If using MCC, set the MCC duty cycle of the primary connection to be equal
+ * to the secondary.
+ * - Prefer BSSID candidates which will help provide the best "overall"
+ * performance for all the STA connections.
+ */
+enum qca_wlan_concurrent_sta_policy_config {
+ QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0,
+ QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_concurrent_sta_policy - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG:
+ * u8 attribute. Configures the concurrent STA policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config.
+ */
+enum qca_wlan_vendor_attr_concurrent_sta_policy {
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST - 1,
+
+};
+
+/**
+ * enum qca_sta_connect_fail_reason_codes - Defines values carried
+ * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor
+ * attribute.
+ * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received
+ * for unicast Probe Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for
+ * auth request.
+ * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not
+ * received from AP.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for
+ * Association Request frame.
+ * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response
+ * frame is not received from AP.
+ */
+enum qca_sta_connect_fail_reason_codes {
+ QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3,
+ QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6,
+ QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
+};
+
+/**
+ * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different
+ * filters defined in this enum are used in attribute
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK.
+ *
+ * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver
+ * shall filter the channels which are not usable because of coexistence with
+ * cellular radio.
+ * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver
+ * shall filter the channels which are not usable because of existing active
+ * interfaces in the driver and will result in Multi Channel Concurrency, etc.
+ *
+ */
+enum qca_wlan_vendor_usable_channels_filter {
+ QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0,
+ QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_chan_info - Attributes used inside
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ:
+ * u32 attribute, required. Indicates the center frequency of the primary
+ * channel in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ:
+ * u32 attribute. Indicates the center frequency of the primary segment of the
+ * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz,
+ * 160 MHz, and 320 MHz channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ:
+ * u32 attribute. Indicates the center frequency of the secondary segment of
+ * 80+80 channel in MHz. This attribute is required only when
+ * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH:
+ * u32 attribute, required. Indicates the bandwidth of the channel, possible
+ * values are defined in enum nl80211_chan_width.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK:
+ * u32 attribute, required. Indicates all the interface types for which this
+ * channel is usable. This attribute encapsulates bitmasks of interface types
+ * defined in enum nl80211_iftype.
+ *
+ */
+enum qca_wlan_vendor_attr_chan_info {
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_usable_channels - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK:
+ * u32 attribute. Indicates the bands from which the channels should be reported
+ * in response. This attribute encapsulates bit masks of bands defined in enum
+ * nl80211_band. Optional attribute, if not present in the request the driver
+ * shall return channels from all supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK:
+ * u32 attribute. Indicates all the interface types for which the usable
+ * channels information is requested. This attribute encapsulates bitmasks of
+ * interface types defined in enum nl80211_iftype. Optional attribute, if not
+ * present in the request the driver shall send information of all supported
+ * interface modes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK:
+ * u32 attribute. This attribute carries information of all filters that shall
+ * be applied while populating usable channels information by the driver. This
+ * attribute carries bit masks of different filters defined in enum
+ * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present
+ * in the request the driver shall send information of channels without applying
+ * any of the filters that can be configured through this attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * usability information of each channel. The attributes defined in enum
+ * qca_wlan_vendor_attr_chan_info are used inside this attribute.
+ */
+enum qca_wlan_vendor_attr_usable_channels {
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX =
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry
+ * the list of radar history entries.
+ * Each entry contains freq, timestamp, and radar signal detect flag.
+ * The driver shall add an entry when CAC has finished, or radar signal
+ * has been detected post AP beaconing. The driver shall maintain at least
+ * 8 entries in order to save CAC result for a 160 MHz channel.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute.
+ * Channel frequency in MHz.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds.
+ * CLOCK_BOOTTIME timestamp when this entry is updated due to CAC
+ * or radar detection.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute.
+ * This flag indicates radar signal has been detected.
+ */
+enum qca_wlan_vendor_attr_radar_history {
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_mcc_quota_type: MCC channel time quota type
+ *
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR: In the event, it indicates that the
+ * target exited MCC state and cleared the quota information. In the
+ * command it clears MCC quota setting and restores adaptive scheduling.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED: Channel time quota is fixed and
+ * will not be changed.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC: Channel time quota is dynamic
+ * and the target may change the quota based on the data activity.
+ */
+enum qca_wlan_vendor_mcc_quota_type {
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR = 0,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED = 1,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mcc_quota: Used by the vendor event
+ * QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA to indicate MCC channel
+ * quota information or as a command to set the required MCC quota for an
+ * interface.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE: u32 attribute.
+ * The type is defined in enum qca_wlan_vendor_mcc_quota_type.
+ * In a command this specifies the MCC quota type to be set for the interface.
+ * In an event this provides the current quota type in force.
+ * This is required in a command and an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES: Nested attribute to carry
+ * the list of channel quota entries.
+ * In an event each entry contains the frequency and respective time quota for
+ * all the MCC interfaces.
+ * In a command it specifies the interface index and respective time quota.
+ * In a command only one entry (ifindex, quota pair) may be specified.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ: u32 attribute.
+ * Channel frequency in MHz. This is present only in an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE: u32 attribute.
+ * Channel time quota expressed as percentage.
+ * This is present in an event and a command.
+ * In an command, the user shall specify the quota to be allocated for the
+ * interface represented by %QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX.
+ * In an event this provides the existing quota for the channel.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX: u32 attribute.
+ * Specifies the interface index (netdev) for which the corresponding
+ * configurations are applied. This is required in a command only. Only one
+ * interface index may be specified. If not specified, the configuration is
+ * rejected.
+ */
+enum qca_wlan_vendor_attr_mcc_quota {
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES = 2,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE = 4,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX =
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag)
+ * Enable mDNS offload. This attribute is mandatory to enable
+ * mDNS offload feature. If this attribute is not present, mDNS offload
+ * is disabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing
+ * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This
+ * attribute is mandatory when enabling the feature, and not required when
+ * disabling the feature.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing
+ * the following attributes:
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute.
+ * It consists of a hostname and ".local" as the domain name. The character
+ * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes.
+ * It is used to compare the domain in the "QU" query. Only 1 FQDN is
+ * supported per vdev.
+ * For example: myphone.local
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required
+ * u16 attribute. It specifies the total number of resource records present
+ * in the answer section of the answer payload. This attribute is needed by the
+ * firmware to populate the mDNS response frame for mDNS queries without having
+ * to parse the answer payload.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob
+ * attribute sent by the mdnsResponder from userspace. It contains resource
+ * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This
+ * payload is passed down to the firmware and is transmitted in response to
+ * mDNS queries.
+ * The maximum supported size of the answer payload is 512 bytes.
+ */
+enum qca_wlan_vendor_attr_mdns_offload {
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_monitor_data_frame_type - Represent the various
+ * Data frame types to be sent over the monitor interface.
+ */
+enum qca_wlan_vendor_monitor_data_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17),
+};
+
+/**
+ * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various
+ * Management frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames
+ * except the Beacon frame.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected
+ * BSSID Beacon frames. Valid only in the connected state.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents
+ * the Beacon frames obtained during the scan (off channel and connected
+ * channel), when in connected state.
+ */
+enum qca_wlan_vendor_monitor_mgmt_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3),
+};
+
+/**
+ * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various
+ * Control frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame
+ */
+enum qca_wlan_vendor_monitor_ctrl_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the
+ * monitor mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32
+ * attribute.
+ * Represents the interval in milliseconds only for the connected Beacon frames,
+ * expecting the connected BSS's Beacon frames to be sent on the monitor
+ * interface at this specific interval.
+ */
+enum qca_wlan_vendor_attr_set_monitor_mode {
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX =
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags.
+ * Bits will be set to 1 if the corresponding state is enabled.
+ *
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start.
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end.
+ */
+enum qca_wlan_vendor_roam_scan_state {
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_roam_event_type - Roam event type flags.
+ * Bits will be set to 1 if the corresponding event is notified.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event
+ * carries the trigger reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries
+ * the BSSID, RSSI, frequency info of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event
+ * carries the roam fail reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the
+ * BSSID, RSSI, frequency info of the AP to which the roam was attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam
+ * event carries the roam invoke fail reason. When set, it is expected that
+ * the roam event carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event
+ * carries the roam scan state. When set, it is expected that the roam event
+ * carries the respective scan state via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding
+ * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST.
+ */
+enum qca_wlan_vendor_roam_event_type {
+ QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1),
+ QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2),
+ QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info.
+ * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address
+ * representing the BSSID of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value
+ * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is
+ * attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz
+ * on which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam fail reason for the last failed
+ * roaming attempt by the firmware for the specific BSSID. Different roam
+ * failure reason codes are specified in enum qca_vendor_roam_fail_reasons.
+ */
+enum qca_wlan_vendor_attr_roam_events_candidate_info {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the
+ * roam events to the driver or notify these events from the driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the
+ * driver/firmware to enable/disable the notification of roam events. It's a
+ * mandatory attribute and used only in the request from the userspace to the
+ * host driver. 1-Enable, 0-Disable.
+ * If the roaming is totally offloaded to the firmware, this request when
+ * enabled shall mandate the firmware to notify all the relevant roam events
+ * represented by the below attributes. If the host is in the suspend mode,
+ * the behavior of the firmware to notify these events is guided by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get
+ * these events in the suspend state, the firmware is expected to wake up the
+ * host before the respective events are notified. Please note that such a
+ * request to get the events in the suspend state will have a definite power
+ * implication.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents
+ * that the roam events need to be notified in the suspend state too. By
+ * default, these roam events are notified in the resume state. With this flag,
+ * the roam events are notified in both resume and suspend states.
+ * This attribute is used in the request from the userspace to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only.
+ * Represents the different roam event types, signified by the enum
+ * qca_wlan_vendor_roam_event_type.
+ * Each bit of this attribute represents the different roam even types reported
+ * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. Each bit of this attribute represents the
+ * different roam trigger reason code which are defined in enum
+ * qca_vendor_roam_triggers.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info
+ * for which the roam is attempted. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_roam_events_candidate_info.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents
+ * the scan state on which the roam events need to be notified. The values for
+ * this attribute are referred from enum qca_wlan_vendor_roam_scan_state.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of
+ * u32 values. List of frequencies in MHz considered for a roam scan.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ */
+enum qca_wlan_vendor_attr_roam_events {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1,
+};
+
+/**
+ * enum qca_wlan_ratemask_params_type - Rate mask config type
+ *
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM: CCK/OFDM rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
+ */
+enum qca_wlan_ratemask_params_type {
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ratemask_params - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG.
+ * This is used to set the rate mask value to be used in rate selection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST:
+ * Array of nested containing attributes
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE and
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE: u8, represents
+ * the different PHY types to which the rate mask config is to be applied.
+ * The values for this attribute are referred from enum
+ * qca_wlan_vendor_ratemask_params_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap.
+ * A bit value of 1 represents rate is enabled and a value of 0
+ * represents rate is disabled.
+ * For HE targets, 12 bits correspond to one NSS setting.
+ * b0-13 => NSS1, MCS 0-13
+ * b14-27 => NSS2, MCS 0-13 and so on for other NSS.
+ * For VHT targets, 10 bits correspond to one NSS setting.
+ * b0-9 => NSS1, MCS 0-9
+ * b10-19 => NSS2, MCS 0-9 and so on for other NSS.
+ * For HT targets, 8 bits correspond to one NSS setting.
+ * b0-7 => NSS1, MCS 0-7
+ * b8-15 => NSS2, MCS 0-7 and so on for other NSS.
+ * For OFDM/CCK targets, 8 bits correspond to one NSS setting.
+ */
+enum qca_wlan_vendor_attr_ratemask_params {
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/wcn6740/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h b/wcn6740/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
new file mode 100644
index 0000000..054d840
--- /dev/null
+++ b/wcn6740/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
@@ -0,0 +1,381 @@
+/*
+ * 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"
+#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
+#define IEEE80211_HE_OPERATION_6G_OPER_MASK 0x00020000
+
+#define HE_OPER_VHT_CH_WIDTH_OFFSET 0
+#define HE_OPER_VHT_CENTER_FRQ_SEG0_OFFSET 1
+#define HE_OPER_VHT_CENTER_FRQ_SEG1_OFFSET 2
+#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
+
+/* 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_ANI_LEVEL \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL
+#define GET_STA_INFO_LATEST_TX_RATE \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE
+#define GET_STA_INFO_LATEST_RIX \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX
+#define GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT
+#define GET_STA_INFO_LATEST_TX_POWER \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER
+#define GET_STA_INFO_ROAM_TRIGGER_REASON \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON
+#define GET_STA_INFO_TARGET_POWER_24G_1MBPS \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS
+#define GET_STA_INFO_TARGET_POWER_24G_6MBPS \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS
+#define GET_STA_INFO_TARGET_POWER_5G_6MBPS \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS
+#define GET_STA_INFO_ROAM_FAIL_REASON \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON
+#define GET_STA_INFO_ROAM_INVOKE_FAIL_REASON \
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON
+#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];
+ 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;
+ u32 ani_level;
+ u32 roam_trigger_reason;
+ u32 roam_fail_reason;
+ u32 roam_invoke_fail_reason;
+ u32 tsf_out_of_sync_count;
+ u32 latest_tx_power;
+ u32 latest_tx_rate;
+ u32 target_power_24g_1mbps;
+ u32 target_power_24g_6mbps;
+ u32 target_power_5g_6mbps;
+};
+
+enum get_info_cmd {
+ GETSTATSBSSINFO = 1,
+ SETCELLSWITCHMODE = 2,
+ GET_DRIVER_SUPPORTED_FEATURES = 3,
+};
+
+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[COUNTRY_LEN];
+};
+
+#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 */
+
+/* HE channel widths */
+
+#define HE_CHANWIDTH_20MHZ 0
+#define HE_CHANWIDTH_40MHZ 1
+#define HE_CHANWIDTH_80MHZ 2
+#define HE_CHANWIDTH_160MHZ 3
+
+/**
+ * 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)
+
+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_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;
+ 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;
+ u32 ani_level;
+ u32 roam_trigger_reason;
+ u32 roam_fail_reason;
+ u32 roam_invoke_fail_reason;
+ u32 tsf_out_of_sync_count;
+ u32 latest_tx_power;
+ u32 latest_tx_rate;
+ u32 latest_rix;
+ u32 target_power_24g_1mbps;
+ u32 target_power_24g_6mbps;
+ u32 target_power_5g_6mbps;
+ u8 *supp_op_classes; /* Supported Operating Classes element, if
+ * 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
diff --git a/wcn6740/wcnss-service/Android.mk b/wcn6740/wcnss-service/Android.mk
new file mode 100644
index 0000000..42d83e1
--- /dev/null
+++ b/wcn6740/wcnss-service/Android.mk
@@ -0,0 +1,30 @@
+ifneq (,$(filter arm aarch64 arm64, $(TARGET_ARCH)))
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED),true)
+LOCAL_VENDOR_MODULE := true
+endif
+LOCAL_MODULE := wcnss_service
+LOCAL_HEADER_LIBRARIES += vendor_common_inc
+LOCAL_SRC_FILES := wcnss_service.c
+LOCAL_SHARED_LIBRARIES := libc libcutils libutils liblog
+ifeq ($(strip $(TARGET_USES_QCOM_WCNSS_QMI)),true)
+LOCAL_CFLAGS += -DWCNSS_QMI
+ifeq ($(filter 10% Q% q%,$(TARGET_PLATFORM_VERSION)),)
+#For Android R and above, assuming not compiling on Q and lower
+LOCAL_HEADER_LIBRARIES += libqmi_common_headers
+else
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qmi-framework/inc
+endif
+LOCAL_SRC_FILES += wcnss_qmi_client.c
+LOCAL_SHARED_LIBRARIES += libqmiservices libqmi_cci
+LOCAL_HEADER_LIBRARIES += libmdmdetect_headers
+LOCAL_SHARED_LIBRARIES += libmdmdetect
+LOCAL_HEADER_LIBRARIES += libril-qc-qmi-services-headers
+endif #TARGET_USES_QCOM_WCNSS_QMI
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/wcn6740/wcnss-service/wcnss_qmi_client.c b/wcn6740/wcnss-service/wcnss_qmi_client.c
new file mode 100644
index 0000000..3e1fb0e
--- /dev/null
+++ b/wcn6740/wcnss-service/wcnss_qmi_client.c
@@ -0,0 +1,135 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2013, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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.
+--------------------------------------------------------------------------*/
+
+#ifdef WCNSS_QMI
+#define LOG_TAG "wcnss_qmi"
+#include <cutils/log.h>
+#include "wcnss_qmi_client.h"
+#include "qmi_client.h"
+#include "device_management_service_v01.h"
+#include <cutils/properties.h>
+#include <string.h>
+
+#define SUCCESS 0
+#define FAILED -1
+
+#define WLAN_ADDR_SIZE 6
+#define DMS_QMI_TIMEOUT (2000)
+
+static qmi_client_type dms_qmi_client;
+static int dms_init_done = FAILED;
+
+int wcnss_init_qmi()
+{
+ qmi_client_error_type qmi_client_err;
+
+ ALOGE("%s: Initialize wcnss QMI Interface", __func__);
+ qmi_client_os_params dms_os_params;
+
+ memset(&dms_os_params, 0, sizeof(qmi_client_os_params));
+ qmi_client_err = qmi_client_init_instance(dms_get_service_object_v01(),
+ QMI_CLIENT_INSTANCE_ANY, NULL, NULL,
+ &dms_os_params, 5000, &dms_qmi_client);
+
+ if (qmi_client_err != QMI_NO_ERR){
+ ALOGE("%s: Error while Initializing QMI Client: %d",
+ __func__, qmi_client_err);
+ goto exit;
+ }
+
+ dms_init_done = SUCCESS;
+ return SUCCESS;
+
+exit:
+ return FAILED;
+}
+
+int wcnss_qmi_get_wlan_address(unsigned char *pBdAddr)
+{
+ qmi_client_error_type qmi_client_err;
+ dms_get_mac_address_req_msg_v01 addr_req;
+ dms_get_mac_address_resp_msg_v01 addr_resp;
+
+ if ((dms_init_done == FAILED) || (pBdAddr == NULL)) {
+ ALOGE("%s: DMS init fail or pBdAddr is NULL", __func__);
+ return FAILED;
+ }
+
+ /* clear the request content */
+ memset(&addr_req, 0, sizeof(addr_req));
+
+ /*Request to get the WLAN MAC address */
+ addr_req.device = DMS_DEVICE_MAC_WLAN_V01;
+
+ qmi_client_err = qmi_client_send_msg_sync(dms_qmi_client,
+ QMI_DMS_GET_MAC_ADDRESS_REQ_V01, &addr_req, sizeof(addr_req),
+ &addr_resp, sizeof(addr_resp), DMS_QMI_TIMEOUT);
+
+ if (qmi_client_err != QMI_NO_ERR){
+ ALOGE("%s: Failed to get Rsp from Modem Error:%d",
+ __func__, qmi_client_err);
+ return FAILED;
+ }
+
+ ALOGE("%s: Mac Address_valid: %d Mac Address Len: %d",
+ __func__, addr_resp.mac_address_valid,
+ addr_resp.mac_address_len);
+
+ if (addr_resp.mac_address_valid &&
+ (addr_resp.mac_address_len == WLAN_ADDR_SIZE)) {
+ memcpy(pBdAddr, addr_resp.mac_address,
+ addr_resp.mac_address_len);
+ ALOGE("%s: Succesfully Read WLAN MAC Address", __func__);
+ return SUCCESS;
+ } else {
+ ALOGE("%s: Failed to Read WLAN MAC Address", __func__);
+ return FAILED;
+ }
+}
+
+void wcnss_qmi_deinit()
+{
+ qmi_client_error_type qmi_client_err;
+
+ ALOGE("%s: Deinitialize wcnss QMI Interface", __func__);
+
+ if (dms_init_done == FAILED) {
+ ALOGE("%s: DMS Service was not Initialized", __func__);
+ return;
+ }
+
+ qmi_client_err = qmi_client_release(dms_qmi_client);
+
+ if (qmi_client_err != QMI_NO_ERR){
+ ALOGE("%s: Error while releasing qmi_client: %d",
+ __func__, qmi_client_err);
+ }
+
+ dms_init_done = FAILED;
+}
+#endif
diff --git a/qcwcn/wcnss-service/wcnss_qmi_client.h b/wcn6740/wcnss-service/wcnss_qmi_client.h
similarity index 100%
copy from qcwcn/wcnss-service/wcnss_qmi_client.h
copy to wcn6740/wcnss-service/wcnss_qmi_client.h
diff --git a/wcn6740/wcnss-service/wcnss_service.c b/wcn6740/wcnss-service/wcnss_service.c
new file mode 100644
index 0000000..c817be1
--- /dev/null
+++ b/wcn6740/wcnss-service/wcnss_service.c
@@ -0,0 +1,815 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2013, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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.
+--------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <grp.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <sys/sendfile.h>
+#define LOG_TAG "wcnss_service"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#ifdef WCNSS_QMI
+#include "wcnss_qmi_client.h"
+#include "mdm_detect.h"
+#endif
+
+#define SUCCESS 0
+#define FAILED -1
+#define BYTE_0 0
+#define BYTE_1 8
+#define BYTE_2 16
+#define BYTE_3 24
+#define UNUSED(x) (void)(x)
+
+#define MAX_FILE_LENGTH (1024)
+#define WCNSS_MAX_CMD_LEN (128)
+
+/* control messages to wcnss driver */
+#define WCNSS_USR_CTRL_MSG_START 0x00000000
+#define WCNSS_USR_SERIAL_NUM (WCNSS_USR_CTRL_MSG_START + 1)
+#define WCNSS_USR_HAS_CAL_DATA (WCNSS_USR_CTRL_MSG_START + 2)
+#define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3)
+
+
+#define WCNSS_CAL_CHUNK (3*1024)
+#define WCNSS_CAL_FILE "/data/vendor/wifi/WCNSS_qcom_wlan_cal.bin"
+#define WCNSS_FACT_FILE "/data/vendor/wifi/WCN_FACTORY"
+#define WCNSS_DEVICE "/dev/wcnss_wlan"
+#define WCNSS_CTRL "/dev/wcnss_ctrl"
+#define WLAN_INI_FILE_DEST "/data/vendor/wifi/WCNSS_qcom_cfg.ini"
+#define WLAN_INI_FILE_SOURCE "/vendor/etc/wifi/WCNSS_qcom_cfg.ini"
+#define WCNSS_HAS_CAL_DATA\
+ "/sys/module/wcnsscore/parameters/has_calibrated_data"
+#define WLAN_DRIVER_ATH_DEFAULT_VAL "0"
+
+#define ASCII_A 65
+#define ASCII_a 97
+#define ASCII_0 48
+#define HEXA_A 10
+#define HEX_BASE 16
+
+#ifdef WCNSS_QMI
+#define WLAN_ADDR_SIZE 6
+unsigned char wlan_nv_mac_addr[WLAN_ADDR_SIZE];
+#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+/* As we Want to write in 00:0a:f5:11:22:33 format in sysfs file
+ so taking mac length as 12 char + 5 for ":" + NULL
+ */
+#define WLAN_MAC_ADDR_STRING 18
+#endif
+
+#define MAX_SOC_INFO_NAME_LEN (15)
+#define MAX_DATA_NVBIN_PATH_LEN (64)
+#define QRD_DYNAMIC_NV_PROP "persist.sys.dynamic.nv"
+#define QRD_HW_PLATFORM "QRD"
+#define QRD_PLATFORM_SUBTYPE_ID 0
+#define PERSIST_NVFILE "/persist/WCNSS_qcom_wlan_nv.bin"
+#define DATA_NVFILE_DIR "/data/misc/wifi/nvbin/"
+#define SYSFS_SOCID_PATH1 "/sys/devices/soc0/soc_id"
+#define SYSFS_SOCID_PATH2 "/sys/devices/system/soc/soc0/id"
+#define SYSFS_HW_PLATFORM_PATH1 "/sys/devices/soc0/hw_platform"
+#define SYSFS_HW_PLATFORM_PATH2 "/sys/devices/system/soc/soc0/hw_platform"
+#define SYSFS_PLATFORM_SUBTYPE_PATH1 "/sys/devices/soc0/platform_subtype_id"
+#define SYSFS_PLATFORM_SUBTYPE_PATH2 "/sys/devices/system/soc/soc0/platform_subtype_id"
+#define SYSFS_PLATFORM_VERSION_PATH1 "/sys/devices/soc0/platform_version"
+#define SYSFS_PLATFORM_VERSION_PATH2 "/sys/devices/system/soc/soc0/platform_version"
+#define SOCINFO_HWVER_MAJOR(ver) (((ver) & 0x00ff0000) >> 16)
+#define SOCINFO_HWVER_MINOR(ver) ((ver) & 0x000000ff)
+#define GET_SOC_INFO(buf, soc_node_path1, soc_node_path2, info_got) \
+ { if (get_soc_info(buf, soc_node_path1, soc_node_path2) < 0) \
+ { \
+ ALOGE("get_soc_info failed!\n"); \
+ return FAILED; \
+ } \
+ info_got = atoi(buf); \
+ }
+
+int wcnss_write_cal_data(int fd_dev)
+{
+ int rcount = 0;
+ int size = 0;
+ int rc = 0;
+ int wcount = 0;
+ int fd_file;
+ struct stat st;
+
+ char buf[WCNSS_CAL_CHUNK];
+
+ ALOGI("wcnss_write_cal_data trying to write cal");
+
+ rc = stat(WCNSS_CAL_FILE, &st);
+ if (rc < 0) {
+ ALOGE("Failed to stat cal file : %s",
+ strerror(errno));
+ goto exit;
+ }
+
+ size = st.st_size;
+
+ fd_file = open(WCNSS_CAL_FILE, O_RDONLY);
+ if (fd_file < 0) {
+ ALOGE("cal file doesn't exist: %s",
+ strerror(errno));
+ rc = fd_file;
+ goto exit;
+ }
+
+ /* write the file size first, so that platform driver knows
+ * when it recieves the full data */
+ wcount = write(fd_dev, (void *)&size, 4);
+ if (wcount != 4) {
+ ALOGE("Failed to write to wcnss device : %s",
+ strerror(errno));
+ rc = wcount;
+ goto exit_close;
+ }
+
+ do {
+ rcount = read(fd_file, (void *)buf, sizeof(buf));
+ if (rcount < 0) {
+ ALOGE("Failed to read from cal file ; %s",
+ strerror(errno));
+ rc = rcount;
+ goto exit_remove;
+ }
+
+ if (!rcount)
+ break;
+
+ wcount = write(fd_dev, buf, rcount);
+ if (wcount < 0) {
+ ALOGE("Failed to write to wcnss device : %s",
+ strerror(errno));
+ rc = wcount;
+ goto exit_close;
+ }
+
+ } while (rcount);
+ close(fd_file);
+
+ return SUCCESS;
+
+exit_remove:
+ close(fd_file);
+ remove("WCNSS_CAL_FILE");
+ return rc;
+
+exit_close:
+ close(fd_file);
+
+exit:
+ return rc;
+}
+
+
+int wcnss_read_and_store_cal_data(int fd_dev)
+{
+ int rcount = 0;
+ int wcount = 0;
+ int fd_file = -1;
+ int rc = 0;
+
+ char buf[WCNSS_CAL_CHUNK];
+
+ ALOGI("wcnss_read_and_store_cal_data trying to read cal");
+
+ do {
+ /* wait on this read until data comes from fw */
+ rcount = read(fd_dev, (void *)buf, sizeof(buf));
+ if (rcount < 0) {
+ ALOGE("Failed to read from wcnss device : %s",
+ strerror(errno));
+ rc = rcount;
+ goto exit;
+ }
+
+ /* truncate the file only if there is fw data, this read
+ * may never return if the fw decides that no more cal is
+ * required; and the data we have now is good enough.
+ */
+ if (fd_file < 0) {
+ fd_file = open(WCNSS_CAL_FILE, O_WRONLY
+ | O_CREAT | O_TRUNC, 0664);
+ if (fd_file < 0) {
+ ALOGE("Failed to open cal file : %s",
+ strerror(errno));
+ rc = fd_file;
+ goto exit;
+ }
+ }
+
+ if (!rcount)
+ break;
+
+ wcount = write(fd_file, buf, rcount);
+ if (wcount < 0) {
+ ALOGE("Failed to write to cal file : %s",
+ strerror(errno));
+ rc = wcount;
+ goto exit_remove;
+ }
+
+ } while (rcount);
+
+ close(fd_file);
+
+ return SUCCESS;
+
+exit_remove:
+ close(fd_file);
+ remove(WCNSS_CAL_FILE);
+
+exit:
+ return rc;
+}
+
+
+void find_full_path(char *cur_dir, char *file_to_find, char *full_path)
+{
+ DIR *dir;
+ struct stat st;
+ struct dirent *dr;
+ char cwd[1024];
+ int rc;
+
+ chdir(cur_dir);
+
+ dir = opendir(".");
+
+ if (dir != NULL) {
+ while ((dr = readdir(dir))) {
+
+ rc = lstat(dr->d_name, &st);
+ if (rc < 0) {
+ ALOGE("lstat failed %s", strerror(errno));
+ return;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ if ((strcmp(dr->d_name, ".")) &&
+ (strcmp(dr->d_name, ".."))) {
+ find_full_path(dr->d_name,
+ file_to_find, full_path);
+ }
+ } else if (!strcmp(file_to_find, dr->d_name)) {
+ getcwd(cwd, sizeof(cwd));
+ snprintf(full_path, MAX_FILE_LENGTH, "%s/%s",
+ cwd, file_to_find);
+ }
+ }
+ closedir(dir);
+ }
+
+ chdir("..");
+}
+
+void setup_wlan_config_file()
+{
+ int rfd;
+ int wfd;
+ struct stat st_dest, st_src;
+ int rc_dest;
+ int rc;
+ struct group *grp;
+ struct utimbuf new_time;
+
+ rc = stat(WLAN_INI_FILE_SOURCE, &st_src);
+ if (rc != 0) {
+ ALOGE("source file do not exist %s", WLAN_INI_FILE_SOURCE);
+ return;
+ }
+
+ rc_dest = stat(WLAN_INI_FILE_DEST, &st_dest);
+ if (rc_dest == 0 && st_dest.st_size &&
+ (st_dest.st_mtime > st_src.st_mtime)) {
+ ALOGE("wlan ini file exists %s and is newer than %s",
+ WLAN_INI_FILE_DEST, WLAN_INI_FILE_SOURCE);
+ goto out_nocopy;
+ }
+
+ rfd = open(WLAN_INI_FILE_SOURCE, O_RDONLY);
+ if (rfd < 0) {
+ ALOGE("Failed to open ini source file: %s", strerror(errno));
+ return;
+ }
+
+ wfd = open(WLAN_INI_FILE_DEST, O_WRONLY | O_CREAT | O_TRUNC, 0660);
+ if (wfd < 0) {
+ ALOGE("Failed to open ini dest file: %s", strerror(errno));
+ close(rfd);
+ return;
+ }
+
+ rc = sendfile(wfd, rfd, 0, st_src.st_size);
+ if (rc != st_src.st_size) {
+ ALOGE("Failed to copy ini file: %s", strerror(errno));
+ goto out;
+ }
+
+ new_time.actime = st_src.st_atime;
+ new_time.modtime = st_src.st_mtime;
+
+ rc = utime(WLAN_INI_FILE_DEST, &new_time);
+ if (rc != 0)
+ ALOGE("could not preserve the timestamp %s", strerror(errno));
+
+ grp = getgrnam("wifi");
+ if (grp != NULL) {
+ rc = chown(WLAN_INI_FILE_DEST, -1, grp->gr_gid);
+ if (rc != 0)
+ ALOGE("Failed change group of ini file %s", strerror(errno));
+ } else {
+ ALOGE("Failed to get group wifi %s", strerror(errno));
+ }
+
+ property_set("vendor.wlan.driver.config", WLAN_INI_FILE_DEST);
+
+out:
+ close(rfd);
+ close(wfd);
+ return;
+
+out_nocopy:
+ property_set("vendor.wlan.driver.config", WLAN_INI_FILE_DEST);
+ return;
+}
+unsigned int convert_string_to_hex(char* string)
+{
+ int idx;
+ unsigned long int hex_num = 0;
+ for(idx = 0; string[idx] != '\0'; idx++){
+ if(isalpha(string[idx])) {
+ if(string[idx] >='a' && string[idx] <='f') {
+ hex_num = hex_num * HEX_BASE + ((int)string[idx]
+ - ASCII_a + HEXA_A);
+ } else if ( string[idx] >='A' && string[idx] <='F') {
+ hex_num = hex_num * HEX_BASE + ((int)string[idx]
+ - ASCII_A + HEXA_A);
+ } else
+ hex_num = hex_num * HEX_BASE + (int)string[idx];
+ } else {
+ hex_num = hex_num * HEX_BASE + (string[idx]- ASCII_0);
+ }
+ }
+ hex_num = hex_num & 0xFFFFFFFF;
+ return hex_num;
+}
+
+
+#ifdef WCNSS_QMI
+void setup_wcnss_parameters(int *cal, int nv_mac_addr)
+#else
+void setup_wcnss_parameters(int *cal)
+#endif
+{
+ char msg[WCNSS_MAX_CMD_LEN];
+ char serial[PROPERTY_VALUE_MAX];
+ int fd, rc, pos = 0;
+ struct stat st;
+ unsigned int serial_num = 0;
+
+ fd = open(WCNSS_CTRL, O_WRONLY);
+ if (fd < 0) {
+ ALOGE("Failed to open %s : %s", WCNSS_CTRL, strerror(errno));
+ return;
+ }
+
+ rc = property_get("ro.serialno", serial, "");
+ if (rc) {
+ serial_num = convert_string_to_hex(serial);
+ ALOGE("Serial Number is %x", serial_num);
+
+ msg[pos++] = WCNSS_USR_SERIAL_NUM >> BYTE_1;
+ msg[pos++] = WCNSS_USR_SERIAL_NUM >> BYTE_0;
+ msg[pos++] = serial_num >> BYTE_3;
+ msg[pos++] = serial_num >> BYTE_2;
+ msg[pos++] = serial_num >> BYTE_1;
+ msg[pos++] = serial_num >> BYTE_0;
+
+ if (write(fd, msg, pos) < 0) {
+ ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
+ strerror(errno));
+ goto fail;
+ }
+ }
+
+#ifdef WCNSS_QMI
+ if (SUCCESS == nv_mac_addr)
+ {
+ pos = 0;
+ msg[pos++] = WCNSS_USR_WLAN_MAC_ADDR >> BYTE_1;
+ msg[pos++] = WCNSS_USR_WLAN_MAC_ADDR >> BYTE_0;
+ msg[pos++] = wlan_nv_mac_addr[0];
+ msg[pos++] = wlan_nv_mac_addr[1];
+ msg[pos++] = wlan_nv_mac_addr[2];
+ msg[pos++] = wlan_nv_mac_addr[3];
+ msg[pos++] = wlan_nv_mac_addr[4];
+ msg[pos++] = wlan_nv_mac_addr[5];
+
+ ALOGI("WLAN MAC Addr:" MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(wlan_nv_mac_addr));
+
+ if (write(fd, msg, pos) < 0) {
+ ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
+ strerror(errno));
+ goto fail;
+ }
+ }
+#endif
+
+ pos = 0;
+ msg[pos++] = WCNSS_USR_HAS_CAL_DATA >> BYTE_1;
+ msg[pos++] = WCNSS_USR_HAS_CAL_DATA >> BYTE_0;
+
+ rc = stat(WCNSS_FACT_FILE, &st);
+ if (rc == 0) {
+ ALOGE("Factory file found, deleting cal file");
+ unlink(WCNSS_CAL_FILE);
+ goto fail_resp;
+ }
+
+ rc = stat(WCNSS_CAL_FILE, &st);
+ if (rc != 0) {
+ ALOGE("CAL file not found");
+ goto fail_resp;
+ }
+
+ /* has cal data */
+ msg[pos++] = 1;
+
+ if (write(fd, msg, pos) < 0) {
+ ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
+ strerror(errno));
+ goto fail;
+ }
+
+ ALOGI("Correctly triggered cal file");
+ *cal = SUCCESS;
+ close(fd);
+ return;
+
+fail_resp:
+ msg[pos++] = 0;
+ if (write(fd, msg, pos) < 0)
+ ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
+ strerror(errno));
+
+fail:
+ *cal = FAILED;
+ close(fd);
+ return;
+}
+
+void setup_wlan_driver_ath_prop()
+{
+ property_set("vendor.wlan.driver.ath", WLAN_DRIVER_ATH_DEFAULT_VAL);
+}
+
+#ifdef WCNSS_QMI
+int check_modem_compatability(struct dev_info *mdm_detect_info)
+{
+ char args[MODEM_BASEBAND_PROPERTY_SIZE] = {0};
+ int ret = 0;
+ /* Get the hardware property */
+ ret = property_get(MODEM_BASEBAND_PROPERTY, args, "");
+ if (ret > MODEM_BASEBAND_PROPERTY_SIZE) {
+ ALOGE("property [%s] has size [%d] that exceeds max [%d]",
+ MODEM_BASEBAND_PROPERTY, ret, MODEM_BASEBAND_PROPERTY_SIZE);
+ return 0;
+ }
+ /* This will check for the type of hardware, and if the
+ hardware type needs external modem, it will check if the
+ modem type is external*/
+ if(!strncmp(MODEM_BASEBAND_VALUE_APQ, args, 3)) {
+
+ for (ret = 0; ret < mdm_detect_info->num_modems; ret++) {
+ if (mdm_detect_info->mdm_list[ret].type == MDM_TYPE_EXTERNAL) {
+ ALOGE("Hardware supports external modem");
+ return 1;
+ }
+ }
+ ALOGE("Hardware does not support external modem");
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+static int read_line_from_file(const char *path, char *buf, size_t count)
+{
+ char * fgets_ret;
+ FILE * fd;
+ int rv;
+
+ fd = fopen(path, "r");
+ if (fd == NULL)
+ return -1;
+
+ fgets_ret = fgets(buf, (int)count, fd);
+ if (NULL != fgets_ret) {
+ rv = (int)strlen(buf);
+ } else {
+ rv = ferror(fd);
+ }
+
+ fclose(fd);
+
+ return rv;
+}
+
+static int get_soc_info(char *buf, char *soc_node_path1,
+ char *soc_node_path2)
+{
+ int ret = 0;
+
+ ret = read_line_from_file(soc_node_path1, buf,
+ MAX_SOC_INFO_NAME_LEN);
+ if (ret < 0) {
+ ret = read_line_from_file(soc_node_path2, buf,
+ MAX_SOC_INFO_NAME_LEN);
+ if (ret < 0) {
+ ALOGE("getting socinfo(%s, %d) failed.\n",
+ soc_node_path1, ret);
+ return ret;
+ }
+ }
+ if (ret && buf[ret - 1] == '\n')
+ buf[ret - 1] = '\0';
+
+ return ret;
+}
+
+static int get_data_nvfile_path(char *data_nvfile_path,
+ struct stat *pdata_nvfile_stat)
+{
+ char target_board_platform[PROP_VALUE_MAX] = {'\0'};
+ char buf[MAX_SOC_INFO_NAME_LEN] = {'\0'};
+ int soc_id, platform_subtype_id, platform_version;
+ int major_hwver, minor_hwver;
+ int rc;
+
+ rc = property_get("ro.board.platform", target_board_platform, "");
+ if (!rc)
+ {
+ ALOGE("get ro.board.platform fail, rc=%d(%s)\n",
+ rc, strerror(errno));
+ return FAILED;
+ }
+
+ GET_SOC_INFO(buf, SYSFS_SOCID_PATH1, SYSFS_SOCID_PATH2, soc_id);
+ GET_SOC_INFO(buf, SYSFS_PLATFORM_SUBTYPE_PATH1,
+ SYSFS_PLATFORM_SUBTYPE_PATH2, platform_subtype_id);
+ GET_SOC_INFO(buf, SYSFS_PLATFORM_VERSION_PATH1,
+ SYSFS_PLATFORM_VERSION_PATH2, platform_version);
+
+ major_hwver = SOCINFO_HWVER_MAJOR(platform_version);
+ minor_hwver = SOCINFO_HWVER_MINOR(platform_version);
+
+ snprintf(data_nvfile_path, MAX_DATA_NVBIN_PATH_LEN,
+ "%s%s_%d_0x%02x_0x%02x_0x%02x_nv.bin", DATA_NVFILE_DIR,
+ target_board_platform, soc_id, platform_subtype_id&0xff,
+ major_hwver&0xff, minor_hwver&0xff);
+ ALOGI("data_nvfile_path %s\n",
+ data_nvfile_path);
+
+ if (stat(data_nvfile_path, pdata_nvfile_stat) != 0)
+ {
+ ALOGE("source file do not exist %s\n",
+ data_nvfile_path);
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+static int nvbin_sendfile(const char *dst, const char *src,
+ struct stat *src_stat)
+{
+ struct utimbuf new_time;
+ int fp_src, fp_dst;
+ int rc;
+ if ((fp_src = open(src, O_RDONLY)) < 0)
+ {
+ ALOGE("open %s failed(%s).\n",
+ src, strerror(errno));
+ return FAILED;
+ }
+
+ if ((fp_dst = open(dst, O_WRONLY |O_TRUNC)) < 0)
+ {
+ close(fp_src);
+ ALOGE("open %s failed(%s).\n",
+ dst, strerror(errno));
+ return FAILED;
+ }
+
+ if (sendfile(fp_dst, fp_src, 0, src_stat->st_size) == -1)
+ {
+ ALOGE("dynamic nv sendfile failed: (%s).\n",
+ strerror(errno));
+ rc = FAILED;
+ goto exit;
+ }
+
+ new_time.actime = src_stat->st_atime;
+ new_time.modtime = src_stat->st_mtime;
+ if (utime(dst, &new_time) != 0)
+ {
+ ALOGE("could not preserve the timestamp %s",
+ strerror(errno));
+ rc = FAILED;
+ goto exit;
+ }
+
+ rc = SUCCESS;
+exit:
+ close(fp_dst);
+ close(fp_src);
+ return rc;
+}
+void dynamic_nv_replace()
+{
+ char data_nvfile_path[MAX_DATA_NVBIN_PATH_LEN] = {'\0'};
+ char property_nv_replaced_status [PROPERTY_VALUE_MAX] = { '\0' };
+ char buf[MAX_SOC_INFO_NAME_LEN] = {'\0'};
+ struct stat data_nvfile_stat;
+ int rc;
+
+ if (property_get(QRD_DYNAMIC_NV_PROP, property_nv_replaced_status, NULL)
+ && strcmp(property_nv_replaced_status, "done") == 0) {
+ ALOGI("dynamic nv have been replaced. leave\n");
+ return;
+ }
+
+ rc = get_soc_info(buf, SYSFS_HW_PLATFORM_PATH1, SYSFS_HW_PLATFORM_PATH2);
+ if (rc < 0)
+ {
+ ALOGE("get_soc_info(HW_PLATFORM) fail!\n");
+ return;
+ } else {
+ if( 0 != strncmp(buf, QRD_HW_PLATFORM, MAX_SOC_INFO_NAME_LEN))
+ {
+ ALOGI("dynamic nv only for QRD platform, current platform:%s.\n",
+ buf);
+ return;
+ }
+ }
+
+ rc = get_data_nvfile_path(data_nvfile_path, &data_nvfile_stat);
+ if (rc != SUCCESS)
+ {
+ ALOGE("Get source file path fail !\n");
+ return;
+ }
+
+ if (property_set(QRD_DYNAMIC_NV_PROP, "replacing") < 0)
+ {
+ ALOGE("set %s to replacing failed (%s).\n",
+ QRD_DYNAMIC_NV_PROP, strerror(errno));
+ return;
+ }
+
+ rc = nvbin_sendfile(PERSIST_NVFILE, data_nvfile_path, &data_nvfile_stat);
+ if ( rc != SUCCESS)
+ {
+ ALOGE("nvbin_sendfile failed.\n");
+ return;
+ }
+
+ if (property_set(QRD_DYNAMIC_NV_PROP, "done") < 0)
+ {
+ ALOGE("set %s to done failed(%s).\n",
+ QRD_DYNAMIC_NV_PROP, strerror(errno));
+ return;
+ }
+
+ ALOGI("dynamic nv replace sucessfully!\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+ UNUSED(argc), UNUSED(argv);
+ int rc;
+ int fd_dev, ret_cal;
+#ifdef WCNSS_QMI
+ int nv_mac_addr = FAILED;
+ struct dev_info mdm_detect_info;
+ int nom = 0;
+#endif
+
+ setup_wlan_config_file();
+
+#ifdef WCNSS_QMI
+ /* Call ESOC API to get the number of modems.
+ If the number of modems is not zero, only then proceed
+ with the eap_proxy intialization.*/
+
+ nom = get_system_info(&mdm_detect_info);
+
+ if (nom > 0)
+ ALOGE("Failed to get system info, ret %d", nom);
+
+ if (mdm_detect_info.num_modems == 0) {
+ ALOGE("wcnss_service: No Modem support for this target"
+ " number of modems is %d", mdm_detect_info.num_modems);
+ goto nomodem;
+ }
+
+ ALOGE("wcnss_service: num_modems = %d", mdm_detect_info.num_modems);
+
+ if(!check_modem_compatability(&mdm_detect_info)) {
+ ALOGE("wcnss_service: Target does not have external modem");
+ goto nomodem;
+ }
+
+ /* initialize the DMS client and request the wlan mac address */
+
+ if (SUCCESS == wcnss_init_qmi()) {
+
+ rc = wcnss_qmi_get_wlan_address(wlan_nv_mac_addr);
+
+ if (rc == SUCCESS) {
+ nv_mac_addr = SUCCESS;
+ ALOGE("WLAN MAC Addr:" MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(wlan_nv_mac_addr));
+ } else
+ ALOGE("Failed to Get MAC addr from modem");
+
+ wcnss_qmi_deinit();
+ }
+ else
+ ALOGE("Failed to Initialize wcnss QMI Interface");
+
+nomodem:
+#endif
+
+ dynamic_nv_replace();
+
+#ifdef WCNSS_QMI
+ setup_wcnss_parameters(&ret_cal, nv_mac_addr);
+#else
+ setup_wcnss_parameters(&ret_cal);
+#endif
+
+ fd_dev = open(WCNSS_DEVICE, O_RDWR);
+ if (fd_dev < 0) {
+ ALOGE("Failed to open wcnss device : %s",
+ strerror(errno));
+ return fd_dev;
+ }
+
+ if (ret_cal != FAILED) {
+ rc = wcnss_write_cal_data(fd_dev);
+ if (rc != SUCCESS)
+ ALOGE("No cal data is written to WCNSS %d", rc);
+ else
+ ALOGE("Cal data is successfully written to WCNSS");
+ }
+
+ setup_wlan_driver_ath_prop();
+
+ rc = wcnss_read_and_store_cal_data(fd_dev);
+ if (rc != SUCCESS)
+ ALOGE("Failed to read and save cal data %d", rc);
+ else
+ ALOGI("Calibration data was successfull written to %s",
+ WCNSS_CAL_FILE);
+
+ close(fd_dev);
+
+ return rc;
+}