您的位置:首页 > 其它

调试WIFI时的一些札记

2015-01-10 11:34 281 查看
orgin link is as the below:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=23602891&id=3333288
------------------------------------------------------------------------------------------------------

Wifi Application

packages/apps/Settings/src/com/android/settings/wifi/

Wifi Framework

frameworks/base/wifi/java/android/net/wifi/

frameworks/base/services/java/com/android/server/

Wifi JNI

frameworks/base/core/jni/android_net_wifi_Wifi.cpp

Wifi Hardware

hardware/libhardware_legacy/wifi/wifi.c(这个文件里调用的函数在system/core/libnetutils/下面有实现)

Wifi wpa_supplicant

external/wpa_supplicant

Wifi Driver

hardware/broadcom/wlan/bcm4329/src/

kernel/arch/arm/mach-msm/board-msm7x30-xxx.c

------------------------------------------------------------------------------------------------------

各重要类路径:

Service Manager

frameworks/base/cmds/servicemanager/service_manager.c

WifiService WifiHandler

frameworks/base/services/java/com/android/server/WifiService.java

WifiManager.java、WifiMonitor.java、WifiStateTracker.java、WifiNative.java

frameworks/base/wifi/java/android/net/wifi/

frameworks/base/core/java/android/os/Message.java

frameworks/base/core/java/android/content/Context.java

packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

frameworks/base/services/java/com/android/server/ConnectivityService.java

------------------------------------------------------------------------------------------------------

WiFi子系统分析

初始化

SystemServer 是 Android Java 层的系统服务模块,这个模块主要功能就是管理供 Android 应用开发的 system service.

init.rc 文件一行service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server启动SystemServer。Zygote 进程是整个 Android 的孵化器进程,所有的 Activity 进程均是通过它来生成的。在 zygote 进程启动过程中指定了这么一个参数“– start-system-server” ,这个参数就是在 zygote 进程启动的同时启动 SystemServer。

在SystemServer启动的时候,会生成一个ConnectivityService的实例,关键代码片段:

try {

Slog.i(TAG, "Connectivity Service");

connectivity = ConnectivityService.getInstance(context);

ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);

connectivity.startCne();

} catch (Throwable e) {

Slog.e(TAG, "Failure starting Connectivity Service", e);

}

frameworks/base/services/java/com/android/server/ConnectivityService.java

ConnectivityService的构造函数会创建WifiService,关键代码片段如下:

case ConnectivityManager.TYPE_WIFI:

if (DBG) Slog.v(TAG, "Starting Wifi Service.");

WifiStateTracker wst = new WifiStateTracker(context, mHandler);

WifiService wifiService = new WifiService(context, wst);

ServiceManager.addService(Context.WIFI_SERVICE, wifiService);

wifiService.startWifi();

mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;

wst.startMonitoring();

break;

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

public void startMonitoring() {

/*

* Get a handle on the WifiManager. This cannot be done in our

* constructor, because the Wifi service is not yet registered.

*/

mWM = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);

}

WifiStateTracker会创建WifiMonitor接收来自底层的事件,WifiService和WifiMonitor是整个模块的核心。WifiService负责启动关闭wpa_supplicant、启动关闭WifiMonitor监视线程和把命令下发给 wpa_supplicant,而WifiMonitor则负责从wpa_supplicant接收事件通知。

1.使能WIFI

WirelessSettings 在初始化的时候配置了由WifiEnabler来处理Wifi按钮,

