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 \
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
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 {
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 {
// add other details
+ wifi_roaming_capabilities roaming_capa; // capabilities of roaming
} hal_info;
#define PNO_SSID_FOUND 0x1
#include <netlink/handlers.h>
#include <ctype.h>
+#include <errno.h>
#include "wifi_hal.h"
#include "common.h"
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) {
ALOGD("WifiCommand::requestResponse err=%d", err);
out:
nl_cb_put(cb);
- return err;
+ return kernelErrorToWifiHalError(err);
}
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();
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)
}
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);
}
int requestVendorEvent(uint32_t id, int subcmd);
int requestResponse(WifiRequest& request);
+ wifi_error kernelErrorToWifiHalError(int kerr);
+
protected:
wifi_handle wifiHandle() {
return getWifiHandle(mInfo);
+++ /dev/null
-
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/rtnetlink.h>
-#include <netpacket/packet.h>
-#include <linux/filter.h>
-#include <linux/errqueue.h>
-
-#include <linux/pkt_sched.h>
-#include <netlink/object-api.h>
-#include <netlink/netlink.h>
-#include <netlink/socket.h>
-#include <netlink/handlers.h>
-
-#include "sync.h"
-
-#define LOG_TAG "WifiHAL"
-
-#include <utils/Log.h>
-
-#include "wifi_hal.h"
-#include "common.h"
-#include "cpp_bindings.h"
-
-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<wifi_significant_change_result *>(&(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);
-}
-
+++ /dev/null
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/rtnetlink.h>
-#include <netpacket/packet.h>
-#include <linux/filter.h>
-#include <linux/errqueue.h>
-
-#include <linux/pkt_sched.h>
-#include <netlink/object-api.h>
-#include <netlink/netlink.h>
-#include <netlink/socket.h>
-
-#include "nl80211_copy.h"
-
-#include "sync.h"
-
-#define LOG_TAG "WifiHAL"
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#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();
-}
-
#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netlink/genl/genl.h>
#include "cpp_bindings.h"
#include "cutils/properties.h"
+template<typename>
+struct DummyFunction;
+
+template<typename R, typename... Args>
+struct DummyFunction<R (*)(Args...)> {
+ static constexpr R invoke(Args...) { return WIFI_SUCCESS; }
+};
+
+template<typename... Args>
+struct DummyFunction<void (*)(Args...)> {
+ static constexpr void invoke(Args...) { }
+};
+
+template<typename T>
+void populateDummyFor(T& val) {
+ val = &DummyFunction<T>::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
#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);
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 */
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;
}
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);
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++) {
// ALOGD("handling reponse in %s", __func__);
struct nlattr **tb = reply.attributes();
- struct genlmsghdr *gnlh = reply.header();
struct nlattr *mcgrp = NULL;
int i;
}
};
+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:
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;
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());
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);
}
}
}
};
+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);
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 {
closedir(d);
return WIFI_ERROR_OUT_OF_MEMORY;
}
+ memset(info->interfaces, 0, sizeof(interface_info *) * n);
int i = 0;
while ((de = readdir(d))) {
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);
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);
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)
{
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)
{
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)
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;
}
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;
-}
-
--- /dev/null
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink-private/object-api.h>
+#include <netlink-private/types.h>
+
+#include "nl80211_copy.h"
+#include "sync.h"
+
+#define LOG_TAG "WifiHAL"
+
+#include <log/log.h>
+
+#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);
+}
#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,
##### For Google SUPPLICANT #####
ifeq ($(MTKPATH),)
$(warning build BASIC wpa_supplicant)
+
WPA_SUPPL_DIR = external/wpa_supplicant_8
WPA_SRC_FILE :=
########################
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)
#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 )
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;
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");
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);
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)
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,
--- /dev/null
+/*
+ * Driver interaction with Linux nl80211/cfg80211
+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
+ * 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