upload android base code part4

This commit is contained in:
August 2018-08-08 17:00:29 +08:00
parent b9e30e05b1
commit 78ea2404cd
23455 changed files with 5250148 additions and 0 deletions

View file

@ -0,0 +1,3 @@
ifeq ($(BOARD_WIFI_VENDOR), realtek)
include $(call all-subdir-makefiles)
endif

View file

@ -0,0 +1,39 @@
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
########################
include $(CLEAR_VARS)
LOCAL_MODULE := dhcpcd.conf
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/dhcpcd
LOCAL_SRC_FILES := android_dhcpcd.conf
include $(BUILD_PREBUILT)
#########################
WIFI_DRIVER_SOCKET_IFACE := wlan0
ifeq ($(strip $(WPA_SUPPLICANT_VERSION)),VER_0_8_X)
include external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant_conf.mk
else
ifeq ($(strip $(WPA_SUPPLICANT_VERSION)),VER_0_6_X)
include external/wpa_supplicant_6/wpa_supplicant/wpa_supplicant_conf.mk
else
include external/wpa_supplicant/wpa_supplicant_conf.mk
endif
endif
#######################

View file

@ -0,0 +1,9 @@
# dhcpcd configuration for Android Wi-Fi interface
# See dhcpcd.conf(5) for details.
# Disable solicitation of IPv6 Router Advertisements
noipv6rs
interface wlan0
# dhcpcd-run-hooks uses these options.
option subnet_mask, routers, domain_name_servers, interface_mtu

View file

@ -0,0 +1,27 @@
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
PRODUCT_COPY_FILES += \
hardware/realtek/wlan/config/wpa_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant_overlay.conf \
hardware/realtek/wlan/config/p2p_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/p2p_supplicant_overlay.conf \
hardware/realtek/wlan/config/macprog.sh:$(TARGET_COPY_OUT_VENDOR)/xbin/macprog.sh \
device/softwinner/common/init.wireless.realtek.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.wireless.realtek.rc
PRODUCT_COPY_FILES += \
$(TOP_DIR)device/softwinner/$(basename $(TARGET_DEVICE))/configs/init.wireless.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.wireless.rc
PRODUCT_COPY_FILES += \
$(call find-copy-subdir-files,"wifi_efuse_*.map",$(TOP_DIR)device/softwinner/$(basename $(TARGET_DEVICE))/configs/,$(TARGET_COPY_OUT_VENDOR)/etc/wifi)

View file

@ -0,0 +1,72 @@
#!/vendor/bin/sh
macaddr=$(getprop ro.boot.mac)
macaddr=$(echo $macaddr | tr [a-z] [A-Z])
function verify()
{
local mac=$1
local ret=0
if [ -z "$mac" ]; then
ret=1
elif [ "$(echo $mac | wc -c)" -ne 18 ]; then
ret=1
elif [ "$mac" = "00:00:00:00:00:00" ]; then
ret=1
elif [ "$mac" = "FF:FF:FF:FF:FF:FF" ]; then
ret=1
elif [ "${mac:4:13}" = "7:13:36:E4:4B" ]; then
ret=1
elif [ "${mac:4:13}" = "9:CB:C9:A4:EC" ]; then
ret=1
fi
return $ret
}
verify $macaddr
if [ $? -ne "0" ]; then
macaddr="FC"
macaddr="$macaddr:$(printf "%02X" $((RANDOM/128)))"
macaddr="$macaddr:$(printf "%02X" $((RANDOM/128)))"
macaddr="$macaddr:$(printf "%02X" $((RANDOM/128)))"
macaddr="$macaddr:$(printf "%02X" $((RANDOM/128)))"
macaddr="$macaddr:$(printf "%02X" $((RANDOM/128)))"
fi
if [ -n "$macaddr" ]; then
base=0x${macaddr:0:2}
let "val=base&0xFC"
val=$(printf "%02X" $val)
macaddr=${val}${macaddr:2:15}
base=0x${macaddr:3:2}
wifi_file=/data/misc/wifi/wifimac.txt
bt_file=$(getprop ro.bt.bdaddr_path)
if [ -z "$bt_file" ]; then
bt_file=/data/misc/bluetooth/bdaddr
fi
if [ ! -f "$wifi_file" ]; then
let "val=base&0x0F|0x00"
val=$(printf "%02X" $val)
wlan_mac=${macaddr:0:3}${val}${macaddr:5:12}
echo $wlan_mac > $wifi_file
chmod 644 $wifi_file
fi
if [ ! -f "$bt_file" ]; then
let "val=base&0x0F|0x20"
val=$(printf "%02X" $val)
bt_mac=${macaddr:0:3}${val}${macaddr:5:12}
echo $bt_mac > $bt_file
chmod 644 $bt_file
fi
fi

View file

@ -0,0 +1 @@
wowlan_triggers=any

View file

@ -0,0 +1 @@
wowlan_triggers=any

View file

@ -0,0 +1,56 @@
# Copyright (C) 2011 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
# Make the HAL library
# ============================================================
include $(CLEAR_VARS)
LOCAL_CFLAGS := \
-Wall \
-Werror \
-Wno-format \
-Wno-reorder \
-Wno-unused-function \
-Wno-unused-parameter \
-Wno-unused-private-field \
-Wno-unused-variable \
LOCAL_C_INCLUDES += \
external/libnl/include \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
external/wpa_supplicant_8/src/drivers
LOCAL_SRC_FILES := \
wifi_hal.cpp \
rtt.cpp \
common.cpp \
cpp_bindings.cpp \
gscan.cpp \
link_layer_stats.cpp \
wifi_logger.cpp \
wifi_offload.cpp
LOCAL_SHARED_LIBRARIES := \
libnl \
libutils \
liblog
LOCAL_MODULE := libwifi-hal-rtk
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,261 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#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 "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
interface_info *getIfaceInfo(wifi_interface_handle handle)
{
return (interface_info *)handle;
}
wifi_handle getWifiHandle(wifi_interface_handle handle)
{
return getIfaceInfo(handle)->handle;
}
hal_info *getHalInfo(wifi_handle handle)
{
return (hal_info *)handle;
}
hal_info *getHalInfo(wifi_interface_handle handle)
{
return getHalInfo(getWifiHandle(handle));
}
wifi_handle getWifiHandle(hal_info *info)
{
return (wifi_handle)info;
}
wifi_interface_handle getIfaceHandle(interface_info *info)
{
return (wifi_interface_handle)info;
}
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
{
hal_info *info = (hal_info *)handle;
/* TODO: check for multiple handlers? */
pthread_mutex_lock(&info->cb_lock);
wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
if (info->num_event_cb < info->alloc_event_cb) {
info->event_cb[info->num_event_cb].nl_cmd = cmd;
info->event_cb[info->num_event_cb].vendor_id = 0;
info->event_cb[info->num_event_cb].vendor_subcmd = 0;
info->event_cb[info->num_event_cb].cb_func = func;
info->event_cb[info->num_event_cb].cb_arg = arg;
ALOGV("Successfully added event handler %p:%p for command %d at %d",
arg, func, cmd, info->num_event_cb);
info->num_event_cb++;
result = WIFI_SUCCESS;
}
pthread_mutex_unlock(&info->cb_lock);
return result;
}
wifi_error wifi_register_vendor_handler(wifi_handle handle,
uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
{
hal_info *info = (hal_info *)handle;
/* TODO: check for multiple handlers? */
pthread_mutex_lock(&info->cb_lock);
wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
if (info->num_event_cb < info->alloc_event_cb) {
info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR;
info->event_cb[info->num_event_cb].vendor_id = id;
info->event_cb[info->num_event_cb].vendor_subcmd = subcmd;
info->event_cb[info->num_event_cb].cb_func = func;
info->event_cb[info->num_event_cb].cb_arg = arg;
ALOGV("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
arg, func, id, subcmd, info->num_event_cb);
info->num_event_cb++;
result = WIFI_SUCCESS;
}
pthread_mutex_unlock(&info->cb_lock);
return result;
}
void wifi_unregister_handler(wifi_handle handle, int cmd)
{
hal_info *info = (hal_info *)handle;
if (cmd == NL80211_CMD_VENDOR) {
ALOGV("Must use wifi_unregister_vendor_handler to remove vendor handlers");
return;
}
pthread_mutex_lock(&info->cb_lock);
for (int i = 0; i < info->num_event_cb; i++) {
if (info->event_cb[i].nl_cmd == cmd) {
ALOGV("Successfully removed event handler %p:%p for cmd = 0x%0x from %d",
info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i);
memmove(&info->event_cb[i], &info->event_cb[i+1],
(info->num_event_cb - i - 1) * sizeof(cb_info));
info->num_event_cb--;
break;
}
}
pthread_mutex_unlock(&info->cb_lock);
}
void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
{
hal_info *info = (hal_info *)handle;
pthread_mutex_lock(&info->cb_lock);
for (int i = 0; i < info->num_event_cb; i++) {
if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
&& info->event_cb[i].vendor_id == id
&& info->event_cb[i].vendor_subcmd == subcmd) {
ALOGV("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i);
memmove(&info->event_cb[i], &info->event_cb[i+1],
(info->num_event_cb - i - 1) * sizeof(cb_info));
info->num_event_cb--;
break;
}
}
pthread_mutex_unlock(&info->cb_lock);
}
wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
{
hal_info *info = (hal_info *)handle;
ALOGV("registering command %d", id);
wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
if (info->num_cmd < info->alloc_cmd) {
info->cmd[info->num_cmd].id = id;
info->cmd[info->num_cmd].cmd = cmd;
ALOGV("Successfully added command %d: %p at %d", id, cmd, info->num_cmd);
info->num_cmd++;
result = WIFI_SUCCESS;
} else {
ALOGV("Failed to add command %d: %p at %d, reached max limit %d",
id, cmd, info->num_cmd, info->alloc_cmd);
}
return result;
}
WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id)
{
hal_info *info = (hal_info *)handle;
ALOGV("un-registering command %d", id);
WifiCommand *cmd = NULL;
for (int i = 0; i < info->num_cmd; i++) {
if (info->cmd[i].id == id) {
cmd = info->cmd[i].cmd;
memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i - 1) * sizeof(cmd_info));
info->num_cmd--;
ALOGV("Successfully removed command %d: %p from %d", id, cmd, i);
break;
}
}
if (!cmd) {
ALOGI("Failed to remove command %d: %p", id, cmd);
}
return cmd;
}
WifiCommand *wifi_get_cmd(wifi_handle handle, int id)
{
hal_info *info = (hal_info *)handle;
WifiCommand *cmd = NULL;
for (int i = 0; i < info->num_cmd; i++) {
if (info->cmd[i].id == id) {
cmd = info->cmd[i].cmd;
break;
}
}
return cmd;
}
void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd)
{
hal_info *info = (hal_info *)handle;
for (int i = 0; i < info->num_cmd; i++) {
if (info->cmd[i].cmd == cmd) {
int id = info->cmd[i].id;
memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i - 1) * sizeof(cmd_info));
info->num_cmd--;
ALOGV("Successfully removed command %d: %p from %d", id, cmd, i);
break;
}
}
}
wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
{
wifi_handle handle = getWifiHandle(iface);
WifiCommand *cmd = wifi_unregister_cmd(handle, id);
ALOGV("Cancel WifiCommand = %p", cmd);
if (cmd) {
cmd->cancel();
cmd->releaseRef();
return WIFI_SUCCESS;
}
return WIFI_ERROR_INVALID_ARGS;
}