private void initToggles() {

mWifiEnabler = new WifiEnabler(

this,

(WifiManager) getSystemService(WIFI_SERVICE),

(CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI));

当用户按下Wifi按钮后,Android会调用WifiEnabler的onPreferenceChange,再由WifiEnabler调用WifiManager的setWifiEnabled接口函数,通过AIDL机制,实际调用的是WifiService的setWifiEnabled函数,WifiService接着向自身发送一条MESSAGE_ENABLE_WIFI消息,这个消息会经过android os(frameworks/base/core/java/android/os/)中的Message类的sendToTarget()方法发送到Handler类中,Handler类通过MessageQueue类维护一个消息队列,它会在指定的时间把消息发送出去。最终由WifiHandler类的handleMessage()方法来处理消息(注意在WifiStateTracker类中也有一个handleMessage函数,WifiService中的handleMessage函数是用来处理在本类中定义的message消息类型;WifiStateTracker类中的handleMessage函数是用来处理在WifiStateTracker中定义的事件类型),它会调用setWifiEnabledBlocking()方法。在setWifiEnabledBlocking方法中做真正的使能工作:首先装载
WIFI内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ),然后启动wpa_supplicant(配置文件为"/data/misc/wifi/wpa_supplicant.conf")再通过WifiStateTracker来启动WifiMonitor中的监视线程。关键代码片段如下:

private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {

......

if (enable) {

if (!mWifiStateTracker.loadDriver()) {

Slog.e(TAG, "Failed to load Wi-Fi driver.");

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

return false;

}

if (!mWifiStateTracker.startSupplicant()) {

mWifiStateTracker.unloadDriver();

Slog.e(TAG, "Failed to start supplicant daemon.");

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

return false;

}

registerForBroadcasts();

mWifiStateTracker.startEventLoop(); //-->startEventLoop()-->mWifiMonitor.startMonitoring();

}

......

setWifiEnabledState(eventualWifiState, uid);

return true; |

}    |

     V

private void setWifiEnabledState(int wifiState, int uid) {

......

// Update state

mWifiStateTracker.setWifiState(wifiState);

// Broadcast

final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);

intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);

intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);

mContext.sendStickyBroadcast(intent);

}

当使能成功后,会广播发送 WIFI_STATE_CHANGED_ACTION 这个Intent通知外界,WIFI已经成功使能了。由于WifiEnabler初始化时注册了BroadcastReceiver,因此它会收到该Intent,从而开始扫描。

private void handleWifiStateChanged(int wifiState) {

if (wifiState == WIFI_STATE_ENABLED) {

loadConfiguredAccessPoints();

attemptScan();

}

2.查找AP

扫描的入口函数是WifiService的startScan,它其实也就是往wpa_supplicant发送SCAN命令。

static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz)

{

jboolean result;

// Ignore any error from setting the scan mode.

// The scan will still work.

if (forceActive && !sScanModeActive)

doSetScanMode(true);

result = doBooleanCommand("SCAN", "OK");

if (forceActive && !sScanModeActive)

doSetScanMode(sScanModeActive);

return result;

}

|

V

doBooleanCommand("SCAN", "OK");

|

V

char reply[256];

doCommand(cmd, reply, sizeof(reply))

|

V

size_t reply_len = replybuflen - 1;

::wifi_command(cmd, replybuf, &reply_len) (以上-->frameworks/base/core/jni/android_net_wifi_Wifi.cpp)

|

V

int wifi_command(const char *command, char *reply, size_t *reply_len)

|

V

wifi_send_command(ctrl_conn, command, reply, reply_len); (以上-->hardware/libhardware_legacy/wifi/wifi.c)

|

V

wpa_ctrl_request (external/wpa_supplicant_6/wpa_supplicant/src/common/wpa_ctrl.c)

command一直传送到wifi_send_command这个函数为止,程序开始变的复杂了一些。注意wifi_send_command的四个参数都是传的指针,后面三个参数都是从上面一直传过来的,下面我们来分析下第一个参数是怎么得来的。

ctrl_conn是一个全局静态变量,是这样定义的:static struct wpa_ctrl *ctrl_conn;

它在wifi_connect_to_supplicant()函数中初始化的。wifi_connect_to_supplicant()调用ctrl_conn = wpa_ctrl_open(ifname),其中ifname是"wlan0",这个wlan0是在system/core/rootdir/etc/init.qcom.rc中设置的:setprop wifi.interface wlan0。wpa_ctrl_open函数就是建立并初始化一个Unix domain socket的client结点,并与作为server的wpa_supplicant结点绑定。

