Android Wifi小记

Wifi代码位置分布

代码路径作用
/framework/opt/net/wifi/service运行在system_server进程,位于Framework层。面向上层APP提供Wifi相关的服务
/framework/opt/net/wifi/wifi_hal运行在android.hardware.wifi@service-1.0 进程。 位于hal层,定义芯片接口方便不同芯片供应商实现。[1]
/external/wpa_supplicant_8wpa_supplicant & hostap 进程。位于native 层。
device/qcom/common/rootdir/etc/init.qcom.rc定义wpa_supplicant 服务的启动,以及wpa_supplicant启动时候参数配置 [2]
/system/connectivity/wificondwificond 进程。 开机的时候在zygote 起来的时候拉起,负责控制 wpa_supplicant & hostap 的启动和停止。以及scan功能[3]
/hardware/interface/wifiandroid.hardware.wifi@service-1.0 进程。 面向framework 提供服务
/vendor/qcom/opensource/interfaces/wifi运行在system_server进行,提供qcom supplicant&hostap hidl层接口
/vendor/qcom/opensource/softap运行在hostap 进程, qcom hostap 功能的实现
/vendor/qcom/opensource/wlan/qcacld-3.0qcom 芯片驱动
  • [1] wifi_hal 的实现,区别一般hal层的service通过dlopen去动态加载so库。android.hardware.wifi 直接将libwifi-hal作为动态库进行编译。那么怎么区分不同芯片供应商的实现了?这个问题可以通过wifi-hal的Android.mk(/framework/opt/net/wifi/libwifi-hal/Android.mk) 找到答案。在编译libwifi-hal的时候会根据 BORAD_WLAN_DEVICE 宏来决定链接不同芯片供应商的静态库。
LIB_WIFI_HAL := libwifi-hal-fallback
VENDOR_LOCAL_SHARED_LIBRARIES :=
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
  LIB_WIFI_HAL := libwifi-hal-bcm
else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
  LIB_WIFI_HAL := libwifi-hal-qcom
  VENDOR_LOCAL_SHARED_LIBRARIES := libcld80211
else ifeq ($(BOARD_WLAN_DEVICE), mrvl)
  # this is commented because none of the nexus devices
  # that sport Marvell's wifi have support for HAL
  # LIB_WIFI_HAL := libwifi-hal-mrvl
else ifeq ($(BOARD_WLAN_DEVICE), MediaTek)
  # support MTK WIFI HAL
  LIB_WIFI_HAL := libwifi-hal-mt66xx
else ifeq ($(BOARD_WLAN_DEVICE), emulator)
  LIB_WIFI_HAL := libwifi-hal-emu
endif

# The WiFi HAL that you should be linking.
# ============================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libwifi-hal
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CFLAGS := $(wifi_hal_cflags)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := \
    $(LOCAL_PATH)/include
LOCAL_EXPORT_HEADER_LIBRARY_HEADERS := libhardware_legacy_headers
LOCAL_HEADER_LIBRARIES := libhardware_legacy_headers
LOCAL_SHARED_LIBRARIES := \
    libbase \
    libcutils \
    liblog \
    libnl \
    libutils \
    $(VENDOR_LOCAL_SHARED_LIBRARIES)
LOCAL_SRC_FILES := \
    driver_tool.cpp \
    hal_tool.cpp
LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL) libwifi-hal-common
include $(BUILD_SHARED_LIBRARY)

在hardware/interface/wifi/1.2/default/Android.mk ,android.hardware.wifi@1.0-service-lib 依赖 wifi-hal


  • [2] wpa_supplicant
    进程起来的时候可以配置参数
wpa_supplicant v2.4
Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors

This software may be distributed under the terms of the BSD license.
See README for more details.

This product includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit (http://www.openssl.org/)

usage:
  wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] [-g<global ctrl>] \
        [-G<group>] \
        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
        [-b<br_ifname>] [-e<entropy file>] [-f<debug file>] \
        [-o<override driver>] [-O<override ctrl>] \
        [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
        [-m<P2P Device config file>] \
        [-p<driver_param>] [-b<br_ifname>] [-I<config file>] ...]

