summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:09:49 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:09:49 +0000
commit353e7d58feafb5313c2f671dc8cb30771b621ce9 (patch)
tree66ed4556cb03968ce064ec6980351f7ab300e9c9
parent20d05a24a8bed01d8ac9f5e044b18fada1efd7c2 (diff)
parent19cb6f27c73ab4f738d0836fa39f1edebffb9559 (diff)
downloadwlan-android13-mainline-media-swcodec-release.tar.gz
Change-Id: I87926a7f9ff795e02f7721bce645c0a6d5fb3b02
-rw-r--r--METADATA3
-rw-r--r--OWNERS3
-rw-r--r--bcmdhd/dhdutil/Android.mk3
-rw-r--r--bcmdhd/dhdutil/bcmutils.c2
-rwxr-xr-xbcmdhd/wifi_hal/Android.mk14
-rwxr-xr-xbcmdhd/wifi_hal/brcm_version.h2
-rwxr-xr-xbcmdhd/wifi_hal/common.cpp64
-rwxr-xr-xbcmdhd/wifi_hal/common.h246
-rwxr-xr-xbcmdhd/wifi_hal/cpp_bindings.cpp47
-rwxr-xr-xbcmdhd/wifi_hal/cpp_bindings.h8
-rwxr-xr-xbcmdhd/wifi_hal/gscan.cpp132
-rw-r--r--bcmdhd/wifi_hal/link_layer_stats.cpp171
-rwxr-xr-xbcmdhd/wifi_hal/nan.cpp695
-rw-r--r--bcmdhd/wifi_hal/rtt.cpp121
-rw-r--r--bcmdhd/wifi_hal/sync.h2
-rwxr-xr-xbcmdhd/wifi_hal/twt.cpp947
-rwxr-xr-xbcmdhd/wifi_hal/wifi_hal.cpp1541
-rwxr-xr-xbcmdhd/wifi_hal/wifi_logger.cpp1385
-rw-r--r--bcmdhd/wifi_hal/wifi_offload.cpp17
-rw-r--r--bcmdhd/wpa_supplicant_8_lib/Android.mk3
20 files changed, 4885 insertions, 521 deletions
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+ license_type: NOTICE
+}
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..d8c95cc
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+arabawy@google.com
+etancohen@google.com
+kumachang@google.com
diff --git a/bcmdhd/dhdutil/Android.mk b/bcmdhd/dhdutil/Android.mk
index 2385abd..c7e7fdc 100644
--- a/bcmdhd/dhdutil/Android.mk
+++ b/bcmdhd/dhdutil/Android.mk
@@ -26,6 +26,9 @@ LOCAL_SRC_FILES := \
miniopt.c
LOCAL_MODULE := dhdutil
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-ISC
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
LOCAL_CFLAGS := -DSDTEST -DTARGETENV_android -Dlinux -DLINUX
ifeq ($(TARGET_ARCH),arm)
LOCAL_CFLAGS += -mabi=aapcs-linux
diff --git a/bcmdhd/dhdutil/bcmutils.c b/bcmdhd/dhdutil/bcmutils.c
index 0fdbe73..655d267 100644
--- a/bcmdhd/dhdutil/bcmutils.c
+++ b/bcmdhd/dhdutil/bcmutils.c
@@ -1776,7 +1776,7 @@ static const char *crypto_algo_names[] = {
"AES_CCM",
"AES_OCB_MSDU",
"AES_OCB_MPDU",
- "NALG"
+ "NALG",
"UNDEF",
"UNDEF",
"UNDEF",
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
index 5763789..471c312 100755
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -41,6 +41,14 @@ LOCAL_C_INCLUDES += \
LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers
+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
+#only for pixel feature
+LOCAL_CFLAGS += -DRING_DUMP
+endif
+
LOCAL_SRC_FILES := \
wifi_hal.cpp \
rtt.cpp \
@@ -50,10 +58,12 @@ LOCAL_SRC_FILES := \
nan.cpp \
link_layer_stats.cpp \
wifi_logger.cpp \
- wifi_offload.cpp
+ wifi_offload.cpp \
+ twt.cpp
LOCAL_MODULE := libwifi-hal-bcm
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_STATIC_LIBRARY)
-
diff --git a/bcmdhd/wifi_hal/brcm_version.h b/bcmdhd/wifi_hal/brcm_version.h
index 14efbee..184d5d5 100755
--- a/bcmdhd/wifi_hal/brcm_version.h
+++ b/bcmdhd/wifi_hal/brcm_version.h
@@ -1 +1 @@
-#define HAL_VERSION "Android-10-FRC2-SDK_29 59.0 (r854927) 2019-12-06 23:33:52 +0530 (Fri, 06 Dec 2019)"
+#define HAL_VERSION "BCMDHD vendor HAL"
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
index c164ba4..5a9d5ab 100755
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -105,14 +105,34 @@ wifi_error wifi_register_vendor_handler(wifi_handle handle,
wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
if (info->num_event_cb < info->alloc_event_cb) {
- info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
- info->event_cb[info->num_event_cb].vendor_id = id;
- info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
- info->event_cb[info->num_event_cb].cb_func = func;
- info->event_cb[info->num_event_cb].cb_arg = arg;
- ALOGV("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
- arg, func, id, subcmd, info->num_event_cb);
- info->num_event_cb++;
+ /* To avoid an unwanted duplication of the record, find first.
+ * Update it if the same record is already exist.
+ * KEY => [nl_cmd, vendor_id, vendor_subcmd]
+ */
+ int i = 0;
+ bool is_update = false;
+ for (i = 0; i < info->num_event_cb; i++) {
+ if ((info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR) &&
+ (info->event_cb[i].vendor_id == id) &&
+ (info->event_cb[i].vendor_subcmd == subcmd)) {
+ is_update = true;
+ break;
+ }
+ }
+
+ if (is_update) {
+ info->event_cb[i].cb_func = func;
+ info->event_cb[i].cb_arg = arg;
+ } else {
+ info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
+ info->event_cb[info->num_event_cb].vendor_id = id;
+ info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
+ info->event_cb[info->num_event_cb].cb_func = func;
+ info->event_cb[info->num_event_cb].cb_arg = arg;
+ info->num_event_cb++;
+ }
+ ALOGI("%s ""event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
+ is_update ? "Updated" : "Added", arg, func, id, subcmd, info->num_event_cb);
result = WIFI_SUCCESS;
}
@@ -146,18 +166,15 @@ void wifi_unregister_handler(wifi_handle handle, int cmd)
pthread_mutex_unlock(&info->cb_lock);
}
-void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
+void wifi_unregister_vendor_handler_without_lock(wifi_handle handle, uint32_t id, int subcmd)
{
hal_info *info = (hal_info *)handle;
- pthread_mutex_lock(&info->cb_lock);
-
for (int i = 0; i < info->num_event_cb; i++) {
-
if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
&& info->event_cb[i].vendor_id == id
&& info->event_cb[i].vendor_subcmd == subcmd) {
- ALOGV("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
+ ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i);
memmove(&info->event_cb[i], &info->event_cb[i+1],
(info->num_event_cb - i - 1) * sizeof(cb_info));
@@ -165,11 +182,17 @@ void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
break;
}
}
+}
+void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
+{
+ hal_info *info = (hal_info *)handle;
+
+ pthread_mutex_lock(&info->cb_lock);
+ wifi_unregister_vendor_handler_without_lock(handle, id, subcmd);
pthread_mutex_unlock(&info->cb_lock);
}
-
wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
{
hal_info *info = (hal_info *)handle;
@@ -263,6 +286,19 @@ wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
return WIFI_ERROR_INVALID_ARGS;
}
+wifi_error wifi_get_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ WifiCommand *cmd = wifi_get_cmd(handle, id);
+ ALOGV("Get Cancel WifiCommand = %p", cmd);
+ if (cmd) {
+ cmd->cancel();
+ cmd->releaseRef();
+ return WIFI_SUCCESS;
+ }
+
+ return WIFI_ERROR_INVALID_ARGS;
+}
void set_hautil_mode(bool util_mode)
{
halutil_mode = util_mode;
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 98801b2..ecc1abf 100755
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -44,6 +44,7 @@
*/
const uint32_t GOOGLE_OUI = 0x001A11;
+const uint32_t BRCM_OUI = 0x001018;
/* TODO: define vendor OUI here */
@@ -53,7 +54,11 @@ const uint32_t GOOGLE_OUI = 0x001A11;
#define NMR2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
#define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
#define NAN_MASTER_RANK_LEN 8
+#define NAN_SCID_INFO_LEN 16
+#define SAR_CONFIG_SCENARIO_COUNT 100
+#define MAX_NUM_RADIOS 3
+#define MAX_CMD_RESP_BUF_LEN 8192
/*
This enum defines ranges for various commands; commands themselves
@@ -102,8 +107,40 @@ typedef enum {
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
/* define all tx power related commands between 0x1900 and 0x1910 */
- ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
- ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x1910,
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
+ ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x1910,
+
+ /* define all thermal mode related commands between 0x1920 and 0x192F */
+ ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_START = 0x1920,
+ ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_END = 0x192F,
+
+ /* define all DSCP related commands between 0x2000 and 0x20FF */
+ ANDROID_NL80211_SUBCMD_DSCP_RANGE_START = 0x2000,
+ ANDROID_NL80211_SUBCMD_DSCP_RANGE_END = 0x20FF,
+
+ /* define all Channel Avoidance related commands between 0x2100 and 0x211F */
+ ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_START = 0x2100,
+ ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_END = 0x211F,
+
+ /* define all OTA Download related commands between 0x2120 and 0x212F */
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START = 0x2120,
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_END = 0x212F,
+
+ /* define all VOIP mode config related commands between 0x2130 and 0x213F */
+ ANDROID_NL80211_SUBCMD_VIOP_MODE_START = 0x2130,
+ ANDROID_NL80211_SUBCMD_VIOP_MODE_END = 0x213F,
+
+ /* define all TWT related commands between 0x2140 and 0x214F */
+ ANDROID_NL80211_SUBCMD_TWT_START = 0x2140,
+ ANDROID_NL80211_SUBCMD_TWT_END = 0x214F,
+
+ /* define all Usable Channel related commands between 0x2150 and 0x215F */
+ ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_START = 0x2150,
+ ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_END = 0x215F,
+
+ /* define all init/deinit related commands between 0x2160 and 0x216F */
+ ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START = 0x2160,
+ ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_END = 0x216F,
/* This is reserved for future usage */
@@ -147,6 +184,9 @@ typedef enum {
WIFI_SUBCMD_FW_ROAM_POLICY, /* 0x1019 */
WIFI_SUBCMD_ROAM_CAPABILITY, /* 0x101a */
WIFI_SUBCMD_SET_LATENCY_MODE, /* 0x101b */
+ WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION, /* 0x101c */
+ WIFI_SUBCMD_SET_MULTISTA_USE_CASE, /* 0x101d */
+ WIFI_SUBCMD_SET_DTIM_CONFIG, /* 0x101e */
GSCAN_SUBCMD_MAX,
@@ -172,7 +212,27 @@ typedef enum {
NAN_SUBCMD_ENABLE_MERGE, /* 0x1712 */
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
+ APF_SUBCMD_READ_FILTER,
WIFI_SUBCMD_TX_POWER_SCENARIO = ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START,
+ WIFI_SUBCMD_THERMAL_MITIGATION = ANDROID_NL80211_SUBCMD_MITIGATION_RANGE_START,
+ DSCP_SUBCMD_SET_TABLE = ANDROID_NL80211_SUBCMD_DSCP_RANGE_START,
+ DSCP_SUBCMD_RESET_TABLE, /* 0x2001 */
+ CHAVOID_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_CHAVOID_RANGE_START,
+
+ TWT_SUBCMD_GETCAPABILITY = ANDROID_NL80211_SUBCMD_TWT_START,
+ TWT_SUBCMD_SETUP_REQUEST,
+ TWT_SUBCMD_TEAR_DOWN_REQUEST,
+ TWT_SUBCMD_INFO_FRAME_REQUEST,
+ TWT_SUBCMD_GETSTATS,
+ TWT_SUBCMD_CLR_STATS,
+
+ WIFI_SUBCMD_CONFIG_VOIP_MODE = ANDROID_NL80211_SUBCMD_VIOP_MODE_START,
+
+ WIFI_SUBCMD_GET_OTA_CURRUNT_INFO = ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START,
+ WIFI_SUBCMD_OTA_UPDATE,
+ WIFI_SUBCMD_USABLE_CHANNEL = ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_START,
+ WIFI_SUBCMD_TRIGGER_SSR = ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START,
+ WIFI_SUBCMD_GET_RADIO_COMBO_MATRIX,
} WIFI_SUB_COMMAND;
typedef enum {
@@ -212,10 +272,14 @@ typedef enum {
NAN_EVENT_SDF = 28,
NAN_EVENT_TCA = 29,
NAN_EVENT_SUBSCRIBE_UNMATCH = 30,
- NAN_EVENT_UNKNOWN,
+ NAN_EVENT_UNKNOWN = 31,
+ BRCM_VENDOR_EVENT_HANGED = 33,
ROAM_EVENT_START,
GOOGLE_FILE_DUMP_EVENT = 37,
- NAN_ASYNC_RESPONSE_DISABLED = 40
+ NAN_ASYNC_RESPONSE_DISABLED = 40,
+ BRCM_VENDOR_EVENT_TWT = 43,
+ BRCM_TPUT_DUMP_EVENT = 44,
+ NAN_EVENT_MATCH_EXPIRY = 45
} WIFI_EVENT;
typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
@@ -239,8 +303,15 @@ typedef struct {
wifi_handle handle; // handle to wifi data
char name[IFNAMSIZ+1]; // interface name + trailing null
int id; // id to use when talking to driver
+ bool is_virtual; // mark each iface as virtual or static
} interface_info;
+typedef enum {
+ NAN_STATE_DISABLED = 0,
+ NAN_STATE_AP = 1,
+ NAN_STATE_CHRE = 2,
+} nan_enab_state_t;
+
typedef struct {
struct nl_sock *cmd_sock; // command socket object
@@ -265,7 +336,11 @@ typedef struct {
interface_info **interfaces; // array of interfaces
int num_interfaces; // number of interfaces
+ int max_num_interfaces; // max number of interfaces
+ wifi_subsystem_restart_handler restart_handler; // trigger sub system handler
+ wifi_chre_handler chre_nan_cb; // chre CB for nan status
+ nan_enab_state_t nan_state; // Nan enable state
// add other details
} hal_info;
@@ -302,11 +377,65 @@ typedef struct wifi_gscan_full_result {
u8 ie_data[1]; // IE data to follow
} wifi_gscan_full_result_t;
+void twt_deinit_handler();
+
+typedef enum {
+ TWT_EVENT_INVALID = 0,
+ TWT_SETUP_RESPONSE = 1,
+ TWT_TEARDOWN_COMPLETION = 2,
+ TWT_INFORM_FRAME = 3,
+ TWT_NOTIFY = 4,
+ TWT_EVENT_LAST
+} TwtEventType;
+
+typedef enum {
+ TWT_INVALID = 0,
+ TWT_SETUP_REQUEST = 1,
+ TWT_INFO_FRAME_REQUEST = 2,
+ TWT_TEAR_DOWN_REQUEST = 3,
+ TWT_LAST
+} TwtRequestType;
+
+typedef enum {
+ TWT_ATTRIBUTE_INVALID = 0,
+ TWT_ATTRIBUTE_CONFIG_ID = 1,
+ TWT_ATTRIBUTE_NEG_TYPE = 2,
+ TWT_ATTRIBUTE_TRIGGER_TYPE = 3,
+ TWT_ATTRIBUTE_WAKE_DUR_US = 4,
+ TWT_ATTRIBUTE_WAKE_INT_US = 5,
+ TWT_ATTRIBUTE_WAKE_INT_MIN_US = 6,
+ TWT_ATTRIBUTE_WAKE_INT_MAX_US = 7,
+ TWT_ATTRIBUTE_WAKE_DUR_MIN_US = 8,
+ TWT_ATTRIBUTE_WAKE_DUR_MAX_US = 9,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE = 10,
+ TWT_ATTRIBUTE_AVG_PKT_NUM = 11,
+ TWT_ATTRIBUTE_WAKE_TIME_OFF_US = 12,
+ TWT_ATTRIBUTE_ALL_TWT = 13,
+ TWT_ATTRIBUTE_RESUME_TIME_US = 14,
+ TWT_ATTRIBUTE_AVG_EOSP_DUR = 15,
+ TWT_ATTRIBUTE_EOSP_COUNT = 16,
+ TWT_ATTRIBUTE_NUM_SP = 17,
+ TWT_ATTRIBUTE_DEVICE_CAP = 18,
+ TWT_ATTRIBUTE_PEER_CAP = 19,
+ TWT_ATTRIBUTE_STATUS = 20,
+ TWT_ATTRIBUTE_REASON_CODE = 21,
+ TWT_ATTRIBUTE_RESUMED = 22,
+ TWT_ATTRIBUTE_NOTIFICATION = 23,
+ TWT_ATTRIBUTE_SUB_EVENT = 24,
+ TWT_ATTRIBUTE_NUM_PEER_STATS = 25,
+ TWT_ATTRIBUTE_AVG_PKT_NUM_TX = 26,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE_TX = 27,
+ TWT_ATTRIBUTE_AVG_PKT_NUM_RX = 28,
+ TWT_ATTRIBUTE_AVG_PKT_SIZE_RX = 29,
+ TWT_ATTRIBUTE_MAX
+} TWT_ATTRIBUTE;
+
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
wifi_error wifi_register_vendor_handler(wifi_handle handle,
uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg);
void wifi_unregister_handler(wifi_handle handle, int cmd);
+void wifi_unregister_vendor_handler_without_lock(wifi_handle handle, uint32_t id, int subcmd);
void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd);
wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd);
@@ -321,18 +450,127 @@ hal_info *getHalInfo(wifi_interface_handle handle);
wifi_handle getWifiHandle(hal_info *info);
wifi_interface_handle getIfaceHandle(interface_info *info);
wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
+wifi_error wifi_get_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
wifi_error nan_deinit_handler();
wifi_error wifi_start_hal(wifi_interface_handle iface);
wifi_error wifi_stop_hal(wifi_interface_handle iface);
wifi_interface_handle wifi_get_wlan_interface(wifi_handle info,
wifi_interface_handle *ifaceHandles, int numIfaceHandles);
+#ifdef RING_DUMP
+wifi_error wifi_start_ring_dump(wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler ring_handle);
+wifi_error wifi_stop_ring_dump(wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler ring_handle);
+#endif /* RING_DUMP */
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version);
wifi_error wifi_hal_preInit(wifi_interface_handle iface);
/* API to get wake reason statistics */
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
+ wifi_interface_type iface_type);
+wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname);
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels,
+ wifi_coex_unsafe_channel channels[], u32 restrictions);
+wifi_error wifi_set_voip_mode(wifi_interface_handle handle, wifi_voip_mode mode);
+wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier);
void set_hautil_mode(bool halutil_mode);
bool get_halutil_mode();
+/* API's to support TWT */
+
+/**@brief twt_get_capability
+ * Request TWT capability
+ * @param wifi_interface_handle:
+ * @return Synchronous wifi_error and TwtCapabilitySet
+ */
+wifi_error twt_get_capability(wifi_interface_handle iface, TwtCapabilitySet* twt_cap_set);
+
+/**@brief twt_register_handler
+ * Request to register TWT callback
+ * @param wifi_interface_handle:
+ * @param TwtCallbackHandler:
+ * @return Synchronous wifi_error
+ */
+wifi_error twt_register_handler(wifi_interface_handle iface, TwtCallbackHandler handler);
+
+/**@brief twt_setup_request
+ * Request to send TWT setup frame
+ * @param wifi_interface_handle:
+ * @param TwtSetupRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtSetupResponse CB return TwtSetupResponse
+ */
+wifi_error twt_setup_request(wifi_interface_handle iface, TwtSetupRequest* msg);
+
+/**@brief twt_teardown_request
+ * Request to send TWT teardown frame
+ * @param wifi_interface_handle:
+ * @param TwtTeardownRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtTeardownCompletion CB return TwtTeardownCompletion
+ * TwtTeardownCompletion may also be received due to other events
+ * like CSA, BTCX, TWT scheduler, MultiConnection, peer-initiated teardown, etc.
+ */
+wifi_error twt_teardown_request(wifi_interface_handle iface, TwtTeardownRequest* msg);
+
+/**@brief twt_info_frame_request
+ * Request to send TWT info frame
+ * @param wifi_interface_handle:
+ * @param TwtInfoFrameRequest:
+ * @return Synchronous wifi_error
+ * @return Asynchronous EventTwtInfoFrameReceived CB return TwtInfoFrameReceived
+ * Driver may also receive Peer-initiated TwtInfoFrame
+ */
+wifi_error twt_info_frame_request(wifi_interface_handle iface, TwtInfoFrameRequest* msg);
+
+/**@brief twt_get_stats
+ * Request to get TWT stats
+ * @param wifi_interface_handle:
+ * @param config_id:
+ * @return Synchronous wifi_error and TwtStats
+ */
+wifi_error twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* stats);
+
+/**@brief twt_clear_stats
+ * Request to clear TWT stats
+ * @param wifi_interface_handle:
+ * @param config_id:
+ * @return Synchronous wifi_error
+ */
+wifi_error twt_clear_stats(wifi_interface_handle iface, u8 config_id);
+
+wifi_error wifi_trigger_subsystem_restart(wifi_handle handle);
+
+/**@brief nan_chre_enable_request
+ * Request from CHRE to enable NAN
+ * @param transaction id:
+ * @param wifi_interface_handle:
+ * @param NanEnableRequest:
+ * @return Synchronous wifi_error
+ */
+wifi_error nan_chre_enable_request(transaction_id id,
+ wifi_interface_handle iface,
+ NanEnableRequest* msg);
+
+/**@brief nan_chre_disable_request
+ * Request from CHRE to disable NAN
+ * @param transaction id:
+ * @param wifi_interface_handle:
+ * @return Synchronous wifi_error
+ */
+wifi_error nan_chre_disable_request(transaction_id id,
+ wifi_interface_handle iface);
+
+/**@brief nan_chre_register_handler
+ * Register chre handler to handle NAN status
+ * @param wifi_interface_handle:
+ * @param wifi_chre_handler:
+ * @return Synchronous wifi_error
+ */
+wifi_error nan_chre_register_handler(wifi_interface_handle iface,
+ wifi_chre_handler handler);
+
// some common macros
#define min(x, y) ((x) < (y) ? (x) : (y))
diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp
index 5ca6431..7a634bd 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.cpp
+++ b/bcmdhd/wifi_hal/cpp_bindings.cpp
@@ -579,27 +579,56 @@ int WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) {
}
}
+static int mapErrorCodes(int err)
+{
+ int ret;
+ if (!err) {
+ return WIFI_SUCCESS;
+ }
+ switch (err) {
+ case -EOPNOTSUPP:
+ ret = WIFI_ERROR_NOT_SUPPORTED;
+ break;
+ case -ETIMEDOUT:
+ ret = WIFI_ERROR_TIMED_OUT;
+ break;
+ case -EINVAL:
+ ret = WIFI_ERROR_INVALID_ARGS;
+ break;
+ case -ENOMEM:
+ ret = WIFI_ERROR_OUT_OF_MEMORY;
+ break;
+ case -EBUSY:
+ ret = WIFI_ERROR_BUSY;
+ break;
+ default:
+ ret = WIFI_ERROR_UNKNOWN;
+ }
+ ALOGD("error code %d mapped to %d", err, ret);
+ return ret;
+}
+
int WifiRequest::create(uint32_t id, int subcmd) {
int res = create(NL80211_CMD_VENDOR);
if (res < 0) {
- return res;
+ return mapErrorCodes(res);
}
res = put_u32(NL80211_ATTR_VENDOR_ID, id);
if (res < 0) {
- return res;
+ return mapErrorCodes(res);
}
res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd);
if (res < 0) {
- return res;
+ return mapErrorCodes(res);
}
if (mIface != -1) {
res = set_iface_id(mIface);
}
- return res;
+ return mapErrorCodes(res);
}
@@ -618,8 +647,7 @@ int WifiCommand::requestResponse() {
}
int WifiCommand::requestResponse(WifiRequest& request) {
- pthread_mutex_lock(&ResponseMutex);
- int err = 0, res = 0;
+ int err = 0;
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb)
@@ -645,8 +673,7 @@ int WifiCommand::requestResponse(WifiRequest& request) {
}
out:
nl_cb_put(cb);
- pthread_mutex_unlock(&ResponseMutex);
- return err;
+ return mapErrorCodes(err);
}
int WifiCommand::requestEvent(int cmd) {
@@ -675,7 +702,7 @@ int WifiCommand::requestEvent(int cmd) {
out:
wifi_unregister_handler(wifiHandle(), cmd);
- return res;
+ return mapErrorCodes(res);
}
int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) {
@@ -699,7 +726,7 @@ int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) {
out:
wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
- return res;
+ return mapErrorCodes(res);
}
/* Event handlers */
diff --git a/bcmdhd/wifi_hal/cpp_bindings.h b/bcmdhd/wifi_hal/cpp_bindings.h
index 8839a72..8b5600a 100755
--- a/bcmdhd/wifi_hal/cpp_bindings.h
+++ b/bcmdhd/wifi_hal/cpp_bindings.h
@@ -126,7 +126,7 @@ public:
return pos;
}
uint16_t get_type() {
- return pos->nla_type;
+ return nla_type(pos);
}
uint8_t get_u8() {
return nla_get_u8(pos);
@@ -278,7 +278,7 @@ public:
virtual void addRef() {
int refs = __sync_add_and_fetch(&mRefs, 1);
- // ALOGD("addRef: WifiCommand %p has %d references", this, refs);
+ ALOGV("addRef: WifiCommand %p has %d references", this, refs);
}
virtual void releaseRef() {
@@ -347,6 +347,10 @@ protected:
return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
}
+ void unregisterVendorHandlerWithoutLock(uint32_t id, int subcmd) {
+ wifi_unregister_vendor_handler_without_lock(wifiHandle(), id, subcmd);
+ }
+
void unregisterVendorHandler(uint32_t id, int subcmd) {
wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
}
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
index f5722f2..995c989 100755
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -235,7 +235,7 @@ class GetCapabilitiesCommand : public WifiCommand
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
- ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %zd", id, subcmd, len,
+ ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %d", id, subcmd, len,
mRequestsize);
memcpy(mCapabilities, data, min(len, mRequestsize));
@@ -252,6 +252,7 @@ wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
return (wifi_error) command.requestResponse();
}
+/* Function to get chipset supported roaming capabilities */
wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
wifi_roaming_capabilities *capabilities)
{
@@ -345,48 +346,6 @@ wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
/////////////////////////////////////////////////////////////////////////////
/* helper functions */
-
-static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
-{
- memset(results, 0, sizeof(wifi_scan_result) * num);
-
- int i = 0;
- for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
-
- int index = it.get_type();
- ALOGI("retrieved scan result %d", index);
- nlattr *sc_data = (nlattr *) it.get_data();
- wifi_scan_result *result = results + i;
-
- for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
- int type = it2.get_type();
- if (type == GSCAN_ATTRIBUTE_SSID) {
- strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
- result->ssid[it2.get_len()] = 0;
- } else if (type == GSCAN_ATTRIBUTE_BSSID) {
- memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
- } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
- result->ts = it2.get_u64();
- } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
- result->ts = it2.get_u16();
- } else if (type == GSCAN_ATTRIBUTE_RSSI) {
- result->rssi = it2.get_u8();
- } else if (type == GSCAN_ATTRIBUTE_RTT) {
- result->rtt = it2.get_u64();
- } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
- result->rtt_sd = it2.get_u64();
- }
- }
-
- }
-
- if (i >= num) {
- ALOGE("Got too many results; skipping some");
- }
-
- return i;
-}
-
int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
int result = request.create(GOOGLE_OUI, subcmd);
@@ -413,7 +372,7 @@ public:
FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
wifi_scan_result_handler handler)
: WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
- { }
+ {*mParams = 0;}
int createRequest(WifiRequest& request, int subcmd, int enable) {
int result = request.create(GOOGLE_OUI, subcmd);
@@ -445,8 +404,8 @@ public:
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
- ALOGE("failed to enable full scan results; result = %d", result);
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
+ ALOGE("failed to enable full scan results; result = %d", result);
return result;
}
@@ -607,6 +566,12 @@ public:
return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
}
+ void unregisterVendorHandlerAll() {
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
+ }
+
int start() {
ALOGV("GSCAN start");
WifiRequest request(familyId(), ifaceId());
@@ -616,8 +581,13 @@ public:
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
+
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandlerAll();
ALOGE("failed to configure setup; result = %d", result);
return result;
}
@@ -626,12 +596,14 @@ public:
result = createScanConfigRequest(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandlerAll();
ALOGE("failed to create scan config request; result = %d", result);
return result;
}
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandlerAll();
ALOGE("failed to configure scan; result = %d", result);
return result;
}
@@ -640,20 +612,15 @@ public:
result = createStartRequest(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandlerAll();
ALOGE("failed to create start request; result = %d", result);
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandlerAll();
ALOGE("failed to start scan; result = %d", result);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
return result;
}
return result;
@@ -673,9 +640,7 @@ public:
}
}
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
+ unregisterVendorHandlerAll();
return WIFI_SUCCESS;
}
@@ -744,7 +709,6 @@ wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
if (id == -1) {
wifi_scan_result_handler handler;
wifi_scan_cmd_params dummy_params;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
@@ -803,7 +767,7 @@ int wifi_handle_full_scan_event(
wifi_gscan_result_t *fixed = &drv_res->fixed;
if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
- ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len,
+ ALOGE("BAD event data, len %d ie_len %d fixed length %lu!\n", len,
ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
return NL_SKIP;
}
@@ -818,7 +782,7 @@ int wifi_handle_full_scan_event(
if(handler.on_full_scan_result)
handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
- ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n",
+ ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %ld %lx %lx %x %d\n",
fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length);
@@ -830,11 +794,9 @@ int wifi_handle_full_scan_event(
wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
{
ALOGV("Disabling full scan results");
- wifi_handle handle = getWifiHandle(iface);
if(id == -1) {
wifi_scan_result_handler handler;
- wifi_handle handle = getWifiHandle(iface);
int params_dummy;
memset(&handler, 0, sizeof(handler));
@@ -1101,6 +1063,11 @@ public:
return result;
}
+ void unregisterVendorHandlerAll() {
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
+ }
+
int start() {
ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid);
WifiRequest request(familyId(), ifaceId());
@@ -1109,27 +1076,26 @@ public:
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
+
result = requestResponse(request);
if (result < 0) {
+ unregisterVendorHandlerAll();
ALOGI("Failed to execute hotlist setup request, result = %d", result);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
return result;
}
ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid);
result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
if (result < 0) {
+ unregisterVendorHandlerAll();
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-
result = requestResponse(request);
if (result < 0) {
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
+ unregisterVendorHandlerAll();
return result;
}
@@ -1139,8 +1105,7 @@ public:
virtual int cancel() {
/* unregister event handler */
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
- unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
+ unregisterVendorHandlerAll();
/* create set hotlist message with empty hotlist */
WifiRequest request(familyId(), ifaceId());
int result = createTeardownRequest(request);
@@ -1329,15 +1294,15 @@ public:
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
result = requestResponse(request);
if (result < 0) {
- ALOGI("Failed to execute ePNO setup request, result = %d", result);
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
+ ALOGI("Failed to execute ePNO setup request, result = %d", result);
return result;
}
ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
ALOGI("successfully restarted the scan");
return result;
}
@@ -1368,7 +1333,6 @@ public:
virtual int handleEvent(WifiEvent& event) {
ALOGI("ePNO event");
- int event_id = event.get_vendor_subcmd();
// event.log();
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -1537,8 +1501,11 @@ public:
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
+
result = requestResponse(request);
if (result < 0) {
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
ALOGI("failed to set significant wifi change config %d", result);
return result;
}
@@ -1547,11 +1514,10 @@ public:
result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
if (result < 0) {
+ unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
return result;
}
- registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
-
result = requestResponse(request);
if (result < 0) {
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
@@ -1661,7 +1627,6 @@ wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
{
if (id == -1) {
wifi_epno_handler handler;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
@@ -1677,6 +1642,9 @@ wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
const wifi_epno_params *params, wifi_epno_handler handler)
{
wifi_handle handle = getWifiHandle(iface);
+ if (handler.on_network_found == NULL) {
+ return WIFI_ERROR_INVALID_ARGS;
+ }
ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -1761,8 +1729,6 @@ class BssidBlacklistCommand : public WifiCommand
wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
wifi_bssid_params params)
{
- wifi_handle handle = getWifiHandle(iface);
-
BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();
@@ -1936,8 +1902,8 @@ public:
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
- ALOGE("failed to set ANQPO networks; result = %d", result);
unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
+ ALOGE("failed to set ANQPO networks; result = %d", result);
return result;
}
@@ -2004,11 +1970,11 @@ public:
ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
- ALOGI("%d\t", mResult->rssi);
- ALOGI("%d\t", mResult->channel);
- ALOGI("%lld\t", mResult->ts);
- ALOGI("%lld\t", mResult->rtt);
- ALOGI("%lld\n", mResult->rtt_sd);
+ ALOGI("rssi:%d\t", mResult->rssi);
+ ALOGI("channel:%d\t", mResult->channel);
+ ALOGI("ts:0x%jx\t", mResult->ts);
+ ALOGI("rtt:0x%jx\t", mResult->rtt);
+ ALOGI("rtt_sd:0x%jx\n", mResult->rtt_sd);
if(*mHandler.on_passpoint_network_found)
(*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 34226f4..3a922db 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -37,12 +37,19 @@
#define LOG_TAG "WifiHAL"
-#include <log/log.h>
+#include <utils/Log.h>
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
+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
+} LINK_STAT_ATTRIBUTE;
+
/* Internal radio statistics structure in the driver */
typedef struct {
wifi_radio radio;
@@ -85,6 +92,12 @@ public:
protected:
virtual int handleResponse(WifiEvent& reply) {
+ void *data = NULL;
+ 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;
// ALOGI("In GetLinkStatsCommand::handleResponse");
@@ -93,31 +106,153 @@ protected:
return NL_SKIP;
}
- int id = reply.get_vendor_id();
- int subcmd = reply.get_vendor_subcmd();
-
- // ALOGI("Id = %0x, subcmd = %d", id, subcmd);
+ id = reply.get_vendor_id();
+ subcmd = reply.get_vendor_subcmd();
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ len = reply.get_vendor_data_len();
- void *data = reply.get_vendor_data();
- int len = reply.get_vendor_data_len();
- wifi_radio_stat *radio_stat =
- convertToExternalRadioStatStructure((wifi_radio_stat_internal *)data);
- if (!radio_stat) {
- ALOGE("Invalid stats pointer received");
+ ALOGV("Id = %0x, subcmd = %d, len = %d\n", id, subcmd, len);
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetLinkStatCommand response; ignoring it");
return NL_SKIP;
}
- wifi_iface_stat *iface_stat =
- (wifi_iface_stat *)((char *)&((wifi_radio_stat_internal *)data)->channels
- + radio_stat->num_channels * sizeof(wifi_channel_stat));
- (*mHandler.on_link_stats_results)(id, iface_stat, 1, radio_stat);
- free(radio_stat);
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ 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_len = it.get_len();
+ } else {
+ ALOGW("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ }
+ }
+
+ if (num_radios) {
+ 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;
+
+ if (!data || !data_len) {
+ ALOGE("%s: null data\n", __func__);
+ return NL_SKIP;
+ }
+
+ data_ptr = (u8*)data;
+ for (int i = 0; i < num_radios; i++) {
+ rem_len -= per_radio_size;
+ if (rem_len < per_radio_size) {
+ ALOGE("No data left for radio %d\n", i);
+ goto exit;
+ }
+ data_ptr = (u8*)data + total_size;
+ if (!data_ptr) {
+ ALOGE("Invalid data for radio index = %d\n", i);
+ goto exit;
+ }
+ radio_stat_ptr =
+ convertToExternalRadioStatStructure((wifi_radio_stat*)data_ptr,
+ &per_radio_size);
+ if (!radio_stat_ptr || !per_radio_size) {
+ 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;
+ }
+
+ 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);
+ goto exit;
+ }
+ (*mHandler.on_link_stats_results)(id, (wifi_iface_stat *)iface_stat,
+ num_radios, (wifi_radio_stat *)radioStatsBuf);
+ } else {
+ /* To be deprecated, adding it to keep it backward compatible */
+ ALOGD("GetLinkStatCommand: zero radio case\n");
+ data = reply.get_vendor_data();
+ if (!data) {
+ ALOGE("Invalid vendor data received\n");
+ return NL_SKIP;
+ }
+
+ num_radios = 1;
+ data = reply.get_vendor_data();
+ len = reply.get_vendor_data_len();
+ if (!data || !len) {
+ ALOGE("Invalid vendor data received\n");
+ return NL_SKIP;
+ }
+ radio_stat_ptr =
+ convertToExternalRadioStatStructureLegacy((wifi_radio_stat_internal *)data);
+ if (!radio_stat_ptr) {
+ ALOGE("Invalid stats pointer received\n");
+ return NL_SKIP;
+ }
+ wifi_iface_stat *iface_stat =
+ (wifi_iface_stat *)((char *)&((wifi_radio_stat_internal *)data)->channels
+ + radio_stat_ptr->num_channels * sizeof(wifi_channel_stat));
+ (*mHandler.on_link_stats_results)(id, iface_stat, num_radios, radio_stat_ptr);
+ }
+exit:
+ if (radio_stat_ptr) {
+ free(radio_stat_ptr);
+ radio_stat_ptr = NULL;
+ }
+ if (radioStatsBuf) {
+ free(radioStatsBuf);
+ radioStatsBuf = NULL;
+ }
return NL_OK;
}
private:
- wifi_radio_stat *convertToExternalRadioStatStructure(wifi_radio_stat_internal *internal_stat_ptr) {
+ wifi_radio_stat *convertToExternalRadioStatStructure(wifi_radio_stat *internal_stat_ptr,
+ uint32_t *per_radio_size) {
+ wifi_radio_stat *external_stat_ptr = NULL;
+ if (!internal_stat_ptr) {
+ ALOGE("Incoming data is null\n");
+ } else {
+ uint32_t channel_size = internal_stat_ptr->num_channels * sizeof(wifi_channel_stat);
+ *per_radio_size = offsetof(wifi_radio_stat, channels) + channel_size;
+ external_stat_ptr = (wifi_radio_stat *)malloc(*per_radio_size);
+ if (external_stat_ptr) {
+ external_stat_ptr->radio = internal_stat_ptr->radio;
+ external_stat_ptr->on_time = internal_stat_ptr->on_time;
+ external_stat_ptr->tx_time = internal_stat_ptr->tx_time;
+ external_stat_ptr->num_tx_levels = internal_stat_ptr->num_tx_levels;
+ external_stat_ptr->tx_time_per_levels = NULL;
+ external_stat_ptr->rx_time = internal_stat_ptr->rx_time;
+ external_stat_ptr->on_time_scan = internal_stat_ptr->on_time_scan;
+ external_stat_ptr->on_time_nbd = internal_stat_ptr->on_time_nbd;
+ external_stat_ptr->on_time_gscan = internal_stat_ptr->on_time_gscan;
+ external_stat_ptr->on_time_roam_scan = internal_stat_ptr->on_time_roam_scan;
+ external_stat_ptr->on_time_pno_scan = internal_stat_ptr->on_time_pno_scan;
+ external_stat_ptr->on_time_hs20 = internal_stat_ptr->on_time_hs20;
+ external_stat_ptr->num_channels = internal_stat_ptr->num_channels;
+ if (internal_stat_ptr->num_channels) {
+ memcpy(&(external_stat_ptr->channels), &(internal_stat_ptr->channels),
+ channel_size);
+ }
+ }
+ }
+ return external_stat_ptr;
+ }
+
+ wifi_radio_stat *convertToExternalRadioStatStructureLegacy(wifi_radio_stat_internal *internal_stat_ptr) {
wifi_radio_stat *external_stat_ptr = NULL;
- if (internal_stat_ptr) {
+ if (!internal_stat_ptr) {
+ ALOGE("Sta_ptr is null\n");
+ } else {
uint32_t channel_size = internal_stat_ptr->num_channels * sizeof(wifi_channel_stat);
uint32_t total_size = sizeof(wifi_radio_stat) + channel_size;
external_stat_ptr = (wifi_radio_stat *)malloc(total_size);
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
index cfabfa8..52f29e3 100755
--- 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) 2019 Broadcom Limited
+ * Portions copyright (C) 2017 Broadcom Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -286,7 +286,12 @@ typedef enum {
NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL = 224,
NAN_ATTRIBUTE_NSS = 225,
NAN_ATTRIBUTE_ENABLE_RANGING = 226,
- NAN_ATTRIBUTE_DW_EARLY_TERM = 227
+ NAN_ATTRIBUTE_DW_EARLY_TERM = 227,
+ NAN_ATTRIBUTE_CHANNEL_INFO = 228,
+ NAN_ATTRIBUTE_NUM_CHANNELS = 229,
+ NAN_ATTRIBUTE_INSTANT_MODE_ENABLE = 230,
+ NAN_ATTRIBUTE_INSTANT_COMM_CHAN = 231,
+ NAN_ATTRIBUTE_CHRE_REQUEST = 232,
} NAN_ATTRIBUTE;
typedef enum {
@@ -310,7 +315,6 @@ 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_LAST = 0xFFFF
} NanRequestType;
@@ -381,41 +385,7 @@ static int is_cmd_response(int cmd);
static int get_svc_hash(unsigned char *svc_name, u16 svc_name_len,
u8 *svc_hash, u16 svc_hash_len);
NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd);
-static NanStatusType nan_map_term_status(u32 vendor_reason);
static NanStatusType nan_map_response_status(int vendor_status);
-static int ioctl_sock = 0;
-
-static int setFlags(int s, struct ifreq *ifr, int set, int clr)
-{
- if(ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- ifr->ifr_flags = (ifr->ifr_flags & (~clr)) | set;
- if (ioctl(s, SIOCSIFFLAGS, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- return WIFI_SUCCESS;
-}
-
-static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
-{
- sin->sin_family = AF_INET;
- sin->sin_port = 0;
- sin->sin_addr.s_addr = inet_addr(addr);
-}
-
-static int setAddr(int s, struct ifreq *ifr, const char *addr)
-{
- init_sockaddr_in((struct sockaddr_in *) &ifr->ifr_addr, addr);
-
- if (ioctl(s, SIOCSIFADDR, ifr) < 0) {
- return WIFI_ERROR_UNKNOWN;
- }
-
- return WIFI_SUCCESS;
-}
/* Function to separate the common events to NAN1.0 events */
static int is_de_event(int cmd) {
@@ -429,6 +399,7 @@ static int is_de_event(int cmd) {
case NAN_EVENT_FOLLOWUP:
case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
case NAN_EVENT_PUBLISH_REPLIED_IND:
+ case NAN_EVENT_MATCH_EXPIRY:
is_de_evt = true;
break;
default:
@@ -574,6 +545,30 @@ class NanHandle
};
+void HandleExpiryEvent(nan_hal_info_t info, nlattr *vendor_data) {
+ ALOGI("Received NAN_EVENT_MATCH_EXPIRY\n");
+ u16 attr_type;
+ NanMatchExpiredInd expired_event;
+ memset(&expired_event, 0, sizeof(NanMatchExpiredInd));
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+ expired_event.publish_subscribe_id = it.get_u16();
+ ALOGI("pub_sub id = %u\n",
+ expired_event.publish_subscribe_id);
+ } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+ expired_event.requestor_instance_id = it.get_u32();
+ ALOGI("req_inst id = %u\n", expired_event.requestor_instance_id);
+ }
+ }
+
+ if (expired_event.requestor_instance_id && expired_event.publish_subscribe_id) {
+ GET_NAN_HANDLE(info)->mHandlers.EventMatchExpired(&expired_event);
+ } else {
+ ALOGE("Invalid values for notifying the expired event, dropping the event\n");
+ }
+}
///////////////////////////////////////////////////////////////////////////////
class NanDiscEnginePrimitive : public WifiCommand
@@ -664,7 +659,7 @@ class NanDiscEnginePrimitive : public WifiCommand
mInstId = mParams->publish_id;
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
if (result < 0) {
ALOGE("%s: Failed to fill pub id, result = %d\n", __func__, result);
return result;
@@ -865,6 +860,11 @@ class NanDiscEnginePrimitive : public WifiCommand
}
if (mParams->scid_len) {
+ if ((mParams->scid_len > NAN_MAX_SCID_BUF_LEN) ||
+ (mParams->scid_len % NAN_SCID_INFO_LEN)) {
+ ALOGE("%s: Invalid scid len, = %d\n", __func__, mParams->scid_len);
+ return NAN_STATUS_INVALID_PARAM;
+ }
result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
mParams->scid_len);
if (result < 0) {
@@ -967,7 +967,7 @@ class NanDiscEnginePrimitive : public WifiCommand
}
ALOGI("%s: pub id = %d, inst_id = %d\n", __func__, mParams->publish_id, mInstId);
- result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
if (result < 0) {
ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_ID, result = %d\n",
__func__, result);
@@ -1176,7 +1176,45 @@ class NanDiscEnginePrimitive : public WifiCommand
return result;
}
+ result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+ mParams->cipher_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_CIPHER_SUITE_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+ mParams->key_info.key_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill NAN_ATTRIBUTE_KEY_TYPE, result = %d\n",
+ __func__, result);
+ return result;
+ }
+
+ if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+ if (mParams->key_info.body.pmk_info.pmk_len) {
+ result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+ return result;
+ }
+ result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+ (void *)mParams->key_info.body.pmk_info.pmk,
+ mParams->key_info.body.pmk_info.pmk_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+ }
+
if (mParams->scid_len) {
+ if (mParams->scid_len != NAN_SCID_INFO_LEN) {
+ ALOGE("%s: Invalid scid len, = %d\n", __func__, mParams->scid_len);
+ return NAN_STATUS_INVALID_PARAM;
+ }
result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
mParams->scid_len);
if (result < 0) {
@@ -1184,7 +1222,6 @@ class NanDiscEnginePrimitive : public WifiCommand
return result;
}
- prhex(NULL, mParams->scid, mParams->scid_len);
result = request.put(NAN_ATTRIBUTE_SCID,
(void *)mParams->scid, mParams->scid_len);
if (result < 0) {
@@ -1513,7 +1550,6 @@ class NanDiscEnginePrimitive : public WifiCommand
int handleEvent(WifiEvent& event) {
int cmd = event.get_vendor_subcmd();
u16 attr_type;
- int result;
ALOGI("Received NanDiscEnginePrimitive event: %d\n", event.get_cmd());
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -1528,15 +1564,16 @@ class NanDiscEnginePrimitive : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- pub_term_event.publish_id = it.get_u16();
+ pub_term_event.publish_id = it.get_u32();
ALOGI("pub id = %u", pub_term_event.publish_id);
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(pub_term_event.nan_reason, it.get_data(),
- sizeof(pub_term_event.nan_reason));
- ALOGI("pub termination reason: %s", pub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason));
+ memcpy(pub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("pub termination reason: %s, len = %d\n",
+ pub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr: %u\n", attr_type);
}
@@ -1560,7 +1597,7 @@ class NanDiscEnginePrimitive : public WifiCommand
ALOGI("sub id: %u", it.get_u16());
subscribe_event.publish_subscribe_id = it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("pub id: %u", it.get_u16());
+ ALOGI("pub id: %u", it.get_u32());
subscribe_event.requestor_instance_id = it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
@@ -1656,9 +1693,10 @@ 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) {
- memcpy(sub_term_event.nan_reason, it.get_data(),
- sizeof(sub_term_event.nan_reason));
- ALOGI("sub termination reason: %s", sub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason));
+ memcpy(sub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("sub termination nan reason: %s, len = %d\n",
+ sub_term_event.nan_reason, len);
} else {
ALOGI("Unknown attr: %d\n", attr_type);
}
@@ -1666,7 +1704,9 @@ class NanDiscEnginePrimitive : public WifiCommand
GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
break;
-
+ case NAN_EVENT_MATCH_EXPIRY:
+ HandleExpiryEvent(info, vendor_data);
+ break;
case NAN_EVENT_FOLLOWUP:
NanFollowupInd followup_event;
memset(&followup_event, 0, sizeof(NanFollowupInd));
@@ -1705,9 +1745,10 @@ 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) {
- memcpy(followup_ind.nan_reason, it.get_data(),
- sizeof(followup_ind.nan_reason));
- ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason));
+ memcpy(followup_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
+ followup_ind.nan_reason, len);
}
}
GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
@@ -1845,7 +1886,7 @@ class NanDataPathPrimitive : public WifiCommand
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+ result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
if (result < 0) {
ALOGE("%s: Failed to fill instance id = %d, result = %d\n",
__func__, mParams->requestor_instance_id, result);
@@ -2018,6 +2059,26 @@ class NanDataPathPrimitive : public WifiCommand
}
}
+ if (mParams->scid_len) {
+ if (mParams->scid_len != NAN_SCID_INFO_LEN) {
+ ALOGE("%s: Invalid scid len, = %d\n", __func__, mParams->scid_len);
+ return NAN_STATUS_INVALID_PARAM;
+ }
+ result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+ mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ result = request.put(NAN_ATTRIBUTE_SCID,
+ (void *)mParams->scid, mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
request.attr_end(data);
return WIFI_SUCCESS;
}
@@ -2163,6 +2224,27 @@ class NanDataPathPrimitive : public WifiCommand
}
}
+ if (mParams->scid_len) {
+ if (mParams->scid_len != NAN_SCID_INFO_LEN) {
+ ALOGE("%s: Invalid scid len, = %d\n", __func__, mParams->scid_len);
+ return NAN_STATUS_INVALID_PARAM;
+ }
+ result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+ mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+ return result;
+ }
+
+ prhex(NULL, mParams->scid, mParams->scid_len);
+ result = request.put(NAN_ATTRIBUTE_SCID,
+ (void *)mParams->scid, mParams->scid_len);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
request.attr_end(data);
return WIFI_SUCCESS;
}
@@ -2226,10 +2308,10 @@ class NanDataPathPrimitive : public WifiCommand
case NAN_DP_INTERFACE_DELETE:
case NAN_DP_INITIATOR_RESPONSE:
case NAN_DP_RESPONDER_RESPONSE:
- case NAN_DP_END:
+ case NAN_DP_END:
valid = true;
break;
- default:
+ default:
ALOGE("NanDataPathPrmitive::Unknown cmd Response: %d\n", response_type);
break;
}
@@ -2304,8 +2386,8 @@ class NanDataPathPrimitive : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("publish_id: %u", it.get_u16());
- ndp_request_event.service_instance_id = it.get_u16();
+ ALOGI("publish_id: %u\n", it.get_u32());
+ ndp_request_event.service_instance_id = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(ndp_request_event.peer_disc_mac_addr,
@@ -2314,17 +2396,17 @@ class NanDataPathPrimitive : public WifiCommand
MAC2STR(ndp_request_event.peer_disc_mac_addr));
} else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
- ALOGI("ndp id: %u", it.get_u32());
+ ALOGI("ndp id: %u\n", it.get_u32());
ndp_request_event.ndp_instance_id = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_SECURITY) {
- ALOGI("security: %u",
+ ALOGI("security: %u\n",
(NanDataPathSecurityCfgStatus)it.get_u8());
ndp_request_event.ndp_cfg.security_cfg =
(NanDataPathSecurityCfgStatus)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_QOS) {
- ALOGI("QoS: %u", (NanDataPathQosCfg)it.get_u8());
+ ALOGI("QoS: %u\n", (NanDataPathQosCfg)it.get_u8());
ndp_request_event.ndp_cfg.qos_cfg = (NanDataPathQosCfg)it.get_u8();
} else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
@@ -2336,7 +2418,17 @@ class NanDataPathPrimitive : public WifiCommand
ndp_ind_app_info_len);
ndp_request_event.app_info.ndp_app_info
[ndp_ind_app_info_len] = '\0';
- ALOGI("service info: %s", ndp_request_event.app_info.ndp_app_info);
+ ALOGI("service info: %s\n", ndp_request_event.app_info.ndp_app_info);
+
+ } 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);
}
}
@@ -2348,6 +2440,7 @@ class NanDataPathPrimitive : public WifiCommand
NanDataPathConfirmInd ndp_create_confirmation_event;
memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
u16 ndp_conf_app_info_len = 0;
+ u8 chan_idx = 0;
counters.dp_confirm_evt++;
ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
@@ -2384,9 +2477,29 @@ class NanDataPathPrimitive : public WifiCommand
ALOGI("reason code %u", (NanDataPathResponseCode)it.get_u8());
ndp_create_confirmation_event.rsp_code =
(NanDataPathResponseCode)it.get_u8();
+ } else if (attr_type == NAN_ATTRIBUTE_NUM_CHANNELS) {
+ ALOGI("num channels %u", it.get_u32());
+ if (it.get_u32() <= NAN_MAX_CHANNEL_INFO_SUPPORTED) {
+ ndp_create_confirmation_event.num_channels = it.get_u32();
+ } else {
+ ndp_create_confirmation_event.num_channels =
+ NAN_MAX_CHANNEL_INFO_SUPPORTED;
+ ALOGE("num channels reset to max allowed %u",
+ ndp_create_confirmation_event.num_channels);
+ }
+ } 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));
+ 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,
+ ndp_create_confirmation_event.channel_info[chan_idx].bandwidth,
+ ndp_create_confirmation_event.channel_info[chan_idx].nss);
+ chan_idx++;
+ }
}
}
-
GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
break;
}
@@ -2431,6 +2544,7 @@ class NanMacControl : public WifiCommand
wifi_interface_handle mIface;
NanRequestType mType;
u32 mVersion;
+ u8 mChreNan;
public:
NanMacControl(wifi_interface_handle iface, int id,
@@ -2470,6 +2584,10 @@ class NanMacControl : public WifiCommand
mParams = params;
}
+ void setChreNan(u8 chre_nan) {
+ mChreNan = chre_nan;
+ }
+
int createRequest(WifiRequest& request) {
ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
if (mType == NAN_REQUEST_ENABLE) {
@@ -2484,10 +2602,6 @@ class NanMacControl : public WifiCommand
/* TODO: Not yet implemented */
} else if (mType == NAN_VERSION_INFO) {
return createVersionRequest(request);
-#ifdef NAN_CLUSTER_MERGE
- } else if (mType == NAN_REQUEST_ENABLE_MERGE) {
- return createEnableMergeRequest(request, (NanEnableMergeRequest *)mParams);
-#endif /* NAN_CLUSTER_MERGE */
} else {
ALOGE("Unknown Nan request\n");
}
@@ -2853,6 +2967,32 @@ class NanMacControl : public WifiCommand
}
}
+ if (mParams->config_enable_instant_mode) {
+ result = request.put_u32(NAN_ATTRIBUTE_INSTANT_MODE_ENABLE,
+ mParams->enable_instant_mode);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable instant mode, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->enable_instant_mode && mParams->config_instant_mode_channel
+ && mParams->instant_mode_channel) {
+ result = request.put_u32(NAN_ATTRIBUTE_INSTANT_COMM_CHAN,
+ mParams->instant_mode_channel);
+ if (result < 0) {
+ ALOGE("%s: Failing in config instant channel, result = %d\n", __func__, result);
+ return result;
+ }
+ ALOGI("%s: instant mode channel = %d\n", __func__, mParams->instant_mode_channel);
+ }
+
+ result = request.put_u8(NAN_ATTRIBUTE_CHRE_REQUEST, mChreNan);
+ if (result < 0) {
+ ALOGE("%s: Failing in config chreNan, result = %d\n", __func__, result);
+ return result;
+ }
+
request.attr_end(data);
NAN_DBG_EXIT();
return WIFI_SUCCESS;
@@ -2869,31 +3009,17 @@ class NanMacControl : public WifiCommand
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- request.attr_end(data);
-
- NAN_DBG_EXIT();
- return result;
- }
-
-#ifdef NAN_CLUSTER_MERGE
- int createEnableMergeRequest(WifiRequest& request,
- NanEnableMergeRequest *mParams) {
- int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE_MERGE);
- if (result < 0) {
- ALOGE("%s: Fail to create request\n", __func__);
- return result;
- }
- nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- result = request.put_u8(NAN_ATTRIBUTE_ENABLE_MERGE, mParams->enable);
+ result = request.put_u8(NAN_ATTRIBUTE_CHRE_REQUEST, mChreNan);
if (result < 0) {
- ALOGE("%s: Failing in enable merge, result = %d\n", __func__, result);
+ ALOGE("%s: Failing in config chreNan, result = %d\n", __func__, result);
return result;
}
+
request.attr_end(data);
+
NAN_DBG_EXIT();
- return WIFI_SUCCESS;
+ return result;
}
-#endif /* NAN_CLUSTER_MERGE */
int createConfigRequest(WifiRequest& request, NanConfigRequest *mParams) {
@@ -3136,6 +3262,27 @@ class NanMacControl : public WifiCommand
return result;
}
}
+
+ if (mParams->config_enable_instant_mode) {
+ result = request.put_u32(NAN_ATTRIBUTE_INSTANT_MODE_ENABLE,
+ mParams->enable_instant_mode);
+ if (result < 0) {
+ ALOGE("%s: Failing to fill enable instant mode, result = %d\n", __func__, result);
+ return result;
+ }
+ }
+
+ if (mParams->enable_instant_mode && mParams->config_instant_mode_channel
+ && mParams->instant_mode_channel) {
+ result = request.put_u32(NAN_ATTRIBUTE_INSTANT_COMM_CHAN,
+ mParams->instant_mode_channel);
+ if (result < 0) {
+ ALOGE("%s: Failing in config instant channel, result = %d\n", __func__, result);
+ return result;
+ }
+ ALOGI("%s: instant mode channel = %d\n", __func__, mParams->instant_mode_channel);
+ }
+
request.attr_end(data);
NAN_DBG_EXIT();
return WIFI_SUCCESS;
@@ -3193,6 +3340,10 @@ class NanMacControl : public WifiCommand
return NL_SKIP;
}
+ if (mChreNan) {
+ return NL_SKIP;
+ }
+
rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
ALOGI("NanMacControl::handleResponse\n");
if (mType == NAN_VERSION_INFO) {
@@ -3258,7 +3409,6 @@ class NanMacControl : public WifiCommand
}
int handleEvent(WifiEvent& event) {
- u16 inst_id;
u32 ndp_instance_id = 0;
int event_id = event.get_vendor_subcmd();
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -3273,16 +3423,19 @@ class NanMacControl : public WifiCommand
return NL_SKIP;
}
+ if (mChreNan) {
+ return NL_SKIP;
+ }
+
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
attr_type = it.get_type();
if (it.get_type() == NAN_ATTRIBUTE_HANDLE) {
- inst_id = it.get_u8();
} else if (it.get_type() == NAN_ATTRIBUTE_NDP_ID) {
ndp_instance_id = it.get_u32();
ALOGI("handleEvent: ndp_instance_id = [%d]\n", ndp_instance_id);
} else if (attr_type == NAN_ATTRIBUTE_CMD_RESP_DATA) {
- ALOGI("sizeof cmd response data: %d, it.get_len() = %d\n",
+ ALOGI("sizeof cmd response data: %ld, it.get_len() = %d\n",
sizeof(nan_hal_resp_t), it.get_len());
if (it.get_len() == sizeof(nan_hal_resp_t)) {
rsp_vndr_data = (nan_hal_resp_t*)it.get_data();
@@ -3316,12 +3469,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");
- handleAsyncResponse(rsp_vndr_data);
- }
- }
+ } 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:
@@ -3395,9 +3553,10 @@ 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) {
- memcpy(disabled_ind.nan_reason, it.get_data(),
- sizeof(disabled_ind.nan_reason));
- ALOGI("Disable nan reason: %s", disabled_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason));
+ memcpy(disabled_ind.nan_reason, it.get_data(), len);
+ ALOGI("Disabled nan reason: %s, len = %d\n",
+ disabled_ind.nan_reason, len);
}
}
@@ -3415,7 +3574,7 @@ class NanMacControl : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
- sdfInd.data.frame_len = it.get_u32();
+ sdfInd.data.frame_len = it.get_u16();
if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
}
@@ -3450,6 +3609,7 @@ class NanMacControl : public WifiCommand
unregisterVendorHandler(GOOGLE_OUI, i);
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
void registerNanVendorEvents()
{
@@ -3458,6 +3618,7 @@ class NanMacControl : public WifiCommand
registerVendorHandler(GOOGLE_OUI, i);
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
};
@@ -3550,8 +3711,6 @@ 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_ENABLE_MERGE)
-
default:
return "UNKNOWN_NAN_CMD";
}
@@ -3737,7 +3896,6 @@ static int get_svc_hash(unsigned char *svc_name,
return WIFI_SUCCESS;
}
-#ifdef CONFIG_BRCM
static int dump_NanEnableRequest(NanEnableRequest* msg)
{
ALOGI("%s: Dump NanEnableRequest msg:\n", __func__);
@@ -3831,10 +3989,19 @@ static int dump_NanEnableRequest(NanEnableRequest* msg)
if (msg->config_disc_mac_addr_randomization) {
ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
}
+ ALOGI("config_enable_instant_mode =%u\n", msg->config_enable_instant_mode);
+ if (msg->config_enable_instant_mode) {
+ ALOGI("enable_instant_mode =%u\n", msg->enable_instant_mode);
+ }
+ ALOGI("config_instant_mode_channel=%u\n", msg->config_instant_mode_channel);
+ if (msg->config_instant_mode_channel) {
+ ALOGI("instant_mode_channel=%u\n", msg->instant_mode_channel);
+ }
return WIFI_SUCCESS;
}
+#ifdef CONFIG_BRCM
static int dump_NanConfigRequestRequest(NanConfigRequest* msg)
{
ALOGI("%s: Dump NanConfigRequest msg:\n", __func__);
@@ -3896,13 +4063,21 @@ static int dump_NanConfigRequestRequest(NanConfigRequest* msg)
if (msg->config_disc_mac_addr_randomization) {
ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
}
+ ALOGI("config_enable_instant_mode =%u\n", msg->config_enable_instant_mode);
+ if (msg->config_enable_instant_mode) {
+ ALOGI("enable_instant_mode =%u\n", msg->enable_instant_mode);
+ }
+ ALOGI("config_instant_mode_channel=%u\n", msg->config_instant_mode_channel);
+ if (msg->config_instant_mode_channel) {
+ ALOGI("instant_mode_channel=%u\n", msg->instant_mode_channel);
+ }
+
return WIFI_SUCCESS;
}
static int dump_NanPublishRequest(NanPublishRequest* msg)
{
ALOGI("%s: Dump NanPublishRequest msg:\n", __func__);
- u8 i = 0;
if (msg == NULL) {
ALOGE("Invalid msg\n");
return WIFI_ERROR_UNKNOWN;
@@ -3916,17 +4091,21 @@ static int dump_NanPublishRequest(NanPublishRequest* msg)
ALOGI("publish_match_indicator=%u\n", msg->publish_match_indicator);
ALOGI("service_responder_policy=%u\n", msg->service_responder_policy);
ALOGI("service_name_len=%u\n", msg->service_name_len);
- if (msg->service_name_len)
+ 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)
+ 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)
+ if (msg->rx_match_filter_len) {
prhex("rx_match_filter", msg->rx_match_filter, msg->rx_match_filter_len);
+ }
ALOGI("tx_match_filter_len=%u\n", msg->tx_match_filter_len);
- if (msg->tx_match_filter_len)
+ if (msg->tx_match_filter_len) {
prhex("tx_match_filter", msg->tx_match_filter, msg->tx_match_filter_len);
+ }
ALOGI("rssi_threshold_flag=%u\n", msg->rssi_threshold_flag);
ALOGI("connmap=%u\n", msg->connmap);
ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
@@ -3935,8 +4114,9 @@ static int dump_NanPublishRequest(NanPublishRequest* msg)
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)
+ 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);
@@ -3949,8 +4129,9 @@ 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)
+ if (msg->sdea_service_specific_info_len) {
ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+ }
return WIFI_SUCCESS;
}
@@ -3999,8 +4180,9 @@ static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
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)
+ 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);
@@ -4022,7 +4204,6 @@ static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
static int dump_NanTransmitFollowupRequest(NanTransmitFollowupRequest* msg)
{
ALOGI("%s: Dump NanTransmitFollowupRequest msg:\n", __func__);
- u8 i = 0;
if (msg == NULL) {
ALOGE("Invalid msg\n");
return WIFI_ERROR_UNKNOWN;
@@ -4068,6 +4249,10 @@ static int dump_NanDataPathInitiatorRequest(NanDataPathInitiatorRequest* msg)
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);
}
@@ -4098,6 +4283,10 @@ static int dump_NanDataPathIndicationResponse(NanDataPathIndicationResponse* msg
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);
}
@@ -4111,32 +4300,66 @@ void nan_reset_dbg_counters()
}
///////////////////////////////////////////////////////////////////////////////
-wifi_error nan_enable_request(transaction_id id,
- wifi_interface_handle iface, NanEnableRequest* msg)
+wifi_error nan_cmn_enabe_request(transaction_id id,
+ NanMacControl *cmd, NanEnableRequest* msg)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
- NanRequestType cmdType = NAN_REQUEST_ENABLE;
-
- ALOGI("Enabling Nan, Handle = %p\n", handle);
-
#ifdef CONFIG_BRCM
// check up nan enable params from Nan manager level
dump_NanEnableRequest(msg);
#endif /* CONFIG_BRCM */
nan_reset_dbg_counters();
- /* XXX: WAR posting async enable response */
- //NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
- NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control);
- NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
- cmd->setType(cmdType);
+
+ cmd->setType(NAN_REQUEST_ENABLE);
cmd->setId(id);
cmd->setMsg((void *)msg);
+
ret = (wifi_error)cmd->start();
if (ret != WIFI_SUCCESS) {
ALOGE("%s : failed in start, error = %d\n", __func__, ret);
}
- //cmd->releaseRef();
+
+ return ret;
+}
+
+wifi_error nan_enable_request(transaction_id id,
+ wifi_interface_handle iface, NanEnableRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ hal_info *h_info = getHalInfo(iface);
+
+ ALOGE("nan_enable_request: nan_state = %d\n", h_info->nan_state);
+
+#ifdef CHRE_NAN
+ //check if host NAN is pre-empting CHRE NAN
+ if (h_info->nan_state == NAN_STATE_CHRE) {
+ /* notify pre-empt to chre */
+ if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) {
+ h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_PREMPTED);
+ }
+ /* first disable NAN for chre */
+ ret = nan_chre_disable_request(1, iface);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to disable NAN for CHRE ret %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* notify unavailable status to chre */
+ if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) {
+ h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_UNAVAILABLE);
+ }
+#endif /* CHRE_NAN */
+
+ NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ cmd->setChreNan(0);
+ ret = nan_cmn_enabe_request(id, cmd, msg);
+
+ if (ret == WIFI_SUCCESS) {
+ h_info->nan_state = NAN_STATE_AP;
+ }
+
return ret;
}
@@ -4151,16 +4374,40 @@ void nan_dump_dbg_counters()
ALOGI("Num Transmit Success %d\n", counters.transmit_txs);
}
+wifi_error nan_cmn_disable_request(transaction_id id, NanMacControl *mac)
+{
+ wifi_error ret = WIFI_SUCCESS;
+
+ nan_dump_dbg_counters();
+
+ mac->setType(NAN_REQUEST_DISABLE);
+ ret = (wifi_error)mac->cancel();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("cancel failed, error = %d\n", ret);
+ } else {
+ ALOGE("Deinitializing Nan Mac Control = %p\n", mac);
+ }
+ mac->releaseRef();
+
+ return ret;
+}
wifi_error nan_disable_request(transaction_id id,
wifi_interface_handle iface)
{
- wifi_handle handle = getWifiHandle(iface);
- NanRequestType cmdType = NAN_REQUEST_DISABLE;
wifi_error ret = WIFI_SUCCESS;
+ hal_info *h_info = getHalInfo(iface);
+
+ ALOGE("nan_disable_request: nan_state %d\n", h_info->nan_state);
+
+ if (h_info->nan_state == NAN_STATE_CHRE) {
+ ALOGE("nan_disable_request: Not enabled for AP.. return\n");
+ return ret;
+ }
- ALOGI("Disabling Nan, Handle = %p\n", handle);
- NanMacControl *cmd = new NanMacControl(iface, id, NULL, cmdType);
NanMacControl *mac_prim = (NanMacControl*)(info.nan_mac_control);
+ NanMacControl *cmd = new NanMacControl(iface, id, NULL, NAN_REQUEST_LAST);
+
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
if (id != NAN_MAC_INVALID_TRANSID) {
ALOGE("Disable NAN MAC transId= %d\n", id);
@@ -4169,17 +4416,15 @@ wifi_error nan_disable_request(transaction_id id,
ALOGE("Invalid transId= %d cur= %d\n", id, mac_prim->getId());
}
- NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-
- nan_dump_dbg_counters();
-
- ret = (wifi_error)cmd->cancel();
- if (ret != WIFI_SUCCESS) {
- ALOGE("cancel failed, error = %d\n", ret);
- } else {
- ALOGE("Deinitializing Nan Mac Control = %p\n", cmd);
+ cmd->setChreNan(0);
+ ret = nan_cmn_disable_request(id, cmd);
+ if (ret == WIFI_SUCCESS) {
+ h_info->nan_state = NAN_STATE_DISABLED;
+ /* notify pre-empt / unavailable status to chre */
+ if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) {
+ h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_AVAILABLE);
+ }
}
- cmd->releaseRef();
return ret;
}
@@ -4211,7 +4456,6 @@ wifi_error nan_publish_cancel_request(transaction_id id,
{
wifi_error ret = WIFI_SUCCESS;
NanDiscEnginePrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_PUBLISH_CANCEL;
ALOGE("Cancellling publish request %d\n", msg->publish_id);
@@ -4258,7 +4502,6 @@ wifi_error nan_subscribe_cancel_request(transaction_id id,
{
wifi_error ret = WIFI_SUCCESS;
NanDiscEnginePrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE_CANCEL;
ALOGE("creating new instance + %d\n", msg->subscribe_id);
@@ -4274,36 +4517,11 @@ wifi_error nan_subscribe_cancel_request(transaction_id id,
return ret;
}
-#ifdef NAN_CLUSTER_MERGE
-/* Function to send NAN cluster merge enable/disable request to the wifi driver.*/
-wifi_error nan_enable_cluster_merge_request(transaction_id id,
- wifi_interface_handle iface, NanEnableMergeRequest* msg)
-{
- wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
- NanRequestType cmdType = NAN_REQUEST_ENABLE_MERGE;
-
- NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
- NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
- cmd->setType(cmdType);
- cmd->setId(id);
- cmd->setMsg((void *)msg);
- ret = (wifi_error)cmd->start();
- if (ret != WIFI_SUCCESS) {
- ALOGE("%s :enable nan cluster merge failed in start, error = %d\n", __func__, ret);
- }
- cmd->releaseRef();
-
- return ret;
-}
-#endif /* NAN_CLUSTER_MERGE */
-
/* Function to send nan transmit followup Request to the wifi driver.*/
wifi_error nan_transmit_followup_request(transaction_id id,
wifi_interface_handle iface, NanTransmitFollowupRequest* msg)
{
NanDiscEnginePrimitive *cmd = NULL;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_REQUEST_TRANSMIT_FOLLOWUP;
wifi_error ret = WIFI_SUCCESS;
@@ -4330,9 +4548,9 @@ wifi_error nan_stats_request(transaction_id id,
wifi_handle handle = getWifiHandle(iface);
ALOGI("Nan Stats, halHandle = %p", handle);
- NanRequestType cmdType = NAN_REQUEST_STATS;
#ifdef NOT_SUPPORTED
+ NanRequestType cmdType = NAN_REQUEST_STATS;
wifi_error ret = WIFI_SUCCESS;
NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -4383,9 +4601,9 @@ wifi_error nan_tca_request(transaction_id id,
wifi_handle handle = getWifiHandle(iface);
ALOGI("Nan TCA, halHandle = %p", handle);
- NanRequestType cmdType = NAN_REQUEST_TCA;
#ifdef NOT_SUPPORTED
+ NanRequestType cmdType = NAN_REQUEST_TCA;
wifi_error ret = WIFI_SUCCESS;
NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -4480,6 +4698,7 @@ wifi_error nan_deinit_handler()
delete GET_NAN_HANDLE(info);
NAN_HANDLE(info) = NULL;
}
+ ALOGI("wifi nan internal clean up done");
return WIFI_SUCCESS;
}
wifi_error nan_register_handler(wifi_interface_handle iface,
@@ -4552,6 +4771,7 @@ class NanEventCap : public WifiCommand
unregisterVendorHandler(GOOGLE_OUI, i);
}
unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ unregisterVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
void registerNanVendorEvents()
{
@@ -4560,6 +4780,7 @@ class NanEventCap : public WifiCommand
registerVendorHandler(GOOGLE_OUI, i);
}
registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+ registerVendorHandler(GOOGLE_OUI, NAN_EVENT_MATCH_EXPIRY);
}
int handleEvent(WifiEvent& event) {
@@ -4623,9 +4844,10 @@ 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) {
- memcpy(disabled_ind.nan_reason, it.get_data(),
- sizeof(disabled_ind.nan_reason));
- ALOGI("nan disable reason: %s", disabled_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(disabled_ind.nan_reason));
+ memcpy(disabled_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan disabled reason: %s, len = %d\n",
+ disabled_ind.nan_reason, len);
}
}
@@ -4642,15 +4864,16 @@ class NanEventCap : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- pub_term_event.publish_id = it.get_u16();
+ pub_term_event.publish_id = it.get_u32();
ALOGI("pub id %u", pub_term_event.publish_id);
} else if (attr_type == NAN_ATTRIBUTE_STATUS) {
pub_term_event.reason = (NanStatusType)it.get_u8();
ALOGI("pub termination status %u", pub_term_event.reason);
} else if (attr_type == NAN_ATTRIBUTE_REASON) {
- memcpy(pub_term_event.nan_reason, it.get_data(),
- sizeof(pub_term_event.nan_reason));
- ALOGI("Pub termination nan reason: %s", pub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(pub_term_event.nan_reason));
+ memcpy(pub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("Pub termination nan reason: %s, len = %d\n",
+ pub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr\n");
}
@@ -4778,9 +5001,10 @@ 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) {
- memcpy(sub_term_event.nan_reason, it.get_data(),
- sizeof(sub_term_event.nan_reason));
- ALOGI("sub termination nan reason: %s", sub_term_event.nan_reason);
+ u8 len = min(it.get_len(), sizeof(sub_term_event.nan_reason));
+ memcpy(sub_term_event.nan_reason, it.get_data(), len);
+ ALOGI("sub termination nan reason: %s, len = %d\n",
+ sub_term_event.nan_reason, len);
} else {
ALOGE("Unknown attr: %u\n", attr_type);
}
@@ -4789,6 +5013,9 @@ class NanEventCap : public WifiCommand
GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
break;
}
+ case NAN_EVENT_MATCH_EXPIRY:
+ HandleExpiryEvent(info, vendor_data);
+ break;
case NAN_EVENT_FOLLOWUP: {
NanFollowupInd followup_event;
memset(&followup_event, 0, sizeof(NanFollowupInd));
@@ -4837,7 +5064,7 @@ class NanEventCap : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
- sdfInd.data.frame_len = it.get_u32();
+ sdfInd.data.frame_len = it.get_u16();
if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
}
@@ -4893,8 +5120,8 @@ class NanEventCap : public WifiCommand
attr_type = it.get_type();
if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
- ALOGI("publish_id: %u\n", it.get_u16());
- ndp_request_event.service_instance_id = it.get_u16();
+ ALOGI("publish_id: %u\n", it.get_u32());
+ ndp_request_event.service_instance_id = it.get_u32();
} else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
memcpy(ndp_request_event.peer_disc_mac_addr,
@@ -4926,6 +5153,15 @@ class NanEventCap : public WifiCommand
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();
+
+ } 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);
}
}
@@ -5014,9 +5250,10 @@ 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) {
- memcpy(followup_ind.nan_reason, it.get_data(),
- sizeof(followup_ind.nan_reason));
- ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+ u8 len = min(it.get_len(), sizeof(followup_ind.nan_reason));
+ memcpy(followup_ind.nan_reason, it.get_data(), len);
+ ALOGI("nan transmit followup ind: reason: %s, len = %d\n",
+ followup_ind.nan_reason, len);
}
}
@@ -5034,7 +5271,6 @@ class NanEventCap : public WifiCommand
/* To see event prints in console */
wifi_error nan_event_check_request(transaction_id id, wifi_interface_handle iface)
{
- wifi_handle handle = getWifiHandle(iface);
NanEventCap *cmd = new NanEventCap(iface, id);
if (cmd == NULL) {
return WIFI_ERROR_NOT_SUPPORTED;
@@ -5047,7 +5283,6 @@ wifi_error nan_data_interface_create(transaction_id id,
wifi_interface_handle iface, char* iface_name)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType = NAN_DATA_PATH_IFACE_CREATE;
@@ -5070,7 +5305,6 @@ wifi_error nan_data_interface_delete(transaction_id id,
wifi_interface_handle iface, char* iface_name)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType = NAN_DATA_PATH_IFACE_DELETE;
@@ -5093,7 +5327,6 @@ wifi_error nan_data_request_initiator(transaction_id id,
wifi_interface_handle iface, NanDataPathInitiatorRequest* msg)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType;
@@ -5179,7 +5412,6 @@ wifi_error nan_data_indication_response(transaction_id id,
wifi_interface_handle iface, NanDataPathIndicationResponse* msg)
{
wifi_error ret = WIFI_SUCCESS;
- wifi_handle handle = getWifiHandle(iface);
NAN_DBG_ENTER();
NanRequestType cmdType;
u8 pub_nmi[NAN_MAC_ADDR_LEN] = {0};
@@ -5275,7 +5507,6 @@ wifi_error nan_data_end(transaction_id id,
{
wifi_error ret = WIFI_SUCCESS;
NanDataPathPrimitive *cmd;
- wifi_handle handle = getWifiHandle(iface);
NanRequestType cmdType = NAN_DATA_PATH_END;
NAN_DBG_ENTER();
@@ -5290,3 +5521,89 @@ wifi_error nan_data_end(transaction_id id,
NAN_DBG_EXIT();
return ret;
}
+
+wifi_error nan_chre_enable_request(transaction_id id,
+ wifi_interface_handle iface, NanEnableRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ NanEnableRequest def_msg;
+ hal_info *h_info = getHalInfo(iface);
+
+ ALOGI("nan_chre_enable_request: nan_state %d\n", h_info->nan_state);
+
+ if (h_info->nan_state == NAN_STATE_CHRE) {
+ return WIFI_SUCCESS;
+ } else if (h_info->nan_state == NAN_STATE_AP) {
+ ALOGE("nan_chre_enable_request: Nan is enabled for AP. Fail CHRE request\n");
+ return WIFI_ERROR_BUSY;
+ }
+
+ NanMacControl *mac = new NanMacControl(iface, 0, NULL, NAN_REQUEST_LAST);
+ NULL_CHECK_RETURN(mac, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ mac->setChreNan(1);
+ if (msg == NULL) {
+ /* default enable params */
+ ALOGI("Input Enable config is NULL, use default config\n");
+ memset(&def_msg, 0, sizeof(def_msg));
+ def_msg.hop_count_limit_val = 5;
+ def_msg.config_2dot4g_support = 1;
+ def_msg.support_2dot4g_val = 1;
+ def_msg.config_2dot4g_beacons = 1;
+ def_msg.beacon_2dot4g_val = 1;
+ def_msg.config_2dot4g_sdf = 1;
+ def_msg.sdf_2dot4g_val = 1;
+ def_msg.config_disc_mac_addr_randomization = true;
+ def_msg.disc_mac_addr_rand_interval_sec = 0;
+ def_msg.config_ndpe_attr = false;
+ ret = nan_cmn_enabe_request(id, mac, &def_msg);
+ } else {
+ ret = nan_cmn_enabe_request(id, mac, msg);
+ }
+
+ if (ret == WIFI_SUCCESS) {
+ h_info->nan_state = NAN_STATE_CHRE;
+ }
+
+ return ret;
+}
+
+wifi_error nan_chre_disable_request(transaction_id id,
+ wifi_interface_handle iface)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ hal_info *h_info = getHalInfo(iface);
+
+ ALOGI("nan_chre_disable_request: nan_state %d\n", h_info->nan_state);
+
+ if (h_info->nan_state == NAN_STATE_AP) {
+ ALOGE("nan_chre_disable_request: Not enabled for CHRE.. return\n");
+ return ret;
+ }
+
+ NanMacControl *cmd = new NanMacControl(iface, id, NULL, NAN_REQUEST_LAST);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ cmd->setChreNan(1);
+ ret = nan_cmn_disable_request(id, cmd);
+
+ if (ret == WIFI_SUCCESS) {
+ h_info->nan_state = NAN_STATE_DISABLED;
+ }
+
+ return ret;
+}
+
+wifi_error nan_chre_register_handler(wifi_interface_handle iface,
+ wifi_chre_handler handler)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ hal_info *h_info = getHalInfo(iface);
+
+ if (h_info) {
+ ALOGE("Registering CHRE handler for Nan Status %p\n", handler.on_chre_nan_rtt_change);
+ h_info->chre_nan_cb = handler;
+ }
+
+ return ret;
+}
diff --git a/bcmdhd/wifi_hal/rtt.cpp b/bcmdhd/wifi_hal/rtt.cpp
index 81eb17f..6bb0a49 100644
--- a/bcmdhd/wifi_hal/rtt.cpp
+++ b/bcmdhd/wifi_hal/rtt.cpp
@@ -60,26 +60,30 @@ typedef enum {
} RTT_SUB_COMMAND;
typedef enum {
- RTT_ATTRIBUTE_TARGET_CNT = 0,
- RTT_ATTRIBUTE_TARGET_INFO,
- RTT_ATTRIBUTE_TARGET_MAC,
- RTT_ATTRIBUTE_TARGET_TYPE,
- RTT_ATTRIBUTE_TARGET_PEER,
- RTT_ATTRIBUTE_TARGET_CHAN,
- RTT_ATTRIBUTE_TARGET_PERIOD,
- RTT_ATTRIBUTE_TARGET_NUM_BURST,
- RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
- RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
- RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
- RTT_ATTRIBUTE_TARGET_LCI,
- RTT_ATTRIBUTE_TARGET_LCR,
- RTT_ATTRIBUTE_TARGET_BURST_DURATION,
- RTT_ATTRIBUTE_TARGET_PREAMBLE,
- RTT_ATTRIBUTE_TARGET_BW,
- RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
- RTT_ATTRIBUTE_RESULTS_PER_TARGET,
- RTT_ATTRIBUTE_RESULT_CNT,
- RTT_ATTRIBUTE_RESULT
+ RTT_ATTRIBUTE_TARGET_INVALID = 0,
+ RTT_ATTRIBUTE_TARGET_CNT = 1,
+ RTT_ATTRIBUTE_TARGET_INFO = 2,
+ RTT_ATTRIBUTE_TARGET_MAC = 3,
+ RTT_ATTRIBUTE_TARGET_TYPE = 4,
+ RTT_ATTRIBUTE_TARGET_PEER = 5,
+ RTT_ATTRIBUTE_TARGET_CHAN = 6,
+ RTT_ATTRIBUTE_TARGET_PERIOD = 7,
+ RTT_ATTRIBUTE_TARGET_NUM_BURST = 8,
+ RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST = 9,
+ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM = 10,
+ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR = 11,
+ RTT_ATTRIBUTE_TARGET_LCI = 12,
+ RTT_ATTRIBUTE_TARGET_LCR = 13,
+ RTT_ATTRIBUTE_TARGET_BURST_DURATION = 14,
+ RTT_ATTRIBUTE_TARGET_PREAMBLE = 15,
+ RTT_ATTRIBUTE_TARGET_BW = 16,
+ RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
+ RTT_ATTRIBUTE_RESULTS_PER_TARGET = 31,
+ RTT_ATTRIBUTE_RESULT_CNT = 32,
+ RTT_ATTRIBUTE_RESULT = 33,
+ RTT_ATTRIBUTE_RESUTL_DETAIL = 34,
+ /* Add any new RTT_ATTRIBUTE prior to RTT_ATTRIBUTE_MAX */
+ RTT_ATTRIBUTE_MAX
} RTT_ATTRIBUTE;
typedef struct strmap_entry {
int id;
@@ -96,6 +100,7 @@ typedef struct dot11_rm_ie dot11_rm_ie_t;
#define DOT11_HDR_LEN 2
#define DOT11_RM_IE_LEN 5
#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementResponse */
#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
#define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */
@@ -313,6 +318,7 @@ class RttCommand : public WifiCommand
unsigned numRttParams;
int mCompleted;
int currentIdx;
+ int currDtlIdx;
int totalCnt;
static const int MAX_RESULTS = 1024;
wifi_rtt_result *rttResults[MAX_RESULTS];
@@ -328,6 +334,7 @@ public:
currentIdx = 0;
mCompleted = 0;
totalCnt = 0;
+ currDtlIdx = 0;
}
RttCommand(wifi_interface_handle iface, int id)
@@ -336,7 +343,11 @@ public:
currentIdx = 0;
mCompleted = 0;
totalCnt = 0;
+ currDtlIdx = 0;
numRttParams = 0;
+ memset(rttResults, 0, sizeof(rttResults));
+ rttParams = NULL;
+ rttHandler.on_rtt_results = NULL;
}
int createSetupRequest(WifiRequest& request) {
@@ -451,7 +462,11 @@ public:
}
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
- request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
+ result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
+
+ if (result < 0) {
+ return result;
+ }
for(unsigned i = 0; i < num_devices; i++) {
result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
if (result < 0) {
@@ -470,13 +485,14 @@ public:
return result;
}
+ registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
ALOGE("failed to configure RTT setup; result = %d", result);
return result;
}
- registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
ALOGI("Successfully started RTT operation");
return result;
}
@@ -528,6 +544,7 @@ public:
int len = event.get_vendor_data_len();
if (vendor_data == NULL || len == 0) {
ALOGI("No rtt results found");
+ return NL_STOP;
}
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
@@ -561,19 +578,18 @@ public:
memcpy(rtt_result, it2.get_data(), it2.get_len());
result_len -= sizeof(wifi_rtt_result);
if (result_len > 0) {
- result_len -= sizeof(wifi_rtt_result);
dot11_rm_ie_t *ele_1;
dot11_rm_ie_t *ele_2;
/* The result has LCI or LCR element */
ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
- if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
+ if (ele_1->id == DOT11_MNG_MEASURE_REPORT_ID) {
if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
rtt_result->LCI = (wifi_information_element *)ele_1;
result_len -= (ele_1->len + DOT11_HDR_LEN);
/* get a next rm ie */
if (result_len > 0) {
ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
- if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
+ if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
rtt_result->LCR = (wifi_information_element *)ele_2;
}
@@ -584,7 +600,7 @@ public:
/* get a next rm ie */
if (result_len > 0) {
ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
- if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
+ if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
(ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
rtt_result->LCI = (wifi_information_element *)ele_2;
}
@@ -595,13 +611,14 @@ public:
totalCnt++;
ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
"\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
- "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
- "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
+ "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %lu ns, rtt_sd : %lu\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,
get_err_info(rtt_result->status), rtt_result->retry_after_duration,
rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
- rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance_mm / 10,
+ (unsigned long)rtt_result->rtt/1000, (unsigned long)rtt_result->rtt_sd,
+ rtt_result->distance_mm / 10,
rtt_result->burst_duration, rtt_result->negotiated_burst_num);
currentIdx++;
}
@@ -611,7 +628,9 @@ public:
}
if (mCompleted) {
unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
- (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
+ if (*rttHandler.on_rtt_results) {
+ (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
+ }
for (int i = 0; i < currentIdx; i++) {
free(rttResults[i]);
rttResults[i] = NULL;
@@ -630,7 +649,19 @@ public:
wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
wifi_handle handle = getWifiHandle(iface);
+ if (handle == NULL) {
+ ALOGE("wifi_rtt_range_request: NULL handle pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = wifi_register_cmd(handle, id, cmd);
@@ -651,7 +682,19 @@ wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle ifac
wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
unsigned num_devices, mac_addr addr[])
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
wifi_handle handle = getWifiHandle(iface);
+ if (handle == NULL) {
+ ALOGE("wifi_rtt_range_cancel: NULL handle pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
RttCommand *cmd = new RttCommand(iface, id);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
cmd->cancel_specific(num_devices, addr);
@@ -663,6 +706,18 @@ wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle ifac
wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
wifi_rtt_capabilities *capabilities)
{
+ if (iface == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (capabilities == NULL) {
+ ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
GetRttCapabilitiesCommand command(iface, capabilities);
return (wifi_error) command.requestResponse();
}
@@ -671,6 +726,12 @@ wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
wifi_rtt_responder* responderInfo)
{
+ if (iface == NULL) {
+ ALOGE("wifi_rtt_get_responder_info: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
GetRttResponderInfoCommand command(iface, responderInfo);
return (wifi_error) command.requestResponse();
diff --git a/bcmdhd/wifi_hal/sync.h b/bcmdhd/wifi_hal/sync.h
index 64f8d39..1118c71 100644
--- a/bcmdhd/wifi_hal/sync.h
+++ b/bcmdhd/wifi_hal/sync.h
@@ -68,4 +68,4 @@ public:
}
};
-#endif \ No newline at end of file
+#endif
diff --git a/bcmdhd/wifi_hal/twt.cpp b/bcmdhd/wifi_hal/twt.cpp
new file mode 100755
index 0000000..15bb738
--- /dev/null
+++ b/bcmdhd/wifi_hal/twt.cpp
@@ -0,0 +1,947 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Portions copyright (C) 2020 Broadcom Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/handlers.h>
+
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+
+static const char *TwtCmdToString(int cmd);
+static void EventGetAttributeData(u8 sub_event_type, nlattr *vendor_data);
+typedef void *TwtRequest;
+
+#define C2S(x) case x: return #x;
+
+typedef struct _twt_hal_info {
+ void *twt_handle;
+ void *twt_feature_request;
+} twt_hal_info_t;
+
+twt_hal_info_t twt_info;
+
+#define TWT_HANDLE(twt_info) ((twt_info).twt_handle)
+#define GET_TWT_HANDLE(twt_info) ((TwtHandle *)twt_info.twt_handle)
+
+#define WL_TWT_CAP_FLAGS_REQ_SUPPORT (1u << 0u)
+#define WL_TWT_CAP_FLAGS_RESP_SUPPORT (1u << 1u)
+#define WL_TWT_CAP_FLAGS_BTWT_SUPPORT (1u << 2u)
+#define WL_TWT_CAP_FLAGS_FLEX_SUPPORT (1u << 3u)
+
+class TwtHandle
+{
+ public:
+ TwtCallbackHandler mHandlers;
+ TwtHandle(wifi_handle handle, TwtCallbackHandler handlers):mHandlers(handlers)
+ {}
+
+};
+
+
+static const char *TwtCmdToString(int cmd)
+{
+ switch (cmd) {
+ C2S(TWT_SETUP_REQUEST);
+ C2S(TWT_INFO_FRAME_REQUEST);
+ C2S(TWT_TEAR_DOWN_REQUEST);
+ default:
+ return "UNKNOWN_NAN_CMD";
+ }
+}
+
+static bool is_twt_sub_event(int sub_event_type)
+{
+ bool is_twt_event = false;
+ switch (sub_event_type) {
+ case TWT_SETUP_RESPONSE:
+ case TWT_TEARDOWN_COMPLETION:
+ case TWT_INFORM_FRAME:
+ case TWT_NOTIFY:
+ is_twt_event = true;
+ }
+ return is_twt_event;
+}
+
+void EventGetAttributeData(u8 sub_event_type, nlattr *vendor_data)
+{
+ u8 attr_type = 0;
+
+ switch (sub_event_type) {
+ case TWT_SETUP_RESPONSE:
+ TwtSetupResponse setup_response;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ setup_response.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_NEG_TYPE:
+ ALOGI("neg type = %u\n", it.get_u8());
+ setup_response.negotiation_type = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ setup_response.reason_code = (TwtSetupReasonCode)it.get_u8();
+ ALOGI("reason code = %u\n", setup_response.reason_code);
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ setup_response.status = it.get_u8();
+ ALOGI("status = %u\n", setup_response.status);
+ break;
+ case TWT_ATTRIBUTE_TRIGGER_TYPE:
+ setup_response.trigger_type = it.get_u8();
+ ALOGI("trigger type = %u\n", setup_response.trigger_type);
+ break;
+ case TWT_ATTRIBUTE_WAKE_DUR_US:
+ setup_response.wake_dur_us = it.get_u32();
+ ALOGI("wake_dur_us = %d\n", setup_response.wake_dur_us);
+ break;
+ case TWT_ATTRIBUTE_WAKE_INT_US:
+ setup_response.wake_int_us = it.get_u32();
+ ALOGI("wake_int_us = %d\n", setup_response.wake_int_us);
+ break;
+ case TWT_ATTRIBUTE_WAKE_TIME_OFF_US:
+ setup_response.wake_time_off_us = it.get_u32();
+ ALOGI("wake_time_off_us = %d\n", setup_response.wake_time_off_us);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtSetupResponse(&setup_response);
+ break;
+ case TWT_TEARDOWN_COMPLETION:
+ TwtTeardownCompletion teardown_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ teardown_event.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ teardown_event.status = it.get_u8();
+ ALOGI("status = %u\n", teardown_event.status);
+ break;
+ case TWT_ATTRIBUTE_ALL_TWT:
+ teardown_event.all_twt = it.get_u8();
+ ALOGI("all_twt = %d\n", teardown_event.all_twt);
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ teardown_event.reason = (TwtTeardownReason)it.get_u8();
+ ALOGI("reason = %u\n", teardown_event.reason);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtTeardownCompletion(&teardown_event);
+ break;
+ case TWT_INFORM_FRAME:
+ TwtInfoFrameReceived info_frame_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ ALOGI("config_id = %u\n", it.get_u8());
+ info_frame_event.config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_REASON_CODE:
+ info_frame_event.reason = (TwtInfoFrameReason)it.get_u8();
+ ALOGI("reason = %u\n", info_frame_event.reason);
+ break;
+ case TWT_ATTRIBUTE_STATUS:
+ info_frame_event.status = it.get_u8();
+ ALOGI("status = %u\n", info_frame_event.status);
+ break;
+ case TWT_ATTRIBUTE_ALL_TWT:
+ info_frame_event.all_twt = it.get_u8();
+ ALOGI("all_twt = %d\n", info_frame_event.all_twt);
+ break;
+ case TWT_ATTRIBUTE_RESUMED:
+ info_frame_event.twt_resumed = it.get_u8();
+ ALOGI("twt_resumed = %u\n", info_frame_event.twt_resumed);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtInfoFrameReceived(&info_frame_event);
+ break;
+ case TWT_NOTIFY:
+ TwtDeviceNotify notif_event;
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ attr_type = it.get_type();
+ switch (attr_type) {
+ case TWT_ATTRIBUTE_NOTIFICATION:
+ notif_event.notification = (TwtNotification)it.get_u8();
+ ALOGI("notification = %u\n", notif_event.notification);
+ break;
+ default:
+ if (attr_type != TWT_ATTRIBUTE_SUB_EVENT) {
+ ALOGE("Unknown attr_type: %d\n", attr_type);
+ }
+ break;
+ }
+ }
+ GET_TWT_HANDLE(twt_info)->mHandlers.EventTwtDeviceNotify(&notif_event);
+ break;
+ default:
+ ALOGE("Unknown event_type: %d\n", sub_event_type);
+ break;
+ }
+ return;
+}
+
+void HandleTwtEvent(nlattr *vendor_data) {
+ u8 sub_event_type = 0;
+ u8 event_type = 0;
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ event_type = it.get_type();
+ if (event_type == TWT_ATTRIBUTE_SUB_EVENT) {
+ sub_event_type = it.get_u8();
+ if (is_twt_sub_event(sub_event_type)) {
+ EventGetAttributeData(sub_event_type, vendor_data);
+ }
+ }
+ }
+ return;
+}
+
+class TwtEventCap : public WifiCommand
+{
+ public:
+ TwtEventCap(wifi_interface_handle iface, int id)
+ : WifiCommand("TwtCommand", iface, id)
+ {}
+
+ int start()
+ {
+ registerTwtVendorEvents();
+ return WIFI_SUCCESS;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ return NL_SKIP;
+ }
+
+ void registerTwtVendorEvents()
+ {
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ void unregisterTwtVendorEvents()
+ {
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ int handleEvent(WifiEvent& event) {
+ u16 attr_type;
+ TwtEventType twt_event;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+
+ ALOGI("EventCapture: Received TWT event: %d\n", event_id);
+ if (!vendor_data || len == 0) {
+ ALOGE("No event data found");
+ return NL_SKIP;
+ }
+
+ switch (event_id) {
+ case BRCM_VENDOR_EVENT_TWT: {
+ ALOGE("Handle TWT event: %d\n", event_id);
+ HandleTwtEvent(vendor_data);
+ break;
+ }
+ default:
+ break;
+ }
+ return NL_SKIP;
+ }
+};
+
+/* To see event prints in console */
+wifi_error twt_event_check_request(transaction_id id, wifi_interface_handle iface)
+{
+ TwtEventCap *cmd = new TwtEventCap(iface, id);
+ if (cmd == NULL) {
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return (wifi_error)cmd->start();
+}
+
+//////////////////////////////////////////////////////////////////////////
+class GetTwtCapabilitiesCommand : public WifiCommand
+{
+ TwtCapabilitySet *mCapabilities;
+public:
+ GetTwtCapabilitiesCommand(wifi_interface_handle iface, TwtCapabilitySet *capabilities)
+ : WifiCommand("GetTwtCapabilitiesCommand", iface, 0), mCapabilities(capabilities)
+ {
+ memset(mCapabilities, 0, sizeof(*mCapabilities));
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to get twt capabilities; iface\n");
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_GETCAPABILITY);
+ if (ret < 0) {
+ ALOGE("Failed to send the twt cap cmd, err = %d\n", ret);
+ }
+ ALOGD("Success to send twt cap cmd, err = %d\n", ret);
+ return ret;
+ }
+
+private:
+ TwtCapability parseTwtCap(uint32_t twt_peer_cap) {
+ TwtCapability cap;
+ cap.requester_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_REQ_SUPPORT) ? 1 : 0;
+ cap.responder_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_RESP_SUPPORT) ? 1 : 0;
+ cap.broadcast_twt_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_BTWT_SUPPORT) ? 1 : 0;
+ cap.flexibile_twt_supported = (twt_peer_cap & WL_TWT_CAP_FLAGS_FLEX_SUPPORT) ? 1 : 0;
+ return cap;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+
+ ALOGI("In GetTwtCapabilitiesCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+ uint32_t twt_device_cap, twt_peer_cap;
+
+ nlattr *data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len);
+ if (data == NULL || len == 0) {
+ ALOGE("no vendor data in GetTwtCapabilitiesCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case TWT_ATTRIBUTE_DEVICE_CAP:
+ twt_device_cap = it.get_u32();
+ mCapabilities->device_capability = parseTwtCap(twt_device_cap);
+ break;
+ case TWT_ATTRIBUTE_PEER_CAP:
+ twt_peer_cap = it.get_u32();
+ mCapabilities->peer_capability = parseTwtCap(twt_peer_cap);
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+
+ ALOGE("Out GetTwtCapabilitiesCommand::handleResponse\n");
+ return NL_OK;
+ }
+};
+
+/* API to get TWT capability */
+wifi_error twt_get_capability(wifi_interface_handle iface,
+ TwtCapabilitySet *twt_cap_set)
+{
+ if (iface == NULL) {
+ ALOGE("twt_get_capability: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (twt_cap_set == NULL) {
+ ALOGE("twt_get_capability: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ GetTwtCapabilitiesCommand command(iface, twt_cap_set);
+ return (wifi_error) command.requestResponse();
+}
+
+//////////////////////////////////////////////////////////////////////////
+class GetTwtStatsCommand : public WifiCommand
+{
+ TwtStats* mStats;
+ u8 mConfig_id;
+public:
+ GetTwtStatsCommand(wifi_interface_handle iface, u8 config_id, TwtStats *stats)
+ : WifiCommand("GetTwtStatsCommand", iface, 0), mConfig_id(config_id), mStats(stats)
+ {
+ memset(mStats, 0, sizeof(*mStats));
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to get twt stats; iface = %d", mIfaceInfo->id);
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_GETSTATS);
+ if (ret < 0) {
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mConfig_id);
+ if (ret < 0) {
+ ALOGE("Failed to set mConfig_id %d\n", mConfig_id);
+ return ret;
+ }
+
+ ALOGI("Successfully configured config id %d\n", mConfig_id);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+
+ ALOGI("In GetTwtStatsCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+
+ nlattr *data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len);
+ if (data == NULL || len == 0) {
+ ALOGE("no vendor data in GetTwtStatsCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case TWT_ATTRIBUTE_CONFIG_ID:
+ mStats->config_id = it.get_u8();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_NUM_TX:
+ mStats->avg_pkt_num_tx = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_NUM_RX:
+ mStats->avg_pkt_num_rx = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_SIZE_TX:
+ mStats->avg_tx_pkt_size = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_PKT_SIZE_RX:
+ mStats->avg_rx_pkt_size = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_AVG_EOSP_DUR:
+ mStats->avg_eosp_dur_us = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_EOSP_COUNT:
+ mStats->eosp_count = it.get_u32();
+ break;
+ case TWT_ATTRIBUTE_NUM_SP:
+ mStats->num_sp = it.get_u32();
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+
+ return NL_OK;
+ }
+};
+
+/* API to get TWT stats */
+wifi_error twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* stats)
+{
+ if (iface == NULL) {
+ ALOGE("twt_get_stats: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ if (stats == NULL) {
+ ALOGE("TwtCapabilitySet: NULL capabilities pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ GetTwtStatsCommand command(iface, config_id, stats);
+ return (wifi_error) command.requestResponse();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+class ClearTwtStatsCommand : public WifiCommand
+{
+ u8 mConfig_id;
+public:
+ ClearTwtStatsCommand(wifi_interface_handle iface, u8 config_id)
+ : WifiCommand("ClearTwtStatsCommand", iface, 0), mConfig_id(config_id)
+ {
+ }
+
+ virtual int create() {
+ ALOGD("Creating message to clear twt stats; config_id = %d\n", mConfig_id);
+
+ int ret = mMsg.create(GOOGLE_OUI, TWT_SUBCMD_CLR_STATS);
+ if (ret < 0) {
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mConfig_id);
+ if (ret < 0) {
+ ALOGE("Failed to set mConfig_id %d\n", mConfig_id);
+ return ret;
+ }
+
+ ALOGI("Successfully configured config id %d\n", mConfig_id);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In ClearTwtStatsCommand::handleResponse");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+/* API to clear TWT stats */
+wifi_error twt_clear_stats(wifi_interface_handle iface, u8 config_id)
+{
+ if (iface == NULL || !config_id) {
+ ALOGE("twt_clear_stats: NULL iface pointer provided."
+ " Exit.");
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ ALOGE("twt_clear_stats: config id: %d\n", config_id);
+
+ ClearTwtStatsCommand command(iface, config_id);
+ return (wifi_error) command.requestResponse();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+class TwtFeatureRequest : public WifiCommand
+{
+ TwtRequest reqContext;
+ TwtRequestType mType;
+
+ public:
+ TwtFeatureRequest(wifi_interface_handle iface,
+ TwtRequest params, TwtRequestType cmdType)
+ : WifiCommand("TwtFeatureRequest", iface, 0), reqContext(params), mType(cmdType)
+ {
+ }
+
+ int createRequest(WifiRequest& request)
+ {
+ ALOGI("TWT CMD: %s\n", TwtCmdToString(mType));
+ if (mType == TWT_SETUP_REQUEST) {
+ return createTwtSetupRequest(request, (TwtSetupRequest *)reqContext);
+ } else if (mType == TWT_INFO_FRAME_REQUEST) {
+ return createInfoFrameRequest(request, (TwtInfoFrameRequest *)reqContext);
+ } else if (mType == TWT_TEAR_DOWN_REQUEST) {
+ return createTearDownRequest(request, (TwtTeardownRequest *)reqContext);
+ } else {
+ ALOGE("%s: Unknown TWT request: %d\n", __func__, mType);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ return WIFI_SUCCESS;
+ }
+
+ int createTwtSetupRequest(WifiRequest& request, TwtSetupRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_SETUP_REQUEST);
+ if (result < 0) {
+ ALOGE("%s Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ /* If handle is 0xFFFF, then update instance_id in response of this request
+ * otherwise, update not needed
+ */
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+
+ if (mParams->negotiation_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_NEG_TYPE, mParams->negotiation_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill negotiation_type = %d, result = %d\n",
+ __func__, mParams->negotiation_type, result);
+ return result;
+ }
+ }
+ if (mParams->trigger_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_TRIGGER_TYPE, mParams->trigger_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill trigger_type = %d, result = %d\n",
+ __func__, mParams->trigger_type, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_US, mParams->wake_dur_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_US, mParams->wake_int_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_us = %d, result = %d\n",
+ __func__, mParams->wake_int_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_min_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_MIN_US, mParams->wake_int_min_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_min_us = %d, result = %d\n",
+ __func__, mParams->wake_int_min_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_int_max_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_INT_MAX_US, mParams->wake_int_max_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_int_max_us = %d, result = %d\n",
+ __func__, mParams->wake_int_max_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_min_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_MIN_US, mParams->wake_dur_min_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_min_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_min_us, result);
+ return result;
+ }
+ }
+ if (mParams->wake_dur_max_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_DUR_MAX_US, mParams->wake_dur_max_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_dur_max_us = %d, result = %d\n",
+ __func__, mParams->wake_dur_max_us, result);
+ return result;
+ }
+ }
+ if (mParams->avg_pkt_size) {
+ result = request.put_u32(TWT_ATTRIBUTE_AVG_PKT_SIZE, mParams->avg_pkt_size);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill avg_pkt_size = %d, result = %d\n",
+ __func__, mParams->avg_pkt_size, result);
+ return result;
+ }
+ }
+ if (mParams->avg_pkt_num) {
+ result = request.put_u32(TWT_ATTRIBUTE_AVG_PKT_NUM, mParams->avg_pkt_num);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill avg_pkt_num = %d, result = %d\n",
+ __func__, mParams->avg_pkt_num, result);
+ return result;
+ }
+ }
+ if (mParams->wake_time_off_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_WAKE_TIME_OFF_US, mParams->wake_time_off_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill wake_time_off_us = %d, result = %d\n",
+ __func__, mParams->wake_time_off_us, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+
+ ALOGI("Returning successfully\n");
+ return result;
+ }
+
+ int createInfoFrameRequest(WifiRequest& request, TwtInfoFrameRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_INFO_FRAME_REQUEST);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+ if (mParams->resume_time_us) {
+ result = request.put_u32(TWT_ATTRIBUTE_RESUME_TIME_US, mParams->resume_time_us);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill resume_time_us = %d, result = %d\n",
+ __func__, mParams->resume_time_us, result);
+ return result;
+ }
+ }
+ if (mParams->all_twt) {
+ result = request.put_u8(TWT_ATTRIBUTE_ALL_TWT, mParams->all_twt);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill all_twt = %d, result = %d\n",
+ __func__, mParams->all_twt, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int createTearDownRequest(WifiRequest& request, TwtTeardownRequest *mParams)
+ {
+ int result = request.create(GOOGLE_OUI, TWT_SUBCMD_TEAR_DOWN_REQUEST);
+ if (result < 0) {
+ ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (mParams->config_id) {
+ result = request.put_u8(TWT_ATTRIBUTE_CONFIG_ID, mParams->config_id);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill config_id = %d, result = %d\n",
+ __func__, mParams->config_id, result);
+ return result;
+ }
+ }
+ if (mParams->negotiation_type) {
+ result = request.put_u8(TWT_ATTRIBUTE_NEG_TYPE, mParams->negotiation_type);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill negotiation_type = %d, result = %d\n",
+ __func__, mParams->negotiation_type, result);
+ return result;
+ }
+ }
+ if (mParams->all_twt) {
+ result = request.put_u8(TWT_ATTRIBUTE_ALL_TWT, mParams->all_twt);
+ if (result < 0) {
+ ALOGE("%s: Failed to fill all_twt = %d, result = %d\n",
+ __func__, mParams->all_twt, result);
+ return result;
+ }
+ }
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int open()
+ {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to create setup request; result = %d", __func__, result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("%s: failed to configure setup; result = %d", __func__, result);
+ return result;
+ }
+
+ request.destroy();
+ return WIFI_SUCCESS;
+ }
+
+ void registerTwtVendorEvents()
+ {
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ void unregisterTwtVendorEvents()
+ {
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_TWT);
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ u16 attr_type;
+ TwtEventType twt_event;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+ ALOGI("Received TWT event: %d\n", event_id);
+
+ if (!vendor_data || len == 0) {
+ ALOGE("No event data found");
+ return NL_SKIP;
+ }
+
+ switch (event_id) {
+ case BRCM_VENDOR_EVENT_TWT: {
+ HandleTwtEvent(vendor_data);
+ break;
+ }
+ default:
+ ALOGE("Unknown event: %d\n", event_id);
+ break;
+ }
+ return NL_SKIP;
+ }
+
+};
+
+void twt_deinit_handler()
+{
+ if (twt_info.twt_feature_request) {
+ /* register for Twt vendor events with info mac class*/
+ TwtFeatureRequest *cmd_event = (TwtFeatureRequest*)(twt_info.twt_feature_request);
+ cmd_event->unregisterTwtVendorEvents();
+ delete (TwtFeatureRequest*)twt_info.twt_feature_request;
+ twt_info.twt_feature_request = NULL;
+ }
+ if (TWT_HANDLE(twt_info)) {
+ delete GET_TWT_HANDLE(twt_info);
+ TWT_HANDLE(twt_info) = NULL;
+ }
+ ALOGI("wifi twt internal clean up done");
+ return;
+}
+
+wifi_error twt_register_handler(wifi_interface_handle iface,
+ TwtCallbackHandler handlers)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ if (TWT_HANDLE(twt_info)) {
+ /* cleanup and re-register */
+ twt_deinit_handler();
+ }
+ memset(&twt_info, 0, sizeof(twt_info));
+ TWT_HANDLE(twt_info) = new TwtHandle(handle, handlers);
+ twt_info.twt_feature_request =
+ (void*)new TwtFeatureRequest(iface, NULL, TWT_LAST);
+ NULL_CHECK_RETURN(twt_info.twt_feature_request,
+ "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ TwtFeatureRequest *cmd_event = (TwtFeatureRequest*)(twt_info.twt_feature_request);
+ cmd_event->registerTwtVendorEvents();
+ return WIFI_SUCCESS;
+}
+
+wifi_error twt_setup_request(wifi_interface_handle iface, TwtSetupRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_SETUP_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error twt_info_frame_request(wifi_interface_handle iface, TwtInfoFrameRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_INFO_FRAME_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error twt_teardown_request(wifi_interface_handle iface, TwtTeardownRequest* msg)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ TwtFeatureRequest *cmd;
+ TwtRequestType cmdType = TWT_TEAR_DOWN_REQUEST;
+
+ cmd = new TwtFeatureRequest(iface, (void *)msg, cmdType);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ret = (wifi_error)cmd->open();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+ }
+ cmd->releaseRef();
+ return ret;
+}
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 258725c..fe679ab 100755
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -53,6 +53,8 @@
#include "rtt.h"
#include "brcm_version.h"
#include <stdio.h>
+#include <string>
+#include <vector>
/*
BUGBUG: normally, libnl allocates ports for all connections it makes; but
being a static library, it doesn't really know how many other netlink connections
@@ -63,6 +65,8 @@
#define WIFI_HAL_CMD_SOCK_PORT 644
#define WIFI_HAL_EVENT_SOCK_PORT 645
+#define MAX_VIRTUAL_IFACES 5
+#define WIFI_HAL_EVENT_BUFFER_NOT_AVAILABLE 105
/*
* Defines for wifi_wait_for_driver_ready()
@@ -71,8 +75,8 @@
#define POLL_DRIVER_DURATION_US (100000)
#define POLL_DRIVER_MAX_TIME_MS (10000)
#define EVENT_BUF_SIZE 2048
+#define C2S(x) case x: return #x;
-static void internal_event_handler(wifi_handle handle, int events);
static int internal_no_seq_check(nl_msg *msg, void *arg);
static int internal_valid_message_handler(nl_msg *msg, void *arg);
static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
@@ -83,28 +87,51 @@ static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_
static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
const u8 *program, u32 len);
+static wifi_error wifi_read_packet_filter(wifi_interface_handle handle, u32 src_offset,
+ u8 *host_dst, u32 length);
static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
u32 *version, u32 *max_len);
static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable);
+static wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels);
+static wifi_error wifi_get_supported_radio_combinations_matrix(wifi_handle handle,
+ u32 max_size, u32* size, wifi_radio_combination_matrix *radio_combination_matrix);
+static void wifi_cleanup_dynamic_ifaces(wifi_handle handle);
typedef enum wifi_attr {
- ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
- ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
- ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
- ANDR_WIFI_ATTRIBUTE_NODFS_SET,
- ANDR_WIFI_ATTRIBUTE_COUNTRY,
- ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
- ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE,
- ANDR_WIFI_ATTRIBUTE_LATENCY_MODE,
- ANDR_WIFI_ATTRIBUTE_RANDOM_MAC,
- ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO
- // Add more attribute here
+ ANDR_WIFI_ATTRIBUTE_INVALID = 0,
+ ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET = 1,
+ ANDR_WIFI_ATTRIBUTE_FEATURE_SET = 2,
+ ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI = 3,
+ ANDR_WIFI_ATTRIBUTE_NODFS_SET = 4,
+ ANDR_WIFI_ATTRIBUTE_COUNTRY = 5,
+ ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE = 6,
+ ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE = 7,
+ ANDR_WIFI_ATTRIBUTE_LATENCY_MODE = 8,
+ ANDR_WIFI_ATTRIBUTE_RANDOM_MAC = 9,
+ ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO = 10,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION = 11,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW = 12,
+ ANDR_WIFI_ATTRIBUTE_VOIP_MODE = 13,
+ ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER = 14,
+ // Add more attribute here
+ ANDR_WIFI_ATTRIBUTE_MAX
} wifi_attr_t;
+enum wifi_radio_combo_attributes {
+ ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_INVALID = 0,
+ ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MATRIX = 1,
+ // Add more attribute here
+ ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MAX
+};
+
enum wifi_rssi_monitor_attr {
- RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
- RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
- RSSI_MONITOR_ATTRIBUTE_START,
+ RSSI_MONITOR_ATTRIBUTE_INVALID = 0,
+ RSSI_MONITOR_ATTRIBUTE_MAX_RSSI = 1,
+ RSSI_MONITOR_ATTRIBUTE_MIN_RSSI = 2,
+ RSSI_MONITOR_ATTRIBUTE_START = 3,
+ // Add more attribute here
+ RSSI_MONITOR_ATTRIBUTE_MAX
};
enum wifi_apf_attr {
@@ -116,7 +143,57 @@ enum wifi_apf_attr {
enum apf_request_type {
GET_APF_CAPABILITIES,
- SET_APF_PROGRAM
+ SET_APF_PROGRAM,
+ READ_APF_PROGRAM
+};
+
+enum wifi_dscp_attr {
+ DSCP_ATTRIBUTE_INVALID = 0,
+ DSCP_ATTRIBUTE_START = 1,
+ DSCP_ATTRIBUTE_END = 2,
+ DSCP_ATTRIBUTE_AC = 3,
+ /* Add more attributes here */
+ DSCP_ATTRIBUTE_MAX
+};
+
+enum wifi_dscp_request_type {
+ SET_DSCP_TABLE,
+ RESET_DSCP_TABLE
+};
+
+enum wifi_chavoid_attr {
+ CHAVOID_ATTRIBUTE_INVALID = 0,
+ CHAVOID_ATTRIBUTE_CNT = 1,
+ CHAVOID_ATTRIBUTE_CONFIG = 2,
+ CHAVOID_ATTRIBUTE_BAND = 3,
+ CHAVOID_ATTRIBUTE_CHANNEL = 4,
+ CHAVOID_ATTRIBUTE_PWRCAP = 5,
+ CHAVOID_ATTRIBUTE_MANDATORY = 6,
+ /* Add more attributes here */
+ CHAVOID_ATTRIBUTE_MAX
+};
+
+enum wifi_usable_channel_attributes {
+ USABLECHAN_ATTRIBUTE_INVALID = 0,
+ USABLECHAN_ATTRIBUTE_BAND = 1,
+ USABLECHAN_ATTRIBUTE_IFACE = 2,
+ USABLECHAN_ATTRIBUTE_FILTER = 3,
+ USABLECHAN_ATTRIBUTE_MAX_SIZE = 4,
+ USABLECHAN_ATTRIBUTE_SIZE = 5,
+ USABLECHAN_ATTRIBUTE_CHANNELS = 6,
+ USABLECHAN_ATTRIBUTE_MAX
+};
+
+enum wifi_multista_attr {
+ MULTISTA_ATTRIBUTE_PRIM_CONN_IFACE,
+ MULTISTA_ATTRIBUTE_USE_CASE,
+ /* Add more attributes here */
+ MULTISTA_ATTRIBUTE_MAX
+};
+
+enum multista_request_type {
+ SET_PRIMARY_CONNECTION,
+ SET_USE_CASE
};
/* Initialize/Cleanup */
@@ -138,26 +215,24 @@ static nl_sock * wifi_create_nl_socket(int port)
wifi_socket_set_local_port(sock, port);
- struct sockaddr *addr = NULL;
- // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
-
- // ALOGI("Connecting socket");
if (nl_connect(sock, NETLINK_GENERIC)) {
ALOGE("Could not connect handle");
nl_socket_free(sock);
return NULL;
}
+ return sock;
+}
- // ALOGI("Making socket nonblocking");
- /*
- if (nl_socket_set_nonblocking(sock)) {
- ALOGE("Could make socket non-blocking");
- nl_socket_free(sock);
- return NULL;
+static const char *IfaceTypeToString(wifi_interface_type iface_type)
+{
+ switch (iface_type) {
+ C2S(WIFI_INTERFACE_TYPE_STA)
+ C2S(WIFI_INTERFACE_TYPE_AP)
+ C2S(WIFI_INTERFACE_TYPE_P2P)
+ C2S(WIFI_INTERFACE_TYPE_NAN)
+ default:
+ return "UNKNOWN_WIFI_INTERFACE_TYPE";
}
- */
-
- return sock;
}
/*initialize function pointer table with Broadcom HHAL API*/
@@ -242,14 +317,60 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
fn->wifi_nan_data_indication_response = nan_data_indication_response;
fn->wifi_nan_data_end = nan_data_end;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
-#ifdef NAN_CLUSTER_MERGE
- fn->wifi_nan_enable_merge_request = nan_enable_cluster_merge_request;
-#endif /* NAN_CLUSTER_MERGE */
fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+ fn->wifi_read_packet_filter = wifi_read_packet_filter;
+ fn->wifi_set_subsystem_restart_handler = wifi_set_subsystem_restart_handler;
+ fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
+ fn->wifi_map_dscp_access_category = wifi_map_dscp_access_category;
+ fn->wifi_reset_dscp_mapping = wifi_reset_dscp_mapping;
+ fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
+ fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
+ fn->wifi_set_coex_unsafe_channels = wifi_set_coex_unsafe_channels;
+ fn->wifi_twt_get_capability = twt_get_capability;
+ fn->wifi_twt_register_handler = twt_register_handler;
+ fn->wifi_twt_setup_request = twt_setup_request;
+ fn->wifi_twt_teardown_request = twt_teardown_request;
+ fn->wifi_twt_info_frame_request = twt_info_frame_request;
+ fn->wifi_twt_get_stats = twt_get_stats;
+ fn->wifi_twt_clear_stats = twt_clear_stats;
+ fn->wifi_multi_sta_set_primary_connection = wifi_multi_sta_set_primary_connection;
+ fn->wifi_multi_sta_set_use_case = wifi_multi_sta_set_use_case;
+ fn->wifi_set_voip_mode = wifi_set_voip_mode;
+ fn->wifi_set_dtim_config = wifi_set_dtim_config;
+ fn->wifi_get_usable_channels = wifi_get_usable_channels;
+ fn->wifi_trigger_subsystem_restart = wifi_trigger_subsystem_restart;
+ fn->wifi_get_supported_radio_combinations_matrix = wifi_get_supported_radio_combinations_matrix;
+ fn->wifi_nan_rtt_chre_enable_request = nan_chre_enable_request;
+ fn->wifi_nan_rtt_chre_disable_request = nan_chre_disable_request;
+ fn->wifi_chre_register_handler = nan_chre_register_handler;
return WIFI_SUCCESS;
}
+#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+#include <google_wifi_firmware_config_version_info.h>
+
+static void
+wifi_check_valid_ota_version(wifi_interface_handle handle)
+{
+ bool valid = false;
+ int32_t default_ver = get_google_default_vendor_wifi_config_version();
+ int32_t ota_ver = get_google_ota_updated_wifi_config_version();
+ ALOGE("default_ver %d, ota_ver %d", default_ver, ota_ver);
+
+ if (ota_ver > default_ver) {
+ valid = verify_google_ota_updated_wifi_config_integrity();
+ }
+
+ if (valid) {
+ ALOGE("Valid config files of OTA.");
+ wifi_hal_ota_update(handle, ota_ver);
+ }
+ else {
+ ALOGE("Do not valid config files of OTA.");
+ }
+}
+#endif // GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
hal_info *halInfo = NULL;
wifi_error wifi_pre_initialize(void)
@@ -302,7 +423,7 @@ wifi_error wifi_pre_initialize(void)
}
/* Set the socket buffer size */
- if (nl_socket_set_buffer_size(event_sock, (512*1024), 0) < 0) {
+ if (nl_socket_set_buffer_size(event_sock, (4*1024*1024), 0) < 0) {
ALOGE("Could not set size for event_sock: %s",
strerror(errno));
} else {
@@ -376,6 +497,9 @@ wifi_error wifi_pre_initialize(void)
if (wlan0Handle != NULL) {
ALOGE("Calling preInit");
if (!get_halutil_mode()) {
+#ifdef GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
+ (void) wifi_check_valid_ota_version(wlan0Handle);
+#endif // GOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER
result = wifi_hal_preInit(wlan0Handle);
if (result != WIFI_SUCCESS) {
ALOGE("wifi_hal_preInit failed");
@@ -416,18 +540,10 @@ wifi_error wifi_initialize(wifi_handle *handle)
if (result != WIFI_SUCCESS) {
ALOGE("wifi_start_hal failed");
}
-#ifdef FILE_DUMP
- else {
- ALOGE("Calling start file dump");
- result = wifi_start_file_dump(wlan0Handle);
- if (result != WIFI_SUCCESS) {
- ALOGE("wifi_start_file_dump failed");
- }
- }
-#endif /* FILE_DUMP */
}
} else {
ALOGI("Not Calling set alert handler as global_iface is NULL");
+ return WIFI_ERROR_UNKNOWN;
}
return WIFI_SUCCESS;
}
@@ -500,15 +616,21 @@ static void internal_cleaned_up_handler(wifi_handle handle)
ALOGI("Internal cleanup completed");
}
+
void wifi_internal_module_cleanup()
{
nan_deinit_handler();
+ twt_deinit_handler();
}
void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
{
+ if (!handle) {
+ ALOGE("Handle is null");
+ return;
+ }
+
hal_info *info = getHalInfo(handle);
- char buf[64];
wifi_error result;
int numIfaceHandles = 0;
@@ -528,39 +650,12 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
}
}
-#ifdef FILE_DUMP
- ALOGE("Calling stop file dump");
- result = wifi_stop_file_dump(wlan0Handle);
- if (result != WIFI_SUCCESS) {
- ALOGE("wifi_stop_file_dump failed");
- }
-#endif /* FILE_DUMP */
} else {
ALOGE("Not cleaning up hal as global_iface is NULL");
}
- if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
- // As a fallback set the cleanup flag to TRUE
- ALOGE("could not write to the cleanup socket");
- } else {
- // Listen to the response
- // Hopefully we dont get errors or get hung up
- // Not much can be done in that case, but assume that
- // it has rx'ed the Exit message to exit the thread.
- // As a fallback set the cleanup flag to TRUE
- memset(buf, 0, sizeof(buf));
- ssize_t result = TEMP_FAILURE_RETRY(read(info->cleanup_socks[0], buf, sizeof(buf)));
- ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
- result, errno, strerror(errno));
- if (strncmp(buf, "Done", 4) == 0) {
- ALOGE("Event processing terminated");
- } else {
- ALOGD("Rx'ed %s", buf);
- }
- }
- info->clean_up = true;
+ /* calling internal modules or cleanup */
wifi_internal_module_cleanup();
- ALOGI("wifi nan internal clean up done");
pthread_mutex_lock(&info->cb_lock);
int bad_commands = 0;
@@ -608,8 +703,17 @@ void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
ALOGE("Leaked command %p", cmd);
}
+ if (!get_halutil_mode()) {
+ wifi_cleanup_dynamic_ifaces(handle);
+ }
pthread_mutex_unlock(&info->cb_lock);
- internal_cleaned_up_handler(handle);
+
+ info->clean_up = true;
+
+ 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");
+ }
ALOGE("wifi_clean_up done");
}
@@ -657,31 +761,25 @@ void wifi_event_loop(wifi_handle handle)
ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[0].fd, buf, sizeof(buf)));
ALOGE("Read after POLL returned %zd, error no = %d (%s)", result2,
errno, strerror(errno));
+ if (errno == WIFI_HAL_EVENT_BUFFER_NOT_AVAILABLE) {
+ ALOGE("Exit, No buffer space");
+ break;
+ }
} else if (pfd[0].revents & POLLHUP) {
ALOGE("Remote side hung up");
break;
- } else if (pfd[0].revents & POLLIN) {
+ } else if (pfd[0].revents & POLLIN && !info->clean_up) {
// ALOGI("Found some events!!!");
internal_pollin_handler(handle);
} else if (pfd[1].revents & POLLIN) {
- memset(buf, 0, sizeof(buf));
- ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[1].fd, buf, sizeof(buf)));
- ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__,
- result2, errno, strerror(errno));
- if (strncmp(buf, "Exit", 4) == 0) {
- ALOGD("Got a signal to exit!!!");
- if (TEMP_FAILURE_RETRY(write(pfd[1].fd, "Done", 4)) < 1) {
- ALOGE("could not write to the cleanup socket");
- }
- break;
- } else {
- ALOGD("Rx'ed %s on the cleanup socket\n", buf);
- }
+ ALOGI("Got a signal to exit!!!");
} else {
ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
}
} while (!info->clean_up);
- ALOGI("Exit %s", __FUNCTION__);
+
+ internal_cleaned_up_handler(handle);
+ ALOGE("Exit %s", __FUNCTION__);
}
///////////////////////////////////////////////////////////////////////////////////////
@@ -721,8 +819,6 @@ static int internal_valid_message_handler(nl_msg *msg, void *arg)
// ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
// event.log();
- bool dispatched = false;
-
pthread_mutex_lock(&info->cb_lock);
for (int i = 0; i < info->num_event_cb; i++) {
@@ -794,7 +890,6 @@ public:
// ALOGI("handling reponse in %s", __func__);
struct nlattr **tb = reply.attributes();
- struct genlmsghdr *gnlh = reply.header();
struct nlattr *mcgrp = NULL;
int i;
@@ -961,7 +1056,36 @@ public:
: WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
(min_rssi), mHandler(eh)
{
+ ALOGI("SetRSSIMonitorCommand %p created", this);
+ }
+
+ virtual ~SetRSSIMonitorCommand() {
+ /*
+ * Mostly, this call will be no effect. However, this could be valid
+ * when object destroy without calling unregisterVendorHandler().
+ * This is added to protect hal crash due to use-after-free.
+ */
+ 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);
+ ALOGI("SetRSSIMonitorCommand %p destroyed", this);
+ }
+
+ virtual void addRef() {
+ int refs = __sync_add_and_fetch(&mRefs, 1);
+ ALOGI("addRef: WifiCommand %p has %d references", this, refs);
+ }
+
+ virtual void releaseRef() {
+ int refs = __sync_sub_and_fetch(&mRefs, 1);
+ if (refs == 0) {
+ ALOGI("releaseRef: WifiCommand %p has deleted", this);
+ delete this;
+ } else {
+ ALOGI("releaseRef: WifiCommand %p has %d references", this, refs);
}
+ }
+
int createRequest(WifiRequest& request, int enable) {
int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
if (result < 0) {
@@ -989,27 +1113,27 @@ public:
int start() {
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request, 1);
- if (result < 0) {
- return result;
- }
- result = requestResponse(request);
- if (result < 0) {
- ALOGI("Failed to set RSSI Monitor, result = %d", result);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to create request; result = %d", result);
return result;
}
- ALOGI("Successfully set RSSI monitoring");
- result = registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ ALOGI("Register GOOGLE_RSSI_MONITOR_EVENT handler");
- if (result < 0) {
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+ ALOGE("Failed to set RSSI Monitor, result = %d", result);
return result;
}
- ALOGI("Done!");
+
+ ALOGI("Successfully set RSSI monitoring");
return result;
}
virtual int cancel() {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request, 0);
@@ -1021,7 +1145,6 @@ public:
ALOGE("failed to stop RSSI monitoring = %d", result);
}
}
- unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
return WIFI_SUCCESS;
}
@@ -1069,6 +1192,7 @@ public:
class AndroidPktFilterCommand : public WifiCommand {
private:
const u8* mProgram;
+ u8* mReadProgram;
u32 mProgramLen;
u32* mVersion;
u32* mMaxLen;
@@ -1094,13 +1218,24 @@ class AndroidPktFilterCommand : public WifiCommand {
mMaxLen = NULL;
}
+ AndroidPktFilterCommand(wifi_interface_handle handle,
+ u8* host_dst, u32 length)
+ : WifiCommand("AndroidPktFilterCommand", handle, 0),
+ mReadProgram(host_dst), mProgramLen(length),
+ mReqType(READ_APF_PROGRAM)
+ {
+ }
+
int createRequest(WifiRequest& request) {
if (mReqType == SET_APF_PROGRAM) {
ALOGI("\n%s: APF set program request\n", __FUNCTION__);
return createSetPktFilterRequest(request);
} else if (mReqType == GET_APF_CAPABILITIES) {
ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
- return createGetPktFilterCapabilitesRequest(request);
+ return createGetPktFilterCapabilitesRequest(request);
+ } else if (mReqType == READ_APF_PROGRAM) {
+ ALOGI("\n%s: APF read packet filter request\n", __FUNCTION__);
+ return createReadPktFilterRequest(request);
} else {
ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
return WIFI_ERROR_NOT_SUPPORTED;
@@ -1143,6 +1278,16 @@ exit: request.attr_end(data);
return result;
}
+ int createReadPktFilterRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, APF_SUBCMD_READ_FILTER);
+ if (result < 0) {
+ return result;
+ }
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+ return result;
+ }
+
int start() {
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request);
@@ -1182,11 +1327,11 @@ exit: request.attr_end(data);
return NL_SKIP;
}
if( mReqType == SET_APF_PROGRAM) {
- ALOGD("Response recieved for set packet filter command\n");
+ ALOGD("Response received for set packet filter command\n");
} else if (mReqType == GET_APF_CAPABILITIES) {
*mVersion = 0;
*mMaxLen = 0;
- ALOGD("Response recieved for get packet filter capabilities command\n");
+ ALOGD("Response received for get packet filter capabilities command\n");
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == APF_ATTRIBUTE_VERSION) {
*mVersion = it.get_u32();
@@ -1199,12 +1344,24 @@ exit: request.attr_end(data);
it.get_type(), it.get_len());
}
}
+ } else if (mReqType == READ_APF_PROGRAM) {
+ ALOGD("Read packet filter, mProgramLen = %d\n", mProgramLen);
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == APF_ATTRIBUTE_PROGRAM) {
+ u8 *buffer = NULL;
+ buffer = (u8 *)it.get_data();
+ memcpy(mReadProgram, buffer, mProgramLen);
+ } else if (it.get_type() == APF_ATTRIBUTE_PROGRAM_LEN) {
+ int apf_length = it.get_u32();
+ ALOGD("apf program length = %d\n", apf_length);
+ }
+ }
}
return NL_OK;
}
int handleEvent(WifiEvent& event) {
- /* No Event to recieve for APF commands */
+ /* No Event to receive for APF commands */
return NL_SKIP;
}
};
@@ -1335,6 +1492,93 @@ protected:
}
};
+/////////////////////////////////////////////////////////////////////
+class GetRadioComboCommand : public WifiCommand {
+private:
+ wifi_radio_combination_matrix *rcmatrix;
+ u32* rc_size;
+ u32 set_size_max;
+ int ret = 0;
+
+public:
+ GetRadioComboCommand(wifi_interface_handle handle, u32 max_size, u32* size,
+ wifi_radio_combination_matrix *radio_combination_matrix)
+ : WifiCommand("GetRadioComboCommand", handle, 0), rcmatrix(radio_combination_matrix),
+ rc_size(size), set_size_max(max_size)
+ {
+ }
+
+ virtual int createRequest(WifiRequest& mMsg) {
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_RADIO_COMBO_MATRIX);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ }
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ mMsg.attr_end(data);
+
+ return ret;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ ret = createRequest(request);
+ if (ret < 0) {
+ ALOGE("Request failed for radio_combo_matrix, result = %d", ret);
+ return ret;
+ }
+ ret = requestResponse(request);
+ if (ret < 0) {
+ ALOGE("Request Response failed for radio_combo_matrix, result = %d", ret);
+ return ret;
+ }
+ ALOGD("Done! %s", __FUNCTION__);
+ return ret;
+ }
+
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In GetRadioComboCommand::handleResponse");
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetRadioComboCommand response; ignoring it");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MATRIX) {
+ void *data = it.get_data();
+ *rc_size = it.get_len();
+ if (!data || !*rc_size) {
+ ALOGE("Buffers pointers not set");
+ return NL_SKIP;
+ }
+ if (set_size_max < *rc_size) {
+ ALOGE("Unexpected buffers size");
+ return NL_SKIP;
+ }
+ memcpy(rcmatrix, data, min(len, *rc_size));
+ } else {
+ ALOGW("Ignoring invalid attribute type = %d, size = %d",
+ it.get_type(), it.get_len());
+ }
+ }
+
+ ALOGD("GetRadioComboCommand::Success");
+ return NL_OK;
+ }
+};
+/////////////////////////////////////////////////////////////////////
class SetLatencyModeCommand : public WifiCommand {
private:
@@ -1385,7 +1629,8 @@ static int wifi_get_multicast_id(wifi_handle handle, const char *name, const cha
static bool is_wifi_interface(const char *name)
{
- if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "swlan", 5) != 0 && strncmp(name, "p2p", 3) != 0) {
+ if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "swlan", 5) != 0 &&
+ strncmp(name, "p2p", 3) != 0 && strncmp(name, "aware", 5) != 0) {
/* not a wifi interface; ignore it */
return false;
} else {
@@ -1395,7 +1640,11 @@ static bool is_wifi_interface(const char *name)
static int get_interface(const char *name, interface_info *info)
{
- strlcpy(info->name, name, sizeof(info->name));
+ int size = 0;
+ size = strlcpy(info->name, name, sizeof(info->name));
+ if (size >= sizeof(info->name)) {
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
info->id = if_nametoindex(name);
// ALOGI("found an interface : %s, id = %d", name, info->id);
return WIFI_SUCCESS;
@@ -1429,7 +1678,9 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
if (d == 0)
return WIFI_ERROR_UNKNOWN;
- info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
+ /* Have place holder for 3 virtual interfaces */
+ n += MAX_VIRTUAL_IFACES;
+ info->interfaces = (interface_info **)calloc(n, sizeof(interface_info *) * n);
if (!info->interfaces) {
info->num_interfaces = 0;
closedir(d);
@@ -1448,10 +1699,12 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
closedir(d);
return WIFI_ERROR_OUT_OF_MEMORY;
}
+ memset(ifinfo, 0, sizeof(interface_info));
if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
- free(ifinfo);
continue;
}
+ /* Mark as static iface */
+ ifinfo->is_virtual = false;
ifinfo->handle = handle;
info->interfaces[i] = ifinfo;
i++;
@@ -1460,7 +1713,8 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
closedir(d);
- info->num_interfaces = n;
+ info->num_interfaces = i;
+ info->max_num_interfaces = n;
return WIFI_SUCCESS;
}
@@ -1474,6 +1728,74 @@ wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle *
return WIFI_SUCCESS;
}
+wifi_error wifi_add_iface_hal_info(wifi_handle handle, const char* ifname)
+{
+ hal_info *info = NULL;
+ int i = 0;
+
+ info = (hal_info *)handle;
+ if (info == NULL) {
+ ALOGE("Could not find info\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ ALOGI("%s: add interface_info for iface: %s\n", __FUNCTION__, ifname);
+ if (info->num_interfaces == MAX_VIRTUAL_IFACES) {
+ ALOGE("No space. max limit reached for virtual interfaces %d\n", info->num_interfaces);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
+ if (!ifinfo) {
+ free(info->interfaces);
+ info->num_interfaces = 0;
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ ifinfo->handle = handle;
+ while (i < info->max_num_interfaces) {
+ if (info->interfaces[i] == NULL) {
+ if (get_interface(ifname, ifinfo) != WIFI_SUCCESS) {
+ continue;
+ }
+ ifinfo->is_virtual = true;
+ info->interfaces[i] = ifinfo;
+ info->num_interfaces++;
+ ALOGI("%s: Added iface: %s at the index %d\n", __FUNCTION__, ifname, i);
+ break;
+ }
+ i++;
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_clear_iface_hal_info(wifi_handle handle, const char* ifname)
+{
+ hal_info *info = (hal_info *)handle;
+ int i = 0;
+
+ ALOGI("%s: clear hal info for iface: %s\n", __FUNCTION__, ifname);
+ while (i < info->max_num_interfaces) {
+ if ((info->interfaces[i] != NULL) &&
+ strncmp(info->interfaces[i]->name, ifname,
+ sizeof(info->interfaces[i]->name)) == 0) {
+ free(info->interfaces[i]);
+ info->interfaces[i] = NULL;
+ info->num_interfaces--;
+ ALOGI("%s: Cleared the index = %d for iface: %s\n", __FUNCTION__, i, ifname);
+ break;
+ }
+ i++;
+ }
+ if (i < info->num_interfaces) {
+ for (int j = i; j < info->num_interfaces; j++) {
+ info->interfaces[j] = info->interfaces[j+1];
+ }
+ info->interfaces[info->num_interfaces] = NULL;
+ }
+ return WIFI_SUCCESS;
+}
+
wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_handle *ifaceHandles, int numIfaceHandles)
{
char buf[EVENT_BUF_SIZE];
@@ -1484,7 +1806,7 @@ wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_h
}
for (int i = 0; i < numIfaceHandles; i++) {
if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
- if (strcmp(buf, "wlan0") == 0) {
+ if (strncmp(buf, "wlan0", 5) == 0) {
ALOGI("found interface %s\n", buf);
wlan0Handle = ifaceHandles[i];
return wlan0Handle;
@@ -1501,6 +1823,29 @@ wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t
return WIFI_SUCCESS;
}
+wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
+{
+ char buf[EVENT_BUF_SIZE];
+ wifi_interface_handle *ifaceHandles;
+ int numIfaceHandles;
+ wifi_interface_handle ifHandle;
+
+ wifi_error res = wifi_get_ifaces((wifi_handle)handle, &numIfaceHandles, &ifaceHandles);
+ if (res < 0) {
+ return NULL;
+ }
+ for (int i = 0; i < numIfaceHandles; i++) {
+ if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
+ if (strcmp(buf, name) == 0) {
+ ALOGI("found interface %s\n", buf);
+ ifHandle = ifaceHandles[i];
+ return ifHandle;
+ }
+ }
+ }
+ return NULL;
+}
+
wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
{
GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1);
@@ -1515,6 +1860,27 @@ wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_siz
return (wifi_error) command.requestResponse();
}
+wifi_error wifi_get_supported_radio_combinations_matrix(wifi_handle handle,
+ u32 max_size, u32* size, wifi_radio_combination_matrix *radio_combination_matrix)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ GetRadioComboCommand *cmd = new GetRadioComboCommand(wlan0Handle, max_size,
+ size, radio_combination_matrix);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGD("Get radio combo matrix success");
+ } else {
+ ALOGE("Get radio combo matrix failed\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
{
SetPnoMacAddrOuiCommand command(handle, scan_oui);
@@ -1537,17 +1903,19 @@ wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *count
static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
{
- ALOGD("Start RSSI monitor %d", id);
+ ALOGI("Starting RSSI monitor %d", id);
wifi_handle handle = getWifiHandle(iface);
SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = wifi_register_cmd(handle, id, cmd);
if (result != WIFI_SUCCESS) {
+ ALOGI("wifi_register_cmd() is failed %d", id);
cmd->releaseRef();
return result;
}
result = (wifi_error)cmd->start();
if (result != WIFI_SUCCESS) {
+ ALOGI("start() is failed %d", id);
wifi_unregister_cmd(handle, id);
cmd->releaseRef();
return result;
@@ -1557,12 +1925,11 @@ static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_
static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
{
- ALOGD("Stopping RSSI monitor");
+ ALOGI("Stopping RSSI monitor %d", id);
if(id == -1) {
wifi_rssi_event_handler handler;
s8 max_rssi = 0, min_rssi = 0;
- wifi_handle handle = getWifiHandle(iface);
memset(&handler, 0, sizeof(handler));
SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
max_rssi, min_rssi, handler);
@@ -1599,6 +1966,19 @@ static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
return result;
}
+static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
+ u32 src_offset, u8 *host_dst, u32 length)
+{
+ ALOGD("Read APF program, halHandle = %p, length = %d\n", handle, length);
+ AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, host_dst, length);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Read APF program success\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
{
SetNdoffloadCommand command(handle, enable);
@@ -1636,7 +2016,7 @@ public:
}
if ((mScenario <= WIFI_POWER_SCENARIO_INVALID) ||
- (mScenario > WIFI_POWER_SCENARIO_ON_BODY_BT)) {
+ (mScenario >= SAR_CONFIG_SCENARIO_COUNT)) {
ALOGE("Unsupported tx power value:%d\n", mScenario);
return WIFI_ERROR_NOT_SUPPORTED;
}
@@ -1690,3 +2070,934 @@ wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
}
/////////////////////////////////////////////////////////////////////////////
+
+class ThermalMitigation : public WifiCommand {
+private:
+ wifi_thermal_mode mMitigation;
+ u32 mCompletionWindow;
+public:
+ // constructor for thermal mitigation setting
+ ThermalMitigation(wifi_interface_handle handle,
+ wifi_thermal_mode mitigation, u32 completion_window)
+ : WifiCommand("ThermalMitigation", handle, 0)
+ {
+ mMitigation = mitigation;
+ mCompletionWindow = completion_window;
+ }
+
+ int createRequest(WifiRequest& request, int subcmd,
+ wifi_thermal_mode mitigation, u32 completion_window) {
+ int result = request.create(GOOGLE_OUI, subcmd);
+ if (result < 0) {
+ return result;
+ }
+
+ if ((mitigation < WIFI_MITIGATION_NONE) ||
+ (mitigation > WIFI_MITIGATION_EMERGENCY)) {
+ ALOGE("Unsupported tx mitigation value:%d\n", mitigation);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_s8(ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION, mitigation);
+ if (result < 0) {
+ ALOGE("Failed to put tx power scenario request; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW,
+ completion_window);
+ if (result < 0) {
+ ALOGE("Failed to put tx power scenario request; result = %d", result);
+ return result;
+ }
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, WIFI_SUBCMD_THERMAL_MITIGATION, mMitigation,
+ mCompletionWindow);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ return result;
+ }
+
+ ALOGD("try to get resp; mitigation=%d, delay=%d", mMitigation, mCompletionWindow);
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to send thermal mitigation; result = %d", result);
+ }
+ return result;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle,
+ wifi_thermal_mode mode,
+ u32 completion_window)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ ThermalMitigation command(wlan0Handle, mode, completion_window);
+ return (wifi_error)command.start();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+class ChAvoidCommand : public WifiCommand {
+ private:
+ u32 mNumParams;
+ wifi_coex_unsafe_channel *chavoidParams;
+ u32 mMandatory;
+
+ public:
+ ChAvoidCommand(wifi_interface_handle handle,
+ u32 num, wifi_coex_unsafe_channel channels[], u32 mandatory)
+ : WifiCommand("ChAvoidCommand", handle, 0),
+ mNumParams(num), chavoidParams(channels), mMandatory(mandatory)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ return createSetChAvoidRequest(request);
+ }
+
+ int createSetChAvoidRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, CHAVOID_SUBCMD_SET_CONFIG);
+ if (result < 0) {
+ ALOGE("%s : Failed to create SUBCMD\n", __func__);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(CHAVOID_ATTRIBUTE_CNT, mNumParams);
+ if (result < 0) {
+ ALOGE("%s : Failed to set cound\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_MANDATORY, mMandatory);
+ if (result < 0) {
+ ALOGE("%s : Failed to set mandatory cap\n", __func__);
+ return result;
+ }
+
+ nlattr *chavoid_config = request.attr_start(CHAVOID_ATTRIBUTE_CONFIG);
+ for (int i = 0; i< mNumParams; i++) {
+ nlattr *item = request.attr_start(i);
+ if (item == NULL) {
+ ALOGE("%s : Failed to alloc item\n", __func__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_BAND, chavoidParams[i].band);
+ if (result < 0) {
+ ALOGE("%s : Failed to set band\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_CHANNEL, chavoidParams[i].channel);
+ if (result < 0) {
+ ALOGE("%s : Failed to set channel\n", __func__);
+ return result;
+ }
+ result = request.put_u32(CHAVOID_ATTRIBUTE_PWRCAP, chavoidParams[i].power_cap_dbm);
+ if (result < 0) {
+ ALOGE("%s : Failed to set power cap\n", __func__);
+ return result;
+ }
+ request.attr_end(item);
+ }
+ request.attr_end(chavoid_config);
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for ChAvoid, result = %d", result);
+ return result;
+ }
+ return result;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ ALOGD("In ChAvoidCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in ChAvoidCommand response; ignoring it");
+ return NL_SKIP;
+ }
+ ALOGD("Response received for ChAvoid command\n");
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* No Event to receive for ChAvoid commands */
+ ALOGD("ChAvoid command %s\n", __FUNCTION__);
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_set_coex_unsafe_channels(wifi_handle handle,
+ u32 num, wifi_coex_unsafe_channel channels[], u32 mandatory)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ ChAvoidCommand *cmd = new ChAvoidCommand(wlan0Handle, num, channels, mandatory);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Setting Channel Avoidance success\n");
+ } else {
+ ALOGE("Setting Channel Avoidance failed\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+class DscpCommand : public WifiCommand {
+ private:
+ u32 mStart;
+ u32 mEnd;
+ u32 mAc;
+ int mReqType;
+ public:
+ DscpCommand(wifi_interface_handle handle,
+ u32 start, u32 end, u32 ac)
+ : WifiCommand("DscpCommand", handle, 0),
+ mStart(start), mEnd(end), mAc(ac),
+ mReqType(SET_DSCP_TABLE)
+ {
+ }
+
+ DscpCommand(wifi_interface_handle handle)
+ : WifiCommand("DscpCommand", handle, 0),
+ mReqType(RESET_DSCP_TABLE)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ if (mReqType == SET_DSCP_TABLE) {
+ ALOGI("\n%s: DSCP set table request\n", __FUNCTION__);
+ return createSetDscpRequest(request);
+ } else if (mReqType == RESET_DSCP_TABLE) {
+ ALOGI("\n%s: DSCP reset table request\n", __FUNCTION__);
+ return createResetDscpRequest(request);
+ } else {
+ ALOGE("\n%s Unknown DSCP request\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createSetDscpRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, DSCP_SUBCMD_SET_TABLE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(DSCP_ATTRIBUTE_START, mStart);
+ if (result < 0) {
+ goto exit;
+ }
+ result = request.put_u32(DSCP_ATTRIBUTE_END, mEnd);
+ if (result < 0) {
+ goto exit;
+ }
+ result = request.put_u32(DSCP_ATTRIBUTE_AC, mAc);
+ if (result < 0) {
+ goto exit;
+ }
+ request.attr_end(data);
+exit:
+ return result;
+ }
+
+ int createResetDscpRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, DSCP_SUBCMD_RESET_TABLE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for DSCP, result = %d", result);
+ return result;
+ }
+ return result;
+ }
+
+ int handleResponse(WifiEvent& reply) {
+ ALOGD("In DscpCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in DscpCommand response; ignoring it");
+ return NL_SKIP;
+ }
+ if( mReqType == SET_DSCP_TABLE) {
+ ALOGD("Response received for Set DSCP command\n");
+ } else if (mReqType == RESET_DSCP_TABLE) {
+ ALOGD("Response received for Reset DSCP command\n");
+ }
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* No Event to receive for DSCP commands */
+ ALOGD("DSCP command %s\n", __FUNCTION__);
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_map_dscp_access_category(wifi_handle handle,
+ u32 start, u32 end, u32 ac)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ DscpCommand *cmd = new DscpCommand(wlan0Handle, start, end, ac);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Mapping DSCP table success\n");
+ } else {
+ ALOGE("Mapping DSCP table fail\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+wifi_error wifi_reset_dscp_mapping(wifi_handle handle)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ DscpCommand *cmd = new DscpCommand(wlan0Handle);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = (wifi_error)cmd->start();
+ if (result == WIFI_SUCCESS) {
+ ALOGI("Resetting DSCP table success\n");
+ } else {
+ ALOGE("Resetting DSCP table fail\n");
+ }
+ cmd->releaseRef();
+ return result;
+}
+
+class VirtualIfaceConfig : public WifiCommand {
+ const char *mIfname;
+ nl80211_iftype mType;
+ u32 mwlan0_id;
+
+public:
+ VirtualIfaceConfig(wifi_interface_handle handle, const char* ifname,
+ nl80211_iftype iface_type, u32 wlan0_id)
+ : WifiCommand("VirtualIfaceConfig", handle, 0), mIfname(ifname), mType(iface_type),
+ mwlan0_id(wlan0_id)
+ {
+ mIfname = ifname;
+ mType = iface_type;
+ mwlan0_id = wlan0_id;
+ }
+ int createRequest(WifiRequest& request, const char* ifname,
+ nl80211_iftype iface_type, u32 wlan0_id) {
+ ALOGD("add ifname = %s, iface_type = %d, wlan0_id = %d",
+ ifname, iface_type, wlan0_id);
+
+ int result = request.create(NL80211_CMD_NEW_INTERFACE);
+ if (result < 0) {
+ ALOGE("failed to create NL80211_CMD_NEW_INTERFACE; result = %d", result);
+ return result;
+ }
+
+ result = request.put_u32(NL80211_ATTR_IFINDEX, wlan0_id);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFINDEX; result = %d", result);
+ return result;
+ }
+
+ result = request.put_string(NL80211_ATTR_IFNAME, ifname);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFNAME = %s; result = %d", ifname, result);
+ return result;
+ }
+
+ result = request.put_u32(NL80211_ATTR_IFTYPE, iface_type);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFTYPE = %d; result = %d", iface_type, result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int deleteRequest(WifiRequest& request, const char* ifname) {
+ ALOGD("delete ifname = %s\n", ifname);
+ int result = request.create(NL80211_CMD_DEL_INTERFACE);
+ if (result < 0) {
+ ALOGE("failed to create NL80211_CMD_DEL_INTERFACE; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFINDEX = %d; result = %d",
+ if_nametoindex(ifname), result);
+ return result;
+ }
+ result = request.put_string(NL80211_ATTR_IFNAME, ifname);
+ if (result < 0) {
+ ALOGE("failed to put NL80211_ATTR_IFNAME = %s; result = %d", ifname, result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createIface() {
+ ALOGE("Creating virtual interface");
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request, mIfname, mType, mwlan0_id);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create virtual iface request; result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to get the virtual iface create response; result = %d\n", result);
+ return result;
+ }
+ ALOGE("Created virtual interface");
+ return WIFI_SUCCESS;
+ }
+
+ int deleteIface() {
+ ALOGD("Deleting virtual interface");
+ WifiRequest request(familyId(), ifaceId());
+ int result = deleteRequest(request, mIfname);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create virtual iface delete request; result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to get response of delete virtual interface; result = %d\n", result);
+ return result;
+ }
+ return WIFI_SUCCESS;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+static std::vector<std::string> added_ifaces;
+
+static void wifi_cleanup_dynamic_ifaces(wifi_handle handle)
+{
+ int len = added_ifaces.size();
+ while (len--) {
+ wifi_virtual_interface_delete(handle, added_ifaces.front().c_str());
+ }
+ added_ifaces.clear();
+}
+
+wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
+ wifi_interface_type iface_type)
+{
+ int numIfaceHandles = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
+ u32 wlan0_id = if_nametoindex("wlan0");
+
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ /* Do not create interface if already exist. */
+ if (if_nametoindex(ifname)) {
+ ALOGD("%s: if_nametoindex(%s) = %d already exists, skip create \n",
+ __FUNCTION__, ifname, if_nametoindex(ifname));
+ return WIFI_SUCCESS;
+ }
+
+ ALOGD("%s: ifname name = %s, type = %s\n", __FUNCTION__, ifname,
+ IfaceTypeToString(iface_type));
+
+ switch (iface_type) {
+ case WIFI_INTERFACE_TYPE_STA:
+ type = NL80211_IFTYPE_STATION;
+ break;
+ case WIFI_INTERFACE_TYPE_AP:
+ type = NL80211_IFTYPE_AP;
+ break;
+ case WIFI_INTERFACE_TYPE_P2P:
+ type = NL80211_IFTYPE_P2P_DEVICE;
+ break;
+ case WIFI_INTERFACE_TYPE_NAN:
+ type = NL80211_IFTYPE_NAN;
+ break;
+ default:
+ ALOGE("%s: Wrong interface type %u\n", __FUNCTION__, iface_type);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ VirtualIfaceConfig command(wlan0Handle, ifname, type, wlan0_id);
+
+ ret = (wifi_error)command.createIface();
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Iface add Error:%d", __FUNCTION__,ret);
+ return ret;
+ }
+ /* Update dynamic interface list */
+ added_ifaces.push_back(std::string(ifname));
+ ret = wifi_add_iface_hal_info((wifi_handle)handle, ifname);
+ return ret;
+}
+
+wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname)
+{
+ int numIfaceHandles = 0;
+ int i = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ hal_info *info = (hal_info *)handle;
+ u32 wlan0_id = if_nametoindex("wlan0");
+
+ if (!handle || !wlan0_id) {
+ ALOGE("%s: Error wifi_handle NULL or wlan0 not present\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ 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;
+ }
+ }
+ i++;
+ }
+
+ ALOGD("%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;
+ }
+ /* Update dynamic interface list */
+ added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
+ added_ifaces.end());
+ ret = wifi_clear_iface_hal_info((wifi_handle)handle, ifname);
+ return ret;
+}
+/////////////////////////////////////////////////////////////////////////////
+
+class MultiStaConfig : public WifiCommand {
+ wifi_multi_sta_use_case mUseCase;
+ int mReqType;
+
+public:
+ MultiStaConfig(wifi_interface_handle handle)
+ : WifiCommand("MultiStaConfig", handle, 0), mReqType(SET_PRIMARY_CONNECTION)
+ {
+ }
+ MultiStaConfig(wifi_interface_handle handle, wifi_multi_sta_use_case use_case)
+ : WifiCommand("MultiStaConfig", handle, 0), mUseCase(use_case), mReqType(SET_USE_CASE)
+ {
+ mUseCase = use_case;
+ }
+
+ int createRequest(WifiRequest& request) {
+ if (mReqType == SET_PRIMARY_CONNECTION) {
+ ALOGI("\n%s: MultiSta set primary connection\n", __FUNCTION__);
+ return createSetPrimaryConnectionRequest(request);
+ } else if (mReqType == SET_USE_CASE) {
+ ALOGI("\n%s: MultiSta set use case\n", __FUNCTION__);
+ return createSetUsecaseRequest(request);
+ } else {
+ ALOGE("\n%s Unknown MultiSta request\n", __FUNCTION__);
+ return WIFI_ERROR_NOT_SUPPORTED;
+ }
+ return WIFI_SUCCESS;
+ }
+
+ int createSetPrimaryConnectionRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ request.attr_end(data);
+
+ return result;
+ }
+
+ int createSetUsecaseRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_MULTISTA_USE_CASE);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+ result = request.put_u32(MULTISTA_ATTRIBUTE_USE_CASE, mUseCase);
+ if (result < 0) {
+ ALOGE("failed to put MULTISTA_ATTRIBUTE_USE_CASE = %d; result = %d", mUseCase, result);
+ goto exit;
+ }
+
+exit: request.attr_end(data);
+ return result;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result < 0) {
+ return result;
+ }
+ result = requestResponse(request);
+ if (result < 0) {
+ ALOGI("Request Response failed for MultiSta, result = %d", result);
+ return result;
+ }
+ ALOGI("Done!");
+ return result;
+ }
+protected:
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("Request complete!");
+ /* Nothing to do on response! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle, wifi_interface_handle iface)
+{
+ wifi_error ret = WIFI_SUCCESS;
+ char buf[IFNAMSIZ];
+
+ if (!handle || !iface) {
+ ALOGE("%s: Error wifi_handle NULL or invalid wifi interface handle\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (wifi_get_iface_name(iface, buf, sizeof(buf)) != WIFI_SUCCESS) {
+ ALOGE("%s : Invalid interface handle\n", __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ ALOGD("Setting Multista primary connection for iface = %s\n", buf);
+
+ MultiStaConfig *cmd = new MultiStaConfig(iface);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ cmd->releaseRef();
+ return ret;
+}
+
+wifi_error wifi_multi_sta_set_use_case(wifi_handle handle, wifi_multi_sta_use_case use_case)
+{
+ int numIfaceHandles = 0;
+ wifi_error ret = WIFI_SUCCESS;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ if (!handle) {
+ ALOGE("%s: Error wifi_handle NULL\n", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (!(use_case >= WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY &&
+ use_case <= WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED)) {
+ ALOGE("%s: Invalid multi_sta usecase %d\n", __FUNCTION__, use_case);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ ALOGD("Setting Multista usecase = %d\n", use_case);
+ MultiStaConfig *cmd = new MultiStaConfig(wlan0Handle, use_case);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ ret = (wifi_error)cmd->start();
+ cmd->releaseRef();
+ return ret;
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SetVoipModeCommand : public WifiCommand {
+
+private:
+ wifi_voip_mode mMode;
+public:
+ SetVoipModeCommand(wifi_interface_handle handle, wifi_voip_mode mode)
+ : WifiCommand("SetVoipModeCommand", handle, 0) {
+ mMode = mode;
+ }
+ virtual int create() {
+ int ret;
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_VOIP_MODE);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_VOIP_MODE, mMode);
+ ALOGE("mMode - %d", mMode);
+ if (ret < 0) {
+ ALOGE("Failed to set voip mode %d\n", mMode);
+ return ret;
+ }
+
+ ALOGI("Successfully configured voip mode %d\n", mMode);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
+
+wifi_error wifi_set_voip_mode(wifi_interface_handle handle, wifi_voip_mode mode)
+{
+ ALOGD("Setting VOIP mode, halHandle = %p Mode = %d\n", handle, mode);
+ SetVoipModeCommand command(handle, mode);
+ return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+class SetDtimConfigCommand : public WifiCommand {
+
+private:
+ uint32_t multiplier;
+public:
+ SetDtimConfigCommand(wifi_interface_handle handle, u32 dtim_multiplier)
+ : WifiCommand("SetDtimConfigCommand", handle, 0) {
+ multiplier = dtim_multiplier;
+ }
+ virtual int create() {
+ int ret;
+
+ ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_DTIM_CONFIG);
+ if (ret < 0) {
+ ALOGE("Can't create message to send to driver - %d", ret);
+ return ret;
+ }
+
+ nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+ ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER, multiplier);
+ if (ret < 0) {
+ ALOGE("Failed to set dtim mutiplier %d\n", multiplier);
+ return ret;
+ }
+
+ ALOGI("Successfully configured dtim multiplier %d\n", multiplier);
+ mMsg.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+};
+
+wifi_error wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier)
+{
+ ALOGD("Setting DTIM config , halHandle = %p Multiplier = %d\n", handle, multiplier);
+ SetDtimConfigCommand command(handle, multiplier);
+ return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+class UsableChannelCommand : public WifiCommand {
+
+private:
+ u32 mBandMask;
+ u32 mIfaceModeMask;
+ u32 mFilterMask;
+ u32 mMaxSize;
+ u32* mSize;
+ wifi_usable_channel* mChannels;
+
+public:
+ UsableChannelCommand(wifi_interface_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels)
+ : WifiCommand("UsableChannelCommand", handle, 0),
+ mBandMask(band_mask), mIfaceModeMask(iface_mode_mask),
+ mFilterMask(filter_mask), mMaxSize(max_size),
+ mSize(size), mChannels(channels)
+ {
+ }
+
+ int createRequest(WifiRequest& request) {
+ createUsableChannelRequest(request);
+ return WIFI_SUCCESS;
+ }
+
+ int createUsableChannelRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_USABLE_CHANNEL);
+ if (result < 0) {
+ ALOGE("Failed to create UsableChannel request; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_BAND, mBandMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put log level; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_IFACE, mIfaceModeMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put ring flags; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_FILTER, mFilterMask);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put usablechan filter; result = %d", result);
+ return result;
+ }
+ result = request.put_u32(USABLECHAN_ATTRIBUTE_MAX_SIZE, mMaxSize);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put usablechan max_size; result = %d", result);
+ return result;
+ }
+ request.attr_end(data);
+
+ return WIFI_SUCCESS;
+ }
+
+ int start() {
+ WifiRequest request(familyId(), ifaceId());
+ int result = createRequest(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to create request; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("failed to set scanning mac OUI; result = %d", result);
+ }
+
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In DebugCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+ wifi_usable_channel *channels(mChannels);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+
+ nl_iterator it(vendor_data);
+ if (it.get_type() == USABLECHAN_ATTRIBUTE_SIZE) {
+ *mSize = it.get_u32();
+ } else {
+ ALOGE("Unknown attribute: %d expecting %d",
+ it.get_type(), USABLECHAN_ATTRIBUTE_SIZE);
+ return NL_SKIP;
+ }
+
+ it.next();
+ if (it.get_type() == USABLECHAN_ATTRIBUTE_CHANNELS) {
+ memcpy(channels, it.get_data(), sizeof(wifi_usable_channel) * *mSize);
+ } else {
+ ALOGE("Unknown attribute: %d expecting %d",
+ it.get_type(), USABLECHAN_ATTRIBUTE_SIZE);
+ return NL_SKIP;
+ }
+
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask,
+ u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels)
+{
+ int numIfaceHandles = 0;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+ UsableChannelCommand command(wlan0Handle, band_mask, iface_mode_mask,
+ filter_mask, max_size, size, channels);
+ return (wifi_error)command.start();
+}
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index e35bf9b..4d2d8dd 100755
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -26,6 +26,7 @@
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/errqueue.h>
+#include <errno.h>
#include <linux/pkt_sched.h>
#include <netlink/object-api.h>
@@ -34,6 +35,7 @@
#include <netlink-private/object-api.h>
#include <netlink-private/types.h>
#include <unistd.h>
+#include <cutils/properties.h>
#include "nl80211_copy.h"
@@ -46,6 +48,7 @@
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
+#include <sys/stat.h>
#include "brcm_version.h"
#define WIFI_HAL_EVENT_SOCK_PORT 645
@@ -69,28 +72,58 @@ typedef enum {
LOGGER_FILE_DUMP_DONE_IND,
LOGGER_SET_HAL_START,
LOGGER_HAL_STOP,
- LOGGER_SET_HAL_PID
+ LOGGER_SET_HAL_PID,
+ LOGGER_SET_TPUT_DEBUG_DUMP_CMD,
+ LOGGER_GET_BUF_RING_MAP
} DEBUG_SUB_COMMAND;
+#define MAX_NV_FILE 4
+#define MAX_SKU_NAME_LEN 5
+#define OTA_PATH "/data/vendor/firmware/wifi/"
+#define OTA_CLM_FILE "bcmdhd_clm.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
+} OTA_TYPE;
+
+char ota_nvram_ext[10];
+typedef struct ota_info_buf {
+ u32 ota_clm_len;
+ const void *ota_clm_buf[1];
+ u32 ota_nvram_len;
+ const void *ota_nvram_buf[1];
+} ota_info_buf_t;
+u32 applied_ota_version = 0;
+
typedef enum {
- LOGGER_ATTRIBUTE_DRIVER_VER,
- LOGGER_ATTRIBUTE_FW_VER,
- LOGGER_ATTRIBUTE_RING_ID,
- LOGGER_ATTRIBUTE_RING_NAME,
- LOGGER_ATTRIBUTE_RING_FLAGS,
- LOGGER_ATTRIBUTE_LOG_LEVEL,
- LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
- LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
- LOGGER_ATTRIBUTE_FW_DUMP_LEN,
- LOGGER_ATTRIBUTE_FW_DUMP_DATA,
- LOGGER_ATTRIBUTE_FW_ERR_CODE,
- LOGGER_ATTRIBUTE_RING_DATA,
- LOGGER_ATTRIBUTE_RING_STATUS,
- LOGGER_ATTRIBUTE_RING_NUM,
- LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
- LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
- LOGGER_ATTRIBUTE_PKT_FATE_NUM,
- LOGGER_ATTRIBUTE_PKT_FATE_DATA,
+ LOGGER_ATTRIBUTE_INVALID = 0,
+ LOGGER_ATTRIBUTE_DRIVER_VER = 1,
+ LOGGER_ATTRIBUTE_FW_VER = 2,
+ LOGGER_ATTRIBUTE_RING_ID = 3,
+ LOGGER_ATTRIBUTE_RING_NAME = 4,
+ LOGGER_ATTRIBUTE_RING_FLAGS = 5,
+ LOGGER_ATTRIBUTE_LOG_LEVEL = 6,
+ LOGGER_ATTRIBUTE_LOG_TIME_INTVAL = 7,
+ LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE = 8,
+ LOGGER_ATTRIBUTE_FW_DUMP_LEN = 9,
+ LOGGER_ATTRIBUTE_FW_DUMP_DATA = 10,
+ LOGGER_ATTRIBUTE_FW_ERR_CODE = 11,
+ LOGGER_ATTRIBUTE_RING_DATA = 12,
+ LOGGER_ATTRIBUTE_RING_STATUS = 13,
+ LOGGER_ATTRIBUTE_RING_NUM = 14,
+ LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN = 15,
+ LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA = 16,
+ LOGGER_ATTRIBUTE_PKT_FATE_NUM = 17,
+ LOGGER_ATTRIBUTE_PKT_FATE_DATA = 18,
+ LOGGER_ATTRIBUTE_HANG_REASON = 19,
+ LOGGER_ATTRIBUTE_BUF_RING_NUM = 20,
+ LOGGER_ATTRIBUTE_BUF_RING_MAP = 21,
+ /* Add new attributes just above this */
+ LOGGER_ATTRIBUTE_MAX
} LOGGER_ATTRIBUTE;
typedef enum {
@@ -108,6 +141,7 @@ typedef enum {
GET_RING_STATUS,
GET_FEATURE,
START_RING_LOG,
+ GET_BUF_RING_MAP,
} GetCmdType;
typedef enum {
@@ -117,9 +151,10 @@ typedef enum {
} PktFateReqType;
enum wake_stat_attributes {
- WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
- WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
- WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
+ WAKE_STAT_ATTRIBUTE_INVALID,
+ WAKE_STAT_ATTRIBUTE_TOTAL,
+ WAKE_STAT_ATTRIBUTE_WAKE,
+ WAKE_STAT_ATTRIBUTE_COUNT,
WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
@@ -136,8 +171,9 @@ enum wake_stat_attributes {
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
- WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
- WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
+ WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
+ WAKE_STAT_ATTRIBUTE_MAX
};
typedef enum {
@@ -146,8 +182,362 @@ typedef enum {
SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
} SET_HAL_START_ATTRIBUTE;
+typedef enum {
+ OTA_DOWNLOAD_CLM_LENGTH_ATTR = 0x0001,
+ OTA_DOWNLOAD_CLM_ATTR = 0x0002,
+ OTA_DOWNLOAD_NVRAM_LENGTH_ATTR = 0x0003,
+ OTA_DOWNLOAD_NVRAM_ATTR = 0x0004,
+ OTA_SET_FORCE_REG_ON = 0x0005,
+ OTA_CUR_NVRAM_EXT_ATTR = 0x0006,
+} OTA_DOWNLOAD_ATTRIBUTE;
+
#define HAL_START_REQUEST_ID 2
+#define HAL_RESTART_ID 3
+#define FILE_NAME_LEN 256
+#define RING_NAME_LEN 32
+#if defined(RING_DUMP)
+/* Loglevel */
+#define DUMP_DEBUG(x)
+#define DUMP_INFO(x) ALOGI x
+#define FILE_DUMP_REQUEST_ID 2
+#define C2S(x) case x: return #x;
+static const char *EWP_EventAttrToString(int len_attr);
+static const char *EWP_CmdAttrToString(int data_attr);
+
+typedef struct buf_data {
+ u32 ver; /* version of struct */
+ u32 len; /* Total len */
+ /* size of each buffer in case of split buffers (0 - single buffer). */
+ u32 buf_threshold;
+ const void *data_buf[1]; /* array of user space buffer pointers.*/
+} buf_data_t;
+
+/* Attributes associated with GOOGLE_FILE_DUMP_EVENT */
+typedef enum {
+ DUMP_LEN_ATTR_INVALID = 0,
+ DUMP_LEN_ATTR_MEMDUMP = 1,
+ DUMP_LEN_ATTR_SSSR_C0_BEFORE = 2,
+ DUMP_LEN_ATTR_SSSR_C0_AFTER = 3,
+ DUMP_LEN_ATTR_SSSR_C1_BEFORE = 4,
+ DUMP_LEN_ATTR_SSSR_C1_AFTER = 5,
+ DUMP_LEN_ATTR_SSSR_C2_BEFORE = 6,
+ DUMP_LEN_ATTR_SSSR_C2_AFTER = 7,
+ DUMP_LEN_ATTR_SSSR_DIG_BEFORE = 8,
+ DUMP_LEN_ATTR_SSSR_DIG_AFTER = 9,
+ DUMP_LEN_ATTR_TIMESTAMP = 10,
+ DUMP_LEN_ATTR_GENERAL_LOG = 11,
+ DUMP_LEN_ATTR_ECNTRS = 12,
+ DUMP_LEN_ATTR_SPECIAL_LOG = 13,
+ DUMP_LEN_ATTR_DHD_DUMP = 14,
+ DUMP_LEN_ATTR_EXT_TRAP = 15,
+ DUMP_LEN_ATTR_HEALTH_CHK = 16,
+ DUMP_LEN_ATTR_PRESERVE_LOG = 17,
+ DUMP_LEN_ATTR_COOKIE = 18,
+ DUMP_LEN_ATTR_FLOWRING_DUMP = 19,
+ DUMP_LEN_ATTR_PKTLOG = 20,
+ DUMP_LEN_ATTR_PKTLOG_DEBUG = 21,
+ DUMP_FILENAME_ATTR_DEBUG_DUMP = 22,
+ DUMP_FILENAME_ATTR_MEM_DUMP = 23,
+ DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP = 24,
+ DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP = 25,
+ DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP = 26,
+ DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP = 27,
+ DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP = 28,
+ DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP = 29,
+ DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP = 30,
+ DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP = 31,
+ DUMP_FILENAME_ATTR_PKTLOG_DUMP = 32,
+ DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP = 33,
+ DUMP_LEN_ATTR_STATUS_LOG = 34,
+ DUMP_LEN_ATTR_AXI_ERROR = 35,
+ DUMP_FILENAME_ATTR_AXI_ERROR_DUMP = 36,
+ DUMP_LEN_ATTR_RTT_LOG = 37,
+ DUMP_LEN_ATTR_SDTC_ETB_DUMP = 38,
+ DUMP_FILENAME_ATTR_SDTC_ETB_DUMP = 39,
+ DUMP_LEN_ATTR_PKTID_MAP_LOG = 40,
+ DUMP_LEN_ATTR_PKTID_UNMAP_LOG = 41,
+ DUMP_LEN_ATTR_EWP_HW_INIT_LOG = 42,
+ DUMP_LEN_ATTR_EWP_HW_MOD_DUMP = 43,
+ DUMP_LEN_ATTR_EWP_HW_REG_DUMP = 44,
+ /* Please add new attributes from here to sync up old DHD */
+ DUMP_EVENT_ATTR_MAX = 45,
+} EWP_DUMP_EVENT_ATTRIBUTE;
+
+/* Attributes associated with DEBUG_GET_DUMP_BUF */
+typedef enum {
+ DUMP_BUF_ATTR_INVALID = 0,
+ DUMP_BUF_ATTR_MEMDUMP = 1,
+ DUMP_BUF_ATTR_SSSR_C0_BEFORE = 2,
+ DUMP_BUF_ATTR_SSSR_C0_AFTER = 3,
+ DUMP_BUF_ATTR_SSSR_C1_BEFORE = 4,
+ DUMP_BUF_ATTR_SSSR_C1_AFTER = 5,
+ DUMP_BUF_ATTR_SSSR_C2_BEFORE = 6,
+ DUMP_BUF_ATTR_SSSR_C2_AFTER = 7,
+ DUMP_BUF_ATTR_SSSR_DIG_BEFORE = 8,
+ DUMP_BUF_ATTR_SSSR_DIG_AFTER = 9,
+ DUMP_BUF_ATTR_TIMESTAMP = 10,
+ DUMP_BUF_ATTR_GENERAL_LOG = 11,
+ DUMP_BUF_ATTR_ECNTRS = 12,
+ DUMP_BUF_ATTR_SPECIAL_LOG = 13,
+ DUMP_BUF_ATTR_DHD_DUMP = 14,
+ DUMP_BUF_ATTR_EXT_TRAP = 15,
+ DUMP_BUF_ATTR_HEALTH_CHK = 16,
+ DUMP_BUF_ATTR_PRESERVE_LOG = 17,
+ DUMP_BUF_ATTR_COOKIE = 18,
+ DUMP_BUF_ATTR_FLOWRING_DUMP = 19,
+ DUMP_BUF_ATTR_PKTLOG = 20,
+ DUMP_BUF_ATTR_PKTLOG_DEBUG = 21,
+ DUMP_BUF_ATTR_STATUS_LOG = 22,
+ DUMP_BUF_ATTR_AXI_ERROR = 23,
+ DUMP_BUF_ATTR_RTT_LOG = 24,
+ DUMP_BUF_ATTR_SDTC_ETB_DUMP = 25,
+ DUMP_BUF_ATTR_PKTID_MAP_LOG = 26,
+ DUMP_BUF_ATTR_PKTID_UNMAP_LOG = 27,
+ DUMP_BUF_ATTR_EWP_HW_INIT_LOG = 28,
+ DUMP_BUF_ATTR_EWP_HW_MOD_DUMP = 29,
+ DUMP_BUF_ATTR_EWP_HW_REG_DUMP = 30,
+ /* Please add new attributes from here to sync up old DHD */
+ DUMP_BUF_ATTR_MAX = 31,
+} EWP_DUMP_CMD_ATTRIBUTE;
+
+typedef enum {
+ DUMP_TYPE_MEM_DUMP = 0,
+ DUMP_TYPE_DEBUG_DUMP = 1,
+ DUMP_TYPE_SSSR_CORE0_BEF_DUMP = 2,
+ DUMP_TYPE_SSSR_CORE0_AFT_DUMP = 3,
+ DUMP_TYPE_SSSR_CORE1_BEF_DUMP = 4,
+ DUMP_TYPE_SSSR_CORE1_AFT_DUMP = 5,
+ DUMP_TYPE_SSSR_CORE2_BEF_DUMP = 6,
+ DUMP_TYPE_SSSR_CORE2_AFT_DUMP = 7,
+ DUMP_TYPE_SSSR_DIG_BEF_DUMP = 8,
+ DUMP_TYPE_SSSR_DIG_AFT_DUMP = 9,
+ DUMP_TYPE_PKTLOG_DUMP = 10,
+ DUMP_TYPE_PKTLOG_DEBUG_DUMP = 11,
+ DUMP_TYPE_AXI_ERROR_DUMP = 12,
+ DUMP_TYPE_D2H_MINI_DUMP = 13,
+ DUMP_TYPE_SDTC_ETB_DUMP = 14,
+ /* Please add new attributes from here to sync up old DHD */
+ DUMP_TYPE_MAX = 15,
+} EWP_DUMP_TYPE;
+
+/* Struct for table which has len_attr, data_attr and dump file type attr */
+typedef struct logger_attr_entry {
+ u8 attr_type; /* Type of attribute */
+ u8 buf_attr; /* Buffer associated with the attribute */
+ u8 dump_type; /* Each attribute will be linked to a dump type */
+} logger_attr_entry_t;
+
+logger_attr_entry_t attr_lookup_tbl[] = {
+ /* Mem Dump Block */
+ {DUMP_FILENAME_ATTR_MEM_DUMP, 0, DUMP_TYPE_MEM_DUMP},
+ {DUMP_LEN_ATTR_MEMDUMP, DUMP_BUF_ATTR_MEMDUMP, DUMP_TYPE_MEM_DUMP},
+ /* SSSR Dump Block */
+ {DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE0_BEF_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C0_BEFORE, DUMP_BUF_ATTR_SSSR_C0_BEFORE, DUMP_TYPE_SSSR_CORE0_BEF_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE0_AFT_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C0_AFTER, DUMP_BUF_ATTR_SSSR_C0_AFTER, DUMP_TYPE_SSSR_CORE0_AFT_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE1_BEF_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C1_BEFORE, DUMP_BUF_ATTR_SSSR_C1_BEFORE, DUMP_TYPE_SSSR_CORE1_BEF_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE1_AFT_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C1_AFTER, DUMP_BUF_ATTR_SSSR_C1_AFTER, DUMP_TYPE_SSSR_CORE1_AFT_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE2_BEF_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C2_BEFORE, DUMP_BUF_ATTR_SSSR_C2_BEFORE, DUMP_TYPE_SSSR_CORE2_BEF_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE2_AFT_DUMP},
+ {DUMP_LEN_ATTR_SSSR_C2_AFTER, DUMP_BUF_ATTR_SSSR_C2_AFTER, DUMP_TYPE_SSSR_CORE2_AFT_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_DIG_BEF_DUMP},
+ {DUMP_LEN_ATTR_SSSR_DIG_BEFORE, DUMP_BUF_ATTR_SSSR_DIG_BEFORE, DUMP_TYPE_SSSR_DIG_BEF_DUMP},
+
+ {DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP, 0, DUMP_TYPE_SSSR_DIG_AFT_DUMP},
+ {DUMP_LEN_ATTR_SSSR_DIG_AFTER, DUMP_BUF_ATTR_SSSR_DIG_AFTER, DUMP_TYPE_SSSR_DIG_AFT_DUMP},
+
+ /* Debug Dump Block */
+ {DUMP_FILENAME_ATTR_DEBUG_DUMP, 0, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_TIMESTAMP, DUMP_BUF_ATTR_TIMESTAMP, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_GENERAL_LOG, DUMP_BUF_ATTR_GENERAL_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_ECNTRS, DUMP_BUF_ATTR_ECNTRS, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_SPECIAL_LOG, DUMP_BUF_ATTR_SPECIAL_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_DHD_DUMP, DUMP_BUF_ATTR_DHD_DUMP, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_EXT_TRAP, DUMP_BUF_ATTR_EXT_TRAP, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_HEALTH_CHK, DUMP_BUF_ATTR_HEALTH_CHK, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_PRESERVE_LOG, DUMP_BUF_ATTR_PRESERVE_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_COOKIE, DUMP_BUF_ATTR_COOKIE, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_FLOWRING_DUMP, DUMP_BUF_ATTR_FLOWRING_DUMP, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_STATUS_LOG, DUMP_BUF_ATTR_STATUS_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_RTT_LOG, DUMP_BUF_ATTR_RTT_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_PKTID_MAP_LOG, DUMP_BUF_ATTR_PKTID_MAP_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_PKTID_UNMAP_LOG, DUMP_BUF_ATTR_PKTID_UNMAP_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_EWP_HW_INIT_LOG, DUMP_BUF_ATTR_EWP_HW_INIT_LOG, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_EWP_HW_MOD_DUMP, DUMP_BUF_ATTR_EWP_HW_MOD_DUMP, DUMP_TYPE_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_EWP_HW_REG_DUMP, DUMP_BUF_ATTR_EWP_HW_REG_DUMP, DUMP_TYPE_DEBUG_DUMP},
+
+ /* PKT log dump block */
+ {DUMP_FILENAME_ATTR_PKTLOG_DUMP, 0, DUMP_TYPE_PKTLOG_DUMP},
+ {DUMP_LEN_ATTR_PKTLOG, DUMP_BUF_ATTR_PKTLOG, DUMP_TYPE_PKTLOG_DUMP},
+ {DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP, 0, DUMP_TYPE_PKTLOG_DEBUG_DUMP},
+ {DUMP_LEN_ATTR_PKTLOG_DEBUG, DUMP_BUF_ATTR_PKTLOG_DEBUG, DUMP_TYPE_PKTLOG_DEBUG_DUMP},
+ /* AXI error log dump block */
+ {DUMP_FILENAME_ATTR_AXI_ERROR_DUMP, 0, DUMP_TYPE_AXI_ERROR_DUMP},
+ {DUMP_LEN_ATTR_AXI_ERROR, DUMP_BUF_ATTR_AXI_ERROR, DUMP_TYPE_AXI_ERROR_DUMP},
+ /* SDTC etb log dump block */
+ {DUMP_FILENAME_ATTR_SDTC_ETB_DUMP, 0, DUMP_TYPE_SDTC_ETB_DUMP},
+ {DUMP_LEN_ATTR_SDTC_ETB_DUMP, DUMP_BUF_ATTR_SDTC_ETB_DUMP, DUMP_TYPE_SDTC_ETB_DUMP},
+ {DUMP_EVENT_ATTR_MAX, 0, 0},
+};
+
+static const char *EWP_EventAttrToString(int len_attr)
+{
+ switch (len_attr) {
+ C2S(DUMP_LEN_ATTR_MEMDUMP)
+ C2S(DUMP_LEN_ATTR_SSSR_C0_BEFORE)
+ C2S(DUMP_LEN_ATTR_SSSR_C0_AFTER)
+ C2S(DUMP_LEN_ATTR_SSSR_C1_BEFORE)
+ C2S(DUMP_LEN_ATTR_SSSR_C1_AFTER)
+ C2S(DUMP_LEN_ATTR_SSSR_C2_BEFORE)
+ C2S(DUMP_LEN_ATTR_SSSR_C2_AFTER)
+ C2S(DUMP_LEN_ATTR_SSSR_DIG_BEFORE)
+ C2S(DUMP_LEN_ATTR_SSSR_DIG_AFTER)
+ C2S(DUMP_LEN_ATTR_TIMESTAMP)
+ C2S(DUMP_LEN_ATTR_GENERAL_LOG)
+ C2S(DUMP_LEN_ATTR_ECNTRS)
+ C2S(DUMP_LEN_ATTR_SPECIAL_LOG)
+ C2S(DUMP_LEN_ATTR_DHD_DUMP)
+ C2S(DUMP_LEN_ATTR_EXT_TRAP)
+ C2S(DUMP_LEN_ATTR_HEALTH_CHK)
+ C2S(DUMP_LEN_ATTR_PRESERVE_LOG)
+ C2S(DUMP_LEN_ATTR_COOKIE)
+ C2S(DUMP_LEN_ATTR_FLOWRING_DUMP)
+ C2S(DUMP_LEN_ATTR_PKTLOG)
+ C2S(DUMP_LEN_ATTR_PKTLOG_DEBUG)
+ C2S(DUMP_LEN_ATTR_STATUS_LOG)
+ C2S(DUMP_FILENAME_ATTR_DEBUG_DUMP)
+ C2S(DUMP_FILENAME_ATTR_MEM_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP)
+ C2S(DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP)
+ C2S(DUMP_FILENAME_ATTR_PKTLOG_DUMP)
+ C2S(DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP)
+ C2S(DUMP_LEN_ATTR_AXI_ERROR)
+ C2S(DUMP_FILENAME_ATTR_AXI_ERROR_DUMP)
+ C2S(DUMP_LEN_ATTR_RTT_LOG)
+ C2S(DUMP_FILENAME_ATTR_SDTC_ETB_DUMP)
+ C2S(DUMP_LEN_ATTR_SDTC_ETB_DUMP)
+ C2S(DUMP_LEN_ATTR_PKTID_MAP_LOG)
+ C2S(DUMP_LEN_ATTR_PKTID_UNMAP_LOG)
+ C2S(DUMP_LEN_ATTR_EWP_HW_INIT_LOG)
+ C2S(DUMP_LEN_ATTR_EWP_HW_MOD_DUMP)
+ C2S(DUMP_LEN_ATTR_EWP_HW_REG_DUMP)
+ default:
+ return "DUMP_LEN_ATTR_INVALID";
+ }
+}
+static const char *EWP_CmdAttrToString(int attr)
+{
+ switch (attr) {
+ C2S(DUMP_BUF_ATTR_MEMDUMP)
+ C2S(DUMP_BUF_ATTR_SSSR_C0_BEFORE)
+ C2S(DUMP_BUF_ATTR_SSSR_C0_AFTER)
+ C2S(DUMP_BUF_ATTR_SSSR_C1_BEFORE)
+ C2S(DUMP_BUF_ATTR_SSSR_C1_AFTER)
+ C2S(DUMP_BUF_ATTR_SSSR_C2_BEFORE)
+ C2S(DUMP_BUF_ATTR_SSSR_C2_AFTER)
+ C2S(DUMP_BUF_ATTR_SSSR_DIG_BEFORE)
+ C2S(DUMP_BUF_ATTR_SSSR_DIG_AFTER)
+ C2S(DUMP_BUF_ATTR_TIMESTAMP)
+ C2S(DUMP_BUF_ATTR_GENERAL_LOG)
+ C2S(DUMP_BUF_ATTR_ECNTRS)
+ C2S(DUMP_BUF_ATTR_SPECIAL_LOG)
+ C2S(DUMP_BUF_ATTR_DHD_DUMP)
+ C2S(DUMP_BUF_ATTR_EXT_TRAP)
+ C2S(DUMP_BUF_ATTR_HEALTH_CHK)
+ C2S(DUMP_BUF_ATTR_PRESERVE_LOG)
+ C2S(DUMP_BUF_ATTR_COOKIE)
+ C2S(DUMP_BUF_ATTR_FLOWRING_DUMP)
+ C2S(DUMP_BUF_ATTR_PKTLOG)
+ C2S(DUMP_BUF_ATTR_PKTLOG_DEBUG)
+ C2S(DUMP_BUF_ATTR_STATUS_LOG)
+ C2S(DUMP_BUF_ATTR_AXI_ERROR)
+ C2S(DUMP_BUF_ATTR_RTT_LOG)
+ C2S(DUMP_BUF_ATTR_SDTC_ETB_DUMP)
+ C2S(DUMP_BUF_ATTR_PKTID_MAP_LOG)
+ C2S(DUMP_BUF_ATTR_PKTID_UNMAP_LOG)
+ C2S(DUMP_BUF_ATTR_EWP_HW_INIT_LOG)
+ C2S(DUMP_BUF_ATTR_EWP_HW_MOD_DUMP)
+ C2S(DUMP_BUF_ATTR_EWP_HW_REG_DUMP)
+ default:
+ return "DUMP_BUF_ATTR_INVALID";
+ }
+}
+
+/* Return index for matching buffer attribute */
+static int logger_attr_buffer_lookup(u8 attr) {
+ for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) {
+ if (attr == attr_lookup_tbl[i].buf_attr) {
+ return i;
+ }
+ }
+ ALOGE("Lookup for buf attr = %s failed\n",
+ EWP_CmdAttrToString(attr));
+ return -1;
+}
+
+/* Return index matching the length attribute */
+static int logger_attr_lookup(u8 attr) {
+ for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) {
+ if (attr == attr_lookup_tbl[i].attr_type) {
+ return i;
+ }
+ }
+ ALOGE("Lookup for len attr = %s failed\n",
+ EWP_EventAttrToString(attr));
+ return -1;
+}
+#endif /* RING_DUMP */
+
+#define DBGRING_NAME_MAX 32 //Copy from legacy hal
+typedef struct wifi_buf_ring_map_entry {
+ uint32_t type;
+ uint32_t ring_id;
+ char ring_name[DBGRING_NAME_MAX];
+} wifi_buf_ring_map_entry_t;
+
+typedef struct {
+ char hw_id[PROPERTY_VALUE_MAX];
+ char sku[MAX_SKU_NAME_LEN];
+} sku_info_t;
+
+sku_info_t sku_table[] = {
+ { {"G9S9B"}, {"MMW"} },
+ { {"G8V0U"}, {"MMW"} },
+ { {"GFQM1"}, {"MMW"} },
+ { {"GB62Z"}, {"MMW"} },
+ { {"GE2AE"}, {"MMW"} },
+ { {"GQML3"}, {"MMW"} },
+ { {"GB7N6"}, {"ROW"} },
+ { {"GLU0G"}, {"ROW"} },
+ { {"GNA8F"}, {"ROW"} },
+ { {"GX7AS"}, {"ROW"} },
+ { {"GP4BC"}, {"ROW"} },
+ { {"GVU6C"}, {"ROW"} },
+ { {"GR1YH"}, {"JPN"} },
+ { {"GF5KQ"}, {"JPN"} },
+ { {"GPQ72"}, {"JPN"} },
+ { {"GB17L"}, {"JPN"} },
+ { {"GFE4J"}, {"JPN"} },
+ { {"G03Z5"}, {"JPN"} },
+ { {"G1AZG"}, {"EU"} }
+};
///////////////////////////////////////////////////////////////////////////////
class DebugCommand : public WifiCommand
{
@@ -155,6 +545,8 @@ class DebugCommand : public WifiCommand
int *mBuffSize;
u32 *mNumRings;
wifi_ring_buffer_status *mStatus;
+ u32 *mNumMaps;
+ wifi_buf_ring_map_entry_t *mMaps;
unsigned int *mSupport;
u32 mVerboseLevel;
u32 mFlags;
@@ -228,6 +620,14 @@ public:
mRingName = NULL;
}
+ // constructor for buf ring map
+ DebugCommand(wifi_interface_handle iface, u32 *num_maps,
+ wifi_buf_ring_map_entry_t *map, GetCmdType cmdType)
+ : WifiCommand("DebugCommand", iface, 0), mNumMaps(num_maps), mMaps(map), mType(cmdType)
+ {
+ memset(mMaps, 0, sizeof(wifi_buf_ring_map_entry_t) * (*mNumMaps));
+ }
+
// constructor for ring params
DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
@@ -366,6 +766,16 @@ public:
break;
}
+ case GET_BUF_RING_MAP:
+ {
+ result = request.create(GOOGLE_OUI, LOGGER_GET_BUF_RING_MAP);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to create get ring status request; result = %d", result);
+ return result;
+ }
+ break;
+ }
+
case START_RING_LOG:
result = createRingRequest(request);
break;
@@ -378,7 +788,7 @@ public:
}
int start() {
- // ALOGD("Start debug command");
+ ALOGD("Start debug command");
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request);
if (result != WIFI_SUCCESS) {
@@ -394,7 +804,7 @@ public:
}
virtual int handleResponse(WifiEvent& reply) {
- ALOGD("In DebugCommand::handleResponse");
+ ALOGD("In DebugCommand::handleResponse, mType:%d\n", mType);
if (reply.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
@@ -449,9 +859,15 @@ public:
it.next();
for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
- memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
- i++;
- status++;
+ if (it.get_len() > sizeof(wifi_ring_buffer_status)) {
+ ALOGE("ring status unexpected len = %d, dest len = %lu",
+ it.get_len(), sizeof(wifi_ring_buffer_status));
+ return NL_SKIP;
+ } else {
+ memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
+ i++;
+ status++;
+ }
} else {
ALOGW("Ignoring invalid attribute type = %d, size = %d",
it.get_type(), it.get_len());
@@ -465,11 +881,57 @@ public:
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
- ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
+ ALOGD("len = %d, expected len = %lu", len, sizeof(unsigned int));
memcpy(mSupport, data, sizeof(unsigned int));
break;
}
+ case GET_BUF_RING_MAP:
+ {
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+ wifi_buf_ring_map_entry_t *map(mMaps);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+
+ nl_iterator it(vendor_data);
+ if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_NUM) {
+ unsigned int num_maps = it.get_u32();
+ if (*mNumMaps < num_maps) {
+ ALOGE("Not enough status buffers provided, available: %d required: %d",
+ *mNumMaps, num_maps);
+ } else {
+ *mNumMaps = num_maps;
+ }
+ } else {
+ ALOGE("Unknown attribute: %d expecting %d",
+ it.get_type(), LOGGER_ATTRIBUTE_BUF_RING_NUM);
+ return NL_SKIP;
+ }
+
+ it.next();
+ for (unsigned int i = 0; it.has_next() && i < *mNumMaps; it.next()) {
+ if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_MAP) {
+ if (it.get_len() > sizeof(wifi_buf_ring_map_entry_t)) {
+ ALOGE("GET_BUF_RING_MAP: unexpected len = %d, dest len = %lu",
+ it.get_len(), sizeof(wifi_buf_ring_map_entry_t));
+ return NL_SKIP;
+ } else {
+ memcpy(map, it.get_data(), sizeof(wifi_buf_ring_map_entry_t));
+ }
+ i++;
+ map++;
+ } else {
+ ALOGW("Ignoring invalid attribute type = %d, size = %d",
+ it.get_type(), it.get_len());
+ }
+ }
+ break;
+ }
+
default:
ALOGW("Unknown Debug command");
}
@@ -559,6 +1021,8 @@ wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
{
if (ring_name) {
+ ALOGE("Ring name: level:%d sec:%d ring_name:%s",
+ verbose_level, max_interval_sec, ring_name);
DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
min_data_size, ring_name, START_RING_LOG);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -586,7 +1050,6 @@ public:
ALOGV("Register loghandler");
int result;
uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
- registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
WifiRequest request(familyId(), ifaceId());
@@ -596,14 +1059,18 @@ public:
ALOGV("Failed to set Hal preInit; result = %d", result);
return result;
}
+ registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
+
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
ALOGV("Hal preInit Failed to put pic = %d", result);
return result;
}
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
ALOGV("Hal preInit Failed to put pid= %d", result);
return result;
}
@@ -612,6 +1079,7 @@ public:
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
ALOGE("Failed to register set Hal preInit; result = %d", result);
return result;
}
@@ -624,6 +1092,7 @@ public:
/* unregister event handler */
unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
+ wifi_unregister_cmd(wifiHandle(), id());
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
@@ -657,16 +1126,23 @@ public:
return NL_SKIP;
}
- if(event_id == GOOGLE_DEBUG_RING_EVENT) {
+ if (event_id == GOOGLE_DEBUG_RING_EVENT) {
wifi_ring_buffer_status status;
memset(&status, 0, sizeof(status));
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
- memcpy(&status, it.get_data(), sizeof(status));
+ if (it.get_len() > sizeof(wifi_ring_buffer_status)) {
+ ALOGE("SetLogHandler: ring status unexpected len = %d, dest len = %lu",
+ it.get_len(), sizeof(wifi_ring_buffer_status));
+ return NL_SKIP;
+ } else {
+ memcpy(&status, it.get_data(), sizeof(wifi_ring_buffer_status));
+ }
} else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
buffer_size = it.get_len();
buffer = (char *)it.get_data();
+ ALOGV("SetLogHandler: ring data size = %d", buffer_size);
} else {
ALOGW("Ignoring invalid attribute type = %d, size = %d",
it.get_type(), it.get_len());
@@ -695,7 +1171,7 @@ wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
wifi_ring_buffer_data_handler handler)
{
wifi_handle handle = getWifiHandle(iface);
- ALOGV("Loghandler start, handle = %p", handle);
+ ALOGE("Loghandler start, handle = %p", handle);
SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -710,13 +1186,17 @@ wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
cmd->releaseRef();
return result;
}
+
+#ifdef RING_DUMP
+ wifi_start_ring_dump(iface, handler);
+#endif /* RING_DUMP */
return result;
}
wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
{
wifi_handle handle = getWifiHandle(iface);
- ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
+ ALOGE("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
if (id == -1) {
wifi_ring_buffer_data_handler handler;
@@ -726,10 +1206,14 @@ wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle ifac
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
cmd->cancel();
cmd->releaseRef();
+
+#ifdef RING_DUMP
+ wifi_stop_ring_dump(iface, handler);
+#endif /* RING_DUMP */
return WIFI_SUCCESS;
}
- return wifi_cancel_cmd(id, iface);
+ return wifi_get_cancel_cmd(id, iface);
}
///////////////////////////////////////////////////////////////////////////////
@@ -795,7 +1279,6 @@ public:
}
virtual int handleEvent(WifiEvent& event) {
- wifi_ring_buffer_id ring_id;
char *buffer = NULL;
int buffer_size = 0;
bool is_err_alert = false;
@@ -827,7 +1310,7 @@ public:
}
}
- if(is_err_alert) {
+ if (is_err_alert) {
mBuffSize = sizeof(mErrCode);
if (mBuff) free(mBuff);
mBuff = (char *)malloc(mBuffSize);
@@ -896,6 +1379,114 @@ public:
}
};
+class SetRestartHandler : public WifiCommand
+{
+ wifi_subsystem_restart_handler mHandler;
+ char *mBuff;
+public:
+ SetRestartHandler(wifi_handle handle, wifi_request_id id, wifi_subsystem_restart_handler handler)
+ : WifiCommand("SetRestartHandler", handle, id), mHandler(handler), mBuff(NULL)
+ { }
+ int start() {
+ ALOGI("Start Restart Handler handler");
+ registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
+ return WIFI_SUCCESS;
+ }
+ virtual int cancel() {
+ ALOGI("Clear Restart Handler");
+
+ /* unregister alert handler */
+ unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
+ wifi_unregister_cmd(wifiHandle(), id());
+ ALOGI("Success to clear restarthandler");
+ return WIFI_SUCCESS;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+ ALOGI("Got event: %d", event_id);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+ if (event_id == BRCM_VENDOR_EVENT_HANGED) {
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ if (it.get_type() == LOGGER_ATTRIBUTE_HANG_REASON) {
+ mBuff = (char *)it.get_data();
+ } else {
+ ALOGI("Ignoring invalid attribute type = %d, size = %d",
+ it.get_type(), it.get_len());
+ }
+ }
+
+ if (*mHandler.on_subsystem_restart) {
+ (*mHandler.on_subsystem_restart)(mBuff);
+ ALOGI("Hang event received. Trigger SSR handler:%p",
+ mHandler.on_subsystem_restart);
+ } else {
+ ALOGI("No Restart handler registered");
+ }
+ }
+ return NL_OK;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+class SubSystemRestart : public WifiCommand
+{
+ public:
+ SubSystemRestart(wifi_interface_handle iface)
+ : WifiCommand("SubSystemRestart", iface, 0)
+ { }
+
+ int createRequest(WifiRequest& request) {
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_TRIGGER_SSR);
+ if (result < 0) {
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ request.attr_end(data);
+ return WIFI_SUCCESS;
+ }
+
+ int create() {
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = createRequest(request);
+ if (result < 0) {
+ ALOGE("Failed to create ssr request result = %d\n", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register ssr response; result = %d\n", result);
+ }
+ return result;
+ }
+
+ protected:
+ int handleResponse(WifiEvent& reply) {
+ /* Nothing to do on response! */
+ return NL_OK;
+ }
+
+ int handleEvent(WifiEvent& event) {
+ /* NO events to handle here! */
+ return NL_SKIP;
+ }
+
+};
///////////////////////////////////////////////////////////////////////////////
class HalInit : public WifiCommand
{
@@ -939,6 +1530,7 @@ class HalInit : public WifiCommand
ALOGE("Failed to register set hal start response; result = %d", result);
}
wifi_unregister_cmd(wifiHandle(), id());
+ ALOGV("Stop HAL Successfully Completed, mErrCode = %d\n", mErrCode);
return result;
}
@@ -983,6 +1575,338 @@ class HalInit : public WifiCommand
}
};
+#ifdef RING_DUMP
+///////////////////////////////////////////////////////////////////////////////
+class RingDump : public WifiCommand
+{
+ int mLargestBuffSize;
+ char *mBuff;
+ int mErrCode;
+ int mNumMaps;
+ wifi_buf_ring_map_entry_t *mMap;
+ int attr_type_len[DUMP_EVENT_ATTR_MAX];
+ char *ring_name[DUMP_BUF_ATTR_MAX];
+ wifi_ring_buffer_data_handler mHandle;
+
+public:
+ RingDump(wifi_interface_handle iface, int id, int num_maps, wifi_buf_ring_map_entry_t *map,
+ wifi_ring_buffer_data_handler ring_handle)
+ : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL),
+ mErrCode(0), mNumMaps(num_maps), mMap(map), mHandle(ring_handle)
+ {
+ memset(attr_type_len, 0, sizeof(attr_type_len));
+ for (int i = 0; i < DUMP_BUF_ATTR_MAX; i++) {
+ ring_name[i] = NULL;
+ }
+ }
+ RingDump(wifi_interface_handle iface, int id)
+ : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL),
+ mErrCode(0)
+ {
+ }
+
+ int start() {
+ DUMP_INFO(("Start Ring Dump Map_cnt:%d\n", mNumMaps));
+ registerVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT);
+
+ //Set ringname to buf hashmap
+ for (int i = 0; i < mNumMaps; i++) {
+ int type = mMap[i].type;
+ ring_name[type] = (char *)malloc(DBGRING_NAME_MAX);
+ memset(ring_name[type], 0, DBGRING_NAME_MAX);
+ memcpy(ring_name[type], mMap[i].ring_name, strlen(mMap[i].ring_name));
+ DUMP_DEBUG(("Set ringname Buf:%s Ringname:%s len:%lu",
+ EWP_CmdAttrToString(type), ring_name[type], strlen(mMap[i].ring_name)));
+ }
+ return WIFI_SUCCESS;
+ }
+
+ virtual int freeup() {
+ DUMP_DEBUG(("freeup:Enter\n"));
+ if (mBuff) {
+ free(mBuff);
+ mBuff = NULL;
+ DUMP_INFO(("freed allocated memory\n"));
+ }
+ return WIFI_SUCCESS;
+ }
+
+ virtual int cancel() {
+ /* unregister file dump handler */
+ unregisterVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT);
+ wifi_unregister_cmd(wifiHandle(), id());
+
+ /* Free up the ring names allocated */
+ for (u8 i = 0; i < DUMP_BUF_ATTR_MAX; i++) {
+ if (ring_name[i]) {
+ free(ring_name[i]);
+ ring_name[i] = NULL;
+ }
+ }
+ if (mBuff) {
+ free(mBuff);
+ }
+
+ DUMP_INFO(("Stop Ring Dump Successfully Completed, mErrCode = %d\n", mErrCode));
+ return WIFI_SUCCESS;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ DUMP_DEBUG(("RingDump::handleResponse\n"));
+ int buf_attr = DUMP_BUF_ATTR_INVALID;
+ int len_attr = DUMP_LEN_ATTR_INVALID;
+ int index = -1;
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in memory dump response; ignoring it");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ buf_attr = it.get_type();
+ switch (buf_attr) {
+ case DUMP_BUF_ATTR_MEMDUMP:
+ case DUMP_BUF_ATTR_TIMESTAMP:
+ case DUMP_BUF_ATTR_ECNTRS:
+ case DUMP_BUF_ATTR_DHD_DUMP:
+ case DUMP_BUF_ATTR_EXT_TRAP:
+ case DUMP_BUF_ATTR_HEALTH_CHK:
+ case DUMP_BUF_ATTR_COOKIE:
+ case DUMP_BUF_ATTR_FLOWRING_DUMP:
+ case DUMP_BUF_ATTR_STATUS_LOG:
+ case DUMP_BUF_ATTR_RTT_LOG:
+ case DUMP_BUF_ATTR_PKTID_MAP_LOG:
+ case DUMP_BUF_ATTR_PKTID_UNMAP_LOG: {
+ if (it.get_u32()) {
+ ALOGE("Copying data to userspace failed, status = %d\n", it.get_u32());
+ return WIFI_ERROR_UNKNOWN;
+ }
+ index = logger_attr_buffer_lookup(buf_attr);
+ if (index == -1) {
+ ALOGE("Invalid index. buf attr = %s\n", EWP_CmdAttrToString(buf_attr));
+ return WIFI_ERROR_UNKNOWN;
+ }
+ len_attr = attr_lookup_tbl[index].attr_type;
+ if (len_attr == DUMP_EVENT_ATTR_MAX) {
+ ALOGE("Invalid len attr = %s\n", EWP_EventAttrToString(len_attr));
+ return WIFI_ERROR_UNKNOWN;
+ }
+ if (!mBuff || attr_type_len[len_attr] <= 0) {
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ if (!ring_name[buf_attr]) {
+ ALOGE("Not allocated buf attr = %s\n", EWP_CmdAttrToString(buf_attr));
+ return WIFI_ERROR_UNKNOWN;
+ }
+ DUMP_INFO(("RingDump:: buf_attr:%s size = %d ring_name:%s\n",
+ EWP_CmdAttrToString(buf_attr), attr_type_len[len_attr],
+ ring_name[buf_attr]));
+ if (mHandle.on_ring_buffer_data) {
+ /* on_ring_buffer_data callback requires status memory
+ * so should pass status memory */
+ wifi_ring_buffer_status status;
+ memset(&status, 0, sizeof(status));
+ /* Skip msg header. Retrieved log */
+ (*mHandle.on_ring_buffer_data)(ring_name[buf_attr], mBuff,
+ attr_type_len[len_attr], &status);
+ }
+ if (mBuff) {
+ memset(mBuff, 0, mLargestBuffSize);
+ }
+ break;
+ }
+ default: {
+ DUMP_DEBUG(("Ignoring invalid attribute buf_attr = %d, size = %d",
+ buf_attr, it.get_len()));
+ break;
+ }
+ }
+ }
+ return NL_OK;
+ }
+
+ virtual int request_logger_dump(WifiRequest& request,
+ buf_data_t *buf, int len_attr) {
+
+ int result = 0;
+ int buf_attr = DUMP_BUF_ATTR_INVALID;
+ int index = -1;
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ index = logger_attr_lookup(len_attr);
+ if (index == -1) {
+ ALOGE("Invalid index\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+ buf_attr = attr_lookup_tbl[index].buf_attr;
+
+ if (buf_attr != DUMP_BUF_ATTR_INVALID) {
+ result = request.put(buf_attr, buf, sizeof(buf_data_t));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to put get memory dump request; result = %d", result);
+ return result;
+ }
+ } else {
+ ALOGE("Invalid buf attr = %s, index = %d\n",
+ EWP_CmdAttrToString(buf_attr), index);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ DUMP_INFO(("Trigger get dump for buf attr = %s\n",
+ EWP_CmdAttrToString(buf_attr)));
+
+ request.attr_end(data);
+ return result;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ mLargestBuffSize = 0;
+ mBuff = NULL;
+ memset(attr_type_len, 0, sizeof(attr_type_len));
+ u8 i = 0;
+ int result = 0;
+ int mActualBuffSize = 0;
+ int index = -1;
+
+ nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = event.get_vendor_data_len();
+ int event_id = event.get_vendor_subcmd();
+ int req_attr_cnt = 0;
+ int req_attr[DUMP_EVENT_ATTR_MAX];
+ int buf_attr = DUMP_BUF_ATTR_INVALID;
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("No Debug data found");
+ return NL_SKIP;
+ }
+ DUMP_INFO(("Ring Dump handler. Got event: %d", event_id));
+
+ buf_data_t buf;
+
+ memset(&buf, 0, sizeof(buf_data_t));
+ buf.ver = 0;
+ buf.buf_threshold = 0;
+
+ if (event_id == GOOGLE_FILE_DUMP_EVENT) {
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ int attr = it.get_type();
+ switch (attr) {
+ case DUMP_LEN_ATTR_MEMDUMP:
+ case DUMP_LEN_ATTR_TIMESTAMP:
+ case DUMP_LEN_ATTR_ECNTRS:
+ case DUMP_LEN_ATTR_DHD_DUMP:
+ case DUMP_LEN_ATTR_EXT_TRAP:
+ case DUMP_LEN_ATTR_HEALTH_CHK:
+ case DUMP_LEN_ATTR_COOKIE:
+ case DUMP_LEN_ATTR_FLOWRING_DUMP:
+ case DUMP_LEN_ATTR_STATUS_LOG:
+ case DUMP_LEN_ATTR_RTT_LOG:
+ case DUMP_LEN_ATTR_PKTID_MAP_LOG:
+ case DUMP_LEN_ATTR_PKTID_UNMAP_LOG: {
+ mActualBuffSize = it.get_u32();
+ DUMP_DEBUG(("len attr %s, len %d\n",
+ EWP_EventAttrToString(attr), mActualBuffSize));
+ if (mActualBuffSize > mLargestBuffSize)
+ mLargestBuffSize = mActualBuffSize;
+ attr_type_len[attr] = mActualBuffSize;
+
+ /* Store the order in which attributes are received
+ * so that file dump can be done in the same order
+ */
+ req_attr[req_attr_cnt++] = attr;
+ break;
+ }
+ default: {
+ ALOGE("Ignoring invalid attribute type = %d, size = %d",
+ attr, it.get_len());
+ break;
+ }
+ }
+ }
+ /* Allocation for the largest buffer size to use it recursively for other buf attr. */
+ if (mLargestBuffSize) {
+ DUMP_INFO(("Max dump size: %d", mLargestBuffSize));
+ mBuff = (char *)malloc(mLargestBuffSize);
+ if (!mBuff) {
+ ALOGE("Buffer allocation failed");
+ return NL_SKIP;
+ }
+ memset(mBuff, 0, mLargestBuffSize);
+ }
+
+ WifiRequest request(familyId(), ifaceId());
+ result = request.create(GOOGLE_OUI, LOGGER_DEBUG_GET_DUMP);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to create get memory dump request; result = %d", result);
+ freeup();
+ goto exit;
+ }
+
+ /* Requesting logger dump for each received attr */
+ for (i = 0; i < req_attr_cnt; i++) {
+ int attr = req_attr[i];
+
+ if (attr_type_len[attr] == 0) {
+ continue;
+ }
+
+ index = logger_attr_lookup(attr);
+ buf_attr = attr_lookup_tbl[index].buf_attr;
+ if (!ring_name[buf_attr]) {
+ ALOGE("Failed to find ringname index:%d buf_attr:%d", index, buf_attr);
+ continue;
+ }
+
+ buf.len = attr_type_len[attr];
+ buf.data_buf[0] = mBuff;
+ DUMP_DEBUG(("buf len = %d, buf ptr= %p for attr = %s\n",
+ buf.len, buf.data_buf[0], EWP_EventAttrToString(attr)));
+ result = request_logger_dump(request, &buf, attr);
+ if (result != WIFI_SUCCESS) {
+ /* Proceeding further for other attributes */
+ ALOGE("Failed to request the logger dump for attr = %s; result = %d",
+ EWP_EventAttrToString(attr), result);
+ continue;
+ }
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register get memory dump response for attr = %s; result = %d",
+ EWP_EventAttrToString(attr), result);
+ /* Proceeding further for other attributes */
+ continue;
+ }
+ }
+
+ WifiRequest request2(familyId(), ifaceId());
+ result = request2.create(GOOGLE_OUI, LOGGER_FILE_DUMP_DONE_IND);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to trigger dev close; result = %d", result);
+ freeup();
+ goto exit;
+ }
+ requestResponse(request2);
+ freeup();
+ } else {
+ ALOGE("dump event missing dump length attribute");
+ return NL_SKIP;
+ }
+ exit:
+ if (result != WIFI_SUCCESS) {
+ return NL_SKIP;
+ }
+ return NL_OK;
+ }
+};
+///////////////////////////////////////////////////////////////////////////////
+#endif /* RING_DUMP */
wifi_error wifi_start_hal(wifi_interface_handle iface)
{
@@ -1026,10 +1950,54 @@ wifi_error wifi_hal_preInit(wifi_interface_handle iface)
return result;
}
-wifi_error wifi_stop_hal(wifi_interface_handle iface)
+#ifdef RING_DUMP
+wifi_error wifi_start_ring_dump(wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler ring_handle)
{
wifi_handle handle = getWifiHandle(iface);
+ DUMP_INFO(("start ring dump, handle = %p", handle));
+ wifi_buf_ring_map_entry_t map[DUMP_BUF_ATTR_MAX];
+ unsigned int num_maps = DUMP_BUF_ATTR_MAX;
+ wifi_error result;
+
+ /* Get mapping table from driver */
+ DebugCommand *debug_cmd = new DebugCommand(iface, &num_maps, map, GET_BUF_RING_MAP);
+ NULL_CHECK_RETURN(debug_cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ result = (wifi_error)debug_cmd->start();
+ debug_cmd->releaseRef();
+
+ /* Set ringname to corresponding buf attr */
+ RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID, num_maps, map, ring_handle);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ result = wifi_register_cmd(handle, FILE_DUMP_REQUEST_ID, cmd);
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ wifi_unregister_cmd(handle, FILE_DUMP_REQUEST_ID);
+ cmd->releaseRef();
+ return result;
+ }
+ return result;
+}
+wifi_error wifi_stop_ring_dump(wifi_interface_handle iface,
+ wifi_ring_buffer_data_handler ring_handle)
+{
+ RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ DUMP_INFO(("stop ring dump"));
+ cmd->cancel();
+ cmd->releaseRef();
+ return WIFI_SUCCESS;
+}
+#endif /* RING_DUMP */
+
+wifi_error wifi_stop_hal(wifi_interface_handle iface)
+{
HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
cmd->cancel();
@@ -1037,6 +2005,85 @@ wifi_error wifi_stop_hal(wifi_interface_handle iface)
return WIFI_SUCCESS;
}
+
+wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle,
+ wifi_subsystem_restart_handler handler)
+{
+ hal_info *info = NULL;
+
+ info = (hal_info *)handle;
+ if (info == NULL) {
+ ALOGE("Could not find hal info\n");
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ SetRestartHandler *cmd = new SetRestartHandler(handle, HAL_RESTART_ID, handler);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+ wifi_error result = wifi_register_cmd(handle, HAL_RESTART_ID, cmd);
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ wifi_unregister_cmd(handle, HAL_RESTART_ID);
+ cmd->releaseRef();
+ return result;
+ }
+
+ /* Cache the handler to use it for trigger subsystem restart */
+ ALOGI("Register SSR handler:%p", handler);
+ info->restart_handler = handler;
+ return result;
+}
+
+wifi_error wifi_trigger_subsystem_restart(wifi_handle handle)
+{
+ wifi_error result = WIFI_SUCCESS;
+ hal_info *info = NULL;
+ char error_str[20];
+ SubSystemRestart *cmd = NULL;
+ wifi_interface_handle *ifaceHandles = NULL;
+ wifi_interface_handle wlan0Handle;
+ int numIfaceHandles = 0;
+
+ info = (hal_info *)handle;
+ if (handle == NULL || info == NULL) {
+ ALOGE("Could not find hal info\n");
+ result = WIFI_ERROR_UNKNOWN;
+ goto exit;
+ }
+
+ ALOGI("Trigger subsystem restart\n");
+
+ wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
+
+ cmd = new SubSystemRestart(wlan0Handle);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ result = (wifi_error)cmd->create();
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ strncpy(error_str, "WIFI_ERROR_UNKNOWN", sizeof(error_str));
+ ALOGE("Failed to create SSR");
+ goto exit;
+ }
+
+ strncpy(error_str, "WIFI_SUCCESS", sizeof(error_str));
+
+exit:
+ if (info->restart_handler.on_subsystem_restart) {
+ ALOGI("Trigger ssr handler registered handler:%p",
+ info->restart_handler.on_subsystem_restart);
+ (info->restart_handler.on_subsystem_restart)(error_str);
+ } else {
+ ALOGI("No trigger ssr handler registered");
+ }
+
+ return result;
+}
+
wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
wifi_alert_handler handler)
{
@@ -1075,7 +2122,7 @@ wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle if
return WIFI_SUCCESS;
}
- return wifi_cancel_cmd(id, iface);
+ return wifi_get_cancel_cmd(id, iface);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1345,7 +2392,7 @@ public:
for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
*mNoProvidedFates = it.get_u32();
- ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
+ ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);
} else {
ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
it.get_type(), it.get_len());
@@ -1429,7 +2476,7 @@ class GetWakeReasonCountCommand : public WifiCommand {
mWakeReasonCnt->total_driver_fw_local_wake =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
+ case WAKE_STAT_ATTRIBUTE_TOTAL:
mWakeReasonCnt->total_cmd_event_wake =
it.get_u32();
break;
@@ -1437,7 +2484,7 @@ class GetWakeReasonCountCommand : public WifiCommand {
mWakeReasonCnt->cmd_event_wake_cnt_used =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
+ case WAKE_STAT_ATTRIBUTE_WAKE:
memcpy(mCmdEventWakeCount, it.get_data(),
(mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
break;
@@ -1485,7 +2532,7 @@ class GetWakeReasonCountCommand : public WifiCommand {
mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
it.get_u32();
break;
- case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
+ case WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT:
mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
it.get_u32();
break;
@@ -1540,3 +2587,253 @@ wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
cmd->releaseRef();
return result;
}
+
+///////////////////////////////////////////////////////////////////////////////
+class OtaUpdateCommand : public WifiCommand
+{
+
+ public:
+ OtaUpdateCommand(wifi_interface_handle iface)
+ : WifiCommand("OtaUpdateCommand", iface, 0)
+ { }
+
+ int start() {
+ ALOGE("Start OtaUpdateCommand");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_GET_OTA_CURRUNT_INFO);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set hal start; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set hal start response; result = %d", result);
+ }
+ return result;
+ }
+
+ int otaDownload(ota_info_buf_t* buf, uint32_t ota_version) {
+ u32 force_reg_on = false;
+ WifiRequest request(familyId(), ifaceId());
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_OTA_UPDATE);
+
+ ALOGE("Download the OTA configuration");
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set Hal preInit; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(OTA_DOWNLOAD_CLM_LENGTH_ATTR, buf->ota_clm_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_CLM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put_u32(OTA_DOWNLOAD_NVRAM_LENGTH_ATTR, buf->ota_nvram_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_NVRAM_ATTR,
+ buf->ota_nvram_buf, sizeof(*buf->ota_nvram_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ if (applied_ota_version != ota_version) {
+ force_reg_on = true;
+ applied_ota_version = ota_version;
+ }
+ result = request.put_u32(OTA_SET_FORCE_REG_ON, force_reg_on);
+ 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);
+ }
+
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In OtaUpdateCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case OTA_CUR_NVRAM_EXT_ATTR:
+ strncpy(ota_nvram_ext, (char*)it.get_string(), it.get_len());
+ ALOGI("Current Nvram ext [%s]\n", ota_nvram_ext);
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error read_ota_file(char* file, char** buffer, uint32_t* size)
+{
+ FILE* fp = NULL;
+ int file_size;
+ char* buf;
+ fp = fopen(file, "r");
+
+ if (fp == NULL) {
+ ALOGI("File [%s] doesn't exist.", file);
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ file_size = ftell(fp);
+
+ buf = (char *)malloc(file_size + 1);
+ if (buf == NULL) {
+ fclose(fp);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ memset(buf, 0, file_size + 1);
+ fseek(fp, 0, SEEK_SET);
+ fread(buf, file_size, 1, fp);
+
+ *buffer = (char*) buf;
+ *size = file_size;
+ fclose(fp);
+ return WIFI_SUCCESS;
+}
+
+wifi_error check_multiple_nvram_clm(uint32_t type, char* hw_revision, char* hw_sku,
+ char** buffer, uint32_t* buffer_len)
+{
+ char file_name[MAX_NV_FILE][FILE_NAME_LEN];
+ char nvram_clmblob_default_file[FILE_NAME_LEN] = {0,};
+ wifi_error result = WIFI_SUCCESS;
+
+ if (type == CLM_BLOB) {
+ sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_CLM_FILE);
+ }
+ else if (type == NVRAM) {
+ sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
+ }
+ for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
+ memset(file_name[i], 0, FILE_NAME_LEN);
+ }
+
+ sprintf(file_name[0], "%s_%s_%s", nvram_clmblob_default_file, hw_revision, hw_sku);
+ sprintf(file_name[1], "%s_%s", nvram_clmblob_default_file, hw_revision);
+ sprintf(file_name[2], "%s_%s", nvram_clmblob_default_file, hw_sku);
+ sprintf(file_name[3], "%s", nvram_clmblob_default_file);
+
+ for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
+ result = read_ota_file(file_name[i], buffer, buffer_len);
+ if (result == WIFI_SUCCESS) {
+ ALOGI("[OTA] %s PATH %s", type == NVRAM ? "NVRAM" : "CLM", file_name[i]);
+ break;
+ }
+ }
+ return result;
+}
+
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ wifi_error result = WIFI_SUCCESS;
+ ota_info_buf_t buf;
+ char *buffer_nvram = NULL;
+ char *buffer_clm = 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,};
+
+ OtaUpdateCommand *cmd = new OtaUpdateCommand(iface);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ALOGD("wifi_hal_ota_update, handle = %p, ota_version %d\n", handle, ota_version);
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ property_get(HW_DEV_PROP, prop_revision_buf, NULL);
+ property_get(HW_SKU_PROP, prop_sku_buf, NULL);
+
+ strncpy(sku_name, "NA", MAX_SKU_NAME_LEN);
+ for (int i = 0; i < ARRAYSIZE(sku_table); i ++) {
+ if (strcmp(prop_sku_buf, sku_table[i].hw_id) == 0) {
+ strncpy(sku_name, sku_table[i].sku, MAX_SKU_NAME_LEN);
+ break;
+ }
+ }
+ ALOGD("prop_sku_buf is %s, sku_name is %s", prop_sku_buf, sku_name);
+
+ check_multiple_nvram_clm(CLM_BLOB, prop_revision_buf, sku_name, &buffer_clm, &buf.ota_clm_len);
+ if (buffer_clm == NULL) {
+ ALOGE("buffer_clm is null");
+ goto exit;
+ }
+ buf.ota_clm_buf[0] = buffer_clm;
+
+ check_multiple_nvram_clm(NVRAM, prop_revision_buf, sku_name,
+ &buffer_nvram, &buf.ota_nvram_len);
+ if (buffer_nvram == NULL) {
+ ALOGE("buffer_nvram is null");
+ goto exit;
+ }
+ buf.ota_nvram_buf[0] = buffer_nvram;
+ cmd->otaDownload(&buf, ota_version);
+
+exit:
+ if (buffer_clm != NULL) {
+ free(buffer_clm);
+ }
+ if (buffer_nvram != NULL) {
+ free(buffer_nvram);
+ }
+
+ cmd->releaseRef();
+
+ return result;
+}
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
index 8054f49..1702ffd 100644
--- a/bcmdhd/wifi_hal/wifi_offload.cpp
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -52,13 +52,16 @@ typedef enum {
} WIFI_OFFLOAD_SUB_COMMAND;
typedef enum {
- MKEEP_ALIVE_ATTRIBUTE_ID,
- MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
- MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
- MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
- MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
- MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
- MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE
+ MKEEP_ALIVE_ATTRIBUTE_INVALID = 0,
+ MKEEP_ALIVE_ATTRIBUTE_ID = 1,
+ MKEEP_ALIVE_ATTRIBUTE_IP_PKT = 2,
+ MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN = 3,
+ MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR = 4,
+ MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR = 5,
+ MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC = 6,
+ MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE = 7,
+ /* Add new attributes just above this */
+ MKEEP_ALIVE_ATTRIBUTE_MAX
} WIFI_MKEEP_ALIVE_ATTRIBUTE;
typedef enum {
diff --git a/bcmdhd/wpa_supplicant_8_lib/Android.mk b/bcmdhd/wpa_supplicant_8_lib/Android.mk
index 518f0ca..448a7ca 100644
--- a/bcmdhd/wpa_supplicant_8_lib/Android.mk
+++ b/bcmdhd/wpa_supplicant_8_lib/Android.mk
@@ -66,6 +66,9 @@ L_CFLAGS += -Wall -Werror -Wno-unused-parameter -Wno-macro-redefined
include $(CLEAR_VARS)
LOCAL_MODULE := lib_driver_cmd_bcmdhd
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
LOCAL_SHARED_LIBRARIES := libc libcutils
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(WPA_SRC_FILE)