接下来monitor_conn = wpa_ctrl_open(ifname),monitor_conn是用来监视从wpa_supplicant发出的event事件。然后调用wpa_ctrl_attach(monitor_conn)。wpa_ctrl_attach最后又调用了wpa_ctrl_request,wpa_ctrl_request用select系统调用来监听socket是否有数据过来,这个socket就是在wpa_ctrl_open函数里初始化的。

我们分析下wpa_ctrl_open函数:

当前项目中代码为:external/wpa_supplicant_6/wpa_supplicant_broadcom/src/common/wpa_ctrl.c

WIFI用的是UNIX domain IPC, wpa_ctrl_open做的工作就是创建两个socket, 服务端是/data/misc/wifi/sockets/wpa_ctrl_185-16,客户端是/dev/socket/wpa_wlan0。客户端socket文件名后缀wlan0正是我们在上面传入过来的。还有一个监听用的socket文件,/data/misc/wifi/sockets/wpa_ctrl_185-17。wpa_ctrl_request函数做的工作其实很简单,就是客户端向服务端发送了一个命令,只不过用的是select机制,猛一看上去可能有点复杂。然后就一步步返回了。还有一点就是monitor_conn,在wifi_connect_to_supplicant函数中会调用wpa_ctrl_attach(monitor_conn)-->wpa_ctrl_attach_helper(ctrl,
1)-->wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, buf, &len, NULL),调用到wpa_ctrl_request,我们上面分析过是往socket中发命令。在wifi.c中的wifi_wait_for_event会调用wpa_ctrl_recv(monitor_conn, buf, &nread)接收刚才发送的命令。

现在问题是与底层driver通信的代码在哪?ATTACH这个命令最终由谁来解析?

当 wpa_supplicant 处理完 SCAN 命令后,它会向控制通道发送事件通知扫描完成,从而wifi_wait_for_event(hardware/libhardware_legacy/wifi/wifi.c)函数会接收到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来处理这个事件:

void handleEvent(int event, String remainder) {

case SCAN_RESULTS:

mWifiStateTracker.notifyScanResultsAvailable();

break;

WifiStateTracker 则接着广播发送 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent:

case EVENT_SCAN_RESULTS_AVAILABLE:

mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

WifiLayer(packages/apps/Settings/src/com/android/settings/wifi/WifiStatusTest.java)注册了接收 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent,所以它的相关处理函数 handleScanResultsAvailable 会被调用,在该函数中,先会去拿到 SCAN 的结果(最终是往wpa_supplicant发送SCAN_RESULT命令并读取返回值来实现的), List<ScanResult> list
= mWifiManager.getScanResults();对每一个扫描返回的 AP,WifiLayer 会调用 TextView 的 setText 函数,从而最终把该 AP 加到 GUI 显示列表中。

3. 连接

用户在 WifiSettings 界面上选择一个 AP,输入密钥,点击连接按钮,Android 就会去连接这个 AP。

private void handleConnect() {

String password = getEnteredPassword();

if (!TextUtils.isEmpty(password)) {

mState.setPassword(password);

}

mWifiLayer.connectToNetwork(mState);

}

WifiLayer 会先检测这个 AP 是不是之前被配置过,这个是通过向 wpa_supplicant 发送 LIST_NETWORK 命令并且比较返回值来实现的,

// Need WifiConfiguration for the AP

WifiConfiguration config = findConfiguredNetwork(state);

如果 wpa_supplicant 没有这个 AP 的配置信息, 则会向 wpa_supplicant 发送 ADD_NETWORK 命令来添加该 AP,

if (config == null) {

// Connecting for the first time, need to create it

config = addConfiguration(state, ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE);

}

ADD_NETWORK 命 令 会 返 回 一 个 ID , WifiLayer 再用这个返回的 ID 作为参数向 wpa_supplicant 发送 ENABLE_NETWORK 命令,从而让 wpa_supplicant 去连接该 AP。

// Make sure that network is enabled, and disable others

mReenableApsOnNetworkStateChange = true;

if (!mWifiManager.enableNetwork(state.networkId, true)) {

Log.e(TAG, "Could not enable network ID " + state.networkId);

error(R.string.error_connecting);

return false;

}

4. 配置 IP 地址

当 wpa_supplicant 成功连接上 AP 之后,它会向控制通道发送事件通知连接上 AP 了,wifi_wait_for_event 函数会接收到该事件,然后由 WifiMonitor 中的 MonitorThread 来处理这个事件,

void handleEvent(int event, String remainder) {

case CONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);

break;

WifiMonitor 再调用 WifiStateTracker 的 notifyStateChange,WifiStateTracker 则接着会往自身发送 EVENT_DHCP_START 消息来启动 DHCP 去获取 IP 地址,

private void handleConnectedState() {

setPollTimer();

mLastSignalLevel = -1;

if (!mHaveIPAddress && !mObtainingIPAddress) {

mObtainingIPAddress = true;

mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();

}

}

然后再广播发送 NETWORK_STATE_CHANGED_ACTION 这个 Intent

case EVENT_NETWORK_STATE_CHANGED:

if (result.state != DetailedState.DISCONNECTED || !mDisconnectPending) {

intent = newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION);

intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);