drivers:
  nl80211 = Linux nl80211/cfg80211
  wext = Linux wireless extensions (generic)
  wired = Wired Ethernet driver
  none = no driver (RADIUS server/WPS ER)
options:
  -b = optional bridge interface name
  -B = run daemon in the background
  -c = Configuration file
  -C = ctrl_interface parameter (only used if -c is not)
  -i = interface name
  -I = additional configuration file
  -d = increase debugging verbosity (-dd even more)
  -D = driver name (can be multiple drivers: nl80211,wext)
  -e = entropy file
  -f = log output to debug file instead of stdout
  -g = global ctrl_interface
  -G = global ctrl_interface group
  -K = include keys (passwords, etc.) in debug output
  -s = log output to syslog instead of stdout
  -T = record to Linux tracing in addition to logging
       (records all messages regardless of debug verbosity)
  -t = include timestamp in debug messages
  -h = show this help text
  -L = show license (BSD)
  -o = override driver parameter for new interfaces
  -O = override ctrl_interface parameter for new interfaces
  -p = driver parameters
  -P = PID file
  -q = decrease debugging verbosity (-qq even less)
  -u = enable DBus control interface
  -v = show version
  -W = wait for a control interface monitor before starting
  -m = Configuration file for the P2P Device interface
  -N = start describing new interface
example:
  wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf

  • [3] wificond 的启动
    在/system/conectivity/wifcond 的 wificond.rc 中只定义了wificond服务器,但是并没有看到启动服务的条件。wificond是会随着zygote起来的时候顺手拉起来的。
//  /system/core/rootdir/init.zygote.64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
~


Wifi 芯片模式

IWifiChip.hal 定义了芯片模式的选择类型

  struct ChipIfaceCombinationLimit {
    vec<IfaceType> types; // Each IfaceType must occur at most once.
    uint32_t maxIfaces;
  };

  /**
   * Set of interfaces that can operate concurrently when in a given mode. See
   * ChipMode below.
   *
   * For example:
   *   [{STA} <= 2]
   *       At most two STA interfaces are supported
   *       [], [STA], [STA+STA]
   *
   *   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]
   *       Any combination of STA, NAN, AP
   *       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]
   *
   *   [{STA} <= 1, {NAN,P2P} <= 1]
   *       Optionally a STA and either NAN or P2P
   *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
   *       Not included [NAN+P2P], [STA+NAN+P2P]
   *
   *   [{STA} <= 1, {STA,NAN} <= 1]
   *       Optionally a STA and either a second STA or a NAN
   *       [], [STA], [STA+NAN], [STA+STA], [NAN]
   *       Not included [STA+STA+NAN]
   */
  struct ChipIfaceCombination {
    vec<ChipIfaceCombinationLimit> limits;
  };

首先ChipIfaceCombinationLimit 中 vec types; 表示包含的芯片支持的接口模式类型。 可能会包含多个接口。 uint32_t maxIfaces 表示最多同时能支持几种接口模式。

[ {STA} <= 2]
包含一个ChipIfaceCombinationLimit. types = { STA }; maxIfaces = 2;
组合如下:
[], //不包含STA
[STA], //支持一路STA
[STA, STA] // 支持两路STA

[{STA} <= 1, {NAN} <= 1, {AP} <= 1]
包含一个ChipIfaceCombinationLimit, types = {STA}; maxIfaces = 1;
包含一个ChipIfaceCombinationLimit, types = { NAN}; maxIfaces = 1;
包含一个ChipIfaceCombinationLimit, types = {AP}; maxIfaces = 1;
组合如下:
[], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]

[{STA} <= 1, {NAN,P2P} <= 1]
包含一个ChipIfaceCombinationLimit, types = {STA}; maxIfaces = 1;
包含一个ChipIfaceCombinationLimit, types = { NAN, P2P}; maxIfaces = 1;
组合如下:
[], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]

不存在[NAN+P2P], [STA+NAN+P2P] 是因为 NAN,P2P在一组中,但是这组最多支持一路接口(maxIface = 1决定)。所以不存在同时NAN P2P同时支持。


