summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-27 10:16:41 -0700
committerXin Li <delphij@google.com>2020-08-27 10:16:41 -0700
commite04942fc155f52be895b30432dcfecbde9c4799e (patch)
treebfb3960f0e76abe9eb757037e777e824f9e7150c
parentef6b231056bb1bdcea293429c939d6c4396714f0 (diff)
parent5c074eb45f6f6c9847128811688d98e0cd9de78f (diff)
downloadwlan-temp_sam_168057903.tar.gz
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)temp_sam_168057903
Bug: 166295507 Merged-In: I3ef9471c3daf6846f9e9ee56df2f57661d4ddb00 Change-Id: I1e02ed042efd096b4d664707cab17560adfa2de7
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/Android.mk7
-rwxr-xr-xbcmdhd/wifi_hal/brcm_version.h1
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/common.cpp10
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/common.h122
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/cpp_bindings.cpp15
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/cpp_bindings.h11
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/gscan.cpp210
-rw-r--r--bcmdhd/wifi_hal/link_layer_stats.cpp15
-rwxr-xr-xbcmdhd/wifi_hal/nan.cpp5292
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/wifi_hal.cpp436
-rwxr-xr-x[-rw-r--r--]bcmdhd/wifi_hal/wifi_logger.cpp455
-rw-r--r--bcmdhd/wifi_hal/wifi_offload.cpp31
12 files changed, 6483 insertions, 122 deletions
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
index b4fe46e..5763789 100644..100755
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -27,12 +27,18 @@ LOCAL_CFLAGS := \
-Wno-unused-parameter \
-Wno-unused-private-field \
-Wno-unused-variable \
+ -Wno-unused-parameter
LOCAL_C_INCLUDES += \
external/libnl/include \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
external/wpa_supplicant_8/src/drivers
+LOCAL_C_INCLUDES += \
+ external/boringssl/include \
+ external/boringssl/src/crypto/digest \
+ external/boringssl/src/crypto/evp/
+
LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers
LOCAL_SRC_FILES := \
@@ -41,6 +47,7 @@ LOCAL_SRC_FILES := \
common.cpp \
cpp_bindings.cpp \
gscan.cpp \
+ nan.cpp \
link_layer_stats.cpp \
wifi_logger.cpp \
wifi_offload.cpp
diff --git a/bcmdhd/wifi_hal/brcm_version.h b/bcmdhd/wifi_hal/brcm_version.h
new file mode 100755
index 0000000..14efbee
--- /dev/null
+++ b/bcmdhd/wifi_hal/brcm_version.h
@@ -0,0 +1 @@
+#define HAL_VERSION "Android-10-FRC2-SDK_29 59.0 (r854927) 2019-12-06 23:33:52 +0530 (Fri, 06 Dec 2019)"
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
index 3540d49..c164ba4 100644..100755
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -37,6 +37,8 @@
#include "common.h"
#include "cpp_bindings.h"
+/* test mode flag for halutil only */
+bool halutil_mode = false;
interface_info *getIfaceInfo(wifi_interface_handle handle)
{
return (interface_info *)handle;
@@ -261,3 +263,11 @@ wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
return WIFI_ERROR_INVALID_ARGS;
}
+void set_hautil_mode(bool util_mode)
+{
+ halutil_mode = util_mode;
+}
+bool get_halutil_mode()
+{
+ return halutil_mode;
+}
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 28e2156..98801b2 100644..100755
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -34,6 +34,8 @@
#define DOT11_OUI_LEN 3
#define DOT11_MAX_SSID_LEN 32
+#define ETHERTYPE_IP 0x0800 /* IP */
+#define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */
#define MAX_PROBE_RESP_IE_LEN 2048
/*
Vendor OUI - This is a unique identifier that identifies organization. Lets
@@ -45,12 +47,21 @@ const uint32_t GOOGLE_OUI = 0x001A11;
/* TODO: define vendor OUI here */
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+#define NMR2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
+#define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+#define NAN_MASTER_RANK_LEN 8
+
+
/*
This enum defines ranges for various commands; commands themselves
can be defined in respective feature headers; i.e. find gscan command
definitions in gscan.cpp
*/
+typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
typedef enum {
/* don't use 0 as a valid subcommand */
VENDOR_NL80211_SUBCMD_UNSPECIFIED,
@@ -90,6 +101,10 @@ typedef enum {
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
+ /* define all tx power related commands between 0x1900 and 0x1910 */
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x1910,
+
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
@@ -115,42 +130,92 @@ typedef enum {
WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */
WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */
WIFI_SUBCMD_NODFS_SET, /* 0x100D */
- WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
+ WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
/* Add more sub commands here */
GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */
- WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
- WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
- WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
- WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
+ WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
+ WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
+ WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
+ WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */
- GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
- WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
- WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
- /* Add more sub commands here */
+ GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
+ WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
+ WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
+ WIFI_SUBCMD_CONFIG_TCPACK_SUP, /* 0x1018 */
+ WIFI_SUBCMD_FW_ROAM_POLICY, /* 0x1019 */
+ WIFI_SUBCMD_ROAM_CAPABILITY, /* 0x101a */
+ WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x101b */
GSCAN_SUBCMD_MAX,
+ /* NAN related */
+ NAN_SUBCMD_ENABLE = ANDROID_NL80211_SUBCMD_NAN_RANGE_START,
+ NAN_SUBCMD_DISABLE, /* 0x1701 */
+ NAN_SUBCMD_PUBLISH, /* 0x1702 */
+ NAN_SUBCMD_SUBSCRIBE, /* 0x1703 */
+ NAN_SUBCMD_PUBLISH_CANCEL, /* 0x1704 */
+ NAN_SUBCMD_SUBSCRIBE_CANCEL, /* 0x1705 */
+ NAN_SUBCMD_TRANSMIT_FOLLOWUP, /* 0x1706 */
+ NAN_SUBCMD_CONFIG, /* 0x1707 */
+ NAN_SUBCMD_TCA, /* 0x1708 */
+ NAN_SUBCMD_STATS, /* 0x1709 */
+ NAN_SUBCMD_GET_CAPABILITIES, /* 0x170A */
+ NAN_SUBCMD_DATA_PATH_IFACE_CREATE, /* 0x170B */
+ NAN_SUBCMD_DATA_PATH_IFACE_DELETE, /* 0x170C */
+ NAN_SUBCMD_DATA_PATH_REQUEST, /* 0x170D */
+ NAN_SUBCMD_DATA_PATH_RESPONSE, /* 0x170E */
+ NAN_SUBCMD_DATA_PATH_END, /* 0x170F */
+ NAN_SUBCMD_DATA_PATH_SEC_INFO, /* 0x1710 */
+ NAN_SUBCMD_VERSION_INFO, /* 0x1711 */
+ NAN_SUBCMD_ENABLE_MERGE, /* 0x1712 */
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
+ WIFI_SUBCMD_TX_POWER_SCENARIO = ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START,
} WIFI_SUB_COMMAND;
typedef enum {
- BRCM_RESERVED1,
- BRCM_RESERVED2,
- GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS ,
- GSCAN_EVENT_HOTLIST_RESULTS_FOUND,
- GSCAN_EVENT_SCAN_RESULTS_AVAILABLE,
- GSCAN_EVENT_FULL_SCAN_RESULTS,
- RTT_EVENT_COMPLETE,
- GSCAN_EVENT_COMPLETE_SCAN,
- GSCAN_EVENT_HOTLIST_RESULTS_LOST,
- GSCAN_EVENT_EPNO_EVENT,
- GOOGLE_DEBUG_RING_EVENT,
- GOOGLE_DEBUG_MEM_DUMP_EVENT,
- GSCAN_EVENT_ANQPO_HOTSPOT_MATCH,
- GOOGLE_RSSI_MONITOR_EVENT
+ BRCM_RESERVED1 = 0,
+ BRCM_RESERVED2 = 1,
+ GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS = 2,
+ GSCAN_EVENT_HOTLIST_RESULTS_FOUND = 3,
+ GSCAN_EVENT_SCAN_RESULTS_AVAILABLE = 4,
+ GSCAN_EVENT_FULL_SCAN_RESULTS = 5,
+ RTT_EVENT_COMPLETE = 6,
+ GSCAN_EVENT_COMPLETE_SCAN = 7,
+ GSCAN_EVENT_HOTLIST_RESULTS_LOST = 8,
+ GSCAN_EVENT_EPNO_EVENT = 9,
+ GOOGLE_DEBUG_RING_EVENT = 10,
+ GOOGLE_DEBUG_MEM_DUMP_EVENT = 11,
+ GSCAN_EVENT_ANQPO_HOTSPOT_MATCH = 12,
+ GOOGLE_RSSI_MONITOR_EVENT = 13,
+ GOOGLE_MKEEP_ALIVE = 14,
+
+ /*
+ * BRCM specific events should be placed after the Generic events
+ * in order to match between the DHD and HAL
+ */
+ NAN_EVENT_ENABLED = 15,
+ NAN_EVENT_DISABLED = 16,
+ NAN_EVENT_SUBSCRIBE_MATCH = 17,
+ NAN_EVENT_PUBLISH_REPLIED_IND = 18,
+ NAN_EVENT_PUBLISH_TERMINATED = 19,
+ NAN_EVENT_SUBSCRIBE_TERMINATED = 20,
+ NAN_EVENT_DE_EVENT = 21,
+ NAN_EVENT_FOLLOWUP = 22,
+ NAN_EVENT_TRANSMIT_FOLLOWUP_IND = 23,
+ NAN_EVENT_DATA_REQUEST = 24,
+ NAN_EVENT_DATA_CONFIRMATION = 25,
+ NAN_EVENT_DATA_END = 26,
+ NAN_EVENT_BEACON = 27,
+ NAN_EVENT_SDF = 28,
+ NAN_EVENT_TCA = 29,
+ NAN_EVENT_SUBSCRIBE_UNMATCH = 30,
+ NAN_EVENT_UNKNOWN,
+ ROAM_EVENT_START,
+ GOOGLE_FILE_DUMP_EVENT = 37,
+ NAN_ASYNC_RESPONSE_DISABLED = 40
} WIFI_EVENT;
typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
@@ -256,6 +321,17 @@ hal_info *getHalInfo(wifi_interface_handle handle);
wifi_handle getWifiHandle(hal_info *info);
wifi_interface_handle getIfaceHandle(interface_info *info);
wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
+wifi_error nan_deinit_handler();
+wifi_error wifi_start_hal(wifi_interface_handle iface);
+wifi_error wifi_stop_hal(wifi_interface_handle iface);
+wifi_interface_handle wifi_get_wlan_interface(wifi_handle info,
+ wifi_interface_handle *ifaceHandles, int numIfaceHandles);
+wifi_error wifi_hal_preInit(wifi_interface_handle iface);
+/* API to get wake reason statistics */
+wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+void set_hautil_mode(bool halutil_mode);
+bool get_halutil_mode();
// some common macros
diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp
index 0ac4c08..5ca6431 100644..100755
--- a/bcmdhd/wifi_hal/cpp_bindings.cpp
+++ b/bcmdhd/wifi_hal/cpp_bindings.cpp
@@ -34,11 +34,22 @@
#include <netlink/handlers.h>
#include <ctype.h>
+#include <errno.h>
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
+pthread_mutex_t ResponseMutex;
+void InitResponseLock() {
+ pthread_mutex_init(&ResponseMutex, NULL);
+}
+
+void DestroyResponseLock()
+{
+ pthread_mutex_destroy(&ResponseMutex);
+}
+
void appendFmt(char *buf, int &offset, const char *fmt, ...)
{
va_list params;
@@ -607,7 +618,8 @@ int WifiCommand::requestResponse() {
}
int WifiCommand::requestResponse(WifiRequest& request) {
- int err = 0;
+ pthread_mutex_lock(&ResponseMutex);
+ int err = 0, res = 0;
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb)
@@ -633,6 +645,7 @@ int WifiCommand::requestResponse(WifiRequest& request) {
}
out:
nl_cb_put(cb);
+ pthread_mutex_unlock(&ResponseMutex);
return err;
}
diff --git a/bcmdhd/wifi_hal/cpp_bindings.h b/bcmdhd/wifi_hal/cpp_bindings.h
index 2c1aa05..8839a72 100644..100755
--- a/bcmdhd/wifi_hal/cpp_bindings.h
+++ b/bcmdhd/wifi_hal/cpp_bindings.h
@@ -101,6 +101,9 @@ public:
return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
}
+ void *get_string(int attribute) {
+ return mAttributes[attribute] ? nla_get_string(mAttributes[attribute]) : NULL;
+ }
private:
WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies
};
@@ -143,6 +146,9 @@ public:
int get_len() {
return nla_len(pos);
}
+ void* get_string() {
+ return nla_get_string(pos);
+ }
private:
nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies
};
@@ -193,6 +199,9 @@ public:
int put(int attribute, void *ptr, unsigned len) {
return nla_put(mMsg, attribute, len, ptr);
}
+ int put_s8(int attribute, int8_t value) {
+ return nla_put(mMsg, attribute, sizeof(value), &value);
+ }
int put_u8(int attribute, uint8_t value) {
return nla_put(mMsg, attribute, sizeof(value), &value);
}
@@ -367,3 +376,5 @@ private:
nla_ok(pos, rem); \
pos = (nlattr *)nla_next(pos, &(rem)))
+extern void InitResponseLock();
+extern void DestroyResponseLock();
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
index 4e4ee93..f5722f2 100644..100755
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -159,10 +159,16 @@ typedef enum {
GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
+ /* Roaming features */
+ GSCAN_ATTRIBUTE_ROAM_STATE_SET = 140,
GSCAN_ATTRIBUTE_MAX
} GSCAN_ATTRIBUTE;
+typedef struct {
+ int num_bssid; // number of blacklisted BSSIDs
+ mac_addr bssids[MAX_BLACKLIST_BSSID]; // blacklisted BSSIDs
+} wifi_bssid_params;
// helper methods
wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
@@ -190,18 +196,22 @@ void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
class GetCapabilitiesCommand : public WifiCommand
{
- wifi_gscan_capabilities *mCapabilities;
-public:
- GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
- : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
+ void *mCapabilities;
+ uint16_t mRequesttype;
+ int mRequestsize;
+ public:
+ GetCapabilitiesCommand(wifi_interface_handle iface, void *capabitlites, uint16_t request_type,
+ int request_size)
+ : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites), mRequesttype(request_type),
+ mRequestsize(request_size)
{
- memset(mCapabilities, 0, sizeof(*mCapabilities));
+ memset(mCapabilities, 0, mRequestsize);
}
virtual int create() {
ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
- int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
+ int ret = mMsg.create(GOOGLE_OUI, mRequesttype);
if (ret < 0) {
return ret;
}
@@ -209,7 +219,7 @@ public:
return ret;
}
-protected:
+ protected:
virtual int handleResponse(WifiEvent& reply) {
ALOGV("In GetCapabilities::handleResponse");
@@ -225,20 +235,28 @@ protected:
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
- ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
- sizeof(*mCapabilities));
+ ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %zd", id, subcmd, len,
+ mRequestsize);
- memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
+ memcpy(mCapabilities, data, min(len, mRequestsize));
return NL_OK;
}
};
-
wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
wifi_gscan_capabilities *capabilities)
{
- GetCapabilitiesCommand command(handle, capabilities);
+ GetCapabilitiesCommand command(handle, capabilities, GSCAN_SUBCMD_GET_CAPABILITIES,
+ (int)sizeof(wifi_gscan_capabilities));
+ return (wifi_error) command.requestResponse();
+}
+
+wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
+ wifi_roaming_capabilities *capabilities)
+{
+ GetCapabilitiesCommand command(handle, capabilities, WIFI_SUBCMD_ROAM_CAPABILITY,
+ (int)sizeof(wifi_roaming_capabilities));
return (wifi_error) command.requestResponse();
}
@@ -1676,6 +1694,174 @@ wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
return result;
}
+class BssidBlacklistCommand : public WifiCommand
+{
+ private:
+ wifi_bssid_params *mParams;
+ public:
+ BssidBlacklistCommand(wifi_interface_handle handle, int id,
+ wifi_bssid_params *params)
+ : WifiCommand("BssidBlacklistCommand", handle, id), mParams(params)
+ { }
+ int createRequest(WifiRequest& request) {
+ if ((mParams->num_bssid < 0) || (mParams->num_bssid > MAX_BLACKLIST_BSSID)) {
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_BSSID_BLACKLIST);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!mParams->num_bssid) {
+ result = request.put_u32(GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH, 1);
+ if (result < 0) {
+ return result;
+ }
+ } else {
+ result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID, mParams->num_bssid);
+ if (result < 0) {
+ return result;
+ }
+ for (int i = 0; i < mParams->num_bssid; i++) {
+ result = request.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID, mParams->bssids[i]);
+ if (result < 0) {
+ return result;
+ }
+ }
+ }
+ request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ ALOGV("Executing bssid blacklist request, num = %d", mParams->num_bssid);
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGE("Failed to execute bssid blacklist request, result = %d", result);
+ return result;
+ }
+
+ ALOGI("Successfully added %d blacklist bssids", mParams->num_bssid);
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
+ wifi_bssid_params params)
+{
+ wifi_handle handle = getWifiHandle(iface);
+
+ BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ //release the reference of command as well
+ cmd->releaseRef();
+ return result;
+}
+
+wifi_error wifi_configure_roaming(wifi_interface_handle iface,
+ wifi_roaming_config *roam_config)
+{
+ wifi_error ret;
+ wifi_bssid_params bssid_params;
+ unsigned int i;
+ wifi_request_id id = 0;
+
+ /* Set bssid blacklist */
+ if (roam_config->num_blacklist_bssid == 0) {
+ /* Flush request */
+ ALOGI("%s: num_blacklist_bssid == 0 (flush)", __FUNCTION__);
+ }
+
+ bssid_params.num_bssid = roam_config->num_blacklist_bssid;
+
+ for (i = 0; i < roam_config->num_blacklist_bssid; i++) {
+ mac_addr &addr1 = roam_config->blacklist_bssid[i];
+ memcpy(&bssid_params.bssids[i], &roam_config->blacklist_bssid[i],
+ sizeof(mac_addr));
+ ALOGI("%02x:%02x:%02x:%02x:%02x:%02x\n", addr1[0],
+ addr1[1], addr1[2], addr1[3], addr1[4], addr1[5]);
+ }
+ ret = wifi_set_bssid_blacklist(id, iface, bssid_params);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to configure blacklist bssids", __FUNCTION__);
+ return ret;
+ }
+
+ return ret;
+}
+
+class FirmwareRoamingStateCommand : public WifiCommand
+{
+ private:
+ fw_roaming_state_t roam_state;
+ public:
+ FirmwareRoamingStateCommand(wifi_interface_handle handle,
+ fw_roaming_state_t state)
+ : WifiCommand("FirmwareRoamingStateCommand", handle, -1), roam_state(state)
+ { }
+ int createRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_FW_ROAM_POLICY);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(GSCAN_ATTRIBUTE_ROAM_STATE_SET, roam_state);
+ if (result < 0) {
+ return result;
+ }
+ request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ ALOGV("Executing firmware roam state set, state = %d", roam_state);
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGE("Failed to execute firmware roam state set, result = %d", result);
+ return result;
+ }
+
+ ALOGI("Successfully set firmware roam state - %d", roam_state);
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_enable_firmware_roaming(wifi_interface_handle iface,
+ fw_roaming_state_t state)
+{
+ /* Set firmware roaming state */
+ FirmwareRoamingStateCommand *cmd = new FirmwareRoamingStateCommand(iface, state);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ //release the reference of command as well
+ cmd->releaseRef();
+ return result;
+}
////////////////////////////////////////////////////////////////////////////////
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 42e3f2f..34226f4 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -106,21 +106,6 @@ protected:
ALOGE("Invalid stats pointer received");
return NL_SKIP;
}
- if (radio_stat->num_channels > 11) {
- ALOGE("Incorrect number of channels = %d", radio_stat->num_channels);
- // dump data before num_channels
- ALOGE("radio: = %d", radio_stat->radio);
- ALOGE("on_time: = %d", radio_stat->on_time);
- ALOGE("tx_time: = %d", radio_stat->tx_time);
- ALOGE("rx_time: = %d", radio_stat->rx_time);
- ALOGE("on_time_scan: = %d", radio_stat->on_time_scan);
- ALOGE("on_time_nbd: = %d", radio_stat->on_time_nbd);
- ALOGE("on_time_gscan: = %d", radio_stat->on_time_gscan);
- ALOGE("on_time_pno_scan: = %d", radio_stat->on_time_pno_scan);
- ALOGE("on_time_hs20: = %d", radio_stat->on_time_hs20);
- free(radio_stat);
- return NL_SKIP;
- }
wifi_iface_stat *iface_stat =
(wifi_iface_stat *)((char *)&((wifi_radio_stat_internal *)data)->channels
+ radio_stat->num_channels * sizeof(wifi_channel_stat));
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
new file mode 100755
index 0000000..cfabfa8
--- /dev/null
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -0,0 +1,5292 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Portions copyright (C) 2019 Broadcom Limited
+ *
+ * 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 <ctype.h>
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+
+#include "nl80211_copy.h"
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+#include <log/log.h>
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "netinet/in.h"
+#include "arpa/inet.h"
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <sys/ioctl.h>
+
+/* Changes between incompatible Version of NAN */
+#define NAN_MAJOR_REL_VERSION 1
+/* Changes between Source and Binary compatible Version of NAN */
+#define NAN_MINOR_REL_VERSION 2
+/* Changes between perfectly compatible Version of NAN */
+#define NAN_PATCH_REL_VERSION 3
+
+#define SVC_NAME_TO_HASH 1
+#define NAN_SVC_HASH_SIZE 6
+#define C2S(x) case x: return #x;
+#define NAN_PUB_RECV_FLAG_MAX 15
+#define NAN_SUB_RECV_FLAG_MAX 7
+#define NAN_DISC_IND_MAX 7
+#define NAN_MAX 255
+#define NAN_MIN 0
+#define INVALID 0xFF
+#define NAN_MAX_PERIOD 16
+#define ISGREATER(i, x) (i > x) ? 1 : 0
+#define NAN_MAX_RSSI 90
+#define NAN_SECURITY_SALT_SIZE 14
+#define NAN_MAC_INVALID_TRANSID 0xFFFF
+
+#define SVCHASH_ISNULL(svc_hash) ((((u8 *)(svc_hash))[0] | \
+ ((u8 *)(svc_hash))[1] | \
+ ((u8 *)(svc_hash))[2] | \
+ ((u8 *)(svc_hash))[3] | \
+ ((u8 *)(svc_hash))[4] | \
+ ((u8 *)(svc_hash))[5]) == 0)
+#define ETHER_ISNULLADDR(ea) ((((u8 *)(ea))[0] | \
+ ((u8 *)(ea))[1] | \
+ ((u8 *)(ea))[2] | \
+ ((u8 *)(ea))[3] | \
+ ((u8 *)(ea))[4] | \
+ ((u8 *)(ea))[5]) == 0)
+
+/* NAN structs versioning b/w DHD and HAL
+ * TODO:add versions for each struct*/
+#define NAN_HAL_VERSION_1 0x2
+struct nan_dbg_cntrs {
+ u32 dp_req; /* cmd */
+ u32 dp_resp; /* cmd */
+ u32 dp_req_evt;
+ u32 dp_confirm_evt;
+ u32 transmit_req; /* cmd */
+ u32 transmit_txs; /* event */
+ u32 transmit_recv; /* event */
+};
+nan_dbg_cntrs counters;
+
+u32 current_dhd_hal_ver = 0;
+
+/* TODO: Known bug in Android which was discovered too late and then left in for backward compatibility.
+ * The issue is that the Service Name selected by the framework is invalid - it contains a space.
+ * Therefore, the underlying implementation partially converts it to lower case and uses the results for PMK generation.
+ * I.e. the PMK is generated based on the following service name: "Wi-Fi Aware Data Path"
+ */
+/* SVC Hash generated for svc name string "Wi-Fi Aware Data Path" */
+u8 NAN_OOB_INTEROP_SVC_HASH[NAN_SVC_HASH_SIZE] = {0x05, 0x9e, 0xd4, 0xcf, 0x89, 0x1a};
+#define NAN_OOB_INTEROP_SVC_NAME "Wi-Fi Aware Data Path"
+
+static const char *NanStatusToString(NanStatusType status)
+{
+ switch (status) {
+ C2S(NAN_STATUS_SUCCESS)
+ C2S(NAN_STATUS_INTERNAL_FAILURE)
+ C2S(NAN_STATUS_PROTOCOL_FAILURE)
+ C2S(NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID)
+ C2S(NAN_STATUS_NO_RESOURCE_AVAILABLE)
+ C2S(NAN_STATUS_INVALID_PARAM)
+ C2S(NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID)
+ C2S(NAN_STATUS_INVALID_NDP_ID)
+ C2S(NAN_STATUS_NAN_NOT_ALLOWED)
+ C2S(NAN_STATUS_NO_OTA_ACK)
+ C2S(NAN_STATUS_ALREADY_ENABLED)
+ C2S(NAN_STATUS_FOLLOWUP_QUEUE_FULL)
+ C2S(NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED)
+
+ default:
+ return "NAN_STATUS_INTERNAL_FAILURE";
+ }
+}
+
+/* Nan Data Path Security Information */
+typedef struct {
+ /*
+ Unique Instance Id identifying the Responder's service.
+ This is same as publish_id notified on the subscribe side
+ in a publish/subscribe scenario
+ */
+ u32 requestor_instance_id; /* Value 0 for no publish/subscribe */
+ /*
+ Discovery MAC addr of the publisher/peer
+ */
+ u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN];
+ /*
+ Unique token Id generated on the initiator/responder
+ side used for a NDP session between two NAN devices
+ */
+ NanDataPathId ndp_instance_id;
+} NanDataPathSecInfoRequest;
+/*
+ * Note: NAN_ATTRIBUTE should match with one that on driver side, wl_cfgnan.h and
+ * NanAttrToString as well for enum to string.
+ */
+typedef enum {
+ NAN_ATTRIBUTE_HEADER = 100,
+ NAN_ATTRIBUTE_HANDLE = 101,
+ NAN_ATTRIBUTE_TRANSAC_ID = 102,
+
+ /* NAN Enable request attributes */
+ NAN_ATTRIBUTE_2G_SUPPORT = 103,
+ NAN_ATTRIBUTE_5G_SUPPORT = 104,
+ NAN_ATTRIBUTE_CLUSTER_LOW = 105,
+ NAN_ATTRIBUTE_CLUSTER_HIGH = 106,
+ NAN_ATTRIBUTE_SID_BEACON = 107,
+ NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON = 108,
+ NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON = 109,
+ NAN_ATTRIBUTE_SDF_2G_SUPPORT = 110,
+ NAN_ATTRIBUTE_SDF_5G_SUPPORT = 111,
+ NAN_ATTRIBUTE_RSSI_CLOSE = 112,
+ NAN_ATTRIBUTE_RSSI_MIDDLE = 113,
+ NAN_ATTRIBUTE_RSSI_PROXIMITY = 114,
+ NAN_ATTRIBUTE_HOP_COUNT_LIMIT = 115,
+ NAN_ATTRIBUTE_RANDOM_FACTOR = 116,
+ NAN_ATTRIBUTE_MASTER_PREF = 117,
+ NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL = 118,
+
+ /* Nan Publish/Subscribe request attributes */
+ NAN_ATTRIBUTE_PUBLISH_ID = 119,
+ NAN_ATTRIBUTE_TTL = 120,
+ NAN_ATTRIBUTE_PERIOD = 121,
+ NAN_ATTRIBUTE_REPLIED_EVENT_FLAG = 122,
+ NAN_ATTRIBUTE_PUBLISH_TYPE = 123,
+ NAN_ATTRIBUTE_TX_TYPE = 124,
+ NAN_ATTRIBUTE_PUBLISH_COUNT = 125,
+ NAN_ATTRIBUTE_SERVICE_NAME_LEN = 126,
+ NAN_ATTRIBUTE_SERVICE_NAME = 127,
+ NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN = 128,
+ NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO = 129,
+ NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN = 130,
+ NAN_ATTRIBUTE_RX_MATCH_FILTER = 131,
+ NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN = 132,
+ NAN_ATTRIBUTE_TX_MATCH_FILTER = 133,
+ NAN_ATTRIBUTE_SUBSCRIBE_ID = 134,
+ NAN_ATTRIBUTE_SUBSCRIBE_TYPE = 135,
+ NAN_ATTRIBUTE_SERVICERESPONSEFILTER = 136,
+ NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE = 137,
+ NAN_ATTRIBUTE_USESERVICERESPONSEFILTER = 138,
+ NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION = 139,
+ NAN_ATTRIBUTE_SUBSCRIBE_MATCH = 140,
+ NAN_ATTRIBUTE_SUBSCRIBE_COUNT = 141,
+ NAN_ATTRIBUTE_MAC_ADDR = 142,
+ NAN_ATTRIBUTE_MAC_ADDR_LIST = 143,
+ NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES = 144,
+ NAN_ATTRIBUTE_PUBLISH_MATCH = 145,
+
+ /* Nan Event attributes */
+ NAN_ATTRIBUTE_ENABLE_STATUS = 146,
+ NAN_ATTRIBUTE_JOIN_STATUS = 147,
+ NAN_ATTRIBUTE_ROLE = 148,
+ NAN_ATTRIBUTE_MASTER_RANK = 149,
+ NAN_ATTRIBUTE_ANCHOR_MASTER_RANK = 150,
+ NAN_ATTRIBUTE_CNT_PEND_TXFRM = 151,
+ NAN_ATTRIBUTE_CNT_BCN_TX = 152,
+ NAN_ATTRIBUTE_CNT_BCN_RX = 153,
+ NAN_ATTRIBUTE_CNT_SVC_DISC_TX = 154,
+ NAN_ATTRIBUTE_CNT_SVC_DISC_RX = 155,
+ NAN_ATTRIBUTE_AMBTT = 156,
+ NAN_ATTRIBUTE_CLUSTER_ID = 157,
+ NAN_ATTRIBUTE_INST_ID = 158,
+ NAN_ATTRIBUTE_OUI = 159,
+ NAN_ATTRIBUTE_STATUS = 160,
+ NAN_ATTRIBUTE_DE_EVENT_TYPE = 161,
+ NAN_ATTRIBUTE_MERGE = 162,
+ NAN_ATTRIBUTE_IFACE = 163,
+ NAN_ATTRIBUTE_CHANNEL = 164,
+ NAN_ATTRIBUTE_PEER_ID = 165,
+ NAN_ATTRIBUTE_NDP_ID = 167,
+ NAN_ATTRIBUTE_SECURITY = 168,
+ NAN_ATTRIBUTE_QOS = 169,
+ NAN_ATTRIBUTE_RSP_CODE = 170,
+ NAN_ATTRIBUTE_INST_COUNT = 171,
+ NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR = 172,
+ NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR = 173,
+ NAN_ATTRIBUTE_IF_ADDR = 174,
+ NAN_ATTRIBUTE_WARMUP_TIME = 175,
+ NAN_ATTRIBUTE_RECV_IND_CFG = 176,
+ NAN_ATTRIBUTE_RSSI_CLOSE_5G = 177,
+ NAN_ATTRIBUTE_RSSI_MIDDLE_5G = 178,
+ NAN_ATTRIBUTE_RSSI_PROXIMITY_5G = 179,
+ NAN_ATTRIBUTE_CONNMAP = 180,
+ NAN_ATTRIBUTE_24G_CHANNEL = 181,
+ NAN_ATTRIBUTE_5G_CHANNEL = 182,
+ NAN_ATTRIBUTE_DWELL_TIME = 183,
+ NAN_ATTRIBUTE_SCAN_PERIOD = 184,
+ NAN_ATTRIBUTE_RSSI_WINDOW_SIZE = 185,
+ NAN_ATTRIBUTE_CONF_CLUSTER_VAL = 186,
+ NAN_ATTRIBUTE_AVAIL_BIT_MAP = 187,
+ NAN_ATTRIBUTE_ENTRY_CONTROL = 188,
+ NAN_ATTRIBUTE_CIPHER_SUITE_TYPE = 189,
+ NAN_ATTRIBUTE_KEY_TYPE = 190,
+ NAN_ATTRIBUTE_KEY_LEN = 191,
+ NAN_ATTRIBUTE_SCID = 192,
+ NAN_ATTRIBUTE_SCID_LEN = 193,
+ NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP = 194,
+ NAN_ATTRIBUTE_SDE_CONTROL_SECURITY = 195,
+ NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE = 196,
+ NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT = 197,
+ NAN_ATTRIBUTE_NO_CONFIG_AVAIL = 198,
+ NAN_ATTRIBUTE_2G_AWAKE_DW = 199,
+ NAN_ATTRIBUTE_5G_AWAKE_DW = 200,
+ NAN_ATTRIBUTE_RANGING_INTERVAL = 201,
+ NAN_ATTRIBUTE_RANGING_INDICATION = 202,
+ NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT = 203,
+ NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT = 204,
+ NAN_ATTRIBUTE_RANGING_AUTO_ACCEPT = 205,
+ NAN_ATTRIBUTE_RANGING_RESULT = 206,
+ NAN_ATTRIBUTE_DISC_IND_CFG = 207,
+ NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG = 208,
+ NAN_ATTRIBUTE_KEY_DATA = 209,
+ NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN = 210,
+ NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO = 211,
+ NAN_ATTRIBUTE_REASON = 212,
+ NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG = 213,
+ NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG = 214,
+ NAN_ATTRIBUTE_DWELL_TIME_5G = 215,
+ NAN_ATTRIBUTE_SCAN_PERIOD_5G = 216,
+ NAN_ATTRIBUTE_SVC_RESPONDER_POLICY = 217,
+ NAN_ATTRIBUTE_EVENT_MASK = 218,
+ NAN_ATTRIBUTE_SUB_SID_BEACON = 219,
+ NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL = 220,
+ NAN_ATTRIBUTE_CMD_RESP_DATA = 221,
+ NAN_ATTRIBUTE_CMD_USE_NDPE = 222,
+ NAN_ATTRIBUTE_ENABLE_MERGE = 223,
+ NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL = 224,
+ NAN_ATTRIBUTE_NSS = 225,
+ NAN_ATTRIBUTE_ENABLE_RANGING = 226,
+ NAN_ATTRIBUTE_DW_EARLY_TERM = 227
+} NAN_ATTRIBUTE;
+
+typedef enum {
+ NAN_REQUEST_ENABLE = 0,
+ NAN_REQUEST_DISABLE = 1,
+ NAN_REQUEST_PUBLISH = 2,
+ NAN_REQUEST_PUBLISH_CANCEL = 3,
+ NAN_REQUEST_TRANSMIT_FOLLOWUP = 4,
+ NAN_REQUEST_SUBSCRIBE = 5,
+ NAN_REQUEST_SUBSCRIBE_CANCEL = 6,
+ NAN_REQUEST_STATS = 7,
+ NAN_REQUEST_CONFIG = 8,
+ NAN_REQUEST_TCA = 9,
+ NAN_REQUEST_EVENT_CHECK = 10,
+ NAN_REQUEST_GET_CAPABILTIES = 11,
+ NAN_DATA_PATH_IFACE_CREATE = 12,
+ NAN_DATA_PATH_IFACE_DELETE = 13,
+ NAN_DATA_PATH_INIT_REQUEST = 14,
+ NAN_DATA_PATH_IND_RESPONSE = 15,
+ NAN_DATA_PATH_END = 16,
+ NAN_DATA_PATH_IFACE_UP = 17,
+ NAN_DATA_PATH_SEC_INFO = 18,
+ NAN_VERSION_INFO = 19,
+ NAN_REQUEST_ENABLE_MERGE = 20,
+ NAN_REQUEST_LAST = 0xFFFF
+} NanRequestType;
+
+/*
+ * The enum is based on the BCME Response defs
+ * used in the firmware and defined at
+ * path: src/include/bcmeutils.h
+ */
+enum nan_response_status {
+ BCME_OK = 0,
+ BCME_ERROR = -1,
+ BCME_BADARG = -2,
+ BCME_BADRATESET = -12,
+ BCME_BADBAND = -13,
+ BCME_BUSY = -16,
+ BCME_BADCHAN = -20,
+ BCME_UNSUPPORTED = -23,
+ BCME_BADLEN = -24,
+ BCME_NOTREADY = -25,
+ BCME_NOMEM = -27,
+ BCME_NOTFOUND = -30,
+ BCME_TXFAIL = -38,
+ BCME_RXFAIL = -39,
+ BCME_SCANREJECT = -43,
+ BCME_USAGE_ERROR = -44,
+ BCME_IOCTL_ERROR = -45
+};
+
+enum nan_de_event_type {
+ NAN_EVENT_IFACE = 0,
+ NAN_EVENT_START = 1,
+ NAN_EVENT_JOIN = 2,
+ NAN_EVENT_ROLE_CHANGE = 3,
+ NAN_EVENT_MERGE = 4
+};
+
+typedef struct _nan_hal_resp {
+ u16 instance_id;
+ u16 subcmd;
+ int32_t status;
+ int32_t value;
+ /* Identifier for the instance of the NDP */
+ u16 ndp_instance_id;
+ /* Publisher NMI */
+ u8 pub_nmi[NAN_MAC_ADDR_LEN];
+ /* SVC_HASH */
+ u8 svc_hash[NAN_SVC_HASH_SIZE];
+ char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */
+ char pad[3];
+ NanCapabilities capabilities;
+} nan_hal_resp_t;
+
+typedef int (*match_fn)(void *p1, void *data);
+
+typedef struct _nan_hal_info {
+ void *nan_handle;
+ void *nan_mac_control;
+ void *nan_disc_control;
+ void *nan_dp_control;
+} nan_hal_info_t;
+
+u8 mNmi[NAN_MAC_ADDR_LEN];
+/* Static functions */
+static int is_de_event(int cmd);
+static int is_dp_event(int cmd);
+static int is_cmd_response(int cmd);
+
+static int get_svc_hash(unsigned char *svc_name, u16 svc_name_len,
+ u8 *svc_hash, u16 svc_hash_len);
+NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd);
+static NanStatusType nan_map_term_status(u32 vendor_reason);
+static NanStatusType nan_map_response_status(int vendor_status);
+static int ioctl_sock = 0;
+
+static int setFlags(int s, struct ifreq *ifr, int set, int clr)
+{
+ if(ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ifr->ifr_flags = (ifr->ifr_flags & (~clr)) | set;
+ if (ioctl(s, SIOCSIFFLAGS, ifr) < 0) {
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ return WIFI_SUCCESS;
+}
+
+static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
+{
+ sin->sin_family = AF_INET;
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = inet_addr(addr);
+}
+
+static int setAddr(int s, struct ifreq *ifr, const char *addr)
+{
+ init_sockaddr_in((struct sockaddr_in *) &ifr->ifr_addr, addr);
+
+ if (ioctl(s, SIOCSIFADDR, ifr) < 0) {
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ return WIFI_SUCCESS;
+}
+
+/* Function to separate the common events to NAN1.0 events */
+static int is_de_event(int cmd) {
+ bool is_de_evt = false;
+
+ switch(cmd) {
+ case NAN_EVENT_SUBSCRIBE_UNMATCH:
+ case NAN_EVENT_SUBSCRIBE_TERMINATED:
+ case NAN_EVENT_PUBLISH_TERMINATED:
+ case NAN_EVENT_SUBSCRIBE_MATCH:
+ case NAN_EVENT_FOLLOWUP:
+ case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
+ case NAN_EVENT_PUBLISH_REPLIED_IND:
+ is_de_evt = true;
+ break;
+ default:
+ /* Not used */
+ break;
+ }
+ return is_de_evt;
+}
+
+/* Function to separate NAN2.0 events */
+static int is_dp_event(int cmd) {
+ bool is_dp_evt = false;
+
+ switch(cmd) {
+ case NAN_EVENT_DATA_REQUEST:
+ case NAN_EVENT_DATA_CONFIRMATION:
+ case NAN_EVENT_DATA_END:
+ is_dp_evt = true;
+ break;
+ default:
+ /* Not used */
+ break;
+ }
+ return is_dp_evt;
+}
+
+static int is_cmd_response(int cmd) {
+ bool is_cmd_resp = false;
+
+ switch(cmd) {
+ case NAN_ASYNC_RESPONSE_DISABLED:
+ is_cmd_resp = true;
+ break;
+ default:
+ break;
+ }
+ return is_cmd_resp;
+}
+
+static NanStatusType nan_map_response_status (int vendor_status) {
+ NanStatusType hal_status;
+
+ switch(vendor_status) {
+ case BCME_OK:
+ hal_status = NAN_STATUS_SUCCESS;
+ break;
+ case BCME_BUSY:
+ hal_status = NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ break;
+ case BCME_NOTREADY:
+ hal_status = NAN_STATUS_NAN_NOT_ALLOWED;
+ break;
+ case BCME_BADLEN:
+ case BCME_BADBAND:
+ hal_status = NAN_STATUS_INVALID_PARAM;
+ break;
+ case BCME_NOMEM:
+ hal_status = NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ break;
+ case NAN_STATUS_INTERNAL_FAILURE:
+ case NAN_STATUS_PROTOCOL_FAILURE:
+ case NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
+ case NAN_STATUS_NO_RESOURCE_AVAILABLE:
+ case NAN_STATUS_INVALID_PARAM:
+ case NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
+ case NAN_STATUS_INVALID_NDP_ID:
+ case NAN_STATUS_NAN_NOT_ALLOWED:
+ case NAN_STATUS_NO_OTA_ACK:
+ case NAN_STATUS_ALREADY_ENABLED:
+ case NAN_STATUS_FOLLOWUP_QUEUE_FULL:
+ case NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
+ hal_status = (NanStatusType)vendor_status;
+ break;
+ default:
+ ALOGE("%s Unknown vendor status, status = %d\n",
+ __func__, vendor_status);
+ /* Generic error */
+ hal_status = NAN_STATUS_INTERNAL_FAILURE;
+ }
+ return hal_status;
+}
+
+static void prhex(const char *msg, u8 *buf, u32 nbytes);
+static const char *NanAttrToString(u16 cmd);
+static const char *NanCmdToString(int cmd);
+static const char *NanRspToString(int cmd);
+
+#define NAN_DBG_ENTER() {ALOGI("Enter: %s\n", __func__);}
+#define NAN_DBG_EXIT() {ALOGI("Exit: %s\n", __func__);}
+
+static int passphrase_to_pmk(u8 *peer_mac, u32 cipher_type,
+ u8 *svc_hash, NanSecurityKeyInfo *key_info, u8 *pmk_hex) {
+ int result = NAN_STATUS_SUCCESS;
+ u8 salt[NAN_SECURITY_SALT_SIZE];
+
+ NAN_DBG_ENTER();
+ salt[0] = 0; /* salt_version */
+ salt[1] = cipher_type;
+ if (svc_hash && peer_mac) {
+ memcpy(&salt[2], svc_hash, NAN_SVC_HASH_SIZE);
+ memcpy(&salt[2 + NAN_SVC_HASH_SIZE], peer_mac,
+ ETHER_ADDR_LEN);
+ prhex("Salt", salt, NAN_SECURITY_SALT_SIZE);
+ } else {
+ ALOGE("Mandory parameters are not present\n");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (key_info->body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ key_info->body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ALOGE("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ result = PKCS5_PBKDF2_HMAC((const char *) key_info->body.passphrase_info.passphrase,
+ key_info->body.passphrase_info.passphrase_len, salt, sizeof(salt),
+ 4096, ((cipher_type == NAN_CIPHER_SUITE_SHARED_KEY_128_MASK) ?
+ (const EVP_MD *)EVP_sha256():(const EVP_MD *)EVP_sha384()), NAN_PMK_INFO_LEN, pmk_hex);
+ prhex("PMK_HEX", pmk_hex, 32);
+ NAN_DBG_EXIT();
+ return result;
+}
+
+typedef void *NanRequest;
+nan_hal_info_t info;
+
+#define SVC_LIST(info) ((info).svc_list)
+#define SVC_LIST_SIZE(info) ((info).svc_list.total_items)
+#define DP_SVC_LIST(info) ((info).dp_svc_list)
+#define DP_SVC_LIST_SIZE(info) ((info).dp_svc_list.total_items)
+#define NAN_HANDLE(info) ((info).nan_handle)
+#define GET_NAN_HANDLE(info) ((NanHandle *)info.nan_handle)
+#define NAN_MAC_CONTROL(info) ((info).nan_mac_control)
+
+///////////////////////////////////////////////////////////////////////////////
+class NanHandle
+{
+ public:
+ NanCallbackHandler mHandlers;
+ NanHandle(wifi_handle handle, NanCallbackHandler handlers):mHandlers(handlers)
+ {}
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanDiscEnginePrimitive : public WifiCommand
+{
+ NanRequest mParams;
+ NanRequestType mType;
+ u16 mInstId;
+ u32 mPeerId;
+ u16 mTxId;
+
+ public:
+ NanDiscEnginePrimitive(wifi_interface_handle iface, int id,
+ NanRequest params, NanRequestType cmdType)
+ : WifiCommand("NanCommand", iface, id), mParams(params), mType(cmdType)
+ {
+ mInstId = 0;
+ mPeerId = 0;
+ setTransactionId(id);
+ }
+
+ ~NanDiscEnginePrimitive() {
+ ALOGE("NanDiscEnginePrimitive destroyed\n");
+ }
+
+ void setType(NanRequestType type) {
+ mType = type;
+ }
+
+ void setInstId(u16 inst_id) {
+ mInstId = inst_id;
+ }
+
+ int getInstanceId() {
+ return mInstId;
+ }
+
+ void setTransactionId(u16 tx_id) {
+ mTxId = tx_id;
+ }
+
+ int getTransactionId() {
+ return mTxId;
+ }
+
+ void setParams(NanRequest params) {
+ mParams = params;
+ }
+
+ int createRequest(WifiRequest& request)
+ {
+ ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+ if (mType == NAN_REQUEST_SUBSCRIBE) {
+ return createSubscribeRequest(request,
+ (NanSubscribeRequest *)mParams);
+ } else if (mType == NAN_REQUEST_SUBSCRIBE_CANCEL) {
+ return createSubscribeCancelRequest(request,
+ (NanSubscribeCancelRequest *)mParams);
+ } else if (mType == NAN_REQUEST_PUBLISH) {
+ return createPublishRequest(request,
+ (NanPublishRequest *)mParams);
+ } else if (mType == NAN_REQUEST_PUBLISH_CANCEL) {
+ return createPublishCancelRequest(request,
+ (NanPublishCancelRequest *)mParams);
+ } else if (mType == NAN_REQUEST_TRANSMIT_FOLLOWUP) {
+ return createTransmitFollowupRequest(request,
+ (NanTransmitFollowupRequest *)mParams);
+ } else if (mType == NAN_REQUEST_GET_CAPABILTIES) {
+ return getCapabilitiesRequest(request);
+ } else {
+ ALOGE("%s Unknown Nan request\n", __func__);
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createPublishRequest(WifiRequest& request, NanPublishRequest *mParams)
+ {
+ NAN_DBG_ENTER();
+ u8 pmk_hex[NAN_PMK_INFO_LEN];
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_PUBLISH);
+ if (result < 0) {
+ ALOGE("%s Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ /* If handle is 0xFFFF, then update instance_id in response of this request
+ * otherwise, update not needed
+ */
+ mInstId = mParams->publish_id;
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pub id, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_TTL, mParams->ttl);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ttl, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (ISGREATER(mParams->period, NAN_MAX_PERIOD)) {
+ ALOGE("%s:Invalid period value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_PERIOD, mParams->period);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill period, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_TYPE, mParams->publish_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pub type, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_TX_TYPE, mParams->tx_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill tx type, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_COUNT, mParams->publish_count);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pub cnt, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->service_name_len) {
+ u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+ result = get_svc_hash(mParams->service_name, mParams->service_name_len,
+ svc_hash, NAN_SVC_HASH_SIZE);
+ if (result < 0) {
+ ALOGE("%s: Failed to get hashed svc name\n", __func__);
+ return result;
+ }
+
+ mParams->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(mParams->service_name, svc_hash, mParams->service_name_len);
+
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+ mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->service_specific_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->rx_match_filter_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN,
+ mParams->rx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill rx match filter len, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->rx_match_filter, mParams->rx_match_filter_len);
+ result = request.put(NAN_ATTRIBUTE_RX_MATCH_FILTER,
+ (void *)mParams->rx_match_filter, mParams->rx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill rx match filter, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->tx_match_filter_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN,
+ mParams->tx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill tx match filter, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->tx_match_filter, mParams->tx_match_filter_len);
+ result = request.put(NAN_ATTRIBUTE_TX_MATCH_FILTER,
+ (void *)mParams->tx_match_filter, mParams->tx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill tx match filter, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_MATCH, mParams->publish_match_indicator);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_MATCH, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (ISGREATER(mParams->recv_indication_cfg, NAN_PUB_RECV_FLAG_MAX)) {
+ ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+ mParams->recv_indication_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RECV_IND_CFG, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+ mParams->cipher_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_CIPHER_SUITE_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+ mParams->key_info.key_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_KEY_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (mParams->key_info.body.pmk_info.pmk_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+ (void *)mParams->key_info.body.pmk_info.pmk,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ALOGE("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ return NAN_STATUS_INVALID_PARAM;
+ } else {
+ memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+ result = passphrase_to_pmk(mNmi, mParams->cipher_type,
+ mParams->service_name, &mParams->key_info, pmk_hex);
+ if (result < 0) {
+ ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
+ if (mParams->scid_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+ mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->scid, mParams->scid_len);
+ result = request.put(NAN_ATTRIBUTE_SCID,
+ (void *)mParams->scid, mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP,
+ mParams->sdea_params.config_nan_data_path);
+
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY,
+ mParams->sdea_params.security_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_SECURITY, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE,
+ mParams->sdea_params.ndp_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT,
+ mParams->sdea_params.ranging_state);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG,
+ mParams->rssi_threshold_flag);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->sdea_service_specific_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SVC_RESPONDER_POLICY,
+ mParams->service_responder_policy);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SVC_RESPONDER_POLICY, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ request.attr_end(data);
+
+ ALOGI("Returning successfully\n");
+ NAN_DBG_EXIT();
+ return result;
+ }
+
+ int createPublishCancelRequest(WifiRequest& request, NanPublishCancelRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_PUBLISH_CANCEL);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (ISGREATER(mInstId, NAN_MAX)) {
+ ALOGE("%s:Invalid publish count value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ ALOGI("%s: pub id = %d, inst_id = %d\n", __func__, mParams->publish_id, mInstId);
+
+ result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_ID, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int createSubscribeRequest(WifiRequest& request, NanSubscribeRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_SUBSCRIBE);
+ if (result < 0) {
+ ALOGE("%s Failed to create request\n", __func__);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+
+ /* If handle is 0xFFFF, then update instance_id in response of this request
+ * otherwise, update not needed
+ */
+ mInstId = mParams->subscribe_id;
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u16(NAN_ATTRIBUTE_SUBSCRIBE_ID, mInstId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub id, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_TTL, mParams->ttl);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ttl, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (ISGREATER(mParams->period, NAN_MAX_PERIOD)) {
+ ALOGE("%s:Invalid period value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_PERIOD, mParams->period);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill period, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_TYPE, mParams->subscribe_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub type, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SERVICERESPONSEFILTER,
+ mParams->serviceResponseFilter);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc resp filter, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE,
+ mParams->serviceResponseInclude);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc resp include, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER,
+ mParams->useServiceResponseFilter);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill use svc resp filter, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION,
+ mParams->ssiRequiredForMatchIndication);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ssi req match ind, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_MATCH,
+ mParams->subscribe_match_indicator);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub match, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_COUNT, mParams->subscribe_count);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub cnt, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->service_name_len) {
+ u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+ result = get_svc_hash(mParams->service_name, mParams->service_name_len,
+ svc_hash, NAN_SVC_HASH_SIZE);
+ if (result < 0) {
+ ALOGE("%s: Failed to get hashed svc name\n", __func__);
+ return result;
+ }
+
+ mParams->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(mParams->service_name, svc_hash, mParams->service_name_len);
+
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc hash len, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+ mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill hashed svc name, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->service_specific_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->rx_match_filter_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN,
+ mParams->rx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill rx match filter len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->rx_match_filter, mParams->rx_match_filter_len);
+ result = request.put(NAN_ATTRIBUTE_RX_MATCH_FILTER,
+ (void *)mParams->rx_match_filter, mParams->rx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill rx match filter, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->tx_match_filter_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN,
+ mParams->tx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill tx match filter len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->tx_match_filter, mParams->tx_match_filter_len);
+ result = request.put(NAN_ATTRIBUTE_TX_MATCH_FILTER,
+ (void *)mParams->tx_match_filter, mParams->tx_match_filter_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill tx match filter, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+ ALOGE("%s: Number of mac addrs: %d have crossed the threshold, fail to subscribe\n",
+ __func__, mParams->num_intf_addr_present);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ } else if (mParams->num_intf_addr_present) {
+ result = request.put_u16(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES,
+ mParams->num_intf_addr_present);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill mac addr list no, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ prhex(NULL, (u8 *)mParams->intf_addr,
+ (mParams->num_intf_addr_present * NAN_MAC_ADDR_LEN));
+ result = request.put(NAN_ATTRIBUTE_MAC_ADDR_LIST, (void *)mParams->intf_addr,
+ (mParams->num_intf_addr_present * NAN_MAC_ADDR_LEN));
+ if (result < 0) {
+ ALOGE("%s: Failed to fill mac addr list, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (ISGREATER(mParams->recv_indication_cfg, NAN_SUB_RECV_FLAG_MAX)) {
+ ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+ mParams->recv_indication_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill recv_indication_cfg, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->scid_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+ mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->scid, mParams->scid_len);
+ result = request.put(NAN_ATTRIBUTE_SCID,
+ (void *)mParams->scid, mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP,
+ mParams->sdea_params.config_nan_data_path);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_nan_data_path, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY,
+ mParams->sdea_params.security_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill security_cfg, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE,
+ mParams->sdea_params.ndp_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp_type, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT,
+ mParams->sdea_params.ranging_state);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ranging state, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->sdea_params.ranging_state == NAN_RANGING_ENABLE) {
+ result = request.put_u32(NAN_ATTRIBUTE_RANGING_INTERVAL,
+ mParams->ranging_cfg.ranging_interval_msec);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ranging_interval_msec, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT,
+ mParams->ranging_cfg.distance_egress_mm);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill distance_egress_mm, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_RANGING_INDICATION,
+ mParams->ranging_cfg.config_ranging_indications);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_ranging_indications, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT,
+ mParams->ranging_cfg.distance_ingress_mm);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill distance_ingress_mm, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ ALOGI("%s:RSSI threshold flag %d", __func__, mParams->rssi_threshold_flag);
+ result = request.put_u8(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG,
+ mParams->rssi_threshold_flag);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill rssi_threshold_flag, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->sdea_service_specific_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int createSubscribeCancelRequest(WifiRequest& request,
+ NanSubscribeCancelRequest *mParams) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_SUBSCRIBE_CANCEL);
+ if (result < 0) {
+ ALOGE("%s Failed to create request \n", __func__);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (ISGREATER(mInstId, NAN_MAX)) {
+ ALOGE("%s:Invalid subscribe id value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ ALOGI("%s: sub id = %u\n", __func__, mInstId);
+
+ result = request.put_u16(NAN_ATTRIBUTE_SUBSCRIBE_ID, mInstId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub id, result = %d\n", __func__, result);
+ return result;
+ }
+
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int createTransmitFollowupRequest(WifiRequest& request,
+ NanTransmitFollowupRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_TRANSMIT_FOLLOWUP);
+ if (result < 0) {
+ ALOGE("%s Failed to create request \n", __func__);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+
+ /* If handle is 0xFFFF, then update instance_id in response of this request
+ * otherwise, update not needed
+ */
+ mInstId = mParams->publish_subscribe_id;
+ mPeerId = mParams->requestor_instance_id;
+ mTxId = getTransactionId();
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(NAN_ATTRIBUTE_PEER_ID, mPeerId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill peer id, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mInstId);
+ if (result < 0) {
+ ALOGE("%s Failed to fill inst id = %d \n", __func__, mInstId);
+ return result;
+ }
+
+ result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->addr);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill mac addr\n", __func__);
+ return result;
+ }
+
+ if (mParams->service_specific_info_len > 0) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info len \n", __func__);
+ return result;
+ }
+
+ prhex(NULL, mParams->service_specific_info, mParams->service_specific_info_len);
+ result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to put svc info, result = %d", __func__, result);
+ return result;
+ }
+ mParams->service_specific_info[mParams->service_specific_info_len] = '\0';
+ ALOGI("Transmit service info string is %s\n", mParams->service_specific_info);
+ }
+
+ if (ISGREATER(mParams->recv_indication_cfg, NAN_PUB_RECV_FLAG_MAX)) {
+ ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+ mParams->recv_indication_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RECV_IND_CFG, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_TRANSAC_ID, mTxId);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_TRANSAC_ID, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->sdea_service_specific_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int getCapabilitiesRequest(WifiRequest& request) {
+ int result = 0;
+ NAN_DBG_ENTER();
+
+ result = request.create(GOOGLE_OUI, NAN_SUBCMD_GET_CAPABILITIES);
+ if (result < 0) {
+ ALOGE("%s Failed to create request \n", __func__);
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ request.attr_end(data);
+
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int start()
+ {
+ int result = 0;
+ WifiRequest request(familyId(), ifaceId());
+ result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create setup request; result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to configure setup; result = %d\n", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ return WIFI_SUCCESS;
+ }
+
+ virtual bool valid_disc_response_type(int response_type) {
+ bool valid = false;
+ switch(response_type) {
+ case NAN_RESPONSE_PUBLISH:
+ case NAN_RESPONSE_SUBSCRIBE:
+ case NAN_GET_CAPABILITIES:
+ case NAN_RESPONSE_PUBLISH_CANCEL:
+ case NAN_RESPONSE_SUBSCRIBE_CANCEL:
+ case NAN_RESPONSE_TRANSMIT_FOLLOWUP:
+ valid = true;
+ break;
+ default:
+ ALOGE("NanDiscEnginePrmitive:Unknown cmd Response: %d\n", response_type);
+ break;
+ }
+ return valid;
+ }
+
+ int handleResponse(WifiEvent& reply)
+ {
+ nan_hal_resp_t *rsp_vndr_data = NULL;
+ NanResponseMsg rsp_data;
+ if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+ rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+ ALOGI("NanDiscEnginePrmitive::handle response\n");
+ memset(&rsp_data, 0, sizeof(NanResponseMsg));
+ rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+ if (!valid_disc_response_type(rsp_data.response_type))
+ return NL_SKIP;
+
+ rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+ ALOGE("Mapped hal status = %d\n", rsp_data.status);
+ if (rsp_vndr_data->nan_reason[0] == '\0') {
+ memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+ strlen(NanStatusToString(rsp_data.status)));
+ rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+ }
+ rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+ ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+
+ if (mInstId == 0 &&
+ (rsp_data.response_type == NAN_RESPONSE_PUBLISH ||
+ rsp_data.response_type == NAN_RESPONSE_SUBSCRIBE)) {
+ ALOGI("Received service instance_id %d\n", rsp_vndr_data->instance_id);
+ mInstId = rsp_vndr_data->instance_id;
+ }
+
+ if (rsp_data.response_type == NAN_RESPONSE_PUBLISH) {
+ rsp_data.body.publish_response.publish_id = mInstId;
+ } else if (rsp_data.response_type == NAN_RESPONSE_SUBSCRIBE) {
+ rsp_data.body.subscribe_response.subscribe_id = mInstId;
+ } else if (rsp_data.response_type == NAN_GET_CAPABILITIES) {
+ memcpy((void *)&rsp_data.body.nan_capabilities, (void *)&rsp_vndr_data->capabilities,
+ sizeof(rsp_data.body.nan_capabilities));
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+ ALOGI("NanDiscEnginePrmitive:Received response for cmd [%s], ret %d\n",
+ NanRspToString(rsp_data.response_type), rsp_data.status);
+
+ return NL_SKIP;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ int cmd = event.get_vendor_subcmd();
+ u16 attr_type;
+ int result;
+
+ ALOGI("Received NanDiscEnginePrimitive event: %d\n", event.get_cmd());
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+ switch(cmd) {
+ case NAN_EVENT_PUBLISH_TERMINATED:
+ NanPublishTerminatedInd pub_term_event;
+
+ memset(&pub_term_event, 0, sizeof(NanPublishTerminatedInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ pub_term_event.publish_id = it.get_u16();
+ ALOGI("pub id = %u", pub_term_event.publish_id);
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ pub_term_event.reason = (NanStatusType)it.get_u8();
+ ALOGI("pub termination status %u", pub_term_event.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(pub_term_event.nan_reason, it.get_data(),
+ sizeof(pub_term_event.nan_reason));
+ ALOGI("pub termination reason: %s", pub_term_event.nan_reason);
+ } else {
+ ALOGE("Unknown attr: %u\n", attr_type);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventPublishTerminated(&pub_term_event);
+ break;
+
+ case NAN_EVENT_SUBSCRIBE_MATCH:
+ NanMatchInd subscribe_event;
+
+ memset(&subscribe_event, 0, sizeof(NanMatchInd));
+
+ /* By default FW is unable to cache this match */
+ subscribe_event.out_of_resource_flag = true;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ ALOGI("sub id: %u", it.get_u16());
+ subscribe_event.publish_subscribe_id = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ ALOGI("pub id: %u", it.get_u16());
+ subscribe_event.requestor_instance_id = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Publisher mac: " MACSTR, MAC2STR(subscribe_event.addr));
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("svc length %d", it.get_u16());
+ subscribe_event.service_specific_info_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(subscribe_event.service_specific_info, it.get_data(),
+ subscribe_event.service_specific_info_len);
+ subscribe_event.service_specific_info
+ [subscribe_event.service_specific_info_len] = '\0';
+ ALOGI("service info: %s", subscribe_event.service_specific_info);
+ } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
+ ALOGI("sdf match filter length: %d", subscribe_event.sdf_match_filter_len);
+ subscribe_event.sdf_match_filter_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER) {
+ memcpy(subscribe_event.sdf_match_filter, it.get_data(),
+ subscribe_event.sdf_match_filter_len);
+ subscribe_event.sdf_match_filter
+ [subscribe_event.sdf_match_filter_len] = '\0';
+ ALOGI("sdf match filter: %s", subscribe_event.sdf_match_filter);
+ } else if (attr_type == NAN_ATTRIBUTE_CIPHER_SUITE_TYPE) {
+ ALOGI("Peer Cipher suite type: %u", it.get_u8());
+ subscribe_event.peer_cipher_type = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
+ ALOGI("scid length %d", it.get_u32());
+ subscribe_event.scid_len= it.get_u32();
+ } else if (attr_type == NAN_ATTRIBUTE_SCID) {
+ memcpy(subscribe_event.scid, it.get_data(),
+ subscribe_event.scid_len);
+ subscribe_event.scid
+ [subscribe_event.scid_len] = '\0';
+ ALOGI("scid: %s", subscribe_event.scid);
+ } else if (attr_type == NAN_ATTRIBUTE_RANGING_INDICATION) {
+ subscribe_event.range_info.ranging_event_type = it.get_u32();
+ ALOGI("ranging indication %d", it.get_u32());
+ } else if (attr_type == NAN_ATTRIBUTE_RANGING_RESULT) {
+ subscribe_event.range_info.range_measurement_mm = it.get_u32();
+ ALOGI("ranging result %d", it.get_u32());
+ } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+ subscribe_event.rssi_value = it.get_u8();
+ ALOGI("rssi value : %u", it.get_u8());
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("sdea svc length %d", it.get_u16());
+ subscribe_event.sdea_service_specific_info_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+ memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
+ subscribe_event.sdea_service_specific_info_len);
+ subscribe_event.sdea_service_specific_info
+ [subscribe_event.sdea_service_specific_info_len] = '\0';
+ ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
+ } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
+ ALOGI("match occurred flag: %u", it.get_u8());
+ subscribe_event.match_occured_flag = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG) {
+ ALOGI("Out of resource flag: %u", it.get_u8());
+ subscribe_event.out_of_resource_flag = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP) {
+ ALOGI("Peer config for data path needed: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.config_nan_data_path = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE) {
+ ALOGI("Data Path type: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.ndp_type = (NdpType)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_SECURITY) {
+ ALOGI("Security configuration: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.security_cfg =
+ (NanDataPathSecurityCfgStatus)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT) {
+ ALOGI("Ranging report state: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.range_report = (NanRangeReport)it.get_u8();
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventMatch(&subscribe_event);
+ break;
+
+ case NAN_EVENT_SUBSCRIBE_UNMATCH:
+ ALOGE("%s: Not applicable yet\n", __func__);
+ break;
+
+ case NAN_EVENT_SUBSCRIBE_TERMINATED:
+ NanSubscribeTerminatedInd sub_term_event;
+ memset(&sub_term_event, 0, sizeof(NanSubscribeTerminatedInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ sub_term_event.subscribe_id = it.get_u16();
+ ALOGI("sub id = %u", sub_term_event.subscribe_id);
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ sub_term_event.reason = (NanStatusType)it.get_u16();
+ ALOGI("sub termination status %u", sub_term_event.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(sub_term_event.nan_reason, it.get_data(),
+ sizeof(sub_term_event.nan_reason));
+ ALOGI("sub termination reason: %s", sub_term_event.nan_reason);
+ } else {
+ ALOGI("Unknown attr: %d\n", attr_type);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
+ break;
+
+ case NAN_EVENT_FOLLOWUP:
+ NanFollowupInd followup_event;
+ memset(&followup_event, 0, sizeof(NanFollowupInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(followup_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ } else if (attr_type == NAN_ATTRIBUTE_PEER_ID) {
+ followup_event.publish_subscribe_id = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_INST_ID) {
+ followup_event.requestor_instance_id = it.get_u32();
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ followup_event.service_specific_info_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(followup_event.service_specific_info, it.get_data(),
+ followup_event.service_specific_info_len);
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+ memcpy(followup_event.sdea_service_specific_info, it.get_data(),
+ followup_event.sdea_service_specific_info_len);
+ }
+ }
+ counters.transmit_recv++;
+ GET_NAN_HANDLE(info)->mHandlers.EventFollowup(&followup_event);
+ break;
+
+ case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
+ NanTransmitFollowupInd followup_ind;
+ counters.transmit_txs++;
+ memset(&followup_ind, 0, sizeof(NanTransmitFollowupInd));
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_TRANSAC_ID) {
+ followup_ind.id = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ followup_ind.reason = (NanStatusType)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(followup_ind.nan_reason, it.get_data(),
+ sizeof(followup_ind.nan_reason));
+ ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
+ break;
+#ifdef NOT_YET
+ case NAN_EVENT_PUBLISH_REPLIED_IND:
+ NanPublishRepliedInd pub_reply_event;
+ memset(&pub_reply_event, 0, sizeof(pub_reply_event));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ ALOGI("sub id: %u", it.get_u16());
+ pub_reply_event.requestor_instance_id = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(pub_reply_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Subscriber mac: " MACSTR, MAC2STR(pub_reply_event.addr));
+ } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+ pub_reply_event.rssi_value = it.get_u8();
+ ALOGI("Received rssi value : %u", it.get_u8());
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventPublishReplied(&pub_reply_event);
+ break;
+#endif /* NOT_YET */
+ } // end-of-switch-case
+ return NL_SKIP;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanDataPathPrimitive : public WifiCommand
+{
+ NanRequest reqContext;
+ u32 mNdpId;
+ NanRequestType mType;
+ u8 count;
+
+ public:
+ NanDataPathPrimitive(wifi_interface_handle iface, int id,
+ NanRequest params, NanRequestType cmdType)
+ : WifiCommand("NanCommand", iface, id), reqContext(params), mType(cmdType)
+ {
+ mNdpId = 0;
+ count = 0;
+ }
+ ~NanDataPathPrimitive() {
+ ALOGE("NanDataPathPrimitive destroyed\n");
+ }
+ u8 mSvcHash[NAN_SVC_HASH_SIZE];
+ u8 mPubNmi[NAN_MAC_ADDR_LEN];
+
+ void setType(NanRequestType type ) {
+ mType = type;
+ }
+
+ int getNdpId() {
+ return mNdpId;
+ }
+
+ int createRequest(WifiRequest& request)
+ {
+ ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+ if (mType == NAN_DATA_PATH_IFACE_CREATE) {
+ return createDataPathIfaceRequest(request, (char *)reqContext);
+ } else if (mType == NAN_DATA_PATH_IFACE_DELETE) {
+ return deleteDataPathIfaceRequest(request, (char *)reqContext);
+ } else if (mType == NAN_DATA_PATH_INIT_REQUEST) {
+ return createDataPathInitRequest(request,
+ (NanDataPathInitiatorRequest *)reqContext);
+ } else if (mType == NAN_DATA_PATH_IND_RESPONSE) {
+ return createDataPathIndResponse(request,
+ (NanDataPathIndicationResponse *)reqContext);
+ } else if (mType == NAN_DATA_PATH_END) {
+ return createDataPathEndRequest(request,
+ (NanDataPathEndRequest *)reqContext);
+ } else if (mType == NAN_DATA_PATH_SEC_INFO) {
+ return createDataPathSecInfoRequest(request,
+ (NanDataPathSecInfoRequest *)reqContext);
+ } else {
+ ALOGE("%s: Unknown NDP request: %d\n", __func__, mType);
+ }
+
+ return WIFI_SUCCESS;
+ }
+
+ int createDataPathIfaceRequest(WifiRequest& request, char *iface_name)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_IFACE_CREATE);
+ if (result < 0) {
+ ALOGE("%s Failed to create request\n", __func__);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_string(NAN_ATTRIBUTE_IFACE, (char *)iface_name);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill iface, result = %d\n", __func__, result);
+ return result;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int deleteDataPathIfaceRequest(WifiRequest& request, char *iface_name)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_IFACE_DELETE);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_string(NAN_ATTRIBUTE_IFACE, (char *)iface_name);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill iface, result = %d\n", __func__, result);
+ return result;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createDataPathSecInfoRequest(WifiRequest& request, NanDataPathSecInfoRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_SEC_INFO);
+ if (result < 0) {
+ ALOGE("%s Failed to create request\n", __func__);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill instance id = %d, result = %d\n",
+ __func__, mParams->requestor_instance_id, result);
+ return result;
+ }
+
+ result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->peer_disc_mac_addr);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill mac addr, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp_instance_id = %d, result = %d\n",
+ __func__, mParams->ndp_instance_id, result);
+ return result;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createDataPathInitRequest(WifiRequest& request, NanDataPathInitiatorRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_REQUEST);
+ u8 pmk_hex[NAN_PMK_INFO_LEN];
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ mNdpId = mParams->requestor_instance_id;
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pub id = %d, result = %d\n",
+ __func__, mParams->requestor_instance_id, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_CHANNEL, (u32)mParams->channel);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill channel = %d, result = %d\n",
+ __func__, mParams->channel, result);
+ return result;
+ }
+
+ result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->peer_disc_mac_addr);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill mac addr, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_string(NAN_ATTRIBUTE_IFACE, mParams->ndp_iface);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp_iface, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SECURITY,
+ (NanDataPathSecurityCfgStatus)mParams->ndp_cfg.security_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill security, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_QOS,
+ (NanDataPathQosCfg) mParams->ndp_cfg.qos_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill QoS, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->app_info.ndp_app_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->app_info.ndp_app_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info len = %d, result = %d\n",
+ __func__, mParams->app_info.ndp_app_info_len, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->app_info.ndp_app_info, mParams->app_info.ndp_app_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+ mParams->cipher_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_CIPHER_SUITE_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+ mParams->key_info.key_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_KEY_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+
+ if (mParams->service_name_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->service_name, mParams->service_name_len);
+ result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+ mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (mParams->key_info.body.pmk_info.pmk_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+ (void *)mParams->key_info.body.pmk_info.pmk,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ALOGE("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ return NAN_STATUS_INVALID_PARAM;
+ } else {
+ memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+ result = passphrase_to_pmk(mParams->peer_disc_mac_addr, mParams->cipher_type,
+ mParams->service_name, &mParams->key_info, pmk_hex);
+ if (result < 0) {
+ ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+ return result;
+ }
+ prhex("PMK", pmk_hex, NAN_PMK_INFO_LEN);
+ }
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createDataPathIndResponse(WifiRequest& request,
+ NanDataPathIndicationResponse *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_RESPONSE);
+ u8 pmk_hex[NAN_PMK_INFO_LEN];
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp_instance_id = %d, result = %d\n",
+ __func__, mParams->ndp_instance_id, result);
+ return result;
+ }
+
+ result = request.put_string(NAN_ATTRIBUTE_IFACE, mParams->ndp_iface);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp_iface, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_SECURITY,
+ (NanDataPathSecurityCfgStatus)mParams->ndp_cfg.security_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill security_cfg, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_QOS,
+ (NanDataPathQosCfg)mParams->ndp_cfg.qos_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill qos_cfg, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->app_info.ndp_app_info_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+ mParams->app_info.ndp_app_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info len = %d, result = %d\n",
+ __func__, mParams->app_info.ndp_app_info_len, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+ (void *)mParams->app_info.ndp_app_info, mParams->app_info.ndp_app_info_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_RSP_CODE, mParams->rsp_code);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill resp code = %d, result = %d\n",
+ __func__, mParams->rsp_code, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+ mParams->cipher_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill cipher_type, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+ mParams->key_info.key_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill key type, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->service_name_len) {
+ result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->service_name, mParams->service_name_len);
+ result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+ mParams->service_name_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (mParams->key_info.body.pmk_info.pmk_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+ (void *)mParams->key_info.body.pmk_info.pmk,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ ALOGE("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ return NAN_STATUS_INVALID_PARAM;
+ } else {
+ memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+ result = passphrase_to_pmk(mPubNmi, mParams->cipher_type,
+ mParams->service_name, &mParams->key_info, pmk_hex);
+ if (result < 0) {
+ ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createDataPathEndRequest(WifiRequest& request, NanDataPathEndRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_END);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ count = mParams->num_ndp_instances;
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u8(NAN_ATTRIBUTE_INST_COUNT, mParams->num_ndp_instances);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill num_ndp_instances = %d, result = %d\n",
+ __func__, mParams->num_ndp_instances, result);
+ return result;
+ }
+
+ while (count) {
+ result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id[count-1]);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill ndp id = %d, result = %d\n",
+ __func__, mParams->ndp_instance_id[count-1], result);
+ return result;
+ }
+ ALOGE("%s:NDP ID = %d\n", __func__, mParams->ndp_instance_id[count-1]);
+ count -= 1;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int open()
+ {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to create setup request; result = %d", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to configure setup; result = %d", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ return WIFI_SUCCESS;
+ }
+
+ virtual bool valid_dp_response_type(int response_type) {
+ bool valid = false;
+ switch(response_type) {
+ case NAN_DP_INTERFACE_CREATE:
+ case NAN_DP_INTERFACE_DELETE:
+ case NAN_DP_INITIATOR_RESPONSE:
+ case NAN_DP_RESPONDER_RESPONSE:
+ case NAN_DP_END:
+ valid = true;
+ break;
+ default:
+ ALOGE("NanDataPathPrmitive::Unknown cmd Response: %d\n", response_type);
+ break;
+ }
+ return valid;
+ }
+
+ int handleResponse(WifiEvent& reply)
+ {
+ nan_hal_resp_t *rsp_vndr_data = NULL;
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+ ALOGI("NanDataPathPrmitive::handle response\n");
+ int32_t result = rsp_vndr_data->value;
+ NanResponseMsg rsp_data;
+
+ memset(&rsp_data, 0, sizeof(NanResponseMsg));
+ rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+
+ if ((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd == NAN_SUBCMD_DATA_PATH_SEC_INFO) {
+ /* Follow through */
+ } else if (!valid_dp_response_type(rsp_data.response_type)) {
+ return NL_SKIP;
+ }
+ rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+ ALOGE("Mapped hal status = %d\n", rsp_data.status);
+
+ if (rsp_vndr_data->nan_reason[0] == '\0') {
+ memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+ strlen(NanStatusToString(rsp_data.status)));
+ rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+ }
+ rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+ ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+
+ if (rsp_data.response_type == NAN_DP_INITIATOR_RESPONSE) {
+ ALOGI("received ndp instance_id %d and ret = %d\n", rsp_vndr_data->ndp_instance_id, result);
+ rsp_data.body.data_request_response.ndp_instance_id = rsp_vndr_data->ndp_instance_id;
+ mNdpId = rsp_vndr_data->ndp_instance_id;
+ } else if ((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd == NAN_SUBCMD_DATA_PATH_SEC_INFO) {
+ memcpy(mPubNmi, rsp_vndr_data->pub_nmi, NAN_MAC_ADDR_LEN);
+ memcpy(mSvcHash, rsp_vndr_data->svc_hash, NAN_SVC_HASH_SIZE);
+ return NL_SKIP;
+ }
+
+ ALOGI("NanDataPathPrmitive:Received response for cmd [%s], ret %d\n",
+ NanRspToString(rsp_data.response_type), rsp_data.status);
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+ return NL_SKIP;
+ }
+
+ int handleEvent(WifiEvent& event)
+ {
+ int cmd = event.get_vendor_subcmd();
+ u16 attr_type;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+ switch(cmd) {
+ case NAN_EVENT_DATA_REQUEST: {
+ NanDataPathRequestInd ndp_request_event;
+ memset(&ndp_request_event, 0, sizeof(NanDataPathRequestInd));
+ u16 ndp_ind_app_info_len = 0;
+ counters.dp_req_evt++;
+ ALOGI("Received NAN_EVENT_DATA_REQUEST_INDICATION\n");
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ ALOGI("publish_id: %u", it.get_u16());
+ ndp_request_event.service_instance_id = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(ndp_request_event.peer_disc_mac_addr,
+ it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Discovery MAC addr of the peer/initiator: " MACSTR "\n",
+ MAC2STR(ndp_request_event.peer_disc_mac_addr));
+
+ } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ ALOGI("ndp id: %u", it.get_u32());
+ ndp_request_event.ndp_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SECURITY) {
+ ALOGI("security: %u",
+ (NanDataPathSecurityCfgStatus)it.get_u8());
+ ndp_request_event.ndp_cfg.security_cfg =
+ (NanDataPathSecurityCfgStatus)it.get_u8();
+
+ } else if (attr_type == NAN_ATTRIBUTE_QOS) {
+ ALOGI("QoS: %u", (NanDataPathQosCfg)it.get_u8());
+ ndp_request_event.ndp_cfg.qos_cfg = (NanDataPathQosCfg)it.get_u8();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ndp_request_event.app_info.ndp_app_info_len = it.get_u16();
+ ndp_ind_app_info_len = ndp_request_event.app_info.ndp_app_info_len;
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(ndp_request_event.app_info.ndp_app_info, it.get_data(),
+ ndp_ind_app_info_len);
+ ndp_request_event.app_info.ndp_app_info
+ [ndp_ind_app_info_len] = '\0';
+ ALOGI("service info: %s", ndp_request_event.app_info.ndp_app_info);
+
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataRequest(&ndp_request_event);
+ break;
+ }
+ case NAN_EVENT_DATA_CONFIRMATION: {
+ NanDataPathConfirmInd ndp_create_confirmation_event;
+ memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
+ u16 ndp_conf_app_info_len = 0;
+ counters.dp_confirm_evt++;
+ ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ ALOGI("ndp id: %u", it.get_u32());
+ ndp_create_confirmation_event.ndp_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR) {
+ memcpy(ndp_create_confirmation_event.peer_ndi_mac_addr, it.get_data(),
+ NAN_MAC_ADDR_LEN);
+ ALOGI("NDI mac address of the peer: " MACSTR "\n",
+ MAC2STR(ndp_create_confirmation_event.peer_ndi_mac_addr));
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("service info len: %d", it.get_u16());
+ ndp_create_confirmation_event.app_info.ndp_app_info_len = it.get_u16();
+ ndp_conf_app_info_len = ndp_create_confirmation_event.app_info.ndp_app_info_len;
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(ndp_create_confirmation_event.app_info.ndp_app_info,
+ it.get_data(), ndp_conf_app_info_len);
+ ndp_create_confirmation_event.app_info.ndp_app_info[ndp_conf_app_info_len]
+ = '\0';
+ ALOGI("service info: %s",
+ ndp_create_confirmation_event.app_info.ndp_app_info);
+
+ } else if (attr_type == NAN_ATTRIBUTE_RSP_CODE) {
+ ALOGI("response code: %u", (NanDataPathResponseCode)it.get_u8());
+ ndp_create_confirmation_event.rsp_code =
+ (NanDataPathResponseCode)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ ALOGI("reason code %u", (NanDataPathResponseCode)it.get_u8());
+ ndp_create_confirmation_event.rsp_code =
+ (NanDataPathResponseCode)it.get_u8();
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
+ break;
+ }
+ case NAN_EVENT_DATA_END: {
+ NanDataPathEndInd ndp_end_event;
+ memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+ u16 attr_type;
+ ALOGI("Received NAN_EVENT_DATA_END\n");
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
+ ALOGI("ndp count: %u\n", it.get_u8());
+ ndp_end_event.num_ndp_instances = it.get_u8();
+ count = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ while (count) {
+ ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
+ ALOGI("NDP Id from the Event = %u\n", ndp_end_event.ndp_instance_id[count-1]);
+ count -= 1;
+ }
+ } else {
+ ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+ break;
+ }
+ } // end-of-switch
+ return NL_SKIP;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanMacControl : public WifiCommand
+{
+ NanRequest mParams;
+ transaction_id mId = NAN_MAC_INVALID_TRANSID;
+ wifi_interface_handle mIface;
+ NanRequestType mType;
+ u32 mVersion;
+
+ public:
+ NanMacControl(wifi_interface_handle iface, int id,
+ NanRequest params, NanRequestType cmdType)
+ : WifiCommand("NanCommand", iface, id), mParams(params), mType(cmdType)
+ {
+ mVersion = 0;
+ setIface(iface);
+ setId(id);
+ }
+ ~NanMacControl() {
+ ALOGE("NanMacControl destroyed\n");
+ }
+
+ void setIface(wifi_interface_handle iface ) {
+ mIface = iface;
+ }
+
+ void setId(transaction_id id) {
+ if (id != NAN_MAC_INVALID_TRANSID) {
+ mId = id;
+ }
+ }
+
+ transaction_id getId() {
+ return mId;
+ }
+
+ void setType(NanRequestType type) {
+ mType = type;
+ }
+ u32 getVersion() {
+ return mVersion;
+ }
+
+ void setMsg(NanRequest params) {
+ mParams = params;
+ }
+
+ int createRequest(WifiRequest& request) {
+ ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+ if (mType == NAN_REQUEST_ENABLE) {
+ return createEnableRequest(request, (NanEnableRequest *)mParams);
+ } else if (mType == NAN_REQUEST_DISABLE) {
+ return createDisableRequest(request);
+ } else if (mType == NAN_REQUEST_CONFIG) {
+ return createConfigRequest(request, (NanConfigRequest*)mParams);
+ } else if (mType == NAN_REQUEST_STATS) {
+ /* TODO: Not yet implemented */
+ } else if (mType == NAN_REQUEST_TCA) {
+ /* TODO: Not yet implemented */
+ } else if (mType == NAN_VERSION_INFO) {
+ return createVersionRequest(request);
+#ifdef NAN_CLUSTER_MERGE
+ } else if (mType == NAN_REQUEST_ENABLE_MERGE) {
+ return createEnableMergeRequest(request, (NanEnableMergeRequest *)mParams);
+#endif /* NAN_CLUSTER_MERGE */
+ } else {
+ ALOGE("Unknown Nan request\n");
+ }
+
+ return WIFI_SUCCESS;
+ }
+
+ int createVersionRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_VERSION_INFO);
+ if (result < 0) {
+ ALOGE("%s: Fail to create request\n", __func__);
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int createEnableRequest(WifiRequest& request, NanEnableRequest *mParams) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE);
+ s8 rssi;
+ if (result < 0) {
+ ALOGE("%s: Fail to create request\n", __func__);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (mParams->config_2dot4g_support) {
+ result = request.put_u8(NAN_ATTRIBUTE_2G_SUPPORT, mParams->support_2dot4g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2g support, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_support_5g) {
+ result = request.put_u8(NAN_ATTRIBUTE_5G_SUPPORT, mParams->support_5g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g support, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_CLUSTER_LOW, mParams->cluster_low);
+ if (result < 0) {
+ ALOGE("%s: Failing in cluster low, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_CLUSTER_HIGH, mParams->cluster_high);
+ if (result < 0) {
+ ALOGE("%s: Failing in cluster high, result = %d\n", __func__, result);
+ return result;
+ }
+
+ if (mParams->config_sid_beacon) {
+ result = request.put_u8(NAN_ATTRIBUTE_SID_BEACON, mParams->sid_beacon_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in sid beacon, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_subscribe_sid_beacon) {
+ result = request.put_u8(NAN_ATTRIBUTE_SUB_SID_BEACON, mParams->subscribe_sid_beacon_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in sub sid beacon, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_2dot4g_beacons) {
+ result = request.put_u8(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON, mParams->beacon_2dot4g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in beacon_2dot4g_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_beacons) {
+ result = request.put_u8(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON, mParams->beacon_5g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g beacon, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_2dot4g_sdf) {
+ result = request.put_u8(NAN_ATTRIBUTE_SDF_2G_SUPPORT, mParams->sdf_2dot4g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2dot4g sdf, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_sdf) {
+ result = request.put_u8(NAN_ATTRIBUTE_SDF_5G_SUPPORT, mParams->sdf_5g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g sdf, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_2dot4g_rssi_close) {
+ if (ISGREATER(mParams->rssi_close_2dot4g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_close_2dot4g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_CLOSE, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2g rssi close, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_2dot4g_rssi_middle) {
+ if (ISGREATER(mParams->rssi_middle_2dot4g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_middle_2dot4g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_MIDDLE, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2g rssi middle, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_2dot4g_rssi_proximity) {
+ if (ISGREATER(mParams->rssi_proximity_2dot4g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_proximity_2dot4g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2g rssi proximity, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_rssi_close) {
+ if (ISGREATER(mParams->rssi_close_5g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_close_5g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_CLOSE_5G, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g rssi close, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_rssi_middle) {
+ if (ISGREATER(mParams->rssi_middle_5g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_middle_5g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_MIDDLE_5G, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g rssi middle, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_rssi_close_proximity) {
+ if (ISGREATER(mParams->rssi_close_proximity_5g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_close_proximity_5g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in rssi_close_proximity_5g_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_cluster_attribute_val) {
+ result = request.put_u8(NAN_ATTRIBUTE_CONF_CLUSTER_VAL, mParams->config_cluster_attribute_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in config_cluster_attribute_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_hop_count_limit) {
+ result = request.put_u8(NAN_ATTRIBUTE_HOP_COUNT_LIMIT,
+ mParams->hop_count_limit_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in hop cnt limit, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_oui) {
+ ALOGI("%s: oui = 0x%04x\n", __func__, mParams->oui_val);
+ result = request.put_u32(NAN_ATTRIBUTE_OUI, mParams->oui_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in oui, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_MASTER_PREF, mParams->master_pref);
+ if (result < 0) {
+ ALOGE("%s: Failing in master pref, result = %d\n", __func__, result);
+ return result;
+ }
+ if (mParams->config_random_factor_force) {
+ result = request.put_u8(NAN_ATTRIBUTE_RANDOM_FACTOR, mParams->random_factor_force_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in random factor, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_24g_channel) {
+ result = request.put_u32(NAN_ATTRIBUTE_24G_CHANNEL, mParams->channel_24g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2.4g channel, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_channel) {
+ result = request.put_u32(NAN_ATTRIBUTE_5G_CHANNEL, mParams->channel_5g_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g channel, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_intf_addr) {
+ result = request.put_addr(NAN_ATTRIBUTE_IF_ADDR, mParams->intf_addr_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in intf addr val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_dw.config_2dot4g_dw_band) {
+ result = request.put_u32(NAN_ATTRIBUTE_2G_AWAKE_DW, mParams->config_dw.dw_2dot4g_interval_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2dot4g awake dw, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_dw.config_5g_dw_band) {
+ result = request.put_u32(NAN_ATTRIBUTE_5G_AWAKE_DW, mParams->config_dw.dw_5g_interval_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g awake dw, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (ISGREATER(mParams->discovery_indication_cfg, NAN_DISC_IND_MAX)) {
+ ALOGE("%s:Invalid disc_ind_cfg value.\n", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_DISC_IND_CFG,
+ mParams->discovery_indication_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_DISC_IND_CFG, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->config_rssi_window_size) {
+ result = request.put_u8(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE,
+ mParams->rssi_window_size_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in rssi_window_size_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_scan_params) {
+ result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME,
+ mParams->scan_params_val.dwell_time[0]);
+ if (result < 0) {
+ ALOGE("%s: Failing in dwell time, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME_5G,
+ mParams->scan_params_val.dwell_time[1]);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g dwell time, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD,
+ mParams->scan_params_val.scan_period[0]);
+ if (result < 0) {
+ ALOGE("%s: Failing in scan_period, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD_5G,
+ mParams->scan_params_val.scan_period[1]);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_disc_mac_addr_randomization) {
+ result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+ mParams->disc_mac_addr_rand_interval_sec);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill rand mac address interval, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_discovery_beacon_int) {
+ result = request.put_u32(NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL,
+ mParams->discovery_beacon_interval);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill disc beacon interval, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_nss) {
+ result = request.put_u32(NAN_ATTRIBUTE_NSS, mParams->nss);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill nss, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_enable_ranging) {
+ result = request.put_u32(NAN_ATTRIBUTE_ENABLE_RANGING, mParams->enable_ranging);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable ranging value, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_dw_early_termination) {
+ result = request.put_u32(NAN_ATTRIBUTE_DW_EARLY_TERM, mParams->enable_dw_termination);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable dw termination value, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_ndpe_attr) {
+ result = request.put_u32(NAN_ATTRIBUTE_CMD_USE_NDPE,
+ mParams->use_ndpe_attr);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill use_ndpe, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int createDisableRequest(WifiRequest& request) {
+ NAN_DBG_ENTER();
+
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DISABLE);
+ if (result < 0) {
+ ALOGE("%s: Fail to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ request.attr_end(data);
+
+ NAN_DBG_EXIT();
+ return result;
+ }
+
+#ifdef NAN_CLUSTER_MERGE
+ int createEnableMergeRequest(WifiRequest& request,
+ NanEnableMergeRequest *mParams) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE_MERGE);
+ if (result < 0) {
+ ALOGE("%s: Fail to create request\n", __func__);
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u8(NAN_ATTRIBUTE_ENABLE_MERGE, mParams->enable);
+ if (result < 0) {
+ ALOGE("%s: Failing in enable merge, result = %d\n", __func__, result);
+ return result;
+ }
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+#endif /* NAN_CLUSTER_MERGE */
+
+ int createConfigRequest(WifiRequest& request, NanConfigRequest *mParams) {
+
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_CONFIG);
+ s8 rssi;
+ if (result < 0) {
+ ALOGE("%s: Fail to create config request\n", __func__);
+ return result;
+ }
+
+ NAN_DBG_ENTER();
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ if (mParams->config_sid_beacon) {
+ result = request.put_u8(NAN_ATTRIBUTE_SID_BEACON, mParams->sid_beacon);
+ if (result < 0) {
+ ALOGE("%s: Failing in sid beacon, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_subscribe_sid_beacon) {
+ result = request.put_u8(NAN_ATTRIBUTE_SUB_SID_BEACON, mParams->subscribe_sid_beacon_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in sub sid beacon, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_rssi_proximity) {
+ if (ISGREATER(mParams->rssi_proximity, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_proximity;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in rssi_proximity, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_master_pref) {
+ ALOGI("%s: master pref = %u\n", __func__, mParams->master_pref);
+ result = request.put_u8(NAN_ATTRIBUTE_MASTER_PREF, mParams->master_pref);
+ if (result < 0) {
+ ALOGE("%s: Failing in master pref, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_5g_rssi_close_proximity) {
+ if (ISGREATER(mParams->rssi_close_proximity_5g_val, NAN_MAX_RSSI)) {
+ ALOGI("%s: Invalid rssi param \n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ rssi = -mParams->rssi_close_proximity_5g_val;
+ result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G, rssi);
+ if (result < 0) {
+ ALOGE("%s: Failing in rssi_close_proximity_5g_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_rssi_window_size) {
+ result = request.put_u8(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE,
+ mParams->rssi_window_size_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in rssi_window_size_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_scan_params) {
+ result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME,
+ mParams->scan_params_val.dwell_time[0]);
+ if (result < 0) {
+ ALOGE("%s: Failing in dwell time, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME_5G,
+ mParams->scan_params_val.dwell_time[1]);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g dwell time, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD,
+ mParams->scan_params_val.scan_period[0]);
+ if (result < 0) {
+ ALOGE("%s: Failing in scan_period, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD_5G,
+ mParams->scan_params_val.scan_period[1]);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_random_factor_force) {
+ result = request.put_u8(NAN_ATTRIBUTE_RANDOM_FACTOR, mParams->random_factor_force_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in random factor, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_hop_count_force) {
+ result = request.put_u8(NAN_ATTRIBUTE_HOP_COUNT_LIMIT,
+ mParams->hop_count_force_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in hop cnt limit, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_cluster_attribute_val) {
+ result = request.put_u8(NAN_ATTRIBUTE_CONF_CLUSTER_VAL, mParams->config_cluster_attribute_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in config_cluster_attribute_val, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_fam) {
+ while (mParams->fam_val.numchans) {
+ result = request.put_u8(NAN_ATTRIBUTE_ENTRY_CONTROL,
+ mParams->fam_val.famchan[mParams->fam_val.numchans].entry_control);
+ if (result < 0) {
+ ALOGE("%s: Failing in entry control, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_CHANNEL,
+ (u32)mParams->fam_val.famchan[mParams->fam_val.numchans].channel);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill channel = %d, result = %d\n", __func__,
+ mParams->fam_val.famchan[mParams->fam_val.numchans].channel, result);
+ return result;
+ }
+
+ result = request.put_u32(NAN_ATTRIBUTE_AVAIL_BIT_MAP,
+ (u32)mParams->fam_val.famchan[mParams->fam_val.numchans].avail_interval_bitmap);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill avail interval bitmap = %d, result = %d\n", __func__,
+ mParams->fam_val.famchan[mParams->fam_val.numchans].avail_interval_bitmap, result);
+ return result;
+ }
+ mParams->fam_val.numchans -= 1;
+ }
+
+ }
+
+ if (mParams->config_dw.config_2dot4g_dw_band) {
+ result = request.put_u32(NAN_ATTRIBUTE_2G_AWAKE_DW, mParams->config_dw.dw_2dot4g_interval_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 2dot4g awake dw, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_dw.config_5g_dw_band) {
+ result = request.put_u32(NAN_ATTRIBUTE_5G_AWAKE_DW, mParams->config_dw.dw_5g_interval_val);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g awake dw, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ if (ISGREATER(mParams->discovery_indication_cfg, NAN_DISC_IND_MAX)) {
+ ALOGE("%s:Invalid disc_ind_cfg value.\n", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ result = request.put_u8(NAN_ATTRIBUTE_DISC_IND_CFG,
+ mParams->discovery_indication_cfg);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_DISC_IND_CFG, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ if (mParams->config_disc_mac_addr_randomization) {
+ result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+ mParams->disc_mac_addr_rand_interval_sec);
+ if (result < 0) {
+ ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ if (mParams->config_ndpe_attr) {
+ result = request.put_u32(NAN_ATTRIBUTE_CMD_USE_NDPE,
+ mParams->use_ndpe_attr);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill use_ndpe, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_disc_mac_addr_randomization) {
+ result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+ mParams->disc_mac_addr_rand_interval_sec);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill rand mac interval, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_discovery_beacon_int) {
+ result = request.put_u32(NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL,
+ mParams->discovery_beacon_interval);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill disc beacon interval, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_nss) {
+ result = request.put_u32(NAN_ATTRIBUTE_NSS, mParams->nss);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill nss, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_enable_ranging) {
+ result = request.put_u32(NAN_ATTRIBUTE_ENABLE_RANGING, mParams->enable_ranging);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable ranging value, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->config_dw_early_termination) {
+ result = request.put_u32(NAN_ATTRIBUTE_DW_EARLY_TERM, mParams->enable_dw_termination);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable dw termination value, result = %d\n",
+ __func__, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int start()
+ {
+ NAN_DBG_ENTER();
+
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create setup request; result = %d", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to configure setup; result = %d", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int cancel()
+ {
+ NAN_DBG_ENTER();
+
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to create setup request; result = %d", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: Failed to configure setup; result = %d", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ nan_hal_resp_t *rsp_vndr_data = NULL;
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+ ALOGI("NanMacControl::handleResponse\n");
+ if (mType == NAN_VERSION_INFO) {
+ mVersion = *((u32*)reply.get_vendor_data());
+ ALOGI("Response not required for version cmd %d\n", mVersion);
+ return NL_SKIP;
+ }
+ if (rsp_vndr_data->subcmd == NAN_SUBCMD_CONFIG) {
+ NanResponseMsg rsp_data;
+ memset(&rsp_data, 0, sizeof(NanResponseMsg));
+ rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+ rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+
+ ALOGI("NanMacControl:Received response for cmd [%s], TxID %d ret %d\n",
+ NanRspToString(rsp_data.response_type), id(), rsp_data.status);
+
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+ }
+ if (rsp_vndr_data->subcmd == NAN_SUBCMD_ENABLE) {
+ NanResponseMsg rsp_data;
+ memset(&rsp_data, 0, sizeof(NanResponseMsg));
+ rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+ rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+
+ ALOGI("NanMacControl:Received response for cmd [%s], TxID %d ret %d\n",
+ NanRspToString(rsp_data.response_type), mId, rsp_data.status);
+
+ if( rsp_data.status != NAN_STATUS_SUCCESS) {
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+ }
+ }
+ return NL_SKIP;
+ }
+
+ int handleAsyncResponse(nan_hal_resp_t *rsp_vndr_data) {
+ NanResponseMsg rsp_data;
+ ALOGI("NanMacControl::handleAsyncResponse\n");
+ /* Enable response will be provided to framework in event path */
+ if (rsp_vndr_data->subcmd == NAN_SUBCMD_ENABLE) {
+ return NL_SKIP;
+ }
+ memset(&rsp_data, 0, sizeof(NanResponseMsg));
+ rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+ rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+ ALOGE("Mapped hal status = %d\n", rsp_data.status);
+
+ /* populate error string if not coming from DHD */
+ if (rsp_vndr_data->nan_reason[0] == '\0') {
+ memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+ strlen(NanStatusToString(rsp_data.status)));
+ rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+ }
+ rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+ ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+ ALOGI("Retrieved ID = %d\n", mId);
+
+ if ((rsp_vndr_data->subcmd == NAN_SUBCMD_DISABLE) &&
+ (mId != NAN_MAC_INVALID_TRANSID)) {
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+ mId = NAN_MAC_INVALID_TRANSID;
+ }
+ return NL_SKIP;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ u16 inst_id;
+ u32 ndp_instance_id = 0;
+ int event_id = event.get_vendor_subcmd();
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ u16 attr_type;
+ nan_hal_resp_t *rsp_vndr_data = NULL;
+
+ ALOGI("%s: Received NanMacControl event = %d (len=%d)\n",
+ __func__, event.get_cmd(), len);
+ if (!vendor_data || len == 0) {
+ ALOGE("No event data found");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (it.get_type() == NAN_ATTRIBUTE_HANDLE) {
+ inst_id = it.get_u8();
+ } else if (it.get_type() == NAN_ATTRIBUTE_NDP_ID) {
+ ndp_instance_id = it.get_u32();
+ ALOGI("handleEvent: ndp_instance_id = [%d]\n", ndp_instance_id);
+ } else if (attr_type == NAN_ATTRIBUTE_CMD_RESP_DATA) {
+ ALOGI("sizeof cmd response data: %d, it.get_len() = %d\n",
+ sizeof(nan_hal_resp_t), it.get_len());
+ if (it.get_len() == sizeof(nan_hal_resp_t)) {
+ rsp_vndr_data = (nan_hal_resp_t*)it.get_data();
+ } else {
+ ALOGE("Wrong cmd response data received\n");
+ return NL_SKIP;
+ }
+ }
+ }
+
+ ALOGI("Received vendor sub cmd %d\n", event_id);
+ if (is_de_event(event_id)) {
+
+ NanDiscEnginePrimitive *de_prim =
+ (NanDiscEnginePrimitive *)(info.nan_disc_control);
+ if (de_prim != NULL) {
+ de_prim->handleEvent(event);
+ } else {
+ ALOGE("%s: de_primitive is no more available\n", __func__);
+ }
+ return NL_SKIP;
+
+ } else if (is_dp_event(event_id)) {
+
+ NanDataPathPrimitive *dp_prim =
+ (NanDataPathPrimitive *)(info.nan_dp_control);
+ ALOGI("ndp_instance_id = [%d]\n", ndp_instance_id);
+ if (dp_prim != NULL) {
+ dp_prim->handleEvent(event);
+ } else {
+ ALOGE("%s: dp_primitive is no more available\n", __func__);
+ }
+ return NL_SKIP;
+ } else {
+ if (is_cmd_response(event_id)) {
+ ALOGE("Handling cmd response asynchronously\n");
+ handleAsyncResponse(rsp_vndr_data);
+ }
+ }
+
+ switch(event_id) {
+ case NAN_EVENT_DE_EVENT:
+ NanDiscEngEventInd de_event;
+ memset(&de_event, 0, sizeof(de_event));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_CLUSTER_ID) {
+ memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("cluster id = " MACSTR "\n", MAC2STR(de_event.data.cluster.addr));
+ } else if (attr_type == NAN_ATTRIBUTE_ENABLE_STATUS) {
+ ALOGI("nan enable status = %u\n", it.get_u16());
+ } else if (attr_type == NAN_ATTRIBUTE_JOIN_STATUS) {
+ ALOGI("nan joined status = %u\n", it.get_u16());
+ } else if (attr_type == NAN_ATTRIBUTE_DE_EVENT_TYPE) {
+ u8 de_type = it.get_u8();
+ ALOGI("nan de event type = %u\n", de_type);
+ if (de_type == NAN_EVENT_IFACE) {
+ de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ ALOGI("received NAN_EVENT_ID_DISC_MAC_ADDR event\n");
+ } else if (de_type == NAN_EVENT_START) {
+ de_event.event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+ ALOGI("received NAN cluster started event\n");
+ } else if (de_type == NAN_EVENT_JOIN) {
+ /* To be deprecated */
+ de_event.event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+ ALOGI("received join event\n");
+ } else if (de_type == NAN_EVENT_ROLE_CHANGE) {
+ ALOGI("received device role change event\n");
+ } else if (de_type == NAN_EVENT_MERGE) {
+ ALOGI("received merge event\n");
+ } else {
+ ALOGI("received unknown DE event, [%d]\n", de_type);
+ }
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(&de_event.data.mac_addr.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ memcpy(mNmi, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Primary discovery mac address = " MACSTR "\n",
+ MAC2STR(mNmi));
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+ /* XXX: WAR for sending intf addr to generate Identity
+ * change callback in framework
+ * Also WAR for enable response
+ */
+ if (de_event.event_type == NAN_EVENT_ID_STARTED_CLUSTER) {
+ NanResponseMsg rsp_data;
+ memcpy(&de_event.data.mac_addr.addr, mNmi, NAN_MAC_ADDR_LEN);
+ de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+ rsp_data.response_type = NAN_RESPONSE_ENABLED;
+ rsp_data.status = NAN_STATUS_SUCCESS;
+ memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+ strlen(NanStatusToString(rsp_data.status)));
+ GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+ /* clean up mId to distinguish duplciated disable command */
+ mId = NAN_MAC_INVALID_TRANSID;
+ }
+ break;
+
+ case NAN_EVENT_DISABLED:
+ ALOGI("Received NAN_EVENT_DISABLED\n");
+ NanDisabledInd disabled_ind;
+ memset(&disabled_ind, 0, sizeof(NanDisabledInd));
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ disabled_ind.reason = (NanStatusType)it.get_u8();
+ ALOGI("Nan Disable:status %u", disabled_ind.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(disabled_ind.nan_reason, it.get_data(),
+ sizeof(disabled_ind.nan_reason));
+ ALOGI("Disable nan reason: %s", disabled_ind.nan_reason);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDisabled(&disabled_ind);
+ /* unregister Nan vendor events */
+ unRegisterNanVendorEvents();
+ break;
+
+ case NAN_EVENT_SDF:
+ ALOGI("Received NAN_EVENT_SDF:\n");
+ NanBeaconSdfPayloadInd sdfInd;
+ memset(&sdfInd, 0, sizeof(sdfInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ sdfInd.data.frame_len = it.get_u32();
+ if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
+ sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
+ }
+ ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN: 0x%x(%d)\n",
+ sdfInd.data.frame_len, sdfInd.data.frame_len);
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO\n");
+ memcpy(&sdfInd.data.frame_data, it.get_data(), sdfInd.data.frame_len);
+ prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
+ sdfInd.data.frame_len);
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventBeaconSdfPayload(&sdfInd);
+ break;
+
+ case NAN_EVENT_TCA:
+ ALOGI("Received NAN_EVENT_TCA\n");
+ break;
+
+ case NAN_EVENT_UNKNOWN:
+ ALOGI("Received NAN_EVENT_UNKNOWN\n");
+ break;
+ } // end-of-switch
+
+ return NL_SKIP;
+ }
+ void unRegisterNanVendorEvents()
+ {
+ int i = 0;
+ for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+ unregisterVendorHandler(GOOGLE_OUI, i);
+ }
+ unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ }
+ void registerNanVendorEvents()
+ {
+ int i = 0;
+ for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+ registerVendorHandler(GOOGLE_OUI, i);
+ }
+ registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ }
+};
+
+/* pretty hex print a contiguous buffer */
+static void prhex(const char *msg, u8 *buf, u32 nbytes)
+{
+ char line[128];
+ char *p;
+ int len = sizeof(line);
+ int nchar;
+ u32 i;
+
+ if (msg && (msg[0] != '\0')) {
+ printf("%s:\n", msg);
+ }
+
+ p = line;
+ for (i = 0; i < nbytes; i++) {
+ if (i % 16 == 0) {
+ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */
+ p += nchar;
+ len -= nchar;
+ }
+
+ if (len > 0) {
+ nchar = snprintf(p, len, "%02x ", buf[i]);
+ p += nchar;
+ len -= nchar;
+ }
+
+ if (i % 16 == 15) {
+ ALOGE("%s\n", line); /* flush line */
+ p = line;
+ len = sizeof(line);
+ }
+ }
+
+ /* flush last partial line */
+ if (p != line) {
+ ALOGE("%s\n", line);
+ }
+}
+
+
+static const char *NanRspToString(int cmd_resp)
+{
+ switch (cmd_resp) {
+ C2S(NAN_RESPONSE_ENABLED)
+ C2S(NAN_RESPONSE_DISABLED)
+ C2S(NAN_RESPONSE_PUBLISH)
+ C2S(NAN_RESPONSE_SUBSCRIBE)
+ C2S(NAN_RESPONSE_PUBLISH_CANCEL)
+ C2S(NAN_RESPONSE_SUBSCRIBE_CANCEL)
+ C2S(NAN_RESPONSE_TRANSMIT_FOLLOWUP)
+ C2S(NAN_RESPONSE_CONFIG)
+ C2S(NAN_RESPONSE_TCA)
+ C2S(NAN_RESPONSE_STATS)
+ C2S(NAN_DP_INTERFACE_CREATE)
+ C2S(NAN_DP_INTERFACE_DELETE)
+ C2S(NAN_DP_INITIATOR_RESPONSE)
+ C2S(NAN_DP_RESPONDER_RESPONSE)
+ C2S(NAN_DP_END)
+ C2S(NAN_GET_CAPABILITIES)
+
+ default:
+ return "UNKNOWN_NAN_CMD_RESPONSE";
+ }
+}
+
+static const char *NanCmdToString(int cmd)
+{
+ switch (cmd) {
+ C2S(NAN_REQUEST_ENABLE)
+ C2S(NAN_REQUEST_DISABLE)
+ C2S(NAN_REQUEST_PUBLISH)
+ C2S(NAN_REQUEST_PUBLISH_CANCEL)
+ C2S(NAN_REQUEST_TRANSMIT_FOLLOWUP)
+ C2S(NAN_REQUEST_SUBSCRIBE)
+ C2S(NAN_REQUEST_SUBSCRIBE_CANCEL)
+ C2S(NAN_REQUEST_STATS)
+ C2S(NAN_REQUEST_CONFIG)
+ C2S(NAN_REQUEST_TCA)
+ C2S(NAN_REQUEST_EVENT_CHECK)
+ C2S(NAN_REQUEST_GET_CAPABILTIES)
+ C2S(NAN_DATA_PATH_IFACE_CREATE)
+ C2S(NAN_DATA_PATH_IFACE_DELETE)
+ C2S(NAN_DATA_PATH_INIT_REQUEST)
+ C2S(NAN_DATA_PATH_IND_RESPONSE)
+ C2S(NAN_DATA_PATH_END)
+ C2S(NAN_DATA_PATH_IFACE_UP)
+ C2S(NAN_DATA_PATH_SEC_INFO)
+ C2S(NAN_VERSION_INFO)
+ C2S(NAN_REQUEST_ENABLE_MERGE)
+
+ default:
+ return "UNKNOWN_NAN_CMD";
+ }
+}
+
+static const char *NanAttrToString(u16 cmd)
+{
+ switch (cmd) {
+ C2S(NAN_ATTRIBUTE_HEADER)
+ C2S(NAN_ATTRIBUTE_HANDLE)
+ C2S(NAN_ATTRIBUTE_TRANSAC_ID)
+ C2S(NAN_ATTRIBUTE_5G_SUPPORT)
+ C2S(NAN_ATTRIBUTE_CLUSTER_LOW)
+ C2S(NAN_ATTRIBUTE_CLUSTER_HIGH)
+ C2S(NAN_ATTRIBUTE_SID_BEACON)
+ C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON)
+ C2S(NAN_ATTRIBUTE_RSSI_CLOSE)
+ C2S(NAN_ATTRIBUTE_RSSI_MIDDLE)
+ C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY)
+ C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT)
+ C2S(NAN_ATTRIBUTE_RANDOM_FACTOR)
+ C2S(NAN_ATTRIBUTE_MASTER_PREF)
+ C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL)
+ C2S(NAN_ATTRIBUTE_PUBLISH_ID)
+ C2S(NAN_ATTRIBUTE_TTL)
+ C2S(NAN_ATTRIBUTE_PERIOD)
+ C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG)
+ C2S(NAN_ATTRIBUTE_PUBLISH_TYPE)
+ C2S(NAN_ATTRIBUTE_TX_TYPE)
+ C2S(NAN_ATTRIBUTE_PUBLISH_COUNT)
+ C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN)
+ C2S(NAN_ATTRIBUTE_SERVICE_NAME)
+ C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN)
+ C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO)
+ C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN)
+ C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER)
+ C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN)
+ C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER)
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID)
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE)
+ C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER)
+ C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE)
+ C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER)
+ C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION)
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH)
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT)
+ C2S(NAN_ATTRIBUTE_MAC_ADDR)
+ C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST)
+ C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES)
+ C2S(NAN_ATTRIBUTE_PUBLISH_MATCH)
+ C2S(NAN_ATTRIBUTE_ENABLE_STATUS)
+ C2S(NAN_ATTRIBUTE_JOIN_STATUS)
+ C2S(NAN_ATTRIBUTE_ROLE)
+ C2S(NAN_ATTRIBUTE_MASTER_RANK)
+ C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK)
+ C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM)
+ C2S(NAN_ATTRIBUTE_CNT_BCN_TX)
+ C2S(NAN_ATTRIBUTE_CNT_BCN_RX)
+ C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX)
+ C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX)
+ C2S(NAN_ATTRIBUTE_AMBTT)
+ C2S(NAN_ATTRIBUTE_CLUSTER_ID)
+ C2S(NAN_ATTRIBUTE_INST_ID)
+ C2S(NAN_ATTRIBUTE_OUI)
+ C2S(NAN_ATTRIBUTE_STATUS)
+ C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE)
+ C2S(NAN_ATTRIBUTE_MERGE)
+ C2S(NAN_ATTRIBUTE_IFACE)
+ C2S(NAN_ATTRIBUTE_CHANNEL)
+ C2S(NAN_ATTRIBUTE_PEER_ID)
+ C2S(NAN_ATTRIBUTE_NDP_ID)
+ C2S(NAN_ATTRIBUTE_SECURITY)
+ C2S(NAN_ATTRIBUTE_QOS)
+ C2S(NAN_ATTRIBUTE_RSP_CODE)
+ C2S(NAN_ATTRIBUTE_INST_COUNT)
+ C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR)
+ C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR)
+ C2S(NAN_ATTRIBUTE_IF_ADDR)
+ C2S(NAN_ATTRIBUTE_WARMUP_TIME)
+ C2S(NAN_ATTRIBUTE_RANGING_RESULT)
+ C2S(NAN_ATTRIBUTE_RANGING_INDICATION)
+ C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN)
+ C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO)
+ C2S(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL)
+ C2S(NAN_ATTRIBUTE_ENABLE_MERGE)
+
+ default:
+ return "NAN_ATTRIBUTE_UNKNOWN";
+ }
+}
+
+NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd)
+{
+ NanResponseType response_type;
+
+ switch(nan_subcmd) {
+ case NAN_SUBCMD_ENABLE:
+ response_type = NAN_RESPONSE_ENABLED;
+ break;
+ case NAN_SUBCMD_DISABLE:
+ response_type = NAN_RESPONSE_DISABLED;
+ break;
+ case NAN_SUBCMD_PUBLISH:
+ response_type = NAN_RESPONSE_PUBLISH;
+ break;
+ case NAN_SUBCMD_SUBSCRIBE:
+ response_type = NAN_RESPONSE_SUBSCRIBE;
+ break;
+ case NAN_SUBCMD_PUBLISH_CANCEL:
+ response_type = NAN_RESPONSE_PUBLISH_CANCEL;
+ break;
+ case NAN_SUBCMD_SUBSCRIBE_CANCEL:
+ response_type = NAN_RESPONSE_SUBSCRIBE_CANCEL;
+ break;
+ case NAN_SUBCMD_TRANSMIT_FOLLOWUP:
+ response_type = NAN_RESPONSE_TRANSMIT_FOLLOWUP;
+ break;
+ case NAN_SUBCMD_CONFIG:
+ response_type = NAN_RESPONSE_CONFIG;
+ break;
+ case NAN_SUBCMD_TCA:
+ response_type = NAN_RESPONSE_TCA;
+ break;
+ case NAN_SUBCMD_STATS:
+ response_type = NAN_RESPONSE_STATS;
+ break;
+ case NAN_SUBCMD_DATA_PATH_IFACE_CREATE:
+ response_type = NAN_DP_INTERFACE_CREATE;
+ break;
+ case NAN_SUBCMD_DATA_PATH_IFACE_DELETE:
+ response_type = NAN_DP_INTERFACE_DELETE;
+ break;
+ case NAN_SUBCMD_DATA_PATH_REQUEST:
+ response_type = NAN_DP_INITIATOR_RESPONSE;
+ break;
+ case NAN_SUBCMD_DATA_PATH_RESPONSE:
+ response_type = NAN_DP_RESPONDER_RESPONSE;
+ break;
+ case NAN_SUBCMD_DATA_PATH_END:
+ response_type = NAN_DP_END;
+ break;
+ case NAN_SUBCMD_GET_CAPABILITIES:
+ response_type = NAN_GET_CAPABILITIES;
+ break;
+ default:
+ /* unknown response for a command */
+ response_type = NAN_RESPONSE_ERROR;
+ break;
+ }
+
+ return response_type;
+}
+
+static int get_svc_hash(unsigned char *svc_name,
+ u16 svc_name_len, u8 *svc_hash, u16 svc_hash_len)
+{
+ SHA256_CTX sha_ctx;
+ u8 sha_hash[SHA256_DIGEST_LENGTH];
+ unsigned char *p;
+ int len = svc_name_len;
+
+ if (!svc_name || !svc_hash) {
+ ALOGE("Bad arguments!!\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (svc_hash_len < NAN_SVC_HASH_SIZE) {
+ ALOGE("Bad len!!\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ for (p = svc_name; *p; p++)
+ {
+ *p = tolower((int)*p);
+ }
+ SHA256_Init(&sha_ctx);
+ SHA256_Update(&sha_ctx, svc_name, len);
+ SHA256_Final(sha_hash, &sha_ctx);
+
+ memcpy(svc_hash, sha_hash, NAN_SVC_HASH_SIZE);
+ ALOGI("svc_name: %s\n", svc_name);
+ prhex("svc_hash:", svc_hash, NAN_SVC_HASH_SIZE);
+
+ return WIFI_SUCCESS;
+}
+
+#ifdef CONFIG_BRCM
+static int dump_NanEnableRequest(NanEnableRequest* msg)
+{
+ ALOGI("%s: Dump NanEnableRequest msg:\n", __func__);
+
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("master_pref=%u\n", msg->master_pref);
+ ALOGI("cluster_low=%u\n", msg->cluster_low);
+ ALOGI("cluster_high=%u\n", msg->cluster_high);
+ ALOGI("config_support_5g=%u\n", msg->config_support_5g);
+ ALOGI("support_5g_val=%u\n", msg->support_5g_val);
+ ALOGI("config_sid_beacon=%u\n", msg->config_sid_beacon);
+ ALOGI("sid beacon=%u\n", msg->sid_beacon_val);
+ ALOGI("config_sub_sid_beacon=%u\n", msg->config_subscribe_sid_beacon);
+ ALOGI("sub sid beacon=%u\n", msg->subscribe_sid_beacon_val);
+ ALOGI("config_2dot4g_rssi_close=%u\n", msg->config_2dot4g_rssi_close);
+ ALOGI("rssi_close_2dot4g_val=%u\n", msg->rssi_close_2dot4g_val);
+ ALOGI("config_2dot4g_rssi_middle=%u\n", msg->config_2dot4g_rssi_middle);
+ ALOGI("rssi_middle_2dot4g_val=%u\n", msg->rssi_middle_2dot4g_val);
+ ALOGI("config_2dot4g_rssi_proximity=%u\n", msg->config_2dot4g_rssi_proximity);
+ ALOGI("rssi_proximity_2dot4g_val=%u\n", msg->rssi_proximity_2dot4g_val);
+ ALOGI("config_hop_count_limit=%u\n", msg->config_hop_count_limit);
+ ALOGI("hop_count_limit_val=%u\n", msg->hop_count_limit_val);
+ ALOGI("config_2dot4g_support=%u\n", msg->config_2dot4g_support);
+ ALOGI("support_2dot4g_val=%u\n", msg->support_2dot4g_val);
+ ALOGI("config_2dot4g_beacons=%u\n", msg->config_2dot4g_beacons);
+ ALOGI("beacon_2dot4g_val=%u\n", msg->beacon_2dot4g_val);
+ ALOGI("config_2dot4g_sdf=%u\n", msg->config_2dot4g_sdf);
+ ALOGI("sdf_2dot4g_val=%u\n", msg->sdf_2dot4g_val);
+ ALOGI("config_5g_beacons=%u\n", msg->config_5g_beacons);
+ ALOGI("beacon_5g_val=%u\n", msg->beacon_5g_val);
+ ALOGI("config_5g_sdf=%u\n", msg->config_5g_sdf);
+ ALOGI("config_5g_rssi_close=%u\n", msg->config_5g_rssi_close);
+ ALOGI("rssi_close_5g_val=%u\n", msg->rssi_close_5g_val);
+ ALOGI("config_5g_rssi_middle=%u\n", msg->config_5g_rssi_middle);
+ ALOGI("rssi_middle_5g_val=%u\n", msg->rssi_middle_5g_val);
+ ALOGI("config_5g_rssi_close_proximity=%u\n", msg->config_5g_rssi_close_proximity);
+ ALOGI("rssi_close_proximity_5g_val=%u\n", msg->rssi_close_proximity_5g_val);
+ ALOGI("config_rssi_window_size=%u\n", msg->config_rssi_window_size);
+ ALOGI("rssi_window_size_val=%u\n", msg->rssi_window_size_val);
+ ALOGI("config_oui=%u\n", msg->config_oui);
+ ALOGI("oui_val=%u\n", msg->oui_val);
+ ALOGI("config_intf_addr=%u\n", msg->config_intf_addr);
+ ALOGI("intf_addr_val=" MACSTR "\n", MAC2STR(msg->intf_addr_val));
+ ALOGI("config_cluster_attribute_val=%u\n", msg->config_cluster_attribute_val);
+ ALOGI("config_scan_params=%u\n", msg->config_scan_params);
+ if (msg->config_scan_params) {
+ ALOGI("dwell_time=%u\n", msg->scan_params_val.dwell_time[0]);
+ ALOGI("scan_period=%u\n", msg->scan_params_val.scan_period[0]);
+ }
+ ALOGI("config_random_factor_force=%u\n", msg->config_random_factor_force);
+ ALOGI("random_factor_force_val=%u\n", msg->random_factor_force_val);
+ ALOGI("config_hop_count_force=%u\n", msg->config_hop_count_force);
+ ALOGI("config_24g_channel=%u\n", msg->config_24g_channel);
+ ALOGI("channel_24g_val=%u\n", msg->channel_24g_val);
+ ALOGI("config_5g_channel=%u\n", msg->config_5g_channel);
+ ALOGI("channel_5g_val=%u\n", msg->channel_5g_val);
+ ALOGI("config_dw.config_2dot4g_dw_band=%u\n", msg->config_dw.config_2dot4g_dw_band);
+ if (msg->config_dw.config_2dot4g_dw_band) {
+ ALOGI("dw_2dot4g_interval_val=%u\n", msg->config_dw.dw_2dot4g_interval_val);
+ }
+ ALOGI("config_dw.config_5g_dw_band=%u\n", msg->config_dw.config_5g_dw_band);
+ if (msg->config_dw.config_5g_dw_band) {
+ ALOGI("dw_5g_interval_val=%u\n", msg->config_dw.dw_5g_interval_val);
+ }
+ ALOGI("discovery_indication_cfg=%u\n", msg->discovery_indication_cfg);
+ ALOGI("config_ndpe_attr=%u\n", msg->config_ndpe_attr);
+ if (msg->config_ndpe_attr) {
+ ALOGI("use_ndpe_attr=%u\n", msg->use_ndpe_attr);
+ }
+ ALOGI("config_discovery_beacon_int=%u\n", msg->config_discovery_beacon_int);
+ if (msg->config_discovery_beacon_int) {
+ ALOGI("discovery beacon interval =%u\n", msg->discovery_beacon_interval);
+ }
+ ALOGI("config_nss=%u\n", msg->config_nss);
+ if (msg->config_nss) {
+ ALOGI("nss =%u\n", msg->nss);
+ }
+ ALOGI("config_enable_ranging =%u\n", msg->config_enable_ranging);
+ if (msg->config_enable_ranging) {
+ ALOGI("enable_ranging =%u\n", msg->enable_ranging);
+ }
+ ALOGI("config_dw_early_termination =%u\n", msg->config_dw_early_termination);
+ if (msg->config_dw_early_termination) {
+ ALOGI("enable_dw_termination =%u\n", msg->enable_dw_termination);
+ }
+ ALOGI("config_disc_mac_addr_randomization=%u\n", msg->config_disc_mac_addr_randomization);
+ if (msg->config_disc_mac_addr_randomization) {
+ ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
+ }
+
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanConfigRequestRequest(NanConfigRequest* msg)
+{
+ ALOGI("%s: Dump NanConfigRequest msg:\n", __func__);
+
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("master_pref=%u\n", msg->master_pref);
+ ALOGI("sid beacon=%u\n", msg->sid_beacon);
+ ALOGI("config_sub_sid_beacon=%u\n", msg->config_subscribe_sid_beacon);
+ ALOGI("sub sid beacon=%u\n", msg->subscribe_sid_beacon_val);
+ ALOGI("rssi_proximity=%u\n", msg->rssi_proximity);
+ ALOGI("rssi_close_proximity_5g_val=%u\n", msg->rssi_close_proximity_5g_val);
+ ALOGI("rssi_window_size_val=%u\n", msg->rssi_window_size_val);
+ ALOGI("scan_params_val.dwell_time[0]=%u\n", msg->scan_params_val.dwell_time[0]);
+ ALOGI("scan_params_val.scan_period[0]=%u\n", msg->scan_params_val.scan_period[0]);
+ ALOGI("config_scan_params=%u\n", msg->config_scan_params);
+ ALOGI("random_factor_force_val=%u\n", msg->random_factor_force_val);
+ ALOGI("hop_count_force_val=%u\n", msg->hop_count_force_val);
+ ALOGI("fam_val.numchans=%u\n", msg->fam_val.numchans);
+ ALOGI("fam_val.famchan[0].entry_control=%u\n", msg->fam_val.famchan[0].entry_control);
+ ALOGI("fam_val.famchan[0].class_val=%u\n", msg->fam_val.famchan[0].class_val);
+ ALOGI("fam_val.famchan[0].channel=%u\n", msg->fam_val.famchan[0].channel);
+ ALOGI("fam_val.famchan[0].mapid=%u\n", msg->fam_val.famchan[0].mapid);
+ ALOGI("fam_val.famchan[0].avail_interval_bitmap=%u\n", msg->fam_val.famchan[0].avail_interval_bitmap);
+ ALOGI("config_dw.config_2dot4g_dw_band=%u\n", msg->config_dw.config_2dot4g_dw_band);
+ if (msg->config_dw.config_2dot4g_dw_band) {
+ ALOGI("dw_2dot4g_interval_val=%u\n", msg->config_dw.dw_2dot4g_interval_val);
+ }
+ ALOGI("config_dw.config_5g_dw_band=%u\n", msg->config_dw.config_5g_dw_band);
+ if (msg->config_dw.config_5g_dw_band) {
+ ALOGI("dw_5g_interval_val=%u\n", msg->config_dw.dw_5g_interval_val);
+ }
+ ALOGI("discovery_indication_cfg=%u\n", msg->discovery_indication_cfg);
+ ALOGI("config_ndpe_attr=%u\n", msg->config_ndpe_attr);
+ if (msg->config_ndpe_attr) {
+ ALOGI("use_ndpe_attr=%u\n", msg->use_ndpe_attr);
+ }
+ ALOGI("config_discovery_beacon_int=%u\n", msg->config_discovery_beacon_int);
+ if (msg->config_discovery_beacon_int) {
+ ALOGI("discovery beacon interval =%u\n", msg->discovery_beacon_interval);
+ }
+ ALOGI("config_nss=%u\n", msg->config_nss);
+ if (msg->config_nss) {
+ ALOGI("nss =%u\n", msg->nss);
+ }
+ ALOGI("config_enable_ranging =%u\n", msg->config_enable_ranging);
+ if (msg->config_enable_ranging) {
+ ALOGI("enable_ranging =%u\n", msg->enable_ranging);
+ }
+ ALOGI("config_dw_early_termination =%u\n", msg->config_dw_early_termination);
+ if (msg->config_dw_early_termination) {
+ ALOGI("enable_dw_termination =%u\n", msg->enable_dw_termination);
+ }
+
+ ALOGI("config_disc_mac_addr_randomization=%u\n", msg->config_disc_mac_addr_randomization);
+ if (msg->config_disc_mac_addr_randomization) {
+ ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
+ }
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanPublishRequest(NanPublishRequest* msg)
+{
+ ALOGI("%s: Dump NanPublishRequest msg:\n", __func__);
+ u8 i = 0;
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ ALOGI("publish_id=%u\n", msg->publish_id);
+ ALOGI("ttl=%u\n", msg->ttl);
+ ALOGI("period=%u\n", msg->period);
+ ALOGI("publish_type=%u\n", msg->publish_type);
+ ALOGI("tx_type=%u\n", msg->tx_type);
+ ALOGI("publish_count=%u\n", msg->publish_count);
+ ALOGI("publish_match_indicator=%u\n", msg->publish_match_indicator);
+ ALOGI("service_responder_policy=%u\n", msg->service_responder_policy);
+ ALOGI("service_name_len=%u\n", msg->service_name_len);
+ if (msg->service_name_len)
+ ALOGI("service_name=%s\n", msg->service_name);
+ ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+ if (msg->service_specific_info_len)
+ ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+ ALOGI("rx_match_filter_len=%u\n", msg->rx_match_filter_len);
+ if (msg->rx_match_filter_len)
+ prhex("rx_match_filter", msg->rx_match_filter, msg->rx_match_filter_len);
+ ALOGI("tx_match_filter_len=%u\n", msg->tx_match_filter_len);
+ if (msg->tx_match_filter_len)
+ prhex("tx_match_filter", msg->tx_match_filter, msg->tx_match_filter_len);
+ ALOGI("rssi_threshold_flag=%u\n", msg->rssi_threshold_flag);
+ ALOGI("connmap=%u\n", msg->connmap);
+ ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+ ALOGI("cipher_type=%u\n", msg->cipher_type);
+ ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+ ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+ ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+ ALOGI("scid_len=%u\n", msg->scid_len);
+ if (msg->scid_len)
+ ALOGI("scid=%s\n", msg->scid);
+ ALOGI("NanSdeaCtrlParams NdpType=%u\n", msg->sdea_params.ndp_type);
+ ALOGI("NanSdeaCtrlParams security_cfg=%u\n", msg->sdea_params.security_cfg);
+ ALOGI("NanSdeaCtrlParams ranging_state=%u\n", msg->sdea_params.ranging_state);
+ ALOGI("NanSdeaCtrlParams range_report=%u\n", msg->sdea_params.range_report);
+ ALOGI("NanRangingCfg ranging_interval_msec=%u\n", msg->ranging_cfg.ranging_interval_msec);
+ ALOGI("NanRangingCfg config_ranging_indications=%u\n", msg->ranging_cfg.config_ranging_indications);
+ ALOGI("NanRangingCfg distance_ingress_mm=%u\n", msg->ranging_cfg.distance_ingress_mm);
+ ALOGI("NanRangingCfg distance_egress_mm=%u\n", msg->ranging_cfg.distance_egress_mm);
+ ALOGI("NanRangingAutoResponse = %u\n", msg->ranging_auto_response);
+ ALOGI("range_response_cfg=%u\n", msg->range_response_cfg.ranging_response);
+
+ ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+ if (msg->sdea_service_specific_info_len)
+ ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
+{
+ ALOGI("%s: Dump NanSubscribeRequest msg:\n", __func__);
+ u8 i = 0;
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ ALOGI("subscribe_id=%u\n", msg->subscribe_id);
+ ALOGI("ttl=%u\n", msg->ttl);
+ ALOGI("period=%u\n", msg->period);
+ ALOGI("subscribe_type=%u\n", msg->subscribe_type);
+ ALOGI("serviceResponseFilter=%u\n", msg->serviceResponseFilter);
+ ALOGI("serviceResponseInclude=%u\n", msg->serviceResponseInclude);
+ ALOGI("useServiceResponseFilter=%u\n", msg->useServiceResponseFilter);
+ ALOGI("ssiRequiredForMatchIndication=%u\n", msg->ssiRequiredForMatchIndication);
+ ALOGI("subscribe_count=%u\n", msg->subscribe_count);
+ ALOGI("subscribe_match_indicator=%u\n", msg->subscribe_match_indicator);
+ ALOGI("service_name_len=%u\n", msg->service_name_len);
+ if (msg->service_name_len)
+ ALOGI("service_name=%s\n", msg->service_name);
+ ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+ if (msg->service_specific_info_len)
+ ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+ ALOGI("rx_match_filter_len=%u\n", msg->rx_match_filter_len);
+ if (msg->rx_match_filter_len)
+ prhex("rx_match_filter", msg->rx_match_filter, msg->rx_match_filter_len);
+ ALOGI("tx_match_filter_len=%u\n", msg->tx_match_filter_len);
+ if (msg->tx_match_filter_len)
+ prhex("tx_match_filter", msg->tx_match_filter, msg->tx_match_filter_len);
+ ALOGI("rssi_threshold_flag=%u\n", msg->rssi_threshold_flag);
+ ALOGI("connmap=%u\n", msg->connmap);
+ ALOGI("num_intf_addr_present=%u\n", msg->num_intf_addr_present);
+ if (msg->num_intf_addr_present) {
+ for (i = 0; i < NAN_MAX_SUBSCRIBE_MAX_ADDRESS; i++) {
+ ALOGI("peer_disc_mac_addr=" MACSTR "\n", MAC2STR(msg->intf_addr[i]));
+ }
+ }
+ ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+ ALOGI("cipher_type=%u\n", msg->cipher_type);
+ ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+ ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+ ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+ ALOGI("scid_len=%u\n", msg->scid_len);
+ if (msg->scid_len)
+ ALOGI("scid=%s\n", msg->scid);
+ ALOGI("NanSdeaCtrlParams NdpType=%u\n", msg->sdea_params.ndp_type);
+ ALOGI("NanSdeaCtrlParams security_cfg=%u\n", msg->sdea_params.security_cfg);
+ ALOGI("NanSdeaCtrlParams ranging_state=%u\n", msg->sdea_params.ranging_state);
+ ALOGI("NanSdeaCtrlParams range_report=%u\n", msg->sdea_params.range_report);
+ ALOGI("NanRangingCfg ranging_interval_msec=%u\n", msg->ranging_cfg.ranging_interval_msec);
+ ALOGI("NanRangingCfg config_ranging_indications=%u\n", msg->ranging_cfg.config_ranging_indications);
+ ALOGI("NanRangingCfg distance_ingress_mm=%u\n", msg->ranging_cfg.distance_ingress_mm);
+ ALOGI("NanRangingCfg distance_egress_mm=%u\n", msg->ranging_cfg.distance_egress_mm);
+ ALOGI("NanRangingAutoResponse = %u\n", msg->ranging_auto_response);
+ ALOGI("range_response = %u\n", msg->range_response_cfg.ranging_response);
+
+ ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+ if (msg->sdea_service_specific_info_len)
+ ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanTransmitFollowupRequest(NanTransmitFollowupRequest* msg)
+{
+ ALOGI("%s: Dump NanTransmitFollowupRequest msg:\n", __func__);
+ u8 i = 0;
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ ALOGI("publish_subscribe_id=%u\n", msg->publish_subscribe_id);
+ ALOGI("requestor_instance_id=%u\n", msg->requestor_instance_id);
+ ALOGI("addr=" MACSTR "\n", MAC2STR(msg->addr));
+ ALOGI("priority=%u\n", msg->priority);
+ ALOGI("dw_or_faw=%u\n", msg->dw_or_faw);
+ ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+ if (msg->service_specific_info_len)
+ ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+ ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+ ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+ if (msg->sdea_service_specific_info_len)
+ ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanDataPathInitiatorRequest(NanDataPathInitiatorRequest* msg)
+{
+ ALOGI("%s: Dump NanDataPathInitiatorRequest msg:\n", __func__);
+
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("requestor_instance_id=%d\n", msg->requestor_instance_id);
+ ALOGI("channel_request_type=%d\n", msg->channel_request_type);
+ ALOGI("channel=%u\n", msg->channel);
+ ALOGI("peer_disc_mac_addr=" MACSTR "\n", MAC2STR(msg->peer_disc_mac_addr));
+ ALOGI("ndp_iface=%s\n", msg->ndp_iface);
+ ALOGI("ndp_cfg: security_cfg =%u\n", msg->ndp_cfg.security_cfg);
+ ALOGI("ndp_cfg: qos_cfg=%u\n", msg->ndp_cfg.qos_cfg);
+ ALOGI("dp app info len=%u\n", msg->app_info.ndp_app_info_len);
+ if (msg->app_info.ndp_app_info_len) {
+ prhex("dp app info=: ", (u8*)msg->app_info.ndp_app_info,
+ msg->app_info.ndp_app_info_len);
+ }
+ ALOGI("cipher_type=%u\n", msg->cipher_type);
+ ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+ ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+ ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+ if (msg->service_name_len) {
+ ALOGI("service_name=%s\n", msg->service_name);
+ }
+ return WIFI_SUCCESS;
+}
+
+static int dump_NanDataPathIndicationResponse(NanDataPathIndicationResponse* msg)
+{
+ ALOGI("%s: Dump NanDataPathIndicationResponse msg:\n", __func__);
+
+ if (msg == NULL) {
+ ALOGE("Invalid msg\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("ndp_instance_id=%d\n", msg->ndp_instance_id);
+ ALOGI("ndp_iface=%s\n", msg->ndp_iface);
+ ALOGI("ndp_cfg: security_cfg =%u\n", msg->ndp_cfg.security_cfg);
+ ALOGI("response code =%u\n", msg->rsp_code);
+ ALOGI("ndp_cfg: qos_cfg=%u\n", msg->ndp_cfg.qos_cfg);
+ ALOGI("dp app info len=%u\n", msg->app_info.ndp_app_info_len);
+ if (msg->app_info.ndp_app_info_len) {
+ prhex("dp app info=: ", (u8*)msg->app_info.ndp_app_info,
+ msg->app_info.ndp_app_info_len);
+ }
+ ALOGI("cipher_type=%u\n", msg->cipher_type);
+ ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+ ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+ ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+ ALOGI("service_name_len=%u\n", msg->service_name_len);
+ if (msg->service_name_len) {
+ ALOGI("service_name=%s\n", msg->service_name);
+ }
+ return WIFI_SUCCESS;
+}
+#endif /* CONFIG_BRCM */
+
+void nan_reset_dbg_counters()
+{
+ memset(&counters, 0, sizeof(counters));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+wifi_error nan_enable_request(transaction_id id,
+ wifi_interface_handle iface, NanEnableRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_ENABLE;
+
+ ALOGI("Enabling Nan, Handle = %p\n", handle);
+
+#ifdef CONFIG_BRCM
+ // check up nan enable params from Nan manager level
+ dump_NanEnableRequest(msg);
+#endif /* CONFIG_BRCM */
+ nan_reset_dbg_counters();
+ /* XXX: WAR posting async enable response */
+ //NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+ NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ cmd->setType(cmdType);
+ cmd->setId(id);
+ cmd->setMsg((void *)msg);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ //cmd->releaseRef();
+ return ret;
+}
+
+void nan_dump_dbg_counters()
+{
+ ALOGI("Num Data Path Requests %d\n", counters.dp_req);
+ ALOGI("Num Data Path Responses %d\n", counters.dp_resp);
+ ALOGI("Num Data Path Confirms %d\n", counters.dp_confirm_evt);
+ ALOGI("Num Data Path Request Events %d\n", counters.dp_req_evt);
+ ALOGI("Num Transmit Requests %d\n", counters.transmit_req);
+ ALOGI("Num Followup Transmits Recvd %d\n", counters.transmit_recv);
+ ALOGI("Num Transmit Success %d\n", counters.transmit_txs);
+}
+
+wifi_error nan_disable_request(transaction_id id,
+ wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_DISABLE;
+ wifi_error ret = WIFI_SUCCESS;
+
+ ALOGI("Disabling Nan, Handle = %p\n", handle);
+ NanMacControl *cmd = new NanMacControl(iface, id, NULL, cmdType);
+ NanMacControl *mac_prim = (NanMacControl*)(info.nan_mac_control);
+
+ if (id != NAN_MAC_INVALID_TRANSID) {
+ ALOGE("Disable NAN MAC transId= %d\n", id);
+ mac_prim->setId(id);
+ } else {
+ ALOGE("Invalid transId= %d cur= %d\n", id, mac_prim->getId());
+ }
+
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ nan_dump_dbg_counters();
+
+ ret = (wifi_error)cmd->cancel();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("cancel failed, error = %d\n", ret);
+ } else {
+ ALOGE("Deinitializing Nan Mac Control = %p\n", cmd);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error nan_publish_request(transaction_id id,
+ wifi_interface_handle iface, NanPublishRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+
+ ALOGI("Publish Nan, halHandle = %p\n", handle);
+#ifdef CONFIG_BRCM
+ dump_NanPublishRequest(msg);
+#endif /* CONFIG_BRCM */
+
+ NanRequestType cmdType = NAN_REQUEST_PUBLISH;
+ NanDiscEnginePrimitive *cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+/* Function to send NAN request to the wifi driver */
+wifi_error nan_publish_cancel_request(transaction_id id,
+ wifi_interface_handle iface, NanPublishCancelRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanDiscEnginePrimitive *cmd;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_PUBLISH_CANCEL;
+
+ ALOGE("Cancellling publish request %d\n", msg->publish_id);
+ cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+ cmd->setInstId(msg->publish_id);
+ cmd->setType(cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+/* Function to send NAN request to the wifi driver */
+wifi_error nan_subscribe_request(transaction_id id,
+ wifi_interface_handle iface, NanSubscribeRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ ALOGI("Subscribe Nan, halHandle = %p handle[%d]\n", handle, msg->subscribe_id);
+ NanDiscEnginePrimitive *cmd;
+#ifdef CONFIG_BRCM
+ dump_NanSubscribeRequest(msg);
+#endif /* CONFIG_BRCM */
+
+ NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE;
+ cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+
+}
+
+/* Function to send NAN request to the wifi driver.*/
+wifi_error nan_subscribe_cancel_request(transaction_id id,
+ wifi_interface_handle iface, NanSubscribeCancelRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanDiscEnginePrimitive *cmd;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE_CANCEL;
+
+ ALOGE("creating new instance + %d\n", msg->subscribe_id);
+ cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+ cmd->setInstId(msg->subscribe_id);
+ cmd->setType(cmdType);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+
+ return ret;
+}
+
+#ifdef NAN_CLUSTER_MERGE
+/* Function to send NAN cluster merge enable/disable request to the wifi driver.*/
+wifi_error nan_enable_cluster_merge_request(transaction_id id,
+ wifi_interface_handle iface, NanEnableMergeRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_ENABLE_MERGE;
+
+ NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ cmd->setType(cmdType);
+ cmd->setId(id);
+ cmd->setMsg((void *)msg);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s :enable nan cluster merge failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+
+ return ret;
+}
+#endif /* NAN_CLUSTER_MERGE */
+
+/* Function to send nan transmit followup Request to the wifi driver.*/
+wifi_error nan_transmit_followup_request(transaction_id id,
+ wifi_interface_handle iface, NanTransmitFollowupRequest* msg)
+{
+ NanDiscEnginePrimitive *cmd = NULL;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_TRANSMIT_FOLLOWUP;
+ wifi_error ret = WIFI_SUCCESS;
+
+#ifdef CONFIG_BRCM
+ dump_NanTransmitFollowupRequest(msg);
+#endif /* CONFIG_BRCM */
+ counters.transmit_req++;
+ cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ cmd->setTransactionId(id);
+
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ 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_handle handle = getWifiHandle(iface);
+
+ ALOGI("Nan Stats, halHandle = %p", handle);
+ NanRequestType cmdType = NAN_REQUEST_STATS;
+
+#ifdef NOT_SUPPORTED
+ wifi_error ret = WIFI_SUCCESS;
+ NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+#else
+ return WIFI_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+/* 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 = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_REQUEST_CONFIG;
+
+ ALOGI("Configuring Nan, halHandle = %p\n", handle);
+
+#ifdef CONFIG_BRCM
+ /* check up nan config params from Nan manager level */
+ dump_NanConfigRequestRequest(msg);
+#endif /* CONFIG_BRCM */
+
+ NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ cmd->setType(cmdType);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("start failed, error = %d\n", ret);
+ } else {
+ ALOGE("Initializing Nan Mac Control = %p\n", cmd);
+ }
+ cmd->releaseRef();
+ 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_handle handle = getWifiHandle(iface);
+
+ ALOGI("Nan TCA, halHandle = %p", handle);
+ NanRequestType cmdType = NAN_REQUEST_TCA;
+
+#ifdef NOT_SUPPORTED
+ wifi_error ret = WIFI_SUCCESS;
+ NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+#else
+ return WIFI_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+wifi_error nan_beacon_sdf_payload_request(transaction_id id,
+ wifi_interface_handle iface, NanBeaconSdfPayloadRequest* msg)
+{
+ ALOGI("Nan Beacon Sdf Payload Request");
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error nan_get_capabilities(transaction_id id, wifi_interface_handle iface)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ ALOGI("Get Nan Capabilties, id=%d, halHandle=%p\n", id, handle);
+
+ NanRequestType cmdType = NAN_REQUEST_GET_CAPABILTIES;
+ NanDiscEnginePrimitive *cmd = new NanDiscEnginePrimitive(iface, id, NULL, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+wifi_error nan_check_dhd_hal_version(wifi_interface_handle iface,
+ wifi_handle handle)
+{
+ NanRequestType cmdType = NAN_VERSION_INFO;
+ NanMacControl *cmd = new NanMacControl(iface, 0, NULL, cmdType);
+ wifi_error ret = WIFI_SUCCESS;
+ u32 version;
+
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ cmd->setType(cmdType);
+
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGI("\nVersion subcmd failed ret = %x\n", ret);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto done;
+ }
+ version = cmd->getVersion();
+ /* check if version handled..can support multiple versions */
+ if (version == NAN_HAL_VERSION_1) {
+ ALOGI("\nGot the supported version %d\n", version);
+ current_dhd_hal_ver = version;
+ ret = WIFI_SUCCESS;
+ goto done;
+ } else {
+ ALOGI("\nGot the unsupported version %d\n", version);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto done;
+ }
+done:
+ cmd->releaseRef();
+ return ret;
+}
+wifi_error nan_deinit_handler()
+{
+ if (info.nan_mac_control) {
+ /* register for Nan vendor events with info mac class*/
+ NanMacControl *cmd_event = (NanMacControl*)(info.nan_mac_control);
+ cmd_event->unRegisterNanVendorEvents();
+ delete (NanMacControl*)info.nan_mac_control;
+ info.nan_mac_control = NULL;
+ }
+ if (info.nan_disc_control) {
+ delete (NanDiscEnginePrimitive*)info.nan_disc_control;
+ info.nan_disc_control = NULL;
+ }
+ if (info.nan_dp_control) {
+ delete (NanDataPathPrimitive*)info.nan_dp_control;
+ info.nan_dp_control = NULL;
+ }
+ if (NAN_HANDLE(info)) {
+ delete GET_NAN_HANDLE(info);
+ NAN_HANDLE(info) = NULL;
+ }
+ return WIFI_SUCCESS;
+}
+wifi_error nan_register_handler(wifi_interface_handle iface,
+ NanCallbackHandler handlers)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ if (NAN_HANDLE(info)) {
+ /* cleanup and re-register */
+ nan_deinit_handler();
+ }
+ ALOGI("\nChecking version compat\n");
+ /* checking version compat b/w DHD and HAL */
+ if (nan_check_dhd_hal_version(iface, handle) != WIFI_SUCCESS) {
+ ALOGE("\n Get version failed..check DHD\n");
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ memset(&info, 0, sizeof(info));
+ NAN_HANDLE(info) = new NanHandle(handle, handlers);
+ info.nan_mac_control =
+ (void*)new NanMacControl(iface, 0, NULL, NAN_REQUEST_LAST);
+ NULL_CHECK_RETURN(info.nan_mac_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ info.nan_disc_control =
+ (void*)new NanDiscEnginePrimitive(iface, 0, NULL, NAN_REQUEST_LAST);
+ NULL_CHECK_RETURN(info.nan_disc_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ info.nan_dp_control =
+ (void*)new NanDataPathPrimitive(iface, 0, NULL, NAN_REQUEST_LAST);
+ NULL_CHECK_RETURN(info.nan_dp_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ /* register for Nan vendor events with info mac class*/
+ NanMacControl *cmd_event = (NanMacControl*)(info.nan_mac_control);
+ cmd_event->registerNanVendorEvents();
+ return WIFI_SUCCESS;
+}
+
+wifi_error nan_get_version(wifi_handle handle, NanVersion* version)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ if (version) {
+ *version = (NAN_MAJOR_REL_VERSION << 16 | NAN_MINOR_REL_VERSION << 8 |
+ NAN_PATCH_REL_VERSION);
+ } else {
+ ret = WIFI_ERROR_INVALID_ARGS;
+ }
+
+ return ret;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanEventCap : public WifiCommand
+{
+ public:
+ NanEventCap(wifi_interface_handle iface, int id)
+ : WifiCommand("NanCommand", iface, id)
+ {}
+
+ int start()
+ {
+ registerNanVendorEvents();
+ return WIFI_SUCCESS;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ return NL_SKIP;
+ }
+ void unRegisterNanVendorEvents()
+ {
+ int i = 0;
+ for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+ unregisterVendorHandler(GOOGLE_OUI, i);
+ }
+ unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ }
+ void registerNanVendorEvents()
+ {
+ int i = 0;
+ for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+ registerVendorHandler(GOOGLE_OUI, i);
+ }
+ registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ }
+
+ int handleEvent(WifiEvent& event) {
+ int cmd = event.get_vendor_subcmd();
+ u16 attr_type;
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+ switch(cmd) {
+ case NAN_EVENT_DE_EVENT: {
+ u16 attr_type;
+ NanDiscEngEventInd de_event;
+ memset(&de_event, 0, sizeof(NanDiscEngEventInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_CLUSTER_ID) {
+ memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("cluster id = " MACSTR "\n", MAC2STR(de_event.data.cluster.addr));
+ } else if (attr_type == NAN_ATTRIBUTE_ENABLE_STATUS) {
+ ALOGI("nan enable status = %u\n", it.get_u16());
+ } else if (attr_type == NAN_ATTRIBUTE_JOIN_STATUS) {
+ ALOGI("nan joined status = %u\n", it.get_u16());
+ } else if (attr_type == NAN_ATTRIBUTE_DE_EVENT_TYPE) {
+ u8 de_type = it.get_u8();
+ ALOGI("nan de event type = %u\n", de_type);
+ if (de_type == NAN_EVENT_IFACE) {
+ de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ ALOGI("received NAN_EVENT_ID_DISC_MAC_ADDR event\n");
+ } else if (de_type == NAN_EVENT_START) {
+ de_event.event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+ ALOGI("received NAN cluster started event\n");
+ } else if (de_type == NAN_EVENT_JOIN) {
+ /* To be deprecated */
+ de_event.event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+ ALOGI("received join event\n");
+ } else if (de_type == NAN_EVENT_ROLE_CHANGE) {
+ ALOGI("received device role change event\n");
+ } else if (de_type == NAN_EVENT_MERGE) {
+ ALOGI("received Merge Event\n");
+ } else {
+ ALOGI("received unknown DE event, [%d]\n", de_type);
+ }
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ memcpy(mNmi, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Primary discovery mac address = " MACSTR "\n",
+ MAC2STR(mNmi));
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+ break;
+ }
+ case NAN_EVENT_DISABLED: {
+ ALOGI("Received NAN_EVENT_DISABLED\n");
+ NanDisabledInd disabled_ind;
+ memset(&disabled_ind, 0, sizeof(NanDisabledInd));
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ disabled_ind.reason = (NanStatusType)it.get_u8();
+ ALOGI("Nan Disable:status %u", disabled_ind.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(disabled_ind.nan_reason, it.get_data(),
+ sizeof(disabled_ind.nan_reason));
+ ALOGI("nan disable reason: %s", disabled_ind.nan_reason);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDisabled(&disabled_ind);
+ unRegisterNanVendorEvents();
+ break;
+ }
+ case NAN_EVENT_PUBLISH_TERMINATED: {
+ ALOGI("Received NAN_EVENT_PUBLISH_TERMINATED\n");
+ NanPublishTerminatedInd pub_term_event;
+ memset(&pub_term_event, 0, sizeof(NanPublishTerminatedInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ pub_term_event.publish_id = it.get_u16();
+ ALOGI("pub id %u", pub_term_event.publish_id);
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ pub_term_event.reason = (NanStatusType)it.get_u8();
+ ALOGI("pub termination status %u", pub_term_event.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(pub_term_event.nan_reason, it.get_data(),
+ sizeof(pub_term_event.nan_reason));
+ ALOGI("Pub termination nan reason: %s", pub_term_event.nan_reason);
+ } else {
+ ALOGE("Unknown attr\n");
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventPublishTerminated(&pub_term_event);
+ break;
+ }
+ case NAN_EVENT_SUBSCRIBE_MATCH: {
+ NanMatchInd subscribe_event;
+ memset(&subscribe_event, 0, sizeof(NanMatchInd));
+ ALOGI("Received NAN_EVENT_SUBSCRIBE_MATCH\n");
+
+ /* By default FW is unable to cache this match */
+ subscribe_event.out_of_resource_flag = true;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ ALOGI("sub id: %u", it.get_u16());
+ subscribe_event.publish_subscribe_id = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ ALOGI("pub id %u", it.get_u32());
+ subscribe_event.requestor_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("publisher mac: " MACSTR, MAC2STR(subscribe_event.addr));
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("svc length: %d", it.get_u16());
+ subscribe_event.service_specific_info_len = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(subscribe_event.service_specific_info, it.get_data(),
+ subscribe_event.service_specific_info_len);
+ subscribe_event.service_specific_info
+ [subscribe_event.service_specific_info_len] = '\0';
+ ALOGI("service info: %s", subscribe_event.service_specific_info);
+
+ } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
+ ALOGI("sdf match filter length: %d", subscribe_event.sdf_match_filter_len);
+ subscribe_event.sdf_match_filter_len = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER) {
+ memcpy(subscribe_event.sdf_match_filter, it.get_data(),
+ subscribe_event.sdf_match_filter_len);
+ subscribe_event.sdf_match_filter
+ [subscribe_event.sdf_match_filter_len] = '\0';
+ ALOGI("sdf match filter: %s", subscribe_event.sdf_match_filter);
+ } else if (attr_type == NAN_ATTRIBUTE_CIPHER_SUITE_TYPE) {
+ ALOGI("Peer Cipher suite type: %u", it.get_u8());
+ subscribe_event.peer_cipher_type = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
+ ALOGI("scid length %d", it.get_u32());
+ subscribe_event.scid_len= it.get_u32();
+ } else if (attr_type == NAN_ATTRIBUTE_SCID) {
+ memcpy(subscribe_event.scid, it.get_data(),
+ subscribe_event.scid_len);
+ subscribe_event.scid
+ [subscribe_event.scid_len] = '\0';
+ ALOGI("scid: %s", subscribe_event.scid);
+ } else if (attr_type == NAN_ATTRIBUTE_RANGING_INDICATION) {
+ subscribe_event.range_info.ranging_event_type = it.get_u32();
+ ALOGI("ranging indication %d", it.get_u32());
+ } else if (attr_type == NAN_ATTRIBUTE_RANGING_RESULT) {
+ subscribe_event.range_info.range_measurement_mm = it.get_u32();
+ ALOGI("ranging result %d", it.get_u32());
+ } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+ subscribe_event.rssi_value = it.get_u8();
+ ALOGI("rssi value : %u", it.get_u8());
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("sdea svc length %d", it.get_u16());
+ subscribe_event.sdea_service_specific_info_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+ memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
+ subscribe_event.sdea_service_specific_info_len);
+ subscribe_event.sdea_service_specific_info
+ [subscribe_event.sdea_service_specific_info_len] = '\0';
+ ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
+ } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
+ ALOGI("match occurred flag: %u", it.get_u8());
+ subscribe_event.match_occured_flag = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG) {
+ ALOGI("Out of resource flag: %u", it.get_u8());
+ subscribe_event.out_of_resource_flag = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP) {
+ ALOGI("Peer config for data path needed: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.config_nan_data_path = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE) {
+ ALOGI("Data Path type: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.ndp_type = (NdpType)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_SECURITY) {
+ ALOGI("Security configuration: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.security_cfg =
+ (NanDataPathSecurityCfgStatus)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT) {
+ ALOGI("Ranging report state: %u", it.get_u8());
+ subscribe_event.peer_sdea_params.range_report = (NanRangeReport)it.get_u8();
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventMatch(&subscribe_event);
+ break;
+ }
+ case NAN_EVENT_SUBSCRIBE_UNMATCH: {
+ ALOGI("Received NAN_EVENT_SUBSCRIBE_UNMATCH\n");
+ ALOGE("%s: Not applicable yet\n", __func__);
+ break;
+ }
+ case NAN_EVENT_SUBSCRIBE_TERMINATED: {
+ NanSubscribeTerminatedInd sub_term_event;
+ memset(&sub_term_event, 0, sizeof(NanSubscribeTerminatedInd));
+ ALOGI("Received NAN_EVENT_SUBSCRIBE_TERMINATED\n");
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ sub_term_event.subscribe_id = it.get_u16();
+ ALOGI("sub id: %u", sub_term_event.subscribe_id);
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ sub_term_event.reason = (NanStatusType)it.get_u8();
+ ALOGI("sub termination status %u", sub_term_event.reason);
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(sub_term_event.nan_reason, it.get_data(),
+ sizeof(sub_term_event.nan_reason));
+ ALOGI("sub termination nan reason: %s", sub_term_event.nan_reason);
+ } else {
+ ALOGE("Unknown attr: %u\n", attr_type);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
+ break;
+ }
+ case NAN_EVENT_FOLLOWUP: {
+ NanFollowupInd followup_event;
+ memset(&followup_event, 0, sizeof(NanFollowupInd));
+ ALOGI("Received NAN_EVENT_FOLLOWUP\n");
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(followup_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+
+ } else if (attr_type == NAN_ATTRIBUTE_PEER_ID) {
+ followup_event.publish_subscribe_id = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_INST_ID) {
+ followup_event.requestor_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ followup_event.service_specific_info_len = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(followup_event.service_specific_info, it.get_data(),
+ followup_event.service_specific_info_len);
+ followup_event.service_specific_info[followup_event.service_specific_info_len] =
+ '\0';
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("sdea svc length %d", it.get_u16());
+ followup_event.sdea_service_specific_info_len = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+ memcpy(followup_event.sdea_service_specific_info, it.get_data(),
+ followup_event.sdea_service_specific_info_len);
+ followup_event.sdea_service_specific_info[followup_event.sdea_service_specific_info_len] = '\0';
+ ALOGI("sdea service info: %s", followup_event.sdea_service_specific_info);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventFollowup(&followup_event);
+ break;
+ }
+ case NAN_EVENT_SDF: {
+ ALOGI("Received NAN_EVENT_SDF:\n");
+ NanBeaconSdfPayloadInd sdfInd;
+ memset(&sdfInd, 0, sizeof(sdfInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ sdfInd.data.frame_len = it.get_u32();
+ if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
+ sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
+ }
+ ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN: 0x%x(%d)\n",
+ sdfInd.data.frame_len, sdfInd.data.frame_len);
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO\n");
+ memcpy(&sdfInd.data.frame_data, it.get_data(), sdfInd.data.frame_len);
+ prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
+ sdfInd.data.frame_len);
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventBeaconSdfPayload(&sdfInd);
+ break;
+ }
+#ifdef NOT_YET
+ case NAN_EVENT_PUBLISH_REPLIED_IND: {
+ ALOGI("Received NAN_EVENT_PUBLISH_REPLIED_IND\n");
+ NanPublishRepliedInd pub_reply_event;
+ memset(&pub_reply_event, 0, sizeof(pub_reply_event));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ ALOGI("sub id: %u", it.get_u32());
+ pub_reply_event.requestor_instance_id = it.get_u32();
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(pub_reply_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Subscriber mac: " MACSTR, MAC2STR(pub_reply_event.addr));
+ } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+ pub_reply_event.rssi_value = it.get_u8();
+ ALOGI("Received rssi value : %u", it.get_u8());
+ }
+ }
+ GET_NAN_HANDLE(info)->mHandlers.EventPublishReplied(&pub_reply_event);
+ break;
+ }
+#endif /* NOT_YET */
+ case NAN_EVENT_TCA: {
+ ALOGI("Received NAN_EVENT_TCA\n");
+ //GET_NAN_HANDLE(info)->mHandlers.EventTca(&sdfPayload);
+ break;
+ }
+ case NAN_EVENT_DATA_REQUEST: {
+ ALOGI("Received NAN_EVENT_DATA_REQUEST_INDICATION\n");
+ NanDataPathRequestInd ndp_request_event;
+ memset(&ndp_request_event, 0, sizeof(NanDataPathRequestInd));
+ u16 ndp_ind_app_info_len = 0;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ ALOGI("publish_id: %u\n", it.get_u16());
+ ndp_request_event.service_instance_id = it.get_u16();
+
+ } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+ memcpy(ndp_request_event.peer_disc_mac_addr,
+ it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("Discovery MAC addr of the peer/initiator: " MACSTR "\n",
+ MAC2STR(ndp_request_event.peer_disc_mac_addr));
+
+ } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ ALOGI("ndp id: %u\n", it.get_u32());
+ ndp_request_event.ndp_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SECURITY) {
+ ALOGI("security: %u\n", (NanDataPathSecurityCfgStatus) it.get_u8());
+ ndp_request_event.ndp_cfg.security_cfg =
+ (NanDataPathSecurityCfgStatus)it.get_u8();
+
+ } else if (attr_type == NAN_ATTRIBUTE_QOS) {
+ ALOGI("QoS: %u", (NanDataPathQosCfg)it.get_u8());
+ ndp_request_event.ndp_cfg.qos_cfg = (NanDataPathQosCfg)it.get_u8();
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("service info len: %d\n", it.get_u16());
+ ndp_ind_app_info_len = it.get_u16();
+ ndp_request_event.app_info.ndp_app_info_len = ndp_ind_app_info_len;
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(ndp_request_event.app_info.ndp_app_info,
+ it.get_data(), ndp_ind_app_info_len);
+ ndp_request_event.app_info.ndp_app_info[ndp_ind_app_info_len] = '\0';
+ ALOGI("service info: %s\n", ndp_request_event.app_info.ndp_app_info);
+
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataRequest(&ndp_request_event);
+ break;
+ }
+ case NAN_EVENT_DATA_CONFIRMATION: {
+ ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
+ NanDataPathConfirmInd ndp_create_confirmation_event;
+ memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
+ u16 ndp_conf_app_info_len = 0;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+
+ if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ ALOGI("ndp id: %u", it.get_u32());
+ ndp_create_confirmation_event.ndp_instance_id = it.get_u32();
+
+ } else if (attr_type == NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR) {
+ memcpy(ndp_create_confirmation_event.peer_ndi_mac_addr,
+ it.get_data(), NAN_MAC_ADDR_LEN);
+ ALOGI("NDI mac address of the peer: " MACSTR "\n",
+ MAC2STR(ndp_create_confirmation_event.peer_ndi_mac_addr));
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+ ALOGI("service info string len: %d\n", it.get_u16());
+ ndp_conf_app_info_len = it.get_u16();
+ ndp_create_confirmation_event.app_info.ndp_app_info_len =
+ ndp_conf_app_info_len;
+
+ } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ memcpy(ndp_create_confirmation_event.app_info.ndp_app_info, it.get_data(),
+ ndp_conf_app_info_len);
+ ndp_create_confirmation_event.app_info.ndp_app_info[ndp_conf_app_info_len] =
+ '\0';
+ ALOGI("service info string: %s\n",
+ ndp_create_confirmation_event.app_info.ndp_app_info);
+
+ } else if (attr_type == NAN_ATTRIBUTE_RSP_CODE) {
+ ALOGI("response code %u\n", (NanDataPathResponseCode) it.get_u8());
+ ndp_create_confirmation_event.rsp_code =
+ (NanDataPathResponseCode)it.get_u8();
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
+ break;
+ }
+ case NAN_EVENT_DATA_END: {
+ ALOGI("Received NAN_EVENT_DATA_END\n");
+ NanDataPathEndInd ndp_end_event;
+ memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+ u8 count = 0;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
+ ALOGI("ndp count: %u\n", it.get_u8());
+ ndp_end_event.num_ndp_instances = it.get_u8();
+ count = it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+ ALOGI("count: %u\n", count);
+ while (count) {
+ ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
+ ALOGI("ndp id: %u\n", ndp_end_event.ndp_instance_id[count-1]);
+ count -= 1;
+ }
+ } else {
+ ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+ break;
+ }
+ case NAN_EVENT_TRANSMIT_FOLLOWUP_IND: {
+ ALOGI("Received NAN_EVENT_TRANSMIT_FOLLOWUP_IND\n");
+ NanTransmitFollowupInd followup_ind;
+ memset(&followup_ind, 0, sizeof(NanTransmitFollowupInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_TRANSAC_ID) {
+ followup_ind.id = it.get_u16();
+ } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ followup_ind.reason = (NanStatusType)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+ memcpy(followup_ind.nan_reason, it.get_data(),
+ sizeof(followup_ind.nan_reason));
+ ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
+ break;
+ }
+ case NAN_EVENT_UNKNOWN:
+ ALOGI("Received NAN_EVENT_UNKNOWN\n");
+ break;
+ } // end-of-switch
+ return NL_SKIP;
+ }
+};
+
+/* To see event prints in console */
+wifi_error nan_event_check_request(transaction_id id, wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ NanEventCap *cmd = new NanEventCap(iface, id);
+ if (cmd == NULL) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return (wifi_error)cmd->start();
+}
+
+/* Create NAN Data Interface */
+wifi_error nan_data_interface_create(transaction_id id,
+ wifi_interface_handle iface, char* iface_name)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NAN_DBG_ENTER();
+
+ NanRequestType cmdType = NAN_DATA_PATH_IFACE_CREATE;
+ NanDataPathPrimitive *cmd =
+ new NanDataPathPrimitive(iface, id, (void *)iface_name, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+
+ NAN_DBG_EXIT();
+ return ret;
+}
+
+/* Delete NAN Data Interface */
+wifi_error nan_data_interface_delete(transaction_id id,
+ wifi_interface_handle iface, char* iface_name)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NAN_DBG_ENTER();
+
+ NanRequestType cmdType = NAN_DATA_PATH_IFACE_DELETE;
+ NanDataPathPrimitive *cmd =
+ new NanDataPathPrimitive(iface, id, (void *)iface_name, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+
+ NAN_DBG_EXIT();
+ return ret;
+}
+
+/* Initiate a NDP session: Initiator */
+wifi_error nan_data_request_initiator(transaction_id id,
+ wifi_interface_handle iface, NanDataPathInitiatorRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+
+ NAN_DBG_ENTER();
+ NanRequestType cmdType;
+ NanDataPathPrimitive *cmd = NULL;
+
+#ifdef CONFIG_BRCM
+ dump_NanDataPathInitiatorRequest(msg);
+#endif /* CONFIG_BRCM */
+ counters.dp_req++;
+ if (msg->service_name_len) {
+ if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
+ (char*)msg->service_name, msg->service_name_len) == 0) {
+ ALOGI("Use Hardcoded svc_hash\n");
+ msg->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(msg->service_name, NAN_OOB_INTEROP_SVC_HASH, NAN_SVC_HASH_SIZE);
+ } else {
+ u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+ ret = (wifi_error)get_svc_hash(msg->service_name, msg->service_name_len,
+ svc_hash, NAN_SVC_HASH_SIZE);
+ if (ret < 0) {
+ ALOGE("%s: Failed to get hashed svc name\n", __func__);
+ goto done;
+ }
+
+ ALOGI("Created svc_hash\n");
+ msg->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(msg->service_name, svc_hash, msg->service_name_len);
+ }
+ } else if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ NanDataPathSecInfoRequest msg_sec_info;
+ if (msg->requestor_instance_id == 0) {
+ ALOGE("Invalid Pub ID = %d, Mandatory param is missing\n", msg->requestor_instance_id);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto done;
+ } else {
+ ALOGI("Pub ID = %d, Mandatory param is present\n", msg->requestor_instance_id);
+ }
+ if (ETHER_ISNULLADDR(msg->peer_disc_mac_addr)) {
+ ALOGE("Invalid Pub NMI, Mandatory param is missing\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto done;
+ }
+
+ msg_sec_info.requestor_instance_id = msg->requestor_instance_id;
+ memcpy(msg_sec_info.peer_disc_mac_addr, msg->peer_disc_mac_addr, NAN_MAC_ADDR_LEN);
+ msg_sec_info.ndp_instance_id = 0;
+ cmdType = NAN_DATA_PATH_SEC_INFO;
+ cmd = new NanDataPathPrimitive(iface, id, (void *)&msg_sec_info, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ goto done;
+ }
+ memcpy(msg->service_name, cmd->mSvcHash, NAN_SVC_HASH_SIZE);
+ }
+ /* free old command */
+ if (cmd) {
+ cmd->releaseRef();
+ }
+ cmdType = NAN_DATA_PATH_INIT_REQUEST;
+ cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ goto done;
+ }
+done:
+ if (cmd) {
+ cmd->releaseRef();
+ }
+
+ NAN_DBG_EXIT();
+ return ret;
+}
+
+/* Response to a data indication received corresponding to a NDP session.
+ * An indication is received with a data request and the responder will send a data response
+ */
+wifi_error nan_data_indication_response(transaction_id id,
+ wifi_interface_handle iface, NanDataPathIndicationResponse* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_handle handle = getWifiHandle(iface);
+ NAN_DBG_ENTER();
+ NanRequestType cmdType;
+ u8 pub_nmi[NAN_MAC_ADDR_LEN] = {0};
+ NanDataPathPrimitive *cmd = NULL;
+
+#ifdef CONFIG_BRCM
+ dump_NanDataPathIndicationResponse(msg);
+#endif /* CONFIG_BRCM */
+ counters.dp_resp++;
+ if (msg->service_name_len) {
+ if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
+ (char*)msg->service_name, msg->service_name_len) == 0) {
+ ALOGI("Use Hardcoded svc_hash\n");
+ msg->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(msg->service_name, NAN_OOB_INTEROP_SVC_HASH, NAN_SVC_HASH_SIZE);
+ } else {
+ u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+ ret = (wifi_error)get_svc_hash(msg->service_name, msg->service_name_len,
+ svc_hash, NAN_SVC_HASH_SIZE);
+ if (ret < 0) {
+ ALOGE("%s: Failed to get hashed svc name\n", __func__);
+ goto done;
+ }
+ ALOGI("Created svc_hash\n");
+ msg->service_name_len = NAN_SVC_HASH_SIZE;
+ memcpy(msg->service_name, svc_hash, msg->service_name_len);
+ }
+ }
+ if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+ NanDataPathSecInfoRequest msg_sec_info;
+
+ if (msg->ndp_instance_id == 0) {
+ ALOGE("Invalid NDP ID, Mandatory info is not present\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto done;
+ } else {
+ ALOGI("NDP ID = %d, Mandatory info is present\n", msg->ndp_instance_id);
+ }
+ msg_sec_info.ndp_instance_id = msg->ndp_instance_id;
+ msg_sec_info.requestor_instance_id = 0;
+ cmdType = NAN_DATA_PATH_SEC_INFO;
+ cmd = new NanDataPathPrimitive(iface, id, (void *)&msg_sec_info, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+ goto done;
+ }
+
+ if (ETHER_ISNULLADDR(cmd->mPubNmi)) {
+ ALOGE("Invalid Pub NMI\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto done;
+ }
+ memcpy(pub_nmi, cmd->mPubNmi, NAN_MAC_ADDR_LEN);
+
+ if (!msg->service_name_len) {
+ if (SVCHASH_ISNULL(cmd->mSvcHash)) {
+ ALOGE("Invalid svc_hash\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto done;
+ }
+ memcpy(msg->service_name, cmd->mSvcHash, NAN_SVC_HASH_SIZE);
+ }
+ }
+ /* free old command */
+ if (cmd) {
+ cmd->releaseRef();
+ }
+ cmdType = NAN_DATA_PATH_IND_RESPONSE;
+ cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ memcpy(cmd->mPubNmi, pub_nmi, NAN_MAC_ADDR_LEN);
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ goto done;
+ }
+
+done:
+ if (cmd) {
+ cmd->releaseRef();
+ }
+ NAN_DBG_EXIT();
+ return ret;
+}
+
+/* NDL termination request: from either Initiator/Responder */
+wifi_error nan_data_end(transaction_id id,
+ wifi_interface_handle iface, NanDataPathEndRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanDataPathPrimitive *cmd;
+ wifi_handle handle = getWifiHandle(iface);
+ NanRequestType cmdType = NAN_DATA_PATH_END;
+ NAN_DBG_ENTER();
+
+ cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ NAN_DBG_EXIT();
+ return ret;
+}
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 508268e..258725c 100644..100755
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -45,13 +45,14 @@
#include "sync.h"
#define LOG_TAG "WifiHAL"
-
#include <log/log.h>
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
#include "rtt.h"
+#include "brcm_version.h"
+#include <stdio.h>
/*
BUGBUG: normally, libnl allocates ports for all connections it makes; but
being a static library, it doesn't really know how many other netlink connections
@@ -69,6 +70,7 @@
*/
#define POLL_DRIVER_DURATION_US (100000)
#define POLL_DRIVER_MAX_TIME_MS (10000)
+#define EVENT_BUF_SIZE 2048
static void internal_event_handler(wifi_handle handle, int events);
static int internal_no_seq_check(nl_msg *msg, void *arg);
@@ -91,7 +93,11 @@ typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
ANDR_WIFI_ATTRIBUTE_NODFS_SET,
ANDR_WIFI_ATTRIBUTE_COUNTRY,
- ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
+ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
+ ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE,
+ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE,
+ ANDR_WIFI_ATTRIBUTE_RANDOM_MAC,
+ ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO
// Add more attribute here
} wifi_attr_t;
@@ -211,109 +217,218 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
+ fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
fn->wifi_set_packet_filter = wifi_set_packet_filter;
+ fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
+ fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
+ fn->wifi_configure_roaming = wifi_configure_roaming;
+ fn->wifi_nan_register_handler = nan_register_handler;
+ fn->wifi_nan_enable_request = nan_enable_request;
+ fn->wifi_nan_disable_request = nan_disable_request;
+ fn->wifi_nan_publish_request = nan_publish_request;
+ fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
+ fn->wifi_nan_subscribe_request = nan_subscribe_request;
+ fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
+ fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
+ fn->wifi_nan_stats_request = nan_stats_request;
+ fn->wifi_nan_config_request = nan_config_request;
+ fn->wifi_nan_tca_request = nan_tca_request;
+ fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
+ fn->wifi_nan_get_version = nan_get_version;
+ fn->wifi_nan_get_capabilities = nan_get_capabilities;
+ fn->wifi_nan_data_interface_create = nan_data_interface_create;
+ fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
+ fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
+ fn->wifi_nan_data_indication_response = nan_data_indication_response;
+ fn->wifi_nan_data_end = nan_data_end;
+ fn->wifi_set_latency_mode = wifi_set_latency_mode;
+#ifdef NAN_CLUSTER_MERGE
+ fn->wifi_nan_enable_merge_request = nan_enable_cluster_merge_request;
+#endif /* NAN_CLUSTER_MERGE */
+ fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
+ fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+
return WIFI_SUCCESS;
}
-wifi_error wifi_initialize(wifi_handle *handle)
+hal_info *halInfo = NULL;
+wifi_error wifi_pre_initialize(void)
{
srand(getpid());
- ALOGI("Initializing wifi");
- hal_info *info = (hal_info *)malloc(sizeof(hal_info));
- if (info == NULL) {
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ wifi_error result = WIFI_SUCCESS;
+ wifi_handle handle;
+
+ ALOGE("wifi_pre_initialize");
+ ALOGE("--- HAL version: %s ---\n", HAL_VERSION);
+ halInfo = (hal_info *)malloc(sizeof(hal_info));
+ if (halInfo == NULL) {
ALOGE("Could not allocate hal_info");
return WIFI_ERROR_UNKNOWN;
}
- memset(info, 0, sizeof(*info));
+ memset(halInfo, 0, sizeof(*halInfo));
ALOGI("Creating socket");
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, halInfo->cleanup_socks) == -1) {
ALOGE("Could not create cleanup sockets");
- free(info);
+ free(halInfo);
return WIFI_ERROR_UNKNOWN;
}
struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
if (cmd_sock == NULL) {
ALOGE("Could not create handle");
- free(info);
+ free(halInfo);
return WIFI_ERROR_UNKNOWN;
}
+ /* Set the socket buffer size */
+ if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
+ ALOGE("Could not set size for cmd_sock: %s",
+ strerror(errno));
+ } else {
+ ALOGV("nl_socket_set_buffer_size successful for cmd_sock");
+ }
struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
if (event_sock == NULL) {
ALOGE("Could not create handle");
nl_socket_free(cmd_sock);
- free(info);
+ free(halInfo);
return WIFI_ERROR_UNKNOWN;
}
+ /* Set the socket buffer size */
+ if (nl_socket_set_buffer_size(event_sock, (512*1024), 0) < 0) {
+ ALOGE("Could not set size for event_sock: %s",
+ strerror(errno));
+ } else {
+ ALOGV("nl_socket_set_buffer_size successful for event_sock");
+ }
+
struct nl_cb *cb = nl_socket_get_cb(event_sock);
if (cb == NULL) {
ALOGE("Could not create handle");
nl_socket_free(cmd_sock);
nl_socket_free(event_sock);
- free(info);
+ free(halInfo);
return WIFI_ERROR_UNKNOWN;
}
- // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
- nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, halInfo);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, halInfo);
nl_cb_put(cb);
- info->cmd_sock = cmd_sock;
- info->event_sock = event_sock;
- info->clean_up = false;
- info->in_event_loop = false;
+ halInfo->cmd_sock = cmd_sock;
+ halInfo->event_sock = event_sock;
+ halInfo->clean_up = false;
+ halInfo->in_event_loop = false;
- info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
- info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
- info->num_event_cb = 0;
+ halInfo->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
+ halInfo->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
+ halInfo->num_event_cb = 0;
- info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
- info->alloc_cmd = DEFAULT_CMD_SIZE;
- info->num_cmd = 0;
+ halInfo->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
+ halInfo->alloc_cmd = DEFAULT_CMD_SIZE;
+ halInfo->num_cmd = 0;
- info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
- if (info->nl80211_family_id < 0) {
+ halInfo->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
+ if (halInfo->nl80211_family_id < 0) {
ALOGE("Could not resolve nl80211 familty id");
nl_socket_free(cmd_sock);
nl_socket_free(event_sock);
- free(info);
+ free(halInfo);
return WIFI_ERROR_UNKNOWN;
}
- pthread_mutex_init(&info->cb_lock, NULL);
+ pthread_mutex_init(&halInfo->cb_lock, NULL);
+ InitResponseLock();
- *handle = (wifi_handle) info;
+ handle = (wifi_handle) halInfo;
- if (wifi_init_interfaces(*handle) != WIFI_SUCCESS) {
+ if (wifi_init_interfaces(handle) != WIFI_SUCCESS) {
ALOGE("No wifi interface found");
nl_socket_free(cmd_sock);
nl_socket_free(event_sock);
- pthread_mutex_destroy(&info->cb_lock);
- free(info);
+ pthread_mutex_destroy(&halInfo->cb_lock);
+ free(halInfo);
return WIFI_ERROR_NOT_AVAILABLE;
}
- if ((wifi_add_membership(*handle, "scan") < 0) ||
- (wifi_add_membership(*handle, "mlme") < 0) ||
- (wifi_add_membership(*handle, "regulatory") < 0) ||
- (wifi_add_membership(*handle, "vendor") < 0)) {
+ if ((wifi_add_membership(handle, "scan") < 0) ||
+ (wifi_add_membership(handle, "mlme") < 0) ||
+ (wifi_add_membership(handle, "regulatory") < 0) ||
+ (wifi_add_membership(handle, "vendor") < 0)) {
ALOGE("Add membership failed");
nl_socket_free(cmd_sock);
nl_socket_free(event_sock);
- pthread_mutex_destroy(&info->cb_lock);
- free(info);
+ pthread_mutex_destroy(&halInfo->cb_lock);
+ free(halInfo);
return WIFI_ERROR_NOT_AVAILABLE;
}
- // ALOGI("Found %d interfaces", info->num_interfaces);
-
ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)halInfo, ifaceHandles, numIfaceHandles);
+
+ if (wlan0Handle != NULL) {
+ ALOGE("Calling preInit");
+ if (!get_halutil_mode()) {
+ result = wifi_hal_preInit(wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_hal_preInit failed");
+ }
+ }
+ }
+
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_initialize(wifi_handle *handle)
+{
+
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ wifi_error result = WIFI_SUCCESS;
+
+ ALOGE("wifi_initialize");
+
+ if (halInfo == NULL) {
+ result = wifi_pre_initialize();
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_initialize wifi_pre_initialize failed");
+ return result;
+ } else {
+ ALOGE("wifi_initialize wifi_pre_initialize succeeded");
+ }
+ }
+
+ *handle = (wifi_handle) halInfo;
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)halInfo, ifaceHandles, numIfaceHandles);
+
+ if (wlan0Handle != NULL) {
+ ALOGE("Calling Hal_init");
+ if (!get_halutil_mode()) {
+ result = wifi_start_hal(wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_start_hal failed");
+ }
+#ifdef FILE_DUMP
+ else {
+ ALOGE("Calling start file dump");
+ result = wifi_start_file_dump(wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_start_file_dump failed");
+ }
+ }
+#endif /* FILE_DUMP */
+ }
+ } else {
+ ALOGI("Not Calling set alert handler as global_iface is NULL");
+ }
return WIFI_SUCCESS;
}
@@ -327,6 +442,7 @@ wifi_error wifi_wait_for_driver_ready(void)
do {
if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
fclose(fd);
+ wifi_pre_initialize();
return WIFI_SUCCESS;
}
usleep(POLL_DRIVER_DURATION_US);
@@ -360,7 +476,10 @@ static void internal_cleaned_up_handler(wifi_handle handle)
hal_info *info = getHalInfo(handle);
wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
+ ALOGI("internal clean up");
+
if (info->cmd_sock != 0) {
+ ALOGI("cmd_sock non null. clean up");
close(info->cleanup_socks[0]);
close(info->cleanup_socks[1]);
nl_socket_free(info->cmd_sock);
@@ -369,19 +488,57 @@ static void internal_cleaned_up_handler(wifi_handle handle)
info->event_sock = NULL;
}
- (*cleaned_up_handler)(handle);
+ if (cleaned_up_handler) {
+ ALOGI("cleanup_handler cb");
+ (*cleaned_up_handler)(handle);
+ } else {
+ ALOGI("!! clean up handler is null!!");
+ }
+ DestroyResponseLock();
pthread_mutex_destroy(&info->cb_lock);
free(info);
ALOGI("Internal cleanup completed");
}
+void wifi_internal_module_cleanup()
+{
+ nan_deinit_handler();
+}
void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
{
hal_info *info = getHalInfo(handle);
char buf[64];
+ wifi_error result;
+
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
info->cleaned_up_handler = handler;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle) info, ifaceHandles, numIfaceHandles);
+
+ if (wlan0Handle != NULL) {
+ ALOGE("Calling hal cleanup");
+ if (!get_halutil_mode()) {
+ result = wifi_stop_hal(wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_stop_hal failed");
+ }
+ }
+
+#ifdef FILE_DUMP
+ ALOGE("Calling stop file dump");
+ result = wifi_stop_file_dump(wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("wifi_stop_file_dump failed");
+ }
+#endif /* FILE_DUMP */
+ } else {
+ ALOGE("Not cleaning up hal as global_iface is NULL");
+ }
+
if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
// As a fallback set the cleanup flag to TRUE
ALOGE("could not write to the cleanup socket");
@@ -402,16 +559,28 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
}
}
info->clean_up = true;
+ wifi_internal_module_cleanup();
+ ALOGI("wifi nan internal clean up done");
pthread_mutex_lock(&info->cb_lock);
int bad_commands = 0;
+ ALOGI("event_cb callbacks left: %d ", info->num_event_cb);
for (int i = 0; i < info->num_event_cb; i++) {
+ ALOGI("event_cb cleanup. index:%d", i);
cb_info *cbi = &(info->event_cb[i]);
+ if (!cbi) {
+ ALOGE("cbi null for index %d", i);
+ continue;
+ }
+ ALOGI("event_cb cleanup. vendor cmd:%d sub_cmd:%d", cbi->vendor_id, cbi->vendor_subcmd);
WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
- ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
+ if (cmd != NULL) {
+ ALOGI("Command left in event_cb %p", cmd);
+ }
}
+ ALOGI("Check bad commands: num_cmd:%d bad_commands:%d", info->num_cmd, bad_commands);
while (info->num_cmd > bad_commands) {
int num_cmd = info->num_cmd;
cmd_info *cmdi = &(info->cmd[bad_commands]);
@@ -432,11 +601,16 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
for (int i = 0; i < info->num_event_cb; i++) {
cb_info *cbi = &(info->event_cb[i]);
+ if (!cbi) {
+ ALOGE("cbi null for index %d", i);
+ continue;
+ }
WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
ALOGE("Leaked command %p", cmd);
}
pthread_mutex_unlock(&info->cb_lock);
internal_cleaned_up_handler(handle);
+ ALOGE("wifi_clean_up done");
}
static int internal_pollin_handler(wifi_handle handle)
@@ -671,6 +845,10 @@ public:
: WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
{
mOui = scan_oui;
+ fset = NULL;
+ feature_matrix = NULL;
+ fm_size = NULL;
+ set_size_max = 0;
}
int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
@@ -820,7 +998,7 @@ public:
return result;
}
ALOGI("Successfully set RSSI monitoring");
- registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ result = registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
if (result < 0) {
@@ -902,6 +1080,8 @@ class AndroidPktFilterCommand : public WifiCommand {
mVersion(version), mMaxLen(max_len),
mReqType(GET_APF_CAPABILITIES)
{
+ mProgram = NULL;
+ mProgramLen = 0;
}
AndroidPktFilterCommand(wifi_interface_handle handle,
@@ -910,6 +1090,8 @@ class AndroidPktFilterCommand : public WifiCommand {
mProgram(program), mProgramLen(len),
mReqType(SET_APF_PROGRAM)
{
+ mVersion = NULL;
+ mMaxLen = NULL;
}
int createRequest(WifiRequest& request) {
@@ -931,20 +1113,21 @@ class AndroidPktFilterCommand : public WifiCommand {
NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
if (result < 0) {
+ delete[] program;
return result;
}
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
if (result < 0) {
- return result;
+ goto exit;
}
memcpy(program, mProgram, mProgramLen);
result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
if (result < 0) {
- return result;
+ goto exit;
}
- request.attr_end(data);
+exit: request.attr_end(data);
delete[] program;
return result;
}
@@ -1066,8 +1249,7 @@ private:
public:
GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
feature_set set_matrix[], int *size, int max_size)
- : WifiCommand("GetFeatureSetCommand", handle, 0)
- {
+ : WifiCommand("GetFeatureSetCommand", handle, 0) {
feature_type = feature;
fset = set;
feature_matrix = set_matrix;
@@ -1154,6 +1336,41 @@ protected:
};
+class SetLatencyModeCommand : public WifiCommand {
+private:
+ u32 mLatencyMode;
+public:
+ SetLatencyModeCommand(wifi_interface_handle handle, u32 LatencyMode)
+ : WifiCommand("SetLatencyModeCommand", handle, 0) {
+ mLatencyMode = LatencyMode;
+ }
+
+ virtual int create() {
+ int ret;
+
+ /* Check for invalid latency Mode */
+ if ((mLatencyMode != WIFI_LATENCY_MODE_NORMAL) &&
+ (mLatencyMode != WIFI_LATENCY_MODE_LOW)) {
+ ALOGE("SetLatencyModeCommand: Invalid mode: %d", mLatencyMode);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_LATENCY_MODE);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_LATENCY_MODE, mLatencyMode);
+ if (ret < 0) {
+ return ret;
+ }
+
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
{
GetMulticastIdCommand cmd(handle, name, group);
@@ -1168,7 +1385,7 @@ static int wifi_get_multicast_id(wifi_handle handle, const char *name, const cha
static bool is_wifi_interface(const char *name)
{
- if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
+ if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "swlan", 5) != 0 && strncmp(name, "p2p", 3) != 0) {
/* not a wifi interface; ignore it */
return false;
} else {
@@ -1178,7 +1395,7 @@ static bool is_wifi_interface(const char *name)
static int get_interface(const char *name, interface_info *info)
{
- strcpy(info->name, name);
+ strlcpy(info->name, name, sizeof(info->name));
info->id = if_nametoindex(name);
// ALOGI("found an interface : %s, id = %d", name, info->id);
return WIFI_SUCCESS;
@@ -1213,6 +1430,11 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
return WIFI_ERROR_UNKNOWN;
info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
+ if (!info->interfaces) {
+ info->num_interfaces = 0;
+ closedir(d);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
int i = 0;
while ((de = readdir(d))) {
@@ -1220,6 +1442,12 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
continue;
if (is_wifi_interface(de->d_name)) {
interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
+ if (!ifinfo) {
+ free(info->interfaces);
+ info->num_interfaces = 0;
+ closedir(d);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
free(ifinfo);
continue;
@@ -1246,10 +1474,30 @@ wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle *
return WIFI_SUCCESS;
}
+wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_handle *ifaceHandles, int numIfaceHandles)
+{
+ char buf[EVENT_BUF_SIZE];
+ wifi_interface_handle wlan0Handle;
+ wifi_error res = wifi_get_ifaces((wifi_handle)info, &numIfaceHandles, &ifaceHandles);
+ if (res < 0) {
+ return NULL;
+ }
+ for (int i = 0; i < numIfaceHandles; i++) {
+ if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
+ if (strcmp(buf, "wlan0") == 0) {
+ ALOGI("found interface %s\n", buf);
+ wlan0Handle = ifaceHandles[i];
+ return wlan0Handle;
+ }
+ }
+ }
+ return NULL;
+}
wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
{
interface_info *info = (interface_info *)handle;
- strcpy(name, info->name);
+ strncpy(name, info->name, (IFNAMSIZ));
+ name[IFNAMSIZ - 1] = '\0';
return WIFI_SUCCESS;
}
@@ -1356,5 +1604,89 @@ static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 ena
SetNdoffloadCommand command(handle, enable);
return (wifi_error) command.requestResponse();
}
+wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode)
+{
+ ALOGD("Setting Wifi Latency mode, halHandle = %p LatencyMode = %d\n", handle, mode);
+ SetLatencyModeCommand command(handle, mode);
+ return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////
+class TxPowerScenario : public WifiCommand {
+ wifi_power_scenario mScenario;
+public:
+ // constructor for tx power scenario setting
+ TxPowerScenario(wifi_interface_handle handle, wifi_power_scenario scenario)
+ : WifiCommand("TxPowerScenario", handle, 0), mScenario(scenario)
+ {
+ mScenario = scenario;
+ }
+
+ // constructor for tx power scenario resetting
+ TxPowerScenario(wifi_interface_handle handle)
+ : WifiCommand("TxPowerScenario", handle, 0)
+ {
+ mScenario = WIFI_POWER_SCENARIO_DEFAULT;
+ }
+
+ int createRequest(WifiRequest& request, int subcmd, wifi_power_scenario mScenario) {
+ int result = request.create(GOOGLE_OUI, subcmd);
+ if (result < 0) {
+ return result;
+ }
+
+ if ((mScenario <= WIFI_POWER_SCENARIO_INVALID) ||
+ (mScenario > WIFI_POWER_SCENARIO_ON_BODY_BT)) {
+ ALOGE("Unsupported tx power value:%d\n", mScenario);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_s8(ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO, mScenario);
+ if (result < 0) {
+ ALOGE("Failed to put tx power scenario request; result = %d", result);
+ return result;
+ }
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start(wifi_power_scenario mScenario) {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, WIFI_SUBCMD_TX_POWER_SCENARIO, mScenario);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to send tx power scenario; result = %d", result);
+ }
+ return result;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+
+wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, wifi_power_scenario scenario)
+{
+ ALOGE("wifi_select_tx_power_scenario");
+ TxPowerScenario command(handle);
+ return (wifi_error)command.start(scenario);
+}
+
+wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
+{
+ wifi_power_scenario scenario = WIFI_POWER_SCENARIO_DEFAULT;
+ ALOGE("wifi_reset_tx_power_scenario");
+ TxPowerScenario command(handle);
+ return (wifi_error)command.start(scenario);
+}
/////////////////////////////////////////////////////////////////////////////
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index 7a38883..e35bf9b 100644..100755
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -33,6 +33,8 @@
#include <netlink/socket.h>
#include <netlink-private/object-api.h>
#include <netlink-private/types.h>
+#include <unistd.h>
+
#include "nl80211_copy.h"
#include "sync.h"
@@ -44,7 +46,10 @@
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
+#include "brcm_version.h"
+#define WIFI_HAL_EVENT_SOCK_PORT 645
+#define ARRAYSIZE(a) (u8)(sizeof(a) / sizeof(a[0]))
typedef enum {
LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
LOGGER_TRIGGER_MEM_DUMP,
@@ -59,6 +64,12 @@ typedef enum {
LOGGER_START_PKT_FATE_MONITORING,
LOGGER_GET_TX_PKT_FATES,
LOGGER_GET_RX_PKT_FATES,
+ LOGGER_GET_WAKE_REASON_STATS,
+ LOGGER_DEBUG_GET_DUMP,
+ LOGGER_FILE_DUMP_DONE_IND,
+ LOGGER_SET_HAL_START,
+ LOGGER_HAL_STOP,
+ LOGGER_SET_HAL_PID
} DEBUG_SUB_COMMAND;
typedef enum {
@@ -72,7 +83,7 @@ typedef enum {
LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
LOGGER_ATTRIBUTE_FW_DUMP_LEN,
LOGGER_ATTRIBUTE_FW_DUMP_DATA,
- // LOGGER_ATTRIBUTE_FW_ERR_CODE,
+ LOGGER_ATTRIBUTE_FW_ERR_CODE,
LOGGER_ATTRIBUTE_RING_DATA,
LOGGER_ATTRIBUTE_RING_STATUS,
LOGGER_ATTRIBUTE_RING_NUM,
@@ -105,6 +116,37 @@ typedef enum {
RX_PACKET_FATE,
} PktFateReqType;
+enum wake_stat_attributes {
+ WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
+ WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
+ WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
+ WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
+ WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
+ WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
+ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
+ WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
+ WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
+ WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
+ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
+ WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
+ WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
+ WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
+ WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
+ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
+ WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
+ WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
+};
+
+typedef enum {
+ SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
+ SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
+ SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
+} SET_HAL_START_ATTRIBUTE;
+
+#define HAL_START_REQUEST_ID 2
///////////////////////////////////////////////////////////////////////////////
class DebugCommand : public WifiCommand
@@ -129,26 +171,62 @@ public:
: WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
(cmdType)
{
+ mNumRings = NULL;
+ mStatus = NULL;
+ mSupport = NULL;
+ mVerboseLevel = 0;
+ mFlags = 0;
+ mMaxIntervalSec = 0;
+ mMinDataSize = 0;
+ mRingName = NULL;
memset(mBuff, 0, *mBuffSize);
}
// constructor for ring data
DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
: WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
- { }
+ {
+ mBuff = NULL;
+ mBuffSize = NULL;
+ mNumRings = NULL;
+ mStatus = NULL;
+ mSupport = NULL;
+ mVerboseLevel = 0;
+ mFlags = 0;
+ mMaxIntervalSec = 0;
+ mMinDataSize = 0;
+ }
// constructor for ring status
DebugCommand(wifi_interface_handle iface, u32 *num_rings,
wifi_ring_buffer_status *status, GetCmdType cmdType)
: WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
{
+ mBuff = NULL;
+ mBuffSize = NULL;
+ mSupport = NULL;
+ mVerboseLevel = 0;
+ mFlags = 0;
+ mMaxIntervalSec = 0;
+ mMinDataSize = 0;
+ mRingName = NULL;
memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
}
// constructor for feature set
DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
: WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
- { }
+ {
+ mBuff = NULL;
+ mBuffSize = NULL;
+ mNumRings = NULL;
+ mStatus = NULL;
+ mVerboseLevel = 0;
+ mFlags = 0;
+ mMaxIntervalSec = 0;
+ mMinDataSize = 0;
+ mRingName = NULL;
+ }
// constructor for ring params
DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
@@ -156,7 +234,13 @@ public:
: WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
mRingName(ring_name), mType(cmdType)
- { }
+ {
+ mBuff = NULL;
+ mBuffSize = NULL;
+ mNumRings = NULL;
+ mStatus = NULL;
+ mSupport = NULL;
+ }
int createRingRequest(WifiRequest& request) {
int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
@@ -500,8 +584,38 @@ public:
int start() {
ALOGV("Register loghandler");
+ int result;
+ uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
- return WIFI_SUCCESS;
+
+ WifiRequest request(familyId(), ifaceId());
+
+ /* set hal event socket port to driver */
+ result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
+ if (result != WIFI_SUCCESS) {
+ ALOGV("Failed to set Hal preInit; result = %d", result);
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
+ if (result != WIFI_SUCCESS) {
+ ALOGV("Hal preInit Failed to put pic = %d", result);
+ return result;
+ }
+
+ if (result != WIFI_SUCCESS) {
+ ALOGV("Hal preInit Failed to put pid= %d", result);
+ return result;
+ }
+
+ request.attr_end(data);
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set Hal preInit; result = %d", result);
+ return result;
+ }
+ return result;
}
virtual int cancel() {
@@ -561,8 +675,13 @@ public:
// ALOGI("Retrieved Debug data");
if (mHandler.on_ring_buffer_data) {
- (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
- &status);
+ /* Skip msg header. Retrieved log */
+ char *pBuff;
+ wifi_ring_buffer_entry *buffer_entry =
+ (wifi_ring_buffer_entry *) buffer;
+ pBuff = (char *) (buffer_entry + 1);
+ (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff,
+ buffer_entry->entry_size, &status);
}
} else {
ALOGE("Unknown Event");
@@ -679,7 +798,7 @@ public:
wifi_ring_buffer_id ring_id;
char *buffer = NULL;
int buffer_size = 0;
-
+ bool is_err_alert = false;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
int len = event.get_vendor_data_len();
@@ -698,15 +817,37 @@ public:
} else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
buffer_size = it.get_len();
buffer = (char *)it.get_data();
- /*
} else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
+ /* Error code is for error alert event only */
mErrCode = it.get_u32();
- */
+ is_err_alert = true;
} else {
ALOGW("Ignoring invalid attribute type = %d, size = %d",
it.get_type(), it.get_len());
}
}
+
+ if(is_err_alert) {
+ mBuffSize = sizeof(mErrCode);
+ if (mBuff) free(mBuff);
+ mBuff = (char *)malloc(mBuffSize);
+ if (!mBuff) {
+ ALOGE("Buffer allocation failed");
+ return NL_SKIP;
+ }
+ memcpy(mBuff, (char *)&mErrCode, mBuffSize);
+ ALOGI("Initiating alert callback");
+ if (mHandler.on_alert) {
+ (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
+ }
+ if (mBuff) {
+ free(mBuff);
+ mBuff = NULL;
+ }
+ mBuffSize = 0;
+ return NL_OK;
+ }
+
if (mBuffSize) {
ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
if (mBuff) free(mBuff);
@@ -755,6 +896,147 @@ public:
}
};
+///////////////////////////////////////////////////////////////////////////////
+class HalInit : public WifiCommand
+{
+ int mErrCode;
+
+ public:
+ HalInit(wifi_interface_handle iface, int id)
+ : WifiCommand("HalInit", iface, id), mErrCode(0)
+ { }
+
+ int start() {
+ ALOGE("Start Set Hal");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set hal start; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set hal start response; result = %d", result);
+ }
+ return result;
+ }
+
+
+ virtual int cancel() {
+ ALOGE("Cancel: Stop Hal");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to stop hal ; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set hal start response; result = %d", result);
+ }
+ wifi_unregister_cmd(wifiHandle(), id());
+ return result;
+ }
+
+ int preInit() {
+ ALOGE("Hal preInit");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set Hal preInit; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Hal preInit Failed to put data= %d", result);
+ return result;
+ }
+ request.attr_end(data);
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set Hal preInit; result = %d", result);
+ }
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGE("In SetHalStarted::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+
+wifi_error wifi_start_hal(wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ ALOGV("HAL INIT start, handle = %p", handle);
+
+ HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
+ cmd->releaseRef();
+ return result;
+ }
+ return result;
+}
+
+wifi_error wifi_hal_preInit(wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ ALOGV("wifi_hal_preInit, handle = %p", handle);
+
+ HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+ result = (wifi_error)cmd->preInit();
+ if (result != WIFI_SUCCESS) {
+ wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
+ cmd->releaseRef();
+ return result;
+ }
+ return result;
+}
+
+wifi_error wifi_stop_hal(wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+
+ HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ cmd->cancel();
+ cmd->releaseRef();
+ return WIFI_SUCCESS;
+}
+
wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
wifi_alert_handler handler)
{
@@ -923,7 +1205,11 @@ class PacketFateCommand: public WifiCommand
public:
PacketFateCommand(wifi_interface_handle handle)
: WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
- { }
+ {
+ mReportBufs = NULL;
+ mNoReqFates = 0;
+ mNoProvidedFates = NULL;
+ }
PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
size_t n_requested_fates, size_t *n_provided_fates)
@@ -1075,6 +1361,143 @@ public:
}
};
+class GetWakeReasonCountCommand : public WifiCommand {
+ WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
+ void *mCmdEventWakeCount;
+ public:
+ GetWakeReasonCountCommand(wifi_interface_handle handle,
+ WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
+ WifiCommand("GetWakeReasonCountCommand", handle, 0),
+ mWakeReasonCnt(wlanDriverWakeReasonCount)
+ {
+ mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
+ }
+
+ int createRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ ALOGD("Start get wake stats command\n");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = createRequest(request);
+ if (result < 0) {
+ ALOGE("Failed to create request result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register wake stats response; result = %d\n", result);
+ }
+ return result;
+ }
+
+ protected:
+ int handleResponse(WifiEvent& reply) {
+ ALOGE("In GetWakeReasonCountCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
+ mWakeReasonCnt->total_driver_fw_local_wake =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
+ mWakeReasonCnt->total_cmd_event_wake =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
+ mWakeReasonCnt->cmd_event_wake_cnt_used =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
+ memcpy(mCmdEventWakeCount, it.get_data(),
+ (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
+ break;
+ case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
+ mWakeReasonCnt->total_rx_data_wake =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
+ mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
+ mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
+ mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
+ mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
+ mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
+ mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
+ mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
+ mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
+ mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
+ mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
+ it.get_u32();
+ break;
+ case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
+ mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
+ it.get_u32();
+ break;
+ default:
+ break;
+ }
+
+ }
+ return NL_OK;
+ }
+};
+
wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
{
PacketFateCommand *cmd = new PacketFateCommand(handle);
@@ -1107,3 +1530,13 @@ wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
cmd->releaseRef();
return result;
}
+
+wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
+{
+ GetWakeReasonCountCommand *cmd =
+ new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
+ wifi_error result = (wifi_error)cmd->start();
+ cmd->releaseRef();
+ return result;
+}
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
index 99c2fec..8054f49 100644
--- a/bcmdhd/wifi_hal/wifi_offload.cpp
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -57,7 +57,8 @@ typedef enum {
MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
- MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
+ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
+ MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE
} WIFI_MKEEP_ALIVE_ATTRIBUTE;
typedef enum {
@@ -75,13 +76,14 @@ class MKeepAliveCommand : public WifiCommand
u8 *mDstMacAddr;
u32 mPeriodMsec;
GetCmdType mType;
+ u16 mEther_type;
public:
// constructor for start sending
- MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
+ MKeepAliveCommand(wifi_interface_handle iface, u8 index, u16 ether_type, u8 *ip_packet, u16 ip_packet_len,
u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
- : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet),
+ : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mEther_type(ether_type), mIpPkt(ip_packet),
mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr),
mPeriodMsec(period_msec), mType(cmdType)
{ }
@@ -89,10 +91,17 @@ public:
// constructor for stop sending
MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
: WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
- { }
+ {
+ mIpPkt = NULL;
+ mIpPktLen = 0;
+ mSrcMacAddr = NULL;
+ mDstMacAddr = NULL;
+ mPeriodMsec = 0;
+ mEther_type = 0;
+ }
int createRequest(WifiRequest &request) {
- int result;
+ int result = WIFI_SUCCESS;
switch (mType) {
case START_MKEEP_ALIVE:
@@ -140,6 +149,11 @@ public:
ALOGE("Failed to put period request; result = %d", result);
return result;
}
+ result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE, mEther_type);
+ if (result < 0) {
+ ALOGE("Failed to put ether type; result = %d", result);
+ return result;
+ }
request.attr_end(data);
break;
@@ -216,13 +230,14 @@ public:
/* API to send specified mkeep_alive packet periodically. */
wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
- u16 /* ether_type */, u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr,
+ u16 ether_type, u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr,
u32 period_msec)
{
if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL)
&& (dst_mac_addr != NULL) && (period_msec > 0)
- && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) {
- MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len,
+ && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX) && ((ether_type == ETHERTYPE_IP) ||
+ (ether_type == ETHERTYPE_IPV6))) {
+ MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ether_type, ip_packet, ip_packet_len,
src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();