if (result.BSSID != null)

intent.putExtra(WifiManager.EXTRA_BSSID, result.BSSID);

mContext.sendStickyBroadcast(intent);

}

break;

WifiLayer 注册了接收 NETWORK_STATE_CHANGED_ACTION 这个 Intent,所以它的相关处理函数 handleNetworkStateChanged 会被调用,当 DHCP 拿到 IP 地址之后,会再发送 EVENT_DHCP_SUCCEEDED 消息,

private class DhcpHandler extends Handler {

public void handleMessage(Message msg) {

switch (msg.what) {

case EVENT_DHCP_START:

if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {

event = EVENT_DHCP_SUCCEEDED;

}

WifiLayer 处 理 EVENT_DHCP_SUCCEEDED 消息 , 会再次广播发送 NETWORK_STATE_CHANGED_ACTION 这个 Intent,这次带上完整的 IP 地址信息。

case EVENT_DHCP_SUCCEEDED:

mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);

setDetailedState(DetailedState.CONNECTED);

intent = newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION);

intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);

mContext.sendStickyBroadcast(intent);

break;

从framework到app的整个连接过程就是这样的。

------------------------------------------------------------------------------------------------

wpa_supplicant提供上行接口和下行接口。上行接口用于与其他模块(如UI)通信。下行接口与内核通信。wpa_supplicant提供的上行接口包括Dbus和Unix domain socket。

Wpa_supplicant 提供两种由外部模块获取信息的方式:一种是外部模块通过发送request 命令然后获取response的问答模式,另一种是wpa_supplicant主动向外部发送event事件,由外部模块监听接收。一般的常用做法是外部模块通过调用wpa_ctrl_open()两次,建立两个control interface接口,一个为ctrl interface,用于发送命令,获取信息,另一个为monitor interface,用于监听接收来自于wpa_supplicant的event时间。这样可以降低通信的耦合性,避免response和event的相互干扰。

下行接口包括:

1.PF_INET socket接口,主要用于向kernel 发送ioctl命令,控制并获取相应信息。

2.PF_NETLINK socket接口,主要用于接收kernel发送上来的event事件。

3.PF_PACKET socket接口,主要用于向driver传递802.11x报文。

具体实现在external/wpa_supplicant/目录下。

------------------------------------------------------------------------------------------------

wifi 动态 mac:

给一itemid,默认是NV_VERNO_MAJ_I,然后从??里读出nv项,也就是mac地址,如果读出为空,那么自动生成,并写到/etc/firmware/nvram.txt里。

------------------------------------------------------------------------------------------------