根据上面的说明,我们来看一下代码走向。

/**
 * isDualInterfaceSupported 是由宏 WIFI_HIDL_FEATURE_DUAL_INTERFACE 决定。 
 * 这个宏在vendor/qcom/properity/common/msmnile_gvmq/BoardConfigVendor.mk 定义了
 */
    if (feature_flags_.lock()->isDualInterfaceSupported()) {
        // V2 Iface combinations for Mode Id = 2.
        // 最多支持一路 STA
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
       // 最多支持一路 AP
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_2 = {{IfaceType::AP}, 1};
        IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
        if (feature_flags_.lock()->isAwareSupported()) {
         // 最多支持 一路 NAN | P2P 但是 maxIfaces = 1 表示NAN & P2P 不能同时存在。
            chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
                                              1};
        } else {
         // 最多支持一路 P2P
            chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
        }
        //[{STA} <=1,  {AP} <= 1]
        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
        
        //[{STA} <= 1, {NAN, P2P} < 1] | [{STA} < 1, {P2P} < 1]
        const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
        
        //[{STA} <= 1, {AP} <= 1, {NAN, P2P} < 1] | [{STA} < 1, {AP} <= 1, {P2P} < 1]
        const IWifiChip::ChipIfaceCombination chip_iface_combination_4 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_2,
             chip_iface_combination_limit_3}};
       //kV2ChipModeId = 2
        if (feature_flags_.lock()->isApDisabled()) {
          const IWifiChip::ChipMode chip_mode = {
              kV2ChipModeId,
              {chip_iface_combination_2}};
          modes_ = {chip_mode};
          LOG(ERROR) << "chip mode combination 2 - STA+P2P/NAN";
        } else if (feature_flags_.lock()->isStaSapP2pEnabled()) {
          const IWifiChip::ChipMode chip_mode = {
              kV2ChipModeId,
              {chip_iface_combination_4}};
          modes_ = {chip_mode};
          LOG(ERROR) << "chip mode combination 4 - STA+SAP+P2P/NAN";
        } else {
          const IWifiChip::ChipMode chip_mode = {
            kV2ChipModeId,
            // [{STA} <=1,  {AP} <= 1, {NAN, P2P} < 1]
            {chip_iface_combination_1, chip_iface_combination_2}};
          modes_ = {chip_mode};
          LOG(ERROR) << "chip mode combination 1 or 2 - STA+AP or STA+P2P/NAN";
        }
    } else {
        // V1 Iface combinations for Mode Id = 0. (STA Mode)
        const IWifiChip::ChipIfaceCombinationLimit
            sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
        IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
        if (feature_flags_.lock()->isAwareSupported()) {
            sta_chip_iface_combination_limit_2 = {
                {IfaceType::P2P, IfaceType::NAN}, 1};
        } else {
            sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
        }
        const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
            {sta_chip_iface_combination_limit_1,
             sta_chip_iface_combination_limit_2}};
        const IWifiChip::ChipMode sta_chip_mode = {
            kV1StaChipModeId, {sta_chip_iface_combination}};
        // Iface combinations for Mode Id = 1. (AP Mode)
        const IWifiChip::ChipIfaceCombinationLimit
            ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
        const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
            {ap_chip_iface_combination_limit}};
        const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
                                                  {ap_chip_iface_combination}};
        if (feature_flags_.lock()->isApDisabled()) {
          modes_ = {sta_chip_mode};
        } else {
          modes_ = {sta_chip_mode, ap_chip_mode};
        }
    }
}

Framework aidl 和 wificond 通讯

aidl 生成 java 和 c++ 的代码。

connectivity/wificond/aidl/android/net/wifi/IWificond.aidl

interface IWificond {
    // Create a network interface suitable for use as a WiFi client.
    @nullable IClientInterface createClientInterface(@utf8InCpp String iface_name);
    ...
    }

生成位置
Java代码生成位置:
out/target/common/obj/JAVA_LIBRARIES/wifi-service_intermediates/aidl/dotdot/dotdot/dotdot/dotdot/dotdo/
在这里插入图片描述
从Java层往下调用,Java层获取的是Bp,wificond是Bn。从下面的代码中可以看出,client直接transact()。
生成代码:

@Override public android.net.wifi.IClientInterface createClientInterface(java.lang.String iface_name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.net.wifi.IClientInterface _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(iface_name);
mRemote.transact(Stub.TRANSACTION_createClientInterface, _data, _reply, 0);
_reply.readException();
_result = android.net.wifi.IClientInterface.Stub.asInterface(_reply.readStrongBinder());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

C++ 侧生成的代码位置:
out/target/product/msmnile_gvmq/obj/STATIC_LIBRARIES/libwificond_ipc_intermediates/aidl-generated

在这里插入图片描述
wificond进程, server.h 实现BnWifiCond。然后Java层通过transact()直接调到BnWificond的onTransact方法中。最后调到server方法中。

::android::status_t BnWificond::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
::android::status_t _aidl_ret_status = ::android::OK;
switch (_aidl_code) {
...
case Call::CREATECLIENTINTERFACE:
{
::std::string in_iface_name;
::android::sp<::android::net::wifi::IClientInterface> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_iface_name);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
//此处调用server.h中的实现。
::android::binder::Status _aidl_status(createClientInterface(in_iface_name, &_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::net::wifi::IClientInterface::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
...
}


nl80211 & netlink

+-------------+
|             |
|  Userspace  |
|             |
+-------------+
      ^
- - - | - - - - 
      | nl80211 (netlink)
      v
+-------------+
|             |
|  cfg80211   |
|             |
+-------------+
+-------------+
|             |
|  mac80211   |
|   driver    |
|             |
+-------------+
mac80211 driver

mac80211是一个框架,驱动程序开发人员可以使用它来编写SoftMAC无线设备的驱动程序。

SoftMAC设备允许对硬件进行更精细的控制,允许在软件中实现802.11帧管理,包括解析和生成802.11无线帧。今天大多数的802.11设备往往是这种类型的,FullMAC设备已经变得稀少。

mac80211为SoftMAC设备实现cfg80211回调,mac80211依靠cfg80211来注册到网络子系统和配置。 配置是通过cfg80211处理,可以通过nl80211和wireless extensions。
在mac80211中MLME在station 模式(STA )下是在内核中实现的,AP模式( hostapd )下是在用户空间实现的。

如果你有支持nl80211的新的用户空间的应用程序,那你不需要wireless-extensions来支持mac80211设备。

(先挖坑,后面再补)
参考:
About nl80211
man 7 netlink
libnl


ifconfig

通过ioctl 操作interface
man 7 netdevice


SYNOPSIS
       #include <sys/ioctl.h>
       #include <net/if.h>

DESCRIPTION
       This man page describes the sockets interface which is used to configure network devices.

       Linux supports some standard ioctls to configure network devices.  They can be used on any socket's file descriptor regardless of the family or type.  Most of them pass an ifreq struc-
       ture:

           struct ifreq {
               char ifr_name[IFNAMSIZ]; /* Interface name */
               union {
                   struct sockaddr ifr_addr;
                   struct sockaddr ifr_dstaddr;
                   struct sockaddr ifr_broadaddr;
                   struct sockaddr ifr_netmask;
                   struct sockaddr ifr_hwaddr;
                   short           ifr_flags;
                   int             ifr_ifindex;
                   int             ifr_metric;
                   int             ifr_mtu;
                   struct ifmap    ifr_map;
                   char            ifr_slave[IFNAMSIZ];
                   char            ifr_newname[IFNAMSIZ];
                   char           *ifr_data;
               };
           };
bool InterfaceTool::GetUpState(const char* if_name) {
  base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
  if (sock.get() < 0) {
    LOG(ERROR) << "Failed to open socket to set up/down state ("
               << strerror(errno) << ")";
    return false;
  }

  struct ifreq ifr;
  if (!GetIfState(if_name, sock.get(), &ifr)) {
    return false;  // logging done internally
  }

  return ifr.ifr_flags & IFF_UP;
}

bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {
  base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
  if (sock.get() < 0) {
    LOG(ERROR) << "Failed to open socket to set up/down state ("
               << strerror(errno) << ")";
    return false;
  }

  struct ifreq ifr;
  if (!GetIfState(if_name, sock.get(), &ifr)) {
    return false;  // logging done internally
  }

  const bool currently_up = ifr.ifr_flags & IFF_UP;
  if (currently_up == request_up) {
    return true;
  }

  if (request_up) {
    ifr.ifr_flags |= IFF_UP;
  } else {
    ifr.ifr_flags &= ~IFF_UP;
  }

  if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFFLAGS, &ifr)) != 0) {
    LOG(ERROR) << "Could not set interface flags for " << if_name
               << " (" << strerror(errno) << ")";
    return false;
  }

  return true;
}

