Wifi模块全总结.doc_第1页
Wifi模块全总结.doc_第2页
Wifi模块全总结.doc_第3页
Wifi模块全总结.doc_第4页
Wifi模块全总结.doc_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

WIFI学习总结1WLAN技术32802.11协议简述32.1.1概述33802.11四种主要物理组件43.1工作站(Station)43.2接入点(Access Point)43.3无线媒介(Wireless Medium)43.4分布式系统(Distribution System)44WIFI适配层55wpa_supplicant65.1wpa_ctrl的作用65.2WPA_SUPPLICANT65.2.1概念65.2.2Wpa_supplicant与驱动的交互66Wpa_cli调试工具76.1启动wpa_supplicant76.2连接wpa_cli到wpa_supplicant76.3示例86.3.1无密钥认证AP86.3.2WEP认证AP86.3.3WPA-PSK/WPA2-PSK认证AP86.3.4隐藏AP97Wifi模块解析和启动流程97.1框架分析97.2Wifi启动流程118WLAN驱动结构介绍228.1SDIO驱动228.2Boardcom无线通讯芯片238.2.1概述238.2.2源码238.3详细接口及代码分析248.3.1WIFI驱动流程分析248.3.2WIFI设备注册流程258.3.3WIFI驱动流程(二)408.3.4网络设备注册流程439IOCTL的调用逻辑4810数据的传送5610.1数据传送过程简述5610.2Bcm4329芯片wlan驱动数据传送5710.3传输超时5911数据的接收5911.1数据接收的方式和过程5911.2选择哪种接收模式6011.3Bcm4329芯片wlan驱动数据传送6012电源管理相关的调用逻辑6513Android平台的Wifi模块移植要点7413.1Wifi结构7413.2Wifi模块环境7513.3Wifi模块的编译7513.3.1Wifi驱动源码7513.3.2在android平台添加BCM43xx驱动7513.3.3编译wifi驱动源码7913.3.4在android中使用BCM43xx801 WLAN技术WLAN是英文WirelessLAN的缩写,就是无线局域网的意思。无线以太网技术是一种基于无线传输的局域网技术,与有线网络技术相比,具有灵活、建网迅速、个人化等特点。将这一技术应用于电信网的接入网领域,能够方便、灵活地为用户提供网络接入,适合于用户流动性较大、有数据业务需求的公共场所、高端的企业及家庭用户、需要临时建网的场合以及难以采用有线接入方式的环境等。2 802.11协议简述2.1.1 概述作为全球公认的局域网权威,IEEE802工作组建立的标准在过去二十年内在局域网领域独领风骚。这些协议包括了802.3Ethernet协议、802.5TokenRing协议、802.3z100BASET快速以太网协议。在1997年,经过了7年的工作以后,IEEE发布了802.11协议,这也是在无线局域网领域内的第一个国际上被认可的协议。在1999年9月,他们又提出了802.11bHighRate协议,用来对802.11协议进行补充,802.11b在802.11的1Mbps和2Mbps速率下又增加了5.5Mbps和11Mbps两个新的网络吞吐速率。利用802.11b,移动用户能够获得同Ethernet一样的性能、网络吞吐率、可用性。这个基于标准的技术使得管理员可以根据环境选择合适的局域网技术来构造自己的网络,满足他们的商业用户和其他用户的需求。802.11协议主要工作在ISO协议的最低两层上,并在物理层上进行了一些改动,加入了高速数字传输的特性和连接的稳定性。主要内容:1.802.11工作方式2.802.11物理层3.802.11b的增强物理层4.802.11数字链路层5.联合结构、蜂窝结构和漫游3 802.11四种主要物理组件3.1 工作站(Station)构建网络的主要目的是为了在工作站间传送数据。所谓工作站,是指配备无线网络接口的计算设备。3.2 接入点(Access Point)802.11网络所使用的帧必须经过转换,方能被传递至其他不同类型的网络。具备无线至有线的桥接功能的设备称为接入点,接入点的功能不仅于此,但桥接最为重要。3.3 无线媒介(Wireless Medium)802.11标准以无线媒介在工作站之间传递帧。其所定义的物理层不只是一种,802.11最初标准化了两种射频物理层以及一种红外线物理层。3.4 分布式系统(Distribution System)当几个接入点串联以覆盖较大区域时,彼此之间必须相互通信以掌握移动式工作站的行踪。分布式系统属于802.11的逻辑组件,负责将帧转送至目的地。下图为802.11网络的基本服务集(basic service set),其中包含了这四种物理组件。4 WIFI适配层里面定义很多字符串变量和适配层的接口实现,是对wpa_supplicant程序通信的接口封装,用来完成上层和wpa_supplicant的通信, 头文件在libhardware/include/hardware下,这里的函数用来向JNI的本地实现提供调用接口。这里的函数,我把它们分为四类函数:一类是命令相关的(控制)函数,就是在JNI层android_XXX_Command()函数所调用 的Wifi_Command()函数,调用流程如下:android_XXX_command()=docommand()=wifi_command()=wifi_send_command()=wpa_ctrl_require()。二类是 监听函数,即Wifi_wait_for_event()函数,调用流程如下:android_net_wifi_Waitforevent()= wifi_wait_for_event()=wpa_ctrl_recv()。三就是WPA_SUPPLICANT的启动,连接,关闭函数四是驱动的加载和卸载函数5 wpa_supplicant5.1 wpa_ctrl的作用定义了两类套接字和一个管道,并分别实现了和wpa_supplicant的通信,而在实际的实现中采用的都是套接字的方式,因此wpa_supplicant适配层和wpa_supplicant层 是通过socket通讯的。要是从wifi.c中真的很难看出它和wpa_supplicant有什么关系,和它联系密切的就是 这个wpa_ctrl.h文件,这里面定义了一个类wpa_ctrl,这个类中声明了两个Socket套接口,一个是本地一个是要连接的套接 口,wpa_ctrl与wpa_supplicant的通信就需要socket来帮忙了,而wpa_supplicant就是通过调用 wpa_ctrl.h中定义的函数和wpa_supplicant进行通讯的,wpa_ctrl类(其实是其中的两个socket)就是他们之间的桥梁。5.2 WPA_SUPPLICANT5.2.1 概念wpa_supplicant本是开源项目源码,被谷歌修改后加入android移动平台,它主要是用来支持WEP,WPA/WPA2和WAPI无线协议和加密认证的,而实际上的工作内容是通过socket(不管是wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯)与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调动驱动来对WiFi芯片操作。 简单的说,wpa_supplicant就是WiFi驱动和用户的中转站外加对协议和加密认证的支持。 5.2.2 Wpa_supplicant与驱动的交互5.2.2.1 wpa_supplicant.c首先定义一个驱动操作数组externstruct wpa_driver_ops *wpa_supplicant_drivers,然后是系列wpa_supplicant_XXX()函数,很多函数里面调用 wpa_drv_XXX()函数,这些函数是wpa_supplicant_i.h中实现的函数。几乎每个函数都需要一个wpa_supplicant结 构,对其进行所有的控制和通信操作。5.2.2.2 Wpa_supplicant_i.h其中定义了一个重要数据结构wpa_supplicant,其中有一个重要的driver成 员,它是wpa_driver_ops类型,可以被用来调用抽象层的接口。接下来是系列函数声明,这些函数声明在wpa_supplicant.c中实现,然后就是wpa_drv_XXX函数,这些函数就是在 wpa_supplicant.c中被wpa_supplicant_xxx函数调用的,而这些wpa_drv_xxx函数也都有一个 wpa_supplicant结构的变量指针,用来调用封装的抽象接口,而这些抽象接口的实现在driver_wext.c中(如果使用的汉斯WEXT驱动)。这里要注意的是:在wpa_suppliant.c文件中定义的很多函数是在该头文件中声明的,而不是在wpa_supplicant.h中声明的。5.2.2.3 Driver_wext.c对wpa_drvier_ops的个函数的具体实现,该结构指针在wpa_supplicant注册一个网络接口时会被初始化赋予指定的操作指针,wpa_supplicant.c中的wpa_supplicant_xxx函数通过wpa_supplicant结构中的该操作指针调用WEXT的实现接口。就是在该文件中,创建了三个socket:ioctrl_socket,event_socket和mlme_socket,它们分别有自己的用途,如ioctrl_socket用于发送控制命令,event_socket用于监听驱动传来的event事件等。Wpa_supplicant通过这三个socket与wifi驱动关联,这里的socket同fd(文件描述符)类似。6 Wpa_cli调试工具6.1 启动wpa_supplicant使用下面命令启动wpa_supplicant: wpa_supplicant -Dwext -iwlan0 -C/data/system/wpa_supplicant -c/data/misc/wifi/wpa_supplicant.conf为了确保wpa_supplicant真的启动起来了,使用“ps”命令查看。6.2 连接wpa_cli到wpa_supplicant wpa_cli -p/data/system/wpa_supplicant -iwlan0 然后,就可以使用wpa_cli调试工具进行wifi调试了,下面列出了一些常用的调试命令: scan /扫描周围的AP scan_results /显示扫描结果 status /显示当前的连接状态信息 terminate /终止wpa_supplicant quit/退出wpa_cli add_network /返回可用network id set_network /设置网络 select_network /选择网络,禁用其它网络 disable_network /禁用网络 enable_network /启用网络6.3 示例6.3.1 无密钥认证AP add_network (返回可用network id, 假定返回0) set_network 0 ssid “666” set_network 0 key_mgmt NONE enable_network 0 quit如果上面的操作正确,我们会连接到一个AP,它的SSID为“666”,现在需要一个IP来访问internet: dhcpcd wlan0成功获取IP后,即可连上internet。6.3.2 WEP认证AP add_network (假设返回1) set_network 1 ssid “666” set_network 1 key_mgmt NONE set_network 1 wep_key0 “ap passwork” set_network 1 wep_tx_keyidx 0 select_network 1(如果你已经连上了其它的AP,那么就需要这个命令来禁用其它的网络) enable_network 1然后同上获取IP,连接到internet上。6.3.3 WPA-PSK/WPA2-PSK认证AP add_network (假定返回2) set_network 2 ssid “666” set_network 2 psk “your pre-shared key” select_network 2 enable_network 2还有其它的命令进一步设置网络,不过wpa_supplicant已经给了我们一些默认的配置。6.3.4 隐藏AP原则上应该只要在上面的基础上去set_network netid scan_ssid 1即可,测试过无加密的Hidden AP,WEP/WPA/WPA2应该道理一样。7 Wifi模块解析和启动流程7.1 框架分析WIFI整体框架如图所示:WirelessSettingsWifiSettingAccessPointDialogWifiEnablerWifiLayerWifiManagerWifiStateTrackerWifiWpa_supplicantKernel/net驱动Wifi电源管理驱动WiFi模块驱动.koWifi模组WifiServiceWifiMonitorWifiNatvieAndroid_net_wifi_wifiWIFI_STATE_CHANGED_ACTIONNETWORK_STATE_CHANGED_ACTIONSCAN_RESULTS_AVAILABLE_ACTIONSUPPLICANT_CONNECTION_CHANGE_ACTIONJAVA VM首先,用户程序使用WifiManager类来管理Wifi模块,它能够获得Wifi模块的状态,配置和控制Wifi模块,而所有这些操作都要依赖 Wifiservice类来实现。WifiService和WifiMonitor类是Wifi框架的核心,如图所示。下面先来看看WifiService是什么时候,怎么被创建和初始化 的。在systemServer启动之后,它会创建一个 ConnectivityServer对象,这个对象的构造函数会创建一个WifiService的实例,代码如下所示:framework/base/services/java/com/android/server/ConnectivityService.javacase ConnectivityManager.TYPE_WIFI:if (DBG) Slog.v(TAG, Starting Wifi Service.);WifiStateTracker wst = new WifiStateTracker(context, mHandler); /创建WifiStateTracker实例 WifiService wifiService = newWifiService(context, wst);/创建WifiService实例ServiceManager.addService(Context.WIFI_SERVICE, wifiService); /向服务管理系统添加Wifi服务wifiService.startWifi(); /启动WifimNetTrackersConnectivityManager.TYPE_WIFI = wst; wst.startMonitoring(); /启动WifiMonitor中的WifiThread线程 WifiService的主要工作:WifiMonitor和Wpa_supplicant的启动和关闭,向Wpa_supplicant发送命令。 WifiMonitor的主要工作:阻塞监听并接收来自Wpa_supplicant的消息,然后发送给WifiStateTracker。 上面两个线程通过AF_UNIX套接字和Wpa_supplicant通信,在通信过程中有两种连接方式:控制连接和监听连接。它们创建代码如下:ctrl_conn =wpa_ctrl_open(ifname);. . .monitor_conn = wpa_ctrl_open(ifname);7.2 Wifi启动流程 (1)使能Wifi 要想使用Wifi模块,必须首先使能Wifi,当你第一次按下Wifi使能按钮时,WirelessSettings会实例化一个WifiEnabler 对象,实例化代码如下:packages/apps/settings/src/com/android/settings/WirelessSettings.javaprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI); mWifiEnabler= new WifiEnabler(this, wifi); WifiEnabler类的定义大致如下,它实现了一个监听接口,当WifiEnabler对象被初始化后,它监听到你按键的动作,会调用响应函数 onPreferenceChange(),这个函数会调用WifiManager的setWifiEnabled()函数。public class WifiEnabler implementsPreference.OnPreferenceChangeListener public boolean onPreferenceChange(Preference preference,Object value) booleanenable = (Boolean) value;if (mWifiManager.setWifiEnabled(enable) mCheckBox.setEnabled(false); 我们都知道Wifimanager只是个服务代理,所以它会调用WifiService的setWifiEnabled()函数,而这个函数会调用 sendEnableMessage()函数,了解android消息处理机制的都知道,这个函数最终会给自己发送一个 MESSAGE_ENABLE_WIFI的消息,被WifiService里面定义的handlermessage()函数处理,会调用 setWifiEnabledBlocking()函数。下面是调用流程:mWifiEnabler.onpreferencechange()=mWifiManage.setWifienabled()=mWifiService.setWifiEnabled()=mWifiService.sendEnableMessage()=mWifiService.handleMessage()=mWifiService.setWifiEnabledBlocking().在 setWifiEnabledBlocking()函数中主要做如下工作:加载Wifi驱动,启动wpa_supplicant,注册广播接收器,启动 WifiThread监听线程。代码如下:if (enable) if (!mWifiStateTracker.loadDriver() Slog.e(TAG, Failed toload Wi-Fi driver.);setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false;if (!mWifiStateTracker.startSupplicant() mWifiStateTracker.unloadDriver(); Slog.e(TAG, Failed tostart supplicant daemon.);setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false;registerForBroadcasts();mWifiStateTracker.startEventLoop();至此,Wifi使能结束,自动进入扫描阶段。(2) 扫描AP 当驱动加载成功后,如果配置文件的AP_SCAN = 1,扫描会自动开始,WifiMonitor将会从supplicant收到一个消息EVENT_DRIVER_STATE_CHANGED,调用 handleDriverEvent(),然后调用mWifiStateTracker.notifyDriverStarted(),该函数向消息队列 添加EVENT_DRIVER_STATE_CHANGED,handlermessage()函数处理消息时调用scan()函数,并通过 WifiNative将扫描命令发送到wpa_supplicant。Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.javaprivate void handleDriverEvent(Stringstate) if (state = null) return;if (state.equals(STOPPED) mWifiStateTracker.notifyDriverStopped(); else if (state.equals(STARTED) mWifiStateTracker.notifyDriverStarted(); else if (state.equals(HANGED) mWifiStateTracker.notifyDriverHung();Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.javacase EVENT_DRIVER_STATE_CHANGED: switch(msg.arg1) case DRIVER_STARTED: /* *Set the number of allowed radio channels according *to the system setting, since it gets reset by the *driver upon changing to the STARTED state. */ setNumAllowedChannels();synchronized (this) if (mRunState = RUN_STATE_STARTING) mRunState = RUN_STATE_RUNNING;if (!mIsScanOnly) reconnectCommand(); else / In somesituations, supplicant needs to be kickstarted to / start thebackground scanning scan(true); break; 上面是启动Wifi 时,自动进行的AP的扫描,用户当然也可以手动扫描AP,这部分实现在WifiService里面,WifiService通过startScan()接 口函数发送扫描命令到supplicant。Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.javapublic boolean startScan(booleanforceActive) enforceChangePermission();switch (mWifiStateTracker.getSupplicantState() case DISCONNECTED:case INACTIVE:case SCANNING:case DORMANT: break;default:mWifiStateTracker.setScanResultHandling(WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); break;return mWifiStateTracker.scan(forceActive); 然后下面的流程同上面的自动扫描,我们来分析一下手动扫描从哪里开始的。我们应该知道手动扫描是通过菜单键的扫描键来响应的,而响应该动作的应该是 WifiSettings类中Scanner类的handlerMessage()函数,它调用WifiManager的 startScanActive(),这才调用WifiService的startScan()。packages/apps/Settings/src/com/android/settings/wifiwifisettings.javapublic boolean onCreateOptionsMenu(Menu menu) menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan).setIcon(R.drawable.ic_menu_scan_network);menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced).setIcon(android.R.drawable.ic_menu_manage);return super.onCreateOptionsMenu(menu); 当按下菜单键时,WifiSettings就会调用这个函数绘制菜单。如果选择扫描按钮,WifiSettings会调用 onOptionsItemSelected()。packages/apps/Settings/src/com/android/settings/wifiwifisettings.javapublic booleanonOptionsItemSelected(MenuItem item) switch (item.getItemId() case MENU_ID_SCAN: if(mWifiManager.isWifiEnabled() mScanner.resume(); return true;case MENU_ID_ADVANCED: startActivity(new Intent(this,AdvancedSettings.class); return true;return super.onOptionsItemSelected(item);private class Scanner extends Handler private int mRetry = 0;void resume() if (!hasMessages(0) sendEmptyMessage(0);void pause() mRetry = 0; mAccessPoints.setProgress(false);removeMessages(0);Overridepublic void handleMessage(Message message) if (mWifiManager.startScanActive() mRetry = 0; else if (+mRetry = 3) mRetry = 0;Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,Toast.LENGTH_LONG).show(); return;mAccessPoints.setProgress(mRetry != 0);sendEmptyMessageDelayed(0, 6000); 这里的mWifiManager.startScanActive()就会调用WifiService里 的startScan()函数,下面的流程和上面的一样,这里不赘述。当supplicant完成了这个扫描命令后,它会发送一个消息给上 层,提醒他们扫描已经完成,WifiMonitor会接收到这消息,然后再发送给WifiStateTracker。Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.javavoid handleEvent(int event, String remainder) switch (event) caseDISCONNECTED:handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder); break; case CONNECTED:handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder); break; case SCAN_RESULTS: mWifiStateTracker.notifyScanResultsAvailable(); break; case UNKNOWN: break; WifiStateTracker将会广播 SCAN_RESULTS_AVAILABLE_ACTION消息:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.javapublic voidhandleMessage(Message msg) Intent intent;case EVENT_SCAN_RESULTS_AVAILABLE: if(ActivityManagerNative.isSystemReady() mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); sendScanResultsAvailable(); /* * On receiving the first scanresults after connecting to * the supplicant, switch scanmode over to passive. */ setScanMode(false); break; 由于WifiSettings类注册了intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用 handleEvent(),调用流程如下所示。WifiSettings.handleEvent() =WifiSettings.updateAccessPoints() = mWifiManager.getScanResults() = mService.getScanResults()= mWifiStateTracker.scanResults() = WifiNative.scanResultsCommand()将 获取AP列表的命令发送到supplicant,然后supplicant通过Socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本 相同。(3)配置,连接AP当用户选择一个活跃的AP时,WifiSettings响应打开一个对话框来配 置AP,比如加密方法和连接AP的验证模式。配置好AP后,WifiService添加或更新网络连接到特定的AP。packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.javapublic booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) if (preference instanceof AccessPoint) mSelected = (AccessPoint) preference;showDialog(mSelected, false); else if (preference = mAddNetwork) mSelected = null;showDialog(null, true); else if (preference = mNotifyOpenNetworks) Secure.putInt(getContentResolver(),Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,mNotifyOpenNetworks.isChecked() ? 1 : 0); else return super.onPreferenceTreeClick(screen, preference);return true; 配置好以后,当按下“Connect Press”时,WifiSettings通过发送LIST_NETWORK命令到supplicant来检查该网络是否配置。如果没有该网络或没有配置 它,WifiService调用addorUpdateNetwork()函数来添加或更新网络,然后发送命令给supplicant,连接到这个网络。 下面是从响应连接按钮到WifiServi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论