什么是 WPS(Wi-Fi Protected Setup) WPS(Wi-Fi Protected Setup,Wi-Fi保护设置)是由Wi-Fi联盟(http://www.wi-fi.org/)组织实施的认证项目,主要致力于简化无线局域网的安装及安全性能配置工作。在传统方式下,用户新建一个无线网络时,必须在接入点手动设置网络名(SSID)和安全密钥,然后在客户端验证密钥以阻止“不速之客”的闯入。这整个过程需要用户具备Wi-Fi设备的背景知识和修改必要配置的能力。Wi- Fi Protected Setup能帮助用户自动设置网络名(SSID)、配置强大的WPA数据编码及认证功能,用户只需输入个人信息码(PIN方法)或按下按钮(按钮设置,或称PBC),即能安全地连入WLAN。

------------------------------------------------------------------------------------------------

| <---------- D-Bus Application API

+--------------------+

| connection manager |

| or p2p control app |

+--------------------+

| <---------- D-Bus supplicant API

| or socket control interface

+--------------------+

| wpa_supplicant |

+--------------------+

| <---------- nl80211

+--------------------+

| cfg80211 |

+--------------------+

| <---------- struct API

+--------------------+

| mac80211 |

+--------------------+

| <---------- mac80211's driver API

+--------------------+

| driver |

+--------------------+

[Wireless Card]

|

[Linux Kernel]

| |

[udev][libnl]-[iw]

| / \

[crda] \

| \

[ Wireless |

Regulatory |

Database ] |

|

|

[ hostapd ]

无线网卡:操作接收/发送无线包。

linux内核:linux内核包涵了无线网尗的驱动,mac80211子系统处理包的产生与时序安排。nl80211处理在用户空间配置无线接口cfg80211。

libnl:通过netlink与内核对话的传输层。

udev:udev是内核通过events/calls到crda的设施。

iw:是我们用来测试libnl是否正确工作,以及在无线网卡上创建额外的虚拟无线接口的用户空间工具。

crda:是内核通过udev来查找什么频段/频率是有效的,在什么强度的用户空间程序。这个从内核维护的静态表中移到用户空间,它可以不需要重载驱动和重启的情况下更新。

无线控制数据库:crda使用允许的频率和传输强度等级的数据库。

hostapd:这是个用来操作信号的产生和其它无线包,以及wpa-psk, wpa2等加密的守护进程。

------------------------------------------------------------------------------------------------

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java目录里:

mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");

sDnsPropNames = new String[] {

"dhcp." + mInterfaceName + ".dns1",

"dhcp." + mInterfaceName + ".dns2"

};

执行过程:

当wpa_supplicant起来以后:

守护进程会产生一个/data/system/wpa_supplicant/wlan0接口

根据wpa_cupplicant.conf得来:

ctrl_interface=DIR=/data/system/wpa_supplicant

同时在/data/misc/wifi/下创建一个sockets目录,下面会有二个socket

一个是控制接口,一个是监控接口(这个接口用于监测从wpa_supplicant发出的event事件。)。

Wifi.c会通过这二个接口和守护进程通信。

wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运行wpa_supplicant,使用wpa_cli来搜索、设置、和连接网络。

------------------------------------------------------------------------------------------------

关闭wifi的过程:

在wifi连接成功后,logcat会一直打印:

V/WifiStateTracker( 962): handleMessage(): msg.what= 8 //EVENT_POLL_INTERVAL = 8

也就是WifiStateTracker会一直轮询wifi的状态。

点击关闭wifi后,执行流程是这样的(Log中很清楚,可自行看代码跟踪):

V/WifiStateTracker( 962): handleMessage(): msg.what= 8

I/wpa_supplicant( 896): CTRL-EVENT-TERMINATING - signal 15 received

V/WifiMonitor( 962): Event [CTRL-EVENT-TERMINATING - signal 15 received]

V/WifiStateTracker( 962): handleMessage(): msg.what= 2

V/DATA ( 1051): [DCT(0) ] intent received :android.net.wifi.WIFI_STATE_CHANGED

V/WifiStateTracker( 962): Connection to supplicant lost

V/WifiStateTracker( 962): *** reset mP2pState to IDLE

V/WifiStateTracker( 962): clearP2pNotification enter

V/WifiStateTracker( 962): clearP2pNotification exit

I/ActivityManager( 962): Start proc com.android.settings for broadcast com.android.settings/.widget.SettingsAppWidgetProvider: pid=1495 uid=1000 gids={3002, 3001, 3003}

D/ConnectivityService( 962): ConnectivityChange for WIFI: DISCONNECTED/DISCONNECTED

D/ConnectivityService( 962): Got Network Disconnected from Driver nwtype=1

D/WifiStateTracker( 962): P2P Reset connections and stopping DHCP

D/WifiStateTracker( 962): Reset connections and stopping DHCP

D/WifiStateTracker( 962): requestConnectionInfo

D/WifiStateTracker( 962): requestConnectionStatus

I/wpa_supplicant( 896): CTRL-EVENT-STATE-CHANGE id=0 state=0 BSSID=00:00:00:00:00:00

I/wpa_supplicant( 896): CTRL_IFACE monitor[0]: 2 - No such file or directory

I/dun_service( 110): process rmnet event

I/dun_service( 102): process rmnet event

------------------------------------------------------------------------------------------------

Porting WiFi drivers to Android:(好详细的说)
http://blog.linuxconsulting.ro/2010/04/porting-wifi-drivers-to-android.html
------------------------------------------------------------------------------------------------

Wifi-Direct Porting[SDK Layer]:

加入一个方法要改的文件:

frameworks/base/core/java/android/net/ConnectivityManager.java

frameworks/base/core/java/android/net/IConnectivityManager.aidl

有关Wifi-Direct的一些宏定义:

frameworks/base/core/java/android/provider/Settings.java

对新加入命令的处理函数族:

frameworks/base/core/jni/android_net_wifi_Wifi.cpp

配置Wifi-Direct iface/netmask:

frameworks/base/services/java/com/android/server/connectivity/Tethering.java

在这几个文件中分别加入控制和查询WIFI连接状态的函数族:

packages/apps/Settings/src/com/android/settings/wifi/WifiDirectSettings.java

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

frameworks/base/services/java/com/android/server/WifiService.java

frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl

frameworks/base/wifi/java/android/net/wifi/WifiNative.java

比方说在这几个文件中分别有一个名称为findP2p()函数。

public boolean findP2p(int p2pTimeout) /* Request the supplicant to find P2P devices. p2pTimeout timeout in seconds, 0 means indefinite time */

调用流程是这样的:

WifiDirectSettings-->WifiManager通过Binder机制(IWifiManager.aidl)-->WifiService-->WifiStateTracker通过JNI接口(WifiNative.java)-->android_net_wifi_Wifi-->doBooleanCommand-->doCommand-->wifi_command-->wifi_send_command-->wpa_ctrl_request

另外,WifiManager定义WIFI相关的状态宏,例如P2P_STATE_XXX、WIFI_AP_STATE_XXX等;WifiStateTracker定义WIFI相关的事件宏,例如EVENT_DHCP_START、EVENT_P2P_DHCP_START、EVENT_SUPPLICANT_CONNECTION等;WifiService定义消息类型,例如MESSAGE_ENABLE_WIFI、MESSAGE_DISABLE_WIFI等。

WifiMonitor:

frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

看注释,写的很清楚:

/** Events we receive from the supplicant daemon */

private static final int CONNECTED = 1;

private static final int DISCONNECTED = 2;

private static final int STATE_CHANGE = 3;

private static final int SCAN_RESULTS = 4;

private static final int LINK_SPEED = 5;

private static final int TERMINATING = 6;

private static final int DRIVER_STATE = 7;

private static final int UNKNOWN = 8;

在Porting的过程中,对WifiMonitor这个文件只修改了这些地方:

1).