qcom 平台WLAN相关编译文件

在qcom平台,就wlan相关的编译分布的比较散,一时间难以追踪。先记一笔方便后续的工作查看。
跟qcom相关的编译主要分布 /device 和 /vendor下面。
在进行编译的时候我们都是需要lunch,这个过程就是选择需要编译的工程版本。

//加载编译Android相关的环境变量
source build/env   
//选择工程版本,后续进行编译的时候,就是从 /device/qcom/msmnile_gvmq/msmnile_gvmq.mk 下的编译脚本开始加载编译。
lunch msmnile_gvmq  

从msmnile_gvmq.mk开始。

  • 1
    加载 /device/qcom/common/common.mk 进行编译
// file path: /device/qcom/msmnile_gvmq/msmnile_gvmq.mk
$(call inherit-product, device/qcom/common/common64.mk)
  • 2
    加载同目录下base.mk 进行编译
    加载 /vendor/qcom/proprietary/common/config/device-vendor.mk 进行编译
//file path: /device/qcom/common/commom.mk
$(call inherit-product, device/qcom/common/base.mk)

# For PRODUCT_COPY_FILES, the first instance takes precedence.
# Since we want use QC specific files, we should inherit
# device-vendor.mk first to make sure QC specific files gets installed.
$(call inherit-product-if-exists, $(QCPATH)/common/config/device-vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
  • 2-1
    这个文件里配置了需要很高通相关的module,值得去研究一下。
//file path:  /device/qcom/msmnile_gvmq/AndroidBoard.mk
#----------------------------------------------------------------------
# wlan specific
#----------------------------------------------------------------------
ifeq ($(strip $(BOARD_HAS_QCOM_WLAN)),true)
include device/qcom/wlan/msmnile_au/AndroidBoardWlan.mk
endif

//file path:  /device/qcom/wlan/msmnile_au/AndroidBoardWlan.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE       := hostapd_default.conf
LOCAL_MODULE_TAGS  := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)/hostapd
LOCAL_SRC_FILES    := hostapd.conf
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE       := hostapd.accept
LOCAL_MODULE_TAGS  := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)/hostapd
LOCAL_SRC_FILES    := hostapd.accept
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE       := hostapd.deny
LOCAL_MODULE_TAGS  := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)/hostapd
LOCAL_SRC_FILES    := hostapd.deny
include $(BUILD_PREBUILT)

//file path: /device/qcom/common/base.mk
#HOSTAPD
HOSTAPD := hostapd
HOSTAPD += hostapd_cli
HOSTAPD += nt_password_hash
HOSTAPD += hlr_auc_gw
HOSTAPD += test-milenage
HOSTAPD += hostapd.conf
HOSTAPD += hostapd_default.conf
HOSTAPD += hostapd.deny
HOSTAPD += hostapd.accept

#INIT
INIT += init.qcom.rc

//file path: /device/qcom/common/rootdir/Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE       := init.qcom.rc
LOCAL_MODULE_TAGS  := optional eng
LOCAL_MODULE_CLASS := ETC
LOCAL_SRC_FILES    := etc/init.qcom.rc
LOCAL_MODULE_PATH  := $(TARGET_OUT_VENDOR_ETC)/init/hw
include $(BUILD_PREBUILT)

//file path: device/qcom/common/rootdir/etc/init.qcom.rc
service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
    -iwlan0 -Dnl80211 -c/vendor/etc/wifi/wpa_supplicant.conf
