summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-03 01:22:03 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-02-03 01:22:03 +0000
commit03f4a165181b9d0761d2ab8e796a6417977eef90 (patch)
tree0956b36a452c503cc8982cb9d7ced92519fa0ae6
parenteae62b98409be855ff25142bafea5468fcd0d35c (diff)
parent27105db09ef8eb411d4add2ee764fec3beed8cf6 (diff)
downloadwlan-simpleperf-release.tar.gz
Merge "Snap for 11400057 from 95d94cbe5dde46aa8358399c6a1074a6e30baeed to simpleperf-release" into simpleperf-releasesimpleperf-release
-rw-r--r--bcmdhd/halutil/Android.mk59
-rw-r--r--bcmdhd/halutil/halutil.cpp8793
-rw-r--r--bcmdhd/halutil/wifi_hal_stub.cpp489
-rwxr-xr-xbcmdhd/wifi_hal/common.cpp2
-rw-r--r--bcmdhd/wifi_hal/common.h10
-rwxr-xr-xbcmdhd/wifi_hal/cpp_bindings.cpp11
-rwxr-xr-xbcmdhd/wifi_hal/cpp_bindings.h2
-rwxr-xr-xbcmdhd/wifi_hal/gscan.cpp2
-rw-r--r--bcmdhd/wifi_hal/link_layer_stats.cpp337
-rw-r--r--[-rwxr-xr-x]bcmdhd/wifi_hal/nan.cpp527
-rw-r--r--bcmdhd/wifi_hal/rtt.cpp2
-rw-r--r--bcmdhd/wifi_hal/scan.cpp2
-rw-r--r--bcmdhd/wifi_hal/sync.h2
-rwxr-xr-xbcmdhd/wifi_hal/twt.cpp2
-rw-r--r--bcmdhd/wifi_hal/wifi_hal.cpp88
-rwxr-xr-xbcmdhd/wifi_hal/wifi_logger.cpp66
-rw-r--r--bcmdhd/wifi_hal/wifi_offload.cpp2
17 files changed, 10129 insertions, 267 deletions
diff --git a/bcmdhd/halutil/Android.mk b/bcmdhd/halutil/Android.mk
new file mode 100644
index 0000000..3838494
--- /dev/null
+++ b/bcmdhd/halutil/Android.mk
@@ -0,0 +1,59 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# ============================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_REQUIRED_MODULES := libhardware_legacy
+LOCAL_LDLIBS := -llog
+
+LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
+LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
+LOCAL_CPPFLAGS += -Wno-conversion-null -Wunused-variable
+
+LOCAL_C_INCLUDES += \
+ frameworks/opt/net/wifi/libwifi_hal/include/wifi_hal \
+ frameworks/opt/net/wifi/libwifi_system_iface/include/wifi_system \
+ hardware/broadcom/wlan/bcmdhd/wifi_hal \
+ external/libnl/include \
+ $(call include-path-for, libhardware_legacy)/hardware_legacy \
+ external/wpa_supplicant_8/src/drivers \
+ libcore/include
+
+LOCAL_SHARED_LIBRARIES += \
+ libcutils \
+ libc \
+ libutils
+
+LOCAL_STATIC_LIBRARIES += libwifi-hal-bcm libnl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_SHARED_LIBRARIES += libcrypto libwifi-hal
+LOCAL_SHARED_LIBRARIES += libwifi-system-iface
+
+ifneq ($(wildcard vendor/google/libraries/GoogleWifiConfigLib),)
+ LOCAL_SHARED_LIBRARIES += \
+ google_wifi_firmware_config_version_c_wrapper
+ LOCAL_CFLAGS += -DGOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+endif
+
+LOCAL_SRC_FILES := \
+ halutil.cpp
+
+LOCAL_MODULE := halutil_brcm
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+include $(BUILD_EXECUTABLE)
diff --git a/bcmdhd/halutil/halutil.cpp b/bcmdhd/halutil/halutil.cpp
new file mode 100644
index 0000000..c5c46b7
--- /dev/null
+++ b/bcmdhd/halutil/halutil.cpp
@@ -0,0 +1,8793 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Portions copyright (C) 2022 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 <stdlib.h>
+#ifndef ANDROID
+#include <stddef.h>
+#endif
+
+#define LOG_TAG "WifiHAL"
+
+#define NAN_MAX_SIDS_IN_BEACONS 127
+#include <utils/Log.h>
+#ifndef ANDROID
+#include <cutils/memory.h>
+#endif
+#include <inttypes.h>
+#include <sys/socket.h>
+#ifdef ANDROID
+#include <linux/if.h>
+#endif
+#include <ctype.h>
+#include <stdarg.h>
+#include <semaphore.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include "netinet/in.h"
+#include "arpa/inet.h"
+#ifndef ANDROID
+#include <sys/ioctl.h>
+#include <net/if.h>
+#endif
+#include <sys/ioctl.h>
+#include <linux/netlink.h>
+#include "wifi_hal.h"
+#include "wifi_nan.h"
+#include "wifi_twt.h"
+#include "hal_tool.h"
+#include "interface_tool.h"
+
+#include "common.h"
+
+#define EVENT_COUNT 256
+#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_DISC_MAC_RAND_INTVL 30
+pthread_mutex_t printMutex;
+
+static wifi_hal_fn hal_fn;
+static char* frequency_to_channel(int center_freq);
+
+/* API to spawn a hal instance from halutil CLI to capture events */
+wifi_error nan_event_check_request(transaction_id id,
+ wifi_interface_handle handle);
+
+/* API to spawn a hal instance from halutil CLI to capture events */
+wifi_error twt_event_check_request(transaction_id id,
+ wifi_interface_handle handle);
+static int set_interface_params(char *p_info, char *val_p, int len);
+static void printApfUsage();
+static void printTxPowerUsage();
+
+void printMsg(const char *fmt, ...)
+{
+ pthread_mutex_lock(&printMutex);
+ va_list l;
+ va_start(l, fmt);
+
+ vprintf(fmt, l);
+ va_end(l);
+ pthread_mutex_unlock(&printMutex);
+}
+
+template<typename T, unsigned N>
+unsigned countof(T (&rgt)[N]) {
+ return N;
+}
+
+#define NBBY 8 /* number of bits/byte */
+
+/* Bit map related macros. */
+#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#define CEIL(x, y) (((x) + ((y) - 1)) / (y))
+
+/* TLV defines */
+#define TLV_TAG_OFF 0 /* tag offset */
+#define TLV_LEN_OFF 1 /* length offset */
+#define TLV_HDR_LEN 2 /* header length */
+#define TLV_BODY_OFF 2 /* body offset */
+#define TLV_BODY_LEN_MAX 255 /* max body length */
+
+
+/* Information Element IDs */
+#define WIFI_EID_SSID 0
+#define WIFI_EID_SUPP_RATES 1
+#define WIFI_EID_FH_PARAMS 2
+#define WIFI_EID_DS_PARAMS 3
+#define WIFI_EID_CF_PARAMS 4
+#define WIFI_EID_TIM 5
+#define WIFI_EID_IBSS_PARAMS 6
+#define WIFI_EID_COUNTRY 7
+#define WIFI_EID_BSS_LOAD 11
+#define WIFI_EID_CHALLENGE 16
+/* EIDs defined by IEEE 802.11h - START */
+#define WIFI_EID_PWR_CONSTRAINT 32
+#define WIFI_EID_PWR_CAPABILITY 33
+#define WIFI_EID_TPC_REQUEST 34
+#define WIFI_EID_TPC_REPORT 35
+#define WIFI_EID_SUPPORTED_CHANNELS 36
+#define WIFI_EID_CHANNEL_SWITCH 37
+#define WIFI_EID_MEASURE_REQUEST 38
+#define WIFI_EID_MEASURE_REPORT 39
+#define WIFI_EID_QUITE 40
+#define WIFI_EID_IBSS_DFS 41
+/* EIDs defined by IEEE 802.11h - END */
+#define WIFI_EID_ERP_INFO 42
+#define WIFI_EID_HT_CAP 45
+#define WIFI_EID_QOS 46
+#define WIFI_EID_RSN 48
+#define WIFI_EID_EXT_SUPP_RATES 50
+#define WIFI_EID_NEIGHBOR_REPORT 52
+#define WIFI_EID_MOBILITY_DOMAIN 54
+#define WIFI_EID_FAST_BSS_TRANSITION 55
+#define WIFI_EID_TIMEOUT_INTERVAL 56
+#define WIFI_EID_RIC_DATA 57
+#define WIFI_EID_SUPPORTED_OPERATING_CLASSES 59
+#define WIFI_EID_HT_OPERATION 61
+#define WIFI_EID_SECONDARY_CHANNEL_OFFSET 62
+#define WIFI_EID_WAPI 68
+#define WIFI_EID_TIME_ADVERTISEMENT 69
+#define WIFI_EID_20_40_BSS_COEXISTENCE 72
+#define WIFI_EID_20_40_BSS_INTOLERANT 73
+#define WIFI_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
+#define WIFI_EID_MMIE 76
+#define WIFI_EID_SSID_LIST 84
+#define WIFI_EID_BSS_MAX_IDLE_PERIOD 90
+#define WIFI_EID_TFS_REQ 91
+#define WIFI_EID_TFS_RESP 92
+#define WIFI_EID_WNMSLEEP 93
+#define WIFI_EID_TIME_ZONE 98
+#define WIFI_EID_LINK_ID 101
+#define WIFI_EID_INTERWORKING 107
+#define WIFI_EID_ADV_PROTO 108
+#define WIFI_EID_QOS_MAP_SET 110
+#define WIFI_EID_ROAMING_CONSORTIUM 111
+#define WIFI_EID_EXT_CAPAB 127
+#define WIFI_EID_CCKM 156
+#define WIFI_EID_VHT_CAP 191
+#define WIFI_EID_VHT_OPERATION 192
+#define WIFI_EID_VHT_EXTENDED_BSS_LOAD 193
+#define WIFI_EID_VHT_WIDE_BW_CHSWITCH 194
+#define WIFI_EID_VHT_TRANSMIT_POWER_ENVELOPE 195
+#define WIFI_EID_VHT_CHANNEL_SWITCH_WRAPPER 196
+#define WIFI_EID_VHT_AID 197
+#define WIFI_EID_VHT_QUIET_CHANNEL 198
+#define WIFI_EID_VHT_OPERATING_MODE_NOTIFICATION 199
+#define WIFI_EID_VENDOR_SPECIFIC 221
+
+
+/* Extended capabilities IE bitfields */
+/* 20/40 BSS Coexistence Management support bit position */
+#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0
+/* Extended Channel Switching support bit position */
+#define DOT11_EXT_CAP_EXT_CHAN_SWITCHING 2
+/* scheduled PSMP support bit position */
+#define DOT11_EXT_CAP_SPSMP 6
+/* Flexible Multicast Service */
+#define DOT11_EXT_CAP_FMS 11
+/* proxy ARP service support bit position */
+#define DOT11_EXT_CAP_PROXY_ARP 12
+/* Civic Location */
+#define DOT11_EXT_CAP_CIVIC_LOC 14
+/* Geospatial Location */
+#define DOT11_EXT_CAP_LCI 15
+/* Traffic Filter Service */
+#define DOT11_EXT_CAP_TFS 16
+/* WNM-Sleep Mode */
+#define DOT11_EXT_CAP_WNM_SLEEP 17
+/* TIM Broadcast service */
+#define DOT11_EXT_CAP_TIMBC 18
+/* BSS Transition Management support bit position */
+#define DOT11_EXT_CAP_BSSTRANS_MGMT 19
+/* Direct Multicast Service */
+#define DOT11_EXT_CAP_DMS 26
+/* Interworking support bit position */
+#define DOT11_EXT_CAP_IW 31
+/* QoS map support bit position */
+#define DOT11_EXT_CAP_QOS_MAP 32
+/* service Interval granularity bit position and mask */
+#define DOT11_EXT_CAP_SI 41
+#define DOT11_EXT_CAP_SI_MASK 0x0E
+/* WNM notification */
+#define DOT11_EXT_CAP_WNM_NOTIF 46
+/* Operating mode notification - VHT (11ac D3.0 - 8.4.2.29) */
+#define DOT11_EXT_CAP_OPER_MODE_NOTIF 62
+/* Fine timing measurement - D3.0 */
+#define DOT11_EXT_CAP_FTM_RESPONDER 70
+#define DOT11_EXT_CAP_FTM_INITIATOR 71 /* tentative 11mcd3.0 */
+
+#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */
+#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */
+#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */
+#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */
+
+enum vht_op_chan_width {
+ VHT_OP_CHAN_WIDTH_20_40 = 0,
+ VHT_OP_CHAN_WIDTH_80 = 1,
+ VHT_OP_CHAN_WIDTH_160 = 2,
+ VHT_OP_CHAN_WIDTH_80_80 = 3
+};
+/**
+ * Channel Factor for the starting frequence of 2.4 GHz channels.
+ * The value corresponds to 2407 MHz.
+ */
+#define CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */
+
+/**
+ * Channel Factor for the starting frequence of 5 GHz channels.
+ * The value corresponds to 5000 MHz.
+ */
+#define CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
+
+
+/* ************* HT definitions. ************* */
+#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
+#define MAX_MCS_NUM (128) /* max mcs number = 128 */
+
+struct ht_op_ie {
+ u8 ctl_ch; /* control channel number */
+ u8 chan_info; /* ext ch,rec. ch. width, RIFS support */
+ u16 opmode; /* operation mode */
+ u16 misc_bits; /* misc bits */
+ u8 basic_mcs[MCSSET_LEN]; /* required MCS set */
+} __attribute__ ((packed));
+struct vht_op_ie {
+ u8 chan_width;
+ u8 chan1;
+ u8 chan2;
+ u16 supp_mcs; /* same def as above in vht cap */
+} __attribute__ ((packed));
+
+#define EVENT_BUF_SIZE 2048
+#define MAX_EVENT_MSG_LEN 256
+#define MAX_CH_BUF_SIZE 256
+#define MAX_FEATURE_SET 8
+#define MAX_RADIO_COMBO 5
+#define MAX_CORE 2
+#define HOTLIST_LOST_WINDOW 5
+
+static wifi_handle halHandle;
+static wifi_interface_handle *ifaceHandles;
+static wifi_interface_handle wlan0Handle;
+static wifi_interface_handle p2p0Handle;
+static int numIfaceHandles;
+static int cmdId = 0;
+static int max_event_wait = 5;
+static int stest_max_ap = 10;
+static int stest_base_period = 5000;
+static int stest_threshold_percent = 80;
+static int stest_threshold_num_scans = 10;
+static int swctest_rssi_sample_size = 3;
+static int swctest_rssi_lost_ap = 3;
+static int swctest_rssi_min_breaching = 2;
+static int swctest_rssi_ch_threshold = 1;
+static int htest_low_threshold = 90;
+static int htest_high_threshold = 10;
+static int rssi_monitor = 0;
+static signed char min_rssi = 0;
+static signed char max_rssi = 0;
+static size_t n_requested_pkt_fate = 0;
+
+#define FILE_NAME_LEN 128
+#define FILE_MAX_SIZE (1 * 1024 * 1024)
+#define MAX_RING_NAME_SIZE 32
+
+#define NUM_ALERT_DUMPS 10
+#define ETHER_ADDR_LEN 6
+#define MAX_NAN_MSG_BUF_SIZE 256
+
+#define NAN_MAX_CLUST_VALUE_RANGE 0xFFFF
+#define MAX_CH_AVOID 128
+
+/*
+ * Host can send Post Connectivity Capability attributes
+ * to be included in Service Discovery frames transmitted.
+ */
+enum post_connectivity_capability {
+ FEATURE_NOT_SUPPORTED = 0,
+ FEATURE_SUPPORTED = 1
+};
+
+
+/////////////////////////////////////////////////////////////////
+// Logger related.
+
+#define DEFAULT_MEMDUMP_FILE "/data/memdump.bin"
+#define ALERT_MEMDUMP_PREFIX "/data/alertdump"
+#define RINGDATA_PREFIX "/data/ring-"
+#define DEFAULT_TX_PKT_FATE_FILE "/data/txpktfate.txt"
+#define DEFAULT_RX_PKT_FATE_FILE "/data/rxpktfate.txt"
+
+static char mem_dump_file[FILE_NAME_LEN] = DEFAULT_MEMDUMP_FILE;
+static char tx_pkt_fate_file[FILE_NAME_LEN] = DEFAULT_TX_PKT_FATE_FILE;
+static char rx_pkt_fate_file[FILE_NAME_LEN] = DEFAULT_RX_PKT_FATE_FILE;
+
+struct LoggerParams {
+ u32 verbose_level;
+ u32 flags;
+ u32 max_interval_sec;
+ u32 min_data_size;
+ wifi_ring_buffer_id ring_id;
+ char ring_name[MAX_RING_NAME_SIZE];
+};
+struct LoggerParams default_logger_param = {0, 0 , 0 , 0, 0, {0}};
+
+char default_ring_name[MAX_RING_NAME_SIZE] = "fw_event";
+
+typedef enum {
+ LOG_INVALID = -1,
+ LOG_START,
+ LOG_GET_MEMDUMP,
+ LOG_GET_FW_VER,
+ LOG_GET_DRV_VER,
+ LOG_GET_RING_STATUS,
+ LOG_GET_RINGDATA,
+ LOG_GET_FEATURE,
+ LOG_GET_RING_DATA,
+ LOG_MONITOR_PKTFATE,
+ LOG_GET_TXPKTFATE,
+ LOG_GET_RXPKTFATE,
+ LOG_SET_LOG_HANDLER,
+ LOG_SET_ALERT_HANDLER,
+} LoggerCmd;
+
+LoggerCmd log_cmd = LOG_INVALID;
+wifi_ring_buffer_id ringId = -1;
+
+#define C2S(x) case x: return #x;
+
+static const char *RBentryTypeToString(int cmd) {
+ switch (cmd) {
+ C2S(ENTRY_TYPE_CONNECT_EVENT)
+ C2S(ENTRY_TYPE_PKT)
+ C2S(ENTRY_TYPE_WAKE_LOCK)
+ C2S(ENTRY_TYPE_POWER_EVENT)
+ C2S(ENTRY_TYPE_DATA)
+ default:
+ return "ENTRY_TYPE_UNKNOWN";
+ }
+}
+
+static const char *RBconnectEventToString(int cmd)
+{
+ switch (cmd) {
+ C2S(WIFI_EVENT_ASSOCIATION_REQUESTED)
+ C2S(WIFI_EVENT_AUTH_COMPLETE)
+ C2S(WIFI_EVENT_ASSOC_COMPLETE)
+ C2S(WIFI_EVENT_FW_AUTH_STARTED)
+ C2S(WIFI_EVENT_FW_ASSOC_STARTED)
+ C2S(WIFI_EVENT_FW_RE_ASSOC_STARTED)
+ C2S(WIFI_EVENT_DRIVER_SCAN_REQUESTED)
+ C2S(WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND)
+ C2S(WIFI_EVENT_DRIVER_SCAN_COMPLETE)
+ C2S(WIFI_EVENT_G_SCAN_STARTED)
+ C2S(WIFI_EVENT_G_SCAN_COMPLETE)
+ C2S(WIFI_EVENT_DISASSOCIATION_REQUESTED)
+ C2S(WIFI_EVENT_RE_ASSOCIATION_REQUESTED)
+ C2S(WIFI_EVENT_ROAM_REQUESTED)
+ C2S(WIFI_EVENT_BEACON_RECEIVED)
+ C2S(WIFI_EVENT_ROAM_SCAN_STARTED)
+ C2S(WIFI_EVENT_ROAM_SCAN_COMPLETE)
+ C2S(WIFI_EVENT_ROAM_SEARCH_STARTED)
+ C2S(WIFI_EVENT_ROAM_SEARCH_STOPPED)
+ C2S(WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT)
+ C2S(WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START)
+ C2S(WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP)
+ C2S(WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED)
+ C2S(WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED)
+ C2S(WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED)
+ C2S(WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE)
+ C2S(WIFI_EVENT_BT_COEX_BT_SCO_START)
+ C2S(WIFI_EVENT_BT_COEX_BT_SCO_STOP)
+ C2S(WIFI_EVENT_BT_COEX_BT_SCAN_START)
+ C2S(WIFI_EVENT_BT_COEX_BT_SCAN_STOP)
+ C2S(WIFI_EVENT_BT_COEX_BT_HID_START)
+ C2S(WIFI_EVENT_BT_COEX_BT_HID_STOP)
+ C2S(WIFI_EVENT_ROAM_AUTH_STARTED)
+ C2S(WIFI_EVENT_ROAM_AUTH_COMPLETE)
+ C2S(WIFI_EVENT_ROAM_ASSOC_STARTED)
+ C2S(WIFI_EVENT_ROAM_ASSOC_COMPLETE)
+ C2S(WIFI_EVENT_DRIVER_PNO_ADD)
+ C2S(WIFI_EVENT_DRIVER_PNO_REMOVE)
+ C2S(WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND)
+ C2S(WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED)
+ C2S(WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND)
+ C2S(WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE)
+ default:
+ return "WIFI_EVENT_UNKNOWN";
+ }
+}
+
+static const char *RBTlvTagToString(int cmd) {
+ switch (cmd) {
+ C2S(WIFI_TAG_VENDOR_SPECIFIC)
+ C2S(WIFI_TAG_BSSID)
+ C2S(WIFI_TAG_ADDR)
+ C2S(WIFI_TAG_SSID)
+ C2S(WIFI_TAG_STATUS)
+ C2S(WIFI_TAG_CHANNEL_SPEC)
+ C2S(WIFI_TAG_WAKE_LOCK_EVENT)
+ C2S(WIFI_TAG_ADDR1)
+ C2S(WIFI_TAG_ADDR2)
+ C2S(WIFI_TAG_ADDR3)
+ C2S(WIFI_TAG_ADDR4)
+ C2S(WIFI_TAG_IE)
+ C2S(WIFI_TAG_INTERFACE)
+ C2S(WIFI_TAG_REASON_CODE)
+ C2S(WIFI_TAG_RATE_MBPS)
+ C2S(WIFI_TAG_CHANNEL)
+ C2S(WIFI_TAG_RSSI)
+ default:
+ return "WIFI_TAG_UNKNOWN";
+ }
+}
+
+static const char *RBchanWidthToString(int cmd) {
+ switch (cmd) {
+ C2S(WIFI_CHAN_WIDTH_20)
+ C2S(WIFI_CHAN_WIDTH_40)
+ C2S(WIFI_CHAN_WIDTH_80)
+ C2S(WIFI_CHAN_WIDTH_160)
+ C2S(WIFI_CHAN_WIDTH_80P80)
+ C2S(WIFI_CHAN_WIDTH_5)
+ C2S(WIFI_CHAN_WIDTH_10)
+ C2S(WIFI_CHAN_WIDTH_INVALID)
+ default:
+ return "WIFI_CHAN_WIDTH_INVALID";
+ }
+}
+
+static const char *BandToString(wlan_mac_band cmd) {
+ switch (cmd) {
+ C2S(WLAN_MAC_2_4_BAND)
+ C2S(WLAN_MAC_5_0_BAND)
+ C2S(WLAN_MAC_6_0_BAND)
+ C2S(WLAN_MAC_60_0_BAND)
+ default:
+ return "INVALID";
+ }
+}
+
+static const char *AntennCfgToString(wifi_antenna_configuration cmd) {
+ switch (cmd) {
+ C2S(WIFI_ANTENNA_1X1)
+ C2S(WIFI_ANTENNA_2X2)
+ C2S(WIFI_ANTENNA_3X3)
+ C2S(WIFI_ANTENNA_4X4)
+ default:
+ return "WIFI_ANTENNA_INVALID";
+ }
+}
+
+/////////////////////////////////////////////////////////////////
+// RTT related to configuration
+#define MAX_SSID_LEN (32 + 1)
+/* 18-bytes of Ethernet address buffer length */
+#define ETHER_ADDR_STR_LEN 18
+#define ETHER_ADDR_LEN 6
+
+#define DEFAULT_RTT_FILE "/data/rtt-ap.list"
+static int rtt_from_file = 0;
+static int rtt_to_file = 0;
+static wifi_band band = WIFI_BAND_UNSPECIFIED;
+static int max_ap = 256; // the maximum count of ap for RTT test
+static char rtt_aplist[FILE_NAME_LEN] = DEFAULT_RTT_FILE;
+static mac_addr responder_addr;
+static wifi_channel responder_channel;
+static int channel_width = 0;
+static bool rtt_sta = false;
+static bool rtt_nan = false;
+static bool is_6g = false;
+struct rtt_params {
+ u32 burst_period;
+ u32 num_burst;
+ u32 num_frames_per_burst;
+ u32 num_retries_per_ftm;
+ u32 num_retries_per_ftmr;
+ u32 burst_duration;
+ u8 LCI_request;
+ u8 LCR_request;
+ u8 preamble;
+ u8 bw;
+ wifi_rtt_type type;
+};
+struct rtt_params default_rtt_param = {0, 0, 0, 0, 0, 15, 0, 0, 0, 0, RTT_TYPE_2_SIDED};
+
+mac_addr hotlist_bssids[16];
+mac_addr blacklist_bssids[16];
+char whitelist_ssids[MAX_WHITELIST_SSID][MAX_SSID_LEN] = {{0}};
+unsigned char mac_oui[3];
+wifi_epno_params epno_cfg;
+int channel_list[16];
+int num_hotlist_bssids = 0;
+int num_channels = 0;
+mac_addr pref_bssids[16];
+int rssi_modifier[16];
+int num_pref_bssids = -1;
+int num_blacklist_bssids = -1;
+int num_whitelist_ssids = -1;
+bool set_roaming_configuration = false;
+
+#define EPNO_HIDDEN (1 << 0)
+#define EPNO_A_BAND_TRIG (1 << 1)
+#define EPNO_BG_BAND_TRIG (1 << 2)
+#define EPNO_ABG_BAND_TRIG (EPNO_A_BAND_TRIG | EPNO_BG_BAND_TRIG)
+#define EPNO_FLAG_STRICT_MATCH (1 << 3)
+#define EPNO_FLAG_SAME_NETWORK (1 << 4)
+
+void parseMacAddress(const char *str, mac_addr addr);
+
+int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
+{
+ struct ifreq ifr;
+ int ret;
+
+ ALOGD("setting interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
+
+ if (sock < 0) {
+ printMsg("Bad socket: %d\n", sock);
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+#ifdef ANDROID
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+#else
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+#endif
+ ALOGD("reading old value\n");
+
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
+ ret = errno ? -errno : -999;
+ printMsg("Could not read interface %s flags: %d\n", ifname, errno);
+ return ret;
+ } else {
+ ALOGD("writing new value\n");
+ }
+
+ if (dev_up) {
+ if (ifr.ifr_flags & IFF_UP) {
+ ALOGD("interface %s is already up\n", ifname);
+ return 0;
+ }
+ ifr.ifr_flags |= IFF_UP;
+ } else {
+ if (!(ifr.ifr_flags & IFF_UP)) {
+ printMsg("interface %s is already down\n", ifname);
+ return 0;
+ }
+ ifr.ifr_flags &= ~IFF_UP;
+ }
+
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
+ ret = errno ? -errno : -999;
+ printMsg("Could not set interface %s flags \n", ifname);
+ return ret;
+ } else {
+ ALOGD("set interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
+ }
+ ALOGD("Done\n");
+ return 0;
+}
+
+
+static int init() {
+ android::wifi_system::HalTool hal_tool;
+ if (!hal_tool.InitFunctionTable(&hal_fn)) {
+ printMsg("Could not initialize the function table!\n");
+ return -1;
+ }
+
+ android::wifi_system::InterfaceTool if_tool;
+ if (!if_tool.SetWifiUpState(true)) {
+ printMsg("Failed to set the interface state to up.\n");
+ return -1;
+ }
+
+ wifi_error res = hal_fn.wifi_initialize(&halHandle);
+ if (res < 0) {
+ return res;
+ }
+
+ res = hal_fn.wifi_get_ifaces(halHandle, &numIfaceHandles, &ifaceHandles);
+ if (res < 0) {
+ return res;
+ }
+
+ char buf[EVENT_BUF_SIZE];
+ for (int i = 0; i < numIfaceHandles; i++) {
+ if (hal_fn.wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
+ if (strcmp(buf, "wlan0") == 0) {
+ printMsg("found interface %s\n", buf);
+ wlan0Handle = ifaceHandles[i];
+ } else if (strcmp(buf, "p2p0") == 0) {
+ printMsg("found interface %s\n", buf);
+ p2p0Handle = ifaceHandles[i];
+ }
+ }
+ }
+
+ return res;
+}
+
+static void cleaned_up_handler(wifi_handle handle) {
+ printMsg("HAL cleaned up handler\n");
+ halHandle = NULL;
+ ifaceHandles = NULL;
+}
+
+static void cleanup() {
+ printMsg("cleaning up HAL\n");
+ hal_fn.wifi_cleanup(halHandle, cleaned_up_handler);
+}
+
+sem_t event_thread_mutex;
+
+static void *eventThreadFunc(void *context) {
+
+ printMsg("starting wifi event loop\n");
+ sem_post( &event_thread_mutex );
+ hal_fn.wifi_event_loop(halHandle);
+ printMsg("out of wifi event loop\n");
+
+ return NULL;
+}
+
+
+static int getNewCmdId() {
+ return cmdId++;
+}
+
+/* pretty hex print a contiguous buffer to file */
+void
+fprhex(FILE *f_wp, char *buf, uint nbytes, bool prefix)
+{
+ char line[128], *p;
+ int rem_len = sizeof(line);
+ int nchar = 0;
+ uint i;
+
+ p = line;
+ for (i = 0; i < nbytes; i++) {
+ if ((i % 16 == 0) && prefix) {
+ nchar = snprintf(p, rem_len, " %04x: ", i); /* line prefix */
+ p += nchar;
+ rem_len -= nchar;
+ }
+
+ if (rem_len > 0) {
+ nchar = snprintf(p, rem_len, "%02x ", (unsigned char)buf[i]);
+ p += nchar;
+ rem_len -= nchar;
+ }
+
+ if (i % 16 == 15) {
+ fprintf(f_wp, "%s\n", line); /* flush line */
+ p = line;
+ rem_len = sizeof(line);
+ }
+ }
+
+ /* flush last partial line */
+ if (p != line) {
+ fprintf(f_wp, "%s\n", line);
+ }
+}
+
+
+/* ------------------------------------------- */
+/* helpers */
+/* ------------------------------------------- */
+
+void printScanHeader() {
+ printMsg("SSID\t\t\t\t\tBSSID\t\t RSSI\tchannel\ttimestamp\tRTT\tRTT SD\n");
+ printMsg("----\t\t\t\t\t-----\t\t ----\t-------\t---------\t---\t------\n");
+}
+
+void printScanResult(wifi_scan_result result) {
+
+ printMsg("%-32s\t", result.ssid);
+
+ printMsg("%02x:%02x:%02x:%02x:%02x:%02x ", result.bssid[0], result.bssid[1],
+ result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
+
+ printMsg("%d\t", result.rssi);
+ printMsg("%d\t", result.channel);
+ printMsg("%lld\t", result.ts);
+ printMsg("%lld\t", result.rtt);
+ printMsg("%lld\n", result.rtt_sd);
+}
+
+void printSignificantChangeResult(wifi_significant_change_result *res) {
+
+ wifi_significant_change_result &result = *res;
+ printMsg("%02x:%02x:%02x:%02x:%02x:%02x ", result.bssid[0], result.bssid[1],
+ result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
+
+ printMsg("%d\t", result.channel);
+
+ for (int i = 0; i < result.num_rssi; i++) {
+ printMsg("%d,", result.rssi[i]);
+ }
+ printMsg("\n");
+}
+
+void printScanCapabilities(wifi_gscan_capabilities capabilities)
+{
+ printMsg("Scan Capabililites\n");
+ printMsg(" max_scan_cache_size = %d\n", capabilities.max_scan_cache_size);
+ printMsg(" max_scan_buckets = %d\n", capabilities.max_scan_buckets);
+ printMsg(" max_ap_cache_per_scan = %d\n", capabilities.max_ap_cache_per_scan);
+ printMsg(" max_rssi_sample_size = %d\n", capabilities.max_rssi_sample_size);
+ printMsg(" max_scan_reporting_threshold = %d\n", capabilities.max_scan_reporting_threshold);
+ printMsg(" max_hotlist_bssids = %d\n", capabilities.max_hotlist_bssids);
+ printMsg(" max_significant_wifi_change_aps = %d\n",
+ capabilities.max_significant_wifi_change_aps);
+ printMsg(" max_number_epno_networks = %d\n", capabilities.max_number_epno_networks);
+}
+
+
+/* ------------------------------------------- */
+/* commands and events */
+/* ------------------------------------------- */
+
+typedef enum {
+ EVENT_TYPE_SCAN_FAILED = 1000,
+ EVENT_TYPE_HOTLIST_AP_FOUND = 1001,
+ EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE = 1002,
+ EVENT_TYPE_RTT_RESULTS = 1003,
+ EVENT_TYPE_SCAN_COMPLETE = 1004,
+ EVENT_TYPE_HOTLIST_AP_LOST = 1005,
+ EVENT_TYPE_EPNO_SSID = 1006,
+ EVENT_TYPE_LOGGER_RINGBUFFER_DATA = 1007,
+ EVENT_TYPE_LOGGER_MEMDUMP_DATA = 1008,
+ EVENT_TYPE_LOGGER_ALERT_DATA = 1009,
+ EVENT_TYPE_RSSI_MONITOR = 1010,
+ EVENT_TYPE_SCAN_RESULTS_THRESHOLD = 1011,
+ EVENT_TYPE_NAN_PUBLISH_REPLIED = 1012,
+ EVENT_TYPE_SUBSCRIBE_MATCHED = 1013,
+ EVENT_TYPE_NAN_FOLLOWUP_RECIEVE = 1014,
+ EVENT_TYPE_NAN_PUBLISH_TERMINATED = 1015,
+ EVENT_TYPE_NAN_DISABLED = 1016,
+ EVENT_TYPE_NAN_SUBSCRIBE_TERMINATED = 1017,
+ EVENT_TYPE_NAN_ENABLED = 1018,
+ EVENT_TYPE_NAN_DATA_REQUEST_INDICATION = 1019,
+ EVENT_TYPE_NAN_DATA_CONFIRMATION = 1020,
+ EVENT_TYPE_NAN_DATA_END_INDICAION = 1021,
+ EVENT_TYPE_NAN_TRANSMIT_FOLLOWUP_INDICATION = 1022,
+ EVENT_TYPE_RTT_RESULTS_DETAIL = 1023,
+ EVENT_TYPE_CHRE_NAN_RTT_STATE_UPDATED = 1024,
+
+} EventType;
+
+typedef struct {
+ int type;
+ char buf[MAX_EVENT_MSG_LEN];
+} EventInfo;
+
+const int MAX_EVENTS_IN_CACHE = 256;
+EventInfo eventCache[256];
+int eventsInCache = 0;
+pthread_cond_t eventCacheCondition;
+pthread_mutex_t eventCacheMutex;
+
+void putEventInCache(int type, const char *msg) {
+ pthread_mutex_lock(&eventCacheMutex);
+ if (eventsInCache + 1 < MAX_EVENTS_IN_CACHE) {
+ eventCache[eventsInCache].type = type;
+ strncpy(eventCache[eventsInCache].buf, msg, (MAX_EVENT_MSG_LEN - 1));
+ eventCache[eventsInCache].buf[MAX_EVENT_MSG_LEN - 1] = '\0';
+ eventsInCache++;
+ pthread_cond_signal(&eventCacheCondition);
+ } else {
+ printMsg("Too many events in the cache\n");
+ }
+ pthread_mutex_unlock(&eventCacheMutex);
+}
+
+void getEventFromCache(EventInfo& info) {
+ pthread_mutex_lock(&eventCacheMutex);
+ while (true) {
+ if (eventsInCache > 0) {
+ info.type = eventCache[0].type;
+ strncpy(info.buf, eventCache[0].buf, (MAX_EVENT_MSG_LEN - 1));
+ eventCache[0].buf[MAX_EVENT_MSG_LEN - 1] = '\0';
+ eventsInCache--;
+ memmove(&eventCache[0], &eventCache[1], sizeof(EventInfo) * eventsInCache);
+ pthread_mutex_unlock(&eventCacheMutex);
+ return;
+ } else {
+ pthread_cond_wait(&eventCacheCondition, &eventCacheMutex);
+ }
+ }
+}
+
+static void on_scan_event(wifi_request_id id, wifi_scan_event event) {
+ EventType internal_event;
+ printMsg("Received scan event\n");
+ if (event == WIFI_SCAN_THRESHOLD_PERCENT || event == WIFI_SCAN_THRESHOLD_NUM_SCANS) {
+ printMsg("Received buffer events - %d \n", event);
+ internal_event = EVENT_TYPE_SCAN_RESULTS_THRESHOLD;
+ } else if(event == WIFI_SCAN_RESULTS_AVAILABLE) {
+ printMsg("Received scan complete event - WIFI_SCAN_RESULTS_AVAILABLE!!\n");
+ internal_event = EVENT_TYPE_SCAN_COMPLETE;
+ } else if (event == WIFI_SCAN_FAILED) {
+ printMsg("Received scan event - WIFI_SCAN_FAILED \n");
+ internal_event = EVENT_TYPE_SCAN_FAILED;
+ } else {
+ /* set to default value */
+ internal_event = EVENT_TYPE_SCAN_FAILED;
+ }
+ putEventInCache(internal_event, "New scan event");
+}
+
+static int scanCmdId;
+static int rssiMonId;
+static int hotlistCmdId;
+static int rttCmdId;
+static int epnoCmdId;
+static int loggerCmdId;
+static u16 nanCmdId;
+static u16 twtCmdId;
+static wifi_error twt_init_handlers(void);
+
+static bool startScan(int max_ap_per_scan, int base_period, int threshold_percent,
+ int threshold_num_scans) {
+
+ /* Get capabilties */
+ wifi_gscan_capabilities capabilities;
+ int result = hal_fn.wifi_get_gscan_capabilities(wlan0Handle, &capabilities);
+ if (result < 0) {
+ printMsg("failed to get scan capabilities - %d\n", result);
+ printMsg("trying scan anyway ..\n");
+ } else {
+ printScanCapabilities(capabilities);
+ }
+
+ wifi_scan_cmd_params params;
+ memset(&params, 0, sizeof(params));
+
+ if(num_channels > 0){
+ params.max_ap_per_scan = max_ap_per_scan;
+ params.base_period = base_period; // 5 second by default
+ params.report_threshold_percent = threshold_percent;
+ params.report_threshold_num_scans = threshold_num_scans;
+ params.num_buckets = 1;
+
+ params.buckets[0].bucket = 0;
+ params.buckets[0].band = WIFI_BAND_UNSPECIFIED;
+ params.buckets[0].period = base_period;
+ params.buckets[0].num_channels = num_channels;
+
+ for(int i = 0; i < num_channels; i++){
+ params.buckets[0].channels[i].channel = channel_list[i];
+ }
+
+ } else {
+
+ /* create a schedule to scan channels 1, 6, 11 every 5 second and
+ * scan 36, 40, 44, 149, 153, 157, 161 165 every 10 second */
+ params.max_ap_per_scan = max_ap_per_scan;
+ params.base_period = base_period; // 5 second
+ params.report_threshold_percent = threshold_percent;
+ params.report_threshold_num_scans = threshold_num_scans;
+ params.num_buckets = 4;
+
+ params.buckets[0].bucket = 0;
+ params.buckets[0].band = WIFI_BAND_BG;
+ params.buckets[0].period = 5000; // 5 second
+ params.buckets[0].report_events = 0;
+ params.buckets[0].num_channels = 3; // driver should ignore list since band is specified
+
+ params.buckets[0].channels[0].channel = 2412;
+ params.buckets[0].channels[1].channel = 2437;
+ params.buckets[0].channels[2].channel = 2462;
+
+ params.buckets[1].bucket = 1;
+ params.buckets[1].band = WIFI_BAND_UNSPECIFIED;
+ params.buckets[1].period = 10000; // 10 second
+ params.buckets[1].report_events = 0;
+ params.buckets[1].num_channels = 6;
+
+
+ params.buckets[1].channels[0].channel = 5180;
+ params.buckets[1].channels[1].channel = 5200;
+ params.buckets[1].channels[2].channel = 5220;
+ params.buckets[1].channels[3].channel = 5745;
+ params.buckets[1].channels[4].channel = 5765;
+ params.buckets[1].channels[5].channel = 5785;
+
+ params.buckets[2].bucket = 2;
+ params.buckets[2].band = WIFI_BAND_UNSPECIFIED;
+ params.buckets[2].period = 15000; // 15 second
+ params.buckets[2].report_events = 0;
+ params.buckets[2].num_channels = 3;
+
+ params.buckets[2].channels[0].channel = 2462;
+ params.buckets[2].channels[1].channel = 5805;
+ params.buckets[2].channels[2].channel = 5825;
+
+ params.buckets[3].bucket = 3;
+ params.buckets[3].band = WIFI_BAND_A;
+ params.buckets[3].period = 35000; // 35 second
+ params.buckets[3].report_events = 1;
+ params.buckets[3].num_channels = 3; // driver should ignore list since band is specified
+
+ params.buckets[3].channels[0].channel = 2462;
+ params.buckets[3].channels[1].channel = 5805;
+ params.buckets[3].channels[2].channel = 5825;
+ }
+
+ wifi_scan_result_handler handler;
+ memset(&handler, 0, sizeof(handler));
+
+ handler.on_scan_event = on_scan_event;
+
+ scanCmdId = getNewCmdId();
+ printMsg("Starting scan --->\n");
+ printMsg("Number of buckets = %d\n", params.num_buckets);
+ return hal_fn.wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS;
+}
+
+static void stopScan() {
+ wifi_request_id id = scanCmdId;
+ if (id == 0)
+ id = -1;
+
+ hal_fn.wifi_stop_gscan(id, wlan0Handle);
+ scanCmdId = 0;
+}
+
+wifi_scan_result **saved_scan_results;
+unsigned max_saved_scan_results;
+unsigned num_saved_scan_results;
+
+static void on_single_shot_scan_event(wifi_request_id id, wifi_scan_event event) {
+ if(event == WIFI_SCAN_RESULTS_AVAILABLE || event == WIFI_SCAN_THRESHOLD_NUM_SCANS ||
+ event == WIFI_SCAN_THRESHOLD_PERCENT) {
+ printMsg("Received scan complete event: %d\n", event);
+ putEventInCache(EVENT_TYPE_SCAN_COMPLETE, "One scan completed");
+ }
+ else if (event == WIFI_SCAN_FAILED) {
+ printMsg("Received scan event - WIFI_SCAN_FAILED \n");
+ putEventInCache(EVENT_TYPE_SCAN_FAILED, "Scan failed");
+ }
+ else {
+ printMsg("Received unknown scan event: %d \n", event);
+ }
+}
+
+static void on_full_scan_result(wifi_request_id id, wifi_scan_result *r, unsigned buckets_scanned) {
+ if (num_saved_scan_results < max_saved_scan_results) {
+ int alloc_len = offsetof(wifi_scan_result, ie_data) + r->ie_length;
+ wifi_scan_result **result = &(saved_scan_results[num_saved_scan_results]);
+ *result = (wifi_scan_result *)malloc(alloc_len);
+ memcpy(*result, r, alloc_len);
+ printMsg("buckets_scanned - %x\n", buckets_scanned);
+ num_saved_scan_results++;
+ }
+}
+
+static int scanOnce(wifi_band band, wifi_scan_result **results, int num_results) {
+
+ saved_scan_results = results;
+ max_saved_scan_results = num_results;
+ num_saved_scan_results = 0;
+
+ wifi_scan_cmd_params params;
+ memset(&params, 0, sizeof(params));
+
+ params.max_ap_per_scan = 10;
+ params.base_period = 5000; // 5 second by default
+ params.report_threshold_percent = 90;
+ params.report_threshold_num_scans = 1;
+ params.num_buckets = 1;
+
+ params.buckets[0].bucket = 0;
+ params.buckets[0].band = band;
+ params.buckets[0].period = 5000; // 5 second
+ params.buckets[0].report_events = 2; // REPORT_EVENTS_AFTER_EACH_SCAN
+ params.buckets[0].num_channels = 0;
+
+ wifi_scan_result_handler handler;
+ memset(&handler, 0, sizeof(handler));
+ handler.on_scan_event = on_single_shot_scan_event;
+ handler.on_full_scan_result = on_full_scan_result;
+
+ int scanCmdId = getNewCmdId();
+ printMsg("Starting scan --->\n");
+ if (hal_fn.wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS) {
+ while (true) {
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_SCAN_RESULTS_THRESHOLD
+ || info.type == EVENT_TYPE_SCAN_COMPLETE) {
+ int retrieved_num_results = num_saved_scan_results;
+ if (retrieved_num_results == 0) {
+ printMsg("fetched 0 scan results, waiting for more..\n");
+ continue;
+ } else {
+ printMsg("fetched %d scan results\n", retrieved_num_results);
+
+ printMsg("Scan once completed, stopping scan\n");
+ hal_fn.wifi_stop_gscan(scanCmdId, wlan0Handle);
+ saved_scan_results = NULL;
+ max_saved_scan_results = 0;
+ num_saved_scan_results = 0;
+ return retrieved_num_results;
+ }
+ }
+ }
+ } else {
+ return 0;
+ }
+}
+
+static int retrieveScanResults() {
+
+ int num_results = 64;
+ wifi_cached_scan_results *results;
+ results = (wifi_cached_scan_results *)malloc(num_results * sizeof(wifi_cached_scan_results));
+ if (!results) {
+ printMsg("%s:Malloc failed\n",__FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(results, 0, sizeof(wifi_cached_scan_results) * num_results);
+ printMsg("Retrieve Scan results available -->\n");
+ int result = hal_fn.wifi_get_cached_gscan_results(wlan0Handle, 1, num_results, results, &num_results);
+ if (result < 0) {
+ printMsg("failed to fetch scan results : %d\n", result);
+ goto exit;
+ } else {
+ printMsg("fetched %d scan results\n", num_results);
+ }
+
+ printScanHeader();
+ for (int i = 0; i < num_results; i++) {
+ printMsg("ScanId = %d, Scanned buckets 0x%x, Flags = %x, num results = %d\n",
+ results[i].scan_id, results[i].buckets_scanned, results[i].flags,
+ results[i].num_results);
+ for (int j = 0; j < results[i].num_results; j++) {
+ printScanResult(results[i].results[j]);
+ }
+ printMsg("\n");
+ }
+
+exit:
+ if (results) {
+ free(results);
+ }
+ return WIFI_SUCCESS;
+}
+
+
+static int compareScanResultsByRssi(const void *p1, const void *p2) {
+ const wifi_scan_result *result1 = *(const wifi_scan_result **)(p1);
+ const wifi_scan_result *result2 = *(const wifi_scan_result **)(p2);
+
+ /* RSSI is -ve, so lower one wins */
+ if (result1->rssi < result2->rssi) {
+ return 1;
+ } else if (result1->rssi == result2->rssi) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+static void sortScanResultsByRssi(wifi_scan_result **results, int num_results) {
+ qsort(results, num_results, sizeof(wifi_scan_result*), &compareScanResultsByRssi);
+}
+
+static int removeDuplicateScanResults(wifi_scan_result **results, int num) {
+ /* remove duplicates by BSSID */
+ int num_results = num;
+ wifi_scan_result *tmp;
+ for (int i = 0; i < num_results; i++) {
+ for (int j = i + 1; j < num_results; ) {
+ if (memcmp((*results[i]).bssid, (*results[j]).bssid, sizeof(mac_addr)) == 0) {
+ int num_to_move = num_results - j - 1;
+ tmp = results[j];
+ memmove(&results[j], &results[j+1], num_to_move * sizeof(wifi_scan_result *));
+ free(tmp);
+ num_results--;
+ } else {
+ j++;
+ }
+ }
+ }
+ return num_results;
+}
+
+static void onRTTResults (wifi_request_id id, unsigned num_results, wifi_rtt_result *result[]) {
+
+ printMsg("RTT results\n");
+ wifi_rtt_result *rtt_result;
+ mac_addr addr = {0};
+ for (unsigned i = 0; i < num_results; i++) {
+ rtt_result = result[i];
+ if (memcmp(addr, rtt_result->addr, sizeof(mac_addr))) {
+ printMsg("Target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ rtt_result->addr[0],
+ rtt_result->addr[1],
+ rtt_result->addr[2],
+ rtt_result->addr[3],
+ rtt_result->addr[4],
+ rtt_result->addr[5]);
+ memcpy(addr, rtt_result->addr, sizeof(mac_addr));
+ }
+ printMsg("\tburst_num : %d, measurement_number : %d, success_number : %d\n"
+ "\tnumber_per_burst_peer : %d, status : %d, retry_after_duration : %d s\n"
+ "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
+ "\tdistance : %d cm, burst_duration : %d ms, negotiated_burst_num : %d\n",
+ rtt_result->burst_num, rtt_result->measurement_number,
+ rtt_result->success_number, rtt_result->number_per_burst_peer,
+ rtt_result->status, rtt_result->retry_after_duration,
+ rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
+ rtt_result->rtt/1000, rtt_result->rtt_sd, rtt_result->distance_mm / 10,
+ rtt_result->burst_duration, rtt_result->negotiated_burst_num);
+ }
+
+ putEventInCache(EVENT_TYPE_RTT_RESULTS, "RTT results");
+}
+
+static void onHotlistAPFound(wifi_request_id id, unsigned num_results, wifi_scan_result *results) {
+
+ printMsg("Found hotlist APs\n");
+ for (unsigned i = 0; i < num_results; i++) {
+ printScanResult(results[i]);
+ }
+ putEventInCache(EVENT_TYPE_HOTLIST_AP_FOUND, "Found a hotlist AP");
+}
+
+static void onHotlistAPLost(wifi_request_id id, unsigned num_results, wifi_scan_result *results) {
+
+ printMsg("Lost hotlist APs\n");
+ for (unsigned i = 0; i < num_results; i++) {
+ printScanResult(results[i]);
+ }
+ putEventInCache(EVENT_TYPE_HOTLIST_AP_LOST, "Lost event Hotlist APs");
+}
+
+static void onePnoSsidFound(wifi_request_id id, unsigned num_results, wifi_scan_result *results) {
+
+ printMsg("Found ePNO SSID\n");
+ for (unsigned i = 0; i < num_results; i++) {
+ printMsg("SSID %s, %02x:%02x:%02x:%02x:%02x:%02x, channel %d, rssi %d\n",
+ results[i].ssid, results[i].bssid[0], results[i].bssid[1],
+ results[i].bssid[2], results[i].bssid[3], results[i].bssid[4],
+ results[i].bssid[5], results[i].channel, (signed char)results[i].rssi);
+ }
+ putEventInCache(EVENT_TYPE_EPNO_SSID, "Found ePNO SSID");
+}
+
+static void onRssiThresholdbreached(wifi_request_id id, u8 *cur_bssid, s8 cur_rssi) {
+
+ printMsg("RSSI threshold breached, cur RSSI - %d!!\n", cur_rssi);
+ printMsg("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+ cur_bssid[0], cur_bssid[1], cur_bssid[2],
+ cur_bssid[3], cur_bssid[4], cur_bssid[5]);
+ putEventInCache(EVENT_TYPE_RSSI_MONITOR, "RSSI monitor Event");
+}
+
+
+static const u8 *bss_get_ie(u8 id, const char* ie, const s32 ie_len)
+{
+ const u8 *end, *pos;
+
+ pos = (const u8 *)ie;
+ end = pos + ie_len;
+
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ break;
+ if (pos[0] == id)
+ return pos;
+ pos += 2 + pos[1];
+ }
+
+ return NULL;
+}
+static bool is11mcAP(const char* ie, const s32 ie_len)
+{
+ const u8 *ext_cap_ie, *ptr_ie;
+ u8 ext_cap_length = 0;
+ ptr_ie = bss_get_ie(WIFI_EID_EXT_CAPAB, ie, ie_len);
+ if (ptr_ie) {
+ ext_cap_length = *(ptr_ie + TLV_LEN_OFF);
+ ext_cap_ie = ptr_ie + TLV_BODY_OFF;
+ if ((ext_cap_length >= CEIL(DOT11_EXT_CAP_FTM_RESPONDER, NBBY)) &&
+ (isset(ext_cap_ie, DOT11_EXT_CAP_FTM_RESPONDER) ||
+ isset(ext_cap_ie, DOT11_EXT_CAP_FTM_INITIATOR))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#define CHAN_FACTOR_6_G 11900u /* 6 GHz band, 5950 MHz */
+int channel2mhz_6g(uint ch)
+{
+ int freq;
+ freq = (ch * 5) + (CHAN_FACTOR_6_G / 2);
+ return freq;
+}
+
+int channel2mhz(uint ch)
+{
+ int freq;
+ int start_factor = (ch > 14)? CHAN_FACTOR_5_G : CHAN_FACTOR_2_4_G;
+ if ((start_factor == CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
+ (ch > 200))
+ freq = -1;
+ else if ((start_factor == CHAN_FACTOR_2_4_G) && (ch == 14))
+ freq = 2484;
+ else
+ freq = ch * 5 + start_factor / 2;
+
+ return freq;
+}
+
+struct ht_op_ie *read_ht_oper_ie(const char* ie, const s32 ie_len)
+{
+ const u8 *ptr_ie;
+ ptr_ie = bss_get_ie(WIFI_EID_HT_OPERATION, ie, ie_len);
+ if (ptr_ie) {
+ return (struct ht_op_ie *)(ptr_ie + TLV_BODY_OFF);
+ }
+ return NULL;
+}
+
+struct vht_op_ie *read_vht_oper_ie(const char* ie, const s32 ie_len)
+{
+ const u8 *ptr_ie;
+ ptr_ie = bss_get_ie(WIFI_EID_VHT_OPERATION, ie, ie_len);
+ if (ptr_ie) {
+ return (struct vht_op_ie *)(ptr_ie + TLV_BODY_OFF);
+ }
+ return NULL;
+}
+
+wifi_channel_info convert_channel(int ch, int chan_width, bool is_6g)
+{
+ wifi_channel_info chan_info;
+ memset(&chan_info, 0, sizeof(wifi_channel_info));
+
+ chan_info.width = (wifi_channel_width)chan_width;
+ if (is_6g) {
+ chan_info.center_freq = channel2mhz_6g(ch);
+ return chan_info;
+ } else {
+ chan_info.center_freq = channel2mhz(ch);
+ }
+ if (chan_width == WIFI_CHAN_WIDTH_160) {
+ if ((ch >= 36) && (ch <= 64))
+ chan_info.center_freq0 = 5250;
+ if ((ch >= 100) && (ch <= 128))
+ chan_info.center_freq0 = 5570;
+ if ((ch >= 149) && (ch <= 177))
+ chan_info.center_freq0 = 5815;
+ } else if (chan_width == WIFI_CHAN_WIDTH_80) {
+ /*primary is the lowest channel*/
+ if ((ch >= 36) && (ch <= 48))
+ chan_info.center_freq0 = 5210;
+ else if ((ch >= 52) && (ch <= 64))
+ chan_info.center_freq0 = 5290;
+ else if ((ch >= 100) && (ch <= 112))
+ chan_info.center_freq0 = 5530;
+ else if ((ch >= 116) && (ch <= 128))
+ chan_info.center_freq0 = 5610;
+ else if ((ch >= 132) && (ch <= 144))
+ chan_info.center_freq0 = 5690;
+ else if ((ch >= 149) && (ch <= 161))
+ chan_info.center_freq0 = 5775;
+ } else {
+ if (chan_width == WIFI_CHAN_WIDTH_40) {
+ if ((ch >= 36) && (ch <= 40))
+ chan_info.center_freq0 = 5190;
+ else if ((ch >= 44) && (ch <= 48))
+ chan_info.center_freq0 = 5230;
+ else if ((ch >= 52) && (ch <= 56))
+ chan_info.center_freq0 = 5270;
+ else if ((ch >= 60) && (ch <= 64))
+ chan_info.center_freq0 = 5310;
+ else if ((ch >= 100) && (ch <= 104))
+ chan_info.center_freq0 = 5510;
+ else if ((ch >= 108) && (ch <= 112))
+ chan_info.center_freq0 = 5550;
+ else if ((ch >= 116) && (ch <= 120))
+ chan_info.center_freq0 = 5590;
+ else if ((ch >= 124) && (ch <= 128))
+ chan_info.center_freq0 = 5630;
+ else if ((ch >= 132) && (ch <= 136))
+ chan_info.center_freq0 = 5670;
+ else if ((ch >= 140) && (ch <= 144))
+ chan_info.center_freq0 = 5710;
+ else if ((ch >= 149) && (ch <= 153))
+ chan_info.center_freq0 = 5755;
+ else if ((ch >= 157) && (ch <= 161))
+ chan_info.center_freq0 = 5795;
+ }
+ }
+ return chan_info;
+}
+
+wifi_channel_info get_channel_of_ie(const char* ie, const s32 ie_len)
+{
+ struct vht_op_ie *vht_op;
+ struct ht_op_ie *ht_op;
+ const u8 *ptr_ie;
+ wifi_channel_info chan_info;
+ memset(&chan_info, 0, sizeof(wifi_channel_info));
+ vht_op = read_vht_oper_ie(ie, ie_len);
+ if ((vht_op = read_vht_oper_ie(ie, ie_len)) &&
+ (ht_op = read_ht_oper_ie(ie, ie_len))) {
+ /* VHT mode */
+ if (vht_op->chan_width == VHT_OP_CHAN_WIDTH_80) {
+ chan_info.width = WIFI_CHAN_WIDTH_80;
+ /* primary channel */
+ chan_info.center_freq = channel2mhz(ht_op->ctl_ch);
+ /* center frequency */
+ chan_info.center_freq0 = channel2mhz(vht_op->chan1);
+ return chan_info;
+ }
+ }
+ if (ht_op = read_ht_oper_ie(ie, ie_len)){
+ /* HT mode */
+ /* control channel */
+ chan_info.center_freq = channel2mhz(ht_op->ctl_ch);
+ chan_info.width = WIFI_CHAN_WIDTH_20;
+ switch (ht_op->chan_info & DOT11_EXT_CH_MASK) {
+ chan_info.center_freq = channel2mhz(ht_op->ctl_ch);
+ case DOT11_EXT_CH_UPPER:
+ chan_info.width = WIFI_CHAN_WIDTH_40;
+ break;
+ case DOT11_EXT_CH_LOWER:
+ chan_info.width = WIFI_CHAN_WIDTH_40;
+ break;
+ case DOT11_EXT_CH_NONE:
+ break;
+ }
+ } else {
+ chan_info.width = WIFI_CHAN_WIDTH_20;
+ ptr_ie = bss_get_ie(WIFI_EID_DS_PARAMS, ie, ie_len);
+ if (ptr_ie) {
+ chan_info.center_freq = channel2mhz(ptr_ie[TLV_BODY_OFF]);
+ }
+ }
+ return chan_info;
+}
+
+static void testRTT()
+{
+ wifi_scan_result *results[max_ap];
+ wifi_scan_result *scan_param;
+ u32 num_ap = 0;
+ /*For STA-STA RTT */
+ u32 num_sta = 0;
+ int result = 0;
+ /* Run by a provided rtt-ap-list file */
+ FILE* w_fp = NULL;
+ wifi_rtt_config params[max_ap];
+ if (!rtt_from_file && !rtt_sta && !rtt_nan) {
+ /* band filter for a specific band */
+ if (band == WIFI_BAND_UNSPECIFIED)
+ band = WIFI_BAND_ABG;
+ int num_results = scanOnce(band, results, max_ap);
+ if (num_results == 0) {
+ printMsg("RTT aborted because of no scan results\n");
+ return;
+ } else {
+ printMsg("Retrieved %d scan results\n", num_results);
+ }
+
+ num_results = removeDuplicateScanResults(results, num_results);
+
+ sortScanResultsByRssi(results, num_results);
+ printMsg("Sorted scan results -\n");
+ for (int i = 0; i < num_results; i++) {
+ printScanResult(*results[i]);
+ }
+ if (rtt_to_file) {
+ /* Write a RTT AP list to a file */
+ w_fp = fopen(rtt_aplist, "w");
+ if (w_fp == NULL) {
+ printMsg("failed to open the file : %s\n", rtt_aplist);
+ return;
+ }
+ fprintf(w_fp, "|SSID|BSSID|Primary Freq|Center Freq|Channel BW(0=20MHZ,1=40MZ,2=80MHZ)"
+ "|rtt_type(1=1WAY,2=2WAY,3=auto)|Peer Type(STA=0, AP=1)|burst period|"
+ "Num of Burst|FTM retry count|FTMR retry count|LCI|LCR|Burst Duration|Preamble|BW\n");
+ }
+ for (int i = 0; i < min(num_results, max_ap); i++) {
+ scan_param = results[i];
+ if(is11mcAP(&scan_param->ie_data[0], scan_param->ie_length)) {
+ memcpy(params[num_ap].addr, scan_param->bssid, sizeof(mac_addr));
+ mac_addr &addr = params[num_ap].addr;
+ printMsg("Adding %s(%02x:%02x:%02x:%02x:%02x:%02x) on Freq (%d) for 11mc RTT\n",
+ scan_param->ssid, addr[0], addr[1],
+ addr[2], addr[3], addr[4], addr[5],
+ scan_param->channel);
+ params[num_ap].type = default_rtt_param.type;
+ params[num_ap].channel = get_channel_of_ie(&scan_param->ie_data[0],
+ scan_param->ie_length);
+ params[num_ap].peer = RTT_PEER_AP;
+ params[num_ap].num_burst = default_rtt_param.num_burst;
+ params[num_ap].num_frames_per_burst = default_rtt_param.num_frames_per_burst;
+ params[num_ap].num_retries_per_rtt_frame =
+ default_rtt_param.num_retries_per_ftm;
+ params[num_ap].num_retries_per_ftmr = default_rtt_param.num_retries_per_ftmr;
+ params[num_ap].burst_period = default_rtt_param.burst_period;
+ params[num_ap].burst_duration = default_rtt_param.burst_duration;
+ params[num_ap].LCI_request = default_rtt_param.LCI_request;
+ params[num_ap].LCR_request = default_rtt_param.LCR_request;
+ params[num_ap].preamble = (wifi_rtt_preamble)default_rtt_param.preamble;
+ params[num_ap].bw = (wifi_rtt_bw)default_rtt_param.bw;
+ if (rtt_to_file) {
+ fprintf(w_fp, "%s %02x:%02x:%02x:%02x:%02x:%02x %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", scan_param->ssid,
+ params[num_ap].addr[0], params[num_ap].addr[1], params[num_ap].addr[2], params[num_ap].addr[3],
+ params[num_ap].addr[4], params[num_ap].addr[5],params[num_ap].channel.center_freq,
+ params[num_ap].channel.center_freq0, params[num_ap].channel.width, params[num_ap].type,params[num_ap].peer,
+ params[num_ap].burst_period, params[num_ap].num_burst, params[num_ap].num_frames_per_burst,
+ params[num_ap].num_retries_per_rtt_frame, params[num_ap].num_retries_per_ftmr,
+ params[num_ap].LCI_request, params[num_ap].LCR_request, params[num_ap].burst_duration,
+ params[num_ap].preamble, params[num_ap].bw);
+ }
+ num_ap++;
+ } else {
+ /* legacy AP */
+ }
+ }
+ /* free the results data */
+ for (int i = 0; i < num_results; i++) {
+ free(results[i]);
+ results[i] = NULL;
+ }
+ if (w_fp)
+ fclose(w_fp);
+ } else if (rtt_sta || rtt_nan) {
+ printf(" Run initiator rtt sta/nan, rtt_sta = %d, rtt_nan = %d \n",
+ rtt_sta, rtt_nan);
+ /* As we have only one target */
+ memcpy(params[num_sta].addr, responder_addr, sizeof(mac_addr));
+ params[num_sta].channel = convert_channel(responder_channel, channel_width, is_6g);
+ printMsg("Adding(" MACSTR ") on Freq (%d),(%d) for 11mc RTT\n",
+ MAC2STR(responder_addr),
+ params[num_sta].channel.center_freq,
+ params[num_sta].channel.center_freq0);
+ /*As we are doing STA-STA RTT */
+ params[num_sta].type = default_rtt_param.type;
+ if (rtt_nan) {
+ params[num_sta].peer = RTT_PEER_NAN;
+ } else if (rtt_sta) {
+ params[num_sta].peer = RTT_PEER_STA;
+ }
+ params[num_sta].num_burst = default_rtt_param.num_burst;
+ params[num_sta].num_frames_per_burst = default_rtt_param.num_frames_per_burst;
+ params[num_sta].num_retries_per_rtt_frame =
+ default_rtt_param.num_retries_per_ftm;
+ params[num_sta].num_retries_per_ftmr = default_rtt_param.num_retries_per_ftmr;
+ params[num_sta].burst_period = default_rtt_param.burst_period;
+ params[num_sta].burst_duration = default_rtt_param.burst_duration;
+ params[num_sta].LCI_request = default_rtt_param.LCI_request;
+ params[num_sta].LCR_request = default_rtt_param.LCR_request;
+ params[num_sta].preamble = (wifi_rtt_preamble)default_rtt_param.preamble;
+ params[num_sta].bw = (wifi_rtt_bw)default_rtt_param.bw;
+ num_sta++;
+
+ } else {
+
+ /* Run by a provided rtt-ap-list file */
+ FILE* fp;
+ char bssid[ETHER_ADDR_STR_LEN];
+ char ssid[MAX_SSID_LEN];
+ char first_char;
+ memset(bssid, 0, sizeof(bssid));
+ memset(ssid, 0, sizeof(ssid));
+ /* Read a RTT AP list from a file */
+ fp = fopen(rtt_aplist, "r");
+ if (fp == NULL) {
+ printMsg("\nRTT AP list file does not exist on %s.\n"
+ "Please specify correct full path or use default one, %s, \n"
+ " by following order in file, such as:\n"
+ "|SSID|BSSID|chan_num|Channel BW(0=20MHZ,1=40MZ,2=80MHZ)|"
+ "RTT_Type(1=1WAY,2=2WAY,3=auto)|Peer Type(STA=0, AP=1)|Burst Period|"
+ "No of Burst|No of FTM Burst|FTM Retry Count|FTMR Retry Count|LCI|LCR|"
+ "Burst Duration|Preamble|Bandwith\n",
+ rtt_aplist, DEFAULT_RTT_FILE);
+ return;
+ }
+ printMsg(" %-16s%-20s%-8s%-12s%-10s%-10s%-16s%-10s%-14s%-11s%-12s%-5s%-5s%-15s%-10s\n",
+ "SSID", "BSSID", "chan", "Bandwidth", "RTT_Type", "RTT_Peer",
+ "Burst_Period", "No_Burst", "No_FTM_Burst", "FTM_Retry",
+ "FTMR_Retry", "LCI", "LCR", "Burst_duration", "Preamble", "Bandwidth");
+ int i = 0;
+ while (!feof(fp)) {
+ if ((fscanf(fp, "%c", &first_char) == 1) && (first_char != '|')) {
+ fseek(fp, -1, SEEK_CUR);
+ result = fscanf(fp, "%s %s %u %u %u %u %u %u %u %u %u %hhu %hhu %u %hhu %hhu\n",
+ ssid, bssid, (unsigned int*)&responder_channel,
+ (unsigned int*)&channel_width,
+ (unsigned int*)&params[i].type, (unsigned int*)&params[i].peer,
+ &params[i].burst_period, &params[i].num_burst,
+ &params[i].num_frames_per_burst,
+ &params[i].num_retries_per_rtt_frame,
+ &params[i].num_retries_per_ftmr,
+ (unsigned char*)&params[i].LCI_request,
+ (unsigned char*)&params[i].LCR_request,
+ (unsigned int*)&params[i].burst_duration,
+ (unsigned char*)&params[i].preamble,
+ (unsigned char*)&params[i].bw);
+
+ if (result != 16) {
+ printMsg("fscanf failed %d\n", result);
+ break;
+ }
+ params[i].channel = convert_channel(responder_channel, channel_width, is_6g);
+ parseMacAddress(bssid, params[i].addr);
+
+ printMsg("[%d] %-16s%-20s%-8u%-14u%-12d%-10d%-10u%-16u%-10u%-14u%-11u%-12u%-5hhu%-5hhu%-15u%-10hhu-10hhu\n",
+ i+1, ssid, bssid, params[i].channel.center_freq,
+ params[i].channel.center_freq0, params[i].channel.width,
+ params[i].type, params[i].peer, params[i].burst_period,
+ params[i].num_burst, params[i].num_frames_per_burst,
+ params[i].num_retries_per_rtt_frame,
+ params[i].num_retries_per_ftmr, params[i].LCI_request,
+ params[i].LCR_request, params[i].burst_duration, params[i].preamble, params[i].bw);
+
+ i++;
+ } else {
+ /* Ignore the rest of the line. */
+ result = fscanf(fp, "%*[^\n]");
+ if (result != 1) {
+ printMsg("fscanf failed %d\n", result);
+ break;
+ }
+
+ result = fscanf(fp, "\n");
+ if (result != 1) {
+ printMsg("fscanf failed %d\n", result);
+ break;
+ }
+ }
+ }
+ num_ap = i;
+ fclose(fp);
+ fp = NULL;
+ }
+
+ wifi_rtt_event_handler handler;
+ handler.on_rtt_results = &onRTTResults;
+ if (!rtt_to_file || rtt_sta || rtt_nan) {
+ if (num_ap || num_sta) {
+ if (num_ap) {
+ printMsg("Configuring RTT for %d APs\n", num_ap);
+ result = hal_fn.wifi_rtt_range_request(rttCmdId, wlan0Handle, num_ap, params, handler);
+ } else if (num_sta) {
+ printMsg("Configuring RTT for %d sta \n", num_sta);
+ result = hal_fn.wifi_rtt_range_request(rttCmdId, wlan0Handle, num_sta, params, handler);
+ }
+
+ if (result == WIFI_SUCCESS) {
+ printMsg("\nWaiting for RTT results\n");
+ while (true) {
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_RTT_RESULTS ||
+ info.type == EVENT_TYPE_RTT_RESULTS_DETAIL) {
+ break;
+ }
+ }
+ } else {
+ printMsg("Could not set setRTTAPs : %d\n", result);
+ }
+ } else {
+ printMsg("no candidate for RTT\n");
+ }
+ } else {
+ printMsg("written AP info into file %s successfully\n", rtt_aplist);
+ }
+}
+
+static int cancelRTT()
+{
+ int ret;
+ ret = hal_fn.wifi_rtt_range_cancel(rttCmdId, wlan0Handle, 0, NULL);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Successfully cancelled the RTT\n");
+ }
+ return ret;
+}
+
+static void getRTTCapability()
+{
+ int ret;
+ wifi_rtt_capabilities rtt_capability;
+ ret = hal_fn.wifi_get_rtt_capabilities(wlan0Handle, &rtt_capability);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Supported Capabilites of RTT :\n");
+ if (rtt_capability.rtt_one_sided_supported)
+ printMsg("One side RTT is supported\n");
+ if (rtt_capability.rtt_ftm_supported)
+ printMsg("FTM(11mc) RTT is supported\n");
+ if (rtt_capability.lci_support)
+ printMsg("LCI is supported\n");
+ if (rtt_capability.lcr_support)
+ printMsg("LCR is supported\n");
+ if (rtt_capability.bw_support) {
+ printMsg("BW(%s %s %s %s) are supported\n",
+ (rtt_capability.bw_support & BW_20_SUPPORT) ? "20MHZ" : "",
+ (rtt_capability.bw_support & BW_40_SUPPORT) ? "40MHZ" : "",
+ (rtt_capability.bw_support & BW_80_SUPPORT) ? "80MHZ" : "",
+ (rtt_capability.bw_support & BW_160_SUPPORT) ? "160MHZ" : "");
+ }
+ if (rtt_capability.preamble_support) {
+ printMsg("Preamble(%s %s %s) are supported\n",
+ (rtt_capability.preamble_support & PREAMBLE_LEGACY) ? "Legacy" : "",
+ (rtt_capability.preamble_support & PREAMBLE_HT) ? "HT" : "",
+ (rtt_capability.preamble_support & PREAMBLE_VHT) ? "VHT" : "");
+
+ }
+ } else {
+ printMsg("Could not get the rtt capabilities : %d\n", ret);
+ }
+
+}
+
+/* TWT related apis */
+static void setupTwtRequest(char *argv[]) {
+ TwtSetupRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *endptr, *param, *val_p;
+
+ /* Set Default twt setup request params */
+ memset(&msg, 0, sizeof(msg));
+
+ /* Parse args for twt params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-config_id") == 0) {
+ msg.config_id = atoi(val_p);
+ } else if (strcmp(param, "-neg_type") == 0) {
+ msg.negotiation_type = atoi(val_p);
+ } else if (strcmp(param, "-trigger_type") == 0) {
+ msg.trigger_type = atoi(val_p);
+ } else if (strcmp(param, "-wake_dur_us") == 0) {
+ msg.wake_dur_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_int_us") == 0) {
+ msg.wake_int_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_int_min_us") == 0) {
+ msg.wake_int_min_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_int_max_us") == 0) {
+ msg.wake_int_max_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_dur_min_us") == 0) {
+ msg.wake_dur_min_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_dur_max_us") == 0) {
+ msg.wake_dur_max_us = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-avg_pkt_size") == 0) {
+ msg.avg_pkt_size = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-avg_pkt_num") == 0) {
+ msg.avg_pkt_num = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-wake_time_off_us") == 0) {
+ msg.wake_time_off_us = strtoul(val_p, &endptr, 0);
+ } else {
+ printMsg("%s:Unsupported Parameter for twt setup request\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ret = twt_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize twt handlers %d\n", ret);
+ goto exit;
+ }
+ ret = twt_setup_request(wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void TeardownTwt(char *argv[]) {
+ TwtTeardownRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param, *val_p;
+
+ /* Set Default twt teardown params */
+ memset(&msg, 0, sizeof(msg));
+
+ /* Parse args for twt params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-config_id") == 0) {
+ msg.config_id = atoi(val_p);
+ } else if (strcmp(param, "-all_twt") == 0) {
+ msg.all_twt = atoi(val_p);
+ } else if (strcmp(param, "-neg_type") == 0) {
+ msg.negotiation_type = atoi(val_p);
+ } else {
+ printMsg("%s:Unsupported Parameter for twt teardown request\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ret = twt_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize twt handlers %d\n", ret);
+ goto exit;
+ }
+ ret = twt_teardown_request(wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void InfoFrameTwt(char *argv[]) {
+ TwtInfoFrameRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param, *val_p;
+
+ /* Set Default twt info frame params */
+ memset(&msg, 0, sizeof(msg));
+
+ /* Parse args for twt params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-config_id") == 0) {
+ msg.config_id = atoi(val_p);
+ } else if (strcmp(param, "-all_twt") == 0) {
+ msg.all_twt = atoi(val_p);
+ } else if (strcmp(param, "-resume_time_us") == 0) {
+ msg.resume_time_us = atoi(val_p);
+ } else {
+ printMsg("%s:Unsupported Parameter for twt info request\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ret = twt_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize twt handlers %d\n", ret);
+ goto exit;
+ }
+ ret = twt_info_frame_request(wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void GetTwtStats(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param, *val_p;
+ u8 config_id = 1;
+ TwtStats twt_stats;
+
+ /* Parse args for twt params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-config_id") == 0) {
+ config_id = atoi(val_p);
+ } else {
+ printMsg("%s:Unsupported Parameter for get stats request\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ memset(&twt_stats, 0, sizeof(twt_stats));
+ ret = twt_get_stats(wlan0Handle, config_id, &twt_stats);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("TWT stats :\n");
+ if (twt_stats.config_id)
+ printMsg("config id = %d\n", twt_stats.config_id);
+ if (twt_stats.avg_pkt_num_tx)
+ printMsg("avg_pkt_num_tx = %d\n", twt_stats.avg_pkt_num_tx);
+ if (twt_stats.avg_pkt_num_rx)
+ printMsg("avg_pkt_num_rx = %d\n", twt_stats.avg_pkt_num_rx);
+ if (twt_stats.avg_tx_pkt_size)
+ printMsg("avg_tx_pkt_size = %d\n", twt_stats.avg_tx_pkt_size);
+ if (twt_stats.avg_rx_pkt_size)
+ printMsg("avg_rx_pkt_size = %d\n", twt_stats.avg_rx_pkt_size);
+ if (twt_stats.avg_eosp_dur_us)
+ printMsg("avg_eosp_dur_us = %d\n", twt_stats.avg_eosp_dur_us);
+ if (twt_stats.eosp_count)
+ printMsg("eosp_count = %d\n", twt_stats.eosp_count);
+
+ return;
+ }
+exit:
+ printMsg("Could not get the twt stats : err %d\n", ret);
+ return;
+}
+
+void ClearTwtStats(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param, *val_p;
+ u8 config_id = 1;
+
+ /* Parse args for twt params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-config_id") == 0) {
+ config_id = atoi(val_p);
+ } else {
+ printMsg("%s:Unsupported Parameter for twt info request\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ret = twt_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize twt handlers %d\n", ret);
+ goto exit;
+ }
+ ret = twt_clear_stats(wlan0Handle, config_id);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void getTWTCapability() {
+ int ret;
+ TwtCapabilitySet twt_capability;
+
+ ret = twt_get_capability(wlan0Handle, &twt_capability);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Supported Capabilites of TWT :\n");
+ if (twt_capability.device_capability.requester_supported)
+ printMsg("Device Requester supported\n");
+ if (twt_capability.device_capability.responder_supported)
+ printMsg("Device Responder supported\n");
+ if (twt_capability.device_capability.broadcast_twt_supported)
+ printMsg("Device Broadcast twt supported\n");
+ if (twt_capability.device_capability.flexibile_twt_supported)
+ printMsg("Device Flexibile twt supported\n");
+ if (twt_capability.peer_capability.requester_supported)
+ printMsg("Peer Requester supported\n");
+ if (twt_capability.peer_capability.responder_supported)
+ printMsg("Peer Responder supported\n");
+ if (twt_capability.peer_capability.broadcast_twt_supported)
+ printMsg("Peer Broadcast twt supported\n");
+ if (twt_capability.peer_capability.flexibile_twt_supported)
+ printMsg("Peer Flexibile twt supported\n");
+ } else {
+ printMsg("Could not get the twt capabilities : %d\n", ret);
+ }
+ return;
+}
+
+static void showResponderCapability(wifi_rtt_responder responder_info)
+{
+ wifi_channel_info channel_info;
+ channel_info = responder_info.channel;
+ printMsg("Centre freq = %d \n",channel_info.center_freq);
+ if (channel_info.width == WIFI_CHAN_WIDTH_20) {
+ printMsg("channel width = 20 \n");
+ } else if (channel_info.width == WIFI_CHAN_WIDTH_40) {
+ printMsg("channel width = 40 \n");
+ } else if (channel_info.width == WIFI_CHAN_WIDTH_80) {
+ printMsg("channel width = 80 \n");
+ }
+ if (channel_info.width == WIFI_CHAN_WIDTH_40 || channel_info.width == WIFI_CHAN_WIDTH_80) {
+ printMsg("CentreFreq0 = %d \n",channel_info.center_freq0);
+ }
+ if (responder_info.preamble & WIFI_RTT_PREAMBLE_HT) {
+ printMsg("Responder preamble = %d \n",responder_info.preamble);
+ }
+ if (responder_info.preamble & WIFI_RTT_PREAMBLE_VHT) {
+ printMsg("Responder preamble = %d \n",responder_info.preamble);
+ }
+ if (responder_info.preamble & WIFI_RTT_PREAMBLE_LEGACY) {
+ printMsg("Responder preamble = %d \n",responder_info.preamble);
+ }
+}
+
+static int getRttResponderInfo()
+{
+ int ret;
+ wifi_rtt_responder responder_info;
+ ret = hal_fn.wifi_rtt_get_responder_info(wlan0Handle, &responder_info);
+ if (ret == WIFI_SUCCESS) {
+ showResponderCapability(responder_info);
+ }
+ return ret;
+}
+
+static int RttEnableResponder()
+{
+ int ret = 0;
+ wifi_request_id id = 0;
+ wifi_channel_info channel_hint;
+ memset(&channel_hint, 0, sizeof(wifi_channel_info));
+ wifi_rtt_responder responder_info;
+ unsigned int max_duration_sec = 0;
+
+ ret = hal_fn.wifi_enable_responder(id, wlan0Handle, channel_hint,
+ max_duration_sec, &responder_info);
+ if (ret == WIFI_SUCCESS) {
+ showResponderCapability(responder_info);
+ }
+ return ret;
+}
+
+static int cancelRttResponder()
+{
+ int ret = 0;
+ wifi_request_id id = 0;
+
+ ret = hal_fn.wifi_disable_responder(id, wlan0Handle);
+ return ret;
+}
+
+/* CHRA NAN RTT related */
+static void OnChreNanRttStateChanged(chre_nan_rtt_state state) {
+ printMsg("CHRE NAN RTT state update : %d\n", state);
+ putEventInCache(EVENT_TYPE_CHRE_NAN_RTT_STATE_UPDATED, "CHRE NAN RTT state updated");
+}
+
+static void enableChreNanRtt() {
+ wifi_error ret = WIFI_SUCCESS;
+ ret = hal_fn.wifi_nan_rtt_chre_enable_request(0, wlan0Handle, NULL);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to enable CHRE NAN RTT: %d\n", ret);
+ }
+
+ return;
+}
+
+static void disableChreNanRtt() {
+ wifi_error ret = WIFI_SUCCESS;
+ ret = hal_fn.wifi_nan_rtt_chre_disable_request(0, wlan0Handle);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to disable CHRE NAN RTT: %d\n", ret);
+ }
+
+ return;
+}
+
+static void registerChreCallback() {
+ wifi_error ret = WIFI_SUCCESS;
+ EventInfo info;
+ wifi_chre_handler handler;
+ handler.on_chre_nan_rtt_change = OnChreNanRttStateChanged;
+ ret = hal_fn.wifi_chre_register_handler(wlan0Handle, handler);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to register CHRE callback: %d\n", ret);
+ } else {
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_CHRE_NAN_RTT_STATE_UPDATED) {
+ printMsg("Received CHRE NAN RTT state, end the CHRE NAN RTT monitor!!\n");
+ break;
+ }
+ }
+ }
+ return;
+}
+
+static void printCachedScanResults(wifi_cached_scan_report *cache_report) {
+ int scanned_channel[MAX_CH_BUF_SIZE] = {0};
+ wifi_cached_scan_result cached_results[MAX_CACHED_SCAN_RESULT];
+ memset(&cached_results, 0, sizeof(cached_results));
+
+ if (cache_report->ts) {
+ printMsg("Printing scan results were queried at (%lu) (in microseconds):\n",
+ cache_report->ts);
+ }
+ printMsg("--------------------------------------\n");
+ if (cache_report->scanned_freq_num > MAX_CH_BUF_SIZE ) {
+ cache_report->scanned_freq_num = MAX_CH_BUF_SIZE;
+ }
+
+ if (cache_report->scanned_freq_num && cache_report->scanned_freq_list) {
+ memcpy(scanned_channel, cache_report->scanned_freq_list,
+ cache_report->scanned_freq_num * sizeof(u32));
+ }
+
+ if (cache_report->result_cnt > MAX_CACHED_SCAN_RESULT) {
+ cache_report->result_cnt = MAX_CACHED_SCAN_RESULT;
+ }
+
+ if (cache_report->result_cnt && cache_report->results) {
+ memcpy(cached_results, cache_report->results,
+ cache_report->result_cnt * sizeof(wifi_cached_scan_result));
+ }
+
+ printMsg("(%d) channels were scanned:\n", cache_report->scanned_freq_num);
+ for (int i = 0; i < cache_report->scanned_freq_num; i++) {
+ printMsg("%d, ", scanned_channel[i]);
+ }
+ printMsg("\n");
+ printMsg("(%d) results reported:\n", cache_report->result_cnt);
+ for (int i = 0; i < cache_report->result_cnt; i++) {
+ printMsg("ssid:%s,bssid: %02x:%02x:%02x:%02x:%02x:%02x,"
+ "rssi: %d, primary_freq: %d, bw: %d, capability: 0x%x,"
+ "flags: 0x%x, age_ms: %d\n",
+ cached_results[i].ssid,
+ cached_results[i].bssid[0], cached_results[i].bssid[1],
+ cached_results[i].bssid[2], cached_results[i].bssid[3],
+ cached_results[i].bssid[4], cached_results[i].bssid[5],
+ cached_results[i].rssi,
+ cached_results[i].chanspec.primary_frequency,
+ cached_results[i].chanspec.width,
+ cached_results[i].capability, cached_results[i].flags,
+ cached_results[i].age_ms);
+ }
+}
+
+static void on_cached_scan_results(wifi_cached_scan_report *cache_report) {
+ if (!cache_report) {
+ printf("Scan results not found! Issue scan first\n");
+ return;
+ }
+
+ printf("onCachedScanResult scanned_freq_num = %d result_cnt %d \n",
+ cache_report->scanned_freq_num, cache_report->result_cnt);
+ printCachedScanResults(cache_report);
+}
+
+static void getWifiCachedScanResults(void) {
+ wifi_cached_scan_result_handler handler;
+ handler.on_cached_scan_results = on_cached_scan_results;
+
+ wifi_error ret = hal_fn.wifi_get_cached_scan_results(wlan0Handle, handler);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to get cached scan results: %d\n", ret);
+ }
+ return;
+}
+
+static int GetCachedGScanResults(int max, wifi_scan_result *results, int *num)
+{
+ int num_results = 64;
+ wifi_cached_scan_results *results2;
+ results2 = (wifi_cached_scan_results *)malloc(num_results * sizeof(wifi_cached_scan_results));
+ memset(results2, 0, sizeof(wifi_cached_scan_results) * num_results);
+ int ret = hal_fn.wifi_get_cached_gscan_results(wlan0Handle, 1, num_results, results2,
+ &num_results);
+ if (ret < 0) {
+ printMsg("failed to fetch scan results : %d\n", ret);
+ goto exit;
+ } else {
+ printMsg("fetched %d scan data\n", num_results);
+ }
+
+ *num = 0;
+ for (int i = 0; i < num_results; i++) {
+ for (int j = 0; j < results2[i].num_results; j++, (*num)++) {
+ memcpy(&(results[*num]), &(results2[i].results[j]), sizeof(wifi_scan_result));
+ }
+ }
+
+exit:
+ if (results2) {
+ free(results2);
+ }
+ return ret;
+}
+
+
+static wifi_error setHotlistAPsUsingScanResult(wifi_bssid_hotlist_params *params)
+{
+ printMsg("testHotlistAPs Scan started, waiting for event ...\n");
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+
+ wifi_scan_result *results;
+ results = (wifi_scan_result *)malloc(256 * sizeof(wifi_scan_result));
+ memset(results, 0, sizeof(wifi_scan_result) * 256);
+
+ printMsg("Retrieving scan results for Hotlist AP setting\n");
+ int num_results = 256;
+ int result = GetCachedGScanResults(num_results, results, &num_results);
+ if (result < 0) {
+ printMsg("failed to fetch scan results : %d\n", result);
+ if (results) {
+ free(results);
+ }
+ return WIFI_ERROR_UNKNOWN;
+ } else {
+ printMsg("fetched %d scan results\n", num_results);
+ }
+
+ for (int i = 0; i < num_results; i++) {
+ printScanResult(results[i]);
+ }
+
+ for (int i = 0; i < stest_max_ap; i++) {
+ memcpy(params->ap[i].bssid, results[i].bssid, sizeof(mac_addr));
+ params->ap[i].low = -htest_low_threshold;
+ params->ap[i].high = -htest_high_threshold;
+ }
+ params->num_bssid = stest_max_ap;
+
+ if (results) {
+ free(results);
+ }
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error setHotlistAPs() {
+ wifi_bssid_hotlist_params params;
+ memset(&params, 0, sizeof(params));
+
+ params.lost_ap_sample_size = HOTLIST_LOST_WINDOW;
+ if (num_hotlist_bssids > 0) {
+ for (int i = 0; i < num_hotlist_bssids; i++) {
+ memcpy(params.ap[i].bssid, hotlist_bssids[i], sizeof(mac_addr));
+ params.ap[i].low = -htest_low_threshold;
+ params.ap[i].high = -htest_high_threshold;
+ }
+ params.num_bssid = num_hotlist_bssids;
+ } else {
+ setHotlistAPsUsingScanResult(&params);
+ }
+
+ printMsg("BSSID\t\t\tHIGH\tLOW\n");
+ for (int i = 0; i < params.num_bssid; i++) {
+ mac_addr &addr = params.ap[i].bssid;
+ printMsg("%02x:%02x:%02x:%02x:%02x:%02x\t%d\t%d\n", addr[0],
+ addr[1], addr[2], addr[3], addr[4], addr[5],
+ params.ap[i].high, params.ap[i].low);
+ }
+
+ wifi_hotlist_ap_found_handler handler;
+ handler.on_hotlist_ap_found = &onHotlistAPFound;
+ handler.on_hotlist_ap_lost = &onHotlistAPLost;
+ hotlistCmdId = getNewCmdId();
+ printMsg("Setting hotlist APs threshold\n");
+ return hal_fn.wifi_set_bssid_hotlist(hotlistCmdId, wlan0Handle, params, handler);
+}
+
+static void resetHotlistAPs() {
+ printMsg(", stoping Hotlist AP scanning\n");
+ hal_fn.wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
+}
+
+static void setPnoMacOui() {
+ hal_fn.wifi_set_scanning_mac_oui(wlan0Handle, mac_oui);
+}
+
+static void testHotlistAPs(){
+
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+
+ printMsg("starting Hotlist AP scanning\n");
+ bool startScanResult = startScan(stest_max_ap,
+ stest_base_period, stest_threshold_percent, stest_threshold_num_scans);
+ if (!startScanResult) {
+ printMsg("testHotlistAPs failed to start scan!!\n");
+ return;
+ }
+
+ int result = setHotlistAPs();
+ if (result == WIFI_SUCCESS) {
+ printMsg("Waiting for Hotlist AP event\n");
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+
+ if (info.type == EVENT_TYPE_SCAN_COMPLETE) {
+ retrieveScanResults();
+ } else if (info.type == EVENT_TYPE_HOTLIST_AP_FOUND ||
+ info.type == EVENT_TYPE_HOTLIST_AP_LOST) {
+ printMsg("Hotlist APs");
+ if (--max_event_wait > 0)
+ printMsg(", waiting for more event ::%d\n", max_event_wait);
+ else
+ break;
+ }
+ }
+ resetHotlistAPs();
+ } else {
+ printMsg("Could not set AP hotlist : %d\n", result);
+ }
+}
+
+static void testPNO(bool clearOnly, bool scan){
+
+ EventInfo info;
+ int result;
+ wifi_epno_handler handler;
+ handler.on_network_found = &onePnoSsidFound;
+ memset(&info, 0, sizeof(info));
+ if (clearOnly) {
+ result = wifi_reset_epno_list(-1, wlan0Handle);
+ if (result != WIFI_SUCCESS) {
+ printMsg("Failed to reset ePNO!!\n");
+ }
+ return;
+ }
+ epnoCmdId = getNewCmdId();
+ printMsg("configuring ePNO SSIDs num %u\n", epno_cfg.num_networks);
+ result = hal_fn.wifi_set_epno_list(epnoCmdId, wlan0Handle, &epno_cfg, handler);
+ if (result == WIFI_SUCCESS && scan) {
+ bool startScanResult = startScan(stest_max_ap,
+ stest_base_period, stest_threshold_percent, stest_threshold_num_scans);
+ if (!startScanResult) {
+ printMsg("testPNO failed to start scan!!\n");
+ return;
+ }
+ printMsg("Waiting for ePNO events\n");
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+
+ if (info.type == EVENT_TYPE_SCAN_COMPLETE) {
+ retrieveScanResults();
+ } else if (info.type == EVENT_TYPE_EPNO_SSID) {
+ printMsg("FOUND ePNO event");
+ if (--max_event_wait > 0)
+ printMsg(", waiting for more event ::%d\n", max_event_wait);
+ else
+ break;
+ }
+ }
+ //wifi_reset_epno_list(epnoCmdId, wlan0Handle);
+ } else if (result != WIFI_SUCCESS) {
+ printMsg("Could not set ePNO : %d\n", result);
+ }
+}
+
+static void onSignificantWifiChange(wifi_request_id id,
+ unsigned num_results, wifi_significant_change_result **results)
+{
+ printMsg("Significant wifi change for %d\n", num_results);
+ for (unsigned i = 0; i < num_results; i++) {
+ printSignificantChangeResult(results[i]);
+ }
+ putEventInCache(EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE, "significant wifi change noticed");
+}
+
+static int SelectSignificantAPsFromScanResults() {
+ wifi_scan_result *results;
+ results = (wifi_scan_result *)malloc(256 * sizeof(wifi_scan_result));
+ memset(results, 0, sizeof(wifi_scan_result) * 256);
+ printMsg("Retrieving scan results for significant wifi change setting\n");
+ int num_results = 256;
+ int result = GetCachedGScanResults(num_results, results, &num_results);
+ if (result < 0) {
+ printMsg("failed to fetch scan results : %d\n", result);
+ if (results) {
+ free(results);
+ }
+ return WIFI_ERROR_UNKNOWN;
+ } else {
+ printMsg("fetched %d scan results\n", num_results);
+ }
+
+ for (int i = 0; i < num_results; i++) {
+ printScanResult(results[i]);
+ }
+
+ wifi_significant_change_params params;
+ memset(&params, 0, sizeof(params));
+
+ params.rssi_sample_size = swctest_rssi_sample_size;
+ params.lost_ap_sample_size = swctest_rssi_lost_ap;
+ params.min_breaching = swctest_rssi_min_breaching;
+
+ for (int i = 0; i < stest_max_ap; i++) {
+ memcpy(params.ap[i].bssid, results[i].bssid, sizeof(mac_addr));
+ params.ap[i].low = results[i].rssi - swctest_rssi_ch_threshold;
+ params.ap[i].high = results[i].rssi + swctest_rssi_ch_threshold;
+ }
+ params.num_bssid = stest_max_ap;
+
+ printMsg("Settting Significant change params rssi_sample_size#%d lost_ap_sample_size#%d"
+ " and min_breaching#%d\n", params.rssi_sample_size,
+ params.lost_ap_sample_size , params.min_breaching);
+ printMsg("BSSID\t\t\tHIGH\tLOW\n");
+ for (int i = 0; i < params.num_bssid; i++) {
+ mac_addr &addr = params.ap[i].bssid;
+ printMsg("%02x:%02x:%02x:%02x:%02x:%02x\t%d\t%d\n", addr[0],
+ addr[1], addr[2], addr[3], addr[4], addr[5],
+ params.ap[i].high, params.ap[i].low);
+ }
+ wifi_significant_change_handler handler;
+ memset(&handler, 0, sizeof(handler));
+ handler.on_significant_change = &onSignificantWifiChange;
+
+ int id = getNewCmdId();
+ if (results) {
+ free(results);
+ }
+ return hal_fn.wifi_set_significant_change_handler(id, wlan0Handle, params, handler);
+
+}
+
+static void untrackSignificantChange() {
+ printMsg(", Stop tracking SignificantChange\n");
+ hal_fn.wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
+}
+
+static void trackSignificantChange() {
+ printMsg("starting trackSignificantChange\n");
+
+ if (!startScan(stest_max_ap,
+ stest_base_period, stest_threshold_percent, stest_threshold_num_scans)) {
+ printMsg("trackSignificantChange failed to start scan!!\n");
+ return;
+ } else {
+ printMsg("trackSignificantChange Scan started, waiting for event ...\n");
+ }
+
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+
+ int result = SelectSignificantAPsFromScanResults();
+ if (result == WIFI_SUCCESS) {
+ printMsg("Waiting for significant wifi change event\n");
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+
+ if (info.type == EVENT_TYPE_SCAN_COMPLETE) {
+ retrieveScanResults();
+ } else if(info.type == EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE) {
+ printMsg("Received significant wifi change");
+ if (--max_event_wait > 0)
+ printMsg(", waiting for more event ::%d\n", max_event_wait);
+ else
+ break;
+ }
+ }
+ untrackSignificantChange();
+ } else {
+ printMsg("Failed to set significant change ::%d\n", result);
+ }
+}
+
+
+void testScan() {
+ printf("starting scan with max_ap_per_scan#%d base_period#%d threshold#%d \n",
+ stest_max_ap,stest_base_period, stest_threshold_percent);
+ if (!startScan(stest_max_ap,
+ stest_base_period, stest_threshold_percent, stest_threshold_num_scans)) {
+ printMsg("failed to start scan!!\n");
+ return;
+ } else {
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+
+ while (true) {
+ getEventFromCache(info);
+ printMsg("retrieved event %d : %s\n", info.type, info.buf);
+ if (info.type == EVENT_TYPE_SCAN_COMPLETE)
+ continue;
+ retrieveScanResults();
+ if(--max_event_wait > 0)
+ printMsg("Waiting for more :: %d event \n", max_event_wait);
+ else
+ break;
+ }
+
+ stopScan();
+ printMsg("stopped scan\n");
+ }
+}
+
+void testStopScan() {
+ stopScan();
+ printMsg("stopped scan\n");
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Logger feature set
+
+static void onRingBufferData(char *ring_name, char *buffer, int buffer_size,
+ wifi_ring_buffer_status *status)
+{
+ // helper for LogHandler
+
+ static int cnt = 1;
+ FILE* w_fp;
+ static int f_count = 0;
+ char ring_file[FILE_NAME_LEN];
+ char *pBuff;
+
+ if (!buffer || buffer_size <= 0) {
+ printMsg("No data in dump buffer\n");
+ return;
+ }
+
+ printMsg("\n%d) RingId=%d, Name=%s, Flags=%u, DebugLevel=%u, "
+ "wBytes=%u, rBytes=%u, RingSize=%u, wRecords=%u\n",
+ cnt++, status->ring_id, status->name, status->flags,
+ status->verbose_level, status->written_bytes,
+ status->read_bytes, status->ring_buffer_byte_size,
+ status->written_records);
+
+ wifi_ring_buffer_entry *buffer_entry = (wifi_ring_buffer_entry *) buffer;
+
+ printMsg("Format: (%d) ", buffer_entry->flags);
+ if (buffer_entry->flags & RING_BUFFER_ENTRY_FLAGS_HAS_BINARY)
+ printMsg("\"BINARY\" ");
+ if (buffer_entry->flags & RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP)
+ printMsg("\"TIMESTAMP\"");
+
+ printMsg(", Type: %s (%d)", RBentryTypeToString(buffer_entry->type), buffer_entry->type);
+ printMsg(", TS: %llu ms", buffer_entry->timestamp);
+ printMsg(", Size: %d bytes\n", buffer_entry->entry_size);
+
+ pBuff = (char *) (buffer_entry + 1);
+ snprintf(ring_file, FILE_NAME_LEN, "%s%s-%d.bin", RINGDATA_PREFIX, ring_name, f_count);
+ w_fp = fopen(ring_file, "a");
+ if (w_fp == NULL) {
+ printMsg("Failed to open a file: %s\n", ring_file);
+ return;
+ }
+
+ fwrite(pBuff, 1, buffer_entry->entry_size, w_fp);
+ if (ftell(w_fp) >= FILE_MAX_SIZE) {
+ f_count++;
+ if (f_count >= NUM_ALERT_DUMPS)
+ f_count = 0;
+ }
+ fclose(w_fp);
+ w_fp = NULL;
+
+ printMsg("Data: ");
+ if (buffer_entry->flags & RING_BUFFER_ENTRY_FLAGS_HAS_BINARY) {
+ for (int i = 0; i < buffer_size; i++)
+ printMsg("%02x ", buffer[i]);
+ printMsg("\n");
+ } else {
+ printMsg("%s\n", pBuff);
+ }
+
+ /*
+ * Parsing Wake Lock event
+ */
+ if (buffer_entry->type == ENTRY_TYPE_WAKE_LOCK) {
+ const char *strStatus[] = {"Taken", "Released", "Timeout"};
+ wake_lock_event *wlock_event = (wake_lock_event *) pBuff;
+
+ printMsg("Wakelock Event: Status=%s (%02x), Name=%s, Reason=%s (%02x)\n",
+ strStatus[wlock_event->status], wlock_event->status,
+ wlock_event->name, "\"TO BE\"", wlock_event->reason);
+ return;
+ }
+
+ /*
+ * Parsing TLV data
+ */
+ if (buffer_entry->type == ENTRY_TYPE_CONNECT_EVENT) {
+ wifi_ring_buffer_driver_connectivity_event *connect_event =
+ (wifi_ring_buffer_driver_connectivity_event *) (pBuff);
+
+ tlv_log *tlv_data = (tlv_log *) (connect_event + 1);
+ printMsg("Event type: %s (%u)\n", RBconnectEventToString(connect_event->event),
+ connect_event->event);
+
+ char *pos = (char *)tlv_data;
+ char *end = (char *)connect_event + buffer_entry->entry_size;
+ while (pos < end) {
+ printMsg("TLV.type: %s (%d), TLV.len=%d (%02x)\n",
+ RBTlvTagToString(tlv_data->tag),
+ tlv_data->tag, tlv_data->length, tlv_data->length);
+
+ switch (tlv_data->tag) {
+ case WIFI_TAG_VENDOR_SPECIFIC:
+ break;
+
+ case WIFI_TAG_BSSID:
+ case WIFI_TAG_ADDR:
+ case WIFI_TAG_ADDR1:
+ case WIFI_TAG_ADDR2:
+ case WIFI_TAG_ADDR3:
+ case WIFI_TAG_ADDR4:
+ {
+ if (tlv_data->length == sizeof(mac_addr)) {
+ mac_addr addr;
+ memcpy(&addr, tlv_data->value, sizeof(mac_addr));
+ printMsg("Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+ } else
+ printMsg("wrong lenght of address\n");
+ break;
+ }
+
+ case WIFI_TAG_SSID:
+ {
+ char ssid[MAX_SSID_LEN];
+ memset(ssid, 0, sizeof(ssid));
+ if (tlv_data->length > MAX_SSID_LEN)
+ tlv_data->length = MAX_SSID_LEN;
+ memcpy(ssid, tlv_data->value, tlv_data->length);
+ printMsg("SSID = %s\n", ssid);
+ break;
+ }
+
+ case WIFI_TAG_STATUS:
+ {
+ unsigned int tag_status = 0;
+ memcpy(&tag_status, tlv_data->value, tlv_data->length);
+ printMsg("tag_Status = %u\n", tag_status);
+ break;
+ }
+
+ case WIFI_TAG_CHANNEL_SPEC:
+ {
+ wifi_channel_info *ch_spec = (wifi_channel_info *) tlv_data->value;
+ printMsg("Channel Info: center_freq=%d, freq0=%d, freq1=%d, width=%s (%d)\n",
+ RBchanWidthToString(ch_spec->width), ch_spec->center_freq,
+ ch_spec->center_freq0, ch_spec->center_freq1);
+ break;
+ }
+
+ case WIFI_TAG_WAKE_LOCK_EVENT:
+ {
+ printMsg("Wake lock event = \"TO BE DONE LATER\"\n", tlv_data->value);
+ break;
+ }
+
+ case WIFI_TAG_TSF:
+ {
+ u64 tsf = 0;
+ memcpy(&tsf, tlv_data->value, tlv_data->length);
+ printMsg("TSF value = %d\n", tsf);
+ break;
+ }
+
+ case WIFI_TAG_IE:
+ {
+ printMsg("Information Element = \"TO BE\"\n");
+ break;
+ }
+
+ case WIFI_TAG_INTERFACE:
+ {
+ const int len = 32;
+ char inf_name[len];
+
+ if (tlv_data->length > len)
+ tlv_data->length = len;
+ memset(inf_name, 0, 32);
+ memcpy(inf_name, tlv_data->value, tlv_data->length);
+ printMsg("Interface = %s\n", inf_name);
+ break;
+ }
+
+ case WIFI_TAG_REASON_CODE:
+ {
+ u16 reason = 0;
+ memcpy(&reason, tlv_data->value, 2);
+ printMsg("Reason code = %d\n", reason);
+ break;
+ }
+
+ case WIFI_TAG_RATE_MBPS:
+ {
+ u32 rate = 0;
+ memcpy(&rate, tlv_data->value, tlv_data->length);
+ printMsg("Rate = %.1f Mbps\n", rate * 0.5); // rate unit is 500 Kbps.
+ break;
+ }
+
+ case WIFI_TAG_CHANNEL:
+ {
+ u16 channel = 0;
+ memcpy(&channel, tlv_data->value, tlv_data->length);
+ printMsg("Channel = %d\n", channel);
+ break;
+ }
+
+ case WIFI_TAG_RSSI:
+ {
+ short rssi = 0;
+ memcpy(&rssi, tlv_data->value, tlv_data->length);
+ printMsg("RSSI = %d\n", rssi);
+ break;
+ }
+ }
+ pos = (char *)(tlv_data + 1);
+ pos += tlv_data->length;
+ tlv_data = (tlv_log *) pos;
+ }
+ }
+}
+
+static void onAlert(wifi_request_id id, char *buffer, int buffer_size, int err_code)
+{
+
+ // helper for AlertHandler
+
+ printMsg("Getting FW Memory dump: (%d bytes), err code: %d\n", buffer_size, err_code);
+
+ FILE* w_fp = NULL;
+ static int f_count = 0;
+ char dump_file[FILE_NAME_LEN];
+
+ if (!buffer || buffer_size <= 0) {
+ printMsg("No data in alert buffer\n");
+ return;
+ }
+
+ snprintf(dump_file, FILE_NAME_LEN, "%s-%d.bin", ALERT_MEMDUMP_PREFIX, f_count++);
+ if (f_count >= NUM_ALERT_DUMPS)
+ f_count = 0;
+
+ w_fp = fopen(dump_file, "w");
+ if (w_fp == NULL) {
+ printMsg("Failed to create a file: %s\n", dump_file);
+ return;
+ }
+
+ printMsg("Write to \"%s\"\n", dump_file);
+ fwrite(buffer, 1, buffer_size, w_fp);
+ fclose(w_fp);
+ w_fp = NULL;
+
+}
+
+static void onFirmwareMemoryDump(char *buffer, int buffer_size)
+{
+ // helper for LoggerGetMemdump()
+
+ printMsg("Getting FW Memory dump: (%d bytes)\n", buffer_size);
+
+ // Write a raw dump data into default local file or specified name
+ FILE* w_fp = NULL;
+
+ if (!buffer || buffer_size <= 0) {
+ printMsg("No data in dump buffer\n");
+ return;
+ }
+
+ w_fp = fopen(mem_dump_file, "w");
+ if (w_fp == NULL) {
+ printMsg("Failed to create a file: %s\n", mem_dump_file);
+ return;
+ }
+
+ printMsg("Write to \"%s\"\n", mem_dump_file);
+ fwrite(buffer, 1, buffer_size, w_fp);
+ fclose(w_fp);
+ w_fp = NULL;
+
+ putEventInCache(EVENT_TYPE_LOGGER_MEMDUMP_DATA, "Memdump data");
+}
+
+static wifi_error LoggerStart()
+{
+ int ret;
+
+ ret = hal_fn.wifi_start_logging(wlan0Handle,
+ default_logger_param.verbose_level, default_logger_param.flags,
+ default_logger_param.max_interval_sec, default_logger_param.min_data_size,
+ default_logger_param.ring_name);
+
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to start Logger: %d\n", ret);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /*
+ * debug mode (0) which means no more debug events will be triggered.
+ *
+ * Hopefully, need to extend this functionality by additional interfaces such as
+ * set verbose level to each ring buffer.
+ */
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetMemdump()
+{
+ wifi_firmware_memory_dump_handler handler;
+ handler.on_firmware_memory_dump = &onFirmwareMemoryDump;
+
+ printMsg("Create Memdump event\n");
+ int result = hal_fn.wifi_get_firmware_memory_dump(wlan0Handle, handler);
+
+ if (result == WIFI_SUCCESS) {
+ EventInfo info;
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_LOGGER_MEMDUMP_DATA)
+ break;
+ else
+ printMsg("Could not get memdump data: %d\n", result);
+ }
+ }
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetRingData()
+{
+ int result = hal_fn.wifi_get_ring_data(wlan0Handle, default_ring_name);
+
+ if (result == WIFI_SUCCESS)
+ printMsg("Get Ring data command success\n");
+ else
+ printMsg("Failed to execute get ring data command\n");
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetFW()
+{
+ int ret;
+ const int BSIZE = 256;
+ int buffer_size = BSIZE;
+
+ char buffer[BSIZE];
+ memset(buffer, 0, BSIZE);
+
+ ret = hal_fn.wifi_get_firmware_version(wlan0Handle, buffer, buffer_size);
+
+ if (ret == WIFI_SUCCESS)
+ printMsg("FW version (len=%d):\n%s\n", strlen(buffer), buffer);
+ else
+ printMsg("Failed to get FW version\n");
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetDriver()
+{
+ int ret;
+ const int BSIZE = 256;
+ int buffer_size = BSIZE;
+
+ char buffer[BSIZE];
+ memset(buffer, 0, BSIZE);
+
+ ret = hal_fn.wifi_get_driver_version(wlan0Handle, buffer, buffer_size);
+
+ if (ret == WIFI_SUCCESS)
+ printMsg("Driver version (len=%d):\n%s\n", strlen(buffer), buffer);
+ else
+ printMsg("Failed to get driver version\n");
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetRingbufferStatus()
+{
+ int ret;
+ const int NRING = 10;
+ u32 num_rings = NRING;
+
+ wifi_ring_buffer_status *status =
+ (wifi_ring_buffer_status *)malloc(sizeof(wifi_ring_buffer_status) * num_rings);
+
+ if (status == NULL)
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ memset(status, 0, sizeof(wifi_ring_buffer_status) * num_rings);
+
+ ret = hal_fn.wifi_get_ring_buffers_status(wlan0Handle, &num_rings, status);
+
+ if (ret == WIFI_SUCCESS) {
+ printMsg("RingBuffer status: [%d ring(s)]\n", num_rings);
+
+ for (unsigned int i = 0; i < num_rings; i++) {
+ printMsg("[%d] RingId=%d, Name=%s, Flags=%u, DebugLevel=%u, "
+ "wBytes=%u, rBytes=%u, RingSize=%u, wRecords=%u, status_addr=%p\n",
+ i+1,
+ status->ring_id,
+ status->name,
+ status->flags,
+ status->verbose_level,
+ status->written_bytes,
+ status->read_bytes,
+ status->ring_buffer_byte_size,
+ status->written_records, status);
+ status++;
+ }
+ } else {
+ printMsg("Failed to get Ringbuffer status\n");
+ }
+
+ free(status);
+ status = NULL;
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerGetFeature()
+{
+ int ret;
+ unsigned int support = 0;
+
+ const char *mapFeatures[] = {
+ "MEMORY_DUMP",
+ "PER_PACKET_TX_RX_STATUS",
+ "CONNECT_EVENT",
+ "POWER_EVENT",
+ "WAKE_LOCK",
+ "VERBOSE",
+ "WATCHDOG_TIMER",
+ "DRIVER_DUMP",
+ "PACKET_FATE"
+ };
+
+ ret = hal_fn.wifi_get_logger_supported_feature_set(wlan0Handle, &support);
+
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Logger supported features: %02x [", support);
+
+ if (support & WIFI_LOGGER_MEMORY_DUMP_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[0]);
+ if (support & WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[1]);
+ if (support & WIFI_LOGGER_CONNECT_EVENT_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[2]);
+ if (support & WIFI_LOGGER_POWER_EVENT_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[3]);
+ if (support & WIFI_LOGGER_WAKE_LOCK_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[4]);
+ if (support & WIFI_LOGGER_VERBOSE_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[5]);
+ if (support & WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[6]);
+ if (support & WIFI_LOGGER_DRIVER_DUMP_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[7]);
+ if (support & WIFI_LOGGER_PACKET_FATE_SUPPORTED)
+ printMsg(" \"%s\" ", mapFeatures[8]);
+ printMsg("]\n");
+ } else {
+ printMsg("Failed to get Logger supported features\n");
+ }
+
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerSetLogHandler()
+{
+ wifi_ring_buffer_data_handler handler;
+ handler.on_ring_buffer_data = &onRingBufferData;
+
+ printMsg("Setting log handler\n");
+ int result = hal_fn.wifi_set_log_handler(loggerCmdId, wlan0Handle, handler);
+
+ if (result == WIFI_SUCCESS) {
+ EventInfo info;
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_LOGGER_RINGBUFFER_DATA)
+ break;
+ }
+ } else {
+ printMsg("Failed set Log handler: %d\n", result);
+ }
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerSetAlertHandler()
+{
+ loggerCmdId = getNewCmdId();
+ wifi_alert_handler handler;
+ handler.on_alert = &onAlert;
+
+ printMsg("Create alert handler\n");
+ int result = hal_fn.wifi_set_alert_handler(loggerCmdId, wlan0Handle, handler);
+
+ if (result == WIFI_SUCCESS) {
+ EventInfo info;
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_LOGGER_ALERT_DATA)
+ break;
+ }
+ } else {
+ printMsg("Failed set Alert handler: %d\n", result);
+ }
+ return WIFI_SUCCESS;
+}
+
+static wifi_error LoggerMonitorPktFate()
+{
+ printMsg("Start packet fate monitor \n");
+ wifi_error result = hal_fn.wifi_start_pkt_fate_monitoring(wlan0Handle);
+
+ if (result == WIFI_SUCCESS) {
+ printMsg("Start packet fate monitor command successful\n");
+ } else {
+ printMsg("Start packet fate monitor command failed, err = %d\n", result);
+ }
+ return result;
+}
+
+static wifi_error LoggerGetTxPktFate()
+{
+ wifi_tx_report *tx_report, *report_ptr;
+ size_t frame_len, n_provided_fates = 0;
+ wifi_error result = WIFI_SUCCESS;
+ FILE *w_fp = NULL;
+
+ printMsg("Logger get tx pkt fate command\n");
+ if (!n_requested_pkt_fate || n_requested_pkt_fate > MAX_FATE_LOG_LEN) {
+ n_requested_pkt_fate = MAX_FATE_LOG_LEN;
+ }
+
+ tx_report = (wifi_tx_report *)malloc(n_requested_pkt_fate * sizeof(*tx_report));
+ if (!tx_report) {
+ printMsg("%s: Memory allocation failed\n",__FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(tx_report, 0, n_requested_pkt_fate * sizeof(*tx_report));
+
+ result = hal_fn.wifi_get_tx_pkt_fates(wlan0Handle, tx_report,
+ n_requested_pkt_fate, &n_provided_fates);
+ if (result != WIFI_SUCCESS) {
+ printMsg("Logger get tx pkt fate command failed, err = %d\n", result);
+ goto exit;
+ }
+
+ if (!n_provided_fates) {
+ printMsg("Got empty pkt fates\n");
+ result = WIFI_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ printMsg("No: of tx pkt fates provided = %d\n", n_provided_fates);
+
+ w_fp = fopen(tx_pkt_fate_file, "w");
+ if (!w_fp) {
+ printMsg("Failed to create file: %s\n", tx_pkt_fate_file);
+ result = WIFI_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ fprintf(w_fp, "--- BEGIN ---\n\n");
+ fprintf(w_fp, "No: of pkt fates provided = %zd\n\n", n_provided_fates);
+ report_ptr = tx_report;
+ for (size_t i = 0; i < n_provided_fates; i++) {
+ fprintf(w_fp, "--- REPORT : %zu ---\n\n", (i + 1));
+ if (report_ptr->frame_inf.frame_len == 0 ||
+ report_ptr->frame_inf.payload_type == FRAME_TYPE_UNKNOWN) {
+ fprintf(w_fp, "Invalid frame...!!!\n\n");
+ }
+ fprintf(w_fp, "MD5 Prefix : ");
+ fprhex(w_fp, report_ptr->md5_prefix, MD5_PREFIX_LEN, false);
+ fprintf(w_fp, "Packet Fate : %d\n", report_ptr->fate);
+ fprintf(w_fp, "Frame Type : %d\n", report_ptr->frame_inf.payload_type);
+ fprintf(w_fp, "Frame Len : %zu\n", report_ptr->frame_inf.frame_len);
+ fprintf(w_fp, "Driver Timestamp : %u\n",
+ report_ptr->frame_inf.driver_timestamp_usec);
+ fprintf(w_fp, "Firmware Timestamp : %u\n",
+ report_ptr->frame_inf.firmware_timestamp_usec);
+ if (report_ptr->frame_inf.payload_type == FRAME_TYPE_ETHERNET_II) {
+ frame_len = min(report_ptr->frame_inf.frame_len, (size_t)MAX_FRAME_LEN_ETHERNET);
+ fprintf(w_fp, "Frame Content (%04zu bytes) : \n", frame_len);
+ fprhex(w_fp, report_ptr->frame_inf.frame_content.ethernet_ii_bytes, frame_len, true);
+ } else {
+ frame_len = min(report_ptr->frame_inf.frame_len, (size_t)MAX_FRAME_LEN_80211_MGMT);
+ fprintf(w_fp, "Frame Content (%04zu bytes) : \n", frame_len);
+ fprhex(w_fp, report_ptr->frame_inf.frame_content.ieee_80211_mgmt_bytes,
+ frame_len, true);
+ }
+ fprintf(w_fp, "\n--- END OF REPORT ---\n\n");
+
+ report_ptr++;
+ }
+ fprintf(w_fp, "--- EOF ---\n");
+
+exit:
+ if (w_fp) {
+ fclose(w_fp);
+ }
+ if (tx_report) {
+ free(tx_report);
+ }
+
+ return result;
+}
+
+static wifi_error LoggerGetRxPktFate()
+{
+ wifi_rx_report *rx_report, *report_ptr;
+ size_t frame_len, n_provided_fates = 0;
+ wifi_error result = WIFI_SUCCESS;
+ FILE *w_fp = NULL;
+
+ printMsg("Logger get rx pkt fate command\n");
+ if (!n_requested_pkt_fate || n_requested_pkt_fate > MAX_FATE_LOG_LEN) {
+ n_requested_pkt_fate = MAX_FATE_LOG_LEN;
+ }
+
+ rx_report = (wifi_rx_report *)malloc(n_requested_pkt_fate * sizeof(*rx_report));
+ if (!rx_report) {
+ printMsg("%s: Memory allocation failed\n",__FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(rx_report, 0, n_requested_pkt_fate * sizeof(*rx_report));
+
+ result = hal_fn.wifi_get_rx_pkt_fates(wlan0Handle, rx_report,
+ n_requested_pkt_fate, &n_provided_fates);
+ if (result != WIFI_SUCCESS) {
+ printMsg("Logger get rx pkt fate command failed, err = %d\n", result);
+ goto exit;
+ }
+
+ if (!n_provided_fates) {
+ printMsg("Got empty pkt fates\n");
+ result = WIFI_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ printMsg("No: of rx pkt fates provided = %d\n", n_provided_fates);
+
+ w_fp = fopen(rx_pkt_fate_file, "w");
+ if (!w_fp) {
+ printMsg("Failed to create file: %s\n", rx_pkt_fate_file);
+ result = WIFI_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ fprintf(w_fp, "--- BEGIN ---\n\n");
+ fprintf(w_fp, "No: of pkt fates provided = %zd\n\n", n_provided_fates);
+ report_ptr = rx_report;
+ for (size_t i = 0; i < n_provided_fates; i++) {
+ fprintf(w_fp, "--- REPORT : %zu ---\n\n", (i + 1));
+ if (report_ptr->frame_inf.frame_len == 0 ||
+ report_ptr->frame_inf.payload_type == FRAME_TYPE_UNKNOWN) {
+ fprintf(w_fp, "Invalid frame...!!!\n\n");
+ }
+ fprintf(w_fp, "MD5 Prefix : ");
+ fprhex(w_fp, report_ptr->md5_prefix, MD5_PREFIX_LEN, false);
+ fprintf(w_fp, "Packet Fate : %d\n", report_ptr->fate);
+ fprintf(w_fp, "Frame Type : %d\n", report_ptr->frame_inf.payload_type);
+ fprintf(w_fp, "Frame Len : %zu\n", report_ptr->frame_inf.frame_len);
+ fprintf(w_fp, "Driver Timestamp : %u\n", report_ptr->frame_inf.driver_timestamp_usec);
+ fprintf(w_fp, "Firmware Timestamp : %u\n", report_ptr->frame_inf.firmware_timestamp_usec);
+ if (report_ptr->frame_inf.payload_type == FRAME_TYPE_ETHERNET_II) {
+ frame_len = min(report_ptr->frame_inf.frame_len, (size_t)MAX_FRAME_LEN_ETHERNET);
+ fprintf(w_fp, "Frame Content (%04zu bytes) : \n", frame_len);
+ fprhex(w_fp, report_ptr->frame_inf.frame_content.ethernet_ii_bytes, frame_len,
+ true);
+ } else {
+ frame_len = min(report_ptr->frame_inf.frame_len, (size_t)MAX_FRAME_LEN_80211_MGMT);
+ fprintf(w_fp, "Frame Content (%04zu bytes) : \n", frame_len);
+ fprhex(w_fp, report_ptr->frame_inf.frame_content.ieee_80211_mgmt_bytes, frame_len,
+ true);
+ }
+ fprintf(w_fp, "\n--- END OF REPORT ---\n\n");
+
+ report_ptr++;
+ }
+ fprintf(w_fp, "--- EOF ---\n");
+
+exit:
+ if (w_fp) {
+ fclose(w_fp);
+ }
+ if (rx_report) {
+ free(rx_report);
+ }
+
+ return result;
+}
+
+static void runLogger()
+{
+ switch (log_cmd) {
+ case LOG_GET_FW_VER:
+ LoggerGetFW();
+ break;
+ case LOG_GET_DRV_VER:
+ LoggerGetDriver();
+ break;
+ case LOG_GET_RING_STATUS:
+ LoggerGetRingbufferStatus();
+ break;
+ case LOG_GET_FEATURE:
+ LoggerGetFeature();
+ break;
+ case LOG_GET_MEMDUMP:
+ LoggerGetMemdump();
+ break;
+ case LOG_GET_RING_DATA:
+ LoggerGetRingData();
+ break;
+ case LOG_START:
+ LoggerStart();
+ break;
+ case LOG_SET_LOG_HANDLER:
+ LoggerSetLogHandler();
+ break;
+ case LOG_SET_ALERT_HANDLER:
+ LoggerSetAlertHandler();
+ break;
+ case LOG_MONITOR_PKTFATE:
+ LoggerMonitorPktFate();
+ break;
+ case LOG_GET_TXPKTFATE:
+ LoggerGetTxPktFate();
+ break;
+ case LOG_GET_RXPKTFATE:
+ LoggerGetRxPktFate();
+ break;
+ default:
+ break;
+ }
+}
+
+static wifi_error start_mkeep_alive(int index, u32 period_msec, u16 ether_type,
+ u8* src_mac, u8* dst_mac, u8* ip_pkt,
+ u16 ip_pkt_len)
+{
+ int ret;
+
+ ret = hal_fn.wifi_start_sending_offloaded_packet(index, wlan0Handle, ether_type, ip_pkt,
+ ip_pkt_len, src_mac, dst_mac, period_msec);
+
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Start mkeep_alive with ID %d, %u period(msec), src(" MACSTR "), "
+ "dst(" MACSTR ")\n", index, period_msec, MAC2STR(src_mac), MAC2STR(dst_mac));
+ } else {
+ printMsg("Failed to start mkeep_alive by ID %d: %d\n", index, ret);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ return WIFI_SUCCESS;
+}
+
+static wifi_error stop_mkeep_alive(int index)
+{
+ int ret;
+
+ ret = hal_fn.wifi_stop_sending_offloaded_packet(index, wlan0Handle);
+
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Stop mkeep_alive with ID %d\n", index);
+ } else {
+ printMsg("Failed to stop mkeep_alive by ID %d: %d\n", index, ret);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ return WIFI_SUCCESS;
+}
+
+byte parseHexChar(char ch) {
+ if (isdigit(ch))
+ return ch - '0';
+ else if ('A' <= ch && ch <= 'F')
+ return ch - 'A' + 10;
+ else if ('a' <= ch && ch <= 'f')
+ return ch - 'a' + 10;
+ else {
+ printMsg("invalid character in bssid %c\n", ch);
+ return 0;
+ }
+}
+
+byte parseHexByte(char ch1, char ch2) {
+ return (parseHexChar(ch1) << 4) | parseHexChar(ch2);
+}
+
+void parseMacAddress(const char *str, mac_addr addr) {
+ addr[0] = parseHexByte(str[0], str[1]);
+ addr[1] = parseHexByte(str[3], str[4]);
+ addr[2] = parseHexByte(str[6], str[7]);
+ addr[3] = parseHexByte(str[9], str[10]);
+ addr[4] = parseHexByte(str[12], str[13]);
+ addr[5] = parseHexByte(str[15], str[16]);
+}
+
+void parseMacOUI(char *str, unsigned char *addr) {
+ addr[0] = parseHexByte(str[0], str[1]);
+ addr[1] = parseHexByte(str[3], str[4]);
+ addr[2] = parseHexByte(str[6], str[7]);
+ printMsg("read mac OUI: %02x:%02x:%02x\n", addr[0],
+ addr[1], addr[2]);
+}
+
+int
+ether_atoe(const char *a, u8 *addr)
+{
+ char *c = NULL;
+ int i = 0;
+ memset(addr, 0, ETHER_ADDR_LEN);
+ for (; i < ETHER_ADDR_LEN; i++) {
+ addr[i] = (u8)strtoul(a, &c, 16);
+ if (*c != ':' && *c != '\0') {
+ return 0;
+ }
+ a = ++c;
+ }
+ return (i == ETHER_ADDR_LEN);
+}
+
+void readTestOptions(int argc, char *argv[]) {
+
+ printf("Total number of argc #%d\n", argc);
+ wifi_epno_network *epno_ssid = epno_cfg.networks;
+ for (int j = 1; j < argc-1; j++) {
+ if (strcmp(argv[j], "-max_ap") == 0 && isdigit(argv[j+1][0])) {
+ stest_max_ap = atoi(argv[++j]);
+ printf(" max_ap #%d\n", stest_max_ap);
+ } else if (strcmp(argv[j], "-base_period") == 0 && isdigit(argv[j+1][0])) {
+ stest_base_period = atoi(argv[++j]);
+ printf(" base_period #%d\n", stest_base_period);
+ } else if (strcmp(argv[j], "-threshold") == 0 && isdigit(argv[j+1][0])) {
+ stest_threshold_percent = atoi(argv[++j]);
+ printf(" threshold #%d\n", stest_threshold_percent);
+ } else if (strcmp(argv[j], "-avg_RSSI") == 0 && isdigit(argv[j+1][0])) {
+ swctest_rssi_sample_size = atoi(argv[++j]);
+ printf(" avg_RSSI #%d\n", swctest_rssi_sample_size);
+ } else if (strcmp(argv[j], "-ap_loss") == 0 && isdigit(argv[j+1][0])) {
+ swctest_rssi_lost_ap = atoi(argv[++j]);
+ printf(" ap_loss #%d\n", swctest_rssi_lost_ap);
+ } else if (strcmp(argv[j], "-ap_breach") == 0 && isdigit(argv[j+1][0])) {
+ swctest_rssi_min_breaching = atoi(argv[++j]);
+ printf(" ap_breach #%d\n", swctest_rssi_min_breaching);
+ } else if (strcmp(argv[j], "-ch_threshold") == 0 && isdigit(argv[j+1][0])) {
+ swctest_rssi_ch_threshold = atoi(argv[++j]);
+ printf(" ch_threshold #%d\n", swctest_rssi_ch_threshold);
+ } else if (strcmp(argv[j], "-wt_event") == 0 && isdigit(argv[j+1][0])) {
+ max_event_wait = atoi(argv[++j]);
+ printf(" wt_event #%d\n", max_event_wait);
+ } else if (strcmp(argv[j], "-low_th") == 0 && isdigit(argv[j+1][0])) {
+ htest_low_threshold = atoi(argv[++j]);
+ printf(" low_threshold #-%d\n", htest_low_threshold);
+ } else if (strcmp(argv[j], "-high_th") == 0 && isdigit(argv[j+1][0])) {
+ htest_high_threshold = atoi(argv[++j]);
+ printf(" high_threshold #-%d\n", htest_high_threshold);
+ } else if (strcmp(argv[j], "-hotlist_bssids") == 0 && isxdigit(argv[j+1][0])) {
+ j++;
+ for (num_hotlist_bssids = 0; j < argc && isxdigit(argv[j][0]);
+ j++, num_hotlist_bssids++) {
+ parseMacAddress(argv[j], hotlist_bssids[num_hotlist_bssids]);
+ }
+ j -= 1;
+ } else if (strcmp(argv[j], "-channel_list") == 0 && isxdigit(argv[j+1][0])) {
+ j++;
+ for (num_channels = 0; j < argc && isxdigit(argv[j][0]); j++, num_channels++) {
+ channel_list[num_channels] = atoi(argv[j]);
+ }
+ j -= 1;
+ } else if ((strcmp(argv[j], "-get_ch_list") == 0)) {
+ if(strcmp(argv[j + 1], "a") == 0) {
+ band = WIFI_BAND_A_WITH_DFS;
+ } else if(strcmp(argv[j + 1], "bg") == 0) {
+ band = WIFI_BAND_BG;
+ } else if(strcmp(argv[j + 1], "abg") == 0) {
+ band = WIFI_BAND_ABG_WITH_DFS;
+ } else if(strcmp(argv[j + 1], "a_nodfs") == 0) {
+ band = WIFI_BAND_A;
+ } else if(strcmp(argv[j + 1], "dfs") == 0) {
+ band = WIFI_BAND_A_DFS;
+ } else if(strcmp(argv[j + 1], "abg_nodfs") == 0) {
+ band = WIFI_BAND_ABG;
+ }
+ j++;
+ } else if (strcmp(argv[j], "-scan_mac_oui") == 0 && isxdigit(argv[j+1][0])) {
+ parseMacOUI(argv[++j], mac_oui);
+ } else if ((strcmp(argv[j], "-ssid") == 0)) {
+ epno_cfg.num_networks++;
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ memcpy(epno_ssid[epno_cfg.num_networks].ssid, argv[j + 1], (size_t)(MAX_SSID_LEN));
+ printf(" SSID %s\n", epno_ssid[epno_cfg.num_networks].ssid);
+ j++;
+ }
+ } else if ((strcmp(argv[j], "-auth") == 0)) {
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ epno_ssid[epno_cfg.num_networks].auth_bit_field = atoi(argv[++j]);
+ printf(" auth %d\n", epno_ssid[epno_cfg.num_networks].auth_bit_field);
+ }
+ } else if ((strcmp(argv[j], "-hidden") == 0)) {
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ epno_ssid[epno_cfg.num_networks].flags |= atoi(argv[++j]) ? EPNO_HIDDEN: 0;
+ printf(" flags %d\n", epno_ssid[epno_cfg.num_networks].flags);
+ }
+ } else if ((strcmp(argv[j], "-strict") == 0)) {
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ epno_ssid[epno_cfg.num_networks].flags |= atoi(argv[++j]) ? EPNO_FLAG_STRICT_MATCH: 0;
+ printf(" flags %d\n", epno_ssid[epno_cfg.num_networks].flags);
+ }
+ } else if ((strcmp(argv[j], "-same_network") == 0)) {
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ epno_ssid[epno_cfg.num_networks].flags |= atoi(argv[++j]) ? EPNO_FLAG_SAME_NETWORK: 0;
+ printf(" flags %d\n", epno_ssid[epno_cfg.num_networks].flags);
+ }
+ } else if (strcmp(argv[j], "-min5g_rssi") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.min5GHz_rssi = -atoi(argv[++j]);
+ printf(" min5g_rssi %d\n", epno_cfg.min5GHz_rssi);
+ } else if (strcmp(argv[j], "-min2g_rssi") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.min24GHz_rssi = -atoi(argv[++j]);
+ printf(" min2g_rssi %d\n", epno_cfg.min24GHz_rssi);
+ } else if (strcmp(argv[j], "-init_score_max") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.initial_score_max = atoi(argv[++j]);
+ printf(" initial_score_max %d\n", epno_cfg.initial_score_max);
+ } else if (strcmp(argv[j], "-cur_conn_bonus") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.current_connection_bonus = atoi(argv[++j]);
+ printf(" cur_conn_bonus %d\n", epno_cfg.current_connection_bonus);
+ } else if (strcmp(argv[j], "-same_network_bonus") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.same_network_bonus = atoi(argv[++j]);
+ printf(" same_network_bonus %d\n", epno_cfg.same_network_bonus);
+ } else if (strcmp(argv[j], "-secure_bonus") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.secure_bonus = atoi(argv[++j]);
+ printf(" secure_bonus %d\n", epno_cfg.secure_bonus);
+ } else if (strcmp(argv[j], "-band5g_bonus") == 0 && isdigit(argv[j+1][0])) {
+ epno_cfg.band5GHz_bonus = atoi(argv[++j]);
+ printf(" band5GHz_bonus %d\n", epno_cfg.band5GHz_bonus);
+ } else if ((strcmp(argv[j], "-trig") == 0)) {
+ if (epno_cfg.num_networks < (int)MAX_EPNO_NETWORKS) {
+ if ((strcmp(argv[j + 1], "a") == 0)) {
+ epno_ssid[epno_cfg.num_networks].flags |= EPNO_A_BAND_TRIG;
+ } else if ((strcmp(argv[j + 1], "bg") == 0)) {
+ epno_ssid[epno_cfg.num_networks].flags |= EPNO_BG_BAND_TRIG;
+ } else if ((strcmp(argv[j + 1], "abg") == 0)) {
+ epno_ssid[epno_cfg.num_networks].flags |= EPNO_ABG_BAND_TRIG;
+ }
+ printf(" flags %d\n", epno_ssid[epno_cfg.num_networks].flags);
+ }
+ j++;
+ } else if ((strcmp(argv[j], "-blacklist_bssids") == 0 && isxdigit(argv[j+1][0])) ||
+ (strcmp(argv[j], "-whitelist_ssids") == 0)) {
+ if (strcmp(argv[j], "-blacklist_bssids") == 0 && isxdigit(argv[j+1][0])) {
+ j++;
+ for (num_blacklist_bssids = 0;
+ j < argc && isxdigit(argv[j][0]) &&
+ num_blacklist_bssids < MAX_BLACKLIST_BSSID;
+ j++, num_blacklist_bssids++) {
+ parseMacAddress(argv[j], blacklist_bssids[num_blacklist_bssids]);
+ }
+ }
+ if (strcmp(argv[j], "-whitelist_ssids") == 0) {
+ j++;
+ for (num_whitelist_ssids = 0;
+ j < argc && (num_whitelist_ssids < MAX_WHITELIST_SSID);
+ j++, num_whitelist_ssids++) {
+ if ((strcmp(argv[j], "-blacklist_bssids") == 0) ||
+ isxdigit(argv[j][0])) {
+ num_whitelist_ssids--;
+ continue;
+ }
+ strncpy(whitelist_ssids[num_whitelist_ssids], argv[j],
+ min(strlen(argv[j]), (size_t)(MAX_SSID_LEN-1)));
+ }
+ /* Setting this flag to true here as -blacklist_bssids has already existing explicit handler */
+ set_roaming_configuration = true;
+ }
+ j -= 1;
+ } else if (strcmp(argv[j], "-rssi_monitor") == 0 && isdigit(argv[j+1][0])) {
+ rssi_monitor = atoi(argv[++j]);
+ printf(" rssi_monitor #%d\n", rssi_monitor);
+ } else if (strcmp(argv[j], "-max_rssi") == 0 && isdigit(argv[j+1][0])) {
+ max_rssi = -atoi(argv[++j]);
+ printf(" max_rssi #%d\n", max_rssi);
+ } else if (strcmp(argv[j], "-min_rssi") == 0 && isdigit(argv[j+1][0])) {
+ min_rssi = -atoi(argv[++j]);
+ printf(" min_rssi #%d\n", min_rssi);
+ }
+ }
+}
+
+void readRTTOptions(int argc, char *argv[]) {
+ for (int j = 1; j < argc-1; j++) {
+ if ((strcmp(argv[j], "-get_ch_list") == 0)) {
+ if(strcmp(argv[j + 1], "a") == 0) {
+ band = WIFI_BAND_A_WITH_DFS;
+ } else if(strcmp(argv[j + 1], "bg") == 0) {
+ band = WIFI_BAND_BG;
+ } else if(strcmp(argv[j + 1], "abg") == 0) {
+ band = WIFI_BAND_ABG_WITH_DFS;
+ } else if(strcmp(argv[j + 1], "a_nodfs") == 0) {
+ band = WIFI_BAND_A;
+ } else if(strcmp(argv[j + 1], "dfs") == 0) {
+ band = WIFI_BAND_A_DFS;
+ } else if(strcmp(argv[j + 1], "abg_nodfs") == 0) {
+ band = WIFI_BAND_ABG;
+ }
+ ALOGE("band chosen = %s[band = %d]\n", argv[j + 1], band);
+ j++;
+ } else if ((strcmp(argv[j], "-l") == 0)) {
+ /*
+ * If this option is specified but there is no file name,
+ * use a default file from rtt_aplist.
+ */
+ if (++j != argc-1) {
+ strncpy(rtt_aplist, argv[j], (FILE_NAME_LEN -1));
+ rtt_aplist[FILE_NAME_LEN -1] = '\0';
+ }
+ rtt_from_file = 1;
+ } else if ((strcmp(argv[j], "-n") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.num_burst = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-f") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.num_frames_per_burst = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-r") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.num_retries_per_ftm = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-m") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.num_retries_per_ftmr = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-b") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.burst_duration = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-max_ap") == 0) && isdigit(argv[j+1][0])) {
+ max_ap = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-lci") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.LCI_request = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-lcr") == 0) && isdigit(argv[j+1][0])) {
+ default_rtt_param.LCR_request = atoi(argv[++j]);
+ } else if ((strcmp(argv[j], "-type") == 0) && isdigit(argv[j+1][0])) {
+ u8 rtt_type = atoi(argv[++j]);
+ if (rtt_type == 1) {
+ printf("RTT Type is ONE-SIDED\n");
+ default_rtt_param.type = RTT_TYPE_1_SIDED;
+ }
+ } else if ((strcmp(argv[j], "-o") == 0)) {
+ /*
+ * If this option is specified but there is no file name,
+ * use a default file from rtt_aplist.
+ */
+ if (++j != argc-1) {
+ strncpy(rtt_aplist, argv[j], (FILE_NAME_LEN -1));
+ rtt_aplist[FILE_NAME_LEN -1] = '\0';
+ }
+ rtt_to_file = 1;
+ } else if ((strcmp(argv[j], "-sta") == 0) ||
+ (strcmp(argv[j], "-nan") == 0)) {
+ if (strcmp(argv[j], "-sta") == 0) {
+ rtt_sta = true;
+ } else {
+ rtt_nan = true;
+ }
+ if (isxdigit(argv[j+1][0])) {
+ j++;
+ parseMacAddress(argv[j], responder_addr);
+ printMsg("Target mac(" MACSTR ")", MAC2STR(responder_addr));
+ }
+ /* Read channel if present */
+ if (argv[j+1]) {
+ if (isdigit(argv[j+1][0])) {
+ j++;
+ responder_channel = atoi(argv[j]);
+ printf("Channel set as %d \n", responder_channel);
+ }
+ /* Read band width if present */
+ if (argv[j+1]) {
+ if (isdigit(argv[j+1][0])) {
+ j++;
+ channel_width = atoi(argv[j]);
+ printf("channel_width as %d \n", channel_width);
+ }
+ }
+ /* check its 6g channel */
+ if (argv[j+1]) {
+ if (isdigit(argv[j+1][0])) {
+ j++;
+ if(atoi(argv[j]) == 1) {
+ printf(" IS 6G CHANNEL \n");
+ is_6g = true;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void readLoggerOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+ int j = 1;
+
+ if (argc < 3) {
+ printUsage();
+ return;
+ }
+
+ if ((strcmp(argv[j], "-start") == 0)) {
+ if ((strcmp(argv[j+1], "pktmonitor") == 0)){
+ log_cmd = LOG_MONITOR_PKTFATE;
+ return;
+ } else if (argc != 13) {
+ printf("\nUse correct logger option:\n");
+ printUsage();
+ return;
+ }
+ log_cmd = LOG_START;
+ memset(&default_logger_param, 0, sizeof(default_logger_param));
+
+ j++;
+ if ((strcmp(argv[j], "-d") == 0) && isdigit(argv[j+1][0]))
+ default_logger_param.verbose_level = (unsigned int)atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-f") == 0) && isdigit(argv[j+1][0]))
+ default_logger_param.flags = atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-i") == 0) && isdigit(argv[j+1][0]))
+ default_logger_param.max_interval_sec = atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-s") == 0) && isdigit(argv[j+1][0]))
+ default_logger_param.min_data_size = atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-n") == 0))
+ memcpy(default_logger_param.ring_name, argv[j+1], (MAX_RING_NAME_SIZE));
+ return;
+ } else if ((strcmp(argv[j], "-get") == 0) && (argc > 3)) {
+ if ((strcmp(argv[j+1], "fw") == 0)) {
+ log_cmd = LOG_GET_FW_VER;
+ } else if ((strcmp(argv[j+1], "driver") == 0)) {
+ log_cmd = LOG_GET_DRV_VER;
+ } else if ((strcmp(argv[j+1], "memdump") == 0)) {
+ log_cmd = LOG_GET_MEMDUMP;
+ j++;
+ if ((j+1 < argc-1) && (strcmp(argv[j+1], "-o") == 0)) {
+ // If this option is specified but there is no file name,
+ // use a default file from DEFAULT_MEMDUMP_FILE.
+ j++;
+ if (j+1 < argc-1) {
+ strncpy(mem_dump_file, argv[j+1] , (FILE_NAME_LEN -1));
+ mem_dump_file[FILE_NAME_LEN -1] = '\0';
+ }
+ }
+ } else if ((strcmp(argv[j+1], "ringstatus") == 0)) {
+ log_cmd = LOG_GET_RING_STATUS;
+ } else if ((strcmp(argv[j+1], "feature") == 0)) {
+ log_cmd = LOG_GET_FEATURE;
+ } else if ((strcmp(argv[j+1], "ringdata") == 0)) {
+ log_cmd = LOG_GET_RING_DATA;
+ j+=2;
+ if ((strcmp(argv[j], "-n") == 0))
+ memcpy(default_ring_name, argv[j+1], MAX_RING_NAME_SIZE);
+ } else if ((strcmp(argv[j+1], "txfate") == 0)) {
+ log_cmd = LOG_GET_TXPKTFATE;
+ j++;
+ while (j+1 < argc-1) {
+ if (strcmp(argv[j+1], "-n") == 0) {
+ j++;
+ if (j+1 < argc-1) {
+ n_requested_pkt_fate = atoi(argv[j+1]);
+ }
+ } else if (strcmp(argv[j+1], "-f") == 0) {
+ j++;
+ if (j+1 < argc-1) {
+ size_t len = min(strlen(argv[j+1]), (size_t)(FILE_NAME_LEN - 1));
+ strncpy(tx_pkt_fate_file, argv[j+1], len);
+ tx_pkt_fate_file[len] = '\0';
+ }
+ }
+ j++;
+ }
+ } else if ((strcmp(argv[j+1], "rxfate") == 0)) {
+ log_cmd = LOG_GET_RXPKTFATE;
+ j++;
+ while (j+1 < argc-1) {
+ if (strcmp(argv[j+1], "-n") == 0) {
+ j++;
+ if (j+1 < argc-1) {
+ n_requested_pkt_fate = atoi(argv[j+1]);
+ }
+ } else if (strcmp(argv[j+1], "-f") == 0) {
+ j++;
+ if (j+1 < argc-1) {
+ size_t len = min(strlen(argv[j+1]), (size_t)(FILE_NAME_LEN - 1));
+ strncpy(rx_pkt_fate_file, argv[j+1], len);
+ rx_pkt_fate_file[len] = '\0';
+ }
+ }
+ j++;
+ }
+ } else {
+ printf("\nUse correct logger option:\n");
+ printUsage();
+ }
+ return;
+ } else if ((strcmp(argv[j], "-set") == 0) && (argc > 3)) {
+ if ((strcmp(argv[j+1], "loghandler") == 0)) {
+ log_cmd = LOG_SET_LOG_HANDLER;
+ } else if ((strcmp(argv[j+1], "alerthandler") == 0)) {
+ log_cmd = LOG_SET_ALERT_HANDLER;
+ }
+ } else {
+ printf("\nUse correct logger option:\n");
+ printUsage();
+
+ return;
+ }
+}
+
+static int str2hex(char *src, char *dst)
+{
+ int i;
+ if (strlen(src) % 2 != 0) {
+ printMsg(("Mask invalid format. Needs to be of even length\n"));
+ return -1;
+ }
+
+ if (strncmp(src, "0x", 2) == 0 || strncmp(src, "0X", 2) == 0) {
+ src = src + 2; /* Skip past 0x */
+ }
+
+ for (i = 0; *src != '\0'; i++) {
+ char num[3];
+ strncpy(num, src, 2);
+ num[2] = '\0';
+ dst[i] = (u8)strtoul(num, NULL, 16);
+ src += 2;
+ }
+ return i;
+}
+
+void readKeepAliveOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+
+ int index = 0;
+ u32 period_msec = 0;
+ mac_addr src_mac; // byte array of src mac address
+ mac_addr dst_mac; // byte array of dest mac address
+ u8 ip_pkt[MKEEP_ALIVE_IP_PKT_MAX] = {0}; // IP pkt including UDP and headers
+ u16 ip_pkt_len = 0, ether_type = 0;
+ int j = 1;
+ int ret = 0;
+
+ /**
+ * For example,
+ *
+ * u8 ip_pkt[] =
+ * "0014a54b164f000f66f45b7e08004500001e000040004011c52a0a8830700a88302513c413c4000a00000a0d"
+ *
+ * length: 44 bytes
+ *
+ * Ethernet header
+ * 0014a54b164f - dest addr
+ * 000f66f45b7e - src addr
+ * 0800 - ether-type ETHERTYPE_IP (IP protocol) or
+ * 86dd - ether-type ETHERTYPE_IPV6 (IPv6 protocol)
+ * IP header
+ * 4500001e - Version, IHL, TOS, Total length
+ * 00004000 - Identification, fragment
+ * 4011c52a - TTL, Protocol, Checksum
+ * 0a883070 - src addr
+ * 0a883025 - dest addr
+ * UDP header
+ * 13c4 - src port
+ * 13c4 - dest port
+ * 000a - UDP length
+ * 0000 - checksum
+ * UDP payload
+ * 0a0d
+ */
+
+ if ((argc == 9) && (strcmp(argv[j], "-start") == 0)) {
+ // Mapping index
+ index = atoi(argv[++j]);
+ if (index < 1 || index > N_AVAIL_ID) {
+ printMsg("Select proper index number (1 to 3) for mkeep_alive.\n");
+ return;
+ }
+
+ // Mapping period
+ period_msec = atoi(argv[++j]);
+ if (period_msec <= 0) {
+ printMsg("Select proper retransmission period for mkeep_alive, great than zero\n");
+ return;
+ }
+
+ // Mapping mac addresses
+ if ((str2hex(argv[++j], (char *)src_mac) != ETHER_ADDR_LEN)
+ || (str2hex(argv[++j], (char *)dst_mac) != ETHER_ADDR_LEN)) {
+ printMsg("Source or destination mac address is not correct. Please make sure.\n");
+ return;
+ }
+
+ // Mapping ether_type
+ ether_type = atoi(argv[++j]);
+ if (!((ether_type == ETHERTYPE_IP) ||
+ (ether_type == ETHERTYPE_IPV6))) {
+ printMsg("Select proper ether_type, valid values 0x0800(2048) for IP or 0x86dd(34525) IP6\n");
+ return;
+ }
+
+ // Mapping string pkt length by hexa byte
+ ip_pkt_len = strlen(argv[++j])/2;
+ if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
+ printMsg("IP pkt size is bigger than max_len (%d) for mkeep_alive. "
+ "Please check up the size of IP packet contents.\n",
+ MKEEP_ALIVE_IP_PKT_MAX);
+ return;
+ }
+
+ // Mapping pkt contents by hexa format
+ memset(ip_pkt, 0, MKEEP_ALIVE_IP_PKT_MAX);
+ if (str2hex(argv[j], (char *)ip_pkt) != ip_pkt_len) {
+ printMsg("Conversion of hexa byte on IP pkt has been failed.\n");
+ return;
+ }
+
+ ret = start_mkeep_alive(index, period_msec, ether_type, src_mac,
+ dst_mac, ip_pkt, ip_pkt_len);
+ if (ret == WIFI_SUCCESS)
+ printMsg("Success to register mkeep_alive by ID %d\n", index);
+ } else if ((argc == 4) && (strcmp(argv[j], "-stop") == 0)) {
+ // mapping index
+ index = atoi(argv[++j]);
+ if (index < 1 || index > N_AVAIL_ID) {
+ printMsg("Select proper index number (1 to 3) for mkeep_alive.\n");
+ return;
+ }
+
+ ret = stop_mkeep_alive(index);
+ if (ret == WIFI_SUCCESS)
+ printMsg("Success to stop mkeep_alive by ID %d\n", index);
+ } else {
+ printf("Use correct mkeep_alive option:\n");
+ }
+}
+
+const char *eht_rates[] = {
+ "OFDM/LEGACY 1Mbps ",
+ "OFDM/LEGACY 2Mbps ",
+ "OFDM/LEGACY 5.5Mbps ",
+ "OFDM/LEGACY 6Mbps ",
+ "OFDM/LEGACY 9Mbps ",
+ "OFDM/LEGACY 11Mbps ",
+ "OFDM/LEGACY 12Mbps ",
+ "OFDM/LEGACY 18Mbps ",
+ "OFDM/LEGACY 24Mbps ",
+ "OFDM/LEGACY 36Mbps ",
+ "OFDM/LEGACY 48Mbps ",
+ "OFDM/LEGACY 54Mbps ",
+ "HT MCS0 | VHT/HE/EHT MCS0 NSS1",
+ "HT MCS1 | VHT/HE/EHT MCS1 NSS1",
+ "HT MCS2 | VHT/HE/EHT MCS2 NSS1",
+ "HT MCS3 | VHT/HE/EHT MCS3 NSS1",
+ "HT MCS4 | VHT/HE/EHT MCS4 NSS1",
+ "HT MCS5 | VHT/HE/EHT MCS5 NSS1",
+ "HT MCS6 | VHT/HE/EHT MCS6 NSS1",
+ "HT MCS7 | VHT/HE/EHT MCS7 NSS1",
+ "HT MCS8 | VHT/HE/EHT MCS8 NSS1",
+ "HT MCS9 | VHT/HE/EHT MCS9 NSS1",
+ "HT MCS10 | VHT/HE/EHT MCS10 NSS1",
+ "HT MCS11 | VHT/HE/EHT MCS11 NSS1",
+ "HT MCS12 | EHT MCS12 NSS1",
+ "HT MCS13 | EHT MCS13 NSS1",
+ "HT MCS14 | EHT MCS14 NSS1",
+ "HT MCS15 | EHT MCS15 NSS1",
+ "HT N/A | VHT/HE/EHT MCS0 NSS2",
+ "HT N/A | VHT/HE/EHT MCS1 NSS2",
+ "HT N/A | VHT/HE/EHT MCS2 NSS2",
+ "HT N/A | VHT/HE/EHT MCS3 NSS2",
+ "HT N/A | VHT/HE/EHT MCS4 NSS2",
+ "HT N/A | VHT/HE/EHT MCS5 NSS2",
+ "HT N/A | VHT/HE/EHT MCS6 NSS2",
+ "HT N/A | VHT/HE/EHT MCS7 NSS2",
+ "HT N/A | VHT/HE/EHT MCS8 NSS2",
+ "HT N/A | VHT/HE/EHT MCS9 NSS2",
+ "HT N/A | VHT/HE/EHT MCS10 NSS2",
+ "HT N/A | VHT/HE/EHT MCS11 NSS2",
+ "HT N/A | EHT MCS12 NSS2",
+ "HT N/A | EHT MCS13 NSS2",
+ "HT N/A | EHT MCS14 NSS2",
+ "HT N/A | EHT MCS15 NSS2",
+};
+
+const char *rates[] = {
+ "OFDM/LEGACY 1Mbps",
+ "OFDM/LEGACY 2Mbps",
+ "OFDM/LEGACY 5.5Mbps",
+ "OFDM/LEGACY 6Mbps",
+ "OFDM/LEGACY 9Mbps",
+ "OFDM/LEGACY 11Mbps",
+ "OFDM/LEGACY 12Mbps",
+ "OFDM/LEGACY 18Mbps",
+ "OFDM/LEGACY 24Mbps",
+ "OFDM/LEGACY 36Mbps",
+ "OFDM/LEGACY 48Mbps",
+ "OFDM/LEGACY 54Mbps",
+ "HT MCS0 | VHT/HE MCS0 NSS1",
+ "HT MCS1 | VHT/HE MCS1 NSS1",
+ "HT MCS2 | VHT/HE MCS2 NSS1",
+ "HT MCS3 | VHT/HE MCS3 NSS1",
+ "HT MCS4 | VHT/HE MCS4 NSS1",
+ "HT MCS5 | VHT/HE MCS5 NSS1",
+ "HT MCS6 | VHT/HE MCS6 NSS1",
+ "HT MCS7 | VHT/HE MCS7 NSS1",
+ "HT MCS8 | VHT/HE MCS8 NSS1",
+ "HT MCS9 | VHT/HE MCS9 NSS1",
+ "HT MCS10 | VHT/HE MCS10 NSS1",
+ "HT MCS11 | VHT/HE MCS11 NSS1",
+ "HT MCS12 | VHT/HE MCS0 NSS2",
+ "HT MCS13 | VHT/HE MCS1 NSS2",
+ "HT MCS14 | VHT/HE MCS2 NSS2",
+ "HT MCS15 | VHT/HE MCS3 NSS2",
+ "HT N/A | VHT/HE MCS4 NSS2",
+ "HT N/A | VHT/HE MCS5 NSS2",
+ "HT N/A | VHT/HE MCS6 NSS2",
+ "HT N/A | VHT/HE MCS7 NSS2",
+ "HT N/A | VHT/HE MCS8 NSS2",
+ "HT N/A | VHT/HE MCS9 NSS2",
+ "HT N/A | VHT/HE MCS10 NSS2",
+ "HT N/A | VHT/HE MCS11 NSS2",
+};
+
+#define NUM_EHT_RATES (sizeof(eht_rates)/sizeof(eht_rates[0]))
+#define NUM_RATES (sizeof(rates)/sizeof(rates[0]))
+
+#define RATE_SPEC_STR_LEN 10
+#define RATE_SPEC_CHECK_INDEX 27
+const char rate_stat_preamble[][RATE_SPEC_STR_LEN] = {
+ "OFDM",
+ "CCK",
+ "HT",
+ "VHT",
+ "HE",
+ "EHT"
+};
+
+const short int rate_stat_bandwidth[] = {
+ 20,
+ 40,
+ 80,
+ 160,
+ 320
+};
+
+int radios = 0;
+int ml_links = 0;
+
+wifi_radio_stat rx_stat[MAX_NUM_RADIOS];
+wifi_channel_stat cca_stat[MAX_CH_BUF_SIZE];
+
+void updateRateStats(u8 **buf, int num_rates) {
+ printMsg("\nPrinting rate statistics: ");
+ printMsg("------------------------------------------------------\n");
+ printMsg("%40s %12s %14s %15s\n", "TX", "RX", "LOST", "RETRIES");
+ for (int k = 0; k < num_rates; k++) {
+ if (!*buf) {
+ ALOGE("No valid buf of rate_stats for index %d\n", k);
+ continue;
+ }
+ wifi_rate_stat *local_ratestat_ptr = (wifi_rate_stat*)(*buf);
+ if (!local_ratestat_ptr) {
+ printMsg("rate stat data of index %d not found\n", k);
+ continue;
+ }
+ if (num_rates == NUM_EHT_RATES) {
+ printMsg("%-28s %10d %10d %10d %10d\n",
+ eht_rates[k], local_ratestat_ptr->tx_mpdu, local_ratestat_ptr->rx_mpdu,
+ local_ratestat_ptr->mpdu_lost, local_ratestat_ptr->retries);
+ } else if (num_rates == NUM_RATES) {
+ printMsg("%-28s %10d %10d %10d %10d\n",
+ rates[k], local_ratestat_ptr->tx_mpdu, local_ratestat_ptr->rx_mpdu,
+ local_ratestat_ptr->mpdu_lost, local_ratestat_ptr->retries);
+ } else {
+ printMsg("num_rates %d value is not supported\n", num_rates);
+ continue;
+ }
+ *buf += sizeof(wifi_rate_stat);
+ }
+}
+
+void printPeerinfoStats(wifi_peer_info *local_peer_ptr) {
+ printMsg("Peer type = %d\n", local_peer_ptr->type);
+ printMsg("Peer mac address: ( " MACSTR " )\n",
+ MAC2STR(local_peer_ptr->peer_mac_address));
+ printMsg("Peer Capabilities = %d\n", local_peer_ptr->capabilities);
+ printMsg("Load_info(Station Count) = %d\n", local_peer_ptr->bssload.sta_count);
+ printMsg("CCA_level(Channel Utilization) = %d\n", local_peer_ptr->bssload.chan_util);
+ printMsg("Num rate %d \n", local_peer_ptr->num_rate);
+ return;
+}
+
+void update_peer_info_per_link(u8 **buf) {
+ wifi_peer_info *local_peer_ptr = (wifi_peer_info*)(*buf);
+ if (!local_peer_ptr) {
+ printMsg("peer data not found, skip\n");
+ return;
+ }
+
+ printPeerinfoStats(local_peer_ptr);
+
+ if (local_peer_ptr->num_rate) {
+ *buf += offsetof(wifi_peer_info, rate_stats);
+ if (!*buf) {
+ ALOGE("No valid rate_stats\n");
+ return;
+ }
+ updateRateStats(buf, local_peer_ptr->num_rate);
+ }
+}
+
+void printPerLinkStats(wifi_link_stat *local_link_ptr, int link_id) {
+ printMsg("Printing link statistics of the link:%d\n", link_id);
+ printMsg("Identifier for the link = %d\n", local_link_ptr->link_id);
+ printMsg("Radio on which link stats are sampled. = %d\n", local_link_ptr->radio);
+ printMsg("Frequency on which link is operating. = %d MHz\n", local_link_ptr->frequency);
+ printMsg("beacon_rx = %d\n", local_link_ptr->beacon_rx);
+ printMsg("average_tsf_offset= %d\n", local_link_ptr->average_tsf_offset);
+ printMsg("leaky_ap_detected= %d\n", local_link_ptr->leaky_ap_detected);
+ printMsg("leaky_ap_avg_num_frames_leaked= %d\n",
+ local_link_ptr->leaky_ap_avg_num_frames_leaked);
+ printMsg("leaky_ap_guard_time= %d\n", local_link_ptr->leaky_ap_guard_time);
+ printMsg("mgmt_rx= %d\n", local_link_ptr->mgmt_rx);
+ printMsg("mgmt_action_rx= %d\n", local_link_ptr->mgmt_action_rx);
+ printMsg("mgmt_action_tx= %d\n", local_link_ptr->mgmt_action_tx);
+ printMsg("RSSI mgmt = %d\n", local_link_ptr->rssi_mgmt);
+ printMsg("RSSI data = %d\n", local_link_ptr->rssi_data);
+ printMsg("RSSI ack = %d\n", local_link_ptr->rssi_ack);
+ printMsg("AC_BE:\n");
+ printMsg("txmpdu = %d\n", local_link_ptr->ac[WIFI_AC_BE].tx_mpdu);
+ printMsg("rxmpdu = %d\n", local_link_ptr->ac[WIFI_AC_BE].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", local_link_ptr->ac[WIFI_AC_BE].mpdu_lost);
+ printMsg("retries = %d\n", local_link_ptr->ac[WIFI_AC_BE].retries);
+ printMsg("AC_BK:\n");
+ printMsg("txmpdu = %d\n", local_link_ptr->ac[WIFI_AC_BK].tx_mpdu);
+ printMsg("rxmpdu = %d\n", local_link_ptr->ac[WIFI_AC_BK].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", local_link_ptr->ac[WIFI_AC_BK].mpdu_lost);
+ printMsg("AC_VI:\n");
+ printMsg("txmpdu = %d\n", local_link_ptr->ac[WIFI_AC_VI].tx_mpdu);
+ printMsg("rxmpdu = %d\n", local_link_ptr->ac[WIFI_AC_VI].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", local_link_ptr->ac[WIFI_AC_VI].mpdu_lost);
+ printMsg("AC_VO:\n");
+ printMsg("txmpdu = %d\n", local_link_ptr->ac[WIFI_AC_VO].tx_mpdu);
+ printMsg("rxmpdu = %d\n", local_link_ptr->ac[WIFI_AC_VO].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", local_link_ptr->ac[WIFI_AC_VO].mpdu_lost);
+ printMsg("time slicing duty_cycle = %d\n", local_link_ptr->time_slicing_duty_cycle_percent);
+ printMsg("Num peers = %d\n", local_link_ptr->num_peers);
+}
+
+void update_per_link_data(u8 **buf, int link_id) {
+ wifi_link_stat *local_link_ptr = (wifi_link_stat*)(*buf);
+ if (!local_link_ptr) {
+ printMsg("link data not found, skip\n");
+ return;
+ }
+
+ printPerLinkStats(local_link_ptr, link_id);
+
+ if (local_link_ptr->num_peers) {
+ for (int j = 0; j < local_link_ptr->num_peers; j++) {
+ *buf += offsetof(wifi_link_stat, peer_info);
+ if (!*buf) {
+ ALOGE("No valid peer info\n");
+ continue;
+ }
+ update_peer_info_per_link(buf);
+ }
+ }
+}
+
+void onMultiLinkStatsResults(wifi_request_id id, wifi_iface_ml_stat *iface_ml_stat,
+ int num_radios, wifi_radio_stat *radio_stat)
+{
+ u8 *local_rx_ptr = NULL, *local_cca_ptr = NULL, *buf_ptr = NULL;
+ int channel_size = 0, num_channels = 0;
+ int cca_avail_size = MAX_CH_BUF_SIZE;
+
+ if (!num_radios || !iface_ml_stat || !radio_stat) {
+ ALOGE("No valid radio stat data\n");
+ return;
+ }
+
+ radios = num_radios;
+ local_rx_ptr = (u8*)radio_stat;
+ local_cca_ptr = (u8*)cca_stat;
+
+ for (int i = 0; i < num_radios; i++) {
+ memset(&rx_stat[i], 0, sizeof(&rx_stat[i]));
+ memcpy(&rx_stat[i], (u8*)local_rx_ptr, offsetof(wifi_radio_stat, channels));
+ local_rx_ptr += offsetof(wifi_radio_stat, channels);
+ num_channels = rx_stat[i].num_channels;
+ if (num_channels) {
+ channel_size = sizeof(wifi_channel_stat)*num_channels;
+ if (cca_avail_size > num_channels) {
+ memcpy(local_cca_ptr, (u8*)local_rx_ptr, channel_size);
+ cca_avail_size -= num_channels;
+ } else {
+ ALOGE("No space left for chan_stat!!: cca_avail: %d, req: %d\n",
+ cca_avail_size, num_channels);
+ break;
+ }
+ }
+ if (i == (num_radios - 1)) {
+ break;
+ }
+ local_rx_ptr += channel_size;
+ local_cca_ptr += channel_size;
+ }
+ /* radio stat data and channel stats data is printed in printMultiLinkStats */
+
+ buf_ptr = (u8*)iface_ml_stat;
+ ml_links = iface_ml_stat->num_links;
+
+ if (ml_links) {
+ buf_ptr += offsetof(wifi_iface_ml_stat, links);
+ for (int i = 0; i < ml_links; i++) {
+ if (!buf_ptr) {
+ ALOGE("No valid multilink data\n");
+ continue;
+ }
+ printMsg("-----------------------------------------------------\n\n");
+ update_per_link_data(&buf_ptr, i);
+ }
+ }
+}
+
+wifi_iface_stat link_stat;
+int num_rate;
+bssload_info_t bssload;
+wifi_peer_info peer_info[32];
+wifi_rate_stat rate_stat[NUM_RATES];
+wifi_rate_stat eht_rate_stat[NUM_EHT_RATES];
+
+void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat,
+ int num_radios, wifi_radio_stat *radio_stat)
+{
+ int num_peer = 0;
+ u8 *local_rx_stat_ptr = NULL, *local_cca_ptr = NULL;
+ int channel_size = 0, num_channels = 0;
+ int cca_avail_size = MAX_CH_BUF_SIZE;
+
+ if (!num_radios || !iface_stat || !radio_stat) {
+ ALOGE("No valid radio stat data\n");
+ return;
+ }
+
+ radios = num_radios;
+ local_rx_stat_ptr = (u8*)radio_stat;
+ local_cca_ptr = (u8*)cca_stat;
+ for (int i = 0; i < num_radios; i++) {
+ memset(&rx_stat[i], 0, sizeof(&rx_stat[i]));
+ memcpy(&rx_stat[i], (u8*)local_rx_stat_ptr, offsetof(wifi_radio_stat, channels));
+ local_rx_stat_ptr += offsetof(wifi_radio_stat, channels);
+ num_channels = rx_stat[i].num_channels;
+ if (num_channels) {
+ channel_size = sizeof(wifi_channel_stat)*num_channels;
+ if (cca_avail_size > num_channels) {
+ memcpy(local_cca_ptr, (u8*)local_rx_stat_ptr, channel_size);
+ cca_avail_size -= num_channels;
+ } else {
+ ALOGE("No space left for chan_stat!!: cca_avail: %d, req: %d\n",
+ cca_avail_size, num_channels);
+ break;
+ }
+ }
+ if (i == (num_radios - 1)) {
+ break;
+ }
+ local_rx_stat_ptr += channel_size;
+ local_cca_ptr += channel_size;
+ }
+
+ num_peer = iface_stat->num_peers;
+ printMsg("onLinkStatsResults num_peer = %d \n", num_peer);
+ memset(&link_stat, 0, sizeof(wifi_iface_stat));
+ memcpy(&link_stat, iface_stat, sizeof(wifi_iface_stat));
+ memcpy(peer_info, iface_stat->peer_info, num_peer*sizeof(wifi_peer_info));
+ num_rate = peer_info[0].num_rate;
+ printMsg("onLinkStatsResults num_rate = %d \n", num_rate);
+
+ memset(&bssload, 0, sizeof(bssload_info_t));
+ memcpy(&bssload, &iface_stat->peer_info->bssload, sizeof(bssload_info_t));
+
+ if (num_rate == NUM_EHT_RATES) {
+ memset(eht_rate_stat, 0, num_rate*sizeof(wifi_rate_stat));
+ memcpy(&eht_rate_stat, iface_stat->peer_info->rate_stats, num_rate*sizeof(wifi_rate_stat));
+ } else if (num_rate == NUM_RATES) {
+ memset(rate_stat, 0, num_rate*sizeof(wifi_rate_stat));
+ memcpy(&rate_stat, iface_stat->peer_info->rate_stats, num_rate*sizeof(wifi_rate_stat));
+ }
+}
+
+void printFeatureListBitMask(void)
+{
+ printMsg("WIFI_FEATURE_INFRA 0x000000001 - Basic infrastructure mode\n");
+ printMsg("WIFI_FEATURE_INFRA_5G 0x000000002 - Support for 5 GHz Band\n");
+ printMsg("WIFI_FEATURE_HOTSPOT 0x000000004 - Support for GAS/ANQP\n");
+ printMsg("WIFI_FEATURE_P2P 0x000000008 - Wifi-Direct\n");
+ printMsg("WIFI_FEATURE_SOFT_AP 0x000000010 - Soft AP\n");
+ printMsg("WIFI_FEATURE_GSCAN 0x000000020 - Google-Scan APIs\n");
+ printMsg("WIFI_FEATURE_NAN 0x000000040 - Neighbor Awareness Networking\n");
+ printMsg("WIFI_FEATURE_D2D_RTT 0x000000080 - Device-to-device RTT\n");
+ printMsg("WIFI_FEATURE_D2AP_RTT 0x000000100 - Device-to-AP RTT\n");
+ printMsg("WIFI_FEATURE_BATCH_SCAN 0x000000200 - Batched Scan (legacy)\n");
+ printMsg("WIFI_FEATURE_PNO 0x000000400 - Preferred network offload\n");
+ printMsg("WIFI_FEATURE_ADDITIONAL_STA 0x000000800 - Support for two STAs\n");
+ printMsg("WIFI_FEATURE_TDLS 0x000001000 - Tunnel directed link setup\n");
+ printMsg("WIFI_FEATURE_TDLS_OFFCHANNEL 0x000002000 - Support for TDLS off channel\n");
+ printMsg("WIFI_FEATURE_EPR 0x000004000 - Enhanced power reporting\n");
+ printMsg("WIFI_FEATURE_AP_STA 0x000008000 - Support for AP STA Concurrency\n");
+ printMsg("WIFI_FEATURE_LINK_LAYER_STATS 0x000010000 - Link layer stats collection\n");
+ printMsg("WIFI_FEATURE_LOGGER 0x000020000 - WiFi Logger\n");
+ printMsg("WIFI_FEATURE_HAL_EPNO 0x000040000 - iFi PNO enhanced\n");
+ printMsg("WIFI_FEATURE_RSSI_MONITOR 0x000080000 - RSSI Monitor\n");
+ printMsg("WIFI_FEATURE_MKEEP_ALIVE 0x000100000 - WiFi mkeep_alive\n");
+ printMsg("WIFI_FEATURE_CONFIG_NDO 0x000200000 - ND offload configure\n");
+ printMsg("WIFI_FEATURE_TX_TRANSMIT_POWER 0x000400000 - apture Tx transmit power levels\n");
+ printMsg("WIFI_FEATURE_CONTROL_ROAMING 0x000800000 - Enable/Disable firmware roaming\n");
+ printMsg("WIFI_FEATURE_IE_WHITELIST 0x001000000 - Support Probe IE white listing\n");
+ printMsg("WIFI_FEATURE_SCAN_RAND 0x002000000 - Support MAC & Probe Sequence Number randomization\n");
+ printMsg("WIFI_FEATURE_SET_TX_POWER_LIMIT 0x004000000 - Support Tx Power Limit setting\n");
+ printMsg("WIFI_FEATURE_USE_BODY_HEAD_SAR 0x008000000 - Support Using Body/Head Proximity for SAR\n");
+ printMsg("WIFI_FEATURE_DYNAMIC_SET_MAC 0x010000000 - Support changing MAC address without iface reset(down and up)\n");
+ printMsg("WIFI_FEATURE_SET_LATENCY_MODE 0x040000000 - Support Latency mode setting\n");
+ printMsg("WIFI_FEATURE_P2P_RAND_MAC 0x080000000 - Support P2P MAC randomization\n");
+ printMsg("WIFI_FEATURE_INFRA_60G 0x100000000 - Support for 60GHz Band\n");
+}
+
+void printRadioComboMatrix(wifi_radio_combination_matrix *rc)
+{
+ u32 num_radio_combinations = rc->num_radio_combinations;
+ wifi_radio_combination *radio_combinations = rc->radio_combinations;
+ u32 num_radio_configurations;
+ int i,j;
+
+ printMsg("printing band info for combinations:%d\n", num_radio_combinations);
+
+ for (i=0; i < num_radio_combinations; i++) {
+ num_radio_configurations = radio_combinations->num_radio_configurations;
+ printMsg("combination:%d num_radio_configurations:%d\n", i, num_radio_configurations);
+ for (j=0; j < num_radio_configurations; j++) {
+ printMsg("band:%s (%d) antenna cfg:%s (%d)\n",
+ BandToString(radio_combinations->radio_configurations[j].band),
+ radio_combinations->radio_configurations[j].band,
+ AntennCfgToString(radio_combinations->radio_configurations[j].antenna_cfg),
+ radio_combinations->radio_configurations[j].antenna_cfg);
+ }
+
+ if (j == (num_radio_combinations - 1)) {
+ break;
+ }
+ radio_combinations = (wifi_radio_combination *)((u8*)radio_combinations + sizeof(u32) +
+ (num_radio_configurations * sizeof(wifi_radio_configuration)));
+ if (!radio_combinations) {
+ break;
+ }
+ }
+ return;
+}
+
+#define CHAN_STR_LEN 10
+static char chan_str[CHAN_STR_LEN];
+
+static char* frequency_to_channel(int center_freq)
+{
+ if (center_freq >= 2412 && center_freq <= 2484) {
+ if (center_freq == 2484) {
+ snprintf(chan_str, CHAN_STR_LEN, "2g/ch14");
+ } else {
+ snprintf(chan_str, CHAN_STR_LEN, "2g/ch%d", (center_freq - 2407) / 5);
+ }
+ } else if (center_freq >= 5180 && center_freq <= 5825) {
+ snprintf(chan_str, CHAN_STR_LEN, "5g/ch%d", (center_freq - 5000) / 5);
+ } else if (center_freq >= 5845 && center_freq <= 5885) {
+ /* UNII-4 channels */
+ snprintf(chan_str, CHAN_STR_LEN, "5g/ch%d", (center_freq - 5000) / 5);
+ } else if (center_freq >= 5935 && center_freq <= 7115) {
+ if (center_freq == 5935) {
+ snprintf(chan_str, CHAN_STR_LEN, "6g/ch2");
+ } else {
+ snprintf(chan_str, CHAN_STR_LEN, "6g/ch%d", (center_freq - 5950) / 5);
+ }
+ } else {
+ snprintf(chan_str, CHAN_STR_LEN, "Err");
+ }
+
+ return &chan_str[0];
+}
+
+void printMultiLinkStats(wifi_channel_stat cca_stat[],
+ wifi_radio_stat rx_stat[], int radios)
+{
+ int new_chan_base = 0;
+ printMsg("\nPrinting radio statistics of multi link\n");
+ printMsg("--------------------------------------\n");
+ for (int i = 0; i < radios; i++) {
+ printMsg("radio = %d\n", rx_stat[i].radio);
+ printMsg("on time = %d\n", rx_stat[i].on_time);
+ printMsg("tx time = %d\n", rx_stat[i].tx_time);
+ printMsg("num_tx_levels = %d\n", rx_stat[i].num_tx_levels);
+ printMsg("rx time = %d\n", rx_stat[i].rx_time);
+ printMsg("SCAN\n");
+ printMsg("on_time_scan(duration)= %d\n", rx_stat[i].on_time_scan);
+ printMsg("on_time_nbd(duration)= %d\n", rx_stat[i].on_time_nbd);
+ printMsg("on_time_gscan(duration)= %d\n", rx_stat[i].on_time_gscan);
+ printMsg("on_time_roam_scan(duration)= %d\n", rx_stat[i].on_time_roam_scan);
+ printMsg("on_time_pno_scan(duration)= %d\n", rx_stat[i].on_time_pno_scan);
+ printMsg("on_time_hs20 = %d\n", rx_stat[i].on_time_hs20);
+ printMsg("cca channel statistics: (num_channels: %d)\n", rx_stat[i].num_channels);
+ for (int j = new_chan_base; j < (new_chan_base + rx_stat[i].num_channels); j++) {
+ printMsg("center_freq=%d (%8s), radio_on_time %10d, cca_busytime %10d\n",
+ cca_stat[j].channel.center_freq,
+ frequency_to_channel(cca_stat[j].channel.center_freq),
+ cca_stat[j].on_time, cca_stat[j].cca_busy_time);
+ }
+ new_chan_base += rx_stat[i].num_channels;
+ }
+ printMsg("\n");
+}
+/////////////////////////////////////////////////////////////////////
+void printLinkStats(wifi_iface_stat *link_stat, wifi_channel_stat cca_stat[],
+ wifi_radio_stat rx_stat[], bssload_info_t *bssload, int radios)
+{
+ int new_chan_base = 0;
+ printMsg("Printing link layer statistics:\n");
+ printMsg("--------------------------------------\n");
+ printMsg("Num peer = %d\n", link_stat->num_peers);
+ printMsg("beacon_rx = %d\n", link_stat->beacon_rx);
+ printMsg("RSSI = %d\n", link_stat->rssi_mgmt);
+ printMsg("Load_info(Station Count) = %d\n", bssload->sta_count);
+ printMsg("CCA_level(Channel Utilization) = %d\n", bssload->chan_util);
+ printMsg("AC_BE:\n");
+ printMsg("txmpdu = %d\n", link_stat->ac[WIFI_AC_BE].tx_mpdu);
+ printMsg("rxmpdu = %d\n", link_stat->ac[WIFI_AC_BE].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", link_stat->ac[WIFI_AC_BE].mpdu_lost);
+ printMsg("retries = %d\n", link_stat->ac[WIFI_AC_BE].retries);
+ printMsg("AC_BK:\n");
+ printMsg("txmpdu = %d\n", link_stat->ac[WIFI_AC_BK].tx_mpdu);
+ printMsg("rxmpdu = %d\n", link_stat->ac[WIFI_AC_BK].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", link_stat->ac[WIFI_AC_BK].mpdu_lost);
+ printMsg("AC_VI:\n");
+ printMsg("txmpdu = %d\n", link_stat->ac[WIFI_AC_VI].tx_mpdu);
+ printMsg("rxmpdu = %d\n", link_stat->ac[WIFI_AC_VI].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", link_stat->ac[WIFI_AC_VI].mpdu_lost);
+ printMsg("AC_VO:\n");
+ printMsg("txmpdu = %d\n", link_stat->ac[WIFI_AC_VO].tx_mpdu);
+ printMsg("rxmpdu = %d\n", link_stat->ac[WIFI_AC_VO].rx_mpdu);
+ printMsg("mpdu_lost = %d\n", link_stat->ac[WIFI_AC_VO].mpdu_lost);
+ printMsg("time slicing duty_cycle = %d\n", link_stat->info.time_slicing_duty_cycle_percent);
+ printMsg("\n");
+ printMsg("Printing radio statistics:\n");
+ printMsg("--------------------------------------\n");
+ for (int i = 0; i < radios; i++) {
+ printMsg("--------------------------------------\n");
+ printMsg("radio = %d\n", rx_stat[i].radio);
+ printMsg("on time = %d\n", rx_stat[i].on_time);
+ printMsg("tx time = %d\n", rx_stat[i].tx_time);
+ printMsg("num_tx_levels = %d\n", rx_stat[i].num_tx_levels);
+ printMsg("rx time = %d\n", rx_stat[i].rx_time);
+ printMsg("SCAN\n");
+ printMsg("on_time_scan(duration)= %d\n", rx_stat[i].on_time_scan);
+ printMsg("on_time_nbd(duration)= %d\n", rx_stat[i].on_time_nbd);
+ printMsg("on_time_gscan(duration)= %d\n", rx_stat[i].on_time_gscan);
+ printMsg("on_time_roam_scan(duration)= %d\n", rx_stat[i].on_time_roam_scan);
+ printMsg("on_time_pno_scan(duration)= %d\n", rx_stat[i].on_time_pno_scan);
+ printMsg("on_time_hs20 = %d\n", rx_stat[i].on_time_hs20);
+ printMsg("cca channel statistics: (num_channels: %d)\n", rx_stat[i].num_channels);
+ for (int j = new_chan_base; j < (new_chan_base + rx_stat[i].num_channels); j++) {
+ printMsg("center_freq=%d (%8s), radio_on_time %10d, cca_busytime %10d\n",
+ cca_stat[j].channel.center_freq,
+ frequency_to_channel(cca_stat[j].channel.center_freq),
+ cca_stat[j].on_time, cca_stat[j].cca_busy_time);
+ }
+ new_chan_base += rx_stat[i].num_channels;
+ }
+ printMsg("\n");
+ if (num_rate == NUM_EHT_RATES) {
+ printMsg("(current BSS info: %s, %dMhz)\n",
+ rate_stat_preamble[eht_rate_stat[RATE_SPEC_CHECK_INDEX].rate.preamble],
+ rate_stat_bandwidth[eht_rate_stat[RATE_SPEC_CHECK_INDEX].rate.bw]);
+ } else if (num_rate == NUM_RATES) {
+ printMsg("(current BSS info: %s, %dMhz)\n",
+ rate_stat_preamble[rate_stat[RATE_SPEC_CHECK_INDEX].rate.preamble],
+ rate_stat_bandwidth[rate_stat[RATE_SPEC_CHECK_INDEX].rate.bw]);
+ } else {
+ printMsg("No peer found!");
+ return;
+ }
+ printMsg("Printing rate statistics: num_rate %d", num_rate);
+ printMsg("--------------------------------------\n");
+ printMsg("%40s %12s %14s %15s\n", "TX", "RX", "LOST", "RETRIES");
+ for (int i=0; i < num_rate; i++) {
+ if (num_rate == NUM_EHT_RATES) {
+ printMsg("%-28s %10d %10d %10d %10d\n",
+ eht_rates[i], eht_rate_stat[i].tx_mpdu, eht_rate_stat[i].rx_mpdu,
+ eht_rate_stat[i].mpdu_lost, eht_rate_stat[i].retries);
+ } else if (num_rate == NUM_RATES) {
+ printMsg("%-28s %10d %10d %10d %10d\n",
+ rates[i], rate_stat[i].tx_mpdu, rate_stat[i].rx_mpdu,
+ rate_stat[i].mpdu_lost, rate_stat[i].retries);
+ }
+ }
+}
+
+void getLinkStats(void)
+{
+ wifi_stats_result_handler handler;
+ memset(&handler, 0, sizeof(handler));
+
+ handler.on_link_stats_results = &onLinkStatsResults;
+ handler.on_multi_link_stats_results = &onMultiLinkStatsResults;
+
+ int result = hal_fn.wifi_get_link_stats(0, wlan0Handle, handler);
+ if (result < 0) {
+ printMsg("failed to get link stat - %d\n", result);
+ } else if (!radios) {
+ printMsg("Invalid link stat data\n");
+ } else if (ml_links) {
+ printMultiLinkStats(cca_stat, rx_stat, radios);
+ } else {
+ printLinkStats(&link_stat, cca_stat, rx_stat, &bssload, radios);
+ }
+}
+
+void getChannelList(void)
+{
+ wifi_channel channel[MAX_CH_BUF_SIZE] = {0, };
+ int num_channels = 0, i = 0;
+
+ int result = hal_fn.wifi_get_valid_channels(wlan0Handle, band, MAX_CH_BUF_SIZE,
+ channel, &num_channels);
+ if (result < 0) {
+ printMsg("failed to get valid channels %d\n", result);
+ return;
+ }
+ printMsg("Number of channels - %d\nChannel List:\n",num_channels);
+ for (i = 0; i < num_channels; i++) {
+ printMsg("%d MHz\n", channel[i]);
+ }
+}
+
+void getFeatureSet(void)
+{
+ feature_set set;
+ int result = hal_fn.wifi_get_supported_feature_set(wlan0Handle, &set);
+
+ if (result < 0) {
+ printMsg("Error %d\n",result);
+ return;
+ }
+ printFeatureListBitMask();
+ printMsg("Supported feature set bit mask - %x\n", set);
+ return;
+}
+
+void getFeatureSetMatrix(void)
+{
+ feature_set set[MAX_FEATURE_SET];
+ int size;
+
+ int result = hal_fn.wifi_get_concurrency_matrix(wlan0Handle, MAX_FEATURE_SET, set, &size);
+
+ if (result < 0) {
+ printMsg("Error %d\n",result);
+ return;
+ }
+ printFeatureListBitMask();
+ for (int i = 0; i < size; i++)
+ printMsg("Concurrent feature set - %x\n", set[i]);
+ return;
+}
+
+void getSupportedRadioMatrix(void)
+{
+ wifi_radio_combination_matrix *radio_matrix;
+ u32 size, max_size = 0;
+ int result;
+
+ max_size = sizeof(wifi_radio_combination_matrix) +
+ MAX_RADIO_COMBO*(sizeof(wifi_radio_combination) +
+ MAX_CORE * sizeof(wifi_radio_configuration));
+
+ radio_matrix = (wifi_radio_combination_matrix*)malloc(max_size);
+ if (!radio_matrix) {
+ printMsg("%s:Malloc failed\n",__FUNCTION__);
+ return;
+ }
+ memset(radio_matrix, 0 , max_size);
+
+ result = hal_fn.wifi_get_supported_radio_combinations_matrix(halHandle,
+ max_size, &size, radio_matrix);
+ if (!radio_matrix || !size || result < 0) {
+ printMsg("Error %d\n", result);
+ goto free_mem;
+ }
+
+ printRadioComboMatrix(radio_matrix);
+
+free_mem:
+ if (radio_matrix) {
+ free(radio_matrix);
+ }
+
+ return;
+}
+
+int getWakeStats()
+{
+ WLAN_DRIVER_WAKE_REASON_CNT *wake_reason_cnt;
+
+ wake_reason_cnt = (WLAN_DRIVER_WAKE_REASON_CNT*) malloc(sizeof(WLAN_DRIVER_WAKE_REASON_CNT));
+ if (!wake_reason_cnt) {
+ printMsg("%s:Malloc failed\n",__FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(wake_reason_cnt, 0 , sizeof(WLAN_DRIVER_WAKE_REASON_CNT));
+ wake_reason_cnt->cmd_event_wake_cnt_sz = EVENT_COUNT;
+ wake_reason_cnt->cmd_event_wake_cnt = (int*)malloc(EVENT_COUNT * sizeof(int));
+
+ int result = hal_fn.wifi_get_wake_reason_stats(wlan0Handle, wake_reason_cnt);
+ if (result < 0) {
+ printMsg("Error %d\n",result);
+ free(wake_reason_cnt->cmd_event_wake_cnt);
+ free(wake_reason_cnt);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ printMsg(" ------- DRIVER WAKE REASON STATS -------\n");
+ printMsg("TotalCmdWake = %d\n", wake_reason_cnt->total_cmd_event_wake);
+ printMsg("MaxCmdEvent = %d\n", wake_reason_cnt->cmd_event_wake_cnt_sz);
+ printMsg("MaxCmdEventUsed = %d\n", wake_reason_cnt->cmd_event_wake_cnt_used);
+ printMsg("-----------------------------------------------------------\n");
+ printMsg("TotalRxDataWake = %d\n", wake_reason_cnt->total_rx_data_wake);
+ printMsg("RxUniCnt = %d\n", wake_reason_cnt->rx_wake_details.rx_unicast_cnt);
+ printMsg("RxMultiCnt = %d\n", wake_reason_cnt->rx_wake_details.rx_multicast_cnt);
+ printMsg("RxBcastCnt = %d\n", wake_reason_cnt->rx_wake_details.rx_broadcast_cnt);
+ printMsg("-----------------------------------------------------------\n");
+ printMsg("ICMP count = %d\n", wake_reason_cnt->rx_wake_pkt_classification_info.icmp_pkt);
+ printMsg("ICMP6 count = %d\n", wake_reason_cnt->rx_wake_pkt_classification_info.icmp6_pkt);
+ printMsg("ICMP6 ra count = %d\n", wake_reason_cnt->rx_wake_pkt_classification_info.icmp6_ra);
+ printMsg("ICMP6 na count = %d\n", wake_reason_cnt->rx_wake_pkt_classification_info.icmp6_na);
+ printMsg("ICMP6 ns count = %d\n", wake_reason_cnt->rx_wake_pkt_classification_info.icmp6_ns);
+ printMsg("-----------------------------------------------------------\n");
+ printMsg("Rx IPV4 Mcast = %d\n", wake_reason_cnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt);
+ printMsg("Rx IPV6 Mcast = %d\n", wake_reason_cnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt);
+ printMsg("Rx Other Mcast = %d\n", wake_reason_cnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt);
+ printMsg("-----------------------------------------------------------\n");
+ printMsg("Events Received and received count\n");
+ for (int i = 0; i <= wake_reason_cnt->cmd_event_wake_cnt_used; i++) {
+ if (wake_reason_cnt->cmd_event_wake_cnt[i] != 0)
+ printMsg("Event ID %d = %u\n", i, wake_reason_cnt->cmd_event_wake_cnt[i]);
+ }
+
+ free(wake_reason_cnt->cmd_event_wake_cnt);
+ free(wake_reason_cnt);
+ return WIFI_SUCCESS;
+}
+
+static wifi_error setBlacklist(bool clear)
+{
+ if (num_blacklist_bssids == -1 && !clear)
+ return WIFI_SUCCESS;
+ wifi_roaming_config roam_config;
+ cmdId = getNewCmdId();
+ if (clear) {
+ roam_config.num_blacklist_bssid = 0;
+ printMsg("Clear Blacklist BSSIDs\n");
+ } else {
+ roam_config.num_blacklist_bssid = num_blacklist_bssids;
+ printMsg("Setting %d Blacklist BSSIDs\n", num_blacklist_bssids);
+ }
+ for (int i = 0; i < num_blacklist_bssids; i++) {
+ memcpy(&roam_config.blacklist_bssid[i], &blacklist_bssids[i],
+ sizeof(mac_addr) );
+ }
+ return hal_fn.wifi_configure_roaming(wlan0Handle, &roam_config);
+}
+
+static wifi_error setRoamingConfiguration()
+{
+ wifi_error ret;
+ wifi_roaming_config roam_config;
+ cmdId = getNewCmdId();
+
+ roam_config.num_blacklist_bssid = num_blacklist_bssids;
+ roam_config.num_whitelist_ssid = num_whitelist_ssids;
+ if(num_blacklist_bssids != -1) {
+ for (int i = 0; i < num_blacklist_bssids; i++) {
+ memcpy(&roam_config.blacklist_bssid[i], &blacklist_bssids[i], sizeof(mac_addr) );
+ }
+ }
+
+ if(num_whitelist_ssids != -1) {
+ for (int j = 0; j < num_whitelist_ssids; j++) {
+ printf("%s\n", whitelist_ssids[j]);
+ strncpy(roam_config.whitelist_ssid[j].ssid_str, whitelist_ssids[j], (MAX_SSID_LENGTH - 1));
+ roam_config.whitelist_ssid[j].ssid_str[MAX_SSID_LENGTH - 1] = '\0';
+ roam_config.whitelist_ssid[j].length =
+ strlen(roam_config.whitelist_ssid[j].ssid_str);
+ }
+ }
+
+ ret = hal_fn.wifi_configure_roaming(wlan0Handle, &roam_config);
+
+ return ret;
+}
+
+static wifi_error getRoamingCapabilities()
+{
+ wifi_error ret;
+ wifi_roaming_capabilities roam_capability;
+
+ ret = hal_fn.wifi_get_roaming_capabilities(wlan0Handle, &roam_capability);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Roaming Capabilities\n"
+ "max_blacklist_size = %d\n"
+ "max_whitelist_size = %d\n", roam_capability.max_blacklist_size,
+ roam_capability.max_whitelist_size);
+ } else {
+ printMsg("Failed to get Roaming capabilities\n");
+ }
+ return ret;
+}
+
+static wifi_error setFWRoamingState(fw_roaming_state_t state)
+{
+ wifi_error ret = WIFI_SUCCESS;
+
+ return ret;
+}
+
+static void testRssiMonitor()
+{
+ int id = -1;
+ wifi_rssi_event_handler handler;
+ EventInfo info;
+ handler.on_rssi_threshold_breached = onRssiThresholdbreached;
+ if (rssi_monitor) {
+ rssiMonId = getNewCmdId();
+ wifi_error ret = hal_fn.wifi_start_rssi_monitoring(rssiMonId, wlan0Handle,
+ max_rssi, min_rssi, handler);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to set RSSI monitor %d\n", ret);
+ return;
+ }
+ printMsg("rssi_monitor: %d %d %d %d\n", rssi_monitor, max_rssi, min_rssi,rssiMonId);
+ while (true) {
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ if (info.type == EVENT_TYPE_RSSI_MONITOR) {
+ printMsg("done!!\n");
+ break;
+ }
+ }
+ } else {
+ if (rssiMonId == 0)
+ id = -1;
+ hal_fn.wifi_stop_rssi_monitoring(id, wlan0Handle);
+ }
+ return;
+}
+
+static wifi_error setApfProgram(char *str, wifi_interface_handle ifHandle)
+{
+ u32 program_len;
+ u8* program;
+ wifi_error ret;
+
+ if (str == NULL) {
+ printMsg("APF program missing\n");
+ printApfUsage();
+ return WIFI_ERROR_UNINITIALIZED;
+ }
+
+ if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0) {
+ str = str + 2; /* Skip past 0x */
+ }
+ program_len = (strlen((const char *)str) / 2);
+ program = (u8 *)malloc(program_len);
+ if (!program) {
+ printMsg("Memory allocation failed\n");
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ if ((u32)str2hex(str, (char *)program) != program_len) {
+ printMsg("Invalid APF program\n");
+ if (program) {
+ free(program);
+ }
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ ret = hal_fn.wifi_set_packet_filter(ifHandle, program, program_len);
+ if (ret != WIFI_SUCCESS) {
+ if (program) {
+ free(program);
+ }
+ printMsg("Failed to set APF program, ret = %d\n", ret);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ if (program) {
+ free(program);
+ }
+
+ return ret;
+}
+
+static wifi_error getApfCapabilities(wifi_interface_handle ifHandle)
+{
+ u32 version, max_len;
+
+ wifi_error ret = hal_fn.wifi_get_packet_filter_capabilities(ifHandle,
+ &version, &max_len);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to get APF capability, ret = %d\n", ret);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ printMsg("APF capabilities, version = %u, max_len = %u bytes\n",
+ version, max_len);
+ return WIFI_SUCCESS;
+}
+
+static wifi_error getApfFilterData(wifi_interface_handle ifHandle)
+{
+ u8 *buf, *pc;
+ u32 version, max_len, i;
+ wifi_error ret;
+
+ ret = hal_fn.wifi_get_packet_filter_capabilities(ifHandle,
+ &version, &max_len);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to get APF buffer size, ret = %d\n", ret);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ buf = (u8 *)malloc(max_len);
+ if (!buf) {
+ printMsg("Memory allocation failed\n");
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = hal_fn.wifi_read_packet_filter(ifHandle, 0, buf, max_len);
+ if (ret != WIFI_SUCCESS) {
+ if (buf) {
+ free(buf);
+ }
+ printMsg("Failed to get APF buffer dump, ret = %d\n", ret);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ printMsg("\nAPF buffer size = %u (0x%x) bytes\n\n", max_len, max_len);
+ printMsg("APF buffer data =\n\n");
+ for (i = 1, pc = buf; pc && (i <= max_len); pc++, i++) {
+ printf("%02X", *pc);
+ if (i && ((i % 64) == 0)) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+
+ if (buf) {
+ free(buf);
+ }
+ return WIFI_SUCCESS;
+}
+
+int testApfOptions(int argc, char *argv[])
+{
+ void printApfUsage(); // declaration for below printUsage()
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+ char *val_p = NULL;
+ wifi_error ret;
+ wifi_interface_handle ifHandle = NULL;
+
+ argv++; /* skip utility */
+ argv++; /* skip -apf command */
+
+ val_p = *argv++;
+ if (val_p != NULL) {
+ if (!set_interface_params(iface_name, val_p, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto usage;
+ }
+ }
+
+ ifHandle = wifi_get_iface_handle(halHandle, iface_name);
+ if (ifHandle == NULL) {
+ printMsg("Invalid iface handle for the requested interface\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto usage;
+ } else {
+ while ((val_p = *argv++) != NULL) {
+ if (!val_p) {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, val_p);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto usage;
+ }
+ if (strcmp(val_p, "-set") == 0) {
+ val_p = *argv++;
+ if (strcmp(val_p, "program") == 0) {
+ val_p = *argv++;
+ printMsg("program = %s\n\n", val_p);
+ printMsg("set program capa: Iface handle = %p for the requested interface: %s\n",
+ ifHandle, iface_name);
+ if (ifHandle) {
+ ret = setApfProgram(val_p, ifHandle);
+ }
+ } else {
+ printMsg("Invalid value after program arg\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto usage;
+ }
+ } else if (strcmp(val_p, "-get") == 0) {
+ val_p = *argv++;
+ if (strcmp(val_p, "capa") == 0) {
+ printMsg("get capa: Iface handle = %p for the requested interface: %s\n",
+ ifHandle, iface_name);
+ if (ifHandle) {
+ ret = getApfCapabilities(ifHandle);
+ }
+ } else if (strcmp(val_p, "data") == 0) {
+ printMsg("get data: Iface handle = %p for the requested interface: %s\n",
+ ifHandle, iface_name);
+ if (ifHandle) {
+ ret = getApfFilterData(ifHandle);
+ }
+ } else {
+ printMsg("Invalid value for get cmd\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto usage;
+ }
+ } else {
+ printMsg("Invalid option for apf cmd\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto usage;
+ }
+ }
+ }
+
+usage:
+ printApfUsage();
+ return WIFI_ERROR_INVALID_ARGS;
+}
+
+static int setDscpMap(s32 start, s32 end, s32 ac)
+{
+ void printUsage(); // declaration for below printUsage()
+ int ret;
+
+ if (start == -1 || end == -1 || ac == -1) {
+ printMsg("DSCP param missing\n");
+ printUsage();
+ return WIFI_ERROR_UNINITIALIZED;
+ }
+
+ ret = hal_fn.wifi_map_dscp_access_category(halHandle, start, end, ac);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to set DSCP: %d\n", ret);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ return WIFI_SUCCESS;
+}
+
+static int resetDscpMap()
+{
+ int ret;
+
+ ret = hal_fn.wifi_reset_dscp_mapping(halHandle);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to reset DSCP: %d\n", ret);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ return WIFI_SUCCESS;
+}
+
+static int setChannelAvoidance(u32 num, wifi_coex_unsafe_channel configs[], u32 mandatory)
+{
+ int ret;
+
+ ret = hal_fn.wifi_set_coex_unsafe_channels(halHandle, num, configs, mandatory);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to set Channel Avoidance: %d\n", ret);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ return WIFI_SUCCESS;
+}
+
+void testSarOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+ wifi_power_scenario mWifi_power_scenario;
+ wifi_error res;
+ int scenario;
+
+ if (argc < 2) {
+ goto usage;
+ }
+
+ if ((argc > 2) && (strcmp(argv[1], "enable") == 0)) {
+ scenario = atoi(argv[2]);
+ if ((scenario < WIFI_POWER_SCENARIO_DEFAULT) || (scenario > SAR_CONFIG_SCENARIO_COUNT)) {
+ printMsg("Unsupported tx power value:%d: Allowed range -1 to 99\n", scenario);
+ return;
+ }
+ mWifi_power_scenario = (wifi_power_scenario)scenario;
+ res = hal_fn.wifi_select_tx_power_scenario(wlan0Handle, mWifi_power_scenario);
+ } else if ((strcmp(argv[1], "disable") == 0)) {
+ res = hal_fn.wifi_reset_tx_power_scenario(wlan0Handle);
+ } else {
+ goto usage;
+ }
+
+ if (res == WIFI_SUCCESS) {
+ printMsg("Success to execute sar test command\n");
+ } else {
+ printMsg("Failed to execute sar test command, res = %d\n", res);
+ }
+ return;
+
+usage:
+ printUsage();
+ return;
+}
+
+void testThermalMitigationOptions(int argc, char *argv[])
+{
+ void printUsage(); //declaration for below printUsage()
+ wifi_thermal_mode mode;
+ wifi_error result;
+
+ if (argc < 2) {
+ goto usage;
+ }
+
+ if (strcmp(argv[1], "none") == 0) {
+ mode = WIFI_MITIGATION_NONE;
+ } else if (strcmp(argv[1], "light") == 0) {
+ mode = WIFI_MITIGATION_LIGHT;
+ } else if (strcmp(argv[1], "moderate") == 0) {
+ mode = WIFI_MITIGATION_MODERATE;
+ } else if (strcmp(argv[1], "severe") == 0) {
+ mode = WIFI_MITIGATION_SEVERE;
+ } else if (strcmp(argv[1], "critical") == 0) {
+ mode = WIFI_MITIGATION_CRITICAL;
+ } else if (strcmp(argv[1], "emergency") == 0) {
+ mode = WIFI_MITIGATION_EMERGENCY;
+ } else {
+ printMsg("unknown thermal mode %s\n", argv[1]);
+ goto usage;
+ }
+
+ result = hal_fn.wifi_set_thermal_mitigation_mode(halHandle, mode, 0);
+ if (result == WIFI_ERROR_NONE) {
+ printMsg("Success set thermal mode\n");
+ } else {
+ printMsg("Failed set thermal mode, result = %d\n", result);
+ }
+ return;
+
+usage:
+ printUsage();
+}
+
+void testLatencyModeOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+ wifi_latency_mode mWifi_latency_mode;
+ wifi_error res;
+
+ if (argc < 2) {
+ goto usage;
+ }
+
+ if (strcmp(argv[1], "normal") == 0) {
+ mWifi_latency_mode = WIFI_LATENCY_MODE_NORMAL;
+ } else if (strcmp(argv[1], "low") == 0) {
+ mWifi_latency_mode = WIFI_LATENCY_MODE_LOW;
+ } else if (strcmp(argv[1], "ultra-low") == 0) {
+ mWifi_latency_mode = (wifi_latency_mode)2 ; //TODO: To be removed
+ } else {
+ goto usage;
+ }
+
+ res = hal_fn.wifi_set_latency_mode(wlan0Handle, mWifi_latency_mode);
+ if (res == WIFI_SUCCESS) {
+ printMsg("Success to execute set wifi latency mode test command\n");
+ } else {
+ printMsg("Failed to execute set wifi latency mode test command, res = %d\n", res);
+ }
+ return;
+
+usage:
+ printUsage();
+ return;
+}
+
+void testDscpOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+ int j = 1;
+ s32 start = -1;
+ s32 end = -1;
+ s32 ac = -1;
+
+ if (argc < 3) {
+ goto usage;
+ }
+
+ if ((strcmp(argv[j], "-reset") == 0) && (argc == 3)) {
+ resetDscpMap();
+ } else if ((strcmp(argv[j], "-set") == 0) && (argc == 9)) {
+ if ((strcmp(argv[++j], "-s") == 0) && isdigit(argv[j+1][0]))
+ start = atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-e") == 0) && isdigit(argv[j+1][0]))
+ end = atoi(argv[++j]);
+ if ((strcmp(argv[++j], "-ac") == 0) && isdigit(argv[j+1][0]))
+ ac = atoi(argv[++j]);
+ setDscpMap(start, end, ac);
+ } else {
+ goto usage;
+ }
+ return;
+
+usage:
+ printUsage();
+ return;
+}
+
+static void printTxPowerUsage() {
+ printf("Usage: halutil [OPTION]\n");
+ printf(" -tx_pwr_cap -enable\n");
+ printf(" -tx_pwr_cap -disable\n");
+ return;
+}
+
+static void printApfUsage() {
+ printf("Usage: halutil [OPTION]\n");
+ printf(" -apf [-ifname] <interface name> [-get] [capa]\n");
+ printf(" -apf [-ifname] <interface name> [-get] [data]\n");
+ printf(" -apf [-ifname] <interface name> [-set] [program] <bytecodes>\n");
+ return;
+}
+
+static void printTwtUsage() {
+ printf("Usage: halutil [OPTION]\n");
+ printf("halutil -twt -setup -config_id <> -neg_type <0 for individual TWT, 1 for broadcast TWT> "
+ "-trigger_type <0 for non-triggered TWT, 1 for triggered TWT> "
+ "-wake_dur_us <> -wake_int_us <> -wake_int_min_us <> "
+ "-wake_int_max_us <> -wake_dur_min_us <> -wake_dur_max_us <> "
+ "-avg_pkt_size <> -avg_pkt_num <> -wake_time_off_us <>\n");
+ printf("halutil -twt -info_frame -config_id <>"
+ " -all_twt <0 for individual setp request, 1 for all TWT> -resume_time_us <>\n");
+ printf("halutil -twt -teardown -config_id <> -all_twt <> "
+ " -neg_type <0 for individual TWT, 1 for broadcast TWT>\n");
+ printf("halutil -twt -get_stats -config_id <>\n");
+ printf("halutil -twt -clear_stats -config_id <>\n");
+ printf("halutil -get_capa_twt\n");
+ printf("halutil -twt -event_chk\n");
+ return;
+}
+
+static void printChreNanRttUsage() {
+ printf("Usage: halutil [OPTION]\n");
+ printf("halutil -chre_nan_rtt -enable\n");
+ printf("halutil -chre_nan_rtt -disable\n");
+ printf("halutil -chre -register\n");
+ return;
+}
+
+void
+bandstr_to_macband(char *band_str, wlan_mac_band *band)
+{
+ if (!strcasecmp(band_str, "a")) {
+ *band = WLAN_MAC_5_0_BAND;
+ } else if (!strcasecmp(band_str, "b")) {
+ *band = WLAN_MAC_2_4_BAND;
+ } else if (!strcasecmp(band_str, "6g")) {
+ *band = WLAN_MAC_6_0_BAND;
+ } else if (!strcasecmp(band_str, "60")) {
+ *band = WLAN_MAC_60_0_BAND;
+ }
+}
+void
+bandstr_to_band(char *band_str, u32 *band)
+{
+ if (!strcasecmp(band_str, "a")) {
+ *band = WIFI_BAND_A;
+ } else if (!strcasecmp(band_str, "b")) {
+ *band = WIFI_BAND_BG;
+ } else if (!strcasecmp(band_str, "all")) {
+ *band = WIFI_BAND_ABG;
+ } else {
+ *band = WIFI_BAND_UNSPECIFIED;
+ }
+}
+
+void parse_unsafe(char *val_p, wifi_coex_unsafe_channel ca_configs[], int *idx)
+{
+ char *space_end;
+ char *comma_end;
+ char *space = strtok_r(val_p, ":", &space_end);
+ wlan_mac_band band;
+ while (space != NULL) {
+ char *token = strtok_r(space, ",", &comma_end);
+ if (!token) {
+ printf("Need 3 values\n");
+ return;
+ }
+ bandstr_to_macband(token, &band);
+ if (band != WLAN_MAC_2_4_BAND && band != WLAN_MAC_5_0_BAND) {
+ printMsg("Unsupported band\n");
+ return;
+ }
+ ca_configs[*idx].band = band;
+ token = strtok_r(NULL, ",", &comma_end);
+ if (!token) {
+ printf("Need 3 values\n");
+ return;
+ }
+ ca_configs[*idx].channel = atoi(token);
+ token = strtok_r(NULL, ",", &comma_end);
+ if (!token) {
+ printf("Need 3 values\n");
+ return;
+ }
+ ca_configs[*idx].power_cap_dbm = atoi(token);
+
+ token = strtok_r(NULL, ",", &comma_end);
+ if (token) {
+ printf("Need only 3 values\n");
+ return;
+ }
+ (*idx)++;
+
+ space = strtok_r(NULL, ":", &space_end);
+ }
+}
+
+
+void testChannelAvoidanceOptions(int argc, char *argv[])
+{
+ char *param;
+ char *val_p;
+ wifi_coex_unsafe_channel ca_configs[MAX_CH_AVOID];
+ u32 mandatory;
+ int idx = 0;
+ memset(ca_configs, 0, MAX_CH_AVOID * sizeof(wifi_coex_unsafe_channel));
+
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ return;
+ }
+
+ if (!strncmp(param, "-unsafe", 7)) {
+ parse_unsafe(val_p, ca_configs, &idx);
+ } else if (!strncmp(param, "-m", 2)) {
+ mandatory = atoi(val_p);
+ }
+ }
+
+ for (int i=0; i<idx; i++) {
+ printMsg("CONFIG %d %d %d\n",
+ ca_configs[i].band, ca_configs[i].channel, ca_configs[i].power_cap_dbm);
+ }
+
+ setChannelAvoidance(idx, ca_configs, mandatory);
+ return;
+}
+
+void
+bandstr_to_wlan_mac_band(char *band_str, u32 *band)
+{
+ if (!strcasecmp(band_str, "2g")) {
+ *band = WLAN_MAC_2_4_BAND;
+ } else if (!strcasecmp(band_str, "5g")) {
+ *band = WLAN_MAC_5_0_BAND;
+ } else if (!strcasecmp(band_str, "6g")) {
+ *band = WLAN_MAC_6_0_BAND;
+ }
+}
+
+void
+ifacestr_to_wifi_interface_mode(char *iface_str, u8 *mode)
+{
+ if (!strcasecmp(iface_str, "sta")) {
+ *mode = WIFI_INTERFACE_STA;
+ } else if (!strcasecmp(iface_str, "softap")) {
+ *mode = WIFI_INTERFACE_SOFTAP;
+ } else if (!strcasecmp(iface_str, "ibss")) {
+ *mode = WIFI_INTERFACE_IBSS;
+ } else if (!strcasecmp(iface_str, "p2p_cli")) {
+ *mode = WIFI_INTERFACE_P2P_CLIENT;
+ } else if (!strcasecmp(iface_str, "p2p_go")) {
+ *mode = WIFI_INTERFACE_P2P_GO;
+ } else if (!strcasecmp(iface_str, "nan")) {
+ *mode = WIFI_INTERFACE_NAN;
+ } else if (!strcasecmp(iface_str, "mesh")) {
+ *mode = WIFI_INTERFACE_MESH;
+ } else if (!strcasecmp(iface_str, "tdls")) {
+ *mode = WIFI_INTERFACE_TDLS;
+ } else {
+ printMsg("Incorrect iface type."
+ " ex: sta/softap/ibss/p2p_cli/p2p_go/nan/mesh/tdls\n");
+ *mode = WIFI_INTERFACE_UNKNOWN;
+ }
+}
+
+u32 usable_channel_parse_band(char *val_p)
+{
+ char *delim_end;
+ char *delim = strtok_r(val_p, ",", &delim_end);
+ u32 band;
+ u32 band_mask = 0;
+ while (delim != NULL) {
+ band = 0;
+ bandstr_to_wlan_mac_band(delim, &band);
+ if (band) {
+ band_mask |= band;
+ }
+ delim = strtok_r(NULL, ",", &delim_end);
+ }
+ return band_mask;
+}
+
+u32 usable_channel_parse_iface(char *val_p)
+{
+ char *delim_end;
+ char *delim = strtok_r(val_p, ",", &delim_end);
+ u8 iface_mode;
+ u32 iface_mode_mask = 0;
+ while (delim != NULL) {
+ iface_mode = 0;
+ ifacestr_to_wifi_interface_mode(delim, &iface_mode);
+ if (iface_mode != WIFI_INTERFACE_UNKNOWN) {
+ iface_mode_mask |= (1 << iface_mode);
+ delim = strtok_r(NULL, ",", &delim_end);
+ }
+ }
+ return iface_mode_mask;
+}
+
+static wifi_error testUsableChannelOptions(int argc, char *argv[])
+{
+ char *param;
+ char *val_p;
+ u32 band_mask;
+ u32 iface_mode_mask;
+ u32 filter_mask;
+ u32 max_size = 0;
+ u32 size;
+ wifi_error ret;
+ wifi_usable_channel* channels = NULL;
+
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (!strncmp(param, "-b", 2)) {
+ band_mask = usable_channel_parse_band(val_p);
+ } else if (!strncmp(param, "-i", 2)) {
+ iface_mode_mask = usable_channel_parse_iface(val_p);
+ } else if (!strncmp(param, "-f", 2)) {
+ filter_mask = atoi(val_p);
+ } else if (!strncmp(param, "-m", 2)) {
+ max_size = atoi(val_p);
+ }
+ }
+
+ printMsg("Usable channel param BAND:%d IFACE:%d FILTER:%d MAX_SIZE:%d\n", band_mask, iface_mode_mask, filter_mask, max_size);
+ if (max_size == 0) {
+ printMsg("Max size should be bigger than 0\n");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ if (band_mask == 0) {
+ printMsg("Band mask should be bigger than 0\n");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ channels = (wifi_usable_channel *)malloc(sizeof(wifi_usable_channel) * max_size);
+ if (!channels) {
+ printMsg("Failed to alloc channels\n");
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(channels, 0, sizeof(wifi_usable_channel) * max_size);
+
+ printMsg("Call wifi_get_usable_channels\n");
+ ret = hal_fn.wifi_get_usable_channels(halHandle, band_mask, iface_mode_mask, filter_mask, max_size, &size, channels);
+ if (ret == WIFI_SUCCESS) {
+ printMsg("Usable channel success: size:%d max_size:%d\n", size, max_size);
+
+ for (unsigned int i=0; i < size; i++) {
+ printMsg("[%d] freq=%d, width=%d(%s), iface=%d ",
+ i+1, channels[i].freq, channels[i].width,
+ RBchanWidthToString(channels[i].width), channels[i].iface_mode_mask);
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_STA)) {
+ printMsg("STA ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_SOFTAP)) {
+ printMsg("SOFTAP ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_IBSS)) {
+ printMsg("IBSS ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_P2P_CLIENT)) {
+ printMsg("P2P_CLI ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_P2P_GO)) {
+ printMsg("P2P_GO ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_NAN)) {
+ printMsg("NAN ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_MESH)) {
+ printMsg("MESH ");
+ }
+ if (channels[i].iface_mode_mask & (1 << WIFI_INTERFACE_TDLS)) {
+ printMsg("TDLS ");
+ }
+ printMsg("\n");
+ }
+ } else {
+ printMsg("Failed to get usable channels\n");
+ }
+
+ free(channels);
+
+ return ret;
+}
+
+void testTxPowerLimitOptions(int argc, char *argv[])
+{
+ void printUsage(); // declaration for below printUsage()
+ wifi_error res;
+
+ if (argc < 2) {
+ goto usage;
+ }
+
+ if ((strcmp(argv[1], "-enable") == 0)) {
+ res = hal_fn.wifi_enable_tx_power_limits(wlan0Handle, true);
+ } else if ((strcmp(argv[1], "-disable") == 0)) {
+ res = hal_fn.wifi_enable_tx_power_limits(wlan0Handle, false);
+ } else {
+ goto usage;
+ }
+
+ if (res == WIFI_SUCCESS) {
+ printMsg("Success to execute tx power limit command\n");
+ } else {
+ printMsg("Failed to execute tx power limit command, res = %d\n", res);
+ }
+ return;
+
+usage:
+ printUsage();
+ return;
+}
+
+void printUsage() {
+ printf("Usage: halutil [OPTION]\n");
+ printf(" -v print version\n");
+ printf(" -s start AP scan test\n");
+ printf(" -swc start Significant Wifi change test\n");
+ printf(" -h start Hotlist APs scan test\n");
+ printf(" -ss stop scan test\n");
+ printf(" -max_ap Max AP for scan \n");
+ printf(" -base_period Base period for scan \n");
+ printf(" -threshold Threshold scan test\n");
+ printf(" -avg_RSSI samples for averaging RSSI\n");
+ printf(" -ap_loss samples to confirm AP loss\n");
+ printf(" -ap_breach APs breaching threshold\n");
+ printf(" -ch_threshold Change in threshold\n");
+ printf(" -wt_event Waiting event for test\n");
+ printf(" -low_th Low threshold for hotlist APs\n");
+ printf(" -hight_th High threshold for hotlist APs\n");
+ printf(" -hotlist_bssids BSSIDs for hotlist test\n");
+ printf(" -stats print link layer statistics\n");
+ printf(" -get_ch_list <a/bg/abg/a_nodfs/abg_nodfs/dfs/"
+ "6g/a6g_nodfs/all_nodfs/all> Get channel list\n");
+ printf(" -get_feature_set Get Feature set\n");
+ printf(" -get_feature_matrix Get concurrent feature matrix\n");
+ printf(" -get_wake_stats print wake reason statistics\n");
+ printf(" -rtt [-get_ch_list <a/bg/abg/a_nodfs/abg_nodfs/dfs/"
+ "6g/a6g_nodfs/all_nodfs/all>] [-i <burst_period of 100ms unit> [0 - 31] ]"
+ " [-n <exponents of 2 = (num_bursts)> [0 - 15]]\n"
+ " [-f <num_frames_per_burst>] [-r <num_retries_per_ftm>]\n"
+ " [-m <num_retries_per_ftmr>] [-b <burst_duration [2-11 or 15]>]"
+ " [-max_ap <count of allowed max AP>] [-l <file to read>] [-o <file to be stored>]\n");
+ printf(" -cancel_rtt cancel current RTT process\n");
+ printf(" -enable_resp enables the responder\n");
+ printf(" -cancel_resp cancel the responder\n");
+ printf(" -get_responder_info return the responder info\n");
+ printf(" -rtt -sta/-nan <peer mac addr> <channel> [ <bandwidth> [0 - 2]] <is_6g>"
+ " bandwidth - 0 for 20, 1 for 40 , 2 for 80 . is_6g = 1 if channel is 6G\n");
+ printf(" -get_capa_rtt Get the capability of RTT such as 11mc");
+ printf(" -scan_mac_oui XY:AB:CD\n");
+ printf(" -nodfs <0|1> Turn OFF/ON non-DFS locales\n");
+ printf(" -country <alpha2 country code> Set country\n");
+ printf(" -ePNO Configure ePNO SSIDs\n");
+ printf(" -blacklist_bssids blacklist bssids\n");
+ printf(" -whitelist_ssids set whitelist ssids\n"
+ " -whitelist_ssids ssid1 ssid2 ...\n");
+ printf(" -get_roaming_capabilities get roaming capabilities\n");
+ printf(" -set_fw_roaming_state set FW roaming state\n");
+ printf(" -logger [-start] [-d <debug_level> -f <flags> -i <max_interval_sec>\n"
+ " -s <min_data_size> -n <ring_name>]\n"
+ " [pktmonitor]\n"
+ " [-get] [fw] [driver] [feature] [memdump -o <filename>]\n"
+ " [ringstatus] [ringdata -n <ring_name>]\n"
+ " [txfate -n <no of pkts> -f <filename>]\n"
+ " [rxfate -n <no of pkts> -f <filename>]\n"
+ " [-set] [loghandler] [alerthandler]\n");
+ printf(" -rssi_monitor enable/disable\n");
+ printf(" -max_rssi max rssi threshold for RSSI monitor\n");
+ printf(" -min_rssi min rssi threshold for RSSI monitor\n");
+ printf(" -mkeep_alive [-start] <index (1 to 3)> <period_msec> <src_mac> <dst_mac> <ether_type>"
+ "[IP packet contents by Hexa format string]\n");
+ printf(" [-stop] <index (1 to 3)>\n");
+ printf(" e.g., -mkeep_alive -start 1 20000 000f66f45b7e 0014a54b164f 0800 4500001e0000400040"
+ "11c52a0a8830700a88302513c413c4000a00000a0d\n");
+ printf(" -nd_offload <0|1> enable/disable ND offload feature\n"
+ " enable also triggers IPv6 address update\n");
+ printf(" -latency_mode set latency mode WIFI_LATENCY_MODE_NORMAL/WIFI_LATENCY_MODE_LOW on particular interface\n"
+ " -latency_mode <interface_name> <low/normal/ultra-low mode>\n");
+ printf(" -sar enable <wifi_power_scenario -1 to 99>\n");
+ printf(" -sar disable\n");
+ printf(" -thermal <mode (none/light/moderate/severe/critical/emergency)>\n");
+ printf(" -nan [-enable] [-master_pref <master pref (2 to 254)>]\n"
+ " [-clus_id <cluster ID (50:6F:9A:01:XX:XX)]>\n"
+ " [-cluster_low <0 to 0xffff> -cluster_high <0 to 0xffff>\n"
+ " [-nan_addr <nan interface mac address(XX:XX:XX:XX:XX:XX)]>\n"
+ " [-dual_band <0/1>]\n"
+ " [-24g_chan <2.4GHz channel in MHz >]\n"
+ " [-5g_chan <5GHz channel in MHz >]\n"
+ " [-hc_limit <hop count limit>]\n"
+ " [-warmup_time <warm up time>] [-disc_ind_cfg <0 to 7>]\n"
+ " [-random_factor <random factor value>]\n"
+ " [-rssi_close_2dot4g_val <value>] [-rssi_middle_2dot4g_val <value>]\n"
+ " [-rssi_proximity_2dot4g_val <value>] [-support_2dot4g_val <0/1>]\n"
+ " [-beacon_2dot4g_val <0/1>] [-sdf_2dot4g_val <0/1>]\n"
+ " [-beacon_5g_val <0/1>] [-sdf_5g_val <0/1>] [-rssi_close_5g_val <RSSI value>]\n"
+ " [-rssi_middle_5g_val <RSSI value>] [-rssi_close_proximity_5g_val <RSSI value>]\n"
+ " [-rssi_window_size_val <value>] [-config_cluster_attribute_val <0/1>]\n"
+ " [-dwell_time <value in ms>] [-scan_period <value>] [-sid_flag <0/1>] [-sid_count <1 to 127>]\n"
+ " [-sub_sid_flag <0/1>] [-sub_sid_count <1 to 127>]\n"
+ " [-dwell_time_5g <value in ms>] [-scan_period_5g <value>]\n"
+ " [-awake_dw_2g <value> -awake_dw_5g <value>]\n"
+ " [-instant_mode <0-disable, 1-enable>]\n"
+ " [-instant_chan <2.4/5GHz channel in MHz >]\n");
+ printf(" -nan [-disable]\n");
+ printf(" -nan [-config] [-sid_flag <0/1>]\n"
+ " [-sid_count <1 to 127>]\n"
+ " [-sub_sid_flag <0/1>] [-sub_sid_count <1 to 127>]\n"
+ " [-rssi_proximity <rssi_proximity value>]\n"
+ " [-numchans <No of channels> -entry_control <Availability interval duration>]\n"
+ " [-channel <Channel value in MHz> -avail_interval_bitmap <u32 value>]\n"
+ " [-master_pref <master_pref>]\n"
+ " [-rssi_close_prox_5g <rssi_close_prox_5g value>]\n"
+ " [-rssi_window_size_val <rssi_window_size_val>]\n"
+ " [-dwell_time <dwell_time value in ms>\n"
+ " [-scan_period <scan_period value>]\n"
+ " [-dwell_time_5g <value in ms>] [-scan_period_5g <value>]\n"
+ " [-random_factor <random_factor value>]\n"
+ " [-hc_limit <hc_limit>] [-disc_ind_cfg <0 to 7>]\n"
+ " [-awake_dw_2g <value> -awake_dw_5g <value>]\n"
+ " [-instant_mode <0-disable, 1-enable>]\n"
+ " [-instant_chan <2.4/5GHz channel in MHz >]\n");
+ printf(" -nan [-publish] [-svc <svc_name>] [-info <svc info>\n"
+ " [-pub_type <0/1/2>] [-pub_count <val>] [-rssi_thresh_flag <0/1>]\n"
+ " [-tx_type <0/1>] [-ttl <val>] [-svc_awake_dw <val>] [-match_ind <0/1/2>]\n"
+ " [-match_rx <0/ascii str>] [-match_tx <0/ascii str>] [-passphrase <Passphrase value, len must not be less than 8 or greater than 63>]\n"
+ " [-recv_flag <0 to 15>] [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>] [-pmk <PMK value>]\n"
+ " [-scid <scid value>] [-dp_type <0-Unicast, 1-multicast>]\n"
+ " [-secure_dp <0-No security, 1-Security>] [-ranging <0-disable, 1-enable>)]\n"
+ " [-ranging_intvl [intrvl in ms betw two ranging measurements] -ranging_ind \n"
+ " [BIT0 - Continuous Ranging event notification, BIT1 - Ingress distance is <=, BIT2 - Egress distance is >=.]\n"
+ " [-ingress [Ingress distance in centimeters] \n"
+ " [ -egress [Egress distance in centimeters] \n"
+ " [-auto_dp_accept [0 - User response required to accept dp, 1 - User response not required to accept dp] \n");
+ printf(" -nan [-subscribe] [-svc <svc_name>] [-info <svc info>\n"
+ " [-sub_type <0/1>] [-sub_count <val>] [-pub_ssi <0/1>]\n"
+ " [-ttl <val>] [-svc_awake_dw <val>] [-match_ind <0/1/2>]\n"
+ " [-match_rx <0/ascii str>] [-match_tx <0/ascii str>]\n"
+ " [-mac_list <addr>] [-srf_use <0/1>] [-rssi_thresh_flag <0/1>]]\n"
+ " [-srf_include <0/1>] [-srf_type <0/1>] [-recv_flag <0 to 7>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>]\n"
+ " [-scid <scid value>] [-dp_type <0-Unicast,1-multicast>]\n"
+ " [-secure_dp <0-No security, 1-Security>] [-ranging <0-disable, 1-enable>)]\n"
+ " [-ranging_intvl [intrvl in ms betw two ranging measurements] -ranging_ind \n"
+ " [BIT0 - Continuous Ranging event notification, BIT1 - Ingress distance is <=, BIT2 - Egress distance is >=.]\n"
+ " [-ingress [Ingress distance in centimeters] \n"
+ " [ -egress [Egress distance in centimeters] \n");
+ printf(" -nan [-cancel_pub <publish id>]\n");
+ printf(" -nan [-cancel_sub <subscribe id>\n");
+ printf(" -nan [-transmit] [-src_id <instance id>] [-dest_id <instance id>]\n"
+ " [-peer_addr <mac addr>] [-info <svc info>] \n"
+ " [-recv_flag <1-Disable followUp response, 0-Enable followup response from FW>]\n");
+ printf(" -nan [-get_capabilities]\n");
+ printf("\n ****** Nan Data Path Commands ***** \n");
+ printf(" -nan [-create] [-iface <iface name>]\n");
+ printf(" -nan [-delete] [-iface <iface name>]\n");
+ printf(" -nan [-init] [-pub_id <pub id>] [-disc_mac <discovery mac addr>]\n"
+ " [-chan_req_type <NAN DP channel config options>]\n"
+ " [-chan <channel in mhz>] [-iface <iface>] [-sec <security>] [-key_type <1 or 2>\n"
+ " [-qos <qos>] [-info <seq of values in the frame body>] [-passphrase <Passphrase value, len must not be less than 8 or greater than 63>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>] [-pmk <PMK value>] [-svc <svc_name>]\n");
+ printf(" -nan [-resp] [-ndp_id <NDP id>] [-iface <NDP iface name>]\n"
+ " [-resp_code <accept = 0, reject = 1>] [-qos <qos>] [-key_type <1 or 2>] \n"
+ " [-info <seq of values in the frame body>] [-passphrase <Passphrase value, len must not be less than 8 or greater than 63>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>] [-pmk <PMK value>] [-svc <svc_name>]\n");
+ printf(" -nan [-end] [-inst_count <count>] [-inst_id <NDP id>\n");
+ printf(" -nan [-up] [-iface <iface name>] [-ip <ip>]\n");
+ printf(" -nan [-addr]\n");
+ printf(" -nan [-event_chk]\n");
+ printf(" -nan [-ver]\n");
+ printf(" -nan [-exit]\n");
+ printf(" -dscp [-set] [-s <start>] [-e <end>] [-ac <access_category>]\n");
+ printf(" -dscp [-reset] \n");
+ printf(" -ch_avoid [-unsafe <band type, a,b>,<channel number>,<power capacity, maximum output for the channel in dBm>]\n"
+ " -unsafe can be used multiple times\n"
+ " b for BAND_24GHZ\n"
+ " a for BAND_5GHZ\n"
+ " [-m <mandatory flag as decimal>]\n"
+ " 1 << 0 for FLAG_UNSPECIFIED \n"
+ " 1 << 1 for FLAG_WIFI_DIRECT\n"
+ " 1 << 2 for FLAG_SOFTAP\n"
+ " 1 << 4 for FLAG_WIFI_AWARE\n");
+ printf(" -usable_ch [-b <band_mask>], [-i <iface_mask>], [-f <filter_mask>], [-m <max_size of channel>]\n"
+ " [-b 2g,5g,6g]\n"
+ " [-i sta,nan,softap,p2p_go,p2p_cli]\n");
+ printf("-ifadd -name <virtual iface name to be created>"
+ " -type <0 for STA, 1 for AP, 2 for P2P, 3 for NAN>\n");
+ printf("-ifdel -name <virtual iface name to be deleted>\n");
+ printf(" -voip_mode <interface_name> <0|1> voip mode off/on on particular interface\n");
+ printf(" -dtim_multiplier <dtim count> Set suspend bcn_li_dtim.\n");
+ printf(" -on_ssr cmd to trigger sub system restart.\n");
+ printf(" -getSupportedRadioMatrix cmd to get the supported radio combo matrix.\n");
+ printf(" -get_cached_scan_results cmd to get the cached scan results.\n");
+ printf(" -set_channel_mask <value> [1 for indoor channel, 2 for DFS channel]\n");
+ printTwtUsage();
+ printTxPowerUsage();
+ printChreNanRttUsage();
+}
+
+/* Generic function to copy Iface_name/Ip/App specific Info to the buffer */
+static int set_interface_params(char *p_info, char *val_p, int len) {
+ void *p;
+ p = strncpy(p_info, val_p, len);
+ if (p_info[len - 1] == '\n') {
+ p_info[len - 1] = '\0';
+ }
+ if (!p) {
+ printMsg("Error\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ printMsg("Info/Iface/Ip = \"%s\"\n", (char*)p);
+ return WIFI_SUCCESS;
+}
+
+void OnNanNotifyResponse(transaction_id id, NanResponseMsg* rsp_data) {
+ if(rsp_data) {
+ switch(rsp_data->response_type) {
+ case NAN_RESPONSE_ENABLED:
+ printMsg("Nan Enable Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_RESPONSE_DISABLED:
+ printMsg("Nan Disable Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_RESPONSE_CONFIG:
+ printMsg("Nan Config Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_RESPONSE_PUBLISH:
+ printMsg("Nan Publish Response Received, Publish ID "
+ "= %d, status = %d\n",
+ rsp_data->body.publish_response.publish_id, rsp_data->status);
+ break;
+ case NAN_RESPONSE_SUBSCRIBE:
+ printMsg("Nan Subscribe Response Received, Subscribe ID "
+ "= %d, status = %d\n",
+ rsp_data->body.subscribe_response.subscribe_id, rsp_data->status);
+ break;
+ case NAN_RESPONSE_PUBLISH_CANCEL:
+ printMsg("Nan Cancel Publish Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_RESPONSE_SUBSCRIBE_CANCEL:
+ printMsg("Nan Cancel Subscribe Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_RESPONSE_TRANSMIT_FOLLOWUP:
+ printMsg("Transmit followup response received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_DP_INTERFACE_CREATE:
+ printMsg("ndp iface create response received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_DP_INTERFACE_DELETE:
+ printMsg("ndp iface delete response received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_DP_INITIATOR_RESPONSE:
+ printMsg("ndp response received, ndp_instance_id = %d, status = %d\n",
+ rsp_data->body.data_request_response.ndp_instance_id, rsp_data->status);
+ break;
+ case NAN_DP_RESPONDER_RESPONSE:
+ printMsg("Nan Data Path Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_DP_END:
+ printMsg("Nan Data Path End Response Received, status = %d\n", rsp_data->status);
+ break;
+ case NAN_GET_CAPABILITIES:
+ printMsg("Nan Get Capabilities Response Received, status = %d\n", rsp_data->status);
+ printMsg("max_concurrent_nan_clusters = %d\n",
+ rsp_data->body.nan_capabilities.max_concurrent_nan_clusters);
+ printMsg("max_publishes = %d\n",
+ rsp_data->body.nan_capabilities.max_publishes);
+ printMsg("max_subscribes = %d\n",
+ rsp_data->body.nan_capabilities.max_subscribes);
+ printMsg("max_service_name_len = %d\n",
+ rsp_data->body.nan_capabilities.max_service_name_len);
+ printMsg("max_match_filter_len = %d\n",
+ rsp_data->body.nan_capabilities.max_match_filter_len);
+ printMsg("max_total_match_filter_len = %d\n",
+ rsp_data->body.nan_capabilities.max_total_match_filter_len);
+ printMsg("max_service_specific_info_len = %d\n",
+ rsp_data->body.nan_capabilities.max_service_specific_info_len);
+ printMsg("max_ndi_interfaces = %d\n",
+ rsp_data->body.nan_capabilities.max_ndi_interfaces);
+ printMsg("max_ndp_sessions = %d\n",
+ rsp_data->body.nan_capabilities.max_ndp_sessions);
+ printMsg("max_app_info_len = %d\n",
+ rsp_data->body.nan_capabilities.max_app_info_len);
+ printMsg("max_queued_transmit_followup_msgs = %d\n",
+ rsp_data->body.nan_capabilities.max_queued_transmit_followup_msgs);
+ printMsg("max_Subscribe_Interface_Addresses = %d\n",
+ rsp_data->body.nan_capabilities.max_subscribe_address);
+ printMsg("supported_CipherSuites = %d\n",
+ rsp_data->body.nan_capabilities.cipher_suites_supported);
+ printMsg("max_Extended_ServiceSpecific_Info_Len = %d\n",
+ rsp_data->body.nan_capabilities.max_sdea_service_specific_info_len);
+ printMsg("ndpe_attr_supported = %d\n",
+ rsp_data->body.nan_capabilities.ndpe_attr_supported);
+ break;
+ default:
+ printMsg("Unknown Response Received, %d\n",
+ rsp_data->response_type);
+ }
+ }
+ return;
+}
+void OnNanEventPublishTerminated(NanPublishTerminatedInd* event) {
+ char msg_buf[MAX_NAN_MSG_BUF_SIZE] = {'\0'};
+ printMsg("\n NanPublishTerminated\n");
+ snprintf(msg_buf, MAX_NAN_MSG_BUF_SIZE,
+ "NanPublishTerminated: id %u, reason %u\n",
+ event->publish_id, event->reason);
+ printMsg("Publish Terminated: nan_reason = %s\n", event->nan_reason);
+ putEventInCache(EVENT_TYPE_NAN_PUBLISH_TERMINATED, msg_buf);
+}
+void OnNanEventMatch (NanMatchInd* event) {
+ printMsg("\n Subscriber id = %d\n", event->publish_subscribe_id);
+ printMsg("Publisher Id = %d\n", event->requestor_instance_id);
+ printMsg("Subscribe Match found: Publisher Device Addr( " MACSTR " )\n",
+ MAC2STR(event->addr));
+ if (event->service_specific_info_len) {
+ printMsg("svc info len = %d and svc info = %s\n",
+ event->service_specific_info_len,
+ event->service_specific_info);
+ }
+ if(event->sdf_match_filter_len) {
+ printMsg("sdf match filter len = %d and sdf_match_filter = %s\n",
+ event->sdf_match_filter_len,
+ event->sdf_match_filter);
+ }
+ printMsg("Match occurred flag = %d\n", event->match_occured_flag);
+ printMsg("Out of resource flag = %d\n", event->out_of_resource_flag);
+ printMsg("rssi value = %d\n", event->rssi_value);
+ printMsg("Peer cipher suite type = %d\n", event->peer_cipher_type);
+ if (event->scid_len) {
+ printMsg("scid len = %d and scid = %s\n",
+ event->scid_len, event->scid);
+ }
+ /* Peer sdea params */
+ printMsg("Peer config for data path needed %d\n", event->peer_sdea_params.config_nan_data_path);
+ printMsg("Data Path type %d\n", event->peer_sdea_params.ndp_type);
+ printMsg("Security configuration %d\n", event->peer_sdea_params.security_cfg);
+ printMsg("Ranging report state %d\n", event->peer_sdea_params.range_report);
+
+ printMsg("Distance to the device: %d mm\n", event->range_info.range_measurement_mm);
+ printMsg("Ranging event type: %d\n", event->range_info.ranging_event_type);
+
+ if (event->sdea_service_specific_info_len) {
+ printMsg("sdea svc info len = %d and sdea svc info = %s\n",
+ event->sdea_service_specific_info_len,
+ event->sdea_service_specific_info);
+ }
+ /* Event enabled is not available in android-m */
+ putEventInCache(EVENT_TYPE_SUBSCRIBE_MATCHED,
+ "SubscribeMatched");
+}
+void OnNanEventMatchExpired (NanMatchExpiredInd* event) {
+ printMsg("NanMatchExpired between publish_subscribe_id = %u "
+ "and peer_instance_id = %u\n",
+ event->publish_subscribe_id, event->requestor_instance_id);
+}
+void OnNanEventSubscribeTerminated (NanSubscribeTerminatedInd* event) {
+ char msg_buf[MAX_NAN_MSG_BUF_SIZE] = {'\0'};
+ printMsg("\n NanSubscribeTerminated\n");
+ snprintf(msg_buf, MAX_NAN_MSG_BUF_SIZE,
+ "NanSubscribeTerminated: id %u, reason %u\n",
+ event->subscribe_id, event->reason);
+ printMsg("Subscribe Terminated: nan_reason = %s\n", event->nan_reason);
+ putEventInCache(EVENT_TYPE_NAN_SUBSCRIBE_TERMINATED, msg_buf);
+}
+void OnNanEventFollowup (NanFollowupInd* event) {
+ printMsg("\n Instance id= %u\n",
+ event->publish_subscribe_id);
+ printMsg("Peer instance id = %u\n",
+ event->requestor_instance_id);
+ printMsg("Transmit Followup Received in %s\n",
+ (event->dw_or_faw)? "FAW":"DW");
+ printMsg("peer addr (" MACSTR ")\n", MAC2STR(event->addr));
+ if (event->service_specific_info_len) {
+ printMsg("followup svc_info len = %d and info = %s\n",
+ event->service_specific_info_len,event->service_specific_info);
+ }
+ if (event->sdea_service_specific_info_len) {
+ printMsg("sdea svc info len = %d and sdea svc info = %s\n",
+ event->sdea_service_specific_info_len,
+ event->sdea_service_specific_info);
+ }
+
+ putEventInCache(EVENT_TYPE_NAN_FOLLOWUP_RECIEVE,
+ "NanFollowupReceived");
+}
+void OnNanTransmitFollowupInd (NanTransmitFollowupInd* event) {
+ printMsg("\n Transaction id = %u\n",
+ event->id);
+ printMsg("Transmit Followup Status = %u\n",
+ event->reason);
+ printMsg("Nan Transmit Followup Ind: nan_reason = %s\n", event->nan_reason);
+ putEventInCache(EVENT_TYPE_NAN_TRANSMIT_FOLLOWUP_INDICATION,
+ "NanTransmitFollowupInd");
+}
+
+void OnNanPublishRepliedInd (NanPublishRepliedInd* event) {
+ printMsg("\n Requestor Instance Id/Subscriber Id = %d\n", event->requestor_instance_id);
+ printMsg("Subscriber found: Device( " MACSTR " )\n",
+ MAC2STR(event->addr));
+ printMsg("rssi value = %d\n", event->rssi_value);
+}
+
+void OnNanEventDiscEngEvent (NanDiscEngEventInd* event) {
+ if (event->event_type == NAN_EVENT_ID_DISC_MAC_ADDR) {
+ printMsg("\n DE Event Received, Nan Disc Mac Addr Creation Event\n");
+ printMsg("NMI Mac address (" MACSTR ")\n",
+ MAC2STR(event->data.mac_addr.addr));
+ } else if (event->event_type == NAN_EVENT_ID_STARTED_CLUSTER) {
+ printMsg("DE Event Received, Nan Cluster Started \n");
+ } else if (event->event_type == NAN_EVENT_ID_JOINED_CLUSTER) {
+ printMsg("DE Event Received, Nan Cluster Joined \n");
+ printMsg("Joined cluster ID (" MACSTR ")\n",
+ MAC2STR(event->data.cluster.addr));
+ } else {
+ printMsg("Unknown DE Event Received, %d\n", event->event_type);
+ return;
+ }
+}
+void OnNanEventDisabled (NanDisabledInd* event) {
+ printMsg("\n Nan disabledInd received, reason = %u\n", event->reason);
+ printMsg("Nan Disabled Event: nan_reason = %s\n", event->nan_reason);
+}
+void OnNanEventTca (NanTCAInd* event) {}
+void OnNanEventBeaconSdfPayload (NanBeaconSdfPayloadInd* event) {}
+void OnNanEventDataIndication (NanDataPathRequestInd* event) {
+ printMsg("\n service id = %d\n", event->service_instance_id);
+ printMsg("Discovery MAC addr of the peer/initiator(" MACSTR ")\n",
+ MAC2STR(event->peer_disc_mac_addr));
+ printMsg("ndp id = %d\n", event->ndp_instance_id);
+ printMsg("qos = %d\n", event->ndp_cfg.qos_cfg);
+ printMsg("security = %d\n", event->ndp_cfg.security_cfg);
+ if (event->app_info.ndp_app_info_len) {
+ printMsg("service info = %s and its length = %d\n",
+ event->app_info.ndp_app_info,
+ event->app_info.ndp_app_info_len);
+ }
+ putEventInCache(EVENT_TYPE_NAN_DATA_REQUEST_INDICATION,
+ "NanDataEventIndication");
+}
+void OnNanEventDataConfirmation (NanDataPathConfirmInd* event) {
+ printMsg("\n ndp id = %d\n", event->ndp_instance_id);
+ printMsg("NDI mac address of the peer = (" MACSTR ")\n",
+ MAC2STR(event->peer_ndi_mac_addr));
+ if (event->app_info.ndp_app_info_len) {
+ printMsg("service info = %s and length = %d\n",
+ event->app_info.ndp_app_info,
+ event->app_info.ndp_app_info_len);
+ }
+ printMsg("Response code = %d\n", event->rsp_code);
+ switch (event->rsp_code) {
+ case NAN_DP_REQUEST_ACCEPT:
+ printMsg("Response code [%d]:NAN_DP_REQUEST_ACCEPT\n", event->rsp_code);
+ break;
+ case NAN_DP_REQUEST_REJECT:
+ printMsg("Response code [%d]:NAN_DP_REQUEST_REJECT\n", event->rsp_code);
+ printMsg("Reason code for rejection= %d\n", event->reason_code);
+ break;
+ default:
+ printMsg("Unknown response code = %d\n", event->rsp_code);
+ break;
+ }
+ putEventInCache(EVENT_TYPE_NAN_DATA_CONFIRMATION,
+ "NanDataConfirmation");
+}
+void OnNanEventDataPathEnd (NanDataPathEndInd* event) {
+ printMsg("\n ndp id count = %d\n", event->num_ndp_instances);
+ printMsg("ndp id = %d\n",
+ event->ndp_instance_id[event->num_ndp_instances -1]);
+ putEventInCache(EVENT_TYPE_NAN_DATA_END_INDICAION,
+ "NanDataEndIndication");
+}
+
+void OnNanRangeRequestInd (NanRangeRequestInd *event) {
+ printMsg("\n Received NanRangeRequestInd\n");
+}
+void OnNanRangeReportInd (NanRangeReportInd *event) {
+ printMsg("\n Received NanRangeReportInd\n");
+}
+void OnNanDataPathScheduleUpdateInd (NanDataPathScheduleUpdateInd *event) {
+ printMsg("\n Received NanDataPathScheduleUpdateInd\n");
+}
+
+wifi_error nan_init_handlers(void) {
+ wifi_error ret = WIFI_SUCCESS;
+ NanCallbackHandler handlers;
+ memset(&handlers, 0, sizeof(handlers));
+ handlers.NotifyResponse = OnNanNotifyResponse;
+ handlers.EventPublishTerminated = OnNanEventPublishTerminated;
+ handlers.EventMatch = OnNanEventMatch;
+ handlers.EventMatchExpired = OnNanEventMatchExpired;
+ handlers.EventSubscribeTerminated = OnNanEventSubscribeTerminated;
+ handlers.EventFollowup = OnNanEventFollowup;
+ handlers.EventDiscEngEvent = OnNanEventDiscEngEvent;
+ handlers.EventDisabled = OnNanEventDisabled;
+ handlers.EventTca = OnNanEventTca;
+ handlers.EventBeaconSdfPayload = OnNanEventBeaconSdfPayload;
+ handlers.EventDataRequest = OnNanEventDataIndication;
+ handlers.EventDataConfirm = OnNanEventDataConfirmation;
+ handlers.EventDataEnd = OnNanEventDataPathEnd;
+ handlers.EventTransmitFollowup = OnNanTransmitFollowupInd;
+ handlers.EventPublishReplied = OnNanPublishRepliedInd;
+ handlers.EventRangeRequest = OnNanRangeRequestInd;
+ handlers.EventRangeReport = OnNanRangeReportInd;
+ handlers.EventScheduleUpdate = OnNanDataPathScheduleUpdateInd;
+ ret = nan_register_handler(wlan0Handle , handlers);
+ printMsg("%s: ret = %d\n", __FUNCTION__, ret);
+ return ret;
+}
+
+static void OnTwtNotify(TwtDeviceNotify* event) {
+ if (event) {
+ printMsg("OnTwtNotify, notification = %d\n", event->notification);
+ }
+ return;
+}
+
+static void OnTwtSetupResponse(TwtSetupResponse* event) {
+ printMsg("\n OnTwtSetupResponse\n");
+ if (event) {
+ printMsg("config id = %d\n", event->config_id);
+ printMsg("status = %d\n", event->status);
+ printMsg("reason_code = %d\n", event->reason_code);
+ printMsg("negotiation_type = %d\n", event->negotiation_type);
+ printMsg("trigger_type = %d\n", event->trigger_type);
+ printMsg("wake_dur_us = %d\n", event->wake_dur_us);
+ printMsg("wake_int_us = %d\n", event->wake_int_us);
+ printMsg("wake_time_off_us = %d\n", event->wake_time_off_us);
+ }
+ return;
+}
+
+static void OnTwtTearDownCompletion(TwtTeardownCompletion* event) {
+ printMsg("\n OnTwtTearDownCompletion\n");
+ if (event) {
+ printMsg("config id = %d\n", event->config_id);
+ printMsg("status = %d\n", event->status);
+ printMsg("all twt = %d\n", event->all_twt);
+ printMsg("reason = %d\n", event->reason);
+ }
+ return;
+}
+
+static void OnTwtInfoFrameReceived(TwtInfoFrameReceived* event) {
+ printMsg("\n OnTwtInfoFrameReceived\n");
+ if (event) {
+ printMsg("config id = %d\n", event->config_id);
+ printMsg("status = %d\n", event->status);
+ printMsg("all twt = %d\n", event->all_twt);
+ printMsg("reason = %d\n", event->reason);
+ printMsg("twt_resumed = %d\n", event->twt_resumed);
+ }
+ return;
+}
+
+wifi_error twt_init_handlers(void) {
+ wifi_error ret = WIFI_SUCCESS;
+ TwtCallbackHandler handlers;
+ memset(&handlers, 0, sizeof(handlers));
+ handlers.EventTwtDeviceNotify = OnTwtNotify;
+ handlers.EventTwtSetupResponse = OnTwtSetupResponse;
+ handlers.EventTwtTeardownCompletion = OnTwtTearDownCompletion;
+ handlers.EventTwtInfoFrameReceived = OnTwtInfoFrameReceived;
+ ret = twt_register_handler(wlan0Handle , handlers);
+ printMsg("%s: ret = %d\n", __FUNCTION__, ret);
+ return ret;
+}
+
+/*
+ * Debug function to see the events reaching to HAL
+ * CTRL-C to exit the blocking command.
+ */
+void twtEventCheck(void) {
+ wifi_error ret = WIFI_SUCCESS;
+
+ ret = twt_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize twt handlers %d\n", ret);
+ return;
+ }
+
+ twtCmdId = getNewCmdId();
+ ret = twt_event_check_request(twtCmdId, wlan0Handle);
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to check the twt events: %d\n", ret);
+ return;
+ }
+
+ printMsg("CTRL-C to exit the thread.\n");
+ while (1)
+ {
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ printMsg("\n Retrieved event %d : %s\n\n", info.type, info.buf);
+ }
+}
+/*
+ * Debug function to see the events reaching to HAL
+ * CTRL-C to exit the blocking command.
+ */
+void nanEventCheck(void) {
+ wifi_error ret = WIFI_SUCCESS;
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ return;
+ }
+ nanCmdId = getNewCmdId();
+ nan_event_check_request(nanCmdId, wlan0Handle);
+ printMsg("CTRL-C to exit the thread.\n");
+ while (1)
+ {
+ EventInfo info;
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ printMsg("\n Retrieved event %d : %s\n\n", info.type, info.buf);
+ }
+}
+
+void nanVersion(void) {
+ NanVersion version = 0;
+ wifi_error err = WIFI_SUCCESS;
+ err = nan_get_version(0, &version);
+ if (err == WIFI_SUCCESS) {
+ printMsg("NAN VERSION is %d\n", version);
+ } else {
+ printMsg("Nan Version Command Failed, err = %d\n", err);
+ }
+}
+
+void set_cluster_id(char *clus_id, NanEnableRequest *msg) {
+ u8 addr[NAN_MAC_ADDR_LEN]; /* cluster id */
+ if (!clus_id || (!ether_atoe(clus_id, addr))) {
+ printMsg("bad cluster id !!\n");
+ } else {
+ msg->cluster_high = ((addr[4] << 8) | addr[5]);
+ msg->cluster_low = msg->cluster_high;
+ printMsg("cluster low: %x, cluster high: %x\n", msg->cluster_low, msg->cluster_high);
+ }
+ return;
+}
+
+int
+get_oui_bytes(u8 *oui_str, u8 *oui)
+{
+ int idx;
+ u8 val;
+ u8 *src, *dest;
+ char hexstr[3];
+ char* endptr = NULL;
+
+ src = oui_str;
+ dest = oui;
+
+ for (idx = 0; idx < 3; idx++) {
+ hexstr[0] = src[0];
+ hexstr[1] = src[1];
+ hexstr[2] = '\0';
+ val = (u8) strtoul(hexstr, &endptr, 16);
+ *dest++ = val;
+ src += 2;
+ if (((idx < (3 - 1)) && (*src++ != ':')) || (*endptr != '\0'))
+ return WIFI_ERROR_UNKNOWN;
+ }
+ return WIFI_SUCCESS;
+}
+
+void nanSetOui(char *nan_oui, char* nan_type, NanEnableRequest *msg) {
+ u8 type;
+ u32 value;
+ char* endptr;
+
+ if(!nan_type) {
+ printMsg("nan oui type is missing. Setting NAN OUI to default \n");
+ return;
+ }
+
+ if (get_oui_bytes((u8 *)nan_oui, (u8 *)&value)) {
+ printMsg("%s: Wrong OUI value. Setting Default OUI and type\n",__FUNCTION__);
+ msg->oui_val = 0;
+ return;
+ }
+
+ type = strtoul(nan_type, &endptr, 0);
+ if (*endptr != '\0') {
+ printMsg("%s:Wrong nan OUI type. Setting default OUI and type\n", __FUNCTION__);
+ msg->oui_val = 0;
+ return;
+ }
+ value = (value & 0xffffff) + (type << 24);
+ msg->config_oui = 1;
+ msg->oui_val = value;
+}
+
+void enableNan(char *argv[]) {
+ NanEnableRequest msg ;
+ wifi_error ret = WIFI_SUCCESS;
+ char *endptr, *param, *val_p;
+ int sid_flag = 0xff, sid_count = 0xff;
+ int sub_sid_flag = 0xff, sub_sid_count = 0xff;
+ u8 val;
+ u16 clust_range;
+
+ /* Set Default enable params */
+ memset(&msg, 0, sizeof(msg));
+ msg.hop_count_limit_val = 5;
+ msg.config_2dot4g_support = FEATURE_SUPPORTED;
+ msg.support_2dot4g_val = FEATURE_SUPPORTED;
+ msg.config_2dot4g_beacons = FEATURE_SUPPORTED;
+ msg.beacon_2dot4g_val = FEATURE_SUPPORTED;
+ msg.config_2dot4g_sdf = FEATURE_SUPPORTED;
+ msg.sdf_2dot4g_val = FEATURE_SUPPORTED;
+ msg.config_disc_mac_addr_randomization = true;
+ msg.disc_mac_addr_rand_interval_sec = 0;
+ msg.config_ndpe_attr = false;
+ msg.cluster_low = 0;
+ msg.cluster_high = NAN_MAX_CLUST_VALUE_RANGE;
+
+ /* Parse args for nan params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-clus_id") == 0) {
+ set_cluster_id(val_p, &msg);
+ } else if (strcmp(param, "-cluster_low") == 0) {
+ clust_range = atoi(val_p);
+ if (clust_range < 0 || clust_range > NAN_MAX_CLUST_VALUE_RANGE) {
+ msg.cluster_low = 0;
+ }
+ msg.cluster_low = clust_range;
+ } else if (strcmp(param, "-cluster_high") == 0) {
+ clust_range = atoi(val_p);
+ if (clust_range < 0 || clust_range > NAN_MAX_CLUST_VALUE_RANGE) {
+ msg.cluster_high = NAN_MAX_CLUST_VALUE_RANGE;
+ }
+ msg.cluster_high = clust_range;
+ } else if (strcmp(param, "-master_pref") == 0) {
+ msg.master_pref = strtoul(val_p, &endptr, 0);
+ if (*endptr != '\0' || (msg.master_pref < 2 || msg.master_pref > 254)) {
+ printMsg("%s:Invalid Master Preference.Setting it to Random\n", __FUNCTION__);
+ msg.master_pref = 0;
+ }
+ } else if (strcmp(param, "-dual_band") == 0) {
+ msg.support_5g_val = strtoul(val_p, &endptr, 0);
+ if (*endptr != '\0' || msg.support_5g_val > 1) {
+ printMsg("%s:Invalid Dual Band Value.\n", __FUNCTION__);
+ msg.config_support_5g = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.config_support_5g = true;
+ }
+ } else if (strcmp(param, "-hc_limit") == 0) {
+ msg.hop_count_limit_val = strtoul(val_p, &endptr, 0);
+ if (*endptr != '\0') {
+ printMsg("%s:Invalid Hop Count Limit. Setting to Default\n", __FUNCTION__);
+ msg.config_hop_count_limit = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.config_hop_count_limit = true;
+ }
+ } else if (strcmp(param, "-oui") == 0) {
+ nanSetOui(val_p, *argv++, &msg);
+ } else if (strcmp(param, "-sid_flag") == 0) {
+ sid_flag = atoi(val_p);
+ if (sid_flag) {
+ msg.config_sid_beacon = true;
+ } else {
+ printMsg("%s:Invalid Service Id Flag. Setting to Default\n", __FUNCTION__);
+ msg.config_sid_beacon = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sid_count") == 0) {
+ sid_count = atoi(val_p);
+ if (sid_count < 0 || sid_count > NAN_MAX_SIDS_IN_BEACONS) {
+ printMsg("%s:Invalid Service ID Count Limit. Setting to Default\n", __FUNCTION__);
+ sid_count = 0;
+ } else {
+ msg.sid_beacon_val = ((sid_count << 1) | sid_flag);
+ }
+ } else if (strcmp(param, "-sub_sid_flag") == 0) {
+ sub_sid_flag = atoi(val_p);
+ if (sub_sid_flag) {
+ msg.config_subscribe_sid_beacon = true;
+ } else {
+ printMsg("%s:Invalid Subscribe Service Id Flag. Setting to Default\n", __FUNCTION__);
+ msg.config_subscribe_sid_beacon = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sub_sid_count") == 0) {
+ sub_sid_count = atoi(val_p);
+ if (sub_sid_count < 0 || sub_sid_count > NAN_MAX_SIDS_IN_BEACONS) {
+ printMsg("%s:Invalid Subscribe Service ID Count Limit. Setting to Default\n", __FUNCTION__);
+ sub_sid_count = 0;
+ } else {
+ msg.subscribe_sid_beacon_val = ((sub_sid_count << 1) | sub_sid_flag);
+ }
+ } else if (strcmp(param, "-rssi_close_2dot4g_val") == 0) {
+ msg.rssi_close_2dot4g_val = atoi(val_p);
+ if (msg.rssi_close_2dot4g_val) {
+ msg.config_2dot4g_rssi_close = true;
+ }
+ } else if (strcmp(param, "-rssi_middle_2dot4g_val") == 0) {
+ msg.rssi_middle_2dot4g_val = atoi(val_p);
+ if (msg.rssi_middle_2dot4g_val) {
+ msg.config_2dot4g_rssi_middle = true;
+ }
+ } else if (strcmp(param, "-rssi_proximity_2dot4g_val") == 0) {
+ msg.rssi_proximity_2dot4g_val = atoi(val_p);
+ if (msg.rssi_proximity_2dot4g_val) {
+ msg.config_2dot4g_rssi_proximity = true;
+ }
+ } else if (strcmp(param, "-support_2dot4g_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * Defines 2.4G channel access support
+ * 0 - No Support
+ * 1 - Supported
+ */
+ switch(val) {
+ case FEATURE_NOT_SUPPORTED:
+ msg.support_2dot4g_val = FEATURE_NOT_SUPPORTED;
+ break;
+ default:
+ msg.support_2dot4g_val = FEATURE_SUPPORTED;
+ break;
+ }
+ } else if (strcmp(param, "-beacon_2dot4g_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * Defines 2.4G channels will be used for sync/discovery beacons
+ * 0 - 2.4G channels not used for beacons
+ * 1 - 2.4G channels used for beacons
+ */
+ switch(val) {
+ case FEATURE_NOT_SUPPORTED:
+ msg.beacon_2dot4g_val = FEATURE_NOT_SUPPORTED;
+ break;
+ default:
+ msg.beacon_2dot4g_val = FEATURE_SUPPORTED;
+ break;
+ }
+ } else if (strcmp(param, "-sdf_2dot4g_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * Defines 2.4G channels will be used for Service Discovery frames
+ * 0 - 2.4G channels not used for Service Discovery frames
+ * 1 - 2.4G channels used for Service Discovery frames
+ */
+ switch(val) {
+ case FEATURE_NOT_SUPPORTED:
+ msg.sdf_2dot4g_val = FEATURE_NOT_SUPPORTED;
+ break;
+ default:
+ msg.sdf_2dot4g_val = FEATURE_SUPPORTED;
+ break;
+ }
+ } else if (strcmp(param, "-beacon_5g_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * Defines 5G channels will be used for sync/discovery beacons
+ * 0 - 5G channels not used for beacons
+ * 1 - 5G channels used for beacons
+ */
+ switch(val) {
+ case FEATURE_SUPPORTED:
+ msg.beacon_5g_val = FEATURE_SUPPORTED;
+ break;
+ default:
+ msg.beacon_5g_val = FEATURE_NOT_SUPPORTED;
+ break;
+ }
+ msg.config_5g_beacons = true;
+ } else if (strcmp(param, "-sdf_5g_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * Defines 5G channels will be used for Service Discovery frames
+ * 0 - 5G channels not used for Service Discovery frames
+ * 1 - 5G channels used for Service Discovery frames
+ */
+ switch(val) {
+ case FEATURE_SUPPORTED:
+ msg.sdf_5g_val = FEATURE_SUPPORTED;
+ break;
+ default:
+ msg.sdf_5g_val = FEATURE_NOT_SUPPORTED;
+ break;
+ }
+ msg.config_5g_sdf = true;
+ } else if (strcmp(param, "-rssi_close_5g_val") == 0) {
+ msg.rssi_close_5g_val = atoi(val_p);
+ if (msg.rssi_close_5g_val) {
+ msg.config_5g_rssi_close = true;
+ }
+ } else if (strcmp(param, "-rssi_middle_5g_val") == 0) {
+ msg.rssi_middle_5g_val = atoi(val_p);
+ if (msg.rssi_middle_5g_val) {
+ msg.config_5g_rssi_middle = true;
+ }
+ } else if (strcmp(param, "-rssi_close_proximity_5g_val") == 0) {
+ msg.rssi_close_proximity_5g_val = atoi(val_p);
+ if (msg.rssi_close_proximity_5g_val) {
+ msg.config_5g_rssi_close_proximity = true;
+ }
+ } else if (strcmp(param, "-rssi_window_size_val") == 0) {
+ msg.rssi_window_size_val = atoi(val_p);
+ if (msg.rssi_window_size_val) {
+ msg.config_rssi_window_size = true;
+ } else {
+ printMsg("%s:Invalid rssi_window_size_val\n", __FUNCTION__);
+ msg.config_rssi_window_size = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-config_cluster_attribute_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * If set to 1, the Discovery Engine will enclose the Cluster
+ * Attribute only sent in Beacons in a Vendor Specific Attribute
+ * and transmit in a Service Descriptor Frame.
+ */
+
+ switch(val) {
+ case FEATURE_SUPPORTED:
+ msg.config_cluster_attribute_val = FEATURE_SUPPORTED;
+ break;
+ default:
+ msg.config_cluster_attribute_val = FEATURE_NOT_SUPPORTED;
+ break;
+ }
+ } else if (strcmp(param, "-dwell_time") == 0) {
+ msg.scan_params_val.dwell_time[0] = atoi(val_p);
+ if (msg.scan_params_val.dwell_time[0]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-scan_period") == 0) {
+ msg.scan_params_val.scan_period[0] = atoi(val_p);
+ if (msg.scan_params_val.scan_period[0]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-dwell_time_5g") == 0) {
+ msg.scan_params_val.dwell_time[1] = atoi(val_p);
+ if (msg.scan_params_val.dwell_time[1]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params for 5g\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-scan_period_5g") == 0) {
+ msg.scan_params_val.scan_period[1] = atoi(val_p);
+ if (msg.scan_params_val.scan_period[1]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params for 5g\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-random_factor") == 0) {
+ msg.random_factor_force_val = atoi(val_p);
+ if (msg.random_factor_force_val) {
+ msg.config_random_factor_force = true;
+ } else {
+ printMsg("%s:Invalid random factor\n", __FUNCTION__);
+ msg.config_random_factor_force = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-24g_chan") == 0) {
+ msg.channel_24g_val = atoi(val_p);
+ if (msg.channel_24g_val) {
+ msg.config_24g_channel = true;
+ } else {
+ printMsg("%s:Invalid 2.4GHz channel value\n", __FUNCTION__);
+ msg.config_24g_channel = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-5g_chan") == 0) {
+ msg.channel_5g_val = atoi(val_p);
+ if (msg.channel_5g_val) {
+ msg.config_5g_channel = true;
+ } else {
+ printMsg("%s:Invalid 5GHz channel value\n", __FUNCTION__);
+ msg.config_5g_channel = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-nan_addr") == 0) {
+ if (!ether_atoe(val_p, msg.intf_addr_val)) {
+ printMsg("bad nan interface mac addr, setting to random mac by fw!\n");
+ msg.config_intf_addr = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ msg.config_intf_addr = true;
+ } else if (strcmp(param, "-awake_dw_2g") == 0) {
+ msg.config_dw.dw_2dot4g_interval_val = atoi(val_p);
+ if (msg.config_dw.dw_2dot4g_interval_val) {
+ msg.config_dw.config_2dot4g_dw_band = true;
+ }
+ } else if (strcmp(param, "-awake_dw_5g") == 0) {
+ msg.config_dw.dw_5g_interval_val = atoi(val_p);
+ if (msg.config_dw.dw_5g_interval_val) {
+ msg.config_dw.config_5g_dw_band = true;
+ }
+ } else if (strncmp(param, "-disc_ind_cfg", strlen("-disc_ind_cfg")) == 0) {
+ msg.discovery_indication_cfg = strtoul(val_p, &endptr, 0);
+ printMsg("%s:disc_ind_cfg value = %d.\n",
+ __FUNCTION__, msg.discovery_indication_cfg);
+ } else if (strncmp(param, "-rand_mac", strlen("-rand_mac")) == 0) {
+ msg.config_disc_mac_addr_randomization = true;
+ msg.disc_mac_addr_rand_interval_sec = atoi(val_p);
+ } else if (strcmp(param, "-use_ndpe") == 0) {
+ msg.use_ndpe_attr = atoi(val_p);
+ msg.config_ndpe_attr = true;
+ if ((msg.use_ndpe_attr != 1) && (msg.use_ndpe_attr != 0)) {
+ msg.config_ndpe_attr = false;
+ printMsg("%s:Invalid use_ndpe_attr value\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-disc_bcn_interval") == 0) {
+ msg.discovery_beacon_interval = atoi(val_p);
+ msg.config_discovery_beacon_int = true;
+ } else if (strcmp(param, "-enable_ranging") == 0) {
+ msg.enable_ranging = atoi(val_p);
+ if (msg.enable_ranging) {
+ msg.config_enable_ranging = true;
+ }
+ } else if (strcmp(param, "-nss") == 0) {
+ msg.nss = atoi(val_p);
+ if (msg.nss) {
+ msg.config_nss = true;
+ }
+ } else if (strcmp(param, "-enable_dw_term") == 0) {
+ msg.enable_dw_termination = atoi(val_p);
+ if (msg.enable_dw_termination) {
+ msg.config_dw_early_termination = true;
+ }
+#ifdef NAN_3_1_SUPPORT
+ } else if (strcmp(param, "-instant_mode") == 0) {
+ msg.enable_instant_mode = atoi(val_p);
+ msg.config_enable_instant_mode = true;
+ } else if (strcmp(param, "-instant_chan") == 0) {
+ msg.instant_mode_channel = atoi(val_p);
+ if (msg.instant_mode_channel) {
+ msg.config_instant_mode_channel = true;
+ } else {
+ printMsg("%s:Invalid Instant channel \n", __FUNCTION__);
+ msg.config_instant_mode_channel = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+#endif /* NAN_3_1_SUPPORT */
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Enable\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_enable_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void disableNan(void) {
+ wifi_error ret = WIFI_SUCCESS;
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ return;
+ }
+ ret = nan_disable_request(nanCmdId, wlan0Handle);
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+}
+
+void configNan(char *argv[]) {
+ NanConfigRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *endptr, *param, *val_p;
+ int sid_flag = 0xff, sid_count = 0xff;
+ int sub_sid_flag = 0xff, sub_sid_count = 0xff;
+ u8 val, numchans = 0;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.fam_val.famchan[numchans].entry_control = NAN_DURATION_16MS;
+ msg.config_ndpe_attr = false;
+
+ /* Parse args for nan params */
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p) {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ if (strcmp(param, "-sid_flag") == 0) {
+ sid_flag = atoi(val_p);
+ if (sid_flag) {
+ msg.config_sid_beacon = true;
+ } else {
+ printMsg("%s:Invalid Service Id Flag. Setting to Default\n", __FUNCTION__);
+ msg.config_sid_beacon = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sid_count") == 0) {
+ sid_count = atoi(val_p);
+ if (sid_count < 0 || sid_count > NAN_MAX_SIDS_IN_BEACONS) {
+ printMsg("%s:Invalid Service ID Count Limit. Setting to Default\n", __FUNCTION__);
+ sid_count = 0;
+ } else {
+ msg.sid_beacon = ((sid_count << 1) | sid_flag);
+ }
+ } else if (strcmp(param, "-sub_sid_flag") == 0) {
+ sub_sid_flag = atoi(val_p);
+ if (sub_sid_flag) {
+ msg.config_subscribe_sid_beacon = true;
+ } else {
+ printMsg("%s:Invalid Subscribe Service Id Flag. Setting to Default\n", __FUNCTION__);
+ msg.config_subscribe_sid_beacon = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sub_sid_count") == 0) {
+ sub_sid_count = atoi(val_p);
+ if (sub_sid_count < 0 || sub_sid_count > NAN_MAX_SIDS_IN_BEACONS) {
+ printMsg("%s:Invalid Subscribe Service ID Count Limit. Setting to Default\n", __FUNCTION__);
+ sub_sid_count = 0;
+ } else {
+ msg.subscribe_sid_beacon_val = ((sub_sid_count << 1) | sub_sid_flag);
+ }
+ } else if (strcmp(param, "-rssi_proximity") == 0) {
+ msg.rssi_proximity = atoi(val_p);
+ if (msg.rssi_proximity) {
+ msg.config_rssi_proximity = true;
+ } else {
+ printMsg("%s:Invalid rssi proximity\n", __FUNCTION__);
+ msg.config_rssi_proximity = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-master_pref") == 0) {
+ msg.master_pref = atoi(val_p);
+ if (msg.master_pref) {
+ msg.config_master_pref = true;
+ } else {
+ printMsg("%s:Invalid master_pref\n", __FUNCTION__);
+ msg.config_master_pref = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-rssi_close_prox_5g") == 0) {
+ msg.rssi_close_proximity_5g_val = atoi(val_p);
+ if (msg.rssi_close_proximity_5g_val) {
+ msg.config_5g_rssi_close_proximity = true;
+ } else {
+ printMsg("%s:Invalid 5g rssi close proximity \n", __FUNCTION__);
+ msg.config_5g_rssi_close_proximity = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-rssi_window_size_val") == 0) {
+ msg.rssi_window_size_val = atoi(val_p);
+ if (msg.rssi_window_size_val) {
+ msg.config_rssi_window_size = true;
+ } else {
+ printMsg("%s:Invalid rssi window size val \n", __FUNCTION__);
+ msg.config_rssi_window_size = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-config_cluster_attribute_val") == 0) {
+ val = atoi(val_p);
+ /*
+ * If set to 1, the Discovery Engine will enclose the Cluster
+ * Attribute only sent in Beacons in a Vendor Specific Attribute
+ * and transmit in a Service Descriptor Frame.
+ */
+
+ switch(val) {
+ case FEATURE_SUPPORTED:
+ msg.config_cluster_attribute_val = FEATURE_SUPPORTED;
+ break;
+ default:
+ msg.config_cluster_attribute_val = FEATURE_NOT_SUPPORTED;
+ break;
+ }
+ } else if (strcmp(param, "-dwell_time") == 0) {
+ msg.scan_params_val.dwell_time[0] = atoi(val_p);
+ if (msg.scan_params_val.dwell_time[0]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-scan_period") == 0) {
+ msg.scan_params_val.scan_period[0] = atoi(val_p);
+ if (msg.scan_params_val.scan_period[0]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-dwell_time_5g") == 0) {
+ msg.scan_params_val.dwell_time[1] = atoi(val_p);
+ if (msg.scan_params_val.dwell_time[1]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params for 5g\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-scan_period_5g") == 0) {
+ msg.scan_params_val.scan_period[1] = atoi(val_p);
+ if (msg.scan_params_val.scan_period[1]) {
+ msg.config_scan_params = true;
+ } else {
+ msg.config_scan_params = false;
+ printMsg("%s:Invalid config_scan_params for 5g\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-random_factor") == 0) {
+ msg.random_factor_force_val = atoi(val_p);
+ if (msg.random_factor_force_val) {
+ msg.config_random_factor_force = true;
+ } else {
+ printMsg("%s:Invalid random factor\n", __FUNCTION__);
+ msg.config_random_factor_force = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-hc_limit") == 0) {
+ msg.hop_count_force_val = atoi(val_p);
+ if (msg.hop_count_force_val) {
+ msg.config_hop_count_force = true;
+ } else {
+ printMsg("%s:Invalid hop_count_force_val. Setting to Default\n", __FUNCTION__);
+ msg.config_hop_count_force = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-numchans") == 0) {
+ numchans = atoi(val_p);
+ if (numchans) {
+ msg.config_fam = true;
+ msg.fam_val.numchans = numchans;
+ } else {
+ printMsg("%s:Invalid num chan\n", __FUNCTION__);
+ msg.config_fam = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-entry_control") == 0) {
+ val = atoi(val_p);
+ msg.config_fam = true;
+ switch(val) {
+ case NAN_DURATION_16MS:
+ msg.fam_val.famchan[numchans].entry_control = NAN_DURATION_16MS;
+ break;
+ case NAN_DURATION_32MS:
+ msg.fam_val.famchan[numchans].entry_control = NAN_DURATION_32MS;
+ break;
+ case NAN_DURATION_64MS:
+ msg.fam_val.famchan[numchans].entry_control = NAN_DURATION_64MS;
+ break;
+ default:
+ printMsg("%s: Invalid entry_control\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ msg.config_fam = false;
+ break;
+ }
+ } else if (strcmp(param, "-class_val") == 0) {
+ msg.fam_val.famchan[numchans].class_val = atoi(val_p);
+ if (msg.fam_val.famchan[numchans].class_val) {
+ msg.config_fam = true;
+ } else {
+ printMsg("%s:Invalid fam val\n", __FUNCTION__);
+ msg.config_fam = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-channel") == 0) {
+ msg.fam_val.famchan[numchans].channel = atoi(val_p);
+ if (msg.fam_val.famchan[numchans].channel) {
+ msg.config_fam = true;
+ } else {
+ printMsg("%s:Invalid fam val\n", __FUNCTION__);
+ msg.config_fam = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-mapid") == 0) {
+ msg.fam_val.famchan[numchans].mapid = atoi(val_p);
+ if (msg.fam_val.famchan[numchans].mapid) {
+ msg.config_fam = true;
+ } else {
+ printMsg("%s:Invalid fam val\n", __FUNCTION__);
+ msg.config_fam = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-avail_interval_bitmap") == 0) {
+ msg.fam_val.famchan[numchans].avail_interval_bitmap = atoi(val_p);
+ printMsg("avail_interval_bitmap = %d\n", msg.fam_val.famchan[numchans].avail_interval_bitmap);
+ if (msg.fam_val.famchan[numchans].avail_interval_bitmap) {
+ msg.config_fam = true;
+ } else {
+ printMsg("%s:Invalid fam val\n", __FUNCTION__);
+ msg.config_fam = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-awake_dw_2g") == 0) {
+ msg.config_dw.dw_2dot4g_interval_val = atoi(val_p);
+ if (msg.config_dw.dw_2dot4g_interval_val) {
+ msg.config_dw.config_2dot4g_dw_band = true;
+ }
+ } else if (strcmp(param, "-awake_dw_5g") == 0) {
+ msg.config_dw.dw_5g_interval_val = atoi(val_p);
+ if (msg.config_dw.dw_5g_interval_val) {
+ msg.config_dw.config_5g_dw_band = true;
+ }
+ } else if (strncmp(param, "-disc_ind_cfg", strlen("-disc_ind_cfg")) == 0) {
+ msg.discovery_indication_cfg = strtoul(val_p, &endptr, 0);
+ printMsg("%s:disc_ind_cfg value = %d.\n",
+ __FUNCTION__, msg.discovery_indication_cfg);
+ } else if (strcmp(param, "-use_ndpe") == 0) {
+ msg.use_ndpe_attr = atoi(val_p);
+ msg.config_ndpe_attr = true;
+ if ((msg.use_ndpe_attr != 1) && (msg.use_ndpe_attr != 0)) {
+ msg.config_ndpe_attr = false;
+ printMsg("%s:Invalid use_ndpe_attr value\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strncmp(param, "-rand_mac", strlen("-rand_mac")) == 0) {
+ msg.config_disc_mac_addr_randomization = true;
+ msg.disc_mac_addr_rand_interval_sec = atoi(val_p);
+ } else if (strcmp(param, "-disc_bcn_interval") == 0) {
+ msg.discovery_beacon_interval = atoi(val_p);
+ msg.config_discovery_beacon_int = true;
+ } else if (strcmp(param, "-enable_ranging") == 0) {
+ msg.enable_ranging = atoi(val_p);
+ if (msg.enable_ranging) {
+ msg.config_enable_ranging = true;
+ }
+ } else if (strcmp(param, "-nss") == 0) {
+ msg.nss = atoi(val_p);
+ if (msg.nss) {
+ msg.config_nss = true;
+ }
+ } else if (strcmp(param, "-enable_dw_term") == 0) {
+ msg.enable_dw_termination = atoi(val_p);
+ if (msg.enable_dw_termination) {
+ msg.config_dw_early_termination = true;
+ }
+#ifdef NAN_3_1_SUPPORT
+ } else if (strcmp(param, "-instant_mode") == 0) {
+ msg.enable_instant_mode = atoi(val_p);
+ msg.config_enable_instant_mode = true;
+ } else if (strcmp(param, "-instant_chan") == 0) {
+ msg.instant_mode_channel = atoi(val_p);
+ if (msg.instant_mode_channel) {
+ msg.config_instant_mode_channel = true;
+ } else {
+ printMsg("%s:Invalid Instant channel \n", __FUNCTION__);
+ msg.config_instant_mode_channel = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+#endif /* NAN_3_1_SUPPORT */
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Config\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_config_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void publishNan(int argc, char *argv[]) {
+ NanPublishRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL, *endptr = NULL;
+ u32 val = 0;
+ u8 *match_rxtmp = NULL, *match_txtmp = NULL;
+
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.publish_id = 0;
+ msg.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+ msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS;
+ msg.tx_type = NAN_TX_TYPE_UNICAST;
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_UNICAST_MSG;
+ msg.service_responder_policy = NAN_SERVICE_ACCEPT_POLICY_NONE;
+ msg.period = 1;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-svc") == 0) {
+ if (strlen((const char *)val_p) > NAN_MAX_SERVICE_NAME_LEN) {
+ printMsg("Invalid service name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_name_len =
+ strlen((const char *)val_p);
+ if (!set_interface_params((char*)msg.service_name,
+ val_p, msg.service_name_len)) {
+ printMsg("Set service name successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_specific_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.service_specific_info,
+ val_p, msg.service_specific_info_len)) {
+ printMsg("Set service specific info successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-pub_count") == 0) {
+ msg.publish_count = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-pub_id") == 0) {
+ msg.publish_id = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-pub_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_PUBLISH_TYPE_UNSOLICITED:
+ msg.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED;
+ break;
+ case NAN_PUBLISH_TYPE_SOLICITED:
+ msg.publish_type = NAN_PUBLISH_TYPE_SOLICITED;
+ break;
+ default:
+ msg.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+ break;
+ }
+ } else if (strcmp(param, "-tx_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_TX_TYPE_BROADCAST:
+ msg.tx_type = NAN_TX_TYPE_BROADCAST;
+ break;
+ default:
+ msg.tx_type = NAN_TX_TYPE_UNICAST;
+ break;
+ }
+ } else if (strcmp(param, "-ttl") == 0) {
+ msg.ttl = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-svc_awake_dw") == 0) {
+ msg.period = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-match_tx") == 0) {
+ u8 m_len = strlen(val_p);
+ if (!match_txtmp) {
+ match_txtmp = msg.tx_match_filter;
+ }
+ if (strcmp(val_p, "0") == 0) {
+ printMsg("wild card\n");
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.tx_match_filter_len)) {
+ *match_txtmp++ = 0;
+ msg.tx_match_filter_len++;
+ }
+ } else {
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.tx_match_filter_len)) {
+ *match_txtmp++ = strlen(val_p);
+ msg.tx_match_filter_len++;
+ strncpy((char *)match_txtmp, val_p, strlen(val_p));
+ match_txtmp += m_len;
+ msg.tx_match_filter_len += m_len;
+ } else {
+ printMsg("Invalid match filter len\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strcmp(param, "-match_rx") == 0) {
+ u8 m_len = strlen(val_p);
+ if (!match_rxtmp) {
+ match_rxtmp = msg.rx_match_filter;
+ }
+ if (strcmp(val_p, "0") == 0) {
+ printMsg("wild card\n");
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.rx_match_filter_len)) {
+ *match_rxtmp++ = 0;
+ msg.rx_match_filter_len++;
+ }
+ } else {
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.rx_match_filter_len)) {
+ *match_rxtmp++ = strlen(val_p);
+ msg.rx_match_filter_len++;
+ strncpy((char *)match_rxtmp, val_p, strlen(val_p));
+ match_rxtmp += m_len;
+ msg.rx_match_filter_len += m_len;
+ } else {
+ printMsg("Invalid match filter len\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strncmp(param, "-recv_flag", strlen("-recv_flag")) == 0) {
+ msg.recv_indication_cfg = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-match_ind") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_MATCH_ALG_MATCH_ONCE:
+ msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
+ break;
+ case NAN_MATCH_ALG_MATCH_NEVER:
+ msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_NEVER;
+ break;
+ default:
+ msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS;
+ break;
+ }
+ } else if (strcmp(param, "-csid") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_CIPHER_SUITE_SHARED_KEY_NONE:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_256_MASK;
+ break;
+#ifdef NAN_3_1_SUPPORT
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK;
+ break;
+#endif /* NAN_3_1_SUPPORT */
+ default:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ }
+ } else if (strcmp(param, "-key_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SECURITY_KEY_INPUT_PMK:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
+ break;
+ case NAN_SECURITY_KEY_INPUT_PASSPHRASE:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ break;
+ default:
+ printMsg("Invalid security key type\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-pmk") == 0) {
+ if (strlen((const char*)val_p) > NAN_PMK_INFO_LEN) {
+ printMsg("Invalid PMK\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.pmk_info.pmk_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.key_info.body.pmk_info.pmk,
+ val_p, msg.key_info.body.pmk_info.pmk_len)) {
+ printMsg("Set PMK successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-passphrase") == 0) {
+ if (strlen((const char*)val_p) < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ strlen((const char*)val_p) > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ printMsg("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.passphrase_info.passphrase_len =
+ (strlen((const char*)val_p));
+ if (!set_interface_params((char*)msg.key_info.body.passphrase_info.passphrase,
+ val_p, msg.key_info.body.passphrase_info.passphrase_len)) {
+ printMsg("Set passphrase successfull, len = %d\n", msg.key_info.body.passphrase_info.passphrase_len);
+ } else {
+ printMsg("Invalid passphrase\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strcmp(param, "-scid") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SCID_BUF_LEN) {
+ printMsg("Invalid SCID\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.scid_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.scid,
+ val_p, msg.scid_len)) {
+ printMsg("Set SCID successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-dp_type") == 0) {
+ val = atoi(val_p);
+ msg.sdea_params.config_nan_data_path = true;
+ switch(val) {
+ case NAN_DATA_PATH_MULTICAST_MSG:
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_MULTICAST_MSG;
+ break;
+ case NAN_DATA_PATH_UNICAST_MSG:
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_UNICAST_MSG;
+ break;
+ default:
+ printMsg("Invalid datapath type\n");
+ msg.sdea_params.config_nan_data_path = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ } else if (strcmp(param, "-secure_dp") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_SECURITY:
+ msg.sdea_params.security_cfg = NAN_DP_CONFIG_SECURITY;
+ break;
+ default:
+ msg.sdea_params.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ break;
+ }
+ } else if (strcmp(param, "-ranging") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_RANGING_ENABLE:
+ msg.sdea_params.ranging_state = NAN_RANGING_ENABLE;
+ break;
+ default:
+ msg.sdea_params.ranging_state = NAN_RANGING_DISABLE;
+ break;
+ }
+ } else if (strcmp(param, "-ranging_intvl") == 0) {
+ msg.ranging_cfg.ranging_interval_msec = atoi(val_p);
+ } else if (strcmp(param, "-ranging_ind") == 0) {
+ msg.ranging_cfg.config_ranging_indications = atoi(val_p);
+ } else if (strcmp(param, "-ingress") == 0) {
+ msg.ranging_cfg.distance_ingress_mm = atoi(val_p);
+ } else if (strcmp(param, "-egress") == 0) {
+ msg.ranging_cfg.distance_egress_mm= atoi(val_p);
+ } else if (strcmp(param, "-rssi_thresh_flag") == 0) {
+ msg.rssi_threshold_flag = atoi(val_p);
+ } else if (strcmp(param, "-sdea_info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid SDEA service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.sdea_service_specific_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.sdea_service_specific_info,
+ val_p, msg.sdea_service_specific_info_len)) {
+ printMsg("Set SDEA service specific info successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-auto_dp_accept") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SERVICE_ACCEPT_POLICY_ALL:
+ msg.service_responder_policy = NAN_SERVICE_ACCEPT_POLICY_ALL;
+ break;
+ default:
+ msg.service_responder_policy = NAN_SERVICE_ACCEPT_POLICY_NONE;
+ break;
+ }
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Publish\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+ if (!msg.service_name_len) {
+ printMsg("service name is mandatory !!\n");
+ goto exit;
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_publish_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void subscribeNan(int argc, char *argv[]) {
+ NanSubscribeRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL, *endptr = NULL;
+ u8 num_mac_addr = 0;
+ u32 val = 0;
+ u8 *match_rxtmp = NULL, *match_txtmp = NULL;
+
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ memset(&msg, 0, sizeof(msg));
+
+ /* set mandatory default values */
+ msg.subscribe_id = 0;
+ msg.subscribe_type = NAN_SUBSCRIBE_TYPE_PASSIVE;
+ msg.useServiceResponseFilter = NAN_DO_NOT_USE_SRF;
+ /*
+ * Set NAN_MATCH_ALG_MATCH_ONCE as default param to avoid
+ * flooding of discovery result events
+ */
+ msg.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_UNICAST_MSG;
+ msg.rx_match_filter_len = 0;
+ msg.tx_match_filter_len = 0;
+ msg.period = 1;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-svc") == 0) {
+ if (strlen((const char *)val_p) > NAN_MAX_SERVICE_NAME_LEN) {
+ printMsg("Invalid service name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_name_len =
+ strlen((const char *)val_p);
+ if (!set_interface_params((char*)msg.service_name,
+ val_p, msg.service_name_len)) {
+ printMsg("Set service name successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_specific_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.service_specific_info,
+ val_p, msg.service_specific_info_len)) {
+ printMsg("Set service specific info successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-sub_count") == 0) {
+ msg.subscribe_count = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-pub_ssi") == 0) {
+ val = atoi(val_p);
+ /*
+ * Flag which specifies if the Service Specific Info is needed in
+ * the Publish message before creating the MatchIndication
+ */
+ /* 0= Not needed, 1= Required */
+ switch(val) {
+ case NAN_SSI_REQUIRED_IN_MATCH_IND:
+ msg.ssiRequiredForMatchIndication = NAN_SSI_REQUIRED_IN_MATCH_IND;
+ break;
+ default:
+ msg.ssiRequiredForMatchIndication = NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+ break;
+ }
+ } else if (strcmp(param, "-sub_id") == 0) {
+ msg.subscribe_id = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-sub_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SUBSCRIBE_TYPE_ACTIVE:
+ msg.subscribe_type = NAN_SUBSCRIBE_TYPE_ACTIVE;
+ break;
+ default:
+ msg.subscribe_type = NAN_SUBSCRIBE_TYPE_PASSIVE;
+ break;
+ }
+ } else if (strcmp(param, "-ttl") == 0) {
+ msg.ttl = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-svc_awake_dw") == 0) {
+ msg.period = strtoul(val_p, &endptr, 0);
+ } else if (strncmp(param, "-srf_use", strlen("-srf_use")) == 0) {
+ val = atoi(val_p);
+ /* 0=Do not send the Service Response Filter,1= send */
+ switch(val) {
+ case NAN_USE_SRF:
+ msg.useServiceResponseFilter = NAN_USE_SRF;
+ break;
+ default:
+ msg.useServiceResponseFilter = NAN_DO_NOT_USE_SRF;
+ break;
+ }
+ } else if (strncmp(param, "-srf_include", strlen("-srf_include")) == 0) {
+ val = strtoul(val_p, &endptr, 0);
+ /* 0=Do not respond if in the Address Set, 1= Respond */
+ switch(val) {
+ case NAN_SRF_INCLUDE_RESPOND:
+ msg.serviceResponseInclude = NAN_SRF_INCLUDE_RESPOND;
+ break;
+ default:
+ msg.serviceResponseInclude = NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+ break;
+ }
+ } else if (strncmp(param, "-srf_type", strlen("-srf_type")) == 0) {
+ val = atoi(val_p);
+ /* 0 - Bloom Filter, 1 - MAC Addr */
+ switch(val) {
+ case NAN_SRF_ATTR_PARTIAL_MAC_ADDR:
+ msg.serviceResponseFilter = NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+ break;
+ default:
+ msg.serviceResponseFilter = NAN_SRF_ATTR_BLOOM_FILTER;
+ break;
+ }
+ } else if (strcmp(param, "-mac_list") == 0) {
+ if (num_mac_addr < NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+ if (!ether_atoe(val_p, msg.intf_addr[num_mac_addr])) {
+ printMsg("bad mac addr !!\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ msg.num_intf_addr_present = ++num_mac_addr;
+ } else {
+ printMsg("max limit reached, %d!!!\n", num_mac_addr);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ if (msg.num_intf_addr_present) {
+ msg.useServiceResponseFilter = NAN_USE_SRF;
+ msg.serviceResponseFilter = NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+ }
+ } else if (strcmp(param, "-match_ind") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_MATCH_ALG_MATCH_ONCE:
+ msg.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
+ break;
+ case NAN_MATCH_ALG_MATCH_NEVER:
+ msg.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_NEVER;
+ break;
+ default:
+ msg.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS;
+ break;
+ }
+ } else if (strcmp(param, "-match_tx") == 0) {
+ u8 m_len = strlen(val_p);
+ if (!match_txtmp) {
+ match_txtmp = msg.tx_match_filter;
+ }
+ if (strcmp(val_p, "0") == 0) {
+ printMsg("wild card\n");
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.tx_match_filter_len)) {
+ *match_txtmp++ = 0;
+ msg.tx_match_filter_len++;
+ }
+ } else {
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.tx_match_filter_len)) {
+ *match_txtmp++ = strlen(val_p);
+ msg.tx_match_filter_len++;
+ strncpy((char *)match_txtmp, val_p, strlen(val_p));
+ match_txtmp += m_len;
+ msg.tx_match_filter_len += m_len;
+ } else {
+ printMsg("Invalid match filter len\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strcmp(param, "-match_rx") == 0) {
+ u8 m_len = strlen(val_p);
+ if (!match_rxtmp) {
+ match_rxtmp = msg.rx_match_filter;
+ }
+ if (strcmp(val_p, "0") == 0) {
+ printMsg("wild card\n");
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.rx_match_filter_len)) {
+ *match_rxtmp++ = 0;
+ msg.rx_match_filter_len++;
+ }
+ } else {
+ if (m_len < (NAN_MAX_MATCH_FILTER_LEN - msg.rx_match_filter_len)) {
+ *match_rxtmp++ = strlen(val_p);
+ msg.rx_match_filter_len++;
+ strncpy((char *)match_rxtmp, val_p, strlen(val_p));
+ match_rxtmp += m_len;
+ msg.rx_match_filter_len += m_len;
+ } else {
+ printMsg("Invalid match filter len\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strncmp(param, "-recv_flag", strlen("-recv_flag")) == 0) {
+ msg.recv_indication_cfg = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-csid") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_CIPHER_SUITE_SHARED_KEY_NONE:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_256_MASK;
+ break;
+#ifdef NAN_3_1_SUPPORT
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK;
+ break;
+#endif /* NAN_3_1_SUPPORT */
+ default:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ }
+ } else if (strcmp(param, "-key_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SECURITY_KEY_INPUT_PMK:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
+ break;
+ case NAN_SECURITY_KEY_INPUT_PASSPHRASE:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ break;
+ default:
+ printMsg("Invalid security key type\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-pmk") == 0) {
+ if (strlen((const char*)val_p) > NAN_PMK_INFO_LEN) {
+ printMsg("Invalid PMK\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.pmk_info.pmk_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.key_info.body.pmk_info.pmk,
+ val_p, msg.key_info.body.pmk_info.pmk_len)) {
+ printMsg("Set PMK successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-passphrase") == 0) {
+ if (strlen((const char*)val_p) < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ strlen((const char*)val_p) > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ printMsg("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.passphrase_info.passphrase_len =
+ (strlen((const char*)val_p));
+ if (!set_interface_params((char*)msg.key_info.body.passphrase_info.passphrase,
+ val_p, msg.key_info.body.passphrase_info.passphrase_len)) {
+ printMsg("Set passphrase successfull, len = %d\n", msg.key_info.body.passphrase_info.passphrase_len);
+ } else {
+ printMsg("Invalid passphrase\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+ } else if (strcmp(param, "-scid") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SCID_BUF_LEN) {
+ printMsg("Invalid SCID\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.scid_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.scid,
+ val_p, msg.scid_len)) {
+ printMsg("Set SCID successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-dp_type") == 0) {
+ val = atoi(val_p);
+ msg.sdea_params.config_nan_data_path = true;
+ switch(val) {
+ case NAN_DATA_PATH_MULTICAST_MSG:
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_MULTICAST_MSG;
+ break;
+ case NAN_DATA_PATH_UNICAST_MSG:
+ msg.sdea_params.ndp_type = NAN_DATA_PATH_UNICAST_MSG;
+ break;
+ default:
+ printMsg("Invalid datapath type\n");
+ msg.sdea_params.config_nan_data_path = false;
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ } else if (strcmp(param, "-secure_dp") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_SECURITY:
+ msg.sdea_params.security_cfg = NAN_DP_CONFIG_SECURITY;
+ break;
+ default:
+ msg.sdea_params.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ break;
+ }
+ } else if (strcmp(param, "-ranging") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_RANGING_ENABLE:
+ msg.sdea_params.ranging_state = NAN_RANGING_ENABLE;
+ break;
+ default:
+ msg.sdea_params.ranging_state = NAN_RANGING_DISABLE;
+ break;
+ }
+ } else if (strcmp(param, "-ranging_intvl") == 0) {
+ msg.ranging_cfg.ranging_interval_msec = atoi(val_p);
+ } else if (strcmp(param, "-ranging_ind") == 0) {
+ msg.ranging_cfg.config_ranging_indications = atoi(val_p);
+ } else if (strcmp(param, "-ingress") == 0) {
+ msg.ranging_cfg.distance_ingress_mm = atoi(val_p);
+ } else if (strcmp(param, "-egress") == 0) {
+ msg.ranging_cfg.distance_egress_mm= atoi(val_p);
+ } else if (strcmp(param, "-rssi_thresh_flag") == 0) {
+ msg.rssi_threshold_flag = atoi(val_p);
+ } else if (strcmp(param, "-sdea_info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid SDEA service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.sdea_service_specific_info_len = strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.sdea_service_specific_info,
+ val_p, msg.sdea_service_specific_info_len)) {
+ printMsg("Set SDEA service specific info successfull\n");
+ }
+ }
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Subscribe\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+ if (!msg.service_name_len) {
+ printMsg("service name is mandatory !!\n");
+ goto exit;
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_subscribe_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void cancelPublishNan(char *argv[]) {
+ NanPublishCancelRequest msg ;
+ wifi_error ret = WIFI_SUCCESS;
+ u16 pub_id;
+ pub_id = atoi(argv[3]);
+ if (pub_id) {
+ msg.publish_id = pub_id;
+ } else {
+ printMsg("\nInvalid argument \n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_publish_cancel_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+
+void cancelSubscribeNan(char *argv[]) {
+ NanSubscribeCancelRequest msg ;
+ wifi_error ret = WIFI_SUCCESS;
+ u16 sub_id;
+ sub_id = atoi(argv[3]);
+ if (sub_id) {
+ msg.subscribe_id = sub_id;
+ } else {
+ printMsg("\nInvalid argument \n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_subscribe_cancel_request(nanCmdId, wlan0Handle, &msg);
+#ifdef NAN_BLOCK_FOR_EVENT
+ memset(&info, 0, sizeof(info));
+ getEventFromCache(info);
+ printMsg("retrieved event %d : %s\n", info.type, info.buf);
+#endif
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void transmitNan(int argc, char *argv[]) {
+ NanTransmitFollowupRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL, *endptr = NULL;
+ u16 src_id = 0;
+ u32 dest_id = 0;
+ u8 *mac_addr = NULL;
+
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ memset(&msg, 0, sizeof(msg));
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-src_id") == 0) {
+ msg.publish_subscribe_id = atoi(val_p);
+ src_id = msg.publish_subscribe_id;
+ } else if (strcmp(param, "-dest_id") == 0) {
+ msg.requestor_instance_id = atoi(val_p);
+ dest_id = msg.requestor_instance_id;
+ } else if (strcmp(param, "-peer_addr") == 0) {
+ if (!ether_atoe(val_p, msg.addr)) {
+ printMsg("bad peer mac addr !!\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ mac_addr = msg.addr;
+ } else if (strcmp(param, "-info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_specific_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.service_specific_info,
+ val_p, msg.service_specific_info_len)) {
+ printMsg("Set service specific info successfull\n");
+ }
+ }
+ } else if (strncmp(param, "-recv_flag", strlen("-recv_flag")) == 0) {
+ msg.recv_indication_cfg = strtoul(val_p, &endptr, 0);
+ } else if (strcmp(param, "-sdea_info") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ printMsg("Invalid SDEA service specific info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.sdea_service_specific_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.sdea_service_specific_info,
+ val_p, msg.sdea_service_specific_info_len)) {
+ printMsg("Set SDEA service specific info successfull\n");
+ }
+ }
+ } else {
+ printMsg("%s:Unsupported Parameter for nan transmit followup\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+
+ if (!src_id) {
+ printMsg("Source Instance Id is mandatory !!\n");
+ goto exit;
+ }
+ if (!dest_id) {
+ printMsg("Destination Instance Id is mandatory !!\n");
+ goto exit;
+ }
+ if (!mac_addr) {
+ printMsg("Peer MAC Address is mandatory !!\n");
+ goto exit;
+ }
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_transmit_followup_request(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void getNanCapabilities(void) {
+ nanCmdId = getNewCmdId();
+ wifi_error ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ return;
+ }
+ nan_get_capabilities(nanCmdId, wlan0Handle);
+}
+
+void nanDataPathIfaceCreate(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char ndp_iface[IFNAMSIZ+1];
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-iface") == 0) {
+ if (!set_interface_params(ndp_iface, val_p, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid Iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else {
+ printMsg("Unsupported Parameter for ndp iface create\n");
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_data_interface_create(nanCmdId, wlan0Handle, ndp_iface);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void nanDataPathIfaceDelete(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char ndp_iface[IFNAMSIZ+1];
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-iface") == 0) {
+ if (!set_interface_params(ndp_iface, val_p, (IFNAMSIZ - 1))) {
+ printMsg("clear interface name successfull\n");
+ } else {
+ printMsg("Invalid Iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else {
+ printMsg("Unsupported Parameter for ndp iface delete\n");
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_data_interface_delete(nanCmdId, wlan0Handle, ndp_iface);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+
+void nanDataInitRequest(int argc, char *argv[]) {
+ NanDataPathInitiatorRequest msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ u32 val = 0;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_NO_QOS;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-pub_id") == 0) {
+ msg.requestor_instance_id = atoi(val_p);
+ } else if (strcmp(param, "-chan_req_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CHANNEL_NOT_REQUESTED:
+ msg.channel_request_type = NAN_DP_CHANNEL_NOT_REQUESTED ;
+ break;
+ case NAN_DP_REQUEST_CHANNEL_SETUP:
+ msg.channel_request_type = NAN_DP_REQUEST_CHANNEL_SETUP;
+ break;
+ case NAN_DP_FORCE_CHANNEL_SETUP:
+ msg.channel_request_type = NAN_DP_FORCE_CHANNEL_SETUP;
+ break;
+ default:
+ msg.channel_request_type = NAN_DP_CHANNEL_NOT_REQUESTED;
+ break;
+ }
+ } else if (strcmp(param, "-chan") == 0) {
+ msg.channel = atoi(val_p);
+ } else if (strcmp(param, "-disc_mac") == 0) {
+ if (!ether_atoe(val_p, msg.peer_disc_mac_addr)) {
+ printMsg("bad Discovery Mac address !!\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-iface") == 0) {
+ if (!set_interface_params(msg.ndp_iface, val_p, (IFNAMSIZ - 1))) {
+ printMsg("Set Iface name successfull\n");
+ } else {
+ printMsg("Invalid Iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sec") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_SECURITY:
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_SECURITY;
+ break;
+ default:
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ break;
+ }
+ } else if (strcmp(param, "-qos") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_QOS:
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_QOS;
+ break;
+ default:
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_NO_QOS;
+ break;
+ }
+ } else if (strcmp(param, "-info") == 0) {
+ if (strlen((const char*)val_p) > NAN_DP_MAX_APP_INFO_LEN) {
+ printMsg("Invalid app info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.app_info.ndp_app_info_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.app_info.ndp_app_info,
+ val_p, msg.app_info.ndp_app_info_len)) {
+ printMsg("Set app info successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-csid") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_CIPHER_SUITE_SHARED_KEY_NONE:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_256_MASK;
+ break;
+#ifdef NAN_3_1_SUPPORT
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK;
+ break;
+#endif /* NAN_3_1_SUPPORT */
+ default:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ }
+ } else if (strcmp(param, "-key_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SECURITY_KEY_INPUT_PMK:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
+ break;
+ case NAN_SECURITY_KEY_INPUT_PASSPHRASE:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ break;
+ default:
+ printMsg("Invalid security key type\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-pmk") == 0) {
+ if (strlen((const char*)val_p) > NAN_PMK_INFO_LEN) {
+ printMsg("Invalid PMK\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.pmk_info.pmk_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.key_info.body.pmk_info.pmk,
+ val_p, msg.key_info.body.pmk_info.pmk_len)) {
+ printMsg("Set PMK successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-passphrase") == 0) {
+ if (strlen((const char*)val_p) < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ strlen((const char*)val_p) > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ printMsg("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.passphrase_info.passphrase_len =
+ (strlen((const char*)val_p));
+ if (!set_interface_params((char*)msg.key_info.body.passphrase_info.passphrase,
+ val_p, msg.key_info.body.passphrase_info.passphrase_len)) {
+ printMsg("Set passphrase successfull, len = %d\n", msg.key_info.body.passphrase_info.passphrase_len);
+ } else {
+ printMsg("Invalid passphrase\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+#ifdef NAN_3_1_SUPPORT
+ } else if (strcmp(param, "-scid") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SCID_BUF_LEN) {
+ printMsg("Invalid SCID\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.scid_len=
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.scid,
+ val_p, msg.scid_len)) {
+ printMsg("Set SCID successfull\n");
+ }
+ }
+#endif /* NAN_3_1_SUPPORT */
+ } else if (strcmp(param, "-svc") == 0) {
+ if (strlen((const char *)val_p) > NAN_MAX_SERVICE_NAME_LEN) {
+ printMsg("Invalid service name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_name_len =
+ strlen((const char *)val_p);
+ if (!set_interface_params((char*)msg.service_name,
+ val_p, msg.service_name_len)) {
+ printMsg("Set service name successfull\n");
+ }
+ }
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Data Path Request\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_data_request_initiator(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void nanDataIndResponse(int argc, char *argv[]) {
+ NanDataPathIndicationResponse msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ u32 val = 0;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_NO_QOS;
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-ndp_id") == 0) {
+ msg.ndp_instance_id = atoi(val_p);
+ } else if (strcmp(param, "-iface") == 0) {
+ if (!set_interface_params(msg.ndp_iface, val_p, (IFNAMSIZ - 1))) {
+ printMsg("Set Iface name successfull\n");
+ } else {
+ printMsg("Invalid Iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-sec") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_SECURITY:
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_SECURITY;
+ break;
+ default:
+ msg.ndp_cfg.security_cfg = NAN_DP_CONFIG_NO_SECURITY;
+ break;
+ }
+ } else if (strcmp(param, "-qos") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_CONFIG_QOS:
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_QOS;
+ break;
+ default:
+ msg.ndp_cfg.qos_cfg = NAN_DP_CONFIG_NO_QOS;
+ break;
+ }
+ } else if (strcmp(param, "-info") == 0) {
+ if ((u16)strlen((const char*)val_p) > NAN_DP_MAX_APP_INFO_LEN) {
+ printMsg("Invalid app info\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.app_info.ndp_app_info_len =
+ (u16)strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.app_info.ndp_app_info,
+ val_p, msg.app_info.ndp_app_info_len)) {
+ printMsg("Set app info successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-resp_code") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_DP_REQUEST_REJECT:
+ msg.rsp_code = NAN_DP_REQUEST_REJECT;
+ break;
+ case NAN_DP_REQUEST_ACCEPT:
+ msg.rsp_code = NAN_DP_REQUEST_ACCEPT;
+ break;
+ default:
+ printMsg("Invalid response code\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-csid") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_CIPHER_SUITE_SHARED_KEY_NONE:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_SHARED_KEY_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_256_MASK;
+ break;
+#ifdef NAN_3_1_SUPPORT
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK;
+ break;
+ case NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK:
+ msg.cipher_type = NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK;
+ break;
+#endif /* NAN_3_1_SUPPORT */
+ default:
+ msg.cipher_type = NAN_CIPHER_SUITE_SHARED_KEY_NONE;
+ break;
+ }
+ } else if (strcmp(param, "-key_type") == 0) {
+ val = atoi(val_p);
+ switch(val) {
+ case NAN_SECURITY_KEY_INPUT_PMK:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
+ break;
+ case NAN_SECURITY_KEY_INPUT_PASSPHRASE:
+ msg.key_info.key_type = NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ break;
+ default:
+ printMsg("Invalid security key type\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-pmk") == 0) {
+ if (strlen((const char*)val_p) > NAN_PMK_INFO_LEN) {
+ printMsg("Invalid PMK\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.pmk_info.pmk_len =
+ strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.key_info.body.pmk_info.pmk,
+ val_p, msg.key_info.body.pmk_info.pmk_len)) {
+ printMsg("Set PMK successfull\n");
+ }
+ }
+ } else if (strcmp(param, "-passphrase") == 0) {
+ if (strlen((const char*)val_p) < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+ strlen((const char*)val_p) > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ printMsg("passphrase must be between %d and %d characters long\n",
+ NAN_SECURITY_MIN_PASSPHRASE_LEN,
+ NAN_SECURITY_MAX_PASSPHRASE_LEN);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.key_info.body.passphrase_info.passphrase_len =
+ (strlen((const char*)val_p));
+ if (!set_interface_params((char*)msg.key_info.body.passphrase_info.passphrase,
+ val_p, msg.key_info.body.passphrase_info.passphrase_len)) {
+ printMsg("Set passphrase successfull, len = %d\n", msg.key_info.body.passphrase_info.passphrase_len);
+ } else {
+ printMsg("Invalid passphrase\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+#ifdef NAN_3_1_SUPPORT
+ } else if (strcmp(param, "-scid") == 0) {
+ if (strlen((const char*)val_p) > NAN_MAX_SCID_BUF_LEN) {
+ printMsg("Invalid SCID\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.scid_len= strlen((const char*)val_p);
+ if (!set_interface_params((char*)msg.scid, val_p, msg.scid_len)) {
+ printMsg("Set SCID successfull\n");
+ }
+ }
+#endif /* NAN_3_1_SUPPORT */
+ } else if (strcmp(param, "-svc") == 0) {
+ if (strlen((const char *)val_p) > NAN_MAX_SERVICE_NAME_LEN) {
+ printMsg("Invalid service name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ msg.service_name_len =
+ strlen((const char *)val_p);
+ if (!set_interface_params((char*)msg.service_name,
+ val_p, msg.service_name_len)) {
+ printMsg("Set service name successfull\n");
+ }
+ }
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Data Path Request\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_data_indication_response(nanCmdId, wlan0Handle, &msg);
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void nanDataPathEnd(int argc, char *argv[]) {
+ NanDataPathEndRequest *msg;
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL, *endptr = NULL;
+ u8 count = 0, i = 0;
+ NanDataPathId ndp_id = 0;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* skip command */
+ argv++;
+
+ msg = (NanDataPathEndRequest *)malloc(NAN_MAX_NDP_COUNT_SIZE + sizeof(u8));
+ if (!msg) {
+ printMsg("Failed to alloc for end request\n");
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+ memset(msg, 0, NAN_MAX_NDP_COUNT_SIZE + sizeof(u8));
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-inst_count") == 0) {
+ count = atoi(val_p);
+ if (!count || count > 1) {
+ printMsg("%s:Invalid inst_count value.\n", __FUNCTION__);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ msg->num_ndp_instances = count;
+ } else if (strcmp(param, "-inst_id") == 0) {
+ if (!msg->num_ndp_instances || (i > msg->num_ndp_instances)) {
+ printMsg("num of ndp instances need to be minimum 1\n");
+ goto exit;
+ }
+ ndp_id = strtoul(val_p, &endptr, 0);
+ msg->ndp_instance_id[i++] = ndp_id;
+ } else {
+ printMsg("%s:Unsupported Parameter for Nan Data Path End Request\n", __FUNCTION__);
+ goto exit;
+ }
+ }
+
+ nanCmdId = getNewCmdId();
+ ret = nan_init_handlers();
+ if (ret != WIFI_SUCCESS) {
+ printMsg("Failed to initialize handlers %d\n", ret);
+ goto exit;
+ }
+ ret = nan_data_end(nanCmdId, wlan0Handle, msg);
+exit:
+ if (msg) {
+ free(msg);
+ }
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void VirtualIfaceAdd(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+ wifi_interface_type iface_type;
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-name") == 0) {
+ if (!set_interface_params(iface_name, val_p, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid Iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else if (strcmp(param, "-type") == 0) {
+ iface_type = (wifi_interface_type)atoi(val_p);
+ } else {
+ printMsg("Unsupported Parameter for virtual iface delete\n");
+ goto exit;
+ }
+ }
+
+ ret = hal_fn.wifi_virtual_interface_create(halHandle, iface_name, iface_type);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successful to add virtual iface\n");
+ } else {
+ printMsg("Failed to add virtual iface, result = %d\n", ret);
+ }
+
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+void VirtualIfaceDelete(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL, *val_p = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+
+ while ((param = *argv++) != NULL) {
+ val_p = *argv++;
+ if (!val_p || *val_p == '-') {
+ printMsg("%s: Need value following %s\n", __FUNCTION__, param);
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ if (strcmp(param, "-name") == 0) {
+ if (!set_interface_params(iface_name, val_p, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid face name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ } else {
+ printMsg("Unsupported Parameter for virtual iface delete\n");
+ goto exit;
+ }
+ }
+
+ ret = hal_fn.wifi_virtual_interface_delete(halHandle, iface_name);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successful to delete virtual iface\n");
+ } else {
+ printMsg("Failed to delete virtual iface, result = %d\n", ret);
+ }
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void
+MultiStaSetPrimaryConnection(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+ wifi_interface_handle ifHandle = NULL;
+
+ while ((param = *argv++) != NULL) {
+ if (!set_interface_params(iface_name, param, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ifHandle = wifi_get_iface_handle(halHandle, iface_name);
+ if (ifHandle == NULL) {
+ printMsg("Invalid iface handle for the requested interface\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ ret = hal_fn.wifi_multi_sta_set_primary_connection(halHandle, ifHandle);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successfully set as primary connection\n");
+ }
+ }
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void
+MultiStaSetUsecase(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ uint use_case;
+ wifi_multi_sta_use_case mMultiStaUsecase;
+
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+
+ use_case = (uint)atoi(*argv);
+ if (use_case >= WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY &&
+ use_case <= WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED) {
+ mMultiStaUsecase = (wifi_multi_sta_use_case)use_case;
+ } else {
+ printMsg("Invalid multi_sta usecase\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ ret = hal_fn.wifi_multi_sta_set_use_case(halHandle, mMultiStaUsecase);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successful to set multista usecase\n");
+ } else {
+ printMsg("Failed to set multista usecase, result = %d\n", ret);
+ }
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+static void
+SetLatencyMode(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+ wifi_interface_handle ifHandle = NULL;
+
+ param = *argv++;
+ if (param != NULL) {
+ if (!set_interface_params(iface_name, param, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull %s\n", iface_name);
+ } else {
+ printMsg("Invalid iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ifHandle = wifi_get_iface_handle(halHandle, iface_name);
+ if (ifHandle == NULL) {
+ printMsg("Invalid iface handle for the requested interface\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ /* Read the requested latency mode */
+ wifi_latency_mode latency_mode = (wifi_latency_mode)(atoi)(*argv);
+ ret = hal_fn.wifi_set_latency_mode(ifHandle, latency_mode);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successfully set latency mode\n");
+ }
+ }
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+
+}
+
+static void
+SetVoipMode(char *argv[]) {
+ wifi_error ret = WIFI_SUCCESS;
+ char *param = NULL;
+ /* skip utility */
+ argv++;
+ /* skip command */
+ argv++;
+ /* Interface name */
+ char iface_name[IFNAMSIZ+1];
+ wifi_interface_handle ifHandle = NULL;
+
+ param = *argv++;
+ if (param != NULL) {
+ if (!set_interface_params(iface_name, param, (IFNAMSIZ - 1))) {
+ printMsg("set interface name successfull\n");
+ } else {
+ printMsg("Invalid iface name\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ }
+
+ ifHandle = wifi_get_iface_handle(halHandle, iface_name);
+ if (ifHandle == NULL) {
+ printMsg("Invalid iface handle for the requested interface\n");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ } else {
+ /* Read the requested voip mode */
+ wifi_voip_mode mode = (wifi_voip_mode)(atoi)(*argv);
+ ret = hal_fn.wifi_set_voip_mode(ifHandle, mode);
+ if (ret == WIFI_ERROR_NONE) {
+ printMsg("Successfully set voip mode\n");
+ }
+ }
+exit:
+ printMsg("%s:ret = %d\n", __FUNCTION__, ret);
+ return;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_mutex_init(&printMutex, NULL);
+
+ set_hautil_mode(true);
+ if (init() != 0) {
+ printMsg("could not initiate HAL");
+ return WIFI_ERROR_UNKNOWN;
+ } else {
+ ALOGD("successfully initialized HAL; wlan0 = %p\n", wlan0Handle);
+ }
+
+ sem_init(&event_thread_mutex,0,0);
+
+ pthread_cond_init(&eventCacheCondition, NULL);
+ pthread_mutex_init(&eventCacheMutex, NULL);
+
+ pthread_t tidEvent;
+ pthread_create(&tidEvent, NULL, &eventThreadFunc, NULL);
+ sem_wait(&event_thread_mutex);
+
+ if (argc < 2) {
+ printUsage();
+ goto cleanup;
+ } else if (argv[1][0] != '-') {
+ printUsage();
+ goto cleanup;
+ } else if ((strcmp(argv[1], "-nan") == 0) && (argc < 3)) {
+ printUsage();
+ goto cleanup;
+ }
+ memset(mac_oui, 0, 3);
+ if (strcmp(argv[1], "-nan") == 0) {
+ if ((strcmp(argv[2], "-enable") == 0)) {
+ enableNan(argv);
+ } else if ((strcmp(argv[2], "-disable") == 0)) {
+ disableNan();
+ } else if ((strcmp(argv[2], "-config") == 0)) {
+ configNan(argv);
+ } else if ((strcmp(argv[2], "-publish") == 0)) {
+ if (argc < 4) {
+ printMsg(" -nan [-publish] [-svc <svc_name>] [-info <svc info>\n"
+ " [-pub_type <0/1/2>] [-pub_count <val>] [-rssi_thresh_flag <0/1>]\n"
+ " [-tx_type <0/1>] [-ttl <val>] [-svc_awake_dw <val>]\n"
+ " [-match_rx <0/ascii str>] [-match_tx <0/ascii str>]] [-match_ind <1/2>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>] [-pmk <PMK value>]\n"
+ " [-passphrase <Passphrase value, len must not be less than 8 or greater than 63>]\n"
+ " [-scid <scid value>] [-dp_type <0-Unicast, 1-multicast>]\n"
+ " [-secure_dp <0-No security, 1-Security>] -ranging <0-disable, 1-enable>)\n"
+ " [-ranging_intvl [intrvl in ms betw two ranging measurements] -ranging_ind \n"
+ " [ BIT0 - Continuous Ranging event notification, BIT1 - Ingress distance is <=, BIT2 - Egress distance is >=.]\n"
+ " [-ingress [Ingress distance in centimeters] \n"
+ " [ -egress [Egress distance in centimeters] \n"
+ " [-auto_dp_accept [0 - User response required to accept dp, 1 - User response not required to accept dp] \n"
+ " [-recv_flag <0 to 15>]");
+ printMsg("\n *Set/Enable corresponding bits to disable any indications that follow a publish"
+ "\n *BIT0 - Disable publish termination indication."
+ "\n *BIT1 - Disable match expired indication."
+ "\n *BIT2 - Disable followUp indication received (OTA)");
+ goto cleanup;
+ }
+ publishNan(argc, argv);
+ } else if ((strcmp(argv[2], "-subscribe") == 0)) {
+ if (argc < 3) {
+ printMsg(" -nan [-subscribe] [-svc <svc_name>] [-info <svc info>\n"
+ " [-sub_type <0/1>] [-sub_count <val>] [-pub_ssi <0/1>]\n"
+ " [-ttl <val>] [-svc_awake_dw <val>] [-match_ind <1/2>]\n"
+ " [-match_rx <0/ascii str>] [-match_tx <0/ascii str>]\n"
+ " [-mac_list <addr>] [-srf_include <0/1>] [-rssi_thresh_flag <0/1>]]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>] [-key_type <1 or 2>] [-pmk <PMK value>]\n"
+ " [-passphrase <Passphrase value, len must not be less than 8 or greater than 63>]\n"
+ " [-scid <scid value>] [-dp_type <0-Unicast, 1-multicast>]\n"
+ " [-secure_dp <0-No security, 1-Security>] -ranging <0-disable, 1-enable>)\n"
+ " [-ranging_intvl [intrvl in ms betw two ranging measurements] -ranging_ind \n"
+ " [BIT0 - Continuous Ranging event notification, BIT1 - Ingress distance is <=, BIT2 - Egress distance is >=.]\n"
+ " [-ingress [Ingress distance in centimeters] \n"
+ " [ -egress [Egress distance in centimeters] \n"
+ " [-recv_flag <0 to 7>]");
+ printMsg("\n *Set/Enable corresponding bits to disable any indications that follow a publish"
+ "\n *BIT0 - Disable publish termination indication."
+ "\n *BIT1 - Disable match expired indication."
+ "\n *BIT2 - Disable followUp indication received (OTA)");
+ goto cleanup;
+ }
+ subscribeNan(argc, argv);
+ } else if ((strcmp(argv[2], "-cancel_pub") == 0)) {
+ if(argc < 3) {
+ printMsg(" -nan [-cancel_pub] [<publish id>]\n");
+ goto cleanup;
+ }
+ cancelPublishNan(argv);
+ } else if ((strcmp(argv[2], "-cancel_sub") == 0)) {
+ if(argc < 3) {
+ printMsg(" -nan [-cancel_sub] [<sublish id>]\n");
+ goto cleanup;
+ }
+ cancelSubscribeNan(argv);
+ } else if ((strcmp(argv[2], "-transmit") == 0)) {
+ if(argc < 5) {
+ printMsg(" -nan [-transmit] [-src_id <instance id>] [-dest_id <instance id>]\n"
+ " [-peer_addr <mac addr>] [-info <svc info>]\n");
+ printMsg("\n Mandatory fields are not present\n");
+ goto cleanup;
+ }
+ transmitNan(argc,argv);
+ } else if ((strcmp(argv[2], "-get_capabilities") == 0)) {
+ getNanCapabilities();
+ } else if ((strcmp(argv[2], "-create") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" -nan [-create] [-iface_name <iface name>]\n");
+ goto cleanup;
+ }
+ nanDataPathIfaceCreate(argv);
+ } else if ((strcmp(argv[2], "-delete") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" -nan [-delete] [-iface_name <iface name>]\n");
+ goto cleanup;
+ }
+ nanDataPathIfaceDelete(argv);
+ } else if ((strcmp(argv[2], "-init") == 0)) {
+ if(argc < 7) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" -nan [-init] [-pub_id <pub id>] [-disc_mac <discovery mac addr>]\n"
+ " [-chan <channel in mhz>] [-iface <iface>] [-sec <security>]\n"
+ " [-qos <qos>] [-info <seq of values in the frame body>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>]\n"
+ " [-scid <scid value>] [-svc <svc_name>]\n");
+ goto cleanup;
+ }
+ nanDataInitRequest(argc, argv);
+ } else if ((strcmp(argv[2], "-resp") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" -nan [-resp] [-ndp_id <NDP id>] [-iface <NDP iface name>]\n"
+ " [-resp_code <accept = 0, accept = 1>] [-qos <qos>]\n"
+ " [-info <seq of values in the frame body>]\n"
+ " [-csid <cipher suite type 0/1/2/4/8>]\n"
+ " [-scid <scid value>] [-svc <svc_name>] \n");
+ goto cleanup;
+ }
+ nanDataIndResponse(argc, argv);
+ } else if ((strcmp(argv[2], "-end") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" -nan [-end] [-inst_count <count>] [-inst_id <NDP id>\n");
+ goto cleanup;
+ }
+ nanDataPathEnd(argc, argv);
+ } else if ((strcmp(argv[2], "-event_chk") == 0)) {
+ nanEventCheck();
+ } else if ((strcmp(argv[2], "-ver") == 0)) {
+ nanVersion();
+ } else if ((strcmp(argv[2], "-exit") == 0)) {
+ return WIFI_SUCCESS;
+ } else {
+ printMsg("\n Unknown command\n");
+ printUsage();
+ return WIFI_SUCCESS;
+ }
+ } else if (strcmp(argv[1], "-s") == 0) {
+ readTestOptions(argc, argv);
+ setPnoMacOui();
+ testScan();
+ } else if(strcmp(argv[1], "-swc") == 0){
+ readTestOptions(argc, argv);
+ setPnoMacOui();
+ trackSignificantChange();
+ } else if (strcmp(argv[1], "-ss") == 0) {
+ // Stop scan so clear the OUI too
+ setPnoMacOui();
+ testStopScan();
+ } else if ((strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "-hotlist_bssids") == 0)) {
+ readTestOptions(argc, argv);
+ setPnoMacOui();
+ testHotlistAPs();
+ } else if (strcmp(argv[1], "-stats") == 0) {
+ getLinkStats();
+ } else if (strcmp(argv[1], "-rtt") == 0) {
+ readRTTOptions(argc, ++argv);
+ testRTT();
+ } else if (strcmp(argv[1], "-cancel_rtt") == 0) {
+ cancelRTT();
+ } else if (strcmp(argv[1], "-get_capa_rtt") == 0) {
+ getRTTCapability();
+ } else if ((strcmp(argv[1], "-get_ch_list") == 0)) {
+ readTestOptions(argc, argv);
+ getChannelList();
+ } else if ((strcmp(argv[1], "-get_responder_info") == 0)) {
+ getRttResponderInfo();
+ } else if ((strcmp(argv[1], "-enable_resp") == 0)) {
+ RttEnableResponder();
+ } else if ((strcmp(argv[1], "-cancel_resp") == 0)) {
+ cancelRttResponder();
+ } else if ((strcmp(argv[1], "-get_feature_set") == 0)) {
+ getFeatureSet();
+ } else if ((strcmp(argv[1], "-get_feature_matrix") == 0)) {
+ getFeatureSetMatrix();
+ } else if ((strcmp(argv[1], "-get_wake_stats") == 0)) {
+ getWakeStats();
+ } else if ((strcmp(argv[1], "-scan_mac_oui") == 0)) {
+ readTestOptions(argc, argv);
+ setPnoMacOui();
+ testScan();
+ } else if (strcmp(argv[1], "-nodfs") == 0) {
+ u32 nodfs = 0;
+ if (argc > 2)
+ nodfs = (u32)atoi(argv[2]);
+ hal_fn.wifi_set_nodfs_flag(wlan0Handle, nodfs);
+ } else if ((strcmp(argv[1], "-ePNO") == 0) || (strcmp(argv[1], "-ePNOCfg") == 0)) {
+ memset(&epno_cfg, 0, sizeof(epno_cfg));
+ epno_cfg.min5GHz_rssi = -45;
+ epno_cfg.min24GHz_rssi = -50;
+ epno_cfg.initial_score_max = 110;
+ epno_cfg.num_networks = -1;
+ readTestOptions(argc, argv);
+ epno_cfg.num_networks++;
+ setBlacklist(false);
+ testPNO(false, (strcmp(argv[1], "-ePNO") == 0));
+ if (strcmp(argv[1], "-ePNOCfg") == 0) {
+ printMsg("Cannot close, will cleanup cfg, ctrl+c to exit\n");
+ while (1);
+ }
+ } else if (strcmp(argv[1], "-ePNOClear") == 0) {
+ testPNO(true, false);
+ setBlacklist(true);
+ } else if (strcmp(argv[1], "-country") == 0) {
+ char *country_code = nullptr;
+ if (argc > 2) {
+ country_code = argv[2];
+ } else {
+ printMsg("Country code not provided\n");
+ goto cleanup;
+ }
+ hal_fn.wifi_set_country_code(wlan0Handle, country_code);
+ } else if ((strcmp(argv[1], "-logger") == 0)) {
+ readLoggerOptions(argc, ++argv);
+ runLogger();
+ } else if (strcmp(argv[1], "-help") == 0) {
+ printUsage();
+ } else if ((strcmp(argv[1], "-blacklist_bssids") == 0) ||
+ (strcmp(argv[1], "-whitelist_ssids") == 0)) {
+ readTestOptions(argc, argv);
+ if (set_roaming_configuration) {
+ setRoamingConfiguration();
+ set_roaming_configuration = false;
+ } else {
+ setBlacklist(((num_blacklist_bssids == -1) ? true: false));
+ }
+ } else if ((strcmp(argv[1], "-get_roaming_capabilities") == 0)) {
+ getRoamingCapabilities();
+ } else if ((strcmp(argv[1], "-set_fw_roaming_state") == 0)) {
+ fw_roaming_state_t roamState = (fw_roaming_state_t)(atoi)(argv[2]);
+ setFWRoamingState(roamState);
+ } else if (strcmp(argv[1], "-rssi_monitor") == 0) {
+ readTestOptions(argc, argv);
+ testRssiMonitor();
+ } else if (strcmp(argv[1], "-mkeep_alive") == 0) {
+ readKeepAliveOptions(argc, ++argv);
+ } else if ((strcmp(argv[1], "-nd_offload") == 0) && (argc > 2)) {
+ u8 enable = (u8)(atoi)(argv[2]);
+ hal_fn.wifi_configure_nd_offload(wlan0Handle, enable);
+ } else if ((strcmp(argv[1], "-apf") == 0)) {
+ testApfOptions(argc, ++argv);
+ } else if ((strcmp(argv[1], "-sar") == 0)) {
+ testSarOptions(argc-1, ++argv);
+ } else if ((strcmp(argv[1], "-latency") == 0)) {
+ testLatencyModeOptions(argc-1, ++argv);
+ } else if ((strcmp(argv[1], "-thermal") == 0)) {
+ testThermalMitigationOptions(argc-1, ++argv);
+ } else if ((strcmp(argv[1], "-dscp") == 0)) {
+ testDscpOptions(argc, ++argv);
+ } else if ((strcmp(argv[1], "-ch_avoid") == 0)) {
+ testChannelAvoidanceOptions(argc, ++argv);
+ } else if ((strcmp(argv[1], "-usable_ch") == 0)) {
+ testUsableChannelOptions(argc, ++argv);
+ } else if ((strcmp(argv[1], "-ifadd") == 0)) {
+ if (argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg(" [-ifadd] [-name <virtual iface name should be wlanX, swlanX, awareX, p2pX>"
+ " -type 0/1/2/3]\n");
+ printMsg(" 0 for STA, 1 for AP, 2 for P2P, 3 for NAN\n");
+ goto cleanup;
+ }
+ VirtualIfaceAdd(argv);
+ } else if ((strcmp(argv[1], "-ifdel") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg("[-ifdel] [-name <virtual iface name>]\n");
+ goto cleanup;
+ }
+ VirtualIfaceDelete(argv);
+ } else if ((strcmp(argv[1], "-latency_mode") == 0) && (argc > 2)) {
+ SetLatencyMode(argv);
+ } else if ((strcmp(argv[1], "-multista_pri_connection") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg("[-multista_pri_connection] [iface name>]\n");
+ goto cleanup;
+ }
+ MultiStaSetPrimaryConnection(argv);
+ } else if ((strcmp(argv[1], "-multista_usecase") == 0)) {
+ if(argc < 3) {
+ printMsg("\n Mandatory fields are not present\n");
+ printMsg("[-multista_usecase] [multista usecase 0/1]\n");
+ goto cleanup;
+ }
+ MultiStaSetUsecase(argv);
+ } else if ((strcmp(argv[1], "-voip_mode") == 0) && (argc > 2)) {
+ SetVoipMode(argv);
+ } else if (strcmp(argv[1], "-twt") == 0) {
+ if ((strcmp(argv[2], "-setup") == 0)) {
+ setupTwtRequest(argv);
+ } else if ((strcmp(argv[2], "-teardown") == 0)) {
+ TeardownTwt(argv);
+ } else if ((strcmp(argv[2], "-info_frame") == 0)) {
+ InfoFrameTwt(argv);
+ } else if ((strcmp(argv[2], "-get_stats") == 0)) {
+ GetTwtStats(argv);
+ } else if ((strcmp(argv[2], "-clear_stats") == 0)) {
+ ClearTwtStats(argv);
+ } else if ((strcmp(argv[2], "-event_chk") == 0)) {
+ twtEventCheck();
+ } else {
+ printMsg("\n Unknown command\n");
+ printTwtUsage();
+ return WIFI_SUCCESS;
+ }
+ } else if (strcmp(argv[1], "-get_capa_twt") == 0) {
+ getTWTCapability();
+ } else if ((strcmp(argv[1], "-dtim_multiplier") == 0) && (argc > 2)) {
+ int dtim_multiplier = (atoi)(argv[2]);
+ hal_fn.wifi_set_dtim_config(wlan0Handle, dtim_multiplier);
+ } else if (strcmp(argv[1], "-on_ssr") == 0) {
+ hal_fn.wifi_trigger_subsystem_restart(halHandle);
+ } else if ((strcmp(argv[1], "-getSupportedRadioMatrix") == 0)) {
+ getSupportedRadioMatrix();
+ } else if ((strcmp(argv[1], "-tx_pwr_cap") == 0)) {
+ testTxPowerLimitOptions(argc, ++argv);
+ } else if (strcmp(argv[1], "-chre_nan_rtt") == 0) {
+ if ((strcmp(argv[2], "-enable") == 0)) {
+ //enable CHRE NAN RTT
+ enableChreNanRtt();
+ } else if ((strcmp(argv[2], "-disable") == 0)) {
+ //disable CHRE NAN RTT
+ disableChreNanRtt();
+ } else {
+ printMsg("\n Unknown command\n");
+ printChreNanRttUsage();
+ }
+ } else if (strcmp(argv[1], "-chre") == 0) {
+ if ((strcmp(argv[2], "-register") == 0)) {
+ //register CHRE callback
+ registerChreCallback();
+ } else {
+ printMsg("\n Unknown command\n");
+ printChreNanRttUsage();
+ }
+ } else if (strcmp(argv[1], "-get_cached_scan_results") == 0) {
+ getWifiCachedScanResults();
+ } else if (strcmp(argv[1], "-set_channel_mask") == 0) {
+ u32 channel_mask = 0;
+ if (argc > 2) {
+ channel_mask = (u32)atoi(argv[2]);
+ }
+ hal_fn.wifi_enable_sta_channel_for_peer_network(halHandle, channel_mask);
+ } else {
+ printUsage();
+ }
+
+cleanup:
+ cleanup();
+ return WIFI_SUCCESS;
+}
diff --git a/bcmdhd/halutil/wifi_hal_stub.cpp b/bcmdhd/halutil/wifi_hal_stub.cpp
new file mode 100644
index 0000000..65a2aff
--- /dev/null
+++ b/bcmdhd/halutil/wifi_hal_stub.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#ifndef ANDROID
+#include <stddef.h>
+#endif
+#include "wifi_hal.h"
+#include "wifi_hal_stub.h"
+
+wifi_error wifi_initialize_stub(wifi_handle *handle) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+void wifi_cleanup_stub(wifi_handle handle, wifi_cleaned_up_handler handler) {
+}
+
+void wifi_event_loop_stub(wifi_handle handle) {
+
+}
+
+void wifi_get_error_info_stub(wifi_error err, const char **msg) {
+ *msg = NULL;
+}
+
+wifi_error wifi_get_supported_feature_set_stub(wifi_interface_handle handle, feature_set *set) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_concurrency_matrix_stub(wifi_interface_handle handle, int max_size,
+ feature_set *matrix, int *size) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_set_scanning_mac_oui_stub(wifi_interface_handle handle, unsigned char *oui_data) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+/* List of all supported channels, including 5GHz channels */
+wifi_error wifi_get_supported_channels_stub(wifi_handle handle, int *size, wifi_channel *list) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+/* Enhanced power reporting */
+wifi_error wifi_is_epr_supported_stub(wifi_handle handle) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+/* multiple interface support */
+wifi_error wifi_get_ifaces_stub(wifi_handle handle, int *num_ifaces, wifi_interface_handle **ifaces) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_iface_name_stub(wifi_interface_handle iface, char *name, size_t size) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_set_iface_event_handler_stub(wifi_request_id id,
+ wifi_interface_handle iface, wifi_event_handler eh) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_reset_iface_event_handler_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_start_gscan_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_scan_cmd_params params, wifi_scan_result_handler handler) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_stop_gscan_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_cached_gscan_results_stub(wifi_interface_handle iface, byte flush,
+ int max, wifi_cached_scan_results *results, int *num) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_set_bssid_hotlist_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_reset_bssid_hotlist_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_set_significant_change_handler_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_significant_change_params params, wifi_significant_change_handler handler) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_reset_significant_change_handler_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_gscan_capabilities_stub(wifi_interface_handle handle,
+ wifi_gscan_capabilities *capabilities) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_set_link_stats_stub(wifi_interface_handle iface, wifi_link_layer_params params) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_link_stats_stub(wifi_request_id id,
+ wifi_interface_handle iface, wifi_stats_result_handler handler) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_clear_link_stats_stub(wifi_interface_handle iface,
+ u32 stats_clear_req_mask, u32 *stats_clear_rsp_mask, u8 stop_req, u8 *stop_rsp) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+wifi_error wifi_get_valid_channels_stub(wifi_interface_handle handle,
+ int band, int max_channels, wifi_channel *channels, int *num_channels) {
+ return WIFI_ERROR_UNINITIALIZED;
+}
+
+/* API to request RTT measurement */
+wifi_error wifi_rtt_range_request_stub(wifi_request_id id, wifi_interface_handle iface,
+ unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+/* API to cancel RTT measurements */
+wifi_error wifi_rtt_range_cancel_stub(wifi_request_id id, wifi_interface_handle iface,
+ unsigned num_devices, mac_addr addr[]) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+/* API to get RTT capability */
+wifi_error wifi_get_rtt_capabilities_stub(wifi_interface_handle iface,
+ wifi_rtt_capabilities *capabilities)
+{
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+/* API to enable RTT responder role */
+wifi_error wifi_enable_responder_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_channel_info channel_hint, unsigned max_duration_seconds,
+ wifi_channel_info* channel_used) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+/* API to disable RTT responder role */
+wifi_error wifi_disable_responder_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+/* API to get available channel for RTT responder role */
+wifi_error wifi_rtt_get_available_channel_stub(wifi_interface_handle iface, wifi_channel_info* channel) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_nodfs_flag_stub(wifi_interface_handle iface, u32 nodfs) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_start_logging_stub(wifi_interface_handle iface, u32 verbose_level, u32 flags,
+ u32 max_interval_sec, u32 min_data_size, char *buffer_name) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_epno_list_stub(int id, wifi_interface_info *iface,
+ const wifi_epno_params *params, wifi_epno_handler handler) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_reset_epno_list_stub(int id, wifi_interface_info *iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_country_code_stub(wifi_interface_handle iface, const char *code) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_firmware_memory_dump_stub( wifi_interface_handle iface,
+ wifi_firmware_memory_dump_handler handler){
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_log_handler_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler handler) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_reset_log_handler_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_alert_handler_stub(wifi_request_id id, wifi_interface_handle iface,
+ wifi_alert_handler handler) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_reset_alert_handler_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_firmware_version_stub( wifi_interface_handle iface, char *buffer,
+ int buffer_size) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_ring_buffers_status_stub(wifi_interface_handle iface,
+ u32 *num_rings, wifi_ring_buffer_status *status) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_logger_supported_feature_set_stub(wifi_interface_handle iface,
+ unsigned int *support) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_ring_data_stub(wifi_interface_handle iface, char *ring_name) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_driver_version_stub(wifi_interface_handle iface, char *buffer,
+ int buffer_size) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_enable_tdls_stub(wifi_interface_handle iface, mac_addr addr,
+ wifi_tdls_params *params, wifi_tdls_handler handler) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_disable_tdls_stub(wifi_interface_handle iface, mac_addr addr) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_tdls_status_stub(wifi_interface_handle iface, mac_addr addr,
+ wifi_tdls_status *status) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_tdls_capabilities_stub(wifi_interface_handle iface,
+ wifi_tdls_capabilities *capabilities) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+
+wifi_error wifi_configure_roaming_stub(wifi_interface_handle handle,
+ wifi_roaming_config *roam_config) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_roaming_capabilities_stub(wifi_interface_handle handle,
+ wifi_roaming_capabilities *caps) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_firmware_roaming_state_stub(wifi_interface_handle handle,
+ fw_roaming_state_t state) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_start_sending_offloaded_packet_stub(wifi_request_id id,
+ wifi_interface_handle iface, u16 ether_type, u8 *ip_packet, u16 ip_packet_len,
+ u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_stop_sending_offloaded_packet_stub(wifi_request_id id, wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_wake_reason_stats_stub(wifi_interface_handle iface,
+ WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_configure_nd_offload_stub(wifi_interface_handle iface, u8 enable) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_driver_memory_dump_stub(wifi_interface_handle iface,
+ wifi_driver_memory_dump_callbacks callbacks) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_start_pkt_fate_monitoring_stub(wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_tx_pkt_fates_stub(wifi_interface_handle handle,
+ wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_rx_pkt_fates_stub(wifi_interface_handle handle,
+ wifi_rx_report *rx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+wifi_error wifi_nan_enable_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanEnableRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_disable_request_stub(transaction_id id,
+ wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_publish_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanPublishRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_publish_cancel_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanPublishCancelRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_subscribe_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanSubscribeRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_subscribe_cancel_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanSubscribeCancelRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_transmit_followup_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanTransmitFollowupRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_stats_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanStatsRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_config_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanConfigRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_tca_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanTCARequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_beacon_sdf_payload_request_stub(transaction_id id,
+ wifi_interface_handle iface,
+ NanBeaconSdfPayloadRequest* msg) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_register_handler_stub(wifi_interface_handle iface,
+ NanCallbackHandler handlers) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_get_version_stub(wifi_handle handle,
+ NanVersion* version) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_nan_get_capabilities_stub(transaction_id id,
+ wifi_interface_handle iface) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_get_packet_filter_capabilities_stub(wifi_interface_handle handle,
+ u32 *version, u32 *max_len) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_set_packet_filter_stub(wifi_interface_handle handle,
+ const u8 *program, u32 len) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error wifi_enable_firmware_roaming_stub(wifi_interface_handle iface,
+ fw_roaming_state_t state) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+int init_wifi_stub_hal_func_table(wifi_hal_fn *hal_fn) {
+ if (hal_fn == NULL) {
+ return -1;
+ }
+ hal_fn->wifi_initialize = wifi_initialize_stub;
+ hal_fn->wifi_cleanup = wifi_cleanup_stub;
+ hal_fn->wifi_event_loop = wifi_event_loop_stub;
+ hal_fn->wifi_get_error_info = wifi_get_error_info_stub;
+ hal_fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set_stub;
+ hal_fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix_stub;
+ hal_fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui_stub;
+ hal_fn->wifi_get_supported_channels = wifi_get_supported_channels_stub;
+ hal_fn->wifi_is_epr_supported = wifi_is_epr_supported_stub;
+ hal_fn->wifi_get_ifaces = wifi_get_ifaces_stub;
+ hal_fn->wifi_get_iface_name = wifi_get_iface_name_stub;
+ hal_fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler_stub;
+ hal_fn->wifi_start_gscan = wifi_start_gscan_stub;
+ hal_fn->wifi_stop_gscan = wifi_stop_gscan_stub;
+ hal_fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results_stub;
+ hal_fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist_stub;
+ hal_fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist_stub;
+ hal_fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler_stub;
+ hal_fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler_stub;
+ hal_fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities_stub;
+ hal_fn->wifi_set_link_stats = wifi_set_link_stats_stub;
+ hal_fn->wifi_get_link_stats = wifi_get_link_stats_stub;
+ hal_fn->wifi_clear_link_stats = wifi_clear_link_stats_stub;
+ hal_fn->wifi_get_valid_channels = wifi_get_valid_channels_stub;
+ hal_fn->wifi_rtt_range_request = wifi_rtt_range_request_stub;
+ hal_fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel_stub;
+ hal_fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities_stub;
+ hal_fn->wifi_start_logging = wifi_start_logging_stub;
+ hal_fn->wifi_set_epno_list = wifi_set_epno_list_stub;
+ hal_fn->wifi_set_country_code = wifi_set_country_code_stub;
+ hal_fn->wifi_enable_tdls = wifi_enable_tdls_stub;
+ hal_fn->wifi_disable_tdls = wifi_disable_tdls_stub;
+ hal_fn->wifi_get_tdls_status = wifi_get_tdls_status_stub;
+ hal_fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities_stub;
+ hal_fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag_stub;
+ hal_fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump_stub;
+ hal_fn->wifi_set_log_handler = wifi_set_log_handler_stub;
+ hal_fn->wifi_reset_log_handler = wifi_reset_log_handler_stub;
+ hal_fn->wifi_set_alert_handler = wifi_set_alert_handler_stub;
+ hal_fn->wifi_reset_alert_handler = wifi_reset_alert_handler_stub;
+ hal_fn->wifi_get_firmware_version = wifi_get_firmware_version_stub;
+ hal_fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_stub;
+ hal_fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_stub;
+ hal_fn->wifi_get_ring_data = wifi_get_ring_data_stub;
+ hal_fn->wifi_get_driver_version = wifi_get_driver_version_stub;
+ hal_fn->wifi_configure_roaming = wifi_configure_roaming_stub;
+ hal_fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities_stub;
+ hal_fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet_stub;
+ hal_fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet_stub;
+ hal_fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats_stub;
+ hal_fn->wifi_configure_nd_offload = wifi_configure_nd_offload_stub;
+ hal_fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump_stub;
+ hal_fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring_stub;
+ hal_fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates_stub;
+ hal_fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates_stub;
+ hal_fn->wifi_nan_enable_request = wifi_nan_enable_request_stub;
+ hal_fn->wifi_nan_disable_request = wifi_nan_disable_request_stub;
+ hal_fn->wifi_nan_publish_request = wifi_nan_publish_request_stub;
+ hal_fn->wifi_nan_publish_cancel_request = wifi_nan_publish_cancel_request_stub;
+ hal_fn->wifi_nan_subscribe_request = wifi_nan_subscribe_request_stub;
+ hal_fn->wifi_nan_subscribe_cancel_request = wifi_nan_subscribe_cancel_request_stub;
+ hal_fn->wifi_nan_transmit_followup_request = wifi_nan_transmit_followup_request_stub;
+ hal_fn->wifi_nan_stats_request = wifi_nan_stats_request_stub;
+ hal_fn->wifi_nan_config_request = wifi_nan_config_request_stub;
+ hal_fn->wifi_nan_tca_request = wifi_nan_tca_request_stub;
+ hal_fn->wifi_nan_beacon_sdf_payload_request = wifi_nan_beacon_sdf_payload_request_stub;
+ hal_fn->wifi_nan_register_handler = wifi_nan_register_handler_stub;
+ hal_fn->wifi_nan_get_version = wifi_nan_get_version_stub;
+ hal_fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_stub;
+ hal_fn->wifi_set_packet_filter = wifi_set_packet_filter_stub;
+ hal_fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming_stub;
+ hal_fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
+ hal_fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+ hal_fn->wifi_get_supported_radio_combinations_matrix =
+ wifi_get_supported_radio_combinations_matrix;
+
+ return 0;
+}
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
index 1a55aac..7f164ab 100755
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index b54fbb1..acb649f 100644
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,10 +56,13 @@ const uint32_t BRCM_OUI = 0x001018;
#define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
#define NAN_MASTER_RANK_LEN 8
#define NAN_SCID_INFO_LEN 16
+#define NAN_MAX_NDP_PEER 8u
+#define NAN_MAX_NDP_COUNT_SIZE NAN_MAX_NDP_PEER * sizeof(NanDataPathId)
#define SAR_CONFIG_SCENARIO_COUNT 100
#define MAX_NUM_RADIOS 3
#define MAX_CMD_RESP_BUF_LEN 8192
+#define MAX_MLO_LINK 3
/*
This enum defines ranges for various commands; commands themselves
@@ -215,6 +218,8 @@ typedef enum {
NAN_SUBCMD_DATA_PATH_SEC_INFO, /* 0x1710 */
NAN_SUBCMD_VERSION_INFO, /* 0x1711 */
NAN_SUBCMD_ENABLE_MERGE, /* 0x1712 */
+ NAN_SUBCMD_SUSPEND, /* 0x1713 */
+ NAN_SUBCMD_RESUME, /* 0x1714 */
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
APF_SUBCMD_READ_FILTER,
@@ -286,7 +291,8 @@ typedef enum {
NAN_ASYNC_RESPONSE_DISABLED = 40,
BRCM_VENDOR_EVENT_TWT = 43,
BRCM_TPUT_DUMP_EVENT = 44,
- NAN_EVENT_MATCH_EXPIRY = 45
+ NAN_EVENT_MATCH_EXPIRY = 45,
+ NAN_EVENT_SUSPENSION_STATUS = 49
} WIFI_EVENT;
typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp
index fa120e7..8ef0ca8 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.cpp
+++ b/bcmdhd/wifi_hal/cpp_bindings.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -653,8 +653,15 @@ int WifiCommand::requestResponse(WifiRequest& request) {
int err = 0;
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!cb)
+ if (!cb) {
+ ALOGE("nl80211: cb alloc failed");
goto out;
+ }
+
+ if (!mInfo->cmd_sock) {
+ ALOGE("cmd_sock is already freed mInfo:%p mIfaceInfo:%p\n", mInfo, mIfaceInfo);
+ goto out;
+ }
err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* send message */
if (err < 0)
diff --git a/bcmdhd/wifi_hal/cpp_bindings.h b/bcmdhd/wifi_hal/cpp_bindings.h
index cc1c662..69b699c 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.h
+++ b/bcmdhd/wifi_hal/cpp_bindings.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
index 19bab2b..eaddc53 100755
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 05ab438..c17b3b8 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,8 @@ typedef enum {
ANDR_WIFI_ATTRIBUTE_INVALID = 0,
ANDR_WIFI_ATTRIBUTE_NUM_RADIO = 1,
ANDR_WIFI_ATTRIBUTE_STATS_INFO = 2,
- ANDR_WIFI_ATTRIBUTE_STATS_MAX = 3
+ ANDR_WIFI_ATTRIBUTE_ML_STATS_INFO = 3,
+ ANDR_WIFI_ATTRIBUTE_STATS_MAX = 4
} LINK_STAT_ATTRIBUTE;
/* Internal radio statistics structure in the driver */
@@ -92,12 +93,15 @@ public:
protected:
virtual int handleResponse(WifiEvent& reply) {
- void *data = NULL;
+ bool ml_data = false;
wifi_radio_stat *radio_stat_ptr = NULL;
- u8 *iface_stat = NULL;
- u8 *radioStatsBuf = NULL, *output = NULL, *data_ptr = NULL;
- uint32_t total_size = 0, per_radio_size = 0, data_len = 0, rem_len = 0;
- int num_radios = 0, id = 0, subcmd = 0, len = 0;
+ wifi_iface_ml_stat *iface_ml_stat_ptr = NULL;
+ u8 *radioStatsBuf = NULL, *ifaceMlStatsBuf = NULL, *outbuf = NULL, *data_ptr = NULL;
+ u8 *data = NULL, *iface_stat = NULL;
+ uint32_t offset = 0, per_radio_size = 0, data_len = 0, outbuf_rem_len = 0, data_rem_len = 0;
+ int ret = 0, num_radios = 0, id = 0, subcmd = 0, len = 0;
+ u32 fixed_iface_ml_stat_size = 0, all_links_stat_size = 0;
+ u8 num_links = 0;
ALOGI("In GetLinkStatsCommand::handleResponse");
@@ -121,38 +125,41 @@ protected:
if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_RADIO) {
num_radios = it.get_u32();
} else if (it.get_type() == ANDR_WIFI_ATTRIBUTE_STATS_INFO) {
- data = it.get_data();
+ data = (u8 *)it.get_data();
data_len = it.get_len();
+ } else if (it.get_type() == ANDR_WIFI_ATTRIBUTE_ML_STATS_INFO) {
+ data = (u8 *)it.get_data();
+ data_len = it.get_len();
+ ml_data = true;
} else {
- ALOGW("Ignoring invalid attribute type = %d, size = %d\n",
+ ALOGW("Ignoring invalid attribute type = %d, size = %d",
it.get_type(), it.get_len());
- return NL_SKIP;
}
}
if (num_radios) {
- if (!data || !data_len) {
- ALOGE("%s: null data\n", __func__);
- return NL_SKIP;
- }
-
- rem_len = MAX_CMD_RESP_BUF_LEN;
+ outbuf_rem_len = MAX_CMD_RESP_BUF_LEN;
radioStatsBuf = (u8 *)malloc(MAX_CMD_RESP_BUF_LEN);
if (!radioStatsBuf) {
ALOGE("No memory\n");
return NL_SKIP;
}
memset(radioStatsBuf, 0, MAX_CMD_RESP_BUF_LEN);
- output = radioStatsBuf;
+ outbuf = radioStatsBuf;
- data_ptr = (u8*)data;
+ if (!data || !data_len) {
+ ALOGE("%s: null data\n", __func__);
+ goto exit;
+ }
+ data_ptr = data;
for (int i = 0; i < num_radios; i++) {
- rem_len -= per_radio_size;
- if (rem_len < per_radio_size) {
+ outbuf_rem_len -= per_radio_size;
+ if (outbuf_rem_len < per_radio_size) {
ALOGE("No data left for radio %d\n", i);
goto exit;
}
- data_ptr = (u8*)data + total_size;
+
+ data_ptr = data + offset;
if (!data_ptr) {
ALOGE("Invalid data for radio index = %d\n", i);
goto exit;
@@ -161,40 +168,115 @@ protected:
convertToExternalRadioStatStructure((wifi_radio_stat*)data_ptr,
&per_radio_size);
if (!radio_stat_ptr || !per_radio_size) {
- if (radio_stat_ptr) {
- free(radio_stat_ptr);
- radio_stat_ptr = NULL;
- }
ALOGE("No data for radio %d\n", i);
continue;
}
- memcpy(output, radio_stat_ptr, per_radio_size);
- output += per_radio_size;
- total_size += per_radio_size;
- free(radio_stat_ptr);
- radio_stat_ptr = NULL;
+ memcpy(outbuf, radio_stat_ptr, per_radio_size);
+ outbuf += per_radio_size;
+ /* Accounted size of all the radio data len */
+ offset += per_radio_size;
}
- iface_stat = ((u8*)data + total_size);
- if (!iface_stat || data_len < total_size) {
- ALOGE("No data for iface stats!!, data_len = %d, total_size = %d\n",
- data_len, total_size);
+ if (ml_data) {
+ outbuf = NULL;
+ data_rem_len = data_len - offset;
+ fixed_iface_ml_stat_size = offsetof(wifi_iface_ml_stat, links);
+
+ /* Allocate vendor hal buffer, instead of using the nlmsg allocated buffer */
+ ifaceMlStatsBuf = (u8 *)malloc(MAX_CMD_RESP_BUF_LEN);
+ if (!ifaceMlStatsBuf) {
+ ALOGE("No memory\n");
+ goto exit;
+ }
+ outbuf_rem_len = MAX_CMD_RESP_BUF_LEN;
+ memset(ifaceMlStatsBuf, 0, MAX_CMD_RESP_BUF_LEN);
+ outbuf = ifaceMlStatsBuf;
+
+ if (data_rem_len >= fixed_iface_ml_stat_size) {
+ data_ptr = (data + offset);
+ if (!data_ptr) {
+ ALOGE("No iface ml stats fixed data!!, data_len = %d, offset = %d\n",
+ data_len, offset);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ if (outbuf_rem_len < fixed_iface_ml_stat_size) {
+ ALOGE("No space to copy fixed iface ml stats!, rem_len %d, req_len %d\n",
+ outbuf_rem_len, fixed_iface_ml_stat_size);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ memcpy(outbuf, data_ptr, fixed_iface_ml_stat_size);
+ data_rem_len -= fixed_iface_ml_stat_size;
+ outbuf_rem_len -= fixed_iface_ml_stat_size;
+ outbuf += fixed_iface_ml_stat_size;
+ offset += fixed_iface_ml_stat_size;
+
+ iface_ml_stat_ptr = (wifi_iface_ml_stat *)ifaceMlStatsBuf;
+ if (!iface_ml_stat_ptr) {
+ ALOGE("No iface ml stats data!!");
+ goto exit;
+ }
+
+ num_links = iface_ml_stat_ptr->num_links;
+ all_links_stat_size = (num_links * offsetof(wifi_link_stat, peer_info));
+
+ if (num_links >= MAX_MLO_LINK) {
+ ALOGE("Invalid num links :%d\n", num_links);
+ goto exit;
+ }
+ if (num_links && (data_rem_len >= all_links_stat_size)) {
+ ret = convertToExternalIfaceMlstatStructure(&data, &offset, &outbuf,
+ &data_rem_len, num_links, &outbuf_rem_len);
+ if (ret < 0) {
+ ALOGE(("Failed to map data to iface ml struct\n"));
+ goto exit;
+ }
+ } else {
+ ALOGE("num_links %d, Required data not found: expected len %d,"
+ " data_rem_len %d\n", num_links, all_links_stat_size, data_rem_len);
+ }
+ (*mHandler.on_multi_link_stats_results)(id,
+ (wifi_iface_ml_stat *)ifaceMlStatsBuf, num_radios,
+ (wifi_radio_stat *)radioStatsBuf);
+ }
+ } else if ((data_len >= (offset + sizeof(wifi_iface_stat)))) {
+ iface_stat = (data + offset);
+ if (!iface_stat) {
+ ALOGE("No data for legacy iface stats!!, data_len = %d, offset = %d\n",
+ data_len, offset);
+ goto exit;
+ }
+ (*mHandler.on_link_stats_results)(id, (wifi_iface_stat *)iface_stat,
+ num_radios, (wifi_radio_stat *)radioStatsBuf);
+ } else {
+ ALOGE("No data for iface stats!!, data_len = %d, offset = %d\n",
+ data_len, offset);
goto exit;
}
- (*mHandler.on_link_stats_results)(id, (wifi_iface_stat *)iface_stat,
- num_radios, (wifi_radio_stat *)radioStatsBuf);
}
exit:
+ if (radio_stat_ptr) {
+ free(radio_stat_ptr);
+ radio_stat_ptr = NULL;
+ }
if (radioStatsBuf) {
free(radioStatsBuf);
radioStatsBuf = NULL;
}
+ if (ifaceMlStatsBuf) {
+ free(ifaceMlStatsBuf);
+ ifaceMlStatsBuf = NULL;
+ }
return NL_OK;
}
private:
wifi_radio_stat *convertToExternalRadioStatStructure(wifi_radio_stat *internal_stat_ptr,
- uint32_t *per_radio_size) {
+ uint32_t *per_radio_size)
+ {
wifi_radio_stat *external_stat_ptr = NULL;
if (!internal_stat_ptr) {
ALOGE("Incoming data is null\n");
@@ -224,6 +306,187 @@ private:
}
return external_stat_ptr;
}
+
+ int convertToExternalRatestatsStructure(u8 **data, u32 *offset, u8 **outbuf,
+ u32 *data_rem_len, wifi_peer_info *peer_info, u8 num_rate, u32 *outbuf_rem_len)
+ {
+ u8 k = 0, num_peers = 0;
+ int ret = 0;
+ u8 *data_ptr = NULL;
+ u32 all_rates_size = 0, per_rate_size = 0;
+
+ per_rate_size = sizeof(wifi_rate_stat);
+ all_rates_size = num_rate * per_rate_size;
+ if (!peer_info && (*data_rem_len != all_rates_size)) {
+ ALOGE("Insufficient data for rate_stats, data_rem_len %d,"
+ "required data size %d \n", *data_rem_len, all_rates_size);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ for (k = 0; k < num_rate; k++) {
+ data_ptr = ((*data) + (*offset));
+ if (!data_ptr) {
+ ALOGE("rate_stats not found!! num_rate %d, *data_rem_len = %d, *offset = %d\n",
+ num_rate, *data_rem_len, *offset);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ if (*data_rem_len < per_rate_size) {
+ ALOGE("no rate_stats!!, data_rem_len %d, rate_stat size %d\n",
+ *data_rem_len, per_rate_size);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ if (*outbuf_rem_len < per_rate_size) {
+ ALOGE("No space to copy rate_stats of index [%d]!, rem_len %d, req_len %d\n",
+ k, *outbuf_rem_len, per_rate_size);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ memcpy(*outbuf, data_ptr, per_rate_size);
+ *data_rem_len -= per_rate_size;
+ *outbuf_rem_len -= per_rate_size;
+ *outbuf += per_rate_size;
+ *offset += per_rate_size;
+ }
+ exit:
+ return ret;
+ }
+
+ int convertToExternalIfaceLinkstatStructure(u8 **data, uint32_t *offset, u8 **outbuf,
+ u32 *data_rem_len, u8 num_peers, wifi_link_stat *links, u32 *outbuf_rem_len)
+ {
+ int ret = 0, j = 0, num_rate = 0;
+ u32 all_rate_stats_per_peer_per_link_size = 0, fixed_peer_info_size = 0;
+ u8 *data_ptr = NULL;
+ wifi_peer_info *peer_info_ptr = NULL;
+
+ for (j = 0; j < num_peers; j++) {
+ data_ptr = ((*data) + (*offset));
+ if (!data_ptr || (!*data_rem_len)) {
+ ALOGE("no peer_info data!! num_peers %d, data_rem_len = %d, *offset = %d\n",
+ num_peers, *data_rem_len, *offset);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ fixed_peer_info_size = offsetof(wifi_peer_info, rate_stats);
+ if (*data_rem_len < fixed_peer_info_size) {
+ ALOGE("no fixed peer_info data!!, data_rem_len %d, fixed peer info %d\n",
+ *data_rem_len, fixed_peer_info_size);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ if (*outbuf_rem_len < fixed_peer_info_size) {
+ ALOGE("No space to copy fixed peer_info of index[%d]!, rem_len %d, req_len %d\n",
+ j, *outbuf_rem_len, fixed_peer_info_size);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ memcpy(*outbuf, data_ptr, fixed_peer_info_size);
+ *data_rem_len -= fixed_peer_info_size;
+ *outbuf_rem_len -= fixed_peer_info_size;
+ *outbuf += fixed_peer_info_size;
+ *offset += fixed_peer_info_size;
+
+ peer_info_ptr = (wifi_peer_info *)data_ptr;
+ if (!peer_info_ptr) {
+ ALOGE("no peer_info data!!");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ num_rate = peer_info_ptr->num_rate;
+ all_rate_stats_per_peer_per_link_size = num_rate*sizeof(wifi_rate_stat);
+ if (num_rate && (*data_rem_len >= all_rate_stats_per_peer_per_link_size)) {
+ ret = convertToExternalRatestatsStructure(data, offset, outbuf, data_rem_len,
+ peer_info_ptr, num_rate, outbuf_rem_len);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE(("Failed to convert it to rate stats\n"));
+ goto exit;
+ }
+ } else {
+ ALOGI("num_rate %d, Required rate_stats not found: expected len %d,"
+ " data_rem_len %d\n", num_rate, all_rate_stats_per_peer_per_link_size,
+ *data_rem_len);
+ continue;
+ }
+ }
+
+ exit:
+ return ret;
+ }
+
+ int convertToExternalIfaceMlstatStructure(u8 **data, u32 *offset, u8 **outbuf,
+ u32 *data_rem_len, u8 num_links, u32 *outbuf_rem_len)
+ {
+ int ret = 0, i = 0;
+ u32 all_peers_per_link_size = 0, fixed_link_stat_size = 0;
+ u8 *data_ptr = NULL;
+ u8 num_peers = 0;
+ wifi_link_stat *links_ptr = NULL;
+
+ for (i = 0; i < num_links; i++) {
+ data_ptr = ((*data) + (*offset));
+ if (!data_ptr || !(*data_rem_len)) {
+ ALOGE("no variable links data!! num_links %d, data_rem_len = %d, offset = %d\n",
+ num_links, *data_rem_len, *offset);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ fixed_link_stat_size = offsetof(wifi_link_stat, peer_info);
+ if (*data_rem_len < fixed_link_stat_size) {
+ ALOGE("no fixed wifi_link_stat data!!, data_rem_len %d, fixed link stat data %d\n",
+ *data_rem_len, fixed_link_stat_size);
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ if (*outbuf_rem_len < fixed_link_stat_size) {
+ ALOGE("No space to copy fixed link stats of index[%d]!, rem_len %d, req_len %d\n",
+ i, *outbuf_rem_len, fixed_link_stat_size);
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ memcpy(*outbuf, data_ptr, fixed_link_stat_size);
+ *outbuf_rem_len -= fixed_link_stat_size;
+ *data_rem_len -= fixed_link_stat_size;
+ *outbuf += fixed_link_stat_size;
+ *offset += fixed_link_stat_size;
+
+ links_ptr = (wifi_link_stat *)data_ptr;
+ if (!links_ptr) {
+ ALOGE("no link_stat data!!");
+ ret = WIFI_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ num_peers = links_ptr->num_peers;
+ all_peers_per_link_size = num_peers * offsetof(wifi_peer_info, rate_stats);
+ if (num_peers && (*data_rem_len >= all_peers_per_link_size)) {
+ ret = convertToExternalIfaceLinkstatStructure(data, offset, outbuf,
+ data_rem_len, num_peers, links_ptr, outbuf_rem_len);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE(("Failed to convert it to iface link stats\n"));
+ goto exit;
+ }
+ } else {
+ ALOGI("num_peers %d, Required data not found: expected len %d, data_rem_len %d\n",
+ num_peers, all_peers_per_link_size, *data_rem_len);
+ continue;
+ }
+ }
+ exit:
+ return ret;
+ }
};
wifi_error wifi_get_link_stats(wifi_request_id id,
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
index 4dd4dd9..d0f7b5a 100755..100644
--- a/bcmdhd/wifi_hal/nan.cpp
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -125,6 +125,11 @@ static const char *NanStatusToString(NanStatusType status)
C2S(NAN_STATUS_ALREADY_ENABLED)
C2S(NAN_STATUS_FOLLOWUP_QUEUE_FULL)
C2S(NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED)
+ C2S(NAN_STATUS_INVALID_PAIRING_ID)
+ C2S(NAN_STATUS_INVALID_BOOTSTRAPPING_ID)
+ C2S(NAN_STATUS_REDUNDANT_REQUEST)
+ C2S(NAN_STATUS_NOT_SUPPORTED)
+ C2S(NAN_STATUS_NO_CONNECTION)
default:
return "NAN_STATUS_INTERNAL_FAILURE";
@@ -292,6 +297,7 @@ typedef enum {
NAN_ATTRIBUTE_INSTANT_MODE_ENABLE = 230,
NAN_ATTRIBUTE_INSTANT_COMM_CHAN = 231,
NAN_ATTRIBUTE_CHRE_REQUEST = 232,
+ NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE = 233
} NAN_ATTRIBUTE;
typedef enum {
@@ -315,6 +321,9 @@ typedef enum {
NAN_DATA_PATH_IFACE_UP = 17,
NAN_DATA_PATH_SEC_INFO = 18,
NAN_VERSION_INFO = 19,
+ NAN_REQUEST_ENABLE_MERGE = 20,
+ NAN_REQUEST_SUSPEND = 21,
+ NAN_REQUEST_RESUME = 22,
NAN_REQUEST_LAST = 0xFFFF
} NanRequestType;
@@ -472,6 +481,11 @@ static NanStatusType nan_map_response_status (int vendor_status) {
case NAN_STATUS_ALREADY_ENABLED:
case NAN_STATUS_FOLLOWUP_QUEUE_FULL:
case NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
+ case NAN_STATUS_INVALID_PAIRING_ID:
+ case NAN_STATUS_INVALID_BOOTSTRAPPING_ID:
+ case NAN_STATUS_REDUNDANT_REQUEST:
+ case NAN_STATUS_NOT_SUPPORTED:
+ case NAN_STATUS_NO_CONNECTION:
hal_status = (NanStatusType)vendor_status;
break;
default:
@@ -702,8 +716,6 @@ class NanDiscEnginePrimitive : public WifiCommand
if (mParams->service_name_len) {
u8 svc_hash[NAN_SVC_HASH_SIZE];
- u16 len = min(mParams->service_name_len, sizeof(mParams->service_name) - 1);
- mParams->service_name[len] = '\0';
result = get_svc_hash(mParams->service_name, mParams->service_name_len,
svc_hash, NAN_SVC_HASH_SIZE);
@@ -946,6 +958,14 @@ class NanDiscEnginePrimitive : public WifiCommand
return result;
}
+ result = request.put_u8(NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE, mParams->enable_suspendability);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE, result = %d\n", __func__, result);
+ return result;
+ }
+ /* To be removed */
+ ALOGE("Publish enable_suspendability=%u\n", mParams->enable_suspendability);
+
request.attr_end(data);
ALOGI("Returning successfully\n");
@@ -1068,9 +1088,6 @@ class NanDiscEnginePrimitive : public WifiCommand
if (mParams->service_name_len) {
u8 svc_hash[NAN_SVC_HASH_SIZE];
- u16 len = min(mParams->service_name_len, sizeof(mParams->service_name) - 1);
- mParams->service_name[len] = '\0';
-
result = get_svc_hash(mParams->service_name, mParams->service_name_len,
svc_hash, NAN_SVC_HASH_SIZE);
if (result < 0) {
@@ -1319,6 +1336,14 @@ class NanDiscEnginePrimitive : public WifiCommand
}
}
+ result = request.put_u8(NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE, mParams->enable_suspendability);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE, result = %d\n", __func__, result);
+ return result;
+ }
+ /* To be removed */
+ ALOGE("Subscribe enable_suspendability=%u\n", mParams->enable_suspendability);
+
request.attr_end(data);
NAN_DBG_EXIT();
return WIFI_SUCCESS;
@@ -1404,8 +1429,6 @@ class NanDiscEnginePrimitive : public WifiCommand
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)) {
@@ -1565,6 +1588,8 @@ class NanDiscEnginePrimitive : public WifiCommand
desc->cipher_suites_supported = src->cipher_suites_supported;
desc->is_instant_mode_supported = src->is_instant_mode_supported;
desc->ndpe_attr_supported = src->ndpe_attr_supported;
+ desc->is_suspension_supported = src->is_suspension_supported;
+ ALOGE(" suspend capability %d \n", rsp_vndr_data->capabilities.is_suspension_supported); //Remove
}
GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
@@ -1597,7 +1622,7 @@ class NanDiscEnginePrimitive : public WifiCommand
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(pub_term_event.nan_reason) - 1));
memcpy(pub_term_event.nan_reason, it.get_data(), len);
pub_term_event.nan_reason[len] = '\0';
ALOGI("pub termination reason: %s, len = %d\n",
@@ -1634,20 +1659,17 @@ class NanDiscEnginePrimitive : public WifiCommand
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);
+ u16 len = min(subscribe_event.service_specific_info_len,
+ sizeof(subscribe_event.service_specific_info));
+ memcpy(subscribe_event.service_specific_info, it.get_data(), len);
} 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();
+ ALOGI("sdf match filter length: %d\n",
+ subscribe_event.sdf_match_filter_len);
} 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);
+ u16 len = min(subscribe_event.sdf_match_filter_len,
+ sizeof(subscribe_event.sdf_match_filter));
+ memcpy(subscribe_event.sdf_match_filter, it.get_data(), len);
} 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();
@@ -1655,11 +1677,9 @@ class NanDiscEnginePrimitive : public WifiCommand
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);
+ u16 len = min(subscribe_event.scid_len,
+ sizeof(subscribe_event.scid));
+ memcpy(subscribe_event.scid, it.get_data(), len);
} 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());
@@ -1673,11 +1693,9 @@ class NanDiscEnginePrimitive : public WifiCommand
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);
+ u16 len = min(subscribe_event.sdea_service_specific_info_len,
+ sizeof(subscribe_event.sdea_service_specific_info));
+ memcpy(subscribe_event.sdea_service_specific_info, it.get_data(), len);
} 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();
@@ -1721,7 +1739,7 @@ class NanDiscEnginePrimitive : public WifiCommand
sub_term_event.reason = (NanStatusType)it.get_u16();
ALOGI("sub termination status %u", sub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(sub_term_event.nan_reason) - 1));
memcpy(sub_term_event.nan_reason, it.get_data(), len);
sub_term_event.nan_reason[len] = '\0';
ALOGI("sub termination nan reason: %s, len = %d\n",
@@ -1752,11 +1770,13 @@ class NanDiscEnginePrimitive : public WifiCommand
} 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);
+ u16 len = min(followup_event.service_specific_info_len,
+ sizeof(followup_event.service_specific_info));
+ memcpy(followup_event.service_specific_info, it.get_data(), 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);
+ u16 len = min(followup_event.sdea_service_specific_info_len,
+ sizeof(followup_event.sdea_service_specific_info));
+ memcpy(followup_event.sdea_service_specific_info, it.get_data(), len);
}
}
counters.transmit_recv++;
@@ -1774,7 +1794,7 @@ class NanDiscEnginePrimitive : public WifiCommand
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
followup_ind.reason = (NanStatusType)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(followup_ind.nan_reason) - 1));
memcpy(followup_ind.nan_reason, it.get_data(), len);
followup_ind.nan_reason[len] = '\0';
ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
@@ -2138,6 +2158,15 @@ class NanDataPathPrimitive : public WifiCommand
}
}
+ if (mParams->publish_subscribe_id) {
+ result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mParams->publish_subscribe_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub id = %d, result = %d\n",
+ __func__, mParams->publish_subscribe_id, result);
+ return result;
+ }
+ }
+
request.attr_end(data);
return WIFI_SUCCESS;
}
@@ -2304,6 +2333,15 @@ class NanDataPathPrimitive : public WifiCommand
}
}
+ if (mParams->publish_subscribe_id) {
+ result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mParams->publish_subscribe_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill sub id = %d, result = %d\n",
+ __func__, mParams->publish_subscribe_id, result);
+ return result;
+ }
+ }
+
request.attr_end(data);
return WIFI_SUCCESS;
}
@@ -2326,16 +2364,18 @@ class NanDataPathPrimitive : public WifiCommand
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;
+ if (!count || count != 1) {
+ ALOGE("Unsupported more than 1 ndp id in single end request!");
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ 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]);
request.attr_end(data);
return WIFI_SUCCESS;
@@ -2414,8 +2454,11 @@ class NanDataPathPrimitive : public WifiCommand
} else {
rsp_data.status = NAN_STATUS_INTERNAL_FAILURE;
}
- } else if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
- ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ } else if (reply.get_cmd() != NL80211_CMD_VENDOR ||
+ reply.get_vendor_data() == NULL ||
+ reply.get_vendor_data_len() != sizeof(nan_hal_resp_t)) {
+ ALOGD("Ignoring reply with cmd = %d mType = %d len = %d\n",
+ reply.get_cmd(), mType, reply.get_vendor_data_len());
return NL_SKIP;
} else {
rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
@@ -2459,6 +2502,7 @@ class NanDataPathPrimitive : public WifiCommand
int handleEvent(WifiEvent& event)
{
int cmd = event.get_vendor_subcmd();
+ NanDataPathEndInd *ndp_end_event = NULL;
u16 attr_type;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -2503,22 +2547,18 @@ class NanDataPathPrimitive : public WifiCommand
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\n", ndp_request_event.app_info.ndp_app_info);
+ u16 len = min(ndp_ind_app_info_len,
+ sizeof(ndp_request_event.app_info.ndp_app_info));
+ memcpy(ndp_request_event.app_info.ndp_app_info, it.get_data(), len);
} else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
ALOGI("scid len: %u\n", it.get_u32());
ndp_request_event.scid_len = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_SCID) {
- memcpy(ndp_request_event.scid, it.get_data(),
- ndp_request_event.scid_len);
- ndp_request_event.scid[ndp_request_event.scid_len] = '\0';
- ALOGI("scid : %s\n", ndp_request_event.scid);
-
+ u16 len = min(ndp_request_event.scid_len,
+ sizeof(ndp_request_event.scid));
+ memcpy(ndp_request_event.scid, it.get_data(), len);
}
}
@@ -2549,14 +2589,13 @@ class NanDataPathPrimitive : public WifiCommand
} 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;
+ ndp_conf_app_info_len =
+ ndp_create_confirmation_event.app_info.ndp_app_info_len;
} else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+ u16 len = min(ndp_conf_app_info_len,
+ sizeof(ndp_create_confirmation_event.app_info.ndp_app_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);
+ it.get_data(), len);
} else if (attr_type == NAN_ATTRIBUTE_RSP_CODE) {
ALOGI("response code: %u", (NanDataPathResponseCode)it.get_u8());
@@ -2578,8 +2617,11 @@ class NanDataPathPrimitive : public WifiCommand
}
} else if (attr_type == NAN_ATTRIBUTE_CHANNEL_INFO) {
ALOGI("Channel info \n");
- memcpy((u8 *)ndp_create_confirmation_event.channel_info, it.get_data(),
- ndp_create_confirmation_event.num_channels * sizeof(NanChannelInfo));
+ u16 len = min(
+ ndp_create_confirmation_event.num_channels * sizeof(NanChannelInfo),
+ it.get_len());
+ memcpy((u8 *)ndp_create_confirmation_event.channel_info,
+ it.get_data(), len);
while (chan_idx < ndp_create_confirmation_event.num_channels) {
ALOGI("channel: %u, Bandwidth: %u, nss: %u\n",
ndp_create_confirmation_event.channel_info[chan_idx].channel,
@@ -2593,9 +2635,19 @@ class NanDataPathPrimitive : public WifiCommand
break;
}
case NAN_EVENT_DATA_END: {
- NanDataPathEndInd ndp_end_event;
- memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+ u8 i = 0;
u16 attr_type;
+
+ ndp_end_event =
+ (NanDataPathEndInd *)malloc(NAN_MAX_NDP_COUNT_SIZE +
+ sizeof(ndp_end_event->num_ndp_instances));
+ if (!ndp_end_event) {
+ ALOGE("Failed to alloc for end request event\n");
+ break;
+ }
+
+ memset(ndp_end_event, 0, (NAN_MAX_NDP_COUNT_SIZE +
+ sizeof(ndp_end_event->num_ndp_instances)));
ALOGI("Received NAN_EVENT_DATA_END\n");
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
@@ -2603,23 +2655,33 @@ class NanDataPathPrimitive : public WifiCommand
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();
+ if (!count || (count != 1)) {
+ ALOGE("%s:Invalid inst_count value.\n", __FUNCTION__);
+ break;
+ }
+ ndp_end_event->num_ndp_instances = count;
} 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;
+ if (!ndp_end_event->num_ndp_instances ||
+ (i > ndp_end_event->num_ndp_instances)) {
+ ALOGE("num of ndp instances need to be minimum 1\n");
+ break;
}
+ ndp_end_event->ndp_instance_id[i++] = it.get_u32();
+ ALOGI("NDP Id from the Event = %u\n", it.get_u32());
} else {
ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
}
}
- GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+ GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(ndp_end_event);
break;
}
} // end-of-switch
+
+ if (ndp_end_event) {
+ free(ndp_end_event);
+ }
return NL_SKIP;
}
};
@@ -2691,6 +2753,10 @@ class NanMacControl : public WifiCommand
/* TODO: Not yet implemented */
} else if (mType == NAN_VERSION_INFO) {
return createVersionRequest(request);
+ } else if (mType == NAN_REQUEST_SUSPEND) {
+ return createSuspendRequest(request, (NanSuspendRequest *)mParams);
+ } else if (mType == NAN_REQUEST_RESUME) {
+ return createResumeRequest(request, (NanResumeRequest *)mParams);
} else {
ALOGE("Unknown Nan request\n");
}
@@ -3263,7 +3329,6 @@ class NanMacControl : public WifiCommand
}
mParams->fam_val.numchans -= 1;
}
-
}
if (mParams->config_dw.config_2dot4g_dw_band) {
@@ -3377,29 +3442,43 @@ class NanMacControl : public WifiCommand
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);
+ int createSuspendRequest(WifiRequest& request,
+ NanSuspendRequest *mParams) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_SUSPEND);
+ if (result < 0) {
+ ALOGE("%s: Fail to create Suspension Start request\n", __func__);
return result;
}
-
- result = requestResponse(request);
- if (result != WIFI_SUCCESS) {
- ALOGE("%s: Failed to configure setup; result = %d", __func__, result);
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mParams->publish_subscribe_id);
+ if (result < 0) {
+ ALOGE("%s: Failing in Suspension Start request, result = %d\n", __func__, result);
return result;
}
+ request.attr_end(data);
+ NAN_DBG_EXIT();
+ return WIFI_SUCCESS;
+ }
- request.destroy();
+ int createResumeRequest(WifiRequest& request,
+ NanResumeRequest *mParams) {
+ int result = request.create(GOOGLE_OUI, NAN_SUBCMD_RESUME);
+ if (result < 0) {
+ ALOGE("%s: Fail to create Resume request\n", __func__);
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mParams->publish_subscribe_id);
+ if (result < 0) {
+ ALOGE("%s: Failing in Resume request, result = %d\n", __func__, result);
+ return result;
+ }
+ request.attr_end(data);
NAN_DBG_EXIT();
return WIFI_SUCCESS;
}
- int cancel()
+ int start()
{
NAN_DBG_ENTER();
@@ -3421,6 +3500,11 @@ class NanMacControl : public WifiCommand
return WIFI_SUCCESS;
}
+ int cancel()
+ {
+ return start();
+ }
+
int handleResponse(WifiEvent& reply) {
nan_hal_resp_t *rsp_vndr_data = NULL;
@@ -3464,6 +3548,18 @@ class NanMacControl : public WifiCommand
GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
}
}
+ if ((rsp_vndr_data->subcmd == NAN_SUBCMD_SUSPEND) ||
+ (rsp_vndr_data->subcmd == NAN_SUBCMD_RESUME)) {
+ 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 = (NanStatusType)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);
+ }
return NL_SKIP;
}
@@ -3558,17 +3654,17 @@ class NanMacControl : public WifiCommand
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");
- if (rsp_vndr_data != NULL) {
- handleAsyncResponse(rsp_vndr_data);
- } else {
- ALOGE("Wrong response data, rsp_vndr_data is NULL\n");
- return NL_SKIP;
- }
- }
- }
+ } else {
+ if (is_cmd_response(event_id)) {
+ ALOGE("Handling cmd response asynchronously\n");
+ if (rsp_vndr_data != NULL) {
+ handleAsyncResponse(rsp_vndr_data);
+ } else {
+ ALOGE("Wrong response data, rsp_vndr_data is NULL\n");
+ return NL_SKIP;
+ }
+ }
+ }
switch(event_id) {
case NAN_EVENT_DE_EVENT:
@@ -3642,7 +3738,7 @@ class NanMacControl : public WifiCommand
disabled_ind.reason = (NanStatusType)it.get_u8();
ALOGI("Nan Disable:status %u", disabled_ind.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(disabled_ind.nan_reason) - 1));
memcpy(disabled_ind.nan_reason, it.get_data(), len);
disabled_ind.nan_reason[len] = '\0';
ALOGI("Disabled nan reason: %s, len = %d\n",
@@ -3673,7 +3769,8 @@ class NanMacControl : public WifiCommand
} 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);
+ u16 len = min(sdfInd.data.frame_len, sizeof(sdfInd.data.frame_data));
+ memcpy(&sdfInd.data.frame_data, it.get_data(), len);
prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
sdfInd.data.frame_len);
}
@@ -3685,6 +3782,21 @@ class NanMacControl : public WifiCommand
ALOGI("Received NAN_EVENT_TCA\n");
break;
+ case NAN_EVENT_SUSPENSION_STATUS:
+ ALOGI("Received NAN_EVENT_SUSPENSION_STATUS\n");
+ NanSuspensionModeChangeInd suspend_ind;
+ memset(&suspend_ind, 0, sizeof(NanSuspensionModeChangeInd));
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ suspend_ind.is_suspended = (bool)it.get_u8();
+ ALOGI("Nan Suspension :status %u", suspend_ind.is_suspended);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventSuspensionModeChange(&suspend_ind);
+ break;
+
case NAN_EVENT_UNKNOWN:
ALOGI("Received NAN_EVENT_UNKNOWN\n");
break;
@@ -3700,6 +3812,7 @@ class NanMacControl : public WifiCommand
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_SUSPENSION_STATUS);
}
void registerNanVendorEvents()
{
@@ -3709,6 +3822,7 @@ class NanMacControl : public WifiCommand
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_SUSPENSION_STATUS);
}
};
@@ -3772,6 +3886,8 @@ static const char *NanRspToString(int cmd_resp)
C2S(NAN_DP_RESPONDER_RESPONSE)
C2S(NAN_DP_END)
C2S(NAN_GET_CAPABILITIES)
+ C2S(NAN_SUSPEND_REQUEST_RESPONSE)
+ C2S(NAN_RESUME_REQUEST_RESPONSE)
default:
return "UNKNOWN_NAN_CMD_RESPONSE";
@@ -3801,6 +3917,8 @@ static const char *NanCmdToString(int cmd)
C2S(NAN_DATA_PATH_IFACE_UP)
C2S(NAN_DATA_PATH_SEC_INFO)
C2S(NAN_VERSION_INFO)
+ C2S(NAN_REQUEST_SUSPEND)
+ C2S(NAN_REQUEST_RESUME)
default:
return "UNKNOWN_NAN_CMD";
}
@@ -3886,6 +4004,7 @@ static const char *NanAttrToString(u16 cmd)
C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO)
C2S(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL)
C2S(NAN_ATTRIBUTE_ENABLE_MERGE)
+ C2S(NAN_ATTRIBUTE_SVC_CFG_SUPENDABLE)
default:
return "NAN_ATTRIBUTE_UNKNOWN";
@@ -3945,6 +4064,12 @@ NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd)
case NAN_SUBCMD_GET_CAPABILITIES:
response_type = NAN_GET_CAPABILITIES;
break;
+ case NAN_SUBCMD_SUSPEND:
+ response_type = NAN_SUSPEND_REQUEST_RESPONSE;
+ break;
+ case NAN_SUBCMD_RESUME:
+ response_type = NAN_RESUME_REQUEST_RESPONSE;
+ break;
default:
/* unknown response for a command */
response_type = NAN_RESPONSE_ERROR;
@@ -4207,7 +4332,8 @@ static int dump_NanPublishRequest(NanPublishRequest* msg)
}
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);
+ prhex("service_specific_info",
+ msg->service_specific_info, msg->service_specific_info_len);
}
ALOGI("rx_match_filter_len=%u\n", msg->rx_match_filter_len);
if (msg->rx_match_filter_len) {
@@ -4222,12 +4348,7 @@ static int dump_NanPublishRequest(NanPublishRequest* msg)
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);
@@ -4240,9 +4361,6 @@ static int dump_NanPublishRequest(NanPublishRequest* msg)
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;
}
@@ -4269,8 +4387,6 @@ static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
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);
@@ -4288,12 +4404,7 @@ static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
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);
@@ -4306,8 +4417,6 @@ static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
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;
}
@@ -4325,12 +4434,8 @@ static int dump_NanTransmitFollowupRequest(NanTransmitFollowupRequest* msg)
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;
}
@@ -4358,12 +4463,7 @@ static int dump_NanDataPathInitiatorRequest(NanDataPathInitiatorRequest* msg)
}
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);
- }
if (msg->service_name_len) {
ALOGI("service_name=%s\n", msg->service_name);
}
@@ -4391,13 +4491,8 @@ static int dump_NanDataPathIndicationResponse(NanDataPathIndicationResponse* msg
}
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);
ALOGI("scid_len=%u\n", msg->scid_len);
- if (msg->scid_len) {
- ALOGI("scid=%s\n", msg->scid);
- }
if (msg->service_name_len) {
ALOGI("service_name=%s\n", msg->service_name);
}
@@ -4494,7 +4589,7 @@ wifi_error nan_cmn_disable_request(transaction_id id, NanMacControl *mac)
mac->setType(NAN_REQUEST_DISABLE);
ret = (wifi_error)mac->cancel();
if (ret != WIFI_SUCCESS) {
- ALOGE("cancel failed, error = %d\n", ret);
+ ALOGE("Disable req: cmd cancel failed, error = %d\n", ret);
} else {
ALOGE("Deinitializing Nan Mac Control = %p\n", mac);
}
@@ -4845,6 +4940,48 @@ wifi_error nan_register_handler(wifi_interface_handle iface,
return WIFI_SUCCESS;
}
+/* Function to send NAN device Suspension start request to the wifi driver.*/
+wifi_error wifi_nan_suspend_request(transaction_id id,
+ wifi_interface_handle iface, NanSuspendRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanRequestType cmdType = NAN_REQUEST_SUSPEND;
+
+ 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);
+ ALOGE("%s :Suspend request svc_id = %d\n", __func__, msg->publish_subscribe_id);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s :Suspend request failed, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+/* Function to send NAN device Resume request to the wifi driver.*/
+wifi_error wifi_nan_resume_request(transaction_id id,
+ wifi_interface_handle iface, NanResumeRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanRequestType cmdType = NAN_REQUEST_RESUME;
+
+ 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);
+ ALOGE("%s :Resume request svc_id = %d\n", __func__, msg->publish_subscribe_id);
+ ret = (wifi_error)cmd->start();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s :Resume request failed, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
wifi_error nan_get_version(wifi_handle handle, NanVersion* version)
{
wifi_error ret = WIFI_SUCCESS;
@@ -4884,6 +5021,7 @@ class NanEventCap : public WifiCommand
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_SUSPENSION_STATUS);
}
void registerNanVendorEvents()
{
@@ -4893,9 +5031,11 @@ class NanEventCap : public WifiCommand
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_SUSPENSION_STATUS);
}
int handleEvent(WifiEvent& event) {
+ NanDataPathEndInd *ndp_end_event = NULL;
int cmd = event.get_vendor_subcmd();
u16 attr_type;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -4956,7 +5096,7 @@ class NanEventCap : public WifiCommand
disabled_ind.reason = (NanStatusType)it.get_u8();
ALOGI("Nan Disable:status %u", disabled_ind.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(disabled_ind.nan_reason) - 1));
memcpy(disabled_ind.nan_reason, it.get_data(), len);
disabled_ind.nan_reason[len] = '\0';
ALOGI("nan disabled reason: %s, len = %d\n",
@@ -4983,7 +5123,7 @@ class NanEventCap : public WifiCommand
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(pub_term_event.nan_reason) - 1));
memcpy(pub_term_event.nan_reason, it.get_data(), len);
pub_term_event.nan_reason[len] = '\0';
ALOGI("Pub termination nan reason: %s, len = %d\n",
@@ -5024,22 +5164,18 @@ class NanEventCap : public WifiCommand
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);
+ u16 len = min(subscribe_event.service_specific_info_len,
+ sizeof(subscribe_event.service_specific_info));
+ memcpy(subscribe_event.service_specific_info, it.get_data(), len);
} 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();
+ ALOGI("sdf match filter length: %d",
+ subscribe_event.sdf_match_filter_len);
} 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();
@@ -5049,9 +5185,6 @@ class NanEventCap : public WifiCommand
} 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());
@@ -5065,11 +5198,9 @@ class NanEventCap : public WifiCommand
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);
+ u16 len = min(subscribe_event.sdea_service_specific_info_len,
+ sizeof(subscribe_event.sdea_service_specific_info));
+ memcpy(subscribe_event.sdea_service_specific_info, it.get_data(), len);
} 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();
@@ -5115,7 +5246,7 @@ class NanEventCap : public WifiCommand
sub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("sub termination status %u", sub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(sub_term_event.nan_reason) - 1));
memcpy(sub_term_event.nan_reason, it.get_data(), len);
sub_term_event.nan_reason[len] = '\0';
ALOGI("sub termination nan reason: %s, len = %d\n",
@@ -5152,18 +5283,16 @@ class NanEventCap : public WifiCommand
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';
+ u16 len = min(followup_event.service_specific_info_len,
+ sizeof(followup_event.service_specific_info));
+ memcpy(followup_event.service_specific_info, it.get_data(), len);
} 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);
+ u16 len = min(followup_event.sdea_service_specific_info_len,
+ sizeof(followup_event.sdea_service_specific_info));
+ memcpy(followup_event.sdea_service_specific_info, it.get_data(), len);
}
}
@@ -5265,9 +5394,6 @@ class NanEventCap : public WifiCommand
} 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);
-
} else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
ALOGI("scid length %d\n", it.get_u32());
ndp_request_event.scid_len= it.get_u32();
@@ -5275,8 +5401,6 @@ class NanEventCap : public WifiCommand
} else if (attr_type == NAN_ATTRIBUTE_SCID) {
memcpy(ndp_request_event.scid, it.get_data(),
ndp_request_event.scid_len);
- ndp_request_event.scid[ndp_request_event.scid_len] = '\0';
- ALOGI("scid: %s\n", ndp_request_event.scid);
}
}
@@ -5311,11 +5435,6 @@ class NanEventCap : public WifiCommand
} 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 =
@@ -5328,29 +5447,43 @@ class NanEventCap : public WifiCommand
}
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;
+ u8 i = 0, count = 0;
+ u16 attr_type;
+
+ ndp_end_event =
+ (NanDataPathEndInd *)malloc(NAN_MAX_NDP_COUNT_SIZE +
+ sizeof(ndp_end_event->num_ndp_instances));
+ if (!ndp_end_event) {
+ ALOGE("Failed to alloc for end request event\n");
+ break;
+ }
+ memset(ndp_end_event, 0, (NAN_MAX_NDP_COUNT_SIZE +
+ sizeof(ndp_end_event->num_ndp_instances)));
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();
+ if (!count || (count != 1)) {
+ ALOGE("%s:Invalid inst_count value.\n", __FUNCTION__);
+ break;
+ }
+ ndp_end_event->num_ndp_instances = count;
} 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;
+ if (!ndp_end_event->num_ndp_instances ||
+ (i > ndp_end_event->num_ndp_instances)) {
+ ALOGE("num of ndp instances need to be minimum 1\n");
+ break;
}
+ ndp_end_event->ndp_instance_id[i++] = it.get_u32();
+ ALOGI("NDP Id from the Event = %u\n", it.get_u32());
} else {
ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
}
}
-
- GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+ GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(ndp_end_event);
break;
}
case NAN_EVENT_TRANSMIT_FOLLOWUP_IND: {
@@ -5365,7 +5498,7 @@ class NanEventCap : public WifiCommand
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
followup_ind.reason = (NanStatusType)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason) - 1);
+ u8 len = min(it.get_len(), (sizeof(followup_ind.nan_reason) - 1));
memcpy(followup_ind.nan_reason, it.get_data(), len);
followup_ind.nan_reason[len] = '\0';
ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
@@ -5376,10 +5509,30 @@ class NanEventCap : public WifiCommand
GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
break;
}
+ case NAN_EVENT_SUSPENSION_STATUS: {
+ ALOGI("Received NAN_EVENT_SUSPENSION_STATUS\n");
+ NanSuspensionModeChangeInd suspend_ind;
+ memset(&suspend_ind, 0, sizeof(NanSuspensionModeChangeInd));
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_STATUS) {
+ suspend_ind.is_suspended = (bool)it.get_u8();
+ ALOGI("Nan Suspension Event :status %u", suspend_ind.is_suspended);
+ }
+ }
+
+ GET_NAN_HANDLE(info)->mHandlers.EventSuspensionModeChange(&suspend_ind);
+ break;
+ }
+
case NAN_EVENT_UNKNOWN:
ALOGI("Received NAN_EVENT_UNKNOWN\n");
break;
} // end-of-switch
+
+ if (ndp_end_event) {
+ free(ndp_end_event);
+ }
return NL_SKIP;
}
};
@@ -5453,9 +5606,6 @@ wifi_error nan_data_request_initiator(transaction_id id,
#endif /* CONFIG_BRCM */
counters.dp_req++;
if (msg->service_name_len) {
- u16 len = min(msg->service_name_len, sizeof(msg->service_name) - 1);
- msg->service_name[len] = '\0';
-
if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
(char*)msg->service_name, msg->service_name_len) == 0) {
ALOGI("Use Hardcoded svc_hash\n");
@@ -5541,9 +5691,6 @@ wifi_error nan_data_indication_response(transaction_id id,
#endif /* CONFIG_BRCM */
counters.dp_resp++;
if (msg->service_name_len) {
- u16 len = min(msg->service_name_len, sizeof(msg->service_name) - 1);
- msg->service_name[len] = '\0';
-
if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
(char*)msg->service_name, msg->service_name_len) == 0) {
ALOGI("Use Hardcoded svc_hash\n");
diff --git a/bcmdhd/wifi_hal/rtt.cpp b/bcmdhd/wifi_hal/rtt.cpp
index 2197c81..4167c4f 100644
--- a/bcmdhd/wifi_hal/rtt.cpp
+++ b/bcmdhd/wifi_hal/rtt.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/scan.cpp b/bcmdhd/wifi_hal/scan.cpp
index d8ab4e0..0358092 100644
--- a/bcmdhd/wifi_hal/scan.cpp
+++ b/bcmdhd/wifi_hal/scan.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
- * Portions copyright (C) 2022 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/sync.h b/bcmdhd/wifi_hal/sync.h
index 1118c71..91c017f 100644
--- a/bcmdhd/wifi_hal/sync.h
+++ b/bcmdhd/wifi_hal/sync.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/twt.cpp b/bcmdhd/wifi_hal/twt.cpp
index 63cd002..087c17a 100755
--- a/bcmdhd/wifi_hal/twt.cpp
+++ b/bcmdhd/wifi_hal/twt.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2020 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index f746f09..af9b06c 100644
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,6 +104,11 @@ wifi_error wifi_get_cached_scan_results(wifi_interface_handle iface,
wifi_cached_scan_result_handler handler);
wifi_error wifi_enable_sta_channel_for_peer_network(wifi_handle handle,
u32 channelCategoryEnableFlag);
+wifi_error wifi_nan_suspend_request(transaction_id id,
+ wifi_interface_handle iface, NanSuspendRequest* msg);
+wifi_error wifi_nan_resume_request(transaction_id id,
+ wifi_interface_handle iface, NanResumeRequest* msg);
+
typedef enum wifi_attr {
ANDR_WIFI_ATTRIBUTE_INVALID = 0,
@@ -362,6 +367,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
fn->wifi_enable_tx_power_limits = wifi_enable_tx_power_limits;
fn->wifi_get_cached_scan_results = wifi_get_cached_scan_results;
fn->wifi_enable_sta_channel_for_peer_network = wifi_enable_sta_channel_for_peer_network;
+ fn->wifi_nan_suspend_request = wifi_nan_suspend_request;
+ fn->wifi_nan_resume_request = wifi_nan_resume_request;
return WIFI_SUCCESS;
}
#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
@@ -608,7 +615,6 @@ static int wifi_add_membership(wifi_handle handle, const char *group)
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");
@@ -622,12 +628,13 @@ static void internal_cleaned_up_handler(wifi_handle handle)
info->event_sock = NULL;
}
- if (cleaned_up_handler) {
- ALOGI("cleanup_handler cb");
- (*cleaned_up_handler)(handle);
- } else {
- ALOGI("!! clean up handler is null!!");
+ if (info->interfaces) {
+ for (int i = 0; i < info->num_interfaces; i++) {
+ free(info->interfaces[i]);
+ }
+ free(info->interfaces);
}
+
DestroyResponseLock();
pthread_mutex_destroy(&info->cb_lock);
free(info);
@@ -641,7 +648,7 @@ void wifi_internal_module_cleanup()
twt_deinit_handler();
}
-void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
+void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler cleaned_up_handler)
{
if (!handle) {
ALOGE("Handle is null");
@@ -655,8 +662,6 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
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) {
@@ -705,13 +710,13 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
pthread_mutex_unlock(&info->cb_lock);
cmd->cancel();
- pthread_mutex_lock(&info->cb_lock);
if (num_cmd == info->num_cmd) {
ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
bad_commands++;
}
/* release reference added when command is saved */
cmd->releaseRef();
+ pthread_mutex_lock(&info->cb_lock);
}
}
@@ -728,6 +733,14 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
info->clean_up = true;
+ /* global func ptr be invalidated and will not call any command from legacy hal */
+ if (cleaned_up_handler) {
+ ALOGI("cleaned_up_handler to invalidates func ptr");
+ cleaned_up_handler(handle);
+ } else {
+ ALOGI("cleaned up handler 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");
@@ -1085,7 +1098,7 @@ public:
*/
ALOGI("Try to remove event handler if exist, vendor 0x%0x, subcmd 0x%x",
GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
- unregisterVendorHandlerWithoutLock(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
ALOGI("SetRSSIMonitorCommand %p destroyed", this);
}
@@ -1264,8 +1277,10 @@ class AndroidPktFilterCommand : public WifiCommand {
int createSetPktFilterRequest(WifiRequest& request) {
u8 *program = new u8[mProgramLen];
NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ALOGE("Success to allocate program of len: %d\n", mProgramLen);
int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
if (result < 0) {
+ ALOGE("Failed to create cmd: %d, err %d\n", APF_SUBCMD_SET_FILTER, result);
delete[] program;
return result;
}
@@ -1273,11 +1288,13 @@ class AndroidPktFilterCommand : public WifiCommand {
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
if (result < 0) {
+ ALOGE("Failed to put the program_len %d, err %d\n", mProgramLen, result);
goto exit;
}
memcpy(program, mProgram, mProgramLen);
result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
if (result < 0) {
+ ALOGE("Failed to copy program_ptr %d, err %d\n", mProgramLen, result);
goto exit;
}
exit: request.attr_end(data);
@@ -1310,6 +1327,7 @@ exit: request.attr_end(data);
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request);
if (result < 0) {
+ ALOGI("CreateRequest failed for APF, result = %d", result);
return result;
}
result = requestResponse(request);
@@ -1326,7 +1344,7 @@ exit: request.attr_end(data);
}
int handleResponse(WifiEvent& reply) {
- ALOGD("In SetAPFCommand::handleResponse");
+ ALOGE("In SetAPFCommand::handleResponse mReqType %d\n", mReqType);
if (reply.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
@@ -1339,13 +1357,13 @@ exit: request.attr_end(data);
nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
int len = reply.get_vendor_data_len();
- ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+ ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
if (vendor_data == NULL || len == 0) {
ALOGE("no vendor data in SetAPFCommand response; ignoring it");
return NL_SKIP;
}
- if( mReqType == SET_APF_PROGRAM) {
- ALOGD("Response received for set packet filter command\n");
+ if (mReqType == SET_APF_PROGRAM) {
+ ALOGE("Response received for set packet filter command\n");
} else if (mReqType == GET_APF_CAPABILITIES) {
*mVersion = 0;
*mMaxLen = 0;
@@ -1712,6 +1730,11 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
if (is_wifi_interface(de->d_name)) {
interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
if (!ifinfo) {
+ if (info->interfaces) {
+ for (int j = 0; j < i; j++) {
+ free(info->interfaces[j]);
+ }
+ }
free(info->interfaces);
info->num_interfaces = 0;
closedir(d);
@@ -1719,6 +1742,7 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
}
memset(ifinfo, 0, sizeof(interface_info));
if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
+ free(ifinfo);
continue;
}
/* Mark as static iface */
@@ -1976,7 +2000,15 @@ static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle hand
static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
const u8 *program, u32 len)
{
- ALOGD("Setting APF program, halHandle = %p\n", handle);
+ char iface_name[IFNAMSIZ];
+
+ ALOGE("Setting APF program, halHandle = %p\n", handle);
+ if (wifi_get_iface_name(handle, iface_name, sizeof(iface_name)) != WIFI_SUCCESS) {
+ ALOGE("%s : Invalid interface handle\n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ ALOGE("Set apf filter for iface = %s\n", iface_name);
+
AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();
@@ -2652,26 +2684,34 @@ wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname)
return WIFI_ERROR_UNKNOWN;
}
+ /* Check if interface delete requested on valid interface */
while (i < info->max_num_interfaces) {
if (info->interfaces[i] != NULL &&
strncmp(info->interfaces[i]->name,
ifname, sizeof(info->interfaces[i]->name)) == 0) {
- if (info->interfaces[i]->is_virtual == false) {
- ALOGI("%s: %s is static iface, skip delete\n",
- __FUNCTION__, ifname);
- return WIFI_SUCCESS;
+ if (!get_halutil_mode()) {
+ if (info->interfaces[i]->is_virtual == false) {
+ ALOGI("%s: %s is static iface, skip delete\n",
+ __FUNCTION__, ifname);
+ return WIFI_SUCCESS;
+ }
+ } else {
+ ALOGI("%s: %s delete iface", __FUNCTION__, ifname);
+ break;
+ }
}
- }
i++;
}
- ALOGD("%s: iface name=%s\n", __FUNCTION__, ifname);
+ ALOGI("%s: iface name=%s\n", __FUNCTION__, ifname);
wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
VirtualIfaceConfig command(wlan0Handle, ifname, (nl80211_iftype)0, 0);
ret = (wifi_error)command.deleteIface();
if (ret != WIFI_SUCCESS) {
ALOGE("%s: Iface delete Error:%d", __FUNCTION__,ret);
- return ret;
+ /* If lower layer returns an error, hang event is expected to do wifi reset
+ * and hal state needs to be cleared irrespectivily. Hence fall-through.
+ */
}
/* Update dynamic interface list */
added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index dbbcf79..694df19 100755
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,13 +81,15 @@ typedef enum {
#define MAX_SKU_NAME_LEN 5
#define OTA_PATH "/data/vendor/firmware/wifi/"
#define OTA_CLM_FILE "bcmdhd_clm.blob"
+#define OTA_TXCAP_BLOB_FILE "bcmdhd_txcap.blob"
#define OTA_NVRAM_FILE "bcmdhd.cal"
#define HW_DEV_PROP "ro.revision"
#define HW_SKU_PROP "ro.boot.hardware.sku"
typedef enum {
NVRAM,
- CLM_BLOB
+ CLM_BLOB,
+ TXCAP_BLOB
} OTA_TYPE;
char ota_nvram_ext[10];
@@ -96,6 +98,8 @@ typedef struct ota_info_buf {
const void *ota_clm_buf[1];
u32 ota_nvram_len;
const void *ota_nvram_buf[1];
+ u32 ota_txcap_len;
+ const void *ota_txcap_buf[1];
} ota_info_buf_t;
u32 applied_ota_version = 0;
@@ -189,6 +193,8 @@ typedef enum {
OTA_DOWNLOAD_NVRAM_ATTR = 0x0004,
OTA_SET_FORCE_REG_ON = 0x0005,
OTA_CUR_NVRAM_EXT_ATTR = 0x0006,
+ OTA_DOWNLOAD_TXCAP_BLOB_LENGTH_ATTR = 0x0007,
+ OTA_DOWNLOAD_TXCAP_BLOB_ATTR = 0x0008,
} OTA_DOWNLOAD_ATTRIBUTE;
#define HAL_START_REQUEST_ID 2
@@ -518,6 +524,7 @@ typedef struct {
} sku_info_t;
sku_info_t sku_table[] = {
+ // BCM4389
{ {"G9S9B"}, {"MMW"} },
{ {"G8V0U"}, {"MMW"} },
{ {"GFQM1"}, {"MMW"} },
@@ -536,7 +543,20 @@ sku_info_t sku_table[] = {
{ {"GB17L"}, {"JPN"} },
{ {"GFE4J"}, {"JPN"} },
{ {"G03Z5"}, {"JPN"} },
- { {"G1AZG"}, {"EU"} }
+ // BCM4398
+ { {"GKWS6"}, {"MMW"} },
+ { {"G1MNW"}, {"MMW"} },
+ { {"GPJ41"}, {"ROW"} },
+ { {"GC3VE"}, {"ROW"} },
+ { {"GE9DP"}, {"JPN"} },
+ { {"GZPF0"}, {"JPN"} },
+ { {"G1AZG"}, {"EU"} },
+ { {"G9BQD"}, {"NA"} },
+ // BCM4383
+ { {"G8HHN"}, {"MMW"} },
+ { {"G6GPR"}, {"ROW"} },
+ { {"G576D"}, {"JPN"} },
+ { {"GKV4X"}, {"NA"} }
};
///////////////////////////////////////////////////////////////////////////////
class DebugCommand : public WifiCommand
@@ -1645,6 +1665,7 @@ public:
: WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL),
mErrCode(0)
{
+ memset(&mHandle, 0, sizeof(wifi_ring_buffer_data_handler));
}
int start() {
@@ -1685,6 +1706,7 @@ public:
ring_name[i] = NULL;
}
}
+ memset(&mHandle, 0, sizeof(wifi_ring_buffer_data_handler));
DUMP_INFO(("Stop Ring Dump Successfully Completed, mErrCode = %d\n", mErrCode));
return WIFI_SUCCESS;
@@ -2330,6 +2352,7 @@ public:
int createMonitorPktFateRequest(WifiRequest& request) {
int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
if (result < 0) {
+ ALOGE("Failed to create monitorPktFate result:%d\n", result);
return result;
}
@@ -2341,6 +2364,7 @@ public:
int createTxPktFateRequest(WifiRequest& request) {
int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
if (result < 0) {
+ ALOGE("Failed to create TxPktFate result:%d\n", result);
return result;
}
@@ -2348,10 +2372,12 @@ public:
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
if (result < 0) {
+ ALOGE("Failed to set TxPktFate num result:%d mNoReqFates:%d\n", result, mNoReqFates);
return result;
}
result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
if (result < 0) {
+ ALOGE("Failed to set TxPktFate buf result:%d\n", result);
return result;
}
request.attr_end(data);
@@ -2361,6 +2387,7 @@ public:
int createRxPktFateRequest(WifiRequest& request) {
int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
if (result < 0) {
+ ALOGE("Failed to create RxPktFate result:%d\n", result);
return result;
}
@@ -2368,10 +2395,12 @@ public:
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
if (result < 0) {
+ ALOGE("Failed to set RxPktFate num result:%d mNoReqFates:%d\n", result, mNoReqFates);
return result;
}
result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
if (result < 0) {
+ ALOGE("Failed to set RxPktFate buf result:%d\n", result);
return result;
}
request.attr_end(data);
@@ -2700,11 +2729,24 @@ class OtaUpdateCommand : public WifiCommand
return result;
}
+ result = request.put_u32(OTA_DOWNLOAD_TXCAP_BLOB_LENGTH_ATTR, buf->ota_txcap_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_TXCAP_BLOB_ATTR,
+ buf->ota_txcap_buf, sizeof(*buf->ota_txcap_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
request.attr_end(data);
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
- ALOGE("Failed to register set otaDownload; result = %d", result);
+ ALOGE("Failed to register set otaDownload; result = %d\n", result);
}
return result;
@@ -2794,6 +2836,10 @@ wifi_error check_multiple_nvram_clm(uint32_t type, char* hw_revision, char* hw_s
else if (type == NVRAM) {
sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
}
+ else if (type == TXCAP_BLOB) {
+ sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_TXCAP_BLOB_FILE);
+ }
+
for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
memset(file_name[i], 0, FILE_NAME_LEN);
}
@@ -2820,6 +2866,7 @@ wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version
ota_info_buf_t buf;
char *buffer_nvram = NULL;
char *buffer_clm = NULL;
+ char *buffer_txcap_blob = NULL;
char prop_revision_buf[PROPERTY_VALUE_MAX] = {0,};
char prop_sku_buf[PROPERTY_VALUE_MAX] = {0,};
char sku_name[MAX_SKU_NAME_LEN] = {0,};
@@ -2854,6 +2901,14 @@ wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version
}
buf.ota_clm_buf[0] = buffer_clm;
+ check_multiple_nvram_clm(TXCAP_BLOB, prop_revision_buf, sku_name,
+ &buffer_txcap_blob, &buf.ota_txcap_len);
+ if (buffer_txcap_blob == NULL) {
+ ALOGE("buffer_txcap_blob is null");
+ goto exit;
+ }
+ buf.ota_txcap_buf[0] = buffer_txcap_blob;
+
check_multiple_nvram_clm(NVRAM, prop_revision_buf, sku_name,
&buffer_nvram, &buf.ota_nvram_len);
if (buffer_nvram == NULL) {
@@ -2870,6 +2925,9 @@ exit:
if (buffer_nvram != NULL) {
free(buffer_nvram);
}
+ if (buffer_txcap_blob != NULL) {
+ free(buffer_txcap_blob);
+ }
cmd->releaseRef();
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
index a24a882..d80b182 100644
--- a/bcmdhd/wifi_hal/wifi_offload.cpp
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
- * Portions copyright (C) 2017 Broadcom Limited
+ * Portions copyright (C) 2023 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.