/** Adding P2P prefix */

private static final String p2pEventPrefix = "P2P-";

private static final String apStaEventPrefix = "AP-STA-";

2).

在MonitorThread类中加入对P2P事件的判断:

// Parsing P2P event

if (eventStr.startsWith(p2pEventPrefix)

......

3).

对P2P事件的处理函数:

private void handleP2pEvent(String data) {

if (Config.LOGD) Log.d(TAG, "Received P2P event");

mWifiStateTracker.notifyP2pEvent(data);

}

定义supplicant的状态是否是合法的:

frameworks/base/wifi/java/android/net/wifi/SupplicantState.java

界面上的一些修改:

packages/apps/Settings/src/com/android/settings/wifi/*

packages/apps/Settings/AndroidManifest.xml

packages/apps/Settings/res/drawable-* //显示图片

packages/apps/Settings/res/layout/

packages/apps/Settings/res/values/

packages/apps/Settings/res/xml/

------------------------------------------------------------------------------------------------

kernel/arch/arm/mach-msm/board-msm7x30-xxx.c

bcm_wlan_power_on

|

V

bcm_detect_card(1) // kernel/drivers/mmc/core/host.c

|

V

mmc_detect_change(sdio_host, n)-->mmc_schedule_delayed_work(&host->detect, delay)-->mmc_rescan() //kernel/drivers/mmc/core/core.c

|

V

附:

1.下面说下sdio_host是怎么初始化的。

在msmsdcc_probe函数里初始化一个struct mmc_host *mmc,然后调用mmc_add_host(mmc) // kernel/drivers/mmc/host/msm_sdcc.c

|

V

接着在mmc_add_host函数里调用select_sdio_host(host, 1),这里的host就是上面传来的mmc。 // kernel/drivers/mmc/core/host.c

在select_sdio_host函数中给host.c文件中的变量struct mmc_host *sdio_host = NULL; 赋值sdio_host = host。

2.host->detect

是在msmsdcc_probe时调用mmc_alloc_host函数初始化的。INIT_DELAYED_WORK(&host->detect, mmc_rescan)。

mmc流程可参考金明SD资料,不再叙述。

------------------------------------------------------------------------------------------------

下面分析命令到驱动层的流程:

sock_ioctl // net/socket.c

|

V

dev_ioctl // net/core/dev.c

|

V

wext_handle_ioctl-->wext_ioctl_dispatch-->wireless_process_ioctl // net/wireless/wext-core.c

------------------------------------------------------------------------------------------------

wlan 调试纪要: 1: make kernelconfig打开以下选项: CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y EMBEDED_SDIO=y MMC2_SUPPORT=y 可参考: kernel/arch/arm/configs/msm7630-xxx-perf_defconfig

2: 实现上电函数: bcm_wlan_power_on(int) bcm_wlan_power_off(int) kernel/arch/arm/mach-msm/board-msm7X30-xxx.c

3: 驱动编译: cd open-src/src/dhd/linux make LINUXDIR=/home/pengly/btg/xxx/kernel ARCH=arm CROSS_COMPILE=/home/pengly/btg/xxx/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- dhd-cdc-sdmmc-gpl 生成dhd.ko

4: 命令行验证: echo 1 > /sys/devices/platform/msm_sdcc.3/polling insmod /system/lib/modules/dhd.ko "firmware_path=/etc/firmware/sdio.bin nvram_path=/etc/firmware/nvram.txt iface_name=wlan" 加载成功后: wl up wl scan wl results 输出ssid信息则正常

5:上层移植涉及文件: hardware/libhardware_legacy/wifi/wifi.c frameworks/base/wifi/ external/wpa_supplicant_6/ system/core/rootdir/etc/init.qcom.rc /hardware/broadcom

BT 调试纪要: 1: make kernelconfig打开以下选项: CONFIG_BT=y CONFIG_BT_L2CAP=y CONFIG_BT_SCO=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=y CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_LL=y CONFIG_RFKILL=y

2:上电部分驱动注册 kernel/arch/arm/mach-msm/board-msm7X30-xxx.c

3:驱动调试 echo 1 > /sys/devices/platform/bt_power.0/rfkill/rfkill0/state brcm_patchram_plus --enable_hci --patchram /etc/firmware/brcm4330.hcd /dev/ttyHS0 -d hciconfig hci0 up hciconfig hci0 piscan hcitool dev hcitool scan 能搜索到蓝牙设备则正常

4: pcm调试 system/bluetooth/brcm_patchram_plus/brcm_patchram_plus.c 通过hcitool对hci0初始化等

5:其他涉及修改代码: /kernel/driver/bluesleep/bluesleep.c /system/bluetooth/bluedroid/bluetooth.c /system/bluetooth/brcm_patchram_plus/brcm_patchram_plus.c system/core/rootdir/etc/init.qcom.rc
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: