From c481cf0851503f7ee5590d06d0df80bf70630ef0 Mon Sep 17 00:00:00 2001 From: Jan Altensen Date: Sun, 24 Feb 2019 13:33:39 +0100 Subject: [PATCH] update wifi_hal and wpa_supplicant_8_lib Change-Id: I2f0006f415546c1ae42cfa8c76404eea7e49d1df --- wifi_hal/Android.mk | 8 +- wifi_hal/common.h | 16 + wifi_hal/cpp_bindings.cpp | 33 +- wifi_hal/cpp_bindings.h | 4 +- wifi_hal/gscan.cpp | 1881 --------------- wifi_hal/rtt.cpp | 697 ------ wifi_hal/wifi_hal.cpp | 590 +++-- wifi_hal/wifi_logger.cpp | 170 ++ wifi_hal/wifi_offload.cpp | 2 - wpa_supplicant_8_lib/Android.mk | 4 + .../mediatek_driver_cmd_nl80211.c | 2007 ++++++++++++++++- .../mediatek_driver_nl80211.h | 407 ++++ 12 files changed, 2956 insertions(+), 2863 deletions(-) delete mode 100644 wifi_hal/gscan.cpp delete mode 100644 wifi_hal/rtt.cpp create mode 100644 wifi_hal/wifi_logger.cpp create mode 100644 wpa_supplicant_8_lib/mediatek_driver_nl80211.h diff --git a/wifi_hal/Android.mk b/wifi_hal/Android.mk index 8a39c60..48e6646 100644 --- a/wifi_hal/Android.mk +++ b/wifi_hal/Android.mk @@ -24,10 +24,6 @@ LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses LOCAL_CPPFLAGS += -Wno-conversion-null -ifeq ($(MTK_TC7_FEATURE), yes) -LOCAL_CFLAGS += -DCONFIG_PNO_SUPPORT -endif - LOCAL_C_INCLUDES += \ external/libnl/include \ $(call include-path-for, libhardware_legacy)/hardware_legacy \ @@ -35,12 +31,12 @@ LOCAL_C_INCLUDES += \ LOCAL_SRC_FILES := \ wifi_hal.cpp \ - rtt.cpp \ common.cpp \ cpp_bindings.cpp \ - gscan.cpp \ + wifi_logger.cpp \ wifi_offload.cpp +LOCAL_SHARED_LIBRARIES += libutils liblog LOCAL_MODULE := libwifi-hal-mt66xx LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_OWNER := mtk diff --git a/wifi_hal/common.h b/wifi_hal/common.h index 34df2a4..46d9e43 100644 --- a/wifi_hal/common.h +++ b/wifi_hal/common.h @@ -80,6 +80,12 @@ typedef enum { WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ /* Add more sub commands here */ + + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + /* skip 0x0009 for diver set_roaming_policy */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING, /* 0x000b */ + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ } WIFI_SUB_COMMAND; typedef enum { @@ -123,6 +129,15 @@ typedef enum { WIFI_ATTRIBUTE_MAX_RSSI, WIFI_ATTRIBUTE_MIN_RSSI, WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE, + + WIFI_ATTRIBUTE_TX_POWER_SCENARIO, } WIFI_ATTRIBUTE; typedef enum { @@ -188,6 +203,7 @@ typedef struct { // add other details + wifi_roaming_capabilities roaming_capa; // capabilities of roaming } hal_info; #define PNO_SSID_FOUND 0x1 diff --git a/wifi_hal/cpp_bindings.cpp b/wifi_hal/cpp_bindings.cpp index 62127f0..7fbaeba 100644 --- a/wifi_hal/cpp_bindings.cpp +++ b/wifi_hal/cpp_bindings.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "wifi_hal.h" #include "common.h" @@ -582,6 +583,28 @@ static int no_seq_check(struct nl_msg *msg, void *arg) return NL_OK; } +wifi_error WifiCommand::kernelErrorToWifiHalError(int kerr) +{ + if (kerr >= 0) + return WIFI_SUCCESS; + + switch (kerr) { + case -EOPNOTSUPP: + return WIFI_ERROR_NOT_SUPPORTED; + case -EAGAIN: + return WIFI_ERROR_NOT_AVAILABLE; + case -EINVAL: + return WIFI_ERROR_INVALID_ARGS; + case -ETIMEDOUT: + return WIFI_ERROR_TIMED_OUT; + case -ENOMEM: + return WIFI_ERROR_OUT_OF_MEMORY; + case -EBUSY: + return WIFI_ERROR_BUSY; + } + return WIFI_ERROR_UNKNOWN; +} + int WifiCommand::requestResponse() { int err = create(); if (err < 0) { @@ -622,7 +645,7 @@ int WifiCommand::requestResponse(WifiRequest& request) { ALOGD("WifiCommand::requestResponse err=%d", err); out: nl_cb_put(cb); - return err; + return kernelErrorToWifiHalError(err); } int WifiCommand::requestEvent(int cmd) { @@ -641,8 +664,10 @@ int WifiCommand::requestEvent(int cmd) { ALOGD("WifiCommand::requestEvent waiting for response %d", cmd); res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); - if (res < 0) + if (res < 0) { + res = kernelErrorToWifiHalError(res); goto out; + } ALOGD("WifiCommand::requestEvent waiting for event"); res = mCondition.wait(); @@ -666,8 +691,10 @@ int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) { goto out; res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); - if (res < 0) + if (res < 0) { + res = kernelErrorToWifiHalError(res); goto out; + } res = mCondition.wait(); if (res < 0) diff --git a/wifi_hal/cpp_bindings.h b/wifi_hal/cpp_bindings.h index 7aaa481..39a2bd5 100644 --- a/wifi_hal/cpp_bindings.h +++ b/wifi_hal/cpp_bindings.h @@ -251,7 +251,7 @@ public: } virtual void addRef() { - int refs = __sync_add_and_fetch(&mRefs, 1); + __sync_add_and_fetch(&mRefs, 1); // ALOGD("addRef: WifiCommand %p has %d references", this, refs); } @@ -280,6 +280,8 @@ public: int requestVendorEvent(uint32_t id, int subcmd); int requestResponse(WifiRequest& request); + wifi_error kernelErrorToWifiHalError(int kerr); + protected: wifi_handle wifiHandle() { return getWifiHandle(mInfo); diff --git a/wifi_hal/gscan.cpp b/wifi_hal/gscan.cpp deleted file mode 100644 index 4f9c6bf..0000000 --- a/wifi_hal/gscan.cpp +++ /dev/null @@ -1,1881 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" - -typedef enum { - GSCAN_ATTRIBUTE_CAPABILITIES = 1, - - GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, - GSCAN_ATTRIBUTE_BASE_PERIOD, - GSCAN_ATTRIBUTE_BUCKETS_BAND, - GSCAN_ATTRIBUTE_BUCKET_ID, - GSCAN_ATTRIBUTE_BUCKET_PERIOD, - GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, - GSCAN_ATTRIBUTE_BUCKET_CHANNELS, - GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, - GSCAN_ATTRIBUTE_REPORT_THRESHOLD, - GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, - - GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, - GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ - GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ - GSCAN_ENABLE_FULL_SCAN_RESULTS, - GSCAN_ATTRIBUTE_REPORT_EVENTS, - /* Adaptive scan attributes */ - GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT, - GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, - - GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, - GSCAN_ATTRIBUTE_FLUSH_RESULTS, - GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ - GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ - GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ - GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ - GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, - - GSCAN_ATTRIBUTE_SSID = 40, - GSCAN_ATTRIBUTE_BSSID, - GSCAN_ATTRIBUTE_CHANNEL, - GSCAN_ATTRIBUTE_RSSI, - GSCAN_ATTRIBUTE_TIMESTAMP, - GSCAN_ATTRIBUTE_RTT, - GSCAN_ATTRIBUTE_RTTSD, - - GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, - GSCAN_ATTRIBUTE_RSSI_LOW, - GSCAN_ATTRIBUTE_RSSI_HIGH, - GSCAN_ATTRIBUTE_HOTLIST_ELEM, - GSCAN_ATTRIBUTE_HOTLIST_FLUSH, - - GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, - GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, - GSCAN_ATTRIBUTE_MIN_BREACHING, - GSCAN_ATTRIBUTE_NUM_AP, /* TBD */ - GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, - GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, - - /* EPNO */ - GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70, - GSCAN_ATTRIBUTE_EPNO_SSID, - GSCAN_ATTRIBUTE_EPNO_SSID_LEN, - GSCAN_ATTRIBUTE_EPNO_RSSI, - GSCAN_ATTRIBUTE_EPNO_FLAGS, - GSCAN_ATTRIBUTE_EPNO_AUTH, - GSCAN_ATTRIBUTE_EPNO_SSID_NUM, - GSCAN_ATTRIBUTE_EPNO_FLUSH, - - GSCAN_ATTRIBUTE_WHITELIST_SSID = 80, - GSCAN_ATTRIBUTE_NUM_WL_SSID, - GSCAN_ATTRIBUTE_WL_SSID_LEN, - GSCAN_ATTRIBUTE_WL_SSID_FLUSH, - GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM, - GSCAN_ATTRIBUTE_NUM_BSSID, - GSCAN_ATTRIBUTE_BSSID_PREF_LIST, - GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH, - GSCAN_ATTRIBUTE_BSSID_PREF, - GSCAN_ATTRIBUTE_RSSI_MODIFIER, - - GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90, - GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD, - GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR, - GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR, - GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST, - GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS, - GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER, - GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE, - - /* BSSID blacklist */ - GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100, - GSCAN_ATTRIBUTE_BLACKLIST_BSSID, - - /* ANQPO */ - GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110, - GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, - GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, - GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, - GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, - GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, - - /* ePNO cfg */ - GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130, - GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR, - GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX, - GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS, - GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, - GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS, - GSCAN_ATTRIBUTE_EPNO_5G_BONUS, - - GSCAN_ATTRIBUTE_MAX - -} GSCAN_ATTRIBUTE; - -// helper methods -wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface, - wifi_scan_result_handler handler); -wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface); -int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event, - wifi_scan_result_handler handler); -void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from); - - -void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from) -{ - to->ts = from->ts; - to->channel = from->channel; - to->rssi = from->rssi; - to->rtt = from->rtt; - to->rtt_sd = from->rtt_sd; - to->beacon_period = from->beacon_period; - to->capability = from->capability; - memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1)); - memcpy(&to->bssid, &from->bssid, sizeof(mac_addr)); -} - -///////////////////////////////////////////////////////////////////////////// - -class GetCapabilitiesCommand : public WifiCommand -{ - wifi_gscan_capabilities *mCapabilities; -public: - GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) - : WifiCommand("GetCapabilitiesCommand", iface, 0), mCapabilities(capabitlites) - { - memset(mCapabilities, 0, sizeof(*mCapabilities)); - } - - virtual int create() { - ALOGD("[WIFI HAL]Creating message to get gscan capablities; handle=%p, iface=%d, ifname=%s", - mIfaceInfo->handle, mIfaceInfo->id, mIfaceInfo->name); - - int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES); - if (ret < 0) { - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGV("In GetCapabilities::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGE("Ignoring reply with cmd = %d", reply.get_cmd()); - return NL_SKIP; - } - - int id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - int wiphy_id = reply.get_u32(NL80211_ATTR_WIPHY); - int if_id = reply.get_u32(NL80211_ATTR_IFINDEX); - - struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - void *payload = NULL; - if (vendor_data->nla_type == GSCAN_ATTRIBUTE_CAPABILITIES) { - payload = nla_data(vendor_data); - len -= NLA_HDRLEN; - } - - ALOGD("wiphy_id=%d, if_id=%d, Id=%0x, subcmd=%d, len=%d, expected len=%d", - wiphy_id, if_id, id, subcmd, len, sizeof(*mCapabilities)); - if (payload) - memcpy(mCapabilities, payload, min(len, (int) sizeof(*mCapabilities))); - - ALOGI("max_scan_cache_size=%d, %d, %d, %d, %d, %d, %d, %d, max_bssid_history_entries=%d", - mCapabilities->max_scan_cache_size, mCapabilities->max_scan_buckets, - mCapabilities->max_ap_cache_per_scan, - mCapabilities->max_rssi_sample_size, - mCapabilities->max_scan_reporting_threshold, - mCapabilities->max_hotlist_bssids, - mCapabilities->max_hotlist_ssids, - mCapabilities->max_significant_wifi_change_aps, - mCapabilities->max_bssid_history_entries); - - /* this case wifi driver don't support GScan */ - if (!(mCapabilities->max_scan_cache_size || mCapabilities->max_scan_buckets - || mCapabilities->max_ap_cache_per_scan)) - return NL_STOP; - - return NL_OK; - } -}; - -wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, - wifi_gscan_capabilities *capabilities) -{ - GetCapabilitiesCommand command(handle, capabilities); - return (wifi_error) command.requestResponse(); -} - -class GetChannelListCommand : public WifiCommand -{ -private: - wifi_channel *mChannels; - int mMaxChannels; - int *mNumOfChannel; - int mBand; - -public: - GetChannelListCommand(wifi_interface_handle handle, int band, int max_channels, - wifi_channel *channels, int *num_channels) - : WifiCommand("GetChannelListCommand", handle, 0) - { - mBand = band; - mMaxChannels = max_channels; - mChannels = channels; - mNumOfChannel = num_channels; - memset(mChannels, 0, sizeof(wifi_channel) * mMaxChannels); - } - - virtual int create() { - ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CHANNEL_LIST); - if (ret < 0) { - return ret; - } - - ALOGI("In GetChannelList::mBand=%d", mBand); - - nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); - ret = mMsg.put_u32(WIFI_ATTRIBUTE_BAND, mBand); - if (ret < 0) { - return ret; - } - - mMsg.attr_end(data); - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGV("In GetChannelList::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGE("Ignore reply with cmd 0x%x", reply.get_cmd()); - return NL_SKIP; - } - - int vendor_id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd); - - nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = reply.get_vendor_data_len(); - if (vendor == NULL || len == 0) { - ALOGE("No vendor data in GetChannelList response, ignore it"); - return NL_SKIP; - } - - int num_channels = 0; - for (nl_iterator it(vendor); it.has_next(); it.next()) { - if (it.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS) { - num_channels = it.get_u32(); - ALOGI("Get channel list with %d channels", num_channels); - if (num_channels > mMaxChannels) - num_channels = mMaxChannels; - *mNumOfChannel = num_channels; - } else if (it.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST && num_channels) { - memcpy(mChannels, it.get_data(), sizeof(wifi_channel) * num_channels); - } else { - ALOGW("Ignore invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - - ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels, *(mChannels + 1)); - - return NL_OK; - } -}; - -wifi_error wifi_get_valid_channels(wifi_interface_handle handle, - int band, int max_channels, wifi_channel *channels, int *num_channels) -{ - GetChannelListCommand command(handle, band, max_channels, channels, num_channels); - return (wifi_error) command.requestResponse(); -} - -///////////////////////////////////////////////////////////////////////////// - -/* 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); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; -} - -///////////////////////////////////////////////////////////////////////////// -class FullScanResultsCommand : public WifiCommand -{ - int *mParams; - wifi_scan_result_handler mHandler; -public: - FullScanResultsCommand(wifi_interface_handle iface, int id, int *params, - wifi_scan_result_handler handler) - : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler) - { } - - int createRequest(WifiRequest& request, int subcmd, int enable) { - int result = request.create(GOOGLE_OUI, subcmd); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; - - } - - int start() { - ALOGD("Enabling Full scan results"); - WifiRequest request(familyId(), ifaceId()); - int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create request; result = %d", result); - return result; - } - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); - - 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); - return result; - } - - return result; - } - - virtual int cancel() { - ALOGD("Disabling Full scan results"); - - WifiRequest request(familyId(), ifaceId()); - int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to disable full scan results;result = %d", result); - } - } - - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - ALOGD("Request complete!"); - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGV("Full scan results: Got an event"); - return wifi_handle_full_scan_event(id(), event, mHandler); - } - -}; -///////////////////////////////////////////////////////////////////////////// - -class ScanCommand : public WifiCommand -{ - wifi_scan_cmd_params *mParams; - wifi_scan_result_handler mHandler; -public: - ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, - wifi_scan_result_handler handler) - : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); - if (result < 0) { - return result; - } - - for (int i = 0; i < mParams->num_buckets; i++) { - nlattr * bucket = request.attr_start(i); // next bucket - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); - if (result < 0) { - return result; - } - - /* parameter validity check */ - if (mParams->buckets[i].band < WIFI_BAND_UNSPECIFIED - || mParams->buckets[i].band > WIFI_BAND_ABG_WITH_DFS) - mParams->buckets[i].band = WIFI_BAND_ABG; /* default 2.4G + 5G */ - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, - mParams->buckets[i].band); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT, - mParams->buckets[i].step_count); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, - mParams->buckets[i].max_period); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, - mParams->buckets[i].report_events); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, - mParams->buckets[i].num_channels); - if (result < 0) { - return result; - } - - if (mParams->buckets[i].num_channels) { - nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); - ALOGV(" channels: "); - for (int j = 0; j < mParams->buckets[i].num_channels; j++) { - result = request.put_u32(j, mParams->buckets[i].channels[j].channel); - ALOGV(" %u", mParams->buckets[i].channels[j].channel); - - if (result < 0) { - return result; - } - } - request.attr_end(channels); - } - - request.attr_end(bucket); - } - - request.attr_end(data); - return WIFI_SUCCESS; - } - - int createScanConfigRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); - if (result < 0) { - return result; - } - - /* parameter validity check */ - if (mParams->report_threshold_percent < 0 || mParams->report_threshold_percent > 100) - mParams->report_threshold_percent = 100; - result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, - mParams->report_threshold_percent); - if (result < 0) { - return result; - } - - int num_scans = mParams->report_threshold_num_scans; - - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; - } - - int createStartRequest(WifiRequest& request) { - return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); - } - - int createStopRequest(WifiRequest& request) { - return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0); - } - - int start() { - ALOGI("1) GScan Setting configuration: "); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create setup request; result = %d", result); - return result; - } - - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to configure setup; result = %d", result); - return result; - } - - request.destroy(); - - result = createScanConfigRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create scan config request; result = %d", result); - return result; - } - - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to configure scan; result = %d", result); - return result; - } - - ALOGI("2) Enable GScan: "); - - result = createStartRequest(request); - if (result != WIFI_SUCCESS) { - 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) { - 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; - } - - virtual int cancel() { - ALOGI("Stopping GScan"); - - WifiRequest request(familyId(), ifaceId()); - int result = createStopRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create stop request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to stop 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 WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGV("[WIFI HAL]Got a GScan results event"); - - // event.log(); - - struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data(); - int len = event.get_vendor_data_len(); - int event_id = event.get_vendor_subcmd(); - - if (vendor_data) - ALOGV("vendor_data->nla_type=%d nla_len=%d, len=%d, event_id=%d", - vendor_data->nla_type, vendor_data->nla_len, len, event_id); - - if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) || - (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) { - if (vendor_data == NULL || vendor_data->nla_len != 8) { - ALOGE("Bad event data!"); - return NL_SKIP; - } - wifi_scan_event evt_type; - evt_type = (wifi_scan_event) nla_get_u32(vendor_data); - ALOGI("Received event_id=%d, event type=%d", event_id, evt_type); - if (*mHandler.on_scan_event) - (*mHandler.on_scan_event)(id(), evt_type); - } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) { - wifi_handle_full_scan_event(id(), event, mHandler); - } - return NL_SKIP; - } -}; - -wifi_error wifi_start_gscan( - wifi_request_id id, - wifi_interface_handle iface, - wifi_scan_cmd_params params, - wifi_scan_result_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - ALOGD("[WIFI HAL]Starting GScan, halHandle = %p", handle); - - ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) -{ - ALOGD("[WIFI HAL]Stopping GScan"); - wifi_handle handle = getWifiHandle(iface); - - if (id == -1) { - wifi_scan_result_handler handler; - wifi_scan_cmd_params dummy_params; - memset(&handler, 0, sizeof(handler)); - - ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - return wifi_cancel_cmd(id, iface); -} - - -wifi_error wifi_enable_full_scan_results( - wifi_request_id id, - wifi_interface_handle iface, - wifi_scan_result_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - int params_dummy; - ALOGD("[WIFI HAL]Enabling full scan results, halHandle = %p", handle); - - FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, ¶ms_dummy, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -int wifi_handle_full_scan_event( - wifi_request_id id, - WifiEvent& event, - wifi_scan_result_handler handler) -{ - //nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data(); - unsigned int len = event.get_vendor_data_len(); - int event_id = event.get_vendor_subcmd(); - - if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) { - ALOGE("Full scan results: No scan results found"); - return NL_SKIP; - } - - wifi_gscan_full_result_t *drv_res = NULL; - if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) - drv_res = (wifi_gscan_full_result_t *)nla_data(vendor_data); - if (!drv_res) { - ALOGE("cannot get vendor_data of GSCAN_EVENT_FULL_SCAN_RESULTS\n"); - return NL_SKIP; - } - /* To protect against corrupted data, put a ceiling */ - int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length); - wifi_scan_result *full_scan_result; - 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 %lu!\n", len, - ie_len, offsetof(wifi_gscan_full_result_t, ie_data)); - return NL_SKIP; - } - full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data))); - if (!full_scan_result) { - ALOGE("Full scan results: Can't malloc!\n"); - return NL_SKIP; - } - convert_to_hal_result(full_scan_result, fixed); - full_scan_result->ie_length = ie_len; - memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len); - if(handler.on_full_scan_result) - handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket); - - ALOGI("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %llu %llu %llu 0x%x %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, fixed->capability, drv_res->scan_ch_bucket, drv_res->ie_length); - free(full_scan_result); - return NL_SKIP; -} - -wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface) -{ - ALOGD("[WIFI HAL]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)); - FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - - return wifi_cancel_cmd(id, iface); -} - - -///////////////////////////////////////////////////////////////////////////// - -class GetScanResultsCommand : public WifiCommand { - wifi_cached_scan_results *mScans; - int mMax; - int *mNum; - int mRetrieved; - byte mFlush; - int mCompleted; -public: - GetScanResultsCommand(wifi_interface_handle iface, byte flush, - wifi_cached_scan_results *results, int max, int *num) - : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num), - mRetrieved(0), mFlush(flush), mCompleted(0) - { } - - int createRequest(WifiRequest& request, int num, byte flush) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); - if (result < 0) { - return result; - } - - result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush); - if (result < 0) { - return result; - } - - request.attr_end(data); - return WIFI_SUCCESS; - } - - int execute() { - WifiRequest request(familyId(), ifaceId()); - ALOGD("retrieving mMax=%d scan results", mMax); - - for (int i = 0; i < 10 && mRetrieved < mMax; i++) { - int num_to_retrieve = mMax - mRetrieved; - ALOGI("retrieving %d:%d cached gscan results in one shot", mRetrieved, num_to_retrieve); - int result = createRequest(request, num_to_retrieve, mFlush); - if (result < 0) { - ALOGE("failed to create request"); - return result; - } - - int prev_retrieved = mRetrieved; - - result = requestResponse(request); - - if (result != WIFI_SUCCESS) { - ALOGE("failed to retrieve scan results; result = %d", result); - return result; - } - - ALOGD("mRetrieved=%d, prev_retrieved=%d, mCompleted=%d", mRetrieved, prev_retrieved, mCompleted); - - if (mRetrieved == prev_retrieved || mCompleted) { - /* no more items left to retrieve */ - break; - } - - request.destroy(); - } - - ALOGI("GetScanResults total read %d results", mRetrieved); - *mNum = mRetrieved; - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - ALOGV("In GetScanResultsCommand::handleResponse"); - - if (reply.get_cmd() != NL80211_CMD_VENDOR) { - ALOGE("Ignoring reply with cmd = %d", reply.get_cmd()); - return NL_SKIP; - } - - int id = reply.get_vendor_id(); - int subcmd = reply.get_vendor_subcmd(); - - /* - if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) { - ALOGE("Invalid response to GetScanResultsCommand; ignoring it"); - return NL_SKIP; - } - */ - - //nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); - struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - if (vendor_data == NULL || len == 0) { - ALOGE("no vendor data in GetScanResults response; ignoring it"); - return NL_SKIP; - } - ALOGD("Id = %0x, subcmd = %d, vendor=%p, get_vendor_data()=%p vendor->nla_type=%d len=%d", - id, subcmd, vendor_data, reply.get_vendor_data(), vendor_data->nla_type, len); - - for (nl_iterator it(vendor_data); it.has_next(); it.next()) { - if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { - mCompleted = it.get_u8(); - ALOGI("retrieved mCompleted flag : %d", mCompleted); - } else if (it.get_type() >= GSCAN_ATTRIBUTE_NUM_OF_RESULTS - && it.get_type() <= GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) { - int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0; - for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { - if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { - scan_id = it2.get_u32(); - ALOGD("retrieved scan_id : %d", scan_id); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { - flags = it2.get_u8(); - ALOGD("retrieved scan_flags : 0x%0x", flags); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { - num = it2.get_u32(); - ALOGD("retrieved num_results: %d", num); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) { - scan_ch_bucket_mask = it2.get_u32(); - ALOGD("retrieved scan_ch_bucket_mask: 0x%0x", scan_ch_bucket_mask); - } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) { - if (mRetrieved >= mMax) { - ALOGW("Stored %d scans, ignoring excess results", mRetrieved); - break; - } - num = min(num, (int)(it2.get_len()/sizeof(wifi_scan_result))); - num = min(num, (int)MAX_AP_CACHE_PER_SCAN); - ALOGI("Copying %d scan results, mRetrieved=%d, scan_id=%d, flag=0x%x, bktMask=0x%04x", - num, mRetrieved, scan_id, flags, scan_ch_bucket_mask); - wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data(); - wifi_scan_result *mScanResults = mScans[mRetrieved].results; - - for (int i = 0; i < num; i++) { - wifi_gscan_result_t *result = &results[i]; - convert_to_hal_result(&mScanResults[i], result); - mScanResults[i].ie_length = result->ie_length; - //mScanResults[i].ie_data = result->ie_data; - ALOGD("%02d %-32s " MACSTR " %ddB channel=%d, capa=0x%04x, ie_len=%d", i, - result->ssid, MAC2STR(result->bssid), - result->rssi, result->channel, mScanResults[i].capability, mScanResults[i].ie_length); - } - mScans[mRetrieved].scan_id = scan_id; - mScans[mRetrieved].flags = flags; - mScans[mRetrieved].num_results = num; - mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask; - ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id); - mRetrieved++; - } else { - ALOGW("Ignoring invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - } else { - ALOGW("Ignoring invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); - } - } - ALOGD("GetScanResults read %dth results", mRetrieved); - return NL_OK; - } -}; - -wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, - int max, wifi_cached_scan_results *results, int *num) { - - ALOGI("[WIFI HAL]Getting cached gscan results, flush=%d, max=%d, num=%d", flush, max, *num); - - GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - wifi_error err = (wifi_error) cmd->execute(); - cmd->releaseRef(); - return err; -} - -///////////////////////////////////////////////////////////////////////////// - -class BssidHotlistCommand : public WifiCommand -{ -private: - wifi_bssid_hotlist_params mParams; - wifi_hotlist_ap_found_handler mHandler; - static const int MAX_RESULTS = 64; - wifi_scan_result mResults[MAX_RESULTS]; -public: - BssidHotlistCommand(wifi_interface_handle handle, int id, - wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) - : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); - if (result < 0) { - return result; - } - - result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_NUM_AP, mParams.num_bssid); - if (result < 0) { - return result; - } - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); - for (int i = 0; i < mParams.num_bssid; i++) { - nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - - request.attr_end(attr); - request.attr_end(data); - return result; - } - - int createTeardownRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); - if (result < 0) { - return result; - } - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); - request.attr_end(attr); - request.attr_end(data); - return result; - } - - int start() { - ALOGD("[WIFI HAL]Executing hotlist setup request, num = %d", mParams.num_bssid); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - 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) { - return result; - } - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - - result = requestResponse(request); - if (result < 0) { - ALOGE("failed to start scan; result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - return result; - } - - ALOGI("successfully restarted the scan"); - return result; - } - - virtual int cancel() { - /* unregister event handler */ - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); - /* create set hotlist message with empty hotlist */ - WifiRequest request(familyId(), ifaceId()); - int result = createTeardownRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - return result; - } - - ALOGI("Successfully reset APs in current hotlist"); - return result; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGD("[WIFI HAL]Hotlist AP event"); - int event_id = event.get_vendor_subcmd(); - // event.log(); - - struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data(); - int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGI("No scan results found"); - return NL_SKIP; - } - - memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); - - int num = len / sizeof(wifi_scan_result); - num = min(MAX_RESULTS, num); - ALOGD("hotlist APs num=%d, vendor len=%d, nla_len=%d nla_type=%d", - num, len, vendor_data->nla_len, vendor_data->nla_type); - if(vendor_data->nla_type == GSCAN_EVENT_HOTLIST_RESULTS_LOST - || vendor_data->nla_type == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) - memcpy(mResults, nla_data(vendor_data), num * sizeof(wifi_scan_result)); - - if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) { - ALOGI("FOUND %d hotlist APs", num); - if (*mHandler.on_hotlist_ap_found) - (*mHandler.on_hotlist_ap_found)(id(), num, mResults); - } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) { - ALOGI("LOST %d hotlist APs", num); - if (*mHandler.on_hotlist_ap_lost) - (*mHandler.on_hotlist_ap_lost)(id(), num, mResults); - } - return NL_SKIP; - } -}; - -class ePNOCommand : public WifiCommand -{ -private: - wifi_epno_params epno_params; - wifi_epno_handler mHandler; - wifi_scan_result mResults[MAX_EPNO_NETWORKS]; -public: - ePNOCommand(wifi_interface_handle handle, int id, - const wifi_epno_params *params, wifi_epno_handler handler) - : WifiCommand("ePNOCommand", handle, id), mHandler(handler) - { - if (params != NULL) { - memcpy(&epno_params, params, sizeof(wifi_epno_params)); - } else { - memset(&epno_params, 0, sizeof(wifi_epno_params)); - } - } - - int createSetupRequest(WifiRequest& request) { - if (epno_params.num_networks > MAX_EPNO_NETWORKS) { - ALOGE("wrong epno num_networks:%d", epno_params.num_networks); - return WIFI_ERROR_INVALID_ARGS; - } - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); - if (result < 0) { - return result; - } - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); - if (result < 0) { - return result; - } - - result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR, - (u8)epno_params.min5GHz_rssi); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR, - (u8)epno_params.min24GHz_rssi); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX, - epno_params.initial_score_max); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS, - epno_params.current_connection_bonus); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, - epno_params.same_network_bonus); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS, - epno_params.secure_bonus); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS, - epno_params.band5GHz_bonus); - if (result < 0) { - return result; - } - result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM, - epno_params.num_networks); - if (result < 0) { - return result; - } - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST); - wifi_epno_network *ssid_list = epno_params.networks; - for (int i = 0; i < epno_params.num_networks; i++) { - nlattr *attr2 = request.attr_start(i); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN); - ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid, - ssid_list[i].flags, - ssid_list[i].auth_bit_field); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid)); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - request.attr_end(attr); - request.attr_end(data); - return result; - } - - int createTeardownRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); - if (result < 0) { - return result; - } - request.attr_end(data); - return result; - } - - int start() { - ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - ALOGI("Failed to execute ePNO setup request, result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); - 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; - } - - virtual int cancel() { - /* unregister event handler */ - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); - /* create set hotlist message with empty hotlist */ - WifiRequest request(familyId(), ifaceId()); - int result = createTeardownRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - return result; - } - - ALOGI("Successfully reset APs in current hotlist"); - return result; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - 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); - int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGI("No scan results found"); - return NL_SKIP; - } - - memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS); - - unsigned int num = len / sizeof(wifi_pno_result_t); - unsigned int i; - num = min(MAX_EPNO_NETWORKS, num); - wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data(); - for (i = 0; i < num; i++) { - if (res[i].flags == PNO_SSID_FOUND) { - memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len); - memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr)); - - mResults[i].ssid[res[i].ssid_len] = '\0'; - mResults[i].channel = res[i].channel; - mResults[i].rssi = res[i].rssi; - } - } - if (*mHandler.on_network_found) - (*mHandler.on_network_found)(id(), num, mResults); - return NL_SKIP; - } -}; - -wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, - wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) -{ - return wifi_cancel_cmd(id, iface); -} - - -///////////////////////////////////////////////////////////////////////////// - -class SignificantWifiChangeCommand : public WifiCommand -{ - typedef struct { - mac_addr bssid; // BSSID - wifi_channel channel; // channel frequency in MHz - int num_rssi; // number of rssi samples - wifi_rssi rssi[8]; // RSSI history in db - } wifi_significant_change_result_internal; - -private: - wifi_significant_change_params mParams; - wifi_significant_change_handler mHandler; - static const int MAX_RESULTS = 64; - wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; - wifi_significant_change_result *mResults[MAX_RESULTS]; -public: - SignificantWifiChangeCommand(wifi_interface_handle handle, int id, - wifi_significant_change_params params, wifi_significant_change_handler handler) - : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params), - mHandler(handler) - { } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); - if (result < 0) { - return result; - } - result = request.put_u16(GSCAN_ATTRIBUTE_NUM_AP, mParams.num_bssid); - if (result < 0) { - return result; - } - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); - - for (int i = 0; i < mParams.num_bssid; i++) { - nlattr *attr2 = request.attr_start(i); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); - if (result < 0) { - return result; - } - result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - - request.attr_end(attr); - request.attr_end(data); - - return result; - } - - int createTeardownRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); - if (result < 0) { - return result; - } - - request.attr_end(data); - return result; - } - - int start() { - ALOGD("[WIFI HAL]Set significant wifi change config"); - WifiRequest request(familyId(), ifaceId()); - - int result = createSetupRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - ALOGE("failed to set significant wifi change config %d", result); - return result; - } - - ALOGI("successfully set significant wifi change config"); - - result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); - if (result < 0) { - return result; - } - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); - - result = requestResponse(request); - if (result < 0) { - ALOGE("failed to start scan; result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); - return result; - } - - ALOGI("successfully restarted the scan"); - return result; - } - - virtual int cancel() { - /* unregister event handler */ - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); - - /* create set significant change monitor message with empty hotlist */ - WifiRequest request(familyId(), ifaceId()); - - int result = createTeardownRequest(request); - if (result < 0) { - return result; - } - - result = requestResponse(request); - if (result < 0) { - return result; - } - - ALOGI("successfully reset significant wifi change config"); - return result; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGD("[WIFI HAL]Got a significant wifi change event"); - - struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data(); - int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len == 0) { - ALOGI("No scan results found"); - return NL_SKIP; - } - - typedef struct { - uint16_t flags; - uint16_t channel; - mac_addr bssid; - s8 rssi_history[8]; - } ChangeInfo; - - int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); - ChangeInfo *ci; - if (vendor_data->nla_type == GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS) - ci = (ChangeInfo *)nla_data(vendor_data); - else - return NL_SKIP; - - for (int i = 0; i < num; i++) { - memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); - mResultsBuffer[i].channel = ci[i].channel; - mResultsBuffer[i].num_rssi = 8; - for (int j = 0; j < mResultsBuffer[i].num_rssi; j++) - mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; - mResults[i] = reinterpret_cast(&(mResultsBuffer[i])); - } - - ALOGI("Retrieved %d scan results, vendor len=%d nla_type=%d", num, len, vendor_data->nla_type); - - if (num != 0) { - (*mHandler.on_significant_change)(id(), num, mResults); - } else { - ALOGW("No significant change reported"); - } - - return NL_SKIP; - } -}; - -wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, - wifi_significant_change_params params, wifi_significant_change_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( - iface, id, params, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) -{ - return wifi_cancel_cmd(id, iface); -} - -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); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - cmd->cancel(); - cmd->releaseRef(); - return WIFI_SUCCESS; - } - return wifi_cancel_cmd(id, iface); -} - -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); - - ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - - -//////////////////////////////////////////////////////////////////////////////// - -class AnqpoConfigureCommand : public WifiCommand -{ - int num_hs; - wifi_passpoint_network *mNetworks; - wifi_passpoint_event_handler mHandler; - wifi_scan_result *mResult; -public: - AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface, - int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler) - : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list), - mHandler(handler) - { - mResult = NULL; - } - - int createRequest(WifiRequest& request, int val) { - - int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG); - result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - - struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST); - for (int i = 0; i < num_hs; i++) { - nlattr *attr2 = request.attr_start(i); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id); - if (result < 0) { - return result; - } - result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256); - if (result < 0) { - return result; - } - result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, - mNetworks[i].roamingConsortiumIds, 128); - if (result < 0) { - return result; - } - result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3); - if (result < 0) { - return result; - } - - request.attr_end(attr2); - } - - request.attr_end(attr); - request.attr_end(data); - - return WIFI_SUCCESS; - } - - int start() { - - WifiRequest request(familyId(), ifaceId()); - int result = createRequest(request, num_hs); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create request; result = %d", result); - return result; - } - - registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); - - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to set ANQPO networks; result = %d", result); - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); - return result; - } - - return result; - } - - virtual int cancel() { - - WifiRequest request(familyId(), ifaceId()); - int result = createRequest(request, 0); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to reset ANQPO networks;result = %d", result); - } - } - - unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - ALOGD("Request complete!"); - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - typedef struct { - u16 channel; /* channel of GAS protocol */ - u8 dialog_token; /* GAS dialog token */ - u8 fragment_id; /* fragment id */ - u16 status_code; /* status code on GAS completion */ - u16 data_len; /* length of data to follow */ - u8 data[1]; /* variable length specified by data_len */ - } wifi_anqp_gas_resp; - - ALOGI("ANQPO hotspot matched event!"); - - nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - unsigned int len = event.get_vendor_data_len(); - - if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { - ALOGI("No scan results found"); - return NL_SKIP; - } - mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result)); - if (!mResult) { - return NL_SKIP; - } - wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data(); - wifi_gscan_result_t *fixed = &drv_res->fixed; - convert_to_hal_result(mResult, fixed); - - byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length; - wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp; - int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len; - int networkId = *(int *)((byte *)anqp + anqp_len); - - ALOGI("%-32s\t", mResult->ssid); - - 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); - - if(*mHandler.on_passpoint_network_found) - (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp); - free(mResult); - return NL_SKIP; - } -}; - -wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, - wifi_passpoint_network *networks, wifi_passpoint_event_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - - AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler); - 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) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface) -{ - return wifi_cancel_cmd(id, iface); -} - diff --git a/wifi_hal/rtt.cpp b/wifi_hal/rtt.cpp deleted file mode 100644 index a3ecb7e..0000000 --- a/wifi_hal/rtt.cpp +++ /dev/null @@ -1,697 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "nl80211_copy.h" - -#include "sync.h" - -#define LOG_TAG "WifiHAL" - -#include -#include - -#include "wifi_hal.h" -#include "common.h" -#include "cpp_bindings.h" - -using namespace android; -#define RTT_RESULT_SIZE (sizeof(wifi_rtt_result)); - -typedef enum { - RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, - RTT_SUBCMD_CANCEL_CONFIG, - RTT_SUBCMD_GETCAPABILITY, - RTT_SUBCMD_GETAVAILCHANNEL, - RTT_SUBCMD_SET_RESPONDER, - RTT_SUBCMD_CANCEL_RESPONDER, -} RTT_SUB_COMMAND; - -typedef enum { - RTT_ATTRIBUTE_CAPABILITIES = 1, - - RTT_ATTRIBUTE_TARGET_CNT = 10, - 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; - -typedef struct strmap_entry { - int id; - String8 text; -} strmap_entry_t; - -struct dot11_rm_ie { - u8 id; - u8 len; - u8 token; - u8 mode; - u8 type; -} __attribute__ ((packed)); - -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_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ -#define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */ - -static const strmap_entry_t err_info[] = { - {RTT_STATUS_SUCCESS, String8("Success")}, - {RTT_STATUS_FAILURE, String8("Failure")}, - {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")}, - {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")}, - {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")}, - {RTT_STATUS_FAIL_REJECTED, String8("Rejected")}, - {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")}, - {RTT_STATUS_FAIL_SCHEDULE, String8("schedule failed")}, - {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")}, - {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")}, - {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")}, - {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")}, - {RTT_STATUS_ABORTED, String8("aborted")} -}; - -static const char* get_err_info(int status) -{ - int i; - const strmap_entry_t *p_entry; - int num_entries = sizeof(err_info)/ sizeof(err_info[0]); - /* scan thru the table till end */ - p_entry = err_info; - for (i = 0; i < (int) num_entries; i++) - { - if (p_entry->id == status) - return p_entry->text; - p_entry++; /* next entry */ - } - return "unknown error"; /* not found */ -} - -class GetRttCapabilitiesCommand : public WifiCommand -{ - wifi_rtt_capabilities *mCapabilities; -public: - GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites) - : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites) - { - memset(mCapabilities, 0, sizeof(*mCapabilities)); - } - - virtual int create() { - ALOGD("[WIFI HAL]Creating message to get Rtt capablities; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY); - if (ret < 0) { - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGD("In GetRttCapabilitiesCommand::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(); - int wiphy_id = reply.get_u32(NL80211_ATTR_WIPHY); - int if_id = reply.get_u32(NL80211_ATTR_IFINDEX); - - struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - void *payload = NULL; - if(vendor_data->nla_type == RTT_ATTRIBUTE_CAPABILITIES) { - payload = nla_data(vendor_data); - len -= NLA_HDRLEN; - } - - ALOGD("wiphy_id=%d, if_id=%d, Id=%0x, subcmd=%d, len=%d, expected len=%d", wiphy_id, if_id, id, subcmd, len, - sizeof(*mCapabilities)); - if (payload) - memcpy(mCapabilities, payload, min(len, (int) sizeof(*mCapabilities))); - - ALOGI("RTT capability: %d, %d, %d, %d, %d, %d", - mCapabilities->rtt_one_sided_supported, mCapabilities->rtt_ftm_supported, - mCapabilities->lci_support, mCapabilities->lcr_support, - mCapabilities->preamble_support, mCapabilities->bw_support); - - return NL_OK; - } -}; - - -class GetRttResponderInfoCommand : public WifiCommand -{ - wifi_rtt_responder* mResponderInfo; -public: - GetRttResponderInfoCommand(wifi_interface_handle iface, wifi_rtt_responder *responderInfo) - : WifiCommand("GetRttResponderInfoCommand", iface, 0), mResponderInfo(responderInfo) - { - memset(mResponderInfo, 0 , sizeof(*mResponderInfo)); - - } - - virtual int create() { - ALOGD("Creating message to get responder info ; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETAVAILCHANNEL); - if (ret < 0) { - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGD("In GetRttResponderInfoCommand::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(); - - void *data = reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - - ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, - sizeof(*mResponderInfo)); - - memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo))); - - return NL_OK; - } -}; - - -class EnableResponderCommand : public WifiCommand -{ - wifi_channel_info mChannelInfo; - unsigned m_max_duration_sec; - wifi_rtt_responder* mResponderInfo; -public: - EnableResponderCommand(wifi_interface_handle iface, int id, wifi_channel_info channel_hint, - unsigned max_duration_seconds, wifi_rtt_responder *responderInfo) - : WifiCommand("EnableResponderCommand", iface, 0), mChannelInfo(channel_hint), - m_max_duration_sec(max_duration_seconds), mResponderInfo(responderInfo) - { - memset(mResponderInfo, 0, sizeof(*mResponderInfo)); - } - - virtual int create() { - ALOGD("Creating message to set responder ; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_SET_RESPONDER); - if (ret < 0) { - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - - ALOGD("In EnableResponderCommand::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(); - - void *data = reply.get_vendor_data(); - int len = reply.get_vendor_data_len(); - - ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, - sizeof(*mResponderInfo)); - - memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo))); - - return NL_OK; - } -}; - - -class CancelResponderCommand : public WifiCommand -{ - -public: - CancelResponderCommand(wifi_interface_handle iface, int id) - : WifiCommand("CancelResponderCommand", iface, 0)/*, mChannelInfo(channel)*/ - { - - } - - virtual int create() { - ALOGD("Creating message to cancel responder ; iface = %d", mIfaceInfo->id); - - int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_RESPONDER); - if (ret < 0) { - return ret; - } - - return ret; - } - -protected: - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - -}; - - -class RttCommand : public WifiCommand -{ - unsigned numRttParams; - int mCompleted; - int currentIdx; - int totalCnt; - static const int MAX_RESULTS = 1024; - wifi_rtt_result *rttResults[MAX_RESULTS]; - wifi_rtt_config *rttParams; - wifi_rtt_event_handler rttHandler; -public: - RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config, - wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) - : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config), - rttHandler(handler) - { - memset(rttResults, 0, sizeof(rttResults)); - currentIdx = 0; - mCompleted = 0; - totalCnt = 0; - } - - RttCommand(wifi_interface_handle iface, int id) - : WifiCommand("RttCommand", iface, id) - { - currentIdx = 0; - mCompleted = 0; - totalCnt = 0; - numRttParams = 0; - } - - int createSetupRequest(WifiRequest& request) { - int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams); - if (result < 0) { - return result; - } - nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO); - for (unsigned i = 0; i < numRttParams; i++) { - nlattr *attr2 = request.attr_start(i); - if (attr2 == NULL) { - return WIFI_ERROR_OUT_OF_MEMORY; - } - - result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer); - if (result < 0) { - return result; - } - - result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel, - sizeof(wifi_channel_info)); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST, rttParams[i].num_burst); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, - rttParams[i].num_frames_per_burst); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, - rttParams[i].num_retries_per_rtt_frame); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, - rttParams[i].num_retries_per_ftmr); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD, - rttParams[i].burst_period); - if (result < 0) { - return result; - } - - result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION, - rttParams[i].burst_duration); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI, - rttParams[i].LCI_request); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR, - rttParams[i].LCR_request); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW, - rttParams[i].bw); - if (result < 0) { - return result; - } - - result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE, - rttParams[i].preamble); - if (result < 0) { - return result; - } - request.attr_end(attr2); - } - - request.attr_end(rtt_config); - request.attr_end(data); - return WIFI_SUCCESS; - } - - int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) { - int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG); - if (result < 0) { - return result; - } - - nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); - request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices); - for(unsigned i = 0; i < num_devices; i++) { - result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]); - if (result < 0) { - return result; - } - } - request.attr_end(data); - return result; - } - int start() { - ALOGD("Setting RTT configuration"); - WifiRequest request(familyId(), ifaceId()); - int result = createSetupRequest(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create setup request; result = %d", result); - return result; - } - - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to configure RTT setup; result = %d", result); - return result; - } - - registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); - ALOGI("Successfully started RTT operation"); - return result; - } - - virtual int cancel() { - ALOGD("Stopping RTT"); - - WifiRequest request(familyId(), ifaceId()); - int result = createTeardownRequest(request, 0, NULL); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create stop request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to stop scan; result = %d", result); - } - } - - unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); - return WIFI_SUCCESS; - } - - int cancel_specific(unsigned num_devices, mac_addr addr[]) { - ALOGE("Stopping RTT"); - - WifiRequest request(familyId(), ifaceId()); - int result = createTeardownRequest(request, num_devices, addr); - if (result != WIFI_SUCCESS) { - ALOGE("failed to create stop request; result = %d", result); - } else { - result = requestResponse(request); - if (result != WIFI_SUCCESS) { - ALOGE("failed to stop RTT; result = %d", result); - } - } - - unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); - return WIFI_SUCCESS; - } - - virtual int handleResponse(WifiEvent& reply) { - /* Nothing to do on response! */ - return NL_SKIP; - } - - virtual int handleEvent(WifiEvent& event) { - ALOGI("Got an RTT event"); - nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); - int len = event.get_vendor_data_len(); - if (vendor_data == NULL || len == 0) { - ALOGI("No rtt results found"); - } - for (nl_iterator it(vendor_data); it.has_next(); it.next()) { - if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) { - mCompleted = it.get_u32(); - ALOGI("retrieved completed flag : %d\n", mCompleted); - } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) { - int result_cnt = 0; - mac_addr bssid; - for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { - if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) { - memcpy(bssid, it2.get_data(), sizeof(mac_addr)); - ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n", - bssid[0], - bssid[1], - bssid[2], - bssid[3], - bssid[4], - bssid[5]); - } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) { - result_cnt = it2.get_u32(); - ALOGI("retrieved result_cnt : %d\n", result_cnt); - } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) { - int result_len = it2.get_len(); - rttResults[currentIdx] = (wifi_rtt_result *)malloc(it2.get_len()); - wifi_rtt_result *rtt_result = rttResults[currentIdx]; - if (rtt_result == NULL) { - mCompleted = 1; - ALOGE("failed to allocate the wifi_rtt_result\n"); - break; - } - 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->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) && - (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) { - rtt_result->LCR = (wifi_information_element *)ele_2; - } - } - } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){ - rtt_result->LCR = (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) && - (ele_2->type == DOT11_MEASURE_TYPE_LCI)) { - rtt_result->LCI = (wifi_information_element *)ele_2; - } - } - } - } - } - 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", - 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, - rtt_result->burst_duration, rtt_result->negotiated_burst_num); - currentIdx++; - } - } - } - - } - if (mCompleted) { - unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); - (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults); - for (int i = 0; i < currentIdx; i++) { - free(rttResults[i]); - rttResults[i] = NULL; - } - totalCnt = currentIdx = 0; - WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id()); - if (cmd) - cmd->releaseRef(); - } - return NL_SKIP; - } -}; - - -/* API to request RTT measurement */ -wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, - unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) -{ - wifi_handle handle = getWifiHandle(iface); - 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); - if (result != WIFI_SUCCESS) { - cmd->releaseRef(); - return result; - } - result = (wifi_error)cmd->start(); - if (result != WIFI_SUCCESS) { - wifi_unregister_cmd(handle, id); - cmd->releaseRef(); - return result; - } - return result; -} - -/* API to cancel RTT measurements */ -wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, - unsigned num_devices, mac_addr addr[]) -{ - wifi_handle handle = getWifiHandle(iface); - RttCommand *cmd = new RttCommand(iface, id); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - cmd->cancel_specific(num_devices, addr); - cmd->releaseRef(); - return WIFI_SUCCESS; -} - -/* API to get RTT capability */ -wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, - wifi_rtt_capabilities *capabilities) -{ - GetRttCapabilitiesCommand command(iface, capabilities); - return (wifi_error) command.requestResponse(); -} - -/* API to get the responder information */ -wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface, - wifi_rtt_responder* responderInfo) -{ - GetRttResponderInfoCommand command(iface, responderInfo); - return (wifi_error) command.requestResponse(); - -} - -/** - * Enable RTT responder mode. - * channel_hint - hint of the channel information where RTT responder should be enabled on. - * max_duration_seconds - timeout of responder mode. - * wifi_rtt_responder - information for RTT responder e.g. channel used and preamble supported. - */ -wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface, - wifi_channel_info channel_hint, unsigned max_duration_seconds, - wifi_rtt_responder* responderInfo) -{ - EnableResponderCommand command(iface, id, channel_hint, max_duration_seconds, responderInfo); - return (wifi_error) command.requestResponse(); -} - -/** - * Disable RTT responder mode. - */ -wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface) -{ - CancelResponderCommand command(iface, id); - return (wifi_error) command.requestResponse(); -} - diff --git a/wifi_hal/wifi_hal.cpp b/wifi_hal/wifi_hal.cpp index e93dbb2..86ed423 100644 --- a/wifi_hal/wifi_hal.cpp +++ b/wifi_hal/wifi_hal.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -33,6 +35,24 @@ #include "cpp_bindings.h" #include "cutils/properties.h" +template +struct DummyFunction; + +template +struct DummyFunction { + static constexpr R invoke(Args...) { return WIFI_SUCCESS; } +}; + +template +struct DummyFunction { + static constexpr void invoke(Args...) { } +}; + +template +void populateDummyFor(T& val) { + val = &DummyFunction::invoke; +} + /* 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 @@ -44,7 +64,6 @@ #define WIFI_HAL_CMD_SOCK_PORT 644 #define WIFI_HAL_EVENT_SOCK_PORT 645 -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); @@ -54,34 +73,18 @@ static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_ iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh); static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface); -static wifi_error wifi_reset_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface); static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt); static wifi_error wifi_get_packet_filter_capabilities_dummy( wifi_interface_handle handle, u32 *version, u32 *max_len); -static wifi_error wifi_configure_nd_offload_dummy(wifi_interface_handle iface, u8 enable); -static wifi_error wifi_get_firmware_version_dummy( - wifi_interface_handle iface, char *buffer, int buffer_size); -static wifi_error wifi_get_driver_version_dummy( - wifi_interface_handle iface, char *buffer, int buffer_size); -static wifi_error wifi_get_ring_data_dummy(wifi_interface_handle iface, char *ring_name); static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface, u32 *num_rings, wifi_ring_buffer_status *status); static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_handle iface, unsigned int *support); -static wifi_error wifi_start_logging_dummy(wifi_interface_handle iface, u32 verbose_level, - u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name); -static wifi_error wifi_start_pkt_fate_monitoring_dummy(wifi_interface_handle iface); static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates); static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates); -static wifi_error wifi_get_driver_memory_dump_dummy(wifi_interface_handle iface, - wifi_driver_memory_dump_callbacks callbacks); -static wifi_error wifi_set_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface, - wifi_ring_buffer_data_handler handler); -static wifi_error wifi_set_scanning_mac_oui_dummy(wifi_interface_handle handle, oui scan_oui); - /* Initialize/Cleanup */ @@ -122,56 +125,40 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) fn->wifi_cleanup = wifi_cleanup; fn->wifi_event_loop = wifi_event_loop; fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; - fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; - fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui_dummy; fn->wifi_get_ifaces = wifi_get_ifaces; fn->wifi_get_iface_name = wifi_get_iface_name; - fn->wifi_start_gscan = wifi_start_gscan; - fn->wifi_stop_gscan = wifi_stop_gscan; - fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; - fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; - fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; - fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; - fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; - /*fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; - fn->wifi_get_link_stats = wifi_get_link_stats; - fn->wifi_set_link_stats = wifi_set_link_stats; - fn->wifi_clear_link_stats = wifi_clear_link_stats;*/ - fn->wifi_get_valid_channels = wifi_get_valid_channels; - fn->wifi_rtt_range_request = wifi_rtt_range_request; - fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; - fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; - /*fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info; - fn->wifi_enable_responder = wifi_enable_responder; - fn->wifi_disable_responder = wifi_disable_responder; - fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;*/ - fn->wifi_start_logging = wifi_start_logging_dummy; - fn->wifi_set_epno_list = wifi_set_epno_list; - fn->wifi_reset_epno_list = wifi_reset_epno_list; fn->wifi_set_country_code = wifi_set_country_code; - /*fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;*/ - fn->wifi_set_log_handler = wifi_set_log_handler_dummy; - fn->wifi_reset_log_handler = wifi_reset_log_handler_dummy; - /*fn->wifi_set_alert_handler = wifi_set_alert_handler; - fn->wifi_reset_alert_handler = wifi_reset_alert_handler;*/ - fn->wifi_get_firmware_version = wifi_get_firmware_version_dummy; - fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_dummy; - fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_dummy; - fn->wifi_get_ring_data = wifi_get_ring_data_dummy; - fn->wifi_get_driver_version = wifi_get_driver_version_dummy; + fn->wifi_get_firmware_version = wifi_get_firmware_version; + fn->wifi_get_driver_version = wifi_get_driver_version; fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring; fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring; - fn->wifi_configure_nd_offload = wifi_configure_nd_offload_dummy; fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet; fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet; - fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring_dummy; + fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities; + fn->wifi_configure_roaming = wifi_configure_roaming; + fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming; + fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario; + fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario; + fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; + fn->wifi_get_valid_channels = wifi_get_valid_channels; + + fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_dummy; + fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_dummy; fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates_dummy; fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates_dummy; fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_dummy; - - fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump_dummy; fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats_dummy; - fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_dummy; + + populateDummyFor(fn->wifi_wait_for_driver_ready); + populateDummyFor(fn->wifi_set_nodfs_flag); + populateDummyFor(fn->wifi_set_log_handler); + populateDummyFor(fn->wifi_reset_log_handler); + populateDummyFor(fn->wifi_configure_nd_offload); + populateDummyFor(fn->wifi_start_pkt_fate_monitoring); + populateDummyFor(fn->wifi_get_driver_memory_dump); + populateDummyFor(fn->wifi_get_ring_data); + populateDummyFor(fn->wifi_start_logging); + populateDummyFor(fn->wifi_get_gscan_capabilities); return WIFI_SUCCESS; } @@ -331,6 +318,13 @@ static void internal_cleaned_up_handler(wifi_handle handle) info->event_sock = NULL; } + if (info->interfaces) { + int i = 0; + for (; i < info->num_interfaces; i++) + free(info->interfaces[i]); + free(info->interfaces); + } + (*cleaned_up_handler)(handle); pthread_mutex_destroy(&info->cb_lock); free(info); @@ -503,8 +497,6 @@ static int internal_valid_message_handler(nl_msg *msg, void *arg) ALOGV("event received %s", event.get_cmdString()); } - bool dispatched = false; - pthread_mutex_lock(&info->cb_lock); for (int i = 0; i < info->num_event_cb; i++) { @@ -578,7 +570,6 @@ public: // ALOGD("handling reponse in %s", __func__); struct nlattr **tb = reply.attributes(); - struct genlmsghdr *gnlh = reply.header(); struct nlattr *mcgrp = NULL; int i; @@ -771,6 +762,114 @@ public: } }; +class ConfigRoamingCommand : public WifiCommand +{ +private: + wifi_roaming_config *mConfig; + +public: + ConfigRoamingCommand(wifi_interface_handle handle, wifi_roaming_config *config) + : WifiCommand("ConfigRoamingCommand", handle, 0) + { + mConfig = config; + } + + int createRequest(WifiRequest& request, int subcmd, wifi_roaming_config *config) { + int result = request.create(GOOGLE_OUI, subcmd); + if (result < 0) { + return result; + } + + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, config->num_blacklist_bssid); + if (result < 0) { + return result; + } + + mac_addr *bssid_list = config->blacklist_bssid; + for (u32 i = 0; i < config->num_blacklist_bssid; i++) { + result = request.put_addr(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, bssid_list[i]); + ALOGI("Blacklist BSSID[%d] " MACSTR, i, MAC2STR(bssid_list[i])); + if (result < 0) { + return result; + } + } + + result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, config->num_whitelist_ssid); + if (result < 0) { + return result; + } + + char ssid[MAX_SSID_LENGTH + 1]; + ssid_t *ssid_list = config->whitelist_ssid; + for (u32 i = 0; i < config->num_whitelist_ssid; i++) { + memcpy(ssid, ssid_list[i].ssid_str, ssid_list[i].length); + ssid[ssid_list[i].length] = '\0'; + result = request.put( + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, ssid, ssid_list[i].length + 1); + ALOGI("Whitelist ssid[%d] : %s", i, ssid); + if (result < 0) { + return result; + } + } + + request.attr_end(data); + return WIFI_SUCCESS; + } + + int start() { + ALOGD("[WIFI HAL] Configure roaming"); + WifiRequest request(familyId(), ifaceId()); + int result = createRequest(request, WIFI_SUBCMD_CONFIG_ROAMING, mConfig); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to create request, result=%d", result); + return result; + } + + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("[WIFI HAL]Failed to configure roaming, result=%d", result); + } + + return result; + } + +protected: + virtual int handleResponse(WifiEvent& reply) { + ALOGD("ConfigRoamingCommand complete!"); + /* Nothing to do on response! */ + return NL_SKIP; + } +}; + +class EnableRoamingCommand : public WifiCommand { +private: + fw_roaming_state_t mState; +public: + EnableRoamingCommand(wifi_interface_handle handle, fw_roaming_state_t state) + : WifiCommand("EnableRoamingCommand", handle, 0) { + mState = state; + } + virtual int create() { + int ret; + + ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_ENABLE_ROAMING); + 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(WIFI_ATTRIBUTE_ROAMING_STATE, mState); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + return WIFI_SUCCESS; + } +}; + class GetFeatureSetCommand : public WifiCommand { private: @@ -797,8 +896,8 @@ public: if(feature_type == WIFI_ATTRIBUTE_FEATURE_SET) { ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET); - } else if (feature_type == WIFI_ATTRIBUTE_NUM_FEATURE_SET) { - ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX); + } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES) { + ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_ROAMING_CAPABILITIES); } else { ALOGE("Unknown feature type %d", feature_type); return -1; @@ -814,7 +913,7 @@ public: protected: virtual int handleResponse(WifiEvent& reply) { - ALOGD("In GetFeatureSetCommand::handleResponse"); + ALOGD("In GetFeatureSetCommand::handleResponse for %d", feature_type); if (reply.get_cmd() != NL80211_CMD_VENDOR) { ALOGD("Ignore reply with cmd 0x%x", reply.get_cmd()); @@ -839,30 +938,24 @@ protected: return NL_SKIP; } memcpy(fset, data, min(len, (int) sizeof(*fset))); - } - else if (feature_type == WIFI_ATTRIBUTE_NUM_FEATURE_SET) { - int num_features_set = 0; - int i = 0; - + ALOGI("feature_set=0x%x", *fset); + } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES){ if(!feature_matrix || !fm_size) { ALOGE("feature_set pointer is not set"); return NL_SKIP; } + *fm_size = set_size_max; // black and white + int i = 0; + u32 max[2] = {MAX_BLACKLIST_BSSID, MAX_WHITELIST_SSID}; for (nl_iterator it(vendor_data); it.has_next(); it.next()) { - if (it.get_type() == WIFI_ATTRIBUTE_NUM_FEATURE_SET) { - num_features_set = it.get_u32(); - ALOGI("Get feature list with %d concurrent sets", num_features_set); - if(set_size_max && (num_features_set > set_size_max)) - num_features_set = set_size_max; - *fm_size = num_features_set; - } else if ((it.get_type() == WIFI_ATTRIBUTE_FEATURE_SET) && - i < num_features_set) { - feature_matrix[i] = it.get_u32(); + if (it.get_type() == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES && i < set_size_max) { + feature_matrix[i] = it.get_u32() > max[i] ? max[i] : it.get_u32(); + ALOGI("feature_matrix %d: %d", i, feature_matrix[i]); i++; } else { - ALOGW("Ignore invalid attribute type = %d, size = %d", - it.get_type(), it.get_len()); + ALOGW("Ignore invalid attribute type = %d, idx = %d", + it.get_type(), i); } } } @@ -872,6 +965,147 @@ protected: }; +class SelectTxPowerCommand : public WifiCommand { +private: + int mScenario; +public: + SelectTxPowerCommand(wifi_interface_handle handle, int scenario) + : WifiCommand("SelectTxPowerCommand", handle, 0) { + mScenario = scenario; + } + virtual int create() { + int ret; + + ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO); + 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(WIFI_ATTRIBUTE_TX_POWER_SCENARIO, mScenario); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + return WIFI_SUCCESS; + } +}; + +class SetScanMacOuiCommand : public WifiCommand { +private: + const byte *mScanMacOui; +public: + SetScanMacOuiCommand(wifi_interface_handle handle, const oui scan_oui) + : WifiCommand("SetScanMacOuiCommand", handle, 0), mScanMacOui(scan_oui) { + } + virtual int create() { + ALOGI("Set scan mac oui"); + int ret; + + ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI); + 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(WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, (void *)mScanMacOui, sizeof(oui)); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + return WIFI_SUCCESS; + } +}; + +class GetChannelListCommand : public WifiCommand +{ +private: + wifi_channel *mChannels; + int mMaxChannels; + int *mNumOfChannel; + int mBand; + +public: + GetChannelListCommand(wifi_interface_handle handle, int band, int max_channels, + wifi_channel *channels, int *num_channels) + : WifiCommand("GetChannelListCommand", handle, 0) + { + mBand = band; + mMaxChannels = max_channels; + mChannels = channels; + mNumOfChannel = num_channels; + memset(mChannels, 0, sizeof(wifi_channel) * mMaxChannels); + } + + virtual int create() { + ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id); + + int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CHANNEL_LIST); + if (ret < 0) { + return ret; + } + + ALOGI("In GetChannelList::mBand=%d", mBand); + + nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); + ret = mMsg.put_u32(WIFI_ATTRIBUTE_BAND, mBand); + if (ret < 0) { + return ret; + } + + mMsg.attr_end(data); + return ret; + } + +protected: + virtual int handleResponse(WifiEvent& reply) { + + ALOGV("In GetChannelList::handleResponse"); + + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGE("Ignore reply with cmd 0x%x", reply.get_cmd()); + return NL_SKIP; + } + + int vendor_id = reply.get_vendor_id(); + int subcmd = reply.get_vendor_subcmd(); + ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd); + + nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + if (vendor == NULL || len == 0) { + ALOGE("No vendor data in GetChannelList response, ignore it"); + return NL_SKIP; + } + + int num_channels = 0; + for (nl_iterator it(vendor); it.has_next(); it.next()) { + if (it.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS) { + num_channels = it.get_u32(); + ALOGI("Get channel list with %d channels", num_channels); + if (num_channels > mMaxChannels) + num_channels = mMaxChannels; + *mNumOfChannel = num_channels; + } else if (it.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST && num_channels) { + memcpy(mChannels, it.get_data(), sizeof(wifi_channel) * num_channels); + } else { + ALOGW("Ignore invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + + ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels, *(mChannels + 1)); + + return NL_OK; + } +}; + +///////////////////////////////////////////////////////////////////////// + static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) { GetMulticastIdCommand cmd(handle, name, group); @@ -882,11 +1116,9 @@ static int wifi_get_multicast_id(wifi_handle handle, const char *name, const cha return cmd.getId(); } -///////////////////////////////////////////////////////////////////////// - static bool is_wifi_interface(const char *name) { - if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { + if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0 && strncmp(name, "ap", 2) != 0) { /* Not a wifi interface; ignore it */ return false; } else { @@ -936,6 +1168,7 @@ wifi_error wifi_init_interfaces(wifi_handle handle) closedir(d); return WIFI_ERROR_OUT_OF_MEMORY; } + memset(info->interfaces, 0, sizeof(interface_info *) * n); int i = 0; while ((de = readdir(d))) { @@ -978,41 +1211,10 @@ wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *pset) { -#if 0 - GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_FEATURE_SET, set, NULL, NULL, 1); + GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_FEATURE_SET, pset, NULL, NULL, 1); return (wifi_error)command.requestResponse(); -#else - feature_set set = 0; - char prop_buf[PROPERTY_VALUE_MAX]; - - property_get("ro.wlan.mtk.wifi.5g", prop_buf, NULL); - if (!strcmp(prop_buf, "1")) - set |= WIFI_FEATURE_INFRA_5G; - - set |= WIFI_FEATURE_P2P; - set |= WIFI_FEATURE_SOFT_AP; - set |= WIFI_FEATURE_TDLS; - -#ifdef CONFIG_PNO_SUPPORT - set |= WIFI_FEATURE_PNO; -#endif - - - memcpy(pset, &set, sizeof(feature_set)); - - ALOGI("[WIFI HAL]wifi_get_supported_feature_set: handle=%p, feature_set=0x%x", handle, *pset); - return WIFI_SUCCESS; -#endif } -wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, - feature_set set[], int *set_size) -{ - GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_NUM_FEATURE_SET, NULL, set, set_size, set_size_max); - return (wifi_error)command.requestResponse(); -} - - wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code) { SetCountryCodeCommand command(handle, country_code); @@ -1047,7 +1249,6 @@ static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_h 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); NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); @@ -1058,19 +1259,108 @@ static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_h return wifi_cancel_cmd(id, iface); } -///////////////////////////////////////////////////////////////////////////// +wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle, + wifi_roaming_capabilities *caps) { + ALOGI("Get roaming capabilities"); + + wifi_handle wifiHandle = getWifiHandle(handle); + hal_info *info = getHalInfo(wifiHandle); + + if (!caps) { + ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__); + return WIFI_ERROR_INVALID_ARGS; + } + + if (!info) { + ALOGE("%s: hal_info is NULL", __FUNCTION__); + return WIFI_ERROR_INVALID_ARGS; + } + + // first time to get roaming cap + if (info->roaming_capa.max_blacklist_size == 0 && info->roaming_capa.max_whitelist_size == 0) { + int size = 0; + GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, NULL, + (feature_set*) caps, &size, 2); + wifi_error ret = (wifi_error)command.requestResponse(); + if (ret == WIFI_SUCCESS) { + info->roaming_capa.max_blacklist_size = caps->max_blacklist_size; + info->roaming_capa.max_whitelist_size = caps->max_whitelist_size; + } + return ret; + } else { + memcpy(caps, &info->roaming_capa, sizeof(wifi_roaming_capabilities)); + } -static wifi_error wifi_set_scanning_mac_oui_dummy(wifi_interface_handle handle, oui scan_oui) -{ return WIFI_SUCCESS; } -static wifi_error wifi_set_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface, - wifi_ring_buffer_data_handler handler) +wifi_error wifi_configure_roaming(wifi_interface_handle handle, + wifi_roaming_config *roaming_config) { + ALOGI("Configure roaming"); + wifi_handle wifiHandle = getWifiHandle(handle); + hal_info *info = getHalInfo(wifiHandle); + if (!roaming_config) { + ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__); + return WIFI_ERROR_INVALID_ARGS; + } + + /* Set bssid blacklist */ + if (roaming_config->num_blacklist_bssid > info->roaming_capa.max_blacklist_size) { + ALOGE("%s: Number of blacklist bssids(%d) provided is more than maximum blacklist bssids(%d)" + " supported", __FUNCTION__, roaming_config->num_blacklist_bssid, + info->roaming_capa.max_blacklist_size); + return WIFI_ERROR_NOT_SUPPORTED; + } + + /* Set ssid whitelist */ + if (roaming_config->num_whitelist_ssid > info->roaming_capa.max_whitelist_size) { + ALOGE("%s: Number of whitelist ssid(%d) provided is more than maximum whitelist ssids(%d) " + "supported", __FUNCTION__, roaming_config->num_whitelist_ssid, + info->roaming_capa.max_whitelist_size); + return WIFI_ERROR_NOT_SUPPORTED; + } + + ConfigRoamingCommand command(handle, roaming_config); + return (wifi_error)command.start(); +} + +wifi_error wifi_enable_firmware_roaming(wifi_interface_handle handle, + fw_roaming_state_t state) { + ALOGI("Enable roaming %d", state); + EnableRoamingCommand command(handle, state); + return (wifi_error) command.requestResponse(); +} + +wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, + wifi_power_scenario scenario) { - return WIFI_SUCCESS; + ALOGI("Select tx power scenario %d", scenario); + SelectTxPowerCommand command(handle, scenario); + return (wifi_error) command.requestResponse(); } +wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle) +{ + ALOGI("Reset tx power scenario"); + SelectTxPowerCommand command(handle, -1); + return (wifi_error) command.requestResponse(); +} + +wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) +{ + SetScanMacOuiCommand command(handle, scan_oui); + return (wifi_error) command.requestResponse(); +} + +wifi_error wifi_get_valid_channels(wifi_interface_handle handle, + int band, int max_channels, wifi_channel *channels, int *num_channels) +{ + GetChannelListCommand command(handle, band, max_channels, channels, num_channels); + return (wifi_error) command.requestResponse(); +} + +///////////////////////////////////////////////////////////////////////////// + static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) { @@ -1092,16 +1382,6 @@ static wifi_error wifi_get_packet_filter_capabilities_dummy(wifi_interface_handl return WIFI_ERROR_INVALID_ARGS; } -static wifi_error wifi_configure_nd_offload_dummy(wifi_interface_handle iface, u8 enable) -{ - return WIFI_SUCCESS; -} - -static wifi_error wifi_start_pkt_fate_monitoring_dummy(wifi_interface_handle iface) -{ - return WIFI_SUCCESS; -} - static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates) { @@ -1122,44 +1402,6 @@ static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle, return WIFI_ERROR_INVALID_ARGS; } -static wifi_error wifi_get_driver_memory_dump_dummy(wifi_interface_handle iface, - wifi_driver_memory_dump_callbacks callbacks) -{ - return WIFI_SUCCESS; -} - -static wifi_error wifi_reset_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface) -{ - return WIFI_SUCCESS; -} - -static wifi_error wifi_get_firmware_version_dummy(wifi_interface_handle iface, char *buffer, - int buffer_size) -{ - if (buffer && buffer_size > 0) { - strncpy(buffer, "0", buffer_size); - return WIFI_SUCCESS; - } - return WIFI_ERROR_INVALID_ARGS; -} - -static wifi_error wifi_get_driver_version_dummy(wifi_interface_handle iface, - char *buffer, int buffer_size) -{ - if (buffer && buffer_size > 0) { - strncpy(buffer, "0", buffer_size); - return WIFI_SUCCESS; - } - return WIFI_ERROR_INVALID_ARGS; -} - -static wifi_error wifi_get_ring_data_dummy(wifi_interface_handle iface, char *ring_name) -{ - if (ring_name) { - return WIFI_SUCCESS; - } - return WIFI_ERROR_INVALID_ARGS; -} static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface, u32 *num_rings, wifi_ring_buffer_status *status) @@ -1167,7 +1409,7 @@ static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface if (num_rings && status) { *num_rings = 1; memset(status, 0, sizeof(*status)); - strncpy((char*)status->name, "dummy", sizeof(*status->name)); + strncpy((char*)status->name, "dummy", sizeof(status->name)); return WIFI_SUCCESS; } return WIFI_ERROR_INVALID_ARGS; @@ -1182,13 +1424,3 @@ static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_han } return WIFI_ERROR_INVALID_ARGS; } - -static wifi_error wifi_start_logging_dummy(wifi_interface_handle iface, u32 verbose_level, - u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name) -{ - if (ring_name) { - return WIFI_SUCCESS; - } - return WIFI_ERROR_INVALID_ARGS; -} - diff --git a/wifi_hal/wifi_logger.cpp b/wifi_hal/wifi_logger.cpp new file mode 100644 index 0000000..aadd585 --- /dev/null +++ b/wifi_hal/wifi_logger.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nl80211_copy.h" +#include "sync.h" + +#define LOG_TAG "WifiHAL" + +#include + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" + +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER, +}; + +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER, +}; + +enum GetCmdType { + GET_FW_VER, + GET_DRV_VER, +}; + +/////////////////////////////////////////////////////////////////////////////// +class DebugCommand : public WifiCommand +{ + char *mBuff; + int *mBuffSize; + GetCmdType mType; + +public: + + // constructor for get version + DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size, + GetCmdType cmdType) + : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType + (cmdType) + { + memset(mBuff, 0, *mBuffSize); + } + + int createRequest(WifiRequest &request) { + int result; + + nlattr *data = NULL; + switch (mType) { + case GET_FW_VER: + case GET_DRV_VER: + result = request.create(GOOGLE_OUI, LOGGER_GET_VER); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to create get drv version request; result = %d", result); + return result; + } + + data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + + // Driver expecting only attribute type, passing mbuff as data with + // length 0 to avoid undefined state + result = request.put(mType == GET_FW_VER ? + LOGGER_ATTRIBUTE_FW_VER : LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to put get drv version request; result = %d", result); + return result; + } + request.attr_end(data); + break; + default: + ALOGE("Unknown Debug command"); + result = WIFI_ERROR_UNKNOWN; + } + return result; + } + + int start() { + // ALOGD("Start debug command"); + WifiRequest request(familyId(), ifaceId()); + int result = createRequest(request); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to create debug request; result = %d", result); + return result; + } + + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to register debug response; 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; + } + + void *data = NULL; + int len = 0; + switch (mType) { + case GET_DRV_VER: + case GET_FW_VER: + data = reply.get_vendor_data(); + len = reply.get_vendor_data_len(); + + ALOGD("len = %d, expected len = %d", len, *mBuffSize); + memcpy(mBuff, data, min(len, *mBuffSize)); + if (*mBuffSize < len) + return NL_SKIP; + *mBuffSize = len; + break; + default: + ALOGW("Unknown Debug command"); + } + return NL_OK; + } + + virtual int handleEvent(WifiEvent& event) { + /* NO events! */ + return NL_SKIP; + } +}; + +wifi_error get_version(wifi_interface_handle iface, char *buffer, int *buffer_size, GetCmdType type) +{ + if (buffer && (*buffer_size > 0)) { + DebugCommand *cmd = new DebugCommand(iface, buffer, buffer_size, type); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + wifi_error result = (wifi_error)cmd->start(); + cmd->releaseRef(); + return result; + } else { + ALOGE("%s version buffer NULL", type == GET_FW_VER ? "FW" : "Driver"); + return WIFI_ERROR_INVALID_ARGS; + } +} + +/* API to collect a firmware version string */ +wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer, + int buffer_size) +{ + return get_version(iface, buffer, &buffer_size, GET_FW_VER); +} + +/* API to collect a driver version string */ +wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size) +{ + return get_version(iface, buffer, &buffer_size, GET_DRV_VER); +} diff --git a/wifi_hal/wifi_offload.cpp b/wifi_hal/wifi_offload.cpp index af25f9c..d4cfa69 100644 --- a/wifi_hal/wifi_offload.cpp +++ b/wifi_hal/wifi_offload.cpp @@ -25,8 +25,6 @@ #include "common.h" #include "cpp_bindings.h" -//using namespace android; - typedef enum { WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, WIFI_OFFLOAD_STOP_MKEEP_ALIVE, diff --git a/wpa_supplicant_8_lib/Android.mk b/wpa_supplicant_8_lib/Android.mk index 115997a..4d96f9d 100644 --- a/wpa_supplicant_8_lib/Android.mk +++ b/wpa_supplicant_8_lib/Android.mk @@ -18,6 +18,7 @@ LOCAL_PATH := $(call my-dir) ##### For Google SUPPLICANT ##### ifeq ($(MTKPATH),) $(warning build BASIC wpa_supplicant) + WPA_SUPPL_DIR = external/wpa_supplicant_8 WPA_SRC_FILE := @@ -58,7 +59,10 @@ endif ######################## include $(CLEAR_VARS) +LOCAL_SANITIZE := cfi LOCAL_MODULE := lib_driver_cmd_mt66xx +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk LOCAL_SHARED_LIBRARIES := libc libcutils LOCAL_CFLAGS := $(L_CFLAGS) LOCAL_SRC_FILES := $(WPA_SRC_FILE) diff --git a/wpa_supplicant_8_lib/mediatek_driver_cmd_nl80211.c b/wpa_supplicant_8_lib/mediatek_driver_cmd_nl80211.c index c59bcb5..f505f23 100644 --- a/wpa_supplicant_8_lib/mediatek_driver_cmd_nl80211.c +++ b/wpa_supplicant_8_lib/mediatek_driver_cmd_nl80211.c @@ -22,87 +22,1565 @@ #include "android_drv.h" #endif +#include "mediatek_driver_nl80211.h" #include "driver_i.h" +#include "p2p/p2p_i.h" + #include "eloop.h" +#define PRIV_CMD_SIZE 512 + +typedef struct android_wifi_priv_cmd { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +} android_wifi_priv_cmd; + +static int drv_errors = 0; + +static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) +{ + drv_errors++; + if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { + drv_errors = 0; + /* avoid the framework to handle HANGED */ + /* + * wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); + */ + } +} + +static int testmode_sta_statistics_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1] = {}; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_TESTMODE_STA_STATISTICS_NUM] = {}; + struct wpa_driver_sta_statistics_s *sta_statistics = (struct wpa_driver_sta_statistics_s *)arg; + unsigned char i = 0; + static struct nla_policy policy[NL80211_TESTMODE_STA_STATISTICS_NUM] = { + [NL80211_TESTMODE_STA_STATISTICS_VERSION] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_MAC] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_FLAG] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_PER] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_RSSI] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_PHY_MODE] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TX_RATE] = { .type = NLA_U16 }, + [NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT] = { .type = NLA_U32 }, + + [NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME] = { .type = NLA_U32 }, + + [NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + /* + * how many packages TX during statistics interval + */ + [NL80211_TESTMODE_STA_STATISTICS_ENQUEUE] = { .type = NLA_U32 }, + /* + * how many packages this sta TX during statistics interval + */ + [NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE] = { .type = NLA_U32 }, + + /* + * how many packages dequeue during statistics interval + */ + [NL80211_TESTMODE_STA_STATISTICS_DEQUEUE] = { .type = NLA_U32 }, + + /* + * how many packages this sta dequeue during statistics interval + */ + [NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE] = { .type = NLA_U32 }, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + [NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY] = { .type = NLA_UNSPEC }, + + [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY] = { .type = NLA_UNSPEC } + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(sinfo, NL80211_TESTMODE_STA_STATISTICS_MAX, tb[NL80211_ATTR_TESTDATA], policy)) + return NL_SKIP; + + for (i=1; i < NL80211_TESTMODE_STA_STATISTICS_NUM; i++) { + + if (!sinfo[i]) + continue; + + switch(i) { + case NL80211_TESTMODE_STA_STATISTICS_VERSION: + sta_statistics->version = nla_get_u8(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_MAC: + nla_memcpy(sta_statistics->addr, sinfo[i], ETH_ALEN); + break; + case NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE: + sta_statistics->link_score = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_FLAG: + sta_statistics->flag = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_PER: + sta_statistics->per = nla_get_u8(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_RSSI: + sta_statistics->rssi = (((int)nla_get_u8(sinfo[i]) - 220) / 2); + break; + case NL80211_TESTMODE_STA_STATISTICS_PHY_MODE: + sta_statistics->phy_mode = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TX_RATE: + sta_statistics->tx_rate = (((double)nla_get_u16(sinfo[i])) / 2); + break; + case NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT: + sta_statistics->tx_fail_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT: + sta_statistics->tx_timeout_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME: + sta_statistics->tx_avg_air_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT: + sta_statistics->tx_total_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT: + sta_statistics->tx_exc_threshold_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME: + sta_statistics->tx_avg_process_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME: + sta_statistics->tx_max_process_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME: + sta_statistics->tx_avg_hif_process_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME: + sta_statistics->tx_max_hif_process_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY: + nla_memcpy(sta_statistics->tc_buf_full_cnt, sinfo[i], sizeof(sta_statistics->tc_buf_full_cnt)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_que_len, sinfo[i], sizeof(sta_statistics->tc_que_len)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_avg_que_len, sinfo[i], sizeof(sta_statistics->tc_avg_que_len)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_cur_que_len, sinfo[i], sizeof(sta_statistics->tc_cur_que_len)); + break; + + case NL80211_TESTMODE_STA_STATISTICS_ENQUEUE: + sta_statistics->enqueue_total_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_DEQUEUE: + sta_statistics->dequeue_total_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE: + sta_statistics->enqueue_sta_total_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE: + sta_statistics->dequeue_sta_total_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT: + sta_statistics->isr_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT: + sta_statistics->isr_pass_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT: + sta_statistics->isr_task_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT: + sta_statistics->isr_ab_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT: + sta_statistics->isr_sw_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT: + sta_statistics->isr_tx_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT: + sta_statistics->isr_rx_cnt = nla_get_u32(sinfo[i]); + break; + + case NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY: + nla_memcpy(sta_statistics->dequeue_no_tc_res, sinfo[i], + sizeof(sta_statistics->dequeue_no_tc_res)); + break; + + case NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY: + nla_memcpy(sta_statistics->tc_used_res, sinfo[i], + sizeof(sta_statistics->tc_used_res)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY: + nla_memcpy(sta_statistics->tc_wanted_res, sinfo[i], + sizeof(sta_statistics->tc_wanted_res)); + break; + + case NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY: + nla_memcpy(sta_statistics->tc_back_count, sinfo[i], + sizeof(sta_statistics->tc_back_count)); + break; + + case NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY: + nla_memcpy(sta_statistics->reserved, sinfo[i], sizeof(sta_statistics->reserved)); + break; + default: + break; + } + } + + return NL_SKIP; +} + +#ifdef CONFIG_MTK_LTE_COEX +static int testmode_available_channel_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1] = {}; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = {}; + struct wpa_driver_available_chan_s *available_chans = (struct wpa_driver_available_chan_s *)arg; + static struct nla_policy chan_policy[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = { + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149] = { .type = NLA_U32 }, + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(tb_chan, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX, tb[NL80211_ATTR_TESTDATA], chan_policy)) + return NL_SKIP; + + if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1]) + available_chans->ch_2g_base1 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1]); + + if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36]) + available_chans->ch_5g_base36 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36]); + + if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52]) + available_chans->ch_5g_base52 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52]); + + if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100]) + available_chans->ch_5g_base100 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100]); + + if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149]) + available_chans->ch_5g_base149 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149]); + + return NL_SKIP; +} +#endif + +static int wpa_driver_nl80211_testmode(void *priv, const u8 *data, size_t data_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg, *cqm = NULL; + struct wpa_driver_testmode_params *params; + int index; + + msg = nlmsg_alloc(); + if (!msg) + return -1; + + wpa_printf(MSG_DEBUG, "nl80211 test mode: ifindex=%d", drv->ifindex); + + nl80211_cmd(drv, msg, 0, NL80211_CMD_TESTMODE); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT(msg, NL80211_ATTR_TESTDATA, data_len, data); + + params = (struct wpa_driver_testmode_params *)data; + + /* Mask version field */ + index = params->hdr.index & BITS(0, 23); + + switch(index) { + case 0x10: + { + struct wpa_driver_get_sta_statistics_params *sta_params = + (struct wpa_driver_get_sta_statistics_params *)data; + return send_and_recv_msgs(drv, msg, testmode_sta_statistics_handler, sta_params->buf); + } +#ifdef CONFIG_MTK_LTE_COEX + case 0x30: + { + struct wpa_driver_get_available_channel_params *chan_params = + (struct wpa_driver_get_available_channel_params *)data; + return send_and_recv_msgs(drv, msg, testmode_available_channel_handler, chan_params->buf); + } +#endif + default: + { + int ret = send_and_recv_msgs(drv, msg, NULL, NULL); + wpa_printf(MSG_EXCESSIVE, "ret=%d, nl=%p", ret, drv->global->nl); + return ret; + } + } + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} + +static int wpa_driver_nl80211_driver_sw_cmd(void *priv, int set, u32 *adr, u32 *dat) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct wpa_driver_sw_cmd_params params; + struct nl_msg *msg, *cqm = NULL; + int ret = 0; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = NL80211_TESTMODE_SW_CMD; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_sw_cmd_params); + + params.adr = *adr; + params.data = *dat; + + if (set) + params.set = 1; + else + params.set = 0; + + wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, sizeof(struct wpa_driver_sw_cmd_params)); + return 0; +} + +#ifdef CONFIG_HOTSPOT_MGR_SUPPORT +static int wpa_driver_hotspot_block_list_update(void *priv, const u8 *bssid, int blocked) +{ + struct wpa_driver_hotspot_params params; + + os_memset(¶ms, 0, sizeof(params)); + + if (bssid) + os_memcpy(params.bssid, bssid, ETH_ALEN); + + params.blocked = (u8)blocked; + + params.hdr.index = NL80211_TESTMODE_HS20; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_hotspot_params); + + return wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, + sizeof(struct wpa_driver_hotspot_params)); +} + +static int wpa_driver_sta_block(void *priv, char *cmd) +{ + u8 bssid[ETH_ALEN] = {}; + int blocked = 1; + + /* Block client device */ + if (hwaddr_aton(cmd, bssid)) { + wpa_printf(MSG_DEBUG, "STA block: invalid DEVICE ADDRESS '%s'", cmd); + return -1; + } + + wpa_printf(MSG_DEBUG, "Block STA " MACSTR, MAC2STR(bssid)); + return wpa_driver_hotspot_block_list_update(priv, bssid, blocked); +} + +static int wpa_driver_sta_unblock(void *priv, char *cmd) +{ + u8 bssid[ETH_ALEN] = {}; + int blocked = 0; + + /* Unblock client device */ + if (hwaddr_aton(cmd, bssid)) { + wpa_printf(MSG_DEBUG, "STA unblock : invalid DEVICE ADDRESS '%s'", cmd); + return -1; + } + + wpa_printf(MSG_DEBUG, "Unblock STA " MACSTR, MAC2STR(bssid)); + return wpa_driver_hotspot_block_list_update(priv, bssid, blocked); +} + +static int wpa_driver_set_max_client(void *priv, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + int len = 0; + int value = 0; + struct wpa_driver_hotspot_set_config_params params; + + os_memset(¶ms, 0, sizeof(params)); + + value = atoi(cmd); + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_max_connect value=%d\n", value); + + params.hdr.index = NL80211_TESTMODE_HS_SET_CONFIG; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_hotspot_set_config_params); + + params.index = 1; + params.value = (u32)value; + + return wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, + sizeof(struct wpa_driver_hotspot_set_config_params)); +} +#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */ + +#ifdef CONFIG_MTK_LTE_COEX +int wpa_driver_get_lte_available_channels(void *priv, struct wpa_driver_available_chan_s *buf) +{ + struct wpa_driver_get_available_channel_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = 0x30; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_get_available_channel_params); + /* buffer for return structure */ + params.buf = (u8 *)buf; + return wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, + sizeof(struct wpa_driver_get_available_channel_params)); +} + +static u8 wpa_driver_do_mtk_acs(void *priv) +{ + struct wpa_driver_available_chan_s available_chans; + u8 ch[14]; + int ch_num, i; + int wait_cnt = 0; + + do { + os_memset(&available_chans, 0, sizeof(struct wpa_driver_available_chan_s)); + wpa_driver_get_lte_available_channels(priv, &available_chans); + + if (BIT(31) & available_chans.ch_2g_base1) { + wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x", available_chans.ch_2g_base1); + break; + } else { + wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x, waiting for scan complete", + available_chans.ch_2g_base1); + wait_cnt++; + if (wait_cnt > 5) + return 0; + os_sleep(0, 1000*350); + } + } while(1); + + os_memset(ch, 0, sizeof(ch)); + ch_num = 0; + + for (i = 0; i < 14; i++) { + if (BIT(i) & available_chans.ch_2g_base1) { + ch[ch_num] = i + 1; + ch_num++; + } else + continue; + } + + wpa_printf(MSG_DEBUG, "Driver report 2G available %d channel", ch_num); + for (i = 0; i < ch_num; i++) + wpa_printf(MSG_DEBUG,"Channel %d is fine", ch[i]); + + return ch[0]; +} +#endif /* CONFIG_MTK_LTE_COEX */ + +#ifdef CONFIG_WAPI_SUPPORT +int wpa_driver_nl80211_set_wapi_key(void *priv, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, + size_t seq_len, + const u8 *key, size_t key_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg, *cqm = NULL; + struct wpa_driver_wapi_key_params params; + int ret = 0; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = NL80211_TESTMODE_WAPI; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_wapi_key_params); + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]1 %s: ", __FUNCTION__); + + if (seq_len > IW_ENCODE_SEQ_MAX_SIZE * 2) { + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]%s: Invalid seq_len %lu", + __FUNCTION__, (unsigned long)seq_len); + return -1; + } + + params.key_index = key_idx + 1; + params.key_len = key_len; + + if (addr == NULL || + os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) + params.extparams.ext_flags |= IW_ENCODE_EXT_GROUP_KEY; + if (set_tx) + params.extparams.ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; + + if (addr) + os_memcpy(params.extparams.addr, addr, ETH_ALEN); + else + os_memset(params.extparams.addr, 0xff, ETH_ALEN); + + if (key && key_len) { + os_memcpy(params.extparams.key, key, key_len); + params.extparams.key_len = key_len; + } + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]2 %s:", __FUNCTION__); + + wpa_printf(MSG_DEBUG, "%s: Set IW_ENCODE_ALG_SMS4 to ext->alg", + __FUNCTION__); + + params.extparams.alg = IW_ENCODE_ALG_SMS4; + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]3 %s: ", __FUNCTION__); + + if (seq && seq_len) + os_memcpy(params.extparams.tx_seq, seq, seq_len); + + wpa_hexdump(MSG_DEBUG, "seq", seq, seq_len); + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]4 Copy buffer %s: ", __FUNCTION__); + + wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, sizeof(struct wpa_driver_wapi_key_params)); + + return 0; +} + +/** +* wpa_driver_nl80211_send_msg - send some information to driver +* @priv: private driver interface data from init() +* @msg_in: the message sent to driver +* @msg_in_len: the length of sent message +* @msg_out: the message given back from driver +* @msg_out_len: the length of message given back from driver +* +* Returns: 0 on success, -1 on failure +* +*/ +static int wpa_driver_nl80211_send_msg(void *priv, const u8 *msg_in, int msg_in_len, + u8 *msg_out, int *msg_out_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = 0; + + if (msg_in_len > 1024) { + wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_send_msg: msg too long"); + return -1; + } + + return ret; +} +#endif /* CONFIG_WAPI_SUPPORT */ + +static inline int wpa_drv_set_test_mode(struct wpa_supplicant *wpa_s, + const u8 *buf, size_t buf_len) +{ + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, buf, buf_len); +} + + +/********************************************************************** +* OVERLAPPED functins, previous defination is in driver_nl80211.c, +* it will be modified +***********************************************************************/ + +/**********************************************************************/ +extern int wpa_config_write(const char *name, struct wpa_config *config); + +static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int ioctl_sock = -1; + struct iwreq iwr; + int ret = -1; + char buf[11]; +#ifdef MTK_TC1_FEATURE + char replace_ifname[IFNAMSIZ+1]; + + memset(replace_ifname, 0, IFNAMSIZ+1); + os_strlcpy(replace_ifname, "wlan0", os_strlen("wlan0")+1); +#endif + + ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctl_sock < 0) { + wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__); + return -1; + } + os_memset(&iwr, 0, sizeof(iwr)); +#ifdef MTK_TC1_FEATURE + // convert 'p2p0' -> 'wlan0' : + // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution. + if (os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0")) == 0) { + wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0"); + os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ ); + } else { + os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); + } +#else + os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); +#endif + snprintf(buf, sizeof(buf), "COUNTRY %s", alpha2_arg); + iwr.u.data.pointer = buf; + iwr.u.data.length = strlen(buf); + if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) { // SIOCSIWPRIV + wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s", buf); + close(ioctl_sock); + return ret; + } + else { + close(ioctl_sock); + return 0; + } + +} + +/* +* update channel list in wpa_supplicant +* if coutry code chanaged +*/ +static void wpa_driver_notify_country_change(struct wpa_global *global, char *cmd) +{ + struct wpa_supplicant *wpa_s; + + if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { + union wpa_event_data event; + + os_memset(&event, 0, sizeof(event)); + event.channel_list_changed.initiator = REGDOM_SET_BY_USER; + if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { + event.channel_list_changed.type = REGDOM_TYPE_COUNTRY; + if (os_strlen(cmd) > 9) { + event.channel_list_changed.alpha2[0] = cmd[8]; + event.channel_list_changed.alpha2[1] = cmd[9]; + } + } else { + event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; + } + // Notify all interfaces + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event); + } + } +} + +/** + * mtk_p2p_get_device - Fetch a peer entry + * @p2p: P2P module context from p2p_init() + * @addr: P2P Device Address of the peer + * Returns: Pointer to the device entry or %NULL if not found + */ +struct p2p_device *mtk_p2p_get_device(struct p2p_data *p2p, const u8 *addr) +{ + struct p2p_device *dev; + + dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { + if (memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0) + return dev; + } + return NULL; +} +/* + * we should use interface MAC address + * instead of device MAC when query + * STA statistics, as driver uses interface addr + * to do TX/RX + * In most cases, the interface addr and device addr + * should be the same + */ +u8 *wpas_p2p_get_sta_mac(struct wpa_supplicant *wpa_s, u8 *org_addr) +{ + struct p2p_data *p2p = wpa_s->global->p2p; + struct wpa_ssid *ssid = wpa_s->current_ssid; + struct p2p_device *dev = NULL; + int is_p2p_client = 0; + + if (!p2p) { + wpa_printf(MSG_DEBUG, "interface %s not support p2p", wpa_s->ifname); + return NULL; + } + + if (!ssid) { + wpa_printf(MSG_DEBUG, "P2P: ssid not connected"); + return NULL; + } + + dev = mtk_p2p_get_device(p2p, org_addr); + + if (!dev) { + wpa_printf(MSG_DEBUG, "P2P: device " MACSTR "not found", + MAC2STR(org_addr)); + return NULL; + } + + is_p2p_client = ssid->mode == WPAS_MODE_INFRA ? 1 : 0; + + if (is_p2p_client) { + if (memcmp(dev->info.p2p_device_addr, wpa_s->bssid, ETH_ALEN) && + !is_zero_ether_addr(wpa_s->bssid)) { + wpa_printf(MSG_DEBUG, "P2P: we are GC, Use interface_addr " + MACSTR "instead of " MACSTR, + MAC2STR(wpa_s->bssid), + MAC2STR(org_addr)); + return wpa_s->bssid; + } + } + + /* + * we are GO, interface_addr should be filled + * when RX NL80211_CMD_NEW_STA event + * if it is defferent between device addr and interface addr + */ + if (memcmp(dev->info.p2p_device_addr, dev->interface_addr, ETH_ALEN) && + !is_zero_ether_addr(dev->interface_addr)) { + wpa_printf(MSG_DEBUG, "P2P: we are GO, Use interface_addr " MACSTR + "instead of " MACSTR, + MAC2STR(dev->interface_addr), + MAC2STR(org_addr)); + return dev->interface_addr; + } + return NULL; +} + +/* Move GET_STA_STATISTICS to "DRIVER GET_STA_STATISTICS", implement in 3rd part lib */ +/* [ALPS00618361] [WFD Quality Enhancement] */ +int wpas_get_sta_statistics(struct wpa_supplicant *wpa_s, u8 *sta_addr, u8 *buf) +{ + struct wpa_driver_get_sta_statistics_params params; + + os_memset(¶ms, 0, sizeof(params)); + + if(sta_addr) + os_memcpy(params.addr, sta_addr, ETH_ALEN); + + wpa_printf(MSG_DEBUG, "get_sta_statistics ["MACSTR"]", MAC2STR(params.addr)); + + params.hdr.index = NL80211_TESTMODE_STATISTICS; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_get_sta_statistics_params); + + /* buffer for return structure */ + params.buf = buf; + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)¶ms, + sizeof(struct wpa_driver_get_sta_statistics_params)); +} + +/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */ +static int print_sta_statistics(struct wpa_supplicant *wpa_s, struct wpa_driver_sta_statistics_s *sta_stats, + unsigned long mask, char *buf, size_t buflen) +{ + size_t i; + int ret; + char *pos, *end; + + pos = buf; + end = buf + buflen; + + ret = os_snprintf(pos, end - pos, "sta_addr="MACSTR"\n", MAC2STR(sta_stats->addr)); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "link_score=%d\n", sta_stats->link_score); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "per=%d\n", sta_stats->per); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "rssi=%d\n", sta_stats->rssi); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "phy=0x%08X\n", sta_stats->phy_mode); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "rate=%.1f\n", sta_stats->tx_rate); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "total_cnt=%d\n", sta_stats->tx_total_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "threshold_cnt=%d\n", sta_stats->tx_exc_threshold_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "fail_cnt=%d\n", sta_stats->tx_fail_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "timeout_cnt=%d\n", sta_stats->tx_timeout_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "apt=%d\n", sta_stats->tx_avg_process_time); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "aat=%d\n", sta_stats->tx_avg_air_time); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_buf_full_cnt=%d:%d:%d:%d\n", + sta_stats->tc_buf_full_cnt[TC0_INDEX], + sta_stats->tc_buf_full_cnt[TC1_INDEX], + sta_stats->tc_buf_full_cnt[TC2_INDEX], + sta_stats->tc_buf_full_cnt[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_sta_que_len=%d:%d:%d:%d\n", + sta_stats->tc_que_len[TC0_INDEX], + sta_stats->tc_que_len[TC1_INDEX], + sta_stats->tc_que_len[TC2_INDEX], + sta_stats->tc_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_avg_que_len=%d:%d:%d:%d\n", + sta_stats->tc_avg_que_len[TC0_INDEX], + sta_stats->tc_avg_que_len[TC1_INDEX], + sta_stats->tc_avg_que_len[TC2_INDEX], + sta_stats->tc_avg_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_cur_que_len=%d:%d:%d:%d\n", + sta_stats->tc_cur_que_len[TC0_INDEX], + sta_stats->tc_cur_que_len[TC1_INDEX], + sta_stats->tc_cur_que_len[TC2_INDEX], + sta_stats->tc_cur_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "flag=0x%08X\n", sta_stats->flag); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "reserved0="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + for (i = 0; i < 16; i++) { + ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + if (((i + 1) % 4) == 0) { + ret = os_snprintf(pos, end - pos, " "); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + } + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "reserved1="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + for (i = 16; i < 32; i++) { + ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + if (((i + 1) % 4) == 0) { + ret = os_snprintf(pos, end - pos, " "); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + } + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "====\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + return pos - buf; +} + +/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */ +static void format_sta_statistics(struct wpa_driver_sta_statistics_s *s) +{ + wpa_printf(MSG_DEBUG, "NWFD: Basic info* AVG:%4d:EN:%4d:DE:%4d:SEN:%4d:SDE:%4d:HIF:%4d", + s->tx_avg_process_time, + s->enqueue_total_cnt, + s->dequeue_total_cnt, + s->enqueue_sta_total_cnt, + s->dequeue_sta_total_cnt, + s->tx_total_cnt); + + wpa_printf(MSG_DEBUG, "NWFD: Time info* TTL:%4d:AVG:%4d:MAX:%4d:HIFAVG:%4d:HIFMAX:%4d", + s->tx_total_cnt, + s->tx_avg_process_time, + s->tx_max_process_time, + s->tx_avg_hif_process_time, + s->tx_max_hif_process_time); + + wpa_printf(MSG_DEBUG, "NWFD: No TC RES* Score:%4d:EN:%4d#%4d#%4d#%4d:DE:%4d#%4d#%4d#%4d", + s->link_score, + s->tc_buf_full_cnt[TC0_INDEX], + s->tc_buf_full_cnt[TC1_INDEX], + s->tc_buf_full_cnt[TC2_INDEX], + s->tc_buf_full_cnt[TC3_INDEX], + s->dequeue_no_tc_res[TC0_INDEX], + s->dequeue_no_tc_res[TC1_INDEX], + s->dequeue_no_tc_res[TC2_INDEX], + s->dequeue_no_tc_res[TC3_INDEX]); + + wpa_printf(MSG_DEBUG, "NWFD: Irq info* T:%4d:P:%4d:TT:%4d:A:%4d:S:%4d:R:%4d:T:%4d", + s->isr_cnt, + s->isr_pass_cnt, + s->isr_task_cnt, + s->isr_ab_cnt, + s->isr_sw_cnt, + s->isr_rx_cnt, + s->isr_tx_cnt); + + /* + * TC resouce information: format: + * 1. how many TC resource wanted during statistics intervals + * 2. how many TC resource acquire successfully + * 3. how many TC resource back during statistics intervals + */ + wpa_printf(MSG_DEBUG, "NWFD: TC Res info[W:U:B]* Score:%4d:" + "#%5d:%5d:%5d#" + "#%5d:%5d:%5d#" + "#%5d:%5d:%5d#" + "#%5d:%5d:%5d#", + s->link_score, + s->tc_wanted_res[TC0_INDEX], + s->tc_used_res[TC0_INDEX], + s->tc_back_count[TC0_INDEX], + + s->tc_wanted_res[TC1_INDEX], + s->tc_used_res[TC1_INDEX], + s->tc_back_count[TC1_INDEX], + + s->tc_wanted_res[TC2_INDEX], + s->tc_used_res[TC2_INDEX], + s->tc_back_count[TC2_INDEX], + + s->tc_wanted_res[TC3_INDEX], + s->tc_used_res[TC3_INDEX], + s->tc_back_count[TC3_INDEX]); +} + +int wpa_driver_get_sta_statistics(struct wpa_supplicant *wpa_s, char *addr, + char *buf, size_t buflen) +{ + char *str = NULL; + int len = 0; + u8 sta_addr[ETH_ALEN]; + u8 *mac = NULL; + struct wpa_driver_sta_statistics_s sta_statistics; + + memset(&sta_statistics, 0 ,sizeof(sta_statistics)); + + if (hwaddr_aton(addr, sta_addr)) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: invalid " + "address '%s'", addr); + return -1; + } + + mac = wpas_p2p_get_sta_mac(wpa_s, sta_addr); + + if (wpas_get_sta_statistics(wpa_s, mac ? mac : sta_addr, + (u8 *)&sta_statistics) < 0) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: command failed"); + return -1; + } + len = print_sta_statistics(wpa_s, &sta_statistics, 0x00, buf, buflen); + + format_sta_statistics(&sta_statistics); + return len; +} + +#ifdef CONFIG_MTK_P2P_SIGMA +static int wpas_p2p_sigma_test_mode(struct wpa_supplicant *wpa_s, int index, int value) +{ + struct wpa_driver_p2p_sigma_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = 1; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params); + + params.idx = (u32)index; + params.value = (u32)value; + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)¶ms, + sizeof(struct wpa_driver_p2p_sigma_params)); +} + +static int p2p_ctrl_iface_set_opps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int len = 0; + size_t ssid_len = 0; + char *ssid; + int CTWin; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps cmd=%s\n", cmd); + + CTWin = atoi(cmd); + + str = os_strchr(cmd, ' '); + if (str) { + *str ++ = '\0'; + + if (hwaddr_aton(str, addr)) + return -1; + } -/********************************************************************** -* OVERLAPPED functins, previous defination is in driver_nl80211.c, -* it will be modified -***********************************************************************/ + str = os_strchr(str, ' '); + if (str) { + *str ++ = '\0'; -/**********************************************************************/ -static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg) + ssid = wpa_config_parse_string(str, &ssid_len); + if (ssid) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)%s\n", + CTWin, MAC2STR(addr), ssid_len, ssid); + os_free(ssid); + } + else { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)\n", + CTWin, MAC2STR(addr), ssid_len); + } + } + + wpas_p2p_sigma_test_mode(wpa_s, 107, (int)CTWin); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; +} + +static int p2p_ctrl_iface_set_power_save(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ioctl_sock = -1; - struct iwreq iwr; - int ret = -1; - char buf[11]; -#ifdef MTK_TC1_FEATURE - char replace_ifname[IFNAMSIZ+1]; + char *str = NULL; + int len = 0; + int value = 0; - memset(replace_ifname, 0, IFNAMSIZ+1); - os_strlcpy(replace_ifname, "wlan0", os_strlen("wlan0")+1); -#endif + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save cmd=%s\n", cmd); - wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_set_country"); - ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (ioctl_sock < 0) { - wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__); + value = atoi(cmd); + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save value=%d\n", value); + + wpas_p2p_sigma_test_mode(wpa_s, 108, (int)value); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; + +} + +static int p2p_ctrl_iface_set_sleep(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int len = 0; + size_t ssid_len = 0; + char *ssid; + + if (hwaddr_aton(cmd, addr)) return -1; + + str = os_strchr(cmd, ' '); + if (str) { + *str ++ = '\0'; + + ssid = wpa_config_parse_string(str, &ssid_len); + if (ssid) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)%s\n", + MAC2STR(addr), ssid_len, ssid); + os_free(ssid); + } + else { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)\n", + MAC2STR(addr), ssid_len); + } } - os_memset(&iwr, 0, sizeof(iwr)); -#ifdef MTK_TC1_FEATURE - // convert 'p2p0' -> 'wlan0' : - // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution. - if (os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0")) == 0) { - wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0"); - os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ ); - } else { - os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); + + wpas_p2p_sigma_test_mode(wpa_s, 106, 0); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; + +} +#endif /* CONFIG_MTK_P2P_SIGMA */ + +/* utils for parse cmdline: + * cmd: paramters in cmd line + * argv: paramter vector + * len: cmd lenght + * example: + * cmd = "driver P2P_SET_NOA 1 2 3" + * argv[0] = "driver" + * argv[1] = "P2P_SET_NOA" + * argv[2] = "1" + * argv[3] = "2" + * argv[4] = "3" + */ + +int tokenize_space(char *cmd, char *argv[], int len) +{ + char *pos; + char *start; + int argc = 0; + + start = pos = cmd; + for (;;) { + argv[argc] = pos; + argc++; + while (*pos != '\n' && *pos != ' ' && *pos != '\0') { + pos++; + if (pos - start >= len) + break; + } + + if (*pos == '\0') + break; + + if (*pos == '\n' || *pos == ' ') { + *pos++ = '\0'; + if (pos - start >= len) + break; + } } -#else - os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); -#endif - sprintf(buf, "COUNTRY %s", alpha2_arg); - iwr.u.data.pointer = buf; - iwr.u.data.length = strlen(buf); - if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) { // SIOCSIWPRIV - wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s", buf); - close(ioctl_sock); - return ret; + + return argc; +} + +static int p2p_ctrl_iface_set_noa(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + struct wpa_driver_p2p_noa_params { + struct wpa_driver_test_mode_info hdr; + u32 idx; + u32 value; /* should not be used in this case */ + u32 count; + u32 interval; + u32 duration; + }; + char *argv[64]; + int argc; + struct wpa_driver_p2p_noa_params noa_param; + + os_memset(&noa_param, 0, sizeof(noa_param)); + + /* P2P_SET_NOA 255 100 3 */ + /* + * argv format: + * argv[0] = "P2P_SET_NOA" + * argv[1] = "255" + * argv[2] = "100" + * argv[3] = "3" + */ + argc = tokenize_space(cmd, argv, os_strlen(cmd)); + + if (argc != 4) { + wpa_printf(MSG_DEBUG, "P2P: NOA: invalid cmd format"); + return -1; } - else { - close(ioctl_sock); + + /* fill in the params structure */ + noa_param.hdr.index = 1; + noa_param.hdr.index = noa_param.hdr.index | (0x01 << 24); + noa_param.hdr.buflen = sizeof(struct wpa_driver_p2p_noa_params); + + noa_param.idx = 4; + noa_param.count = (u32)atoi(argv[1]); + noa_param.interval= (u32)atoi(argv[2]); + noa_param.duration= (u32)atoi(argv[3]); + + wpa_printf(MSG_DEBUG, "P2P: set noa: %d %d %d", + noa_param.count, + noa_param.interval, + noa_param.duration); + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&noa_param, + sizeof(struct wpa_driver_p2p_noa_params)); +} + +static int p2p_ctrl_iface_set_ps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *argv[64]; + int argc; + int enable; + s32 ctw; + struct wpa_driver_p2p_sigma_params opps_param; + + os_memset(&opps_param, 0, sizeof(opps_param)); + + /* P2P_SET_PS 2 1 3 + * argv format: + * argv[0] = "P2P_SET_PS" + * argv[1] = "2" + * argv[2] = "1" + * argv[3] = "3" + */ + argc = tokenize_space(cmd, argv, os_strlen(cmd)); + + if (argc != 4) { + wpa_printf(MSG_DEBUG, "P2P: Opps: invalid cmd format"); + return -1; + } + + /* fill in the params structure */ + opps_param.hdr.index = 1; + opps_param.hdr.index = opps_param.hdr.index | (0x01 << 24); + opps_param.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params); + + opps_param.idx = 107; + + enable = atoi(argv[2]); + ctw = atoi(argv[3]); + + /* BIT 7 control OPPS on / off */ + if (enable) + ctw |= BIT(7); + + opps_param.value = ctw; + + wpa_printf(MSG_DEBUG, "P2P: set opps: 0x%x", + opps_param.value); + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&opps_param, + sizeof(struct wpa_driver_p2p_sigma_params)); +} + +#ifdef CONFIG_MTK_WFD_SINK +static int wpas_wfd_data_update(struct wpa_supplicant *wpa_s, struct wfd_data_s *p_wfd_data) +{ + struct wpa_driver_wfd_data_s params; + os_memset(¶ms, 0, sizeof(params)); + + wpa_printf(MSG_DEBUG, "WFD: wpas_wfd_data_update wfd_en %u wfd_dev_info 0x%x wfd_ctrl_port %u wfd_state 0x%x", + p_wfd_data->WfdEnable, p_wfd_data->WfdDevInfo, p_wfd_data->WfdControlPort, p_wfd_data->WfdState); + + + params.hdr.index = 2; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wfd_data_s); + + params.WfdCmdType = p_wfd_data->WfdCmdType; + params.WfdEnable = p_wfd_data->WfdEnable; + params.WfdCoupleSinkStatus = p_wfd_data->WfdCoupleSinkStatus; + params.WfdDevInfo = p_wfd_data->WfdDevInfo; + params.WfdControlPort = p_wfd_data->WfdControlPort; + params.WfdMaximumTp = p_wfd_data->WfdMaximumTp; + params.WfdExtendCap = p_wfd_data->WfdExtendCap; + os_memcpy(params.WfdCoupleSinkAddress, p_wfd_data->WfdCoupleSinkAddress, ETH_ALEN); + os_memcpy(params.WfdAssociatedBssid, p_wfd_data->WfdAssociatedBssid, ETH_ALEN); + os_memcpy(params.WfdVideoIp, p_wfd_data->WfdVideoIp, sizeof(p_wfd_data->WfdVideoIp)); + os_memcpy(params.WfdAudioIp, p_wfd_data->WfdAudioIp, sizeof(p_wfd_data->WfdAudioIp)); + params.WfdVideoPort = p_wfd_data->WfdVideoPort; + params.WfdAudioPort = p_wfd_data->WfdAudioPort; + params.WfdFlag = p_wfd_data->WfdFlag; + params.WfdPolicy = p_wfd_data->WfdPolicy; + params.WfdState = p_wfd_data->WfdState; + params.WfdSessionInformationIELen = p_wfd_data->WfdSessionInformationIELen; + os_memcpy(params.WfdSessionInformationIE, p_wfd_data->WfdSessionInformationIE, + p_wfd_data->WfdSessionInformationIELen); + os_memcpy(params.WfdPrimarySinkMac, p_wfd_data->WfdPrimarySinkMac, ETH_ALEN); + os_memcpy(params.WfdSecondarySinkMac, p_wfd_data->WfdSecondarySinkMac, ETH_ALEN); + params.WfdAdvancedFlag = p_wfd_data->WfdAdvancedFlag; + + params.WfdSessionAvailable = p_wfd_data->WfdSessionAvailable; + params.WfdSigmaMode = p_wfd_data->WfdSigmaMode; + os_memcpy(params.WfdLocalIp, p_wfd_data->WfdLocalIp, sizeof(p_wfd_data->WfdLocalIp)); + + return wpa_drv_set_test_mode(wpa_s, (u8 *)¶ms, sizeof(struct wpa_driver_wfd_data_s)); +} + +static int p2p_get_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + int ret = 0; + struct p2p_data *p2p = wpa_s->global->p2p; + wpa_printf(MSG_DEBUG, "%s %d, %d", __func__, __LINE__, p2p->dev_capab); + if (os_strncmp(cmd, "p2p_dev_capa", os_strlen("p2p_dev_capa")) == 0) { + ret = snprintf(buf, buflen, "p2p_dev_capa=%d\n", p2p->dev_capab); + wpa_printf(MSG_DEBUG, "%s %d %d, %s", __func__, __LINE__, p2p->dev_capab, buf); + } else if (os_strncmp(cmd, "p2p_group_capa", os_strlen("p2p_group_capa")) == 0) { + wpa_printf(MSG_DEBUG, "%s not implement", __func__); + ret = -1; + } + return ret; +} + +static int p2p_set_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + int ret = 0; + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + struct p2p_data *p2p = wpa_s->global->p2p; + if (os_strncmp(cmd, "p2p_dev_capa ", os_strlen("p2p_dev_capa ")) == 0) { + int old_cap = p2p->dev_capab; + int dev_cap = atoi(cmd + os_strlen("p2p_dev_capa ")); + p2p->dev_capab = dev_cap & 0xff; + wpa_printf(MSG_DEBUG, "%s %d %d, %d", __func__, __LINE__, p2p->dev_capab, + old_cap); + } else if (os_strncmp(cmd, "p2p_group_capa ", os_strlen("p2p_group_capa ")) == 0) { + wpa_printf(MSG_DEBUG, "%s group not implement", __func__); + ret = -1; + } + return ret; +} + +/** + * priv_p2p_freq_to_channel - Convert frequency into channel info + * @op_class: Buffer for returning operating class + * @channel: Buffer for returning channel number + * Returns: 0 on success, -1 if the specified frequency is unknown + */ +static int priv_p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel) +{ + /* TODO: more operating classes */ + if (freq >= 2412 && freq <= 2472) { + if ((freq - 2407) % 5) + return -1; + + *op_class = 81; /* 2.407 GHz, channels 1..13 */ + *channel = (freq - 2407) / 5; + return 0; + } + + if (freq == 2484) { + *op_class = 82; /* channel 14 */ + *channel = 14; + return 0; + } + + if (freq >= 5180 && freq <= 5240) { + if ((freq - 5000) % 5) + return -1; + + *op_class = 115; /* 5 GHz, channels 36..48 */ + *channel = (freq - 5000) / 5; + return 0; + } + + if (freq >= 5260 && freq <= 5320) { + *op_class = 118; /* 5 GHz, channels 52..64 */ + *channel = (freq - 5000) / 5; + return 0; + } + + if (freq >= 5500 && freq <= 5700) { + *op_class = 121; /* 5 GHz, channels 100..140 */ + *channel = (freq - 5000) / 5; + return 0; + } + + if (freq >= 5745 && freq <= 5805) { + if ((freq - 5000) % 5) + return -1; + + *op_class = 124; /* 5 GHz, channels 149..161 */ + *channel = (freq - 5000) / 5; return 0; } + if (freq >= 5825 && freq <= 5845) { + *op_class = 125; /* 5 GHz, channels 149,153,157,161,165,169 */ + *channel = (freq - 5000) / 5; + return 0; + } + + return -1; } -/* -* update channel list in wpa_supplicant -* if coutry code chanaged -*/ -static void wpa_driver_notify_country_change(void *ctx, char *cmd) +static int p2p_wfd_sink_config_scc(struct wpa_supplicant *wpa_s, int scc, unsigned int oper_freq) { - if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { - union wpa_event_data event; + int ret = 0; + u8 op_reg_class = 0, op_channel = 0; + unsigned int r; + struct wpa_supplicant *iface; + struct p2p_data *p2p = wpa_s->global->p2p; + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + if (!p2p) { + wpa_printf(MSG_DEBUG, "Not support p2p."); + return ret; + } + if (scc && oper_freq) { + priv_p2p_freq_to_channel(oper_freq, &op_reg_class, &op_channel); + p2p->op_channel = op_channel; + p2p->op_reg_class = op_reg_class; + p2p->channels.reg_classes = 1; + p2p->channels.reg_class[0].channels = 1; + p2p->channels.reg_class[0].reg_class = op_reg_class; + p2p->channels.reg_class[0].channel[0] = op_channel; + wpa_printf(MSG_DEBUG, "Enable SCC in WFD sink mode class %d, channel %d", + op_reg_class, op_channel); + return ret; + } + /* Get back to MCC */ + wpa_printf(MSG_DEBUG, "Config MCC"); + if (wpa_s->conf->p2p_oper_reg_class && + wpa_s->conf->p2p_oper_channel) { + p2p->op_reg_class = wpa_s->conf->p2p_oper_reg_class; + p2p->op_channel = wpa_s->conf->p2p_oper_channel; + p2p->cfg->cfg_op_channel = 1; + } else { + p2p->op_reg_class = 81; + os_get_random((u8 *)&r, sizeof(r)); + p2p->op_channel = 1 + (r % 3) * 5; + p2p->cfg->cfg_op_channel = 0; + } - os_memset(&event, 0, sizeof(event)); - event.channel_list_changed.initiator = REGDOM_SET_BY_USER; - if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { - event.channel_list_changed.type = REGDOM_TYPE_COUNTRY; - if (os_strlen(cmd) > 9) { - event.channel_list_changed.alpha2[0] = cmd[8]; - event.channel_list_changed.alpha2[1] = cmd[9]; - } - } else - event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; - wpa_supplicant_event(ctx, EVENT_CHANNEL_LIST_CHANGED, &event); + os_memcpy(&p2p->channels, &p2p->cfg->channels, sizeof(struct p2p_channels)); + return ret; +} + + +static int mtk_get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s, + struct wpa_used_freq_data *freqs_data, + unsigned int len) +{ + struct wpa_supplicant *ifs; + u8 bssid[ETH_ALEN]; + int freq; + unsigned int idx = 0, i; + + wpa_dbg(wpa_s, MSG_DEBUG, + "Determining shared radio frequencies (max len %u)", len); + os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len); + + dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant, + radio_list) { + wpa_printf(MSG_DEBUG, "Get shared freqs ifname %s", ifs->ifname); + if (idx == len) + break; + + if (ifs->current_ssid == NULL || ifs->assoc_freq == 0) + continue; + + if (ifs->current_ssid->mode == WPAS_MODE_AP || + ifs->current_ssid->mode == WPAS_MODE_P2P_GO) + freq = ifs->current_ssid->frequency; + else if (wpa_drv_get_bssid(ifs, bssid) == 0) + freq = ifs->assoc_freq; + else + continue; + + /* Hold only distinct freqs */ + for (i = 0; i < idx; i++) + if (freqs_data[i].freq == freq) + break; + + if (i == idx) + freqs_data[idx++].freq = freq; + + if (ifs->current_ssid->mode == WPAS_MODE_INFRA) { + freqs_data[i].flags = ifs->current_ssid->p2p_group ? + WPA_FREQ_USED_BY_P2P_CLIENT : + WPA_FREQ_USED_BY_INFRA_STATION; + } } + + return idx; +} + + +static int mtk_get_shared_radio_freqs(struct wpa_supplicant *wpa_s, + int *freq_array, unsigned int len) +{ + struct wpa_used_freq_data *freqs_data; + int num, i; + + os_memset(freq_array, 0, sizeof(int) * len); + + freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data)); + if (!freqs_data) + return -1; + + num = mtk_get_shared_radio_freqs_data(wpa_s, freqs_data, len); + for (i = 0; i < num; i++) + freq_array[i] = freqs_data[i].freq; + + os_free(freqs_data); + + return num; } +#endif int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len ) @@ -110,6 +1588,7 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct ifreq ifr; + android_wifi_priv_cmd priv_cmd; struct wpa_supplicant *wpa_s; struct hostapd_data *hapd; int handled = 0; @@ -119,53 +1598,55 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, int ret = -1; if (drv == NULL) { - wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__); + wpa_printf(MSG_ERROR, "%s: drv is NULL, exit", __func__); return -1; } if (drv->ctx == NULL) { - wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__); + wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL, exit", __func__); return -1; } - if (os_strcmp(bss->ifname, "ap0") == 0) { + if (bss->drv->nlmode == NL80211_IFTYPE_AP) { hapd = (struct hostapd_data *)(drv->ctx); } else { wpa_s = (struct wpa_supplicant *)(drv->ctx); if (wpa_s->conf == NULL) { - wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__); + wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL, exit", __func__); return -1; } } - wpa_printf(MSG_DEBUG, "iface %s recv cmd %s", bss->ifname, cmd); + wpa_printf(MSG_INFO, "%s: %s recv cmd %s", __func__, bss->ifname, cmd); handled = 1; if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) { int state; state = atoi(cmd + 10); wpa_printf(MSG_DEBUG, "POWERMODE=%d", state); + } else if (os_strncasecmp(cmd, "GET_STA_STATISTICS ", 19) == 0) { + ret = wpa_driver_get_sta_statistics(wpa_s, cmd + 19, buf, buf_len); } else if (os_strncmp(cmd, "MACADDR", os_strlen("MACADDR")) == 0) { u8 macaddr[ETH_ALEN] = {}; os_memcpy(&macaddr, wpa_s->own_addr, ETH_ALEN); ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); wpa_printf(MSG_DEBUG, "%s", buf); - } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY"))==0) { + } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY")) == 0) { if (os_strlen(cmd) != os_strlen("COUNTRY") + 3) { wpa_printf(MSG_DEBUG, "Ignore COUNTRY cmd %s", cmd); ret = 0; } else { - wpa_printf(MSG_INFO, "set country: %s", cmd+8); - // ret = wpa_drv_set_country(wpa_s, cmd+8); - ret = wpa_driver_mediatek_set_country(priv, cmd+8); + wpa_printf(MSG_INFO, "Set country: %s", cmd + 8); + // ret = wpa_drv_set_country(wpa_s, cmd + 8); + ret = wpa_driver_mediatek_set_country(priv, cmd + 8); if (ret == 0) { wpa_printf(MSG_DEBUG, "Update channel list after country code changed"); - wpa_driver_notify_country_change(wpa_s, cmd); + wpa_driver_notify_country_change(wpa_s->global, cmd); } } } else if (os_strcasecmp(cmd, "start") == 0) { - if (ret = linux_set_iface_flags(drv->global->ioctl_sock, - drv->first_bss->ifname, 1)) { + if ((ret = linux_set_iface_flags(drv->global->ioctl_sock, + drv->first_bss->ifname, 1))) { wpa_printf(MSG_INFO, "nl80211: Could not set interface UP, ret=%d \n", ret); } else { wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STARTED"); @@ -179,14 +1660,14 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, wpa_printf(MSG_INFO, "nl80211: not associated, no need to deauthenticate \n"); } - if (ret = linux_set_iface_flags(drv->global->ioctl_sock, - drv->first_bss->ifname, 0)) { + if ((ret = linux_set_iface_flags(drv->global->ioctl_sock, + drv->first_bss->ifname, 0))) { wpa_printf(MSG_INFO, "nl80211: Could not set interface Down, ret=%d \n", ret); } else { wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STOPPED"); } } else if (os_strncasecmp(cmd, "getpower", 8) == 0) { - u32 mode; + u32 mode = 0; // ret = wpa_driver_wext_driver_get_power(drv, &mode); if (ret == 0) { ret = snprintf(buf, buf_len, "powermode = %u\n", mode); @@ -194,45 +1675,381 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, if (ret < (int)buf_len) return ret; } - } else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) { - u32 thd; - // ret = wpa_driver_wext_driver_get_rts(drv, &thd); - if (ret == 0) { - ret = snprintf(buf, buf_len, "rts-threshold = %u\n", thd); - wpa_printf(MSG_DEBUG, "%s", buf); - if (ret < (int)buf_len) - return ret; + } else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0; + char *cp = cmd + 12; + char *endp; + + if (*cp != '\0') { + idx = (u32)strtol(cp, &endp, 0); + if (endp != cp) { + idx += 0x00900200; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } } - } else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) { - u32 thd = 0; - char *cp = cmd + 17; + } else if (os_strncasecmp(cmd, "rxfilter-remove", 15) == 0) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0; + char *cp = cmd + 15; char *endp; + if (*cp != '\0') { - thd = (u32)strtol(cp, &endp, 0); - // if (endp != cp) - // ret = wpa_driver_wext_driver_set_rts(drv, thd); + idx = (u32)strtol(cp, &endp, 0); + if (endp != cp) { + idx += 0x00900300; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } } + } else if (os_strncasecmp(cmd, "rxfilter-stop", 13) == 0) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0x00900000; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } else if (os_strncasecmp(cmd, "rxfilter-start", 14) == 0) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0x00900100; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; } else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) { ret = 0; /* mt5921 linux driver not implement yet */ } else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) { ret = 0; /* mt5921 linux driver not implement yet */ } else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) { ret = 0; /* mt5921 linux driver not implement yet */ +#ifdef CONFIG_HOTSPOT_MGR_SUPPORT + } else if (os_strncmp(cmd, "STA-BLOCK ", 10) == 0) { + if (wpa_driver_sta_block(priv, cmd + 10)) { + ret = -1; + } else { + ret = 0; + } + } else if (os_strncmp(cmd, "STA-UNBLOCK ", 12) == 0) { + if (wpa_driver_sta_unblock(priv, cmd + 12)) { + ret = -1; + } else { + ret = 0; + } + } else if (os_strncasecmp(cmd, "set_max_client ", 15) == 0) { + wpa_driver_set_max_client(priv, cmd + 15, buf, buf_len); +#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */ +#ifdef CONFIG_MTK_LTE_COEX + } else if (os_strncmp(cmd, "MTK-ACS", 7) == 0) { + u8 ch = wpa_driver_do_mtk_acs(priv); + os_memcpy(buf, &ch, sizeof(u8)); + ret = sizeof(u8); +#endif /* CONFIG_MTK_LTE_COEX */ +#ifdef CONFIG_WAPI_SUPPORT + } else if (os_strncasecmp(cmd, "set-wapi-key", 12) == 0) { + struct wapi_key_param_type { + u8 *addr; + int key_idx; + int set_tx; + u8 *seq; + size_t seq_len; + u8 *key; + size_t key_len; + } *wapi_key_param; + wapi_key_param = (struct wapi_key_param_type*)buf; + + ret = wpa_driver_nl80211_set_wapi_key(priv, (const u8*)wapi_key_param->addr, + wapi_key_param->key_idx, wapi_key_param->set_tx, + (const u8*)wapi_key_param->seq, wapi_key_param->seq_len, + (const u8*)wapi_key_param->key, wapi_key_param->key_len); + } else if (os_strncasecmp(cmd, "wapi-msg-send", 13) == 0) { + struct wapi_msg_send_param_type { + u8 *msg_in; + int msg_in_len; + u8 *msg_out; + int *msg_out_len; + } *wapi_msg_send_param; + wapi_msg_send_param = (struct wapi_msg_send_param_type*)buf; + ret = wpa_driver_nl80211_send_msg(priv, (const u8*)wapi_msg_send_param->msg_in, + wapi_msg_send_param->msg_in_len, wapi_msg_send_param->msg_out, + wapi_msg_send_param->msg_out_len); +#endif /* CONFIG_WAPI_SUPPORT */ +#ifdef CONFIG_MTK_WFD_SINK + } else if (os_strncmp(cmd, "p2p_get_cap ", os_strlen("p2p_get_cap ")) == 0) { + struct p2p_data *p2p = wpa_s->global->p2p; + if (p2p) { + wpa_printf(MSG_DEBUG, "%s %d, %d ", + __func__, __LINE__, p2p->dev_capab); + ret = p2p_get_capability(wpa_s, cmd + os_strlen("p2p_get_cap "), + buf, buf_len); + } + } else if (os_strncmp(cmd, "p2p_set_cap ", os_strlen("p2p_set_cap ")) == 0) { + struct p2p_data *p2p = wpa_s->global->p2p; + if (p2p) { + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + ret = p2p_set_capability(wpa_s, cmd + os_strlen("p2p_set_cap "), + buf, buf_len); + } + } else if (os_strncmp(cmd, "MIRACAST ", os_strlen("MIRACAST ")) == 0) { + unsigned char miracast = atoi(cmd + os_strlen("MIRACAST ")); + char *pos = os_strstr(cmd, " freq="); + unsigned int freq = 0; + int num; + wpa_printf(MSG_DEBUG, "MIRACAST %d", miracast); + switch (miracast) { + case 0: + case 1: + num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1); + if (num > 0 && freq > 0) { + wpa_printf(MSG_DEBUG, "AIS connected %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + break; + case 2: + if (pos) { + pos += 6; + freq = atoi(pos); + wpa_printf(MSG_DEBUG, "MIRACAST freq %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + /* rebuild DRIVER MIRACAST 2 cmd */ + os_memset(cmd, 0, os_strlen(cmd)); + os_memcpy(cmd, "MIRACAST 2", os_strlen("MIRACAST 2")); + } else { + num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1); + if (num > 0 && freq > 0) { + wpa_printf(MSG_DEBUG, "AIS connected %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } + + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + + break; + default: + wpa_printf(MSG_DEBUG, "Unknown MIRACAST value %d", miracast); + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + break; + } + } else if (os_strncasecmp(cmd, "p2p_use_mcc=", os_strlen("p2p_use_mcc=")) == 0) { + unsigned char use_mcc = atoi(cmd + os_strlen("p2p_use_mcc=")); + wpa_printf(MSG_DEBUG, "p2p_use_mcc %d", use_mcc); + // MCC/SCC should be determined by GO negotation + // wpa_s->global->p2p->p2p_use_mcc = use_mcc; + if (use_mcc) { + wpa_printf(MSG_DEBUG, "SCC_MCC, config MCC"); + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } else { + int shared_freq; + int num = 0; + wpa_printf(MSG_DEBUG, "use_mcc=0"); + num = mtk_get_shared_radio_freqs(wpa_s, &shared_freq, 1); + if (num > 0 && shared_freq > 0) { + wpa_printf(MSG_DEBUG, "p2p disconnected, AIS connected %d", shared_freq); + p2p_wfd_sink_config_scc(wpa_s, 1, shared_freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } + } else if (os_strncmp(cmd, "wfd_data_update", os_strlen("wfd_data_update")) == 0) { + wpa_printf(MSG_DEBUG, "CONFIG_MTK_P2P: Update wfd_data"); + ret = wpas_wfd_data_update(wpa_s, (struct wfd_data_s *)buf); +#endif +#ifdef CONFIG_MTK_P2P_SIGMA + } else if (os_strncasecmp(cmd, "mcc", 3) == 0) { + if (wpa_s->drv_priv) { + int mcc = 0; + char *value = NULL; + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + struct wpa_supplicant *_wpa_s; + mcc = atoi(value); + if (mcc) { + for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) { + + /* + * 2 is appropriate? + * just legacy wifi vs p2p wifi? + */ + _wpa_s->num_multichan_concurrent = 2; + _wpa_s->drv_flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; + if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg) + _wpa_s->global->p2p->cfg->concurrent_operations = 1; + } + } else { + for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) { + + /* + * assign as 0 beacause our driver will + * not report iface_combination to supplicant + */ + _wpa_s->num_multichan_concurrent = 0; + _wpa_s->drv_flags &= ~WPA_DRIVER_FLAGS_P2P_CONCURRENT; + if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg) + _wpa_s->global->p2p->cfg->concurrent_operations = 0; + } + } + + wpa_printf(MSG_DEBUG, "mcc = %d", mcc); + ret = 0; + } + } else if (os_strncmp(cmd, "p2p_set_opps ", 13) == 0) { + ret = p2p_ctrl_iface_set_opps(wpa_s, cmd + 13, buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_power_save ", 19) == 0) { + ret = p2p_ctrl_iface_set_power_save(wpa_s, cmd + 19, buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_sleep ", 14) == 0) { + ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd + 14, buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_sleep", 13) == 0) { + char cmd2[] = {"ff:ff:ff:ff:ff:ff \"\""}; + ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd2, buf, buf_len); + } else if (os_strncasecmp(cmd, "sigma_mode", 10) == 0) { + int sigma = 0; + char *value = NULL; + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + sigma = atoi(value); + wpa_printf(MSG_DEBUG, "p2p: sigma: set mode %d", sigma); + // we should not have workaround for sigma programs + // wpa_s->global->p2p->sigma_mode = sigma; + ret = 0; +#endif /* CONFIG_MTK_P2P_SIGMA */ + } else if (os_strncmp(cmd, "P2P_SET_NOA", os_strlen("P2P_SET_NOA")) == 0) { + ret = p2p_ctrl_iface_set_noa(wpa_s, cmd, buf, buf_len); + } else if (os_strncmp(cmd, "P2P_SET_PS", os_strlen("P2P_SET_PS")) == 0) { + ret = p2p_ctrl_iface_set_ps(wpa_s, cmd, buf, buf_len); + } else if (os_strncasecmp(cmd, "SETSUSPENDMODE ", 15) == 0) { + struct wpa_driver_suspendmode_params params; + params.hdr.index = NL80211_TESTMODE_SUSPEND; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(params); + params.suspend = *(cmd+15)-'0'; + wpa_driver_nl80211_testmode(priv, (u8* )¶ms, sizeof(params)); + handled = 0; /* 6630 driver handled this command in driver, so give a chance to 6630 driver */ + }else if(os_strncasecmp(cmd, "mtk_rx_packet_filter ", 21) == 0) { + char buf[9] = {0}, *errChar = NULL; + char *pos = NULL; + /* mtk_rx_packet_filter 00000000000000FE 0000000000000000 0000000000000000 */ + struct wpa_driver_rx_filter_params params; + params.hdr.index = NL80211_TESTMODE_RXFILTER; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(params); + + pos = cmd; + pos = pos + 21; + if (pos == NULL || strlen(cmd) != 71 ) { + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter] Error! \n"); + return -1; + } + + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.Ipv4FilterHigh = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterHigh (0x%08x),errChar [%p]\n", params.Ipv4FilterHigh,errChar); + + pos = pos + 8; + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.Ipv4FilterLow = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterLow (0x%08x),errChar [%p]\n", params.Ipv4FilterLow,errChar); + + pos = pos + 9; + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.Ipv6FilterHigh = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterHigh (0x%08x),errChar [%p]\n", params.Ipv6FilterHigh,errChar); + + pos = pos + 8; + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.Ipv6FilterLow = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterLow (0x%08x),errChar [%p]\n", params.Ipv6FilterLow,errChar); + + pos = pos + 9; + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.SnapFilterHigh = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterHigh (0x%08x),errChar [%p]\n", params.SnapFilterHigh,errChar); + + pos = pos + 8; + os_memcpy(buf,pos,8); + buf[8] = '\0'; + params.SnapFilterLow = strtol(buf,&errChar,16); + wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterLow (0x%08x),errChar [%p]\n", params.SnapFilterLow,errChar); + + ret = wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, sizeof(params)); } else { + u8 buffer[100]; + struct wpa_driver_test_mode_info *params = (struct wpa_driver_test_mode_info *)buffer; + params->index = NL80211_TESTMODE_STR_CMD | (0x01 << 24); + params->buflen = sizeof(*params) + strlen(cmd); + strncpy((char*)(params+1), cmd, sizeof(buffer)-sizeof(*params)); + ret = wpa_driver_nl80211_testmode(priv, buffer, params->buflen); handled = 0; - wpa_printf(MSG_INFO, "Unsupported command"); + wpa_printf(MSG_INFO, "Transparent command for driver nl80211, ret=%d", ret); } + if (handled == 0) { + cmd_len = strlen(cmd); + + memset(&ifr, 0, sizeof(ifr)); + memset(&priv_cmd, 0, sizeof(priv_cmd)); + memset(buf, 0, buf_len); + strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; + + if (cmd_len >= PRIV_CMD_SIZE) { + wpa_printf(MSG_INFO, "%s: cmd: %s overflow", + __func__, cmd); + cmd_len = PRIV_CMD_SIZE - 1; + } + + memcpy(priv_cmd.buf, cmd, cmd_len + 1); + priv_cmd.used_len = cmd_len + 1; + priv_cmd.total_len = PRIV_CMD_SIZE; + ifr.ifr_data = &priv_cmd; + + ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); + if (ret < 0) { + wpa_printf(MSG_ERROR, "%s: failed to issue private commands," + " error msg: %s\n", __func__, strerror(errno)); + wpa_driver_send_hang_msg(drv); + ret = snprintf(buf, buf_len, "%s\n", "FAIL"); + } else { + + wpa_printf(MSG_INFO, "%s: ret = %d used = %u total = %u", + __func__, ret , priv_cmd.used_len, priv_cmd.total_len); + + drv_errors = 0; + ret = 0; + if ((os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0)) + ret = strlen(buf); + /* + * There no need to call wpa_supplicant_event func + * on which the cmd is SETBAND + */ + if (os_strncasecmp(cmd, "SETBAND", 7) == 0) { + /* + * wpa_supplicant_event(drv->ctx, + * EVENT_CHANNEL_LIST_CHANGED, NULL); + */ + wpa_printf(MSG_INFO, "%s: Unsupported command SETBAND\n", __func__); + } + } + } /* handled == 0 */ + return ret; } int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) { + char buf[MAX_DRV_CMD_SIZE]; struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d, ignored", bss->ifname, count, start, duration); - return -1; + wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d", bss->ifname, count, start, duration); + snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration); + return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1); } int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) @@ -246,11 +2063,13 @@ int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) { + char buf[MAX_DRV_CMD_SIZE]; struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS, ignored", bss->ifname); - return -1; + wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS %d %d %d", bss->ifname, legacy_ps, opp_ps, ctwindow); + snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow); + return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1); } int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, diff --git a/wpa_supplicant_8_lib/mediatek_driver_nl80211.h b/wpa_supplicant_8_lib/mediatek_driver_nl80211.h new file mode 100644 index 0000000..9657ec1 --- /dev/null +++ b/wpa_supplicant_8_lib/mediatek_driver_nl80211.h @@ -0,0 +1,407 @@ +/* + * Driver interaction with Linux nl80211/cfg80211 + * Copyright (c) 2002-2010, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2007, Johannes Berg + * Copyright (c) 2009-2010, Atheros Communications + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef _MTK_DRIVER_NL80211_H_ +#define _MTK_DRIVER_NL80211_H_ + + +#ifndef BITS +/* Eddie */ +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + + +enum nl80211_testmode_sta_link_statistics_attr{ + __NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM, + NL80211_TESTMODE_STA_STATISTICS_MAX = NL80211_TESTMODE_STA_STATISTICS_NUM - 1 +}; + +enum nl80211_testmode_link_detect_attr{ + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_OK_CNT, + NL80211_TESTMODE_LINK_RX_OK_CNT, + NL80211_TESTMODE_LINK_RST_REASON, + NL80211_TESTMODE_LINK_RST_TIME, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + NL80211_TESTMODE_LINK_ENQUE_TICK, + NL80211_TESTMODE_LINK_DEQUE_TICK, + NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + NL80211_TESTMODE_LINK_CURR_TICK, + NL80211_TESTMODE_LINK_CURR_TIME, + NL80211_TESTMODE_LINK_DETECT_NUM, + NL80211_TESTMODE_LINK_DETECT_MAX = NL80211_TESTMODE_LINK_DETECT_NUM - 1 +}; + +#define BUG_REPORT_NUM 47 + +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + TC0_INDEX = 0, + TC1_INDEX, + TC2_INDEX, + TC3_INDEX, + TC_DATA_NUM, + TC4_INDEX = TC_DATA_NUM, + TC5_INDEX, + TC_NUM +} ENUM_TRAFFIC_CLASS_INDEX_T; + +struct wpa_driver_sta_statistics_s { + u8 version; + u8 addr[ETH_ALEN]; + u32 flag; + + u32 link_score; + u8 per; + int rssi; + u32 phy_mode; + double tx_rate; + + u32 tx_total_cnt; + u32 enqueue_total_cnt; + u32 dequeue_total_cnt; + u32 enqueue_sta_total_cnt; + u32 dequeue_sta_total_cnt; + u32 tx_exc_threshold_cnt; + + u32 tx_avg_process_time; + u32 tx_max_process_time; + u32 tx_avg_hif_process_time; + u32 tx_max_hif_process_time; + + u32 tx_fail_cnt; + u32 tx_timeout_cnt; + u32 tx_avg_air_time; + + u32 tc_buf_full_cnt[TC_DATA_NUM]; + u32 tc_que_len[TC_DATA_NUM]; + + /* + * how many TC[0-3] resource back from firmware during + * statistics intervals + */ + u32 tc_back_count[TC_DATA_NUM]; + + /* + * how many times that no TC[0-3] resource when dequeue + * statistics intervals + */ + u32 dequeue_no_tc_res[TC_DATA_NUM]; + u32 tc_wanted_res[TC_DATA_NUM]; + u32 tc_used_res[TC_DATA_NUM]; + + /* + * wlan interrupt info + * statistics intervals + */ + u32 isr_cnt; + u32 isr_pass_cnt; + u32 isr_task_cnt; + u32 isr_ab_cnt; + u32 isr_sw_cnt; + u32 isr_tx_cnt; + u32 isr_rx_cnt; + + u32 tc_avg_que_len[TC_DATA_NUM]; + u32 tc_cur_que_len[TC_DATA_NUM]; + + u8 reserved[32]; +}; + +struct wpa_driver_sta_link_detect_s { + u64 tx_fail_cnt; + u64 tx_retry_cnt; + u64 tx_multi_retry_cnt; + u64 ack_fail_cnt; + u64 fcs_err_cnt; + u64 tx_ok_cnt; + u64 rx_ok_cnt; + u32 rst_reason; + u64 rst_time; + u32 roam_fail_times; + u64 roam_fail_time; + u8 tx_done_delay_is_arp; + u32 arrive_drv_tick; + u32 en_que_tick; + u32 de_que_tick; + u32 leave_drv_tick; + u32 curr_tick; + u64 curr_time; + u32 bug_report[BUG_REPORT_NUM]; +}; + +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_ALG_SMS4 0x20 + +/* P2P Sigma*/ +struct wpa_driver_test_mode_info { + u32 index; + u32 buflen; +}; + +struct wpa_driver_testmode_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; + +struct wpa_driver_get_sta_statistics_params { + struct wpa_driver_test_mode_info hdr; + u32 version; + u32 flag; + u8 addr[ETH_ALEN]; + u8 *buf; +}; + +struct wpa_driver_p2p_sigma_params { + struct wpa_driver_test_mode_info hdr; + u32 idx; + u32 value; +}; + +struct wpa_driver_get_sta_link_detect_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; + +/* Hotspot Client Management */ +struct wpa_driver_hotspot_params { + struct wpa_driver_test_mode_info hdr; + u8 blocked; + u8 bssid[ETH_ALEN]; +}; + +struct wpa_driver_hotspot_set_config_params { + struct wpa_driver_test_mode_info hdr; + u32 index; + u32 value; +}; + +#ifdef CONFIG_MTK_LTE_COEX +enum nl80211_testmode_available_chan_attr{ + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1 +}; + +struct wpa_driver_available_chan_s { + u32 ch_2g_base1; + u32 ch_5g_base36; + u32 ch_5g_base52; + u32 ch_5g_base100; + u32 ch_5g_base149; +}; + +struct wpa_driver_get_available_channel_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; +#endif + +/* SW CMD */ +struct wpa_driver_sw_cmd_params { + struct wpa_driver_test_mode_info hdr; + u8 set; + u32 adr; + u32 data; +}; + +struct wpa_driver_suspendmode_params { + struct wpa_driver_test_mode_info hdr; + u8 suspend; +}; + +/* WAPI */ +struct iw_encode_exts { + u32 ext_flags; /* IW_ENCODE_EXT_* */ + u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + u16 alg; /* IW_ENCODE_ALG_* */ + u16 key_len; + u8 key[32]; +}; + +struct wpa_driver_rx_filter_params { + struct wpa_driver_test_mode_info hdr; + u32 Ipv4FilterHigh; + u32 Ipv4FilterLow; + u32 Ipv6FilterHigh; + u32 Ipv6FilterLow; + u32 SnapFilterHigh; + u32 SnapFilterLow; +}; + +struct wpa_driver_wapi_key_params { + struct wpa_driver_test_mode_info hdr; + u8 key_index; + u8 key_len; + struct iw_encode_exts extparams; +}; + +/* CONFIG_MTK_P2P */ +struct wpa_driver_wfd_data_s { + struct wpa_driver_test_mode_info hdr; + u32 WfdCmdType; + u8 WfdEnable; + u8 WfdCoupleSinkStatus; + u8 WfdSessionAvailable; + u8 WfdSigmaMode; + u16 WfdDevInfo; + u16 WfdControlPort; + u16 WfdMaximumTp; + u16 WfdExtendCap; + u8 WfdCoupleSinkAddress[ETH_ALEN]; + u8 WfdAssociatedBssid[ETH_ALEN]; + u8 WfdVideoIp[4]; + u8 WfdAudioIp[4]; + u16 WfdVideoPort; + u16 WfdAudioPort; + u32 WfdFlag; + u32 WfdPolicy; + u32 WfdState; + u8 WfdSessionInformationIE[24*8]; /* Include Subelement ID, length */ + u16 WfdSessionInformationIELen; + u8 Reverved1[2]; + u8 WfdPrimarySinkMac[ETH_ALEN]; + u8 WfdSecondarySinkMac[ETH_ALEN]; + u32 WfdAdvancedFlag; + /* Group 1 64 bytes */ + u8 WfdLocalIp[4]; + u16 WfdLifetimeAc2; /* Unit is 2 TU */ + u16 WfdLifetimeAc3; /* Unit is 2 TU */ + u16 WfdCounterThreshold; /* Unit is ms */ + u8 Reverved2[54]; + /* Group 2 64 bytes */ + u8 Reverved3[64]; + /* Group 3 64 bytes */ + u8 Reverved4[64]; +} wfd_data; + +struct wpa_driver_set_beamplus_params { + struct wpa_driver_test_mode_info hdr; + u32 value; +}; + +enum nl80211_testmode_params { + /* Old test mode command id, compatible with exist testmode command */ + NL80211_TESTMODE_SW_CMD = 1, + NL80211_TESTMODE_WAPI = 2, + NL80211_TESTMODE_HS20 = 3, + NL80211_TESTMODE_POORLINK = 4, + NL80211_TESTMODE_STATISTICS = 0x10, + NL80211_TESTMODE_LINK_DETECT = 0x20, + + // Hotspot manager testmode command + NL80211_TESTMODE_HS_SET_CONFIG = 51, + + /* New test mode command id, should greater than TESTMODE_CMD_ID_NEW_BEGIN */ + NL80211_TESTMODE_NEW_BEGIN = 100, + NL80211_TESTMODE_SUSPEND = 101, + NL80211_TESTMODE_STR_CMD = 102, + NL80211_TESTMODE_RXFILTER = 103 +}; + +#endif -- 2.20.1