View file

@ -0,0 +1,274 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wifi_hal.h"
#ifndef __WIFI_HAL_COMMON_H__
#define __WIFI_HAL_COMMON_H__
#define LOG_TAG "WifiHAL"
#include <utils/Log.h>
#include "nl80211_copy.h"
#include "sync.h"
#define SOCKET_BUFFER_SIZE (32768U)
#define RECV_BUF_SIZE (4096)
#define DEFAULT_EVENT_CB_SIZE (64)
#define DEFAULT_CMD_SIZE (64)
#define DOT11_OUI_LEN 3
#define DOT11_MAX_SSID_LEN 32
#define MAX_PROBE_RESP_IE_LEN 2048
/*
Vendor OUI - This is a unique identifier that identifies organization. Lets
code Android specific functions with Google OUI; although vendors can do more
with their own OUI's as well.
*/
const uint32_t GOOGLE_OUI = 0x001A11;
/* TODO: define vendor OUI here */
/*
This enum defines ranges for various commands; commands themselves
can be defined in respective feature headers; i.e. find gscan command
definitions in gscan.cpp
*/
typedef enum {
/* don't use 0 as a valid subcommand */
VENDOR_NL80211_SUBCMD_UNSPECIFIED,
/* define all vendor startup commands between 0x0 and 0x0FFF */
VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
/* define all GScan related commands between 0x1000 and 0x10FF */
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF,
/* define all RTT related commands between 0x1100 and 0x11FF */
ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
/* define all Logger related commands between 0x1400 and 0x14FF */
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
/* define all wifi offload related commands between 0x1600 and 0x16FF */
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
/* define all NAN related commands between 0x1700 and 0x17FF */
ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
/* define all Android Packet Filter related commands between 0x1800 and 0x18FF */
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
typedef enum {
GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */
GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */
GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */
GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */
GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */
GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */
GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */
GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */
GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */
WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */
WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */
WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */
WIFI_SUBCMD_NODFS_SET, /* 0x100D */
WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
/* Add more sub commands here */
GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */
WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */
GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
/* Add more sub commands here */
GSCAN_SUBCMD_MAX,
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
} WIFI_SUB_COMMAND;
typedef enum {
RTK_RESERVED1,
RTK_RESERVED2,
GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS ,
GSCAN_EVENT_HOTLIST_RESULTS_FOUND,
GSCAN_EVENT_SCAN_RESULTS_AVAILABLE,
GSCAN_EVENT_FULL_SCAN_RESULTS,
RTT_EVENT_COMPLETE,
GSCAN_EVENT_COMPLETE_SCAN,
GSCAN_EVENT_HOTLIST_RESULTS_LOST,
GSCAN_EVENT_EPNO_EVENT,
GOOGLE_DEBUG_RING_EVENT,
GOOGLE_DEBUG_MEM_DUMP_EVENT,
GSCAN_EVENT_ANQPO_HOTSPOT_MATCH,
GOOGLE_RSSI_MONITOR_EVENT
} WIFI_EVENT;
typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
class WifiCommand;
typedef struct {
int nl_cmd;
uint32_t vendor_id;
int vendor_subcmd;
nl_recvmsg_msg_cb_t cb_func;
void *cb_arg;
} cb_info;
typedef struct {
wifi_request_id id;
WifiCommand *cmd;
} cmd_info;
typedef struct {
wifi_handle handle; // handle to wifi data
char name[IFNAMSIZ+1]; // interface name + trailing null
int id; // id to use when talking to driver
} interface_info;
typedef struct {
struct nl_sock *cmd_sock; // command socket object
struct nl_sock *event_sock; // event socket object
int nl80211_family_id; // family id for 80211 driver
int cleanup_socks[2]; // sockets used to implement wifi_cleanup
bool in_event_loop; // Indicates that event loop is active
bool clean_up; // Indication to exit since cleanup has started
wifi_internal_event_handler event_handler; // default event handler
wifi_cleaned_up_handler cleaned_up_handler; // socket cleaned up handler
cb_info *event_cb; // event callbacks
int num_event_cb; // number of event callbacks
int alloc_event_cb; // number of allocated callback objects
pthread_mutex_t cb_lock; // mutex for the event_cb access
cmd_info *cmd; // Outstanding commands
int num_cmd; // number of commands
int alloc_cmd; // number of commands allocated
interface_info **interfaces; // array of interfaces
int num_interfaces; // number of interfaces
// add other details
} hal_info;
#define PNO_SSID_FOUND 0x1
#define PNO_SSID_LOST 0x2
typedef struct wifi_pno_result {
unsigned char ssid[DOT11_MAX_SSID_LEN];
unsigned char ssid_len;
signed char rssi;
u16 channel;
u16 flags;
mac_addr bssid;
} wifi_pno_result_t;
typedef struct wifi_gscan_result {
u64 ts; // Time of discovery
u8 ssid[DOT11_MAX_SSID_LEN+1]; // null terminated
mac_addr bssid; // BSSID
u32 channel; // channel frequency in MHz
s32 rssi; // in db
u64 rtt; // in nanoseconds
u64 rtt_sd; // standard deviation in rtt
u16 beacon_period; // units are Kusec
u16 capability; // Capability information
u32 pad;
} wifi_gscan_result_t;
typedef struct wifi_gscan_full_result {
wifi_gscan_result_t fixed;
u32 scan_ch_bucket; // scan chbucket bitmask
u32 ie_length; // byte length of Information Elements
u8 ie_data[1]; // IE data to follow
} wifi_gscan_full_result_t;
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
wifi_error wifi_register_vendor_handler(wifi_handle handle,
uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg);
void wifi_unregister_handler(wifi_handle handle, int cmd);
void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd);
wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd);
WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id);
WifiCommand *wifi_get_cmd(wifi_handle handle, int id);
void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd);
interface_info *getIfaceInfo(wifi_interface_handle);
wifi_handle getWifiHandle(wifi_interface_handle handle);
hal_info *getHalInfo(wifi_handle handle);
hal_info *getHalInfo(wifi_interface_handle handle);
wifi_handle getWifiHandle(hal_info *info);
wifi_interface_handle getIfaceHandle(interface_info *info);
wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
// some common macros
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
#define LOG_NDEBUG 1
#define NULL_CHECK_RETURN(ptr, str, ret) \
do { \
if (!(ptr)) { \
ALOGV("%s(): null pointer - #ptr (%s)\n", __FUNCTION__, str); \
return ret; \
} \
} while (0)
#endif

View file