#    -O/data/vendor/wifi/wpa/sockets -puse_p2p_group_interface=1 -dd \
#    -g@android:vendor_wpa_wlan0
#   we will start as root and wpa_supplicant will switch to user wifi
#   after setting up the capabilities required for WEXT
#   user wifi
#   group wifi inet keystore
#    interface android.hardware.wifi.supplicant@1.0::ISupplicant default
#    interface android.hardware.wifi.supplicant@1.1::ISupplicant default
    class main
    socket vendor_wpa_wlan0 dgram 660 wifi wifi
    disabled
    oneshot
  • 3
    加载 /vendor/qcom/proprietary/common/msmnile_gvmq/BoradConfigVendor.mk 进行编译
    加载 /device/qcom/wlan/msmnile_au/BoardConfigWlan.mk 进行编译
//file path:/device/qcom/msmnile_gvmq/BoardConfig.mk
-include $(QCPATH)/common/msmnile_gvmq/BoardConfigVendor.mk

ifeq ($(strip $(BOARD_HAS_QCOM_WLAN)),true)
include device/qcom/wlan/msmnile_au/BoardConfigWlan.mk
endif
  • 4
    加载 device/qcom/wlan/msmnile_au/wlan.mk 进行编译
include device/qcom/wlan/msmnile_au/wlan.mk

hostapd.conf 解析

摘抄自:hostapd配置解析

interface=wlp2s0
#bridge=br0
driver=nl80211
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
#ctrl_interface=/var/run/hostapd
#ctrl_interface_group=wheel
#ctrl_interface_group=0
##### IEEE 802.11 related configuration #######################################
ssid=test
#ssid2=mytest
#ssid2=P"hello\nthere"
utf8_ssid=1
# ISO/IEC 3166-1 标准的国家代码,用于设置监管域。根据需要设置,按照哪个国家来操作设备。
# 这可以限制可用的频道和发射功率。
#country_code=CN
# 是否启用 IEEE 802.11d,0 禁用(默认),1 启用。
# 需要正确设置 country_code 才能使 IEEE 802.11d 正常工作。
#ieee80211d=1
# 是否启用 IEEE 802.11h,0 禁用(默认),1 启用。
# 这将启用雷达探测和 DFS 支持,如果可用话。
#ieee80211h=1
# 添加 Power Constraint element 到 Beacon 和 Probe Response frames 中去。
#local_pwr_constraint=5
# 该选项仅在 ieee80211h=1 选项并且已经配置 local_pwr_constraint 选项时可用。
#spectrum_mgmt_required=1
# 设置无线模式需要硬件支持,a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, ad = IEEE 802.11ad (60 GHz)
# hw_mode=a 或 hw_mode=g 选项也与 IEEE 802.11n 一起使用来设置波段。
# 当使用 ACS 时(看下文 channel parameter ),可以使用特殊的选项值 hw_mode=any ,说明可以使用任何可用的波段,该值当前仅在驱动使用了 offloaded ACS 的情况下有效。
# 默认: hw_mode=b
hw_mode=g
# 注意有些设备不使用这个选项,而是需要在 iwconfig 中另外配置。
# 如果编译的时候启用了 CONFIG_ACS 选项。通过设置 channel=acs_survey 或 channel=0,这样 hostapd 可以在运行时基于 ACS survey 算法自动选择合适的信道。
# 有些设备仅支持最大为11频道,有些支持最大为13频道,可以通过iw list 查看。
# 另外启用 ht_capab 将影响可用的频道数
channel=6
# ACS tuning - 信道自动选择
# 参考:http://wireless.kernel.org/en/users/Documentation/acs
# 信道自动选择,有助于选择更好的信道,但是会增加启动时间,一般不需要修改。
# 可以通过设置下面选项自定义 ACS survey 算法。
# 默认:acs_num_scans=5  acs_chan_bias=1:0.8 6:0.8 11:0.8
#acs_num_scans=40
#acs_chan_bias=1:0.8 6:0.8 11:0.8
# 默认允许所有信道
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
# beacon 间隔  (默认: 100; 范围 1565535)
#beacon_int=100
#dtim_period=1
# 默认且最大值为2007个列表
#max_num_sta=255
#rts_threshold=2347
#fragm_threshold=2346
#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540
#basic_rates=10 20
#basic_rates=10 20 55 110
#basic_rates=60 120 240
# 用命令:iw list 查看无线网卡是否有“short preamble supported”。
# 0 禁用,1 启用,无线网卡支持的话可以启用以改善网络性能。
#preamble=1
# 无线MAC地址过滤
# 此选项要求 driver=hostap 或 driver=nl80211
# 0 = 接受所有连接,仅拒绝 deny 列表中的连接
# 1 = 拒绝所有连接,仅接受 accept 列表中的连接
# 2 = 使用外部 RADIUS 服务器 (还是会优先查找 accept/deny 列表)
# 简单一点的话,可以将两个列表设置为同一个文件,仅由 macaddr_acl 来控制允许或拒绝
macaddr_acl=0
accept_mac_file=/etc/hostapd/hostapd.accept
deny_mac_file=/etc/hostapd/hostapd.deny
# 身份验证算法,1 开放系统认证,2 共享密钥认证(需要 WEP)3 两者
auth_algs=3
# 是否广播,0 广播SSID,1 不广播SSID(发送空SSID,即长度为0的SSID),
# 2 忽略广播 SSID 的探测请求,跟1类似,但是兼容某些不支持空SSID的设备
#ignore_broadcast_ssid=0
#vendor_elements=dd0411223301
# 启用WMM
wmm_enabled=1
#
# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]
# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)
#uapsd_advertisement_enabled=1
#
# Low priority / AC_BK = background
#wmm_ac_bk_cwmin=4
#wmm_ac_bk_cwmax=10
#wmm_ac_bk_aifs=7
#wmm_ac_bk_txop_limit=0
#wmm_ac_bk_acm=0
# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10
#
# Normal priority / AC_BE = best effort
#wmm_ac_be_aifs=3
#wmm_ac_be_cwmin=4
#wmm_ac_be_cwmax=10
#wmm_ac_be_txop_limit=0
#wmm_ac_be_acm=0
# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7
#
# High priority / AC_VI = video
#wmm_ac_vi_aifs=2
#wmm_ac_vi_cwmin=3
#wmm_ac_vi_cwmax=4
#wmm_ac_vi_txop_limit=94
#wmm_ac_vi_acm=0
# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188
#
# Highest priority / AC_VO = voice
#wmm_ac_vo_aifs=2
#wmm_ac_vo_cwmin=2
#wmm_ac_vo_cwmax=3
#wmm_ac_vo_txop_limit=47
#wmm_ac_vo_acm=0
# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
# 检测客户端不活动超时,是否在线间隔时间,默认每5分钟检测客户端是否在线
# 站点不活动限制,默认5分钟
#ap_max_inactivity=300
# 默认禁用,设置为1,说明只要客户在5分钟内没有活动就断线,即使客户端仍然在AP信号的范围内,如果客户端过多可以启用来提高带机量。
#skip_inactivity_poll=0
# 对于过度的传输失败或其他连接丢失的情况下,断开连接,这并不适合所有设备
#disassoc_low_ack=1
# 最大允许侦听间隔,默认65535,即不限制 (how many Beacon periods STAs are allowed to remain asleep)
#max_listen_interval=100
# WDS(4-address frame)模式,仅在 driver=nl80211 的情况下支持
#wds_sta=1
# 仅在设置了bridge= 时有效,默认情况下,例如当设置了bridge=br0,那么wds_bridge=br0。
# 当然也可以手动指定为wds_bridge=XXXXX。
#wds_bridge=wds-br0
# Start the AP with beaconing disabled by default.没明白是什么意思。
#start_disabled=0
# AP隔离,1启用,0禁用。默认不隔离。
#ap_isolate=1
#bss_load_update_period=50
# 用于测试的
#bss_load_test=12:80:20000
##### IEEE 802.11n related configuration ######################################
# 启用80211n,你也将需要启用WMM来使用全部HT功能。
ieee80211n=1
# [HT40-][HT40+]没有设置的话将只工作在20MHz,
# [HT40-]对应可使用的频道为5-13
# [HT40+]对应可使用的频道为1-7(欧洲标准为1-9)
# 当多径效应不是很严重时,用户可以将该间隔配置为[SHORT-GI-20][SHORT-GI-40]
# 个人理解,如果不上天馈系统的话可以启用[SHORT-GI-20][SHORT-GI-40],前提是硬件支持。
#ht_capab=[LDPC][HT40-][HT40+][SHORT-GI-20][SHORT-GI-40][SMPS-DYNAMIC][GF][TX-STBC][RX-STBC123][DELAYED-BA][MAX-AMSDU-7935][DSSS_CCK-40][40-INTOLERANT][LSIG-TXOP-PROT]
# intel Wireless-N 105 (rev c4) 网卡支持的选项
ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40][40-INTOLERANT][GF]
# Atheros AR9271 网卡支持的选项
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40][40-INTOLERANT][RX-STBC1]
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
#ht_capab=[HT40+][DSSS_CCK-40][40-INTOLERANT]
# 强制要求客户端使用HT PHY,不使用就拒绝。
#require_ht=0
# 间隔时间(秒)
#obss_interval=5
##### WPA/IEEE 802.11i configuration ##########################################
# 1 wpa,2 wpa2, 3 两者。 新的设备可以设置为2,仅使用wpa2版本。
wpa=2
# 指定密码,ASCII码或密码字符。
#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
#wpa_passphrase=12345678
# 使用密码文件,可以跟客户端MAC地址绑定设置不同的密码,比较实用。
wpa_psk_file=/etc/hostapd/hostapd.wpa_psk
# 是否使用验证服务器,0 禁用(默认),1 可用,2 强制使用(其他方式将拒绝)
#wpa_psk_radius=0
# 设置密钥管理算法WPA-PSK WPA-EAP或两者
wpa_key_mgmt=WPA-PSK
# 设置加密算法,CCMP就是AES,不推荐使用TKIP,除非设备不支持。
wpa_pairwise=CCMP
# 默认情况下rsn_pairwise自动设置为wpa_pairwise的值,当然也可以手动指定。
#rsn_pairwise=CCMP
#wpa_group_rekey=600
#wpa_strict_rekey=1
#wpa_gmk_rekey=86400
#wpa_ptk_rekey=600
# 预认证
#rsn_preauth=1
#rsn_preauth_interfaces=wlp2s0 br0 enp3s0
#peerkey=1
# 80211w支持,0 禁用(默认),1 可选,2 强制使用(其他方式将拒绝) 有些网卡不支持
#ieee80211w=1
# AES-128-CMAC(默认) BIP-GMAC-128 BIP-GMAC-256 BIP-CMAC-256 四种
# 一般通用设备都支持AES-128-CMAC,其他的不一定
#group_mgmt_cipher=AES-128-CMAC
#assoc_sa_query_max_timeout=1000
#assoc_sa_query_retry_timeout=201
#disable_pmksa_caching=0
#okc=1
#sae_anti_clogging_threshold=5
#sae_groups=19 20 21 25 26
##### IEEE 802.11r configuration ##############################################
# Wi-Fi无线漫游标准
#mobility_domain=a1b2
#r0_key_lifetime=10000
#r1_key_holder=000102030405
#reassociation_deadline=1000
#pmk_r1_push=1
##### Neighbor table ##########################################################
#ap_table_max_size=255
#ap_table_expiration_time=3600
##### IEEE 802.11v-2011 #######################################################
# Wi-Fi节能版 
#time_advertisement=2
#time_zone=CST8
# 下面三项有些网卡不支持
#wnm_sleep_mode=1
#bss_transition=1
#proxy_arp=1

#bss=wifi0
#bssid=00:13:10:95:fe:0d
#interface=wifi0
#ssid=test2
#bridge=br0
#driver=nl80211
#auth_algs=1
#ignore_broadcast_ssid=0
#wpa=2
#wpa_passphrase=12345678
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.java的Java类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值