7920|6

854

帖子

0

TA的资源

五彩晶圆(中级)

楼主
 

在S5PV210 Android4.0上移植Marvel8686 WiFi驱动 [复制链接]

        比较惭愧,去年因为忙着项目管理的工作,在调试完S5pv210 DM9000 网卡驱动以及VGA,LCD驱动之后,就停止下来了,现在重新拿起来,把WiFi以及3G/4G等驱动花点时间移植一下,以前partner 移植过USB的一个比较新的WiFi驱动,这个Marvel8686 是非常老的驱动,不过也想尝试一下SDIO接口的,先去百度一下,看人家怎么弄的,虽然他们都是Android4.0 之前的驱动,不过应该大同小异的。


赞赏

1

查看全部赞赏

点赞 关注
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460

回复
举报

854

帖子

0

TA的资源

五彩晶圆(中级)

沙发
 
本帖最后由 Wince.Android 于 2015-3-18 11:00 编辑

1)项目概述

2)Android SDIO WIFI移植

3)Android WIFI 框架分析

4)SDIO WIFI驱动分析

一、SDIO 设备驱动移植
        很不巧内核已经“被”支持了,我就先不费这事了。
二、配置内核以支持Marvel无线WIFI
在这里我编译成模块的方式:


     Device Drivers  --->
            
  • Network device support  --->
                        Wireless LAN  --->  
                                   Marvell 8xxx Libertas WLAN driver support
                                     Marvell Libertas 8385 and 8686 SDIO802.11b/g cards
         
  • Networking support  --->
                        
  •    Wireless  --->  
                                <*>   Improved wireless configuration API   
                               
  •      cfg80211 regulatory debugging   
                               
  •      nl80211 new netlink interface support   
                                {*}   Common routines for IEEE802.11 drivers
  •        配置好后执行:make zImage 然后,make modules以生成我们要的驱动模块。把编译好的drivers/net/wireless/libertas/目下的驱动模块文件libertas.ko和libertas_sdio.ko复制到Android文件系统下的/system/lib/modules/目录下。后面发现根文件系统里面也“被”支持了,很郁闷!
    三、放置好固件
          创建firmware路劲为/system/etc/firmware目录,把helper_sd.bin,sd8686.bin移动至/system/etc/firmware下面,并更改helper_sd.bin为sd8686_helper.bin
    #mkdir /system/etc/firmware
    #mv /helper_sd.bin sd8686.bin /system/etc/firmware/
    #cd /system/etc/firmware
    #mv helper_sd.bin sd8686_helper.bin


    使用如下加载方法:
    insmod /system/lib/modules/libertas.ko
    insmod /system/lib/modules/libertas_sdio.ko

    libertas_sdio: Libertas SDIO driver
    libertas_sdio: Copyright Pierre Ossman
    此时:ifconfig -a
    查看有没有创建wlan0这个设备节点,若没有驱动好网卡,再次热插拔一下就好

    # err = -123
    mmc1: new SDIO card at address 0001
    __func__ = if_sdio_prog_helper
    libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
    init: untracked pid 2074 exited
    libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
    init: untracked pid 2077 exited
    libertas: 00:0b:6c:89:62:4b, fw 9.70.3p23, cap 0x00000303
    ……
    四、手动连接AP
            首先得在Android上移植好无线工具,和FS2410类似(可参考我有关介绍Android上移植无线工具iwconfig、iwlist等)。
    移植好无线工具后便可以测试了:
    ifconfig -a      查看是否有wlan0 网络节点。
    利用无线工具连接:
    ifconfig wlan0 up      
    iwlist wlan0 scanning
    iwconfig wlan0 essid "FS2410"
    ifconfig wlan0 192.168.1.99 netmask 255.255.255.0 up

    这时可以执行:
    ping 192.168.1.1&

    64 bytes from 192.168.1.1: seq=0 ttl=64 time=2.247 ms
    64 bytes from 192.168.1.1: seq=1 ttl=64 time=1.900 ms
    ……
    (可以kill -9 pid 结束进程)

    五、自动连接AP,Android方式
        ……(下一节)

    下一节为正式项目课题:基于Android的SDIO-WIFI移植(2)  

    一、项目概述:

             Android 3G平板电脑功能介绍:该系统为手持移动终端,其底层硬件采用ARM来实现,搭载谷歌的Android操作系统。支持多点触摸屏、通过WIFI实现联网、蓝牙数据传输、摄像头、USB接口、SD卡接口、重力感应系统、实物键盘。在本次项目 主要涉及3G模块、WIFI模块两个部分的开发。
    硬件环境      
         WIFI模块:Marvell8686 SDIO WIFI
         开发板:FS_S5PC100
           Android 2.1
    软件环境
           Linux 2.6.29
    SDIO WIFI部分:

    项目负责人:本人
    项目目标:实现WIFI上网功能、并对WIFI休眠进行改善。
    项目开发流程:
    硬件分析:对Marvell8686 SDIO WIFI模块硬件工作特性了解和分析
    工作原理分析:对Marvel8686 SDIO WIFI工作原理进行分析
    Android WIFI框架分析:对Android WIFI系统框架分析
    进行源码分析、编写、修改及编译
    调试、并完善
    时间安排:
    2011-9-29至2011-10-7:硬件分析、了解驱动框架
    2011-10-8至2011-10-16:Android SDIO WIFI移植及工作原理分析
    2011-10-17至2011-10-23:Android WIFI框架分析
    2011-10-24至2011-10-30:进行源码分析
    2011-10-31至2011-11-5:准备答辩就业

    二、Android SDIO WIFI移植:

    0、Android中WIFI基本架构
    1、WIFI在Android中如何工作
    2、配置内核支持SDIO WIFI-make menuconfig
    3、配置wpa_supplicant的驱动-BoardConfig.mk
    4、使能wpa_supplicant调试信息-common.*
    5、修改wpa_supplicant.conf
    6、配置路径和权限-init.rc
    7、运行wpa_supplicant和dhcpcd-init.rc
    8、设置驱动以模块方式加载-libertas_sdio.ko
    9、提供固件供驱动模块-sd8686.bin sd8686_helper.bin
    10、配置dhcpcd.conf

    WIFI在Android中如何工作

    Android使用一个修改版wpa_supplicant作为daemon来控制WIFI,代码位于   external/wpa_supplicant。wpa_supplicant是通过socket与 hardware/libhardware_legacy/wifi/wifi.c通信。UI通过android.net.wifi package
       (frameworks/base/wifi/java/android/net/wifi/)发送命令给wifi.c。   相应的JNI实现位于frameworks/base/core/jni/android_net_wifi_Wifi.cpp。
       更高一级的网络管理位于frameworks/base/core/java/android/net。
    配置内核支持SDIO WIF

    make menuconfig


    Networking support  --->  
               Wireless  --->  
                     --- Wireless                                                
                    <*>   Improved wireless configuration API                  
                         cfg80211 regulatory debugging                        
                         nl80211 new netlink interface support                                                                              
                     -*-   Common routines for IEEE802.11 drivers   
    Device Drivers  --->   
             Network device support  --->  
                    Wireless LAN  --->   
                   <*>   Marvell 8xxx Libertas WLAN driver support  
                        Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards

    配置wpa_supplicant的驱动

    1)修改vendor/farsight/fs100/BoardConfig.mk:
       把BOARD_WPA_SUPPLICANT_DRIVER :=true
       改为    BOARD_WPA_SUPPLICANT_DRIVER := WEXT
       目的是:把driver_wext.c作为wpa_supplicant的驱动。wpa_supplicant通过它去与内核的wifi驱动打交道。
    2)修改external/wpa_supplicant/Android.mk
        把WPA_BUILD_SUPPLICANT :=false
        改为    WPA_BUILD_SUPPLICANT := true
       默认使用驱动driver_wext.c。
       如果使用定制的wpa_supplicant驱动(例如 madwifi),可以设置:
       BOARD_WPA_SUPPLICANT_DRIVER := MADWIFI

    使能wpa_supplicant调试信息

    wpa_supplicant默认信息显示的等级为SG_INFO,为了输出更多信息,可修改:
    修改external/wpa_supplicant/common.c
        把int wpa_debug_level = MSG_INFO;
        改为:int wpa_debug_level = MSG_DEBUG;
    修改external/wpa_supplicant/common.h
        把宏定义#define wpa_printf(level, ...)中的if ((level) >= MSG_INFO)
        改为if ((level) >= MSG_DEBUG)

    修改wpa_supplicant.conf

    修改wpa_supplicant.conf:
       把external/wpa_supplicant/wpa_supplicant.conf拷贝到out/target/product/fs100/system/etc/wifi/目录下,
       并把:ctrl_interface=DIR=/data/misc/wifi/wpa_supplicant GROUP=wifi
       改为:
       ctrl_interface=wlan0
    配置路径和权限

    A)配置init.rc文件修改out/target/product/fs100/root/init.rc, 让wifi用户拥有相关的权限, 在 #give system access to wpa_supplicant.conf for backup and restore后面增加:
         #add by caoyi 2011-10-19

         mkdir /data/misc/wifi/sockets 0777 wifi wifi

      chown wifi wifi /data/misc/wifi
         chown wifi wifi /data/misc/wifi/wpa_supplicant.conf
      #for dhcp
         mkdir /data/misc/dhcp 0777 dhcp dhcp
         chmod 0770 /data/misc/dhcp
         #end add
    B)注释原有环境变量#export PATH
    改为:
    export PATH /sbin:/system/sbin:/system/bin:/system/xbin
        #above modified by caoyi 2011-10-19
          修改控制台
    注释掉原console
       #modfied by caoyi 2011-10-19
       #service console /system/busybox/bin/ash    改为:service console /system/bin/bash

    运行wpa_supplicant和dhcpcd

    配置init.rc文件修改out/target/product/fs100/root/init.rc, 在末尾添加:
       #add by caoyi 2011-10-19
    for wifi Android private socket
       service wpa_supplicant /system/bin/wpa_supplicant -dd -Dwext -iwlan0 -c        /system/etc/wifi/wpa_supplicant.conf
               socket wpa_wlan0 dgram 660 wifi wifi
               group system wifi inet
               disabled
               oneshot
       #for dhcp
       service dhcpcd /system/bin/dhcpcd wlan0
               group system dhcp
              disabled
              oneshot
       #end add。
    设置驱动以模块方式加载

    拷贝内核生成的drivers/net/wireless/libertas/libertas_sdio驱动模块到out/target/product/fs100/system/lib/modules/目录下。
    然后修改hardware/libhardware_legacy/wifi/wifi.c
        1)修改#define WIFI_DRIVER_MODULE_PATH         "/system/lib/modules/libertas_sdio.ko"
           #define WIFI_DRIVER_MODULE_NAME        "libertas_sdio"  
        #define WIFI_TEST_INTERFACE  "wlan0"
    添加休眠唤醒代码:
    /*add by caoyi 2011-10-19*/
    int module_wakeup_status()
       {
             return 1;
       }
       int wait_time()
      {
         sleep(1);
            return ;
       }
    /*end add*/
    提供固件firmware

    Android不使用标准的hotplug binary,WIFI需要的firmware要复制到/etc/firmware。   或者复制到WIFI驱动指定的位置,然后WIFI驱动会自动加载。
       在此把wifi模块提供的sd8686.bin sd8686_helper.bin放到out/target/product/fs100/system/etc/firmware目录下。

    配置dhcpcd.conf

    修改源码目录下external/dhcpcd下的Android.mk文件
        取消注释
         26  include $(CLEAR_VARS)
         27 LOCAL_MODULE := dhcpcd.conf
         28 LOCAL_MODULE_TAGS := user
         29 LOCAL_MODULE_CLASS := ETC
         30 LOCAL_MODULE_PATH := $(etc_dir)
         31 LOCAL_SRC_FILES := android.conf
         32 include $(BUILD_PREBUILT)   
    然后重新编译mm,将编译产生的dhcpcd.conf放置到文件系统的目录system/etc/dhcpcd/dhcpcd.conf
    最后确定dhcpcd.conf内容有:
         interface wlan0
         option subnet_mask, routers, domain_name_servers   
         option ntp_servers     这几行,否则修改之。
    其它修改

    修改WifiStateTracker.java
    将frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java 里的mInterfaceName = SystemProperties.get("wifi.interface", "eth0");
           改为:
         mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");

    编译镜像文件后烧写到开发板上就可以使用WiFi模块连接外网。

    经验技巧

    移植过程中,我们只是针对文件系统中某几个文件修改,所以没必要重新对整个文件系统编译。而这个时候就可以针对性的编译某个目录,使生成对应的库文件*.so,然后替换之前的库文件。例如:
       我们经常要修改wifi.c。我们可以这样:
    . ./build/envsetup.sh
    tapas
    mmm hardware/libhardware_legacy/
    然后将生成的libhardware_legacy.so拷贝到文件系统fs100_root中lib目录。
    $cp out/target/product/fs100/system/lib/libhardware_legacy.so      fs100_root/system/lib/
    三、Android WIFI 框架分析:

    待续……

    Android WIFI框架分析(1)
     
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     

    回复

    854

    帖子

    0

    TA的资源

    五彩晶圆(中级)

    板凳
     
    本帖最后由 Wince.Android 于 2015-3-18 10:59 编辑

    趁做Android WIFI驱动移植,对Android WIFI框架做了深刻的分析,并做此文档共同学习。

    一、SDIO 设备驱动移植
            很不巧内核已经“被”支持了,我就先不费这事了。
    二、配置内核以支持Marvel无线WIFI
    在这里我编译成模块的方式:


         Device Drivers  --->
                
  • Network device support  --->
                        Wireless LAN  --->  
                                   Marvell 8xxx Libertas WLAN driver support
                                     Marvell Libertas 8385 and 8686 SDIO802.11b/g cards
         
  • Networking support  --->
                        
  •    Wireless  --->  
                                <*>   Improved wireless configuration API   
                               
  •      cfg80211 regulatory debugging   
                               
  •      nl80211 new netlink interface support   
                                {*}   Common routines for IEEE802.11 drivers
  •        配置好后执行:make zImage 然后,make modules以生成我们要的驱动模块。把编译好的drivers/net/wireless/libertas/目下的驱动模块文件libertas.ko和libertas_sdio.ko复制到Android文件系统下的/system/lib/modules/目录下。后面发现根文件系统里面也“被”支持了,很郁闷!
    三、放置好固件
          创建firmware路劲为/system/etc/firmware目录,把helper_sd.bin,sd8686.bin移动至/system/etc/firmware下面,并更改helper_sd.bin为sd8686_helper.bin
    #mkdir /system/etc/firmware
    #mv /helper_sd.bin sd8686.bin /system/etc/firmware/
    #cd /system/etc/firmware
    #mv helper_sd.bin sd8686_helper.bin


    使用如下加载方法:
    insmod /system/lib/modules/libertas.ko
    insmod /system/lib/modules/libertas_sdio.ko

    libertas_sdio: Libertas SDIO driver
    libertas_sdio: Copyright Pierre Ossman
    此时:ifconfig -a
    查看有没有创建wlan0这个设备节点,若没有驱动好网卡,再次热插拔一下就好

    # err = -123
    mmc1: new SDIO card at address 0001
    __func__ = if_sdio_prog_helper
    libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
    init: untracked pid 2074 exited
    libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
    init: untracked pid 2077 exited
    libertas: 00:0b:6c:89:62:4b, fw 9.70.3p23, cap 0x00000303
    ……
    四、手动连接AP
            首先得在Android上移植好无线工具,和FS2410类似(可参考我有关介绍Android上移植无线工具iwconfig、iwlist等)。
    移植好无线工具后便可以测试了:
    ifconfig -a      查看是否有wlan0 网络节点。
    利用无线工具连接:
    ifconfig wlan0 up      
    iwlist wlan0 scanning
    iwconfig wlan0 essid "FS2410"
    ifconfig wlan0 192.168.1.99 netmask 255.255.255.0 up

    这时可以执行:
    ping 192.168.1.1&

    64 bytes from 192.168.1.1: seq=0 ttl=64 time=2.247 ms
    64 bytes from 192.168.1.1: seq=1 ttl=64 time=1.900 ms
    ……
    (可以kill -9 pid 结束进程)

    五、自动连接AP,Android方式
        ……(下一节)

    下一节为正式项目课题:基于Android的SDIO-WIFI移植(2)  

           对上层WIFI的应用,基本流程为:(1)WIFI初始化  (2)Wifi启动      (3)开始扫描AP        (4)显示扫描的AP      (5)配置AP        (6)连接AP     (7)获取IP地址      (8)上网            

    一、Android WIFI模块初始化

    上文Android系统启动分析  讲到在SystemServer中实例化了ConnectivityService,接着的便是WIFI初始化:
    frameworks/base/services/java/com/android/server/ConnectivityService.java
    ConnectivityService 的构造函数会创建WifiService,

    if (DBG) Log.v(TAG, "Starting Wifi Service.");
          WifiStateTracker wst = new WifiStateTracker(context, mHandler);
          WifiService wifiService = new WifiService(context, wst);
          ServiceManager.addService(Context.WIFI_SERVICE, wifiService);

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

    二、WIFI模块启动

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

    Packages\apps\settings\src\com\android\settings\WirelessSettings.java
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.wireless_settings);
            initToggles();
            mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
        }
    private void initToggles() {
        …………
        mWifiEnabler = new WifiEnabler(
                    this, (WifiManager) getSystemService(WIFI_SERVICE),
                    (CheckBoxPreference) wifiPreference);
    …………
    }

            当用户按下Wifi 按钮后,Android 会调用WifiEnabler 的onPreferenceChange,再由WifiEnabler调用WifiManager 的setWifiEnabled 接口函数,通过AIDL,实际调用的是WifiService 的setWifiEnabled 函数,WifiService 接着向自身发送一条MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:
    首先装载WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/libertas_sdio.ko" ),
    然后启动wpa_supplicant ( 配置文件硬编码为"/data/misc/wifi/wpa_supplicant.conf"),再通过WifiStateTracker 来启动WifiMonitor 中的监视线程。
    WifiEnabler.java

    public boolean onPreferenceChange(Preference preference, Object value) {
            // Turn on/off Wi-Fi
           setWifiEnabled((Boolean) value);         
        }
    private void setWifiEnabled(final boolean enable) {
            if (!mWifiManager.setWifiEnabled(enable)) {
            }
        }  

    WifiManager.java
    public boolean setWifiEnabled(boolean enabled) {
                return mService.setWifiEnabled(enabled);
        }
    IWifiManager mService;
    interface IWifiManager{
        …………
        boolean startScan(boolean forceActive);
        boolean setWifiEnabled(boolean enable);
    …………
    }
    IWifiManger.aidl编译后生成了IWifiManger.java,并生成IWifiManger.Stub(服务器端抽象类)和IWifiManger.Stub.Proxy(客户端代理实现类)。WifiService通过继承IWifiManger.Stub实现,而客户端通过getService()函数获取IWifiManger.Stub.Proxy(即Service的代理类),将其作为参数传递给WifiManger,供其与WifiService通信时使用。
    WifiService.java

    public boolean setWifiEnabled(boolean enable) {
    …………
    sendEnableMessage(enable, true, Binder.getCallingUid());
        …………
    }
    private void sendEnableMessage(boolean enable, boolean persist, int uid) {
            Message msg = Message.obtain(mWifiHandler,
                                         (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
                                         (persist ? 1 : 0), uid);
            msg.sendToTarget();
        }
    public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MESSAGE_ENABLE_WIFI:
                       setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);
                    case MESSAGE_START_WIFI:                  
                        mWifiStateTracker.restart();  
                   case MESSAGE_DISABLE_WIFI:                  
                        setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);              
                    case MESSAGE_STOP_WIFI:
                        mWifiStateTracker.disconnectAndStop();
                        break;
                }
            }
        }
    private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {
    if (enable) {
                if (!WifiNative.loadDriver()) {               
                    setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                }
                if (!WifiNative.startSupplicant()) {
                    WifiNative.unloadDriver();              
                    setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                }
                registerForBroadcasts();
                mWifiStateTracker.startEventLoop();
            } else {
      ………………
      }
        // Success!        
           setWifiEnabledState(eventualWifiState, uid);
    }
    private void setWifiEnabledState(int wifiState, int uid) {
    // Broadcast
            final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
    }
    JNI android_net_wifi_wifi.cpp
    // ----------------------------------------------------------------------------

    /*
    * JNI registration.
    */
    static JNINativeMethod gWifiMethods[] = {
        /* name, signature, funcPtr */
        { "loadDriver", "()Z",  (void *)android_net_wifi_loadDriver },   
        { "startSupplicant", "()Z",  (void *)android_net_wifi_startSupplicant },   
        { "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand },      
        { "reconnectCommand", "()Z",  (void *)android_net_wifi_reconnectCommand },   
        { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },
    }
    1)static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz)
    {
        return (jboolean)(::wifi_load_driver() == 0);
    }
    2)static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)
    {
        return (jboolean)(::wifi_start_supplicant() == 0);
    }
    3)WifiStateTracker.java
    mWifiStateTracker.startEventLoop();
    public void startEventLoop() {
            mWifiMonitor.startMonitoring();
        }
    //WifiMonitor.java
    public void startMonitoring() {
            new MonitorThread().start();
        }

    当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI已经成功使能了。//Success!后广播的。

    上文讲到WIFI的启动流程,当然接着便扫描热点(AP),然后显示扫描到的AP、配置AP(填写IP地址等信息)、连接AP、获取IP地址、最后就是想要的上网咯!

    一、扫描热点(AP)

    上文启动WIFI成功后:// Success!        
            setWifiEnabledState(eventualWifiState, uid);
    private void setWifiEnabledState(int wifiState, int uid) {
    // Broadcast
            final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
    }

    当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI已经成功使能了。WifiLayer 创建的时候就会向Android 注册接收WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。

    WifiSetting.java:

    protected void onCreate(Bundle savedInstanceState) {
        mWifiLayer.onCreate();
    }

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

    WifiLayer.java:
    public void onCreate() {
            mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            
            mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
            mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
            mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);        
        }
    public void onResume() {
            mContext.registerReceiver(mReceiver, mIntentFilter);        
            if (isWifiEnabled()) {
                // Kick start the continual scan
                queueContinuousScan();
            }
        }

    以上就是WifiLayer.java注册接收的部分事件。接收部分事件处理有:
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                    handleNetworkStateChanged(
                            (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO),
                            intent.getStringExtra(WifiManager.EXTRA_BSSID));
                } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                    handleScanResultsAvailable();
                } ……

               else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                    handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                            WifiManager.WIFI_STATE_UNKNOWN));
                }           
            }
        };

    从可接受的事件看,当WIFI_STATE_CHANGED_ACTION时,对应的处理函数有:

    handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                            WifiManager.WIFI_STATE_UNKNOWN));

    private void handleWifiStateChanged(int wifiState) {
       attemptScan();
       …………
    }

    public void attemptScan() {
      if (!mWifiManager.startScanActive()) {
                postAttemptScan();
            }
    }

    WifiManager.java:
    public boolean startScanActive() {
    return mService.startScan(true);
    }

    -------AIDL-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    WifiService.java:
    public boolean startScan(boolean forceActive) {
    …………
    return WifiNative.scanCommand(forceActive);
    }

    ---------JNI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    android_net_wifi_wifi.cpp:
    { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },
    static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)
    {
    …………
    result = doBooleanCommand("SCAN", "OK");
    }
    static jboolean doBooleanCommand(const char *cmd, const char *expect)
    {
    if (doCommand(cmd, reply, sizeof(reply)) != 0) {
            return (jboolean)JNI_FALSE;
        }
    }
    static int doCommand(const char *cmd, char *replybuf, int replybuflen)
    {
    if (::wifi_command(cmd, replybuf, &reply_len) != 0)
            return -1;
    …………
    }

    -------HAL------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    wifi.c:
    int wifi_command(const char *command, char *reply, size_t *reply_len)
    {
        return wifi_send_command(ctrl_conn, command, reply, reply_len);
    }
    int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
    {
    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
    …………
    }
    wpa_ctrl.c:
    int wpa_ctrl_request()在wpa_ctrl.c中其实就是执行SCAN命令。

    二、显示扫描的AP

    当扫描成后,WifiMonitor 中的MonitorThread 会被执行来出来这个事件:

      void handleEvent(int event, String remainder) {
                switch (event) {   
                    case SCAN_RESULTS:
                        mWifiStateTracker.notifyScanResultsAvailable();
    ->sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE);
        break;
    }

    WifiStateTracker.java
    public void handleMessage(Message msg) {               
      switch (msg.what) {
                   case EVENT_SCAN_RESULTS_AVAILABLE:
                            if (ActivityManagerNative.isSystemReady()) {
                                    mContext.sendBroadcast(new   Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));      
                         }
    }

    WifiLayer注册接收SCAN_RESULTS_AVAILABLE_ACTION这个Intent:

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
    else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
           {            

                 handleScanResultsAvailable();     

         }
    handleScanResultsAvailable();
           -> list = mWifiManager.getScanResults();
            -> mCallback.onAccessPointSetChanged(ap, true);

    handleScanResultsAvailable()中首先会去拿到SCAN的结果(最终是往wpa_supplicant中发送SCAN_RESULT命令并读取返回值来实现的),对每一个扫描返回的AP,WifiLayer会回调WifiSetting的onAccessPointSetChanged函数,从而最终把该AP加到GUI显示列表中。

    三、配置AP

    当用户在 WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:

    public boolean onPreferenceTreeClick()
              ->showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
                        ->AccessPointDialog dialog   =
                                                new AccessPointDialog(this,    mWifiLayer);
                                         showDialog(dialog);

    当用户在AccessPointDialog中选择好加密方式和输入密钥之后,再点击连接按钮,Android就会去连接这个AP。

    四、连接AP

    在AccessPointDialog.java中点击连接后会执行:

    public void onClick(DialogInterface dialog, int which) {
               handleConnect();
       -> mWifiLayer.connectToNetwork(mState);
        ->  // Need WifiConfiguration for the AP
                                   WifiConfiguration config = findConfiguredNetwork(state);
                                    config = addConfiguration(state, 0);
                                    managerEnableNetwork(state, false)
              ->mWifiManager.enableNetwork()
                                             ->mService.enalbeNetwork()
                         ->WifiNative.enableNetworkCommand()

    接下去就JNI { "enableNetworkCommand", "(IZ)Z", (void*)android_net_wifi_enableNetworkCommand },最终就是向wpa_supplicant发送连接命令
    五、获取IP地址

    当wpa_supplicant成功连接上AP之后,它会向控制通道发送事件通知连接上AP了,从而wifi_wait_for_event函数会接收到该事件,由此WifiMonitor中的MonitorThread会被执行来出来这个事件:

    void handleEvent(int event, String remainder) {
           switch (event) {   
                  case CONNECTED:
                      handleNetworkStateChange();
                      -> mWifiStateTracker.notifyStateChange(newState, BSSID, networkId);
      ->msg.sendToTarget();
                      break;
    }

    WifiStateTracker.java
    public void handleMessage(Message msg) {         
      switch (msg.what) {               
                case EVENT_NETWORK_STATE_CHANGED:
                           sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());      
                         }
    }
    WifiStateTracker中注册的对Wifi相关数据库的观察者if(changed)   则启动:
    private void configureInterface()
       ->  mDhcpTarget.sendEmptyMessage();
    private class DhcpHandler extends Handler
              handleMessage()
                  ->switch (msg.what) {
                          case EVENT_DHCP_START:
                                  Target.sendEmptyMessage(event);

    DhcpHandler会发送EVENT_DHCP_START消息启动DHCP去获取IP地址,当DHCP拿到IP地址之后,会发送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED的消息,然后WifiStateTacker中的handleMessage会处理这样的消息

    case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
         sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());
                ->  Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                -> mContext.sendStickyBroadcast(intent);

    这次带上完整的IP地址信息。WifiLayer中注册了此Intent的接受者,会调用handleNetworkStateChanged进行处理。最后就可以自由的上网了

    转载自http://blog.csdn.net/yicao821/article/details/6895044


     
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     
     

    回复

    854

    帖子

    0

    TA的资源

    五彩晶圆(中级)

    4
     
    这篇文章也写的挺详细的。

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

    http://blog.csdn.net/liyulei316686082/article/details/7006577

    android之wifi移植全过程



                             硬件环境     
                                   WIFI模块:Marvell8686 SDIO WIFI
                                  开发板:S5PC100     
                            软件环境
                                   Linux 2.6.29  Android 2.1

    项目目标:实现WIFI上网功能、并对WIFI休眠进行改善。

    项目开发流程:

    硬件分析:对Marvell8686 SDIO WIFI模块硬件工作特性了解和分析

    工作原理分析:对Marvel8686 SDIO WIFI工作原理进行分析

    Android WIFI框架分析:对Android WIFI系统框架分析

    进行源码分析、编写、修改及编译

    调试、并完善











    一、1.编译内核,生成驱动模块
         在内核的根目录下执行make
         生成libertas.ko 和libertas_sdio.ko
         
  • Networking support  --->  
             
  •    Wireless  --->  
                     --- Wireless                                                
                    <*>   Improved wireless configuration API                  
                     
  •      cfg80211 regulatory debugging                        
                     
  •      nl80211 new netlink interface support                                                                              
                     -*-   Common routines for IEEE802.11 drivers   
             Device Drivers  --->   
             
  • Network device support  --->  
                    Wireless LAN  --->   
                   <*>   Marvell 8xxx Libertas WLAN driver support              (注:编译进内核,若模块则是:libertas.ko)      
                        Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards  (注:编译成libertas_sdio.ko)
         
         2.编译内核,确保支持sd卡
            Device Drivers  ---
               <*> MMC/SD/SDIO card support  --->
                 --- MMC/SD/SDIO card support                                    
                
  •    MMC debugging                                             
                 [ ]   Allow unsafe resume (DANGEROUS)                           
                
  •    MMC embedded SDIO device support (EXPERIMENTAL)            
                 [ ]   Enable paranoid SD card initialization (EXPERIMENTAL)      
                       *** MMC/SD/SDIO Card Drivers ***                           
                 <*>   MMC block device driver                                    
                
  •      Use bounce buffer for simple hosts                       
                 [ ]     Deferr MMC layer resume until I/O is requested           
                 < >   SDIO UART/GPS class support                              
                 < >   MMC host test driver                                       
                       *** MMC/SD/SDIO Host Controller Drivers ***               
                 <*>   Secure Digital Host  
           3.make zImage
             make modules
            (libertas_sdio.ko在drivers/net/wireless/libertas目录下)
    二、制作测试工具(使用静态编译)
        现在,sd卡支持了,驱动以内核自带的以模块的方式编译得到。
        接下来先编译几个测试工具。
        测试无线网卡用无线工具iwconfig iwlist等命令是通过开源软件wireless_tools_29.rar编译得到。         
        步骤:
        1.解压。由于这的是win32的压缩包,先在windows底下解压,再拷贝到Ubuntu下。
        2.修改Makefile:
               8   PREFIX = ./tools  //指定安装路径                  
               12  CC = arm-linux-gnu-gcc (和编译你的文件系统所用保持一致,需要注意的是,如果在执行sudo make 就要该编译链的绝对路径)                                                                                                      
               14  AR = arm-linux-gnu-ar   
               
               #BUILD_STATIC = y          -->    BUILD_STATIC = y                                       
               #BUILD_STRIPPING = y       -->    BUILD_STRIPPING = y   
               

               CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \         
                     -Wpointer-arith -Wcast-qual -Winline -I.
               在这后面添加新行:                              
               CFLAGS += -static
               
        3.make
        4.make install
          由于我是在当前目录下(PREFIX = ./tools) 产生的这个tools文件夹,
          查看有:
          lib sbin usr
          lib目录,libiw.a静态库 ;而sbin目录为一些网络工具,如:iwlist、iwconfig等
          到里面的sbin目录底下,
          $file iwlist  输出信息:iwlist: ELF 32-bit LSB executable, ARM, version 1, statically linked, for GNU/Linux 2.4.3, strippe
          确保是静态的。
          
          然后将这些命令复制到android文件系统的/system/busybox/bin(就是out/target/prodruct/fs100/system/busybox/bin)
          或者system/bin(就是out/target/prodruct/fs100/system/bin)目录下就可以使用这些命令了。  

    三、将固件放到指定目录下。
         1.mkdir /system/etc/firmware(就是out/target/prodruct/fs100/system/etc/firmware)
         2.cp sd8686.bin sd8686_helper.bin  out/target/prodruct/fs100/system/etc/firmware

    四、测试,sdio卡是否可用。
         如果已经编译好了文件系统,就可以跳过第一步。
         1.编译android系统。
                   1)在文件系统根目录下执行:
                   liyulei@liyulei:~/anrdoid/fs/android_system$ . ./build/envsetup.sh
                 注意这里两个’.’  之间有一个空格,第一个’.’指定用当前 shell 解析这个脚本,否则不能执行。
                2)配置板级信息:
                liyulei@liyulei:~/anrdoid/fs/android_system$ tapas
                就是上一步执行结束之后导出到环境变量里的命令,专门用来配置板级信息的。
                 Build for the simulator or the device?
                        1. Device
                       2. Simulator
                Which would you like? [1] 1
                Build type choices are:
                       1. release
                       2. debug
                Which would you like? [1] 1
                Which product would you like? [fs100] fs100
                Variant choices are:
                       1. user
                       2. userdebug
                       3. eng
                Which would you like? [eng] eng
                
                确保输出的配置信息为:
                PLATFORM_VERSION_CODENAME=REL
                PLATFORM_VERSION=2.1-update1  
                TARGET_PRODUCT=fs_s5pc100     
                TARGET_BUILD_VARIANT=eng      
                TARGET_SIMULATOR=false        
                TARGET_BUILD_TYPE=release     
                TARGET_ARCH=arm               
                HOST_ARCH=x86                 
                HOST_OS=linux                 
                HOST_BUILD_TYPE=release      
                BUILD_ID= ERE27               
                
                3)开始编译(如果不能找到 mm,执行”source build/envsetup.sh”):
                liyulei@liyulei:~/anrdoid/fs/android_system$ mm
       
       2.重新生成文件系统镜像。
         liyulei@liyulei:~/anrdoid/fs/android_system$ ./make_fs100_yaffs2_image.sh
         就会在 Android 源码根目录下生成目录“fs100_root”,这个目录就是编译生成的 Android 文件系统,  
         调试时可以直接把这个目录作为 NFS-Server 的目录。还会生成一个“fs100_root.img”文件,这个文件就
         是 Android的 yaffs2 格式的镜像,可以烧写到 Nand Flash 上。
           这里我是烧写上fs100_root.img.
         
         3.手动加载驱动。
           由于sdio8686。需要加载两个.ko(libertas.ko、libertas_sdio.ko) 文件。
           上面linertas.ko的模块,我已经编进内核。
           所以我只需执行:
           1)/# insmod libertas_sdio.ko   
           输出信息:
           libertas_sdio: Libertas SDIO driver                                 
         libertas_sdio: Copyright Pierre Ossman                              
         __func__ = if_sdio_prog_helper                                      
         libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin   
         init: untracked pid 2137 exited                                    
         libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin         
         init: untracked pid 2140 exited                                    
         libertas: 00:0b:6c:91:a3:f6, fw 9.70.3p24, cap 0x00000303           
         libertas: unidentified region code; using the default (USA)         
         wlan0 (libertas_sdio): not using net_device_ops yet                 
         libertas: PREP_CMD: command 0x00a3 failed: 2                        
         libertas: PREP_CMD: command 0x00a3 failed: 2                        
         libertas: wlan0: Marvell WLAN 802.11 adapter                        
        2)/# ifconfig -a  
           (要是提示:-a: No such device,则输入命令:system/busybox/sbin/ifconfig -a)   
        查看是否检测到无线网卡                           
               有如下信息说明检测到无线网卡                                    
                 wlan0     Link encap:Ethernet  HWaddr 00:0B:6C:91:A3:F6      
                           BROADCAST MULTICAST  MTU:1500  Metric:1            
                           RX packets:0 errors:0 dropped:0 overruns:0 frame:0  
                           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
                           collisions:0 txqueuelen:1000                        
                           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)              
        3)测试:  
             /#ifconfig wlan0 up                                                                                                         
            /#iwlist wlan0 scanning                                                                                                         
            /#iwconfig wlan0 essid "fs100"                                                                                                  
            /#ifconfig wlan0 192.168.1.99 netmask 255.255.255.0 up (静态分配ip,
             也可以动态分配,用DHCP)
             /#route add default gw 192.168.1.1(无线路由)
             /#ping 192.168.1.1            
        4)能够ping通后,说明sdio8686 wifi网卡没有问题
       
    五、测试wpa_supplicant。
      因为现在的无线wifi网络大多是wpa加密。 所以需要用到wpa_supplicant。
        android系统中也自带有wpa_supplicant。
        wifi的大致架构是这样的,app-->java framework-->|jni|-->c++ framework -->wifi.c -->wpa_supplicant-->sdio8686.
        所以我们要先测试低层先通了,因此,就得先测试确保wpa_supplicant和sdio8686通了的。
        我们编译android系统时,就已经把自带的wpa_supplicant和wpa_cli编译好并放到system/bin目录下了.
        1.配置wpa_supplicant。
        在liyulei@liyulei:~/anrdoid/fs/android_system/external/wpa_supplicant/在目录下有个wpa_supplicant.conf。
        将wpa_supplicant.conf放到out/target/product/fs100/system/etc 目录下。如果是烧到板子上的话,需要重烧板子。
        要是以网络挂载的方式,则放到相应的目录。
        #vim /rootfs/filesystem/etc/wpa_supplicant.conf           
                                                                  
        修改内容如下:                                            
                                                                  
        # WPA-PSK/TKIP                                            
                                                                  
         ctrl_interface=/var/run/wpa_supplicant                    
                                                                  
         network={                                                
                         ssid="fs100"     //填写无线网络的的用户名
                          key_mgmt=WPA-PSK                          
                          proto=WPA                                 
                         pairwise=TKIP                             
                         group=TKIP                                
                         psk="1234567890" //填写密码               
         }                                                         
       
        2.#mkdir –p /var/run/wpa_supplicant
        3.确认是否加载驱动。
         用ifconfig -a查看是否已经创建wlan0这个节点。
          没有就把驱动加载进内核。
        4.创建连接暗文密码(PSK密码),通过明码转换                                                                    
          #cd /etc (该目录下要有wpa_supplicant.conf)                                                                                                  
          #wpa_passphrase fs100 1234567890 >> wpa_supplicant.conf                                                   
          此时将在wpa_supplicant.conf文件中生成:                                                                    
          network={                                                                                                  
                ssid="fs100"                                                                                       
                #psk="1234567890" //此物为路由器中设定的人类能读得懂的密码,供我们使用                              
                psk=d290464a66df8541cee4f100627446177ee7ce5d9eb36981e4dff412730b2d5a //这个又1234567890转换后的psk密码
          }                                                                                                         
           -----------------------------------------------------------------------------------------------------<----
           ---->遇到问题:在测试过程中要用到wpa_passphrase这个命令程序。但是android并没提供wpa_passphrase       <----
           ---->这命令,我只通过wpa_supplicant-0.7.3这个源码包编译出这个命令。但是这个命令在开发板上执行        <----
           ---->不了(编译链不对)。我又找到android源码中有wpa_passphrase.c,而编译出来的路径下通过find         <----
           ---->命令去找这个wpa_passphrase又找不到。                                                            <----
           ---->解决办法:同过分析wpa_passphrase.c才发现,里面就短短的一个mian函数。有个提示                    <----
           ---->usage: wpa_passphrase [passphrase]\n""\nIf passphrase is left out, it will be read from "<----
         ---->"stdin\n                                                                                        <----
           ---->现在不用我说都知道了吧!所以这个在哪运行都可以,这命令就是为了通过ssid和passphrase得到暗文。    <----
           ---->所以我在Ubuntu底下直接执行:wpa_passphrase fs100 1234567890                                     <----
           ---->同样输出信息:network={                                                                         <----                             
           ---->                          ssid="fs100"                                                          <----                             
           ---->                          #psk="1234567890"                                                     <----
           ---->                          psk=d290464a66df8541cee4f100627446177ee7ce5d9eb36981e4dff412730b2d5a  <----
           ---->                    }                                                                           <----                             
           -----------------------------------------------------------------------------------------------------<-----
         5.然后修改wpa_supplicant.conf配置文件,把 psk="1234567890" 这一行明文密码改成生成的暗文密码,即:
                   psk=d290464a66df8541cee4f100627446177ee7ce5d9eb36981e4dff412730b2d5a                  
                                                                                                         
           其它生成的多余信息删除,最后wpa_supplicant.conf文件如下:                                    
           # WPA-PSK/TKIP                                                                                
                                                                                                 
           ctrl_interface=/var/run/wpa_supplicant                                                        
                                                                                                 
           network={                                                                                    
                      ssid="FS2410"     //填写无线网络的的用户名                                         
                      key_mgmt=WPA-PSK                                                                  
                      proto=WPA                                                                          
                      pairwise=TKIP                                                                     
                      group=TKIP                                                                        
                     psk=d290464a66df8541cee4f100627446177ee7ce5d9eb36981e4dff412730b2d5a               
           }
          
         6.链接AP:
                 在开发板终端输入wpa_supplicant回车,会显示帮助信息,最后有个:                        
                 example:                                                                             
                       wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf                       
                 拷贝example用法,执行:                                                              
                 # wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf &(需要一直放在后台运行)   
                 打印信息有:                                                                        
                 Trying to associate with 00:26:f2:0d:5a:c4 (SSID='fs100' freq=2412 MHz)            
                 Associated with 00:23:68:28:4e:a8                                                   
                 CTRL-EVENT-DISCONNECTED bssid=00:23:68:28:4e:a8 reason=0                             
                 Associated with 00:26:f2:0d:5a:c4                                                   
                 WPA: Key negotiation completed with 00:26:f2:0d:5a:c4 [PTK=TKIP GTK=TKIP]            
                 CTRL-EVENT-CONNECTED - Connection to 00:26:f2:0d:5a:c4 completed (auth) [id=0 id_str=]
                                                                                              
                 分配IP地址:                                                                        
                 #ifconfig wlan0 192.168.1.5  //也可以动态分配 dhclient wlan0                        
                 再ping下网关,是否连接成功:                                                         
                 #ping 192.168.1.1                                                                    
                                                                                                
                 3 packets transmitted, 3 packets received, 0% packet loss                           
                 round-trip min/avg/max = 17.627/20.023/24.631 ms                                    
                 ……                                                                                 
                                                                                                
                 无线网卡连接成功!                           


  •  
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     
     

    回复

    854

    帖子

    0

    TA的资源

    五彩晶圆(中级)

    5
     
    http://blog.csdn.net/yicao821/article/details/6872247

    这篇文章是众多参考文章中比较好的文章,希望后面的人多看看。
     
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     
     

    回复

    854

    帖子

    0

    TA的资源

    五彩晶圆(中级)

    6
     

    default m

    本帖最后由 Wince.Android 于 2015-4-3 15:50 编辑

    在sate210_config上增加如下配置
    # for SDIO marvel 8686 @20150403
    CONFIG_LIBERTAS=y
    CONFIG_LIBERTAS_USB=y
    CONFIG_LIBERTAS_SDIO=y
    CONFIG_LIBERTAS_SPI=y
    CONFIG_LIBERTAS_DEBUG=y
    CONFIG_LIBERTAS_MESH=y

    并在libertas驱动下的Kconfig文件,在上述项目中增加default m if LIBERTAS就可以在make menuconfig  通过选择成M编译成模块了
    config LIBERTAS
            tristate "Marvell 8xxx Libertas WLAN driver support"
            depends on CFG80211
            select WIRELESS_EXT
            select WEXT_SPY
            select LIB80211
            select FW_LOADER
            ---help---
              A library for Marvell Libertas 8xxx devices.

    config LIBERTAS_USB
            tristate "Marvell Libertas 8388 USB 802.11b/g cards"
            depends on LIBERTAS && USB
            default m if LIBERTAS
            ---help---
              A driver for Marvell Libertas 8388 USB devices.

    config LIBERTAS_CS
            tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
            depends on LIBERTAS && PCMCIA
            default m if LIBERTAS
            ---help---
              A driver for Marvell Libertas 8385 CompactFlash devices.

    config LIBERTAS_SDIO
            tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
            depends on LIBERTAS && MMC
            default m if LIBERTAS
            ---help---
              A driver for Marvell Libertas 8385/8686/8688 SDIO devices.

    config LIBERTAS_SPI
            tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
            depends on LIBERTAS && SPI
            default m if LIBERTAS
            ---help---
              A driver for Marvell Libertas 8686 SPI devices.

    config LIBERTAS_DEBUG
            bool "Enable full debugging output in the Libertas module."
            depends on LIBERTAS
            default m if LIBERTAS
            ---help---
              Debugging support.

    config LIBERTAS_MESH
            bool "Enable mesh support"
            depends on LIBERTAS
            default m if LIBERTAS
            help
              This enables Libertas' MESH support, used by e.g. the OLPC people.




    悲剧,这么编译出来的内核启动不了......


    ### 2 do_movi( ) @sate210VIP-uboot @sate210VIP-uboot!

    reading kernel.. 1073, 8192

    MMC read: dev # 0, block # 1073, count 8192 ...8192 blocks read: OK

    completed

    ### 2 do_movi( ) @sate210VIP-uboot @sate210VIP-uboot!

    reading RFS.. 169009, 3072

    MMC read: dev # 0, block # 169009, count 3072 ...3072 blocks read: OK

    completed

    Boot with zImage

    get_format

    -------- 1 --------

    ## Loading init Ramdisk from Legacy Image at 21a00000 ...

       Image Name:   ramdisk

       Created:      2014-02-27   3:03:27 UTC

       Image Type:   ARM Linux RAMDisk Image (uncompressed)

       Data Size:    163847 Bytes = 160 kB

       Load Address: 30a00000

       Entry Point:  30a00000

       Verifying Checksum ... OK



    Starting kernel ...


    就这Starting kernel ...这里挂了。



     
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     
     

    回复

    854

    帖子

    0

    TA的资源

    五彩晶圆(中级)

    7
     
        android之wifi移植全过程(一)之后的android之wifi移植全过程(二)非常不错,照着做应该很快就能搞定了!


    六、android的wifi移植。
         现在底层的都通了,接下来就把wifi移植到android系统中。
         1.提供固件firmware给驱动。
            WIFI需要的firmware要复制到/etc/firmware。   或者复制到WIFI驱动指定的位置,然后WIFI驱动会自动加载。
            在此把wifi模块提供的sd8686.bin sd8686_helper.bin放到out/target/product/fs100/system/etc/firmware目录下。
            其实,和上面放目录是一样的。

         2.修改自己定制的BoardConfig.mk,使能wpa_supplicant。
           修改vendor/farsight/fs100/BoardConfig.mk:                                                      
              把BOARD_WPA_SUPPLICANT_DRIVER :=true                                                         
              改为BOARD_WPA_SUPPLICANT_DRIVER := WEXT                                                                                                                                                
              目的是:把driver_wext.c作为wpa_supplicant的driver。wpa_supplicant通过它去与内核的wifi驱动打交道。
           修改external/wpa_supplicant/Android.mk                                                           
               把WPA_BUILD_SUPPLICANT :=false                                                               
               改为WPA_BUILD_SUPPLICANT := true                                                         
              默认使用驱动driver_wext.c。                                                                  
              如果使用定制的wpa_supplicant驱动(例如 madwifi),可以设置:                                    
              BOARD_WPA_SUPPLICANT_DRIVER := MADWIFI


          3.使wpa_supplicant打印更多的调试信息
        wpa_supplicant默认信息显示的等级为SG_INFO,为了输出更多信息,可修改:  
            修改external/wpa_supplicant/common.c                                   
                把int wpa_debug_level = MSG_INFO;                                 
                改为:int wpa_debug_level = MSG_DEBUG;                             
            修改external/wpa_supplicant/common.h                                   
                把宏定义#define wpa_printf(level, ...)中的if ((level) >= MSG_INFO)
                改为if ((level) >= MSG_DEBUG)
          4.提供一个合适的wpa_supplicant.conf
            修改wpa_supplicant.conf:                                                                                                                 
               把external/wpa_supplicant/wpa_supplicant.conf拷贝到out/target/product/fs100/system/etc/wifi/目录下,
               并把:ctrl_interface=DIR=/data/misc/wifi/wpa_supplicant GROUP=wifi                                 
               改为:                                                                                             
               ctrl_interface=wlan0                                                                              
          5.修改init.rc配置路径和权限
            A)配置init.rc文件修改out/target/product/fs100/root/init.rc, 让wifi用户拥有相关的权限,
              在 #give system access to wpa_supplicant.conf for backup and restore后面增加:
                 #add by liyulei 2011-11-19                                                                                                                       
                 mkdir /data/misc/wifi/sockets 0777 wifi wifi                                                                                                           
            chown wifi wifi /data/misc/wifi                                                                                                                  
                 chown wifi wifi /data/misc/wifi/wpa_supplicant.conf                                                                                                           
                 #for dhcp                                                                                                                                      
                 mkdir /data/misc/dhcp 0777 dhcp dhcp                                                                                                   
                 chmod 0770 /data/misc/dhcp                                                                                                            
                 #end add                                                                                                                                                      
            B)注释原有环境变量#export PATH
              改为:                                                                                                                             
             export PATH /sbin:/system/sbin:/system/bin:/system/xbin                                                                                       
              #above modified by liyulei 2011-11-19                                                                                                                           
          6. 确保wpa_supplicant和dhcpcd是通过init.c起来的。
             配置init.rc文件修改out/target/product/fs100/root/init.rc, 在末尾添加:                                       
                 #add by liyulei 2011-11-19
                 for wifi Android private socket                                             
                 service wpa_supplicant /system/bin/wpa_supplicant -dd -Dwext -iwlan0 -c/system/etc/wifi/wpa_supplicant.conf
                         socket wpa_wlan0 dgram 660 wifi wifi                              
                         group system wifi inet                                                   
                         disabled                                                              
                         oneshot                                                               
                 #for dhcp                                                                          
                 service dhcpcd /system/bin/dhcpcd wlan0                                          
                         group system dhcp                                                           
                         disabled                                                                           
                         oneshot                                                                       
                 #end add。                                                                                                
       7.设置驱动以模块方式加载
       拷贝内核生成的drivers/net/wireless/libertas/libertas_sdio驱动模块
       到out/target/product/fs100/system/lib/modules/目录下。
       然后修改hardware/libhardware_legacy/wifi/wifi.c                                                                       
              1)修改wifi.c中的宏:
                 #define WIFI_DRIVER_MODULE_PATH            "/system/lib/modules/libertas_sdio.ko"                                                            
                 #define WIFI_DRIVER_MODULE_NAME            "libertas_sdio"                                                                                       
                 #define WIFI_TEST_INTERFACE              "wlan0"  
              或者,也可以这样改:
                修改vendor/farsight/fs100/BoardConfig.mk:
                  WIFI_DRIVER_MODULE_PATH  ="/system/lib/modules/libertas_sdio.ko"                                                            
                  WIFI_DRIVER_MODULE_NAME  ="libertas_sdio"                                                                                       
                  WIFI_TEST_INTERFACE     ="wlan0"  
                和上面一样的效果。

          8.添加休眠唤醒代码:
          1)在frameworks\base\core\Jni\android_net_wifi_Wifi.cpp中添加相应的休眠唤醒函数:
          在static JNINativeMethod gWifiMethods[]结构体添加方法:
          {"moduleWakeupStatus","()Z",(void*)android_net_wifi_moduleWakeupStatus},
          {"WaitTime","(I)Z",(void*)android_net_wifi_WaitTime},
          并实现这些方法/*add by liyulei 2011-11-20*/                                                      
              static jboolean android_net_wifi_moduleWakeupStatus(JNIEnv* env, jobject clazz)  
            {                                                                                 
             return (jboolean)(::wifi_module_wakeup_status() == 0);                           
            }                                                                                 
            static jboolean android_net_wifi_WaitTime(JNIEnv* env, jobject clazz, jint waittime)
            {                                                                                 
             return (jboolean)(::wifi_module_wait_time(waittime) == 0);                       
            }                                                                                 
            /*end add by liyulei*/  

            2)而相应的细体实现在wifi.c中:
             在wifi.c添加:                                                            
               /*add by caoyi 2011-10-20*/               
               int wifi_module_wakeup_status()           
                  {                                      
                        return 1;                        
                  }                                      
                  int wifi_module_wait_time(int watiTime)     
                 {                                            
                    sleep(watiTime);                        
                       return  0;                                                                                                                                                   
                  }                                      
               /*end add*/                              

          9.配置dhcpcd.conf
            修改源码目录下external/dhcpcd下的Android.mk文件
        取消注释
           -->26  include $(CLEAR_VARS)
           -->27 LOCAL_MODULE := dhcpcd.conf
           -->28 LOCAL_MODULE_TAGS := user
           -->29 LOCAL_MODULE_CLASS := ETC
           -->30 LOCAL_MODULE_PATH := $(etc_dir)
           -->31 LOCAL_SRC_FILES := android.conf
           -->32 include $(BUILD_PREBUILT)   
           然后重新编译mm,将编译产生的dhcpcd.conf放置到文件系统的目录system/etc/dhcpcd/dhcpcd.conf
            最后确定dhcpcd.conf内容有:
           interface wlan0
           option subnet_mask, routers, domain_name_servers
           option ntp_servers  
           没有的话,就修改。

          10.修改WifiStateTracker.java
           将frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java 里的mInterfaceName = SystemProperties.get("wifi.interface", "eth0");
           改为:
           mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
           最后重新编译mm
           编译镜像文件后烧写到开发板上就可以使用WiFi模块连接网络。

     
    个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
     
     

    回复
    您需要登录后才可以回帖 登录 | 注册

    随便看看
    查找数据手册?

    EEWorld Datasheet 技术支持

    相关文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

     
    EEWorld订阅号

     
    EEWorld服务号

     
    汽车开发圈

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表