@ -0,0 +1,748 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#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 <ctype.h>
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
void appendFmt(char *buf, int &offset, const char *fmt, ...)
{
va_list params;
va_start(params, fmt);
offset += vsprintf(buf + offset, fmt, params);
va_end(params);
}
#define C2S(x) case x: return #x;
static const char *cmdToString(int cmd)
{
switch (cmd) {
C2S(NL80211_CMD_UNSPEC)
C2S(NL80211_CMD_GET_WIPHY)
C2S(NL80211_CMD_SET_WIPHY)
C2S(NL80211_CMD_NEW_WIPHY)
C2S(NL80211_CMD_DEL_WIPHY)
C2S(NL80211_CMD_GET_INTERFACE)
C2S(NL80211_CMD_SET_INTERFACE)
C2S(NL80211_CMD_NEW_INTERFACE)
C2S(NL80211_CMD_DEL_INTERFACE)
C2S(NL80211_CMD_GET_KEY)
C2S(NL80211_CMD_SET_KEY)
C2S(NL80211_CMD_NEW_KEY)
C2S(NL80211_CMD_DEL_KEY)
C2S(NL80211_CMD_GET_BEACON)
C2S(NL80211_CMD_SET_BEACON)
C2S(NL80211_CMD_START_AP)
C2S(NL80211_CMD_STOP_AP)
C2S(NL80211_CMD_GET_STATION)
C2S(NL80211_CMD_SET_STATION)
C2S(NL80211_CMD_NEW_STATION)
C2S(NL80211_CMD_DEL_STATION)
C2S(NL80211_CMD_GET_MPATH)
C2S(NL80211_CMD_SET_MPATH)
C2S(NL80211_CMD_NEW_MPATH)
C2S(NL80211_CMD_DEL_MPATH)
C2S(NL80211_CMD_SET_BSS)
C2S(NL80211_CMD_SET_REG)
C2S(NL80211_CMD_REQ_SET_REG)
C2S(NL80211_CMD_GET_MESH_CONFIG)
C2S(NL80211_CMD_SET_MESH_CONFIG)
C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
C2S(NL80211_CMD_GET_REG)
C2S(NL80211_CMD_GET_SCAN)
C2S(NL80211_CMD_TRIGGER_SCAN)
C2S(NL80211_CMD_NEW_SCAN_RESULTS)
C2S(NL80211_CMD_SCAN_ABORTED)
C2S(NL80211_CMD_REG_CHANGE)
C2S(NL80211_CMD_AUTHENTICATE)
C2S(NL80211_CMD_ASSOCIATE)
C2S(NL80211_CMD_DEAUTHENTICATE)
C2S(NL80211_CMD_DISASSOCIATE)
C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
C2S(NL80211_CMD_REG_BEACON_HINT)
C2S(NL80211_CMD_JOIN_IBSS)
C2S(NL80211_CMD_LEAVE_IBSS)
C2S(NL80211_CMD_TESTMODE)
C2S(NL80211_CMD_CONNECT)
C2S(NL80211_CMD_ROAM)
C2S(NL80211_CMD_DISCONNECT)
C2S(NL80211_CMD_SET_WIPHY_NETNS)
C2S(NL80211_CMD_GET_SURVEY)
C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
C2S(NL80211_CMD_SET_PMKSA)
C2S(NL80211_CMD_DEL_PMKSA)
C2S(NL80211_CMD_FLUSH_PMKSA)
C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
C2S(NL80211_CMD_REGISTER_FRAME)
C2S(NL80211_CMD_FRAME)
C2S(NL80211_CMD_FRAME_TX_STATUS)
C2S(NL80211_CMD_SET_POWER_SAVE)
C2S(NL80211_CMD_GET_POWER_SAVE)
C2S(NL80211_CMD_SET_CQM)
C2S(NL80211_CMD_NOTIFY_CQM)
C2S(NL80211_CMD_SET_CHANNEL)
C2S(NL80211_CMD_SET_WDS_PEER)
C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
C2S(NL80211_CMD_JOIN_MESH)
C2S(NL80211_CMD_LEAVE_MESH)
C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
C2S(NL80211_CMD_GET_WOWLAN)
C2S(NL80211_CMD_SET_WOWLAN)
C2S(NL80211_CMD_START_SCHED_SCAN)
C2S(NL80211_CMD_STOP_SCHED_SCAN)
C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
C2S(NL80211_CMD_PMKSA_CANDIDATE)
C2S(NL80211_CMD_TDLS_OPER)
C2S(NL80211_CMD_TDLS_MGMT)
C2S(NL80211_CMD_UNEXPECTED_FRAME)
C2S(NL80211_CMD_PROBE_CLIENT)
C2S(NL80211_CMD_REGISTER_BEACONS)
C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
C2S(NL80211_CMD_SET_NOACK_MAP)
C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
C2S(NL80211_CMD_START_P2P_DEVICE)
C2S(NL80211_CMD_STOP_P2P_DEVICE)
C2S(NL80211_CMD_CONN_FAILED)
C2S(NL80211_CMD_SET_MCAST_RATE)
C2S(NL80211_CMD_SET_MAC_ACL)
C2S(NL80211_CMD_RADAR_DETECT)
C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
C2S(NL80211_CMD_UPDATE_FT_IES)
C2S(NL80211_CMD_FT_EVENT)
C2S(NL80211_CMD_CRIT_PROTOCOL_START)
C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
C2S(NL80211_CMD_GET_COALESCE)
C2S(NL80211_CMD_SET_COALESCE)
C2S(NL80211_CMD_CHANNEL_SWITCH)
C2S(NL80211_CMD_VENDOR)
C2S(NL80211_CMD_SET_QOS_MAP)
default:
return "NL80211_CMD_UNKNOWN";
}
}
const char *attributeToString(int attribute)
{
switch (attribute) {
C2S(NL80211_ATTR_UNSPEC)
C2S(NL80211_ATTR_WIPHY)
C2S(NL80211_ATTR_WIPHY_NAME)
C2S(NL80211_ATTR_IFINDEX)
C2S(NL80211_ATTR_IFNAME)
C2S(NL80211_ATTR_IFTYPE)
C2S(NL80211_ATTR_MAC)
C2S(NL80211_ATTR_KEY_DATA)
C2S(NL80211_ATTR_KEY_IDX)
C2S(NL80211_ATTR_KEY_CIPHER)
C2S(NL80211_ATTR_KEY_SEQ)
C2S(NL80211_ATTR_KEY_DEFAULT)
C2S(NL80211_ATTR_BEACON_INTERVAL)
C2S(NL80211_ATTR_DTIM_PERIOD)
C2S(NL80211_ATTR_BEACON_HEAD)
C2S(NL80211_ATTR_BEACON_TAIL)
C2S(NL80211_ATTR_STA_AID)
C2S(NL80211_ATTR_STA_FLAGS)
C2S(NL80211_ATTR_STA_LISTEN_INTERVAL)
C2S(NL80211_ATTR_STA_SUPPORTED_RATES)
C2S(NL80211_ATTR_STA_VLAN)
C2S(NL80211_ATTR_STA_INFO)
C2S(NL80211_ATTR_WIPHY_BANDS)
C2S(NL80211_ATTR_MNTR_FLAGS)
C2S(NL80211_ATTR_MESH_ID)
C2S(NL80211_ATTR_STA_PLINK_ACTION)
C2S(NL80211_ATTR_MPATH_NEXT_HOP)
C2S(NL80211_ATTR_MPATH_INFO)
C2S(NL80211_ATTR_BSS_CTS_PROT)
C2S(NL80211_ATTR_BSS_SHORT_PREAMBLE)
C2S(NL80211_ATTR_BSS_SHORT_SLOT_TIME)
C2S(NL80211_ATTR_HT_CAPABILITY)
C2S(NL80211_ATTR_SUPPORTED_IFTYPES)
C2S(NL80211_ATTR_REG_ALPHA2)
C2S(NL80211_ATTR_REG_RULES)
C2S(NL80211_ATTR_MESH_CONFIG)
C2S(NL80211_ATTR_BSS_BASIC_RATES)
C2S(NL80211_ATTR_WIPHY_TXQ_PARAMS)
C2S(NL80211_ATTR_WIPHY_FREQ)
C2S(NL80211_ATTR_WIPHY_CHANNEL_TYPE)
C2S(NL80211_ATTR_KEY_DEFAULT_MGMT)
C2S(NL80211_ATTR_MGMT_SUBTYPE)
C2S(NL80211_ATTR_IE)
C2S(NL80211_ATTR_MAX_NUM_SCAN_SSIDS)
C2S(NL80211_ATTR_SCAN_FREQUENCIES)
C2S(NL80211_ATTR_SCAN_SSIDS)
C2S(NL80211_ATTR_GENERATION) /* replaces old SCAN_GENERATION */
C2S(NL80211_ATTR_BSS)
C2S(NL80211_ATTR_REG_INITIATOR)
C2S(NL80211_ATTR_REG_TYPE)
C2S(NL80211_ATTR_SUPPORTED_COMMANDS)
C2S(NL80211_ATTR_FRAME)
C2S(NL80211_ATTR_SSID)
C2S(NL80211_ATTR_AUTH_TYPE)
C2S(NL80211_ATTR_REASON_CODE)
C2S(NL80211_ATTR_KEY_TYPE)
C2S(NL80211_ATTR_MAX_SCAN_IE_LEN)
C2S(NL80211_ATTR_CIPHER_SUITES)
C2S(NL80211_ATTR_FREQ_BEFORE)
C2S(NL80211_ATTR_FREQ_AFTER)
C2S(NL80211_ATTR_FREQ_FIXED)
C2S(NL80211_ATTR_WIPHY_RETRY_SHORT)
C2S(NL80211_ATTR_WIPHY_RETRY_LONG)
C2S(NL80211_ATTR_WIPHY_FRAG_THRESHOLD)
C2S(NL80211_ATTR_WIPHY_RTS_THRESHOLD)
C2S(NL80211_ATTR_TIMED_OUT)
C2S(NL80211_ATTR_USE_MFP)
C2S(NL80211_ATTR_STA_FLAGS2)
C2S(NL80211_ATTR_CONTROL_PORT)
C2S(NL80211_ATTR_TESTDATA)
C2S(NL80211_ATTR_PRIVACY)
C2S(NL80211_ATTR_DISCONNECTED_BY_AP)
C2S(NL80211_ATTR_STATUS_CODE)
C2S(NL80211_ATTR_CIPHER_SUITES_PAIRWISE)
C2S(NL80211_ATTR_CIPHER_SUITE_GROUP)
C2S(NL80211_ATTR_WPA_VERSIONS)
C2S(NL80211_ATTR_AKM_SUITES)
C2S(NL80211_ATTR_REQ_IE)
C2S(NL80211_ATTR_RESP_IE)
C2S(NL80211_ATTR_PREV_BSSID)
C2S(NL80211_ATTR_KEY)
C2S(NL80211_ATTR_KEYS)
C2S(NL80211_ATTR_PID)
C2S(NL80211_ATTR_4ADDR)
C2S(NL80211_ATTR_SURVEY_INFO)
C2S(NL80211_ATTR_PMKID)
C2S(NL80211_ATTR_MAX_NUM_PMKIDS)
C2S(NL80211_ATTR_DURATION)
C2S(NL80211_ATTR_COOKIE)
C2S(NL80211_ATTR_WIPHY_COVERAGE_CLASS)
C2S(NL80211_ATTR_TX_RATES)
C2S(NL80211_ATTR_FRAME_MATCH)
C2S(NL80211_ATTR_ACK)
C2S(NL80211_ATTR_PS_STATE)
C2S(NL80211_ATTR_CQM)
C2S(NL80211_ATTR_LOCAL_STATE_CHANGE)
C2S(NL80211_ATTR_AP_ISOLATE)
C2S(NL80211_ATTR_WIPHY_TX_POWER_SETTING)
C2S(NL80211_ATTR_WIPHY_TX_POWER_LEVEL)
C2S(NL80211_ATTR_TX_FRAME_TYPES)
C2S(NL80211_ATTR_RX_FRAME_TYPES)
C2S(NL80211_ATTR_FRAME_TYPE)
C2S(NL80211_ATTR_CONTROL_PORT_ETHERTYPE)
C2S(NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)
C2S(NL80211_ATTR_SUPPORT_IBSS_RSN)
C2S(NL80211_ATTR_WIPHY_ANTENNA_TX)
C2S(NL80211_ATTR_WIPHY_ANTENNA_RX)
C2S(NL80211_ATTR_MCAST_RATE)
C2S(NL80211_ATTR_OFFCHANNEL_TX_OK)
C2S(NL80211_ATTR_BSS_HT_OPMODE)
C2S(NL80211_ATTR_KEY_DEFAULT_TYPES)
C2S(NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION)
C2S(NL80211_ATTR_MESH_SETUP)
C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX)
C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX)
C2S(NL80211_ATTR_SUPPORT_MESH_AUTH)
C2S(NL80211_ATTR_STA_PLINK_STATE)
C2S(NL80211_ATTR_WOWLAN_TRIGGERS)
C2S(NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED)
C2S(NL80211_ATTR_SCHED_SCAN_INTERVAL)
C2S(NL80211_ATTR_INTERFACE_COMBINATIONS)
C2S(NL80211_ATTR_SOFTWARE_IFTYPES)
C2S(NL80211_ATTR_REKEY_DATA)
C2S(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS)
C2S(NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN)
C2S(NL80211_ATTR_SCAN_SUPP_RATES)
C2S(NL80211_ATTR_HIDDEN_SSID)
C2S(NL80211_ATTR_IE_PROBE_RESP)
C2S(NL80211_ATTR_IE_ASSOC_RESP)
C2S(NL80211_ATTR_STA_WME)
C2S(NL80211_ATTR_SUPPORT_AP_UAPSD)
C2S(NL80211_ATTR_ROAM_SUPPORT)
C2S(NL80211_ATTR_SCHED_SCAN_MATCH)
C2S(NL80211_ATTR_MAX_MATCH_SETS)
C2S(NL80211_ATTR_PMKSA_CANDIDATE)
C2S(NL80211_ATTR_TX_NO_CCK_RATE)
C2S(NL80211_ATTR_TDLS_ACTION)
C2S(NL80211_ATTR_TDLS_DIALOG_TOKEN)
C2S(NL80211_ATTR_TDLS_OPERATION)
C2S(NL80211_ATTR_TDLS_SUPPORT)
C2S(NL80211_ATTR_TDLS_EXTERNAL_SETUP)
C2S(NL80211_ATTR_DEVICE_AP_SME)
C2S(NL80211_ATTR_DONT_WAIT_FOR_ACK)
C2S(NL80211_ATTR_FEATURE_FLAGS)
C2S(NL80211_ATTR_PROBE_RESP_OFFLOAD)
C2S(NL80211_ATTR_PROBE_RESP)
C2S(NL80211_ATTR_DFS_REGION)
C2S(NL80211_ATTR_DISABLE_HT)
C2S(NL80211_ATTR_HT_CAPABILITY_MASK)
C2S(NL80211_ATTR_NOACK_MAP)
C2S(NL80211_ATTR_INACTIVITY_TIMEOUT)
C2S(NL80211_ATTR_RX_SIGNAL_DBM)
C2S(NL80211_ATTR_BG_SCAN_PERIOD)
C2S(NL80211_ATTR_WDEV)
C2S(NL80211_ATTR_USER_REG_HINT_TYPE)
C2S(NL80211_ATTR_CONN_FAILED_REASON)
C2S(NL80211_ATTR_SAE_DATA)
C2S(NL80211_ATTR_VHT_CAPABILITY)
C2S(NL80211_ATTR_SCAN_FLAGS)
C2S(NL80211_ATTR_CHANNEL_WIDTH)
C2S(NL80211_ATTR_CENTER_FREQ1)
C2S(NL80211_ATTR_CENTER_FREQ2)
C2S(NL80211_ATTR_P2P_CTWINDOW)
C2S(NL80211_ATTR_P2P_OPPPS)
C2S(NL80211_ATTR_LOCAL_MESH_POWER_MODE)
C2S(NL80211_ATTR_ACL_POLICY)
C2S(NL80211_ATTR_MAC_ADDRS)
C2S(NL80211_ATTR_MAC_ACL_MAX)
C2S(NL80211_ATTR_RADAR_EVENT)
C2S(NL80211_ATTR_EXT_CAPA)
C2S(NL80211_ATTR_EXT_CAPA_MASK)
C2S(NL80211_ATTR_STA_CAPABILITY)
C2S(NL80211_ATTR_STA_EXT_CAPABILITY)
C2S(NL80211_ATTR_PROTOCOL_FEATURES)
C2S(NL80211_ATTR_SPLIT_WIPHY_DUMP)
C2S(NL80211_ATTR_DISABLE_VHT)
C2S(NL80211_ATTR_VHT_CAPABILITY_MASK)
C2S(NL80211_ATTR_MDID)
C2S(NL80211_ATTR_IE_RIC)
C2S(NL80211_ATTR_CRIT_PROT_ID)
C2S(NL80211_ATTR_MAX_CRIT_PROT_DURATION)
C2S(NL80211_ATTR_PEER_AID)
C2S(NL80211_ATTR_COALESCE_RULE)
C2S(NL80211_ATTR_CH_SWITCH_COUNT)
C2S(NL80211_ATTR_CH_SWITCH_BLOCK_TX)
C2S(NL80211_ATTR_CSA_IES)
C2S(NL80211_ATTR_CSA_C_OFF_BEACON)
C2S(NL80211_ATTR_CSA_C_OFF_PRESP)
C2S(NL80211_ATTR_RXMGMT_FLAGS)
C2S(NL80211_ATTR_STA_SUPPORTED_CHANNELS)
C2S(NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES)
C2S(NL80211_ATTR_HANDLE_DFS)
C2S(NL80211_ATTR_SUPPORT_5_MHZ)
C2S(NL80211_ATTR_SUPPORT_10_MHZ)
C2S(NL80211_ATTR_OPMODE_NOTIF)
C2S(NL80211_ATTR_VENDOR_ID)
C2S(NL80211_ATTR_VENDOR_SUBCMD)
C2S(NL80211_ATTR_VENDOR_DATA)
C2S(NL80211_ATTR_VENDOR_EVENTS)
C2S(NL80211_ATTR_QOS_MAP)
default:
return "NL80211_ATTR_UNKNOWN";
}
}
void WifiEvent::log() {
parse();
byte *data = (byte *)genlmsg_attrdata(mHeader, 0);
int len = genlmsg_attrlen(mHeader, 0);
ALOGD("cmd = %s, len = %d", get_cmdString(), len);
ALOGD("vendor_id = %04x, vendor_subcmd = %d", get_vendor_id(), get_vendor_subcmd());
for (int i = 0; i < len; i += 16) {
char line[81];
int linelen = min(16, len - i);
int offset = 0;
appendFmt(line, offset, "%02x", data[i]);
for (int j = 1; j < linelen; j++) {
appendFmt(line, offset, " %02x", data[i+j]);
}
for (int j = linelen; j < 16; j++) {
appendFmt(line, offset, " ");
}
line[23] = '-';
appendFmt(line, offset, " ");
for (int j = 0; j < linelen; j++) {
if (isprint(data[i+j])) {
appendFmt(line, offset, "%c", data[i+j]);
} else {
appendFmt(line, offset, "-");
}
}
ALOGD("%s", line);
}
for (unsigned i = 0; i < NL80211_ATTR_MAX_INTERNAL; i++) {
if (mAttributes[i] != NULL) {
ALOGD("found attribute %s", attributeToString(i));
}
}
ALOGD("-- End of message --");
}
const char *WifiEvent::get_cmdString() {
return cmdToString(get_cmd());
}
int WifiEvent::parse() {
if (mHeader != NULL) {
return WIFI_SUCCESS;
}
mHeader = (genlmsghdr *)nlmsg_data(nlmsg_hdr(mMsg));
int result = nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(mHeader, 0),
genlmsg_attrlen(mHeader, 0), NULL);
// ALOGD("event len = %d", nlmsg_hdr(mMsg)->nlmsg_len);
return result;
}
int WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) {
destroy();
mMsg = nlmsg_alloc();
if (mMsg != NULL) {
genlmsg_put(mMsg, /* pid = */ 0, /* seq = */ 0, family,
hdrlen, flags, cmd, /* version = */ 0);
return WIFI_SUCCESS;
} else {
return WIFI_ERROR_OUT_OF_MEMORY;
}
}
int WifiRequest::create(uint32_t id, int subcmd) {
int res = create(NL80211_CMD_VENDOR);
if (res < 0) {
return res;
}
res = put_u32(NL80211_ATTR_VENDOR_ID, id);
if (res < 0) {
return res;
}
res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd);
if (res < 0) {
return res;
}
if (mIface != -1) {
res = set_iface_id(mIface);
}
return res;
}
static int no_seq_check(struct nl_msg *msg, void *arg)
{
return NL_OK;
}
int WifiCommand::requestResponse() {
int err = create(); /* create the message */
if (err < 0) {
return err;
}
return requestResponse(mMsg);
}
int WifiCommand::requestResponse(WifiRequest& request) {
int err = 0;
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb)
goto out;
err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* send message */
if (err < 0)
goto out;
err = 1;
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, response_handler, this);
while (err > 0) { /* wait for reply */
int res = nl_recvmsgs(mInfo->cmd_sock, cb);
if (res) {
ALOGV("nl80211: %s->nl_recvmsgs failed: %d", __func__, res);
}
}
out:
nl_cb_put(cb);
return err;
}
int WifiCommand::requestEvent(int cmd) {
ALOGD("requesting event %d", cmd);
int res = wifi_register_handler(wifiHandle(), cmd, event_handler, this);
if (res < 0) {
return res;
}
res = create(); /* create the message */
if (res < 0)
goto out;
ALOGD("waiting for response %d", cmd);
res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */
if (res < 0)
goto out;
ALOGD("waiting for event %d", cmd);
res = mCondition.wait();
if (res < 0)
goto out;
out:
wifi_unregister_handler(wifiHandle(), cmd);
return res;
}
int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) {
int res = wifi_register_vendor_handler(wifiHandle(), id, subcmd, event_handler, this);
if (res < 0) {
return res;
}
res = create(); /* create the message */
if (res < 0)
goto out;
res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */
if (res < 0)
goto out;
res = mCondition.wait();
if (res < 0)
goto out;
out:
wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
return res;
}
/* Event handlers */
int WifiCommand::response_handler(struct nl_msg *msg, void *arg) {
// ALOGD("response_handler called");
WifiCommand *cmd = (WifiCommand *)arg;
WifiEvent reply(msg);
int res = reply.parse();
if (res < 0) {
ALOGV("Failed to parse reply message = %d", res);
return NL_SKIP;
} else {
// reply.log();
return cmd->handleResponse(reply);
}
}
int WifiCommand::event_handler(struct nl_msg *msg, void *arg) {
WifiCommand *cmd = (WifiCommand *)arg;
WifiEvent event(msg);
int res = event.parse();
if (res < 0) {
ALOGV("Failed to parse event = %d", res);
res = NL_SKIP;
} else {
res = cmd->handleEvent(event);
}
cmd->mCondition.signal();
return res;
}
/* Other event handlers */
int WifiCommand::valid_handler(struct nl_msg *msg, void *arg) {
// ALOGD("valid_handler called");
int *err = (int *)arg;
*err = 0;
return NL_SKIP;
}
int WifiCommand::ack_handler(struct nl_msg *msg, void *arg) {
// ALOGD("ack_handler called");
int *err = (int *)arg;
*err = 0;
return NL_STOP;
}
int WifiCommand::finish_handler(struct nl_msg *msg, void *arg) {
// ALOGD("finish_handler called");
int *ret = (int *)arg;
*ret = 0;
return NL_SKIP;
}
int WifiCommand::error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
int *ret = (int *)arg;
*ret = err->error;
// ALOGD("error_handler received : %d", err->error);
return NL_SKIP;
}

View file

@ -0,0 +1,367 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wifi_hal.h"
#include "common.h"
#include "sync.h"
class WifiEvent
{
/* TODO: remove this when nl headers are updated */
static const unsigned NL80211_ATTR_MAX_INTERNAL = 256;
private:
struct nl_msg *mMsg;
struct genlmsghdr *mHeader;
struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
public:
WifiEvent(nl_msg *msg) {
mMsg = msg;
mHeader = NULL;
memset(mAttributes, 0, sizeof(mAttributes));
}
~WifiEvent() {
/* don't destroy mMsg; it doesn't belong to us */
}
void log();
int parse();
genlmsghdr *header() {
return mHeader;
}
int get_cmd() {
return mHeader->cmd;
}
int get_vendor_id() {
return get_u32(NL80211_ATTR_VENDOR_ID);
}
int get_vendor_subcmd() {
return get_u32(NL80211_ATTR_VENDOR_SUBCMD);
}
void *get_vendor_data() {
return get_data(NL80211_ATTR_VENDOR_DATA);
}
int get_vendor_data_len() {
return get_len(NL80211_ATTR_VENDOR_DATA);
}
const char *get_cmdString();
nlattr ** attributes() {
return mAttributes;
}
nlattr *get_attribute(int attribute) {
return mAttributes[attribute];
}
uint8_t get_u8(int attribute) {
return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0;
}
uint16_t get_u16(int attribute) {
return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0;
}
uint32_t get_u32(int attribute) {
return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0;
}
uint64_t get_u64(int attribute) {
return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0;
}
int get_len(int attribute) {
return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0;
}
void *get_data(int attribute) {
return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
}
private:
WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies
};
class nl_iterator {
struct nlattr *pos;
int rem;
public:
nl_iterator(struct nlattr *attr) {
pos = (struct nlattr *)nla_data(attr);
rem = nla_len(attr);
}
bool has_next() {
return nla_ok(pos, rem);
}
void next() {
pos = (struct nlattr *)nla_next(pos, &(rem));
}
struct nlattr *get() {
return pos;
}
uint16_t get_type() {
return pos->nla_type;
}
uint8_t get_u8() {
return nla_get_u8(pos);
}
uint16_t get_u16() {
return nla_get_u16(pos);
}
uint32_t get_u32() {
return nla_get_u32(pos);
}
uint64_t get_u64() {
return nla_get_u64(pos);
}
void* get_data() {
return nla_data(pos);
}
int get_len() {
return nla_len(pos);
}
private:
nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies
};
class WifiRequest
{
private:
int mFamily;
int mIface;
struct nl_msg *mMsg;
public:
WifiRequest(int family) {
mMsg = NULL;
mFamily = family;
mIface = -1;
}
WifiRequest(int family, int iface) {
mMsg = NULL;
mFamily = family;
mIface = iface;
}
~WifiRequest() {
destroy();
}
void destroy() {
if (mMsg) {
nlmsg_free(mMsg);
mMsg = NULL;
}
}
nl_msg *getMessage() {
return mMsg;
}
/* Command assembly helpers */
int create(int family, uint8_t cmd, int flags, int hdrlen);
int create(uint8_t cmd) {
return create(mFamily, cmd, 0, 0);
}
int create(uint32_t id, int subcmd);
int put(int attribute, void *ptr, unsigned len) {
return nla_put(mMsg, attribute, len, ptr);
}
int put_u8(int attribute, uint8_t value) {
return nla_put(mMsg, attribute, sizeof(value), &value);
}
int put_u16(int attribute, uint16_t value) {
return nla_put(mMsg, attribute, sizeof(value), &value);
}
int put_u32(int attribute, uint32_t value) {
return nla_put(mMsg, attribute, sizeof(value), &value);
}
int put_u64(int attribute, uint64_t value) {
return nla_put(mMsg, attribute, sizeof(value), &value);
}
int put_string(int attribute, const char *value) {
return nla_put(mMsg, attribute, strlen(value) + 1, value);
}
int put_addr(int attribute, mac_addr value) {
return nla_put(mMsg, attribute, sizeof(mac_addr), value);
}
struct nlattr * attr_start(int attribute) {
return nla_nest_start(mMsg, attribute);
}
void attr_end(struct nlattr *attr) {
nla_nest_end(mMsg, attr);
}
int set_iface_id(int ifindex) {
return put_u32(NL80211_ATTR_IFINDEX, ifindex);
}
private:
WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies
};
class WifiCommand
{
protected:
const char *mCmdType;
hal_info *mInfo;
WifiRequest mMsg;
Condition mCondition;
wifi_request_id mReqId;
interface_info *mIfaceInfo;
int mRefs;
public:
WifiCommand(const char *type, wifi_handle handle, wifi_request_id id)
: mCmdType(type), mMsg(getHalInfo(handle)->nl80211_family_id), mReqId(id), mRefs(1)
{
mIfaceInfo = NULL;
mInfo = getHalInfo(handle);
// ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
}
WifiCommand(const char *type, wifi_interface_handle iface, wifi_request_id id)
: mCmdType(type), mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id),
mReqId(id), mRefs(1)
{
mIfaceInfo = getIfaceInfo(iface);
mInfo = getHalInfo(iface);
// ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
}
virtual ~WifiCommand() {
// ALOGD("WifiCommand %p destroyed", this);
}
wifi_request_id id() {
return mReqId;
}
const char *getType() {
return mCmdType;
}
virtual void addRef() {
int refs = __sync_add_and_fetch(&mRefs, 1);
// ALOGD("addRef: WifiCommand %p has %d references", this, refs);
}
virtual void releaseRef() {
int refs = __sync_sub_and_fetch(&mRefs, 1);
if (refs == 0) {
delete this;
} else {
// ALOGD("releaseRef: WifiCommand %p has %d references", this, refs);
}
}
virtual int create() {
/* by default there is no way to cancel */
ALOGD("WifiCommand %p can't be created", this);
return WIFI_ERROR_NOT_SUPPORTED;
}
virtual int cancel() {
/* by default there is no way to cancel */
return WIFI_ERROR_NOT_SUPPORTED;
}
int requestResponse();
int requestEvent(int cmd);
int requestVendorEvent(uint32_t id, int subcmd);
int requestResponse(WifiRequest& request);
protected:
wifi_handle wifiHandle() {
return getWifiHandle(mInfo);
}
wifi_interface_handle ifaceHandle() {
return getIfaceHandle(mIfaceInfo);
}
int familyId() {
return mInfo->nl80211_family_id;
}
int ifaceId() {
return mIfaceInfo->id;
}
/* Override this method to parse reply and dig out data; save it in the object */
virtual int handleResponse(WifiEvent& reply) {
ALOGI("skipping a response");
return NL_SKIP;
}
/* Override this method to parse event and dig out data; save it in the object */
virtual int handleEvent(WifiEvent& event) {
ALOGI("skipping an event");
return NL_SKIP;
}
int registerHandler(int cmd) {
return wifi_register_handler(wifiHandle(), cmd, &event_handler, this);
}
void unregisterHandler(int cmd) {
wifi_unregister_handler(wifiHandle(), cmd);
}
int registerVendorHandler(uint32_t id, int subcmd) {
return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
}
void unregisterVendorHandler(uint32_t id, int subcmd) {
wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
}
private:
WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies
/* Event handling */
static int response_handler(struct nl_msg *msg, void *arg);
static int event_handler(struct nl_msg *msg, void *arg);
/* Other event handlers */
static int valid_handler(struct nl_msg *msg, void *arg);
static int ack_handler(struct nl_msg *msg, void *arg);
static int finish_handler(struct nl_msg *msg, void *arg);
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
};
/* nl message processing macros (required to pass C++ type checks) */
#define for_each_attr(pos, nla, rem) \
for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \
nla_ok(pos, rem); \
pos = (nlattr *)nla_next(pos, &(rem)))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,256 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#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"
/* Internal radio statistics structure in the driver */
typedef struct {
wifi_radio radio;
uint32_t on_time;
uint32_t tx_time;
uint32_t rx_time;
uint32_t on_time_scan;
uint32_t on_time_nbd;
uint32_t on_time_gscan;
uint32_t on_time_roam_scan;
uint32_t on_time_pno_scan;
uint32_t on_time_hs20;
uint32_t num_channels;
wifi_channel_stat channels[];
} wifi_radio_stat_internal;
enum {
LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
LSTATS_SUBCMD_SET_INFO,
LSTATS_SUBCMD_CLEAR_INFO,
};
class GetLinkStatsCommand : public WifiCommand
{
wifi_stats_result_handler mHandler;
public:
GetLinkStatsCommand(wifi_interface_handle iface, wifi_stats_result_handler handler)
: WifiCommand("GetLinkStatsCommand", iface, 0), mHandler(handler)
{ }
virtual int create() {
// ALOGI("Creating message to get link statistics; iface = %d", mIfaceInfo->id);
int ret = mMsg.create(GOOGLE_OUI, LSTATS_SUBCMD_GET_INFO);
if (ret < 0) {
ALOGV("Failed to create %x - %d", LSTATS_SUBCMD_GET_INFO, ret);
return ret;
}
return ret;
}
protected:
virtual int handleResponse(WifiEvent& reply) {
// ALOGI("In GetLinkStatsCommand::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();
// ALOGI("Id = %0x, subcmd = %d", id, subcmd);
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
wifi_radio_stat *radio_stat = (wifi_radio_stat *)data;
if (!radio_stat) {
ALOGV("Invalid stats pointer received");
return NL_SKIP;
}
ALOGV("radio: = %d", radio_stat->radio);
ALOGV("on_time: = %u ms", radio_stat->on_time);
ALOGV("tx_time: = %u ms", radio_stat->tx_time);
ALOGV("num_tx_levels: = %u", radio_stat->num_tx_levels);
radio_stat->tx_time_per_levels = (u32*)((char*)data + sizeof(wifi_radio_stat) + sizeof(wifi_iface_stat));
ALOGV("tx_time_per_levels: = %u ms", radio_stat->tx_time_per_levels[0]);
ALOGV("rx_time: = %u ms", radio_stat->rx_time);
ALOGV("on_time_scan: = %u ms", radio_stat->on_time_scan);
ALOGV("on_time_nbd: = %u ms", radio_stat->on_time_nbd);
ALOGV("on_time_gscan: = %u ms", radio_stat->on_time_gscan);
ALOGV("on_time_pno_scan: = %u ms", radio_stat->on_time_pno_scan);
ALOGV("on_time_hs20: = %u ms", radio_stat->on_time_hs20);
if (radio_stat->num_channels > 11) {
ALOGV("Incorrect number of channels = %d", radio_stat->num_channels);
// dump data before num_channels
ALOGV("radio: = %d", radio_stat->radio);
ALOGV("on_time: = %u ms", radio_stat->on_time);
ALOGV("tx_time: = %u ms", radio_stat->tx_time);
ALOGV("rx_time: = %u ms", radio_stat->rx_time);
ALOGV("on_time_scan: = %u ms", radio_stat->on_time_scan);
ALOGV("on_time_nbd: = %u ms", radio_stat->on_time_nbd);
ALOGV("on_time_gscan: = %u ms", radio_stat->on_time_gscan);
ALOGV("on_time_pno_scan: = %u ms", radio_stat->on_time_pno_scan);
ALOGV("on_time_hs20: = %u ms", radio_stat->on_time_hs20);
free(radio_stat);
return NL_SKIP;
}
wifi_iface_stat *iface_stat = NULL;
iface_stat = (wifi_iface_stat *)((char* )data + sizeof(wifi_radio_stat));
if(*mHandler.on_link_stats_results == NULL) {
ALOGV("*mHandler.on_link_stats_results is NULL");
} else {
(*mHandler.on_link_stats_results)(id, iface_stat, 1, radio_stat);
}
//free(radio_stat);
return NL_OK;
}
};
class SetLinkStatsCommand : public WifiCommand
{
wifi_stats_result_handler mHandler;
public:
SetLinkStatsCommand(wifi_interface_handle iface)
: WifiCommand("SetLinkStatsCommand", iface, 0)
{ }
virtual int create() {
// ALOGI("Creating message to get link statistics; iface = %d", mIfaceInfo->id);
int ret = mMsg.create(GOOGLE_OUI, LSTATS_SUBCMD_SET_INFO);
if (ret < 0) {
ALOGV("Failed to create %x - %d", LSTATS_SUBCMD_SET_INFO, ret);
return ret;
}
return ret;
}
protected:
virtual int handleResponse(WifiEvent& reply) {
// ALOGI("In GetLinkStatsCommand::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();
// ALOGI("Id = %0x, subcmd = %d", id, subcmd);
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
return NL_OK;
}
};
class ClearLinkStatsCommand : public WifiCommand
{
wifi_stats_result_handler mHandler;
public:
ClearLinkStatsCommand(wifi_interface_handle iface)
: WifiCommand("ClearLinkStatsCommand", iface, 0)
{ }
virtual int create() {
// ALOGI("Creating message to get link statistics; iface = %d", mIfaceInfo->id);
int ret = mMsg.create(GOOGLE_OUI, LSTATS_SUBCMD_CLEAR_INFO);
if (ret < 0) {
ALOGV("Failed to create %x - %d", LSTATS_SUBCMD_CLEAR_INFO, ret);
return ret;
}
return ret;
}
protected:
virtual int handleResponse(WifiEvent& reply) {
// ALOGI("In GetLinkStatsCommand::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();
// ALOGI("Id = %0x, subcmd = %d", id, subcmd);
void *data = reply.get_vendor_data();
int len = reply.get_vendor_data_len();
return NL_OK;
}
};
wifi_error wifi_get_link_stats(wifi_request_id id,
wifi_interface_handle iface, wifi_stats_result_handler handler)
{
GetLinkStatsCommand command(iface, handler);
return (wifi_error) command.requestResponse();
}
wifi_error wifi_set_link_stats(
wifi_interface_handle iface, wifi_link_layer_params params)
{
SetLinkStatsCommand command(iface);
return (wifi_error) command.requestResponse();
//return WIFI_SUCCESS;
}
wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
u32 stats_clear_req_mask, u32 *stats_clear_rsp_mask, u8 stop_req, u8 *stop_rsp)
{
ClearLinkStatsCommand command(iface);
return (wifi_error) command.requestResponse();
//return WIFI_SUCCESS;
}

View file

@ -0,0 +1,699 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#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 <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_TARGET_CNT = 0,
RTT_ATTRIBUTE_TARGET_INFO,
RTT_ATTRIBUTE_TARGET_MAC,
RTT_ATTRIBUTE_TARGET_TYPE,
RTT_ATTRIBUTE_TARGET_PEER,
RTT_ATTRIBUTE_TARGET_CHAN,
RTT_ATTRIBUTE_TARGET_PERIOD,
RTT_ATTRIBUTE_TARGET_NUM_BURST,
RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
RTT_ATTRIBUTE_TARGET_LCI,
RTT_ATTRIBUTE_TARGET_LCR,
RTT_ATTRIBUTE_TARGET_BURST_DURATION,
RTT_ATTRIBUTE_TARGET_PREAMBLE,
RTT_ATTRIBUTE_TARGET_BW,
RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
RTT_ATTRIBUTE_RESULTS_PER_TARGET,
RTT_ATTRIBUTE_RESULT_CNT,
RTT_ATTRIBUTE_RESULT
} RTT_ATTRIBUTE;
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("Creating message to get scan 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();
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(*mCapabilities));
memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
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;
wifi_rtt_responder* mResponderInfo;
unsigned m_max_duration_sec;
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 = NULL;
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) {
ALOGV("failed to create setup request; result = %d", result);
return result;
}
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGV("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) {
ALOGV("failed to create stop request; result = %d", result);
} else {
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGV("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[]) {
ALOGV("Stopping RTT");
WifiRequest request(familyId(), ifaceId());
int result = createTeardownRequest(request, num_devices, addr);
if (result != WIFI_SUCCESS) {
ALOGV("failed to create stop request; result = %d", result);
} else {
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGV("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;
ALOGV("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();
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <pthread.h>
#ifndef __WIFI_HAL_SYNC_H__
#define __WIFI_HAL_SYNC_H__
class Mutex
{
private:
pthread_mutex_t mMutex;
public:
Mutex() {
pthread_mutex_init(&mMutex, NULL);
}
~Mutex() {
pthread_mutex_destroy(&mMutex);
}
int tryLock() {
return pthread_mutex_trylock(&mMutex);
}
int lock() {
return pthread_mutex_lock(&mMutex);
}
void unlock() {
pthread_mutex_unlock(&mMutex);
}
};
class Condition
{
private:
pthread_cond_t mCondition;
pthread_mutex_t mMutex;
public:
Condition() {
pthread_mutex_init(&mMutex, NULL);
pthread_cond_init(&mCondition, NULL);
}
~Condition() {
pthread_cond_destroy(&mCondition);
pthread_mutex_destroy(&mMutex);
}
int wait() {
return pthread_cond_wait(&mCondition, &mMutex);
}
void signal() {
pthread_cond_signal(&mCondition);
}
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,247 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#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"
typedef enum {
WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
WIFI_OFFLOAD_STOP_MKEEP_ALIVE,
} WIFI_OFFLOAD_SUB_COMMAND;
typedef enum {
MKEEP_ALIVE_ATTRIBUTE_ID,
MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
} WIFI_MKEEP_ALIVE_ATTRIBUTE;
typedef enum {
START_MKEEP_ALIVE,
STOP_MKEEP_ALIVE,
} GetCmdType;
///////////////////////////////////////////////////////////////////////////////
class MKeepAliveCommand : public WifiCommand
{
u8 mIndex;
u8 *mIpPkt = NULL;
u16 mIpPktLen;
u8 *mSrcMacAddr = NULL;
u8 *mDstMacAddr = NULL;
u32 mPeriodMsec;
GetCmdType mType;
public:
// constructor for start sending
MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
: WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet),
mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr),
mPeriodMsec(period_msec), mType(cmdType)
{ }
// constructor for stop sending
MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
: WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
{ }
int createRequest(WifiRequest &request) {
int result;
switch (mType) {
case START_MKEEP_ALIVE:
{
result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_START_MKEEP_ALIVE);
if (result != WIFI_SUCCESS) {
ALOGV("Failed to create start keep alive request; result = %d", result);
return result;
}
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
if (result < 0) {
ALOGV("Failed to put id request; result = %d", result);
return result;
}
result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, mIpPktLen);
if (result < 0) {
ALOGV("Failed to put ip pkt len request; result = %d", result);
return result;
}
result = request.put(MKEEP_ALIVE_ATTRIBUTE_IP_PKT, (u8*)mIpPkt, mIpPktLen);
if (result < 0) {
ALOGV("Failed to put ip pkt request; result = %d", result);
return result;
}
result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, mSrcMacAddr);
if (result < 0) {
ALOGV("Failed to put src mac address request; result = %d", result);
return result;
}
result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, mDstMacAddr);
if (result < 0) {
ALOGV("Failed to put dst mac address request; result = %d", result);
return result;
}
result = request.put_u32(MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, mPeriodMsec);
if (result < 0) {
ALOGV("Failed to put period request; result = %d", result);
return result;
}
request.attr_end(data);
break;
}
case STOP_MKEEP_ALIVE:
{
result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_STOP_MKEEP_ALIVE);
if (result != WIFI_SUCCESS) {
ALOGV("Failed to create stop keep alive request; result = %d", result);
return result;
}
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
if (result < 0) {
ALOGV("Failed to put id request; result = %d", result);
return result;
}
request.attr_end(data);
break;
}
default:
ALOGV("Unknown wifi keep alive command");
result = WIFI_ERROR_UNKNOWN;
}
return result;
}
int start() {
ALOGD("Start mkeep_alive command");
WifiRequest request(familyId(), ifaceId());
int result = createRequest(request);
if (result != WIFI_SUCCESS) {
ALOGV("Failed to create keep alive request; result = %d", result);
return result;
}
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
ALOGV("Failed to register keep alive response; result = %d", result);
}
return result;
}
virtual int handleResponse(WifiEvent& reply) {
ALOGD("In MKeepAliveCommand::handleResponse");
if (reply.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
return NL_SKIP;
}
switch (mType) {
case START_MKEEP_ALIVE:
case STOP_MKEEP_ALIVE:
break;
default:
ALOGW("Unknown mkeep_alive command");
}
return NL_OK;
}
virtual int handleEvent(WifiEvent& event) {
/* NO events! */
return NL_SKIP;
}
};
/* API to send specified mkeep_alive packet periodically. */
wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec)
{
if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL)
&& (dst_mac_addr != NULL) && (period_msec > 0)
&& (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) {
MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len,
src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();
cmd->releaseRef();
return result;
} else {
ALOGV("Invalid mkeep_alive parameters");
return WIFI_ERROR_INVALID_ARGS;
}
}
/* API to stop sending mkeep_alive packet. */
wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface)
{
if (index > 0 && index <= N_AVAIL_ID) {
MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, STOP_MKEEP_ALIVE);
NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
wifi_error result = (wifi_error)cmd->start();
cmd->releaseRef();
return result;
} else {
ALOGV("Invalid mkeep_alive parameters");
return WIFI_ERROR_INVALID_ARGS;
}
}

View file

@ -0,0 +1,71 @@
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
endif
WPA_SUPPL_DIR = external/wpa_supplicant_8
WPA_SRC_FILE :=
include $(WPA_SUPPL_DIR)/wpa_supplicant/android.config
WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \
$(WPA_SUPPL_DIR)/src/common \
$(WPA_SUPPL_DIR)/src/drivers \
$(WPA_SUPPL_DIR)/src/l2_packet \
$(WPA_SUPPL_DIR)/src/utils \
$(WPA_SUPPL_DIR)/src/wps \
$(WPA_SUPPL_DIR)/wpa_supplicant
ifdef CONFIG_DRIVER_NL80211
WPA_SUPPL_DIR_INCLUDE += external/libnl/include
WPA_SRC_FILE += driver_cmd_nl80211.c
endif
ifdef CONFIG_DRIVER_WEXT
WPA_SRC_FILE += driver_cmd_wext.c
endif
ifeq ($(TARGET_ARCH),arm)
# To force sizeof(enum) = 4
L_CFLAGS += -mabi=aapcs-linux
endif
ifdef CONFIG_ANDROID_LOG
L_CFLAGS += -DCONFIG_ANDROID_LOG
endif
ifdef CONFIG_P2P
L_CFLAGS += -DCONFIG_P2P
endif
########################
include $(CLEAR_VARS)
LOCAL_MODULE := lib_driver_cmd_rtl
LOCAL_SHARED_LIBRARIES := libc libcutils
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(WPA_SRC_FILE)
LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE)
LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_STATIC_LIBRARY)
########################
endif

View file

@ -0,0 +1,43 @@
Copyright (c) 2005-2010, The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of The Android Open Source Project nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
* 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.

View file

@ -0,0 +1,224 @@
/*
* Driver interaction with extended Linux CFG8021
*
* 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.
*
*/
#include "includes.h"
#include <sys/types.h>
#include <fcntl.h>
#include <net/if.h>
#include "common.h"
#include "linux_ioctl.h"
#include "driver_nl80211.h"
#include "rtw_version.h"
#ifdef PURE_LINUX
#ifndef SIOCDEVPRIVATE
#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */
#endif
#ifndef __unused
#if __GNUC_PREREQ(2, 95) || defined(__INTEL_COMPILER)
#define __unused __attribute__((__unused__))
#else
#define __unused
#endif
#endif
#endif /* PURE_LINUX */
#include "wpa_supplicant_i.h"
#include "config.h"
#ifdef ANDROID
#include "android_drv.h"
#endif
typedef struct android_wifi_priv_cmd {
char *bufaddr;
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;
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
}
}
static void wpa_driver_notify_country_change(void *ctx, char *cmd)
{
if ((os_strncasecmp(cmd, "COUNTRY", 7) == 0) ||
(os_strncasecmp(cmd, "SETBAND", 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;
}
wpa_supplicant_event(ctx, EVENT_CHANNEL_LIST_CHANGED, &event);
}
}
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;
int ret = 0;
if (bss->ifindex <= 0 && bss->wdev_id > 0) {
/* DRIVER CMD received on the DEDICATED P2P Interface which doesn't
* have an NETDEVICE associated with it. So we have to re-route the
* command to the parent NETDEVICE
*/
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
wpa_printf(MSG_DEBUG, "Re-routing DRIVER cmd to parent iface");
if (wpa_s && wpa_s->parent) {
/* Update the nl80211 pointers corresponding to parent iface */
bss = wpa_s->parent->drv_priv;
drv = bss->drv;
wpa_printf(MSG_DEBUG, "Re-routing command to iface: %s"
" cmd (%s)", bss->ifname, cmd);
}
}
if (os_strcasecmp(cmd, "STOP") == 0) {
linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
} else if (os_strcasecmp(cmd, "START") == 0) {
linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
} else if (os_strcasecmp(cmd, "lib_version") == 0) {
wpa_msg(drv->ctx, MSG_INFO, RTW_VERSION);
} else if (os_strcasecmp(cmd, "P2P_DISABLE") == 0) {
os_memcpy(buf, "P2P_DISABLE", 12);
wpa_printf(MSG_DEBUG, "P2P_DISABLE");
} else if (os_strcasecmp(cmd, "MACADDR") == 0) {
u8 macaddr[ETH_ALEN] = {};
ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr);
if (!ret)
ret = os_snprintf(buf, buf_len,
"Macaddr = " MACSTR "\n", MAC2STR(macaddr));
} else { /* Use private command */
os_memcpy(buf, cmd, strlen(cmd) + 1);
memset(&ifr, 0, sizeof(ifr));
memset(&priv_cmd, 0, sizeof(priv_cmd));
os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
priv_cmd.bufaddr = buf;
priv_cmd.used_len = buf_len;
priv_cmd.total_len = buf_len;
ifr.ifr_data = (void *)&priv_cmd;
if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to issue private command: %s", __func__, cmd);
wpa_driver_send_hang_msg(drv);
} else {
drv_errors = 0;
ret = 0;
if ((os_strcasecmp(cmd, "LINKSPEED") == 0) ||
(os_strcasecmp(cmd, "RSSI") == 0) ||
(os_strcasecmp(cmd, "GETBAND") == 0) ||
(os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0))
ret = strlen(buf);
wpa_driver_notify_country_change(drv->ctx, cmd);
wpa_printf(MSG_DEBUG, "%s %s len = %d, %zu", __func__, buf, ret, strlen(buf));
}
}
return ret;
}
int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
{
char buf[MAX_DRV_CMD_SIZE];
memset(buf, 0, sizeof(buf));
wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
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 __unused, u8 *buf __unused, size_t len __unused)
{
/* Return 0 till we handle p2p_presence request completely in the driver */
return 0;
}
int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
{
char buf[MAX_DRV_CMD_SIZE];
memset(buf, 0, sizeof(buf));
wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
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,
const struct wpabuf *proberesp,
const struct wpabuf *assocresp)
{
char *buf;
const struct wpabuf *ap_wps_p2p_ie = NULL;
char *_cmd = "SET_AP_WPS_P2P_IE";
char *pbuf;
int ret = 0;
int i, buf_len;
struct cmd_desc {
int cmd;
const struct wpabuf *src;
} cmd_arr[] = {
{0x1, beacon},
{0x2, proberesp},
{0x4, assocresp},
{-1, NULL}
};
wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
for (i = 0; cmd_arr[i].cmd != -1; i++) {
ap_wps_p2p_ie = cmd_arr[i].src;
if (ap_wps_p2p_ie) {
buf_len = strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie);
buf = os_zalloc(buf_len);
if (NULL == buf) {
wpa_printf(MSG_ERROR, "%s: Out of memory",
__func__);
ret = -1;
break;
}
} else {
continue;
}
pbuf = buf;
pbuf += snprintf(pbuf, buf_len - wpabuf_len(ap_wps_p2p_ie),
"%s %d",_cmd, cmd_arr[i].cmd);
*pbuf++ = '\0';
os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie));
ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, buf_len);
os_free(buf);
if (ret < 0)
break;
}
return ret;
}

View file

@ -0,0 +1,396 @@
/*
* Driver interaction with extended Linux Wireless Extensions
*
* 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.
*
*/
#include "includes.h"
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <net/if.h>
#include "linux_wext.h"
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "priv_netlink.h"
#include "driver_wext.h"
#include "ieee802_11_defs.h"
#include "wpa_common.h"
#include "wpa_ctrl.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "linux_ioctl.h"
#include "scan.h"
#include "driver_cmd_wext.h"
#ifdef ANDROID
#include "android_drv.h"
#endif /* ANDROID */
#define RSSI_CMD "RSSI"
#define LINKSPEED_CMD "LINKSPEED"
/**
* wpa_driver_wext_set_scan_timeout - Set scan timeout to report scan completion
* @priv: Pointer to private wext data from wpa_driver_wext_init()
*
* This function can be used to set registered timeout when starting a scan to
* generate a scan completed event if the driver does not report this.
*/
static void wpa_driver_wext_set_scan_timeout(void *priv)
{
struct wpa_driver_wext_data *drv = priv;
int timeout = 10; /* In case scan A and B bands it can be long */
/* Not all drivers generate "scan completed" wireless event, so try to
* read results after a timeout. */
if (drv->scan_complete_events) {
/*
* The driver seems to deliver SIOCGIWSCAN events to notify
* when scan is complete, so use longer timeout to avoid race
* conditions with scanning and following association request.
*/
timeout = 30;
}
wpa_printf(MSG_DEBUG, "Scan requested - scan timeout %d seconds",
timeout);
eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
drv->ctx);
}
/**
* wpa_driver_wext_combo_scan - Request the driver to initiate combo scan
* @priv: Pointer to private wext data from wpa_driver_wext_init()
* @params: Scan parameters
* Returns: 0 on success, -1 on failure
*/
int wpa_driver_wext_combo_scan(void *priv, struct wpa_driver_scan_params *params)
{
char buf[WEXT_CSCAN_BUF_LEN];
struct wpa_driver_wext_data *drv = priv;
struct iwreq iwr;
int ret, bp;
unsigned i;
if (!drv->driver_is_started) {
wpa_printf(MSG_DEBUG, "%s: Driver stopped", __func__);
return 0;
}
wpa_printf(MSG_DEBUG, "%s: Start", __func__);
/* Set list of SSIDs */
bp = WEXT_CSCAN_HEADER_SIZE;
os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
for(i=0; i < params->num_ssids; i++) {
if ((bp + IW_ESSID_MAX_SIZE + 10) >= (int)sizeof(buf))
break;
wpa_printf(MSG_DEBUG, "For Scan: %s", params->ssids[i].ssid);
buf[bp++] = WEXT_CSCAN_SSID_SECTION;
buf[bp++] = params->ssids[i].ssid_len;
os_memcpy(&buf[bp], params->ssids[i].ssid, params->ssids[i].ssid_len);
bp += params->ssids[i].ssid_len;
}
/* Set list of channels */
buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
buf[bp++] = 0;
/* Set passive dwell time (default is 250) */
buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME;
buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME >> 8);
/* Set home dwell time (default is 40) */
buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = buf;
iwr.u.data.length = bp;
if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
if (!drv->bgscan_enabled)
wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
else
ret = 0; /* Hide error in case of bg scan */
}
return ret;
}
static int wpa_driver_wext_set_cscan_params(char *buf, size_t buf_len, char *cmd)
{
char *pasv_ptr;
int bp, i;
u16 pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
u8 channel;
wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
/* Get command parameters */
pasv_ptr = os_strstr(cmd, ",TIME=");
if (pasv_ptr) {
*pasv_ptr = '\0';
pasv_ptr += 6;
pasv_dwell = (u16)atoi(pasv_ptr);
if (pasv_dwell == 0)
pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
}
channel = (u8)atoi(cmd + 5);
bp = WEXT_CSCAN_HEADER_SIZE;
os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
/* Set list of channels */
buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
buf[bp++] = channel;
if (channel != 0) {
i = (pasv_dwell - 1) / WEXT_CSCAN_PASV_DWELL_TIME_DEF;
for (; i > 0; i--) {
if ((size_t)(bp + 12) >= buf_len)
break;
buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
buf[bp++] = channel;
}
} else {
if (pasv_dwell > WEXT_CSCAN_PASV_DWELL_TIME_MAX)
pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_MAX;
}
/* Set passive dwell time (default is 250) */
buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
if (channel != 0) {
buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME_DEF;
buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME_DEF >> 8);
} else {
buf[bp++] = (u8)pasv_dwell;
buf[bp++] = (u8)(pasv_dwell >> 8);
}
/* Set home dwell time (default is 40) */
buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
/* Set cscan type */
buf[bp++] = WEXT_CSCAN_TYPE_SECTION;
buf[bp++] = WEXT_CSCAN_TYPE_PASSIVE;
return bp;
}
static char *wpa_driver_get_country_code(int channels)
{
char *country = "US"; /* WEXT_NUMBER_SCAN_CHANNELS_FCC */
if (channels == WEXT_NUMBER_SCAN_CHANNELS_ETSI)
country = "EU";
else if( channels == WEXT_NUMBER_SCAN_CHANNELS_MKK1)
country = "JP";
return country;
}
static int wpa_driver_set_backgroundscan_params(void *priv)
{
struct wpa_driver_wext_data *drv = priv;
struct wpa_supplicant *wpa_s;
struct iwreq iwr;
int ret = 0, i = 0, bp;
char buf[WEXT_PNO_MAX_COMMAND_SIZE];
struct wpa_ssid *ssid_conf;
if (drv == NULL) {
wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__);
return -1;
}
if (drv->ctx == NULL) {
wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__);
return -1;
}
wpa_s = (struct wpa_supplicant *)(drv->ctx);
if (wpa_s->conf == NULL) {
wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__);
return -1;
}
ssid_conf = wpa_s->conf->ssid;
bp = WEXT_PNOSETUP_HEADER_SIZE;
os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
buf[bp++] = WEXT_PNO_TLV_PREFIX;
buf[bp++] = WEXT_PNO_TLV_VERSION;
buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
buf[bp++] = WEXT_PNO_TLV_RESERVED;
while ((i < WEXT_PNO_AMOUNT) && (ssid_conf != NULL)) {
/* Check that there is enough space needed for 1 more SSID, the other sections and null termination */
if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf))
break;
if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= IW_ESSID_MAX_SIZE)){
wpa_printf(MSG_DEBUG, "For PNO Scan: %s", ssid_conf->ssid);
buf[bp++] = WEXT_PNO_SSID_SECTION;
buf[bp++] = ssid_conf->ssid_len;
os_memcpy(&buf[bp], ssid_conf->ssid, ssid_conf->ssid_len);
bp += ssid_conf->ssid_len;
i++;
}
ssid_conf = ssid_conf->next;
}
buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", WEXT_PNO_SCAN_INTERVAL);
bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
buf[bp++] = WEXT_PNO_REPEAT_SECTION;
os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", WEXT_PNO_REPEAT);
bp += WEXT_PNO_REPEAT_LENGTH;
buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", WEXT_PNO_MAX_REPEAT);
bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = buf;
iwr.u.data.length = bp;
ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
if (ret < 0) {
wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret);
drv->errors++;
if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
drv->errors = 0;
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
}
} else {
drv->errors = 0;
}
return ret;
}
int wpa_driver_wext_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
{
struct wpa_driver_wext_data *drv = priv;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
struct iwreq iwr;
int ret = 0, flags;
wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
return -1;
}
if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
os_strlcpy(cmd, RSSI_CMD, MAX_DRV_CMD_SIZE);
} else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
int no_of_chan;
no_of_chan = atoi(cmd + 13);
os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
wpa_driver_get_country_code(no_of_chan));
} else if (os_strcasecmp(cmd, "STOP") == 0) {
linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
} else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
wpa_printf(MSG_DEBUG,"Reload command");
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
return ret;
} else if( os_strcasecmp(cmd, "BGSCAN-START") == 0 ) {
ret = wpa_driver_set_backgroundscan_params(priv);
if (ret < 0) {
return ret;
}
os_strlcpy(cmd, "PNOFORCE 1", MAX_DRV_CMD_SIZE);
drv->bgscan_enabled = 1;
} else if( os_strcasecmp(cmd, "BGSCAN-STOP") == 0 ) {
os_strlcpy(cmd, "PNOFORCE 0", MAX_DRV_CMD_SIZE);
drv->bgscan_enabled = 0;
}
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
os_memcpy(buf, cmd, strlen(cmd) + 1);
iwr.u.data.pointer = buf;
iwr.u.data.length = buf_len;
if( os_strncasecmp(cmd, "CSCAN", 5) == 0 ) {
if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) ||
(wpa_s->wpa_state >= WPA_COMPLETED))) {
iwr.u.data.length = wpa_driver_wext_set_cscan_params(buf, buf_len, cmd);
} else {
wpa_printf(MSG_ERROR, "Ongoing Scan action...");
return ret;
}
}
ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
if (ret < 0) {
wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, cmd);
drv->errors++;
if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
drv->errors = 0;
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
}
} else {
drv->errors = 0;
ret = 0;
if ((os_strcasecmp(cmd, RSSI_CMD) == 0) ||
(os_strcasecmp(cmd, LINKSPEED_CMD) == 0) ||
(os_strcasecmp(cmd, "MACADDR") == 0) ||
(os_strcasecmp(cmd, "GETPOWER") == 0) ||
(os_strcasecmp(cmd, "GETBAND") == 0)) {
ret = strlen(buf);
} else if (os_strcasecmp(cmd, "START") == 0) {
drv->driver_is_started = TRUE;
linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
/* os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); */
} else if (os_strcasecmp(cmd, "STOP") == 0) {
drv->driver_is_started = FALSE;
/* wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); */
} else if (os_strncasecmp(cmd, "CSCAN", 5) == 0) {
wpa_driver_wext_set_scan_timeout(priv);
wpa_supplicant_notify_scanning(wpa_s, 1);
}
wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
}
return ret;
}
int wpa_driver_signal_poll(void *priv, struct wpa_signal_info *si)
{
char buf[MAX_DRV_CMD_SIZE];
struct wpa_driver_wext_data *drv = priv;
char *prssi;
int res;
os_memset(si, 0, sizeof(*si));
res = wpa_driver_wext_driver_cmd(priv, RSSI_CMD, buf, sizeof(buf));
/* Answer: SSID rssi -Val */
if (res < 0)
return res;
prssi = strcasestr(buf, RSSI_CMD);
if (!prssi)
return -1;
si->current_signal = atoi(prssi + strlen(RSSI_CMD) + 1);
res = wpa_driver_wext_driver_cmd(priv, LINKSPEED_CMD, buf, sizeof(buf));
/* Answer: LinkSpeed Val */
if (res < 0)
return res;
si->current_txrate = atoi(buf + strlen(LINKSPEED_CMD) + 1) * 1000;
return 0;
}

View file

@ -0,0 +1,37 @@
/*
* Driver interaction with extended Linux Wireless Extensions
*
* 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.
*
*/
#ifndef DRIVER_CMD_WEXT_H
#define DRIVER_CMD_WEXT_H
#define WEXT_NUMBER_SCAN_CHANNELS_FCC 11
#define WEXT_NUMBER_SCAN_CHANNELS_ETSI 13
#define WEXT_NUMBER_SCAN_CHANNELS_MKK1 14
#define WPA_DRIVER_WEXT_WAIT_US 400000
#define WEXT_CSCAN_BUF_LEN 360
#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
#define WEXT_CSCAN_HEADER_SIZE 12
#define WEXT_CSCAN_SSID_SECTION 'S'
#define WEXT_CSCAN_CHANNEL_SECTION 'C'
#define WEXT_CSCAN_NPROBE_SECTION 'N'
#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
#define WEXT_CSCAN_TYPE_SECTION 'T'
#define WEXT_CSCAN_TYPE_DEFAULT 0
#define WEXT_CSCAN_TYPE_PASSIVE 1
#define WEXT_CSCAN_PASV_DWELL_TIME 130
#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
#define WEXT_CSCAN_HOME_DWELL_TIME 130
#endif /* DRIVER_CMD_WEXT_H */

View file

@ -0,0 +1,251 @@
/*
* Driver interaction with Linux nl80211/cfg80211
* Copyright (c) 2002-2014, 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 software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef _DRIVER_NL80211_H_
#define _DRIVER_NL80211_H_
#include "includes.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#ifdef CONFIG_LIBNL3_ROUTE
#include <netlink/route/neighbour.h>
#endif /* CONFIG_LIBNL3_ROUTE */
#include <linux/rtnetlink.h>
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/errqueue.h>
#include "nl80211_copy.h"
#include "common.h"
#include "eloop.h"
#include "utils/list.h"
#include "common/qca-vendor.h"
#include "common/qca-vendor-attr.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "l2_packet/l2_packet.h"
#include "netlink.h"
#include "linux_ioctl.h"
#include "radiotap.h"
#include "radiotap_iter.h"
#include "rfkill.h"
#include "driver.h"
#ifdef CONFIG_LIBNL20
/* libnl 2.0 compatibility code */
#define nl_handle nl_sock
#define nl80211_handle_alloc nl_socket_alloc_cb
#define nl80211_handle_destroy nl_socket_free
#endif /* CONFIG_LIBNL20 */
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
#endif
#ifndef IFF_DORMANT
#define IFF_DORMANT 0x20000 /* driver signals dormant */
#endif
#ifndef IF_OPER_DORMANT
#define IF_OPER_DORMANT 5
#endif
#ifndef IF_OPER_UP
#define IF_OPER_UP 6
#endif
struct nl80211_global {
void *ctx;
struct dl_list interfaces;
int if_add_ifindex;
u64 if_add_wdevid;
int if_add_wdevid_set;
struct netlink_data *netlink;
struct nl_cb *nl_cb;
struct nl_handle *nl;
int nl80211_id;
int ioctl_sock; /* socket for ioctl() use */
struct nl_handle *nl_event;
};
struct nl80211_wiphy_data {
struct dl_list list;
struct dl_list bsss;
struct dl_list drvs;
struct nl_handle *nl_beacons;
struct nl_cb *nl_cb;
int wiphy_idx;
};
struct i802_bss {
struct wpa_driver_nl80211_data *drv;
struct i802_bss *next;
int ifindex;
int br_ifindex;
u64 wdev_id;
char ifname[IFNAMSIZ + 1];
char brname[IFNAMSIZ];
unsigned int beacon_set:1;
unsigned int added_if_into_bridge:1;
unsigned int added_bridge:1;
unsigned int in_deinit:1;
unsigned int wdev_id_set:1;
unsigned int added_if:1;
unsigned int static_ap:1;
u8 addr[ETH_ALEN];
int freq;
int bandwidth;
int if_dynamic;
void *ctx;
struct nl_handle *nl_preq, *nl_mgmt;
struct nl_cb *nl_cb;
struct nl80211_wiphy_data *wiphy_data;
struct dl_list wiphy_list;
};
struct wpa_driver_nl80211_data {
struct nl80211_global *global;
struct dl_list list;
struct dl_list wiphy_list;
char phyname[32];
unsigned int wiphy_idx;
u8 perm_addr[ETH_ALEN];
void *ctx;
int ifindex;
int if_removed;
int if_disabled;
int ignore_if_down_event;
struct rfkill_data *rfkill;
struct wpa_driver_capa capa;
u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
int has_capability;
int operstate;
int scan_complete_events;
enum scan_states {
NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,
SCHED_SCAN_RESULTS
} scan_state;
//struct nl_cb *nl_cb;
u8 auth_bssid[ETH_ALEN];
u8 auth_attempt_bssid[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 prev_bssid[ETH_ALEN];
int associated;
u8 ssid[32];
size_t ssid_len;
enum nl80211_iftype nlmode;
enum nl80211_iftype ap_scan_as_station;
unsigned int assoc_freq;
int monitor_sock;
int monitor_ifidx;
int monitor_refcount;
unsigned int disabled_11b_rates:1;
unsigned int pending_remain_on_chan:1;
unsigned int in_interface_list:1;
unsigned int device_ap_sme:1;
unsigned int poll_command_supported:1;
unsigned int data_tx_status:1;
unsigned int scan_for_auth:1;
unsigned int retry_auth:1;
unsigned int use_monitor:1;
unsigned int ignore_next_local_disconnect:1;
unsigned int ignore_next_local_deauth:1;
//unsigned int allow_p2p_device:1;
unsigned int hostapd:1;
unsigned int start_mode_ap:1;
unsigned int start_iface_up:1;
unsigned int test_use_roc_tx:1;
unsigned int ignore_deauth_event:1;
unsigned int vendor_cmd_test_avail:1;
unsigned int roaming_vendor_cmd_avail:1;
unsigned int dfs_vendor_cmd_avail:1;
unsigned int have_low_prio_scan:1;
unsigned int force_connect_cmd:1;
unsigned int addr_changed:1;
unsigned int get_features_vendor_cmd_avail:1;
unsigned int set_rekey_offload:1;
unsigned int p2p_go_ctwindow_supported:1;
unsigned int setband_vendor_cmd_avail:1;
unsigned int get_pref_freq_list:1;
unsigned int set_prob_oper_freq:1;
unsigned int scan_vendor_cmd_avail:1;
unsigned int connect_reassoc:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
#define MAX_SEND_ACTION_COOKIES 20
u64 send_action_cookies[MAX_SEND_ACTION_COOKIES];
unsigned int num_send_action_cookies;
unsigned int last_mgmt_freq;
struct wpa_driver_scan_filter *filter_ssids;
size_t num_filter_ssids;
struct i802_bss *first_bss;
int eapol_tx_sock;
int eapol_sock; /* socket for EAPOL frames */
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
int default_if_indices[16];
/* the AP/AP_VLAN iface that is in this bridge */
int default_if_indices_reason[16];
int *if_indices;
int *if_indices_reason;
int num_if_indices;
/* From failed authentication command */
int auth_freq;
u8 auth_bssid_[ETH_ALEN];
u8 auth_ssid[32];
size_t auth_ssid_len;
int auth_alg;
u8 *auth_ie;
size_t auth_ie_len;
u8 auth_wep_key[4][16];
size_t auth_wep_key_len[4];
int auth_wep_tx_keyidx;
int auth_local_state_change;
int auth_p2p;
/*
* Tells whether the last scan issued from wpa_supplicant was a normal
* scan (NL80211_CMD_TRIGGER_SCAN) or a vendor scan
* (NL80211_CMD_VENDOR). 0 if no pending scan request.
*/
int last_scan_cmd;
};
#endif

View file

@ -0,0 +1,4 @@
#ifndef RTW_VERSION_H
#define RTW_VERSION_H
#define RTW_VERSION "rtw_r24091.20170925"
#endif /* RTW_VERSION_H */