底层wifi驱动开发_底层开发和驱动开发 - CSDN
  • Android Wifi驱动--底层

    2013-03-14 18:16:35
    Android Wifi驱动--底层 从framework到wpa_supplicant的适配层(wifi.c)网上介绍的帖子很多,而且本身也并不复杂,其中framework部分需要注意的是wifiService和wifiMoniter两部分,这两快一个是转发AP的CMD...
    Android Wifi驱动--底层

    从framework到wpa_supplicant的适配层(wifi.c)网上介绍的帖子很多,而且本身也并不复杂,其中framework部分需要注意的是wifiService和wifiMoniter两部分,这两快一个是转发AP的CMD另一个是接收来自wpa_supplicant的CMD。他们与本地库的连接都是通过JNI方法,具体实现方法在android_net_wifi_Wifi.cpp中。在这个文件中可以大致看出AP会给wpa_supplicant下哪些命令。这些命令通过wifi.c的wifi_command发送给wpa_supplicant,在发送命令的过程中实际是调用wpa_ctrl_request来完成命令发送的,wpa_ctrl_request是通过socket的方式与wpa_supplicant进行通信的,然后通过wpa_ctrl_recv来接收来自wpa_supplicant的命令,并返回标识给wifi_wait_for_event。

          但是命令发到wpa_supplicant后的流程网上提到的资料就非常少了,不过由于wpa_supplicant是一个标准的开源项目,已经被移植到很多平台上,它中间的过程我暂时还没有去细看。比较关心的是wpa_supplicant在接收到上层的命令后是怎么将命令发给DRIVER的,DRIVER在接收到命令后的解析的动作以及之后调用驱动功能函数的流程以及驱动对寄存器控制的细节。由于需要注意代码保密,之后不会提及具体使用了哪块WIFI芯片也不会提及此WIFI DRIVER是在什么平台什么产品。

           先贴一张wpa_supplicant的标准结构框图:


    Android Wifi驱动--底层 - 凯歌 - Software

     

            重点关注框图的下半部分,即wpa_supplicant是如何与DRIVER进行联系的。整个过程暂以AP发出SCAN命令为主线。由于现在大部分WIFI DRIVER都支持wext,所以就假设我们的设备走的是wext这条线,其实用ndis也一样,流程感觉差不多。

           首先要说的是,在Driver.h文件中有个结构体wpa_driver_ops:

    /**
     * struct wpa_driver_ops - Driver interface API definition
     *
     * This structure defines the API that each driver interface needs to implement
     * for core wpa_supplicant code. All driver specific functionality is captured
     * in this wrapper.
     */
    struct wpa_driver_ops 

             这个结构体在Driver.c中被声明为

    #ifdef CONFIG_DRIVER_WEXT
    extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */

           然后在driver_wext.c填写了结构体的成员,

    const struct wpa_driver_ops wpa_driver_wext_ops = {
        .name = "wext",
        .desc = "Linux wireless extensions (generic)",
        .get_bssid = wpa_driver_wext_get_bssid,
        .get_ssid = wpa_driver_wext_get_ssid,
        .set_wpa = wpa_driver_wext_set_wpa,
        .set_key = wpa_driver_wext_set_key,
        .set_countermeasures = wpa_driver_wext_set_countermeasures,
        .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
        .scan = wpa_driver_wext_scan,
        .combo_scan = wpa_driver_wext_combo_scan,
        .get_scan_results2 = wpa_driver_wext_get_scan_results,
        .deauthenticate = wpa_driver_wext_deauthenticate,
        .disassociate = wpa_driver_wext_disassociate,
        .set_mode = wpa_driver_wext_set_mode,
        .associate = wpa_driver_wext_associate,
        .set_auth_alg = wpa_driver_wext_set_auth_alg,
        .init = wpa_driver_wext_init,
        .deinit = wpa_driver_wext_deinit,
        .add_pmkid = wpa_driver_wext_add_pmkid,
        .remove_pmkid = wpa_driver_wext_remove_pmkid,
        .flush_pmkid = wpa_driver_wext_flush_pmkid,
        .get_capa = wpa_driver_wext_get_capa,
        .set_operstate = wpa_driver_wext_set_operstate,
    #ifdef ANDROID
        .driver_cmd = wpa_driver_priv_driver_cmd,
    #endif
    };

    这些成员其实都是驱动和wpa_supplicant的接口,以SCAN为例:

    int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)

    中的LINE1174:if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0)从这里可以看出wpa_cupplicant是通过IOCTL来调用SOCKET与DRIVER进行通信的,并给DRIVER下达SIOCSIWSCAN这个命令。

           这样,一个命令从AP到FRAMEWORK到C++本地库再到wpa_supplicant适配层,再由wpa_supplicant下CMD给DRIVER的路线就打通了,写起来虽然不多但也是一点小成果。

     

    由于在这个项目中,WIFI模块是采用SDIO总线来控制的,所以先记录下CLIENT DRIVER的SDIO部分的结构,这部分的SDIO分为三层:SdioDrv、SdioAdapter、SdioBusDrv。其中SdioBusDrv是Client Driver中SDIO与WIFI模块的接口,SdioAdapter是SdioDrv和SdioBusDrv之间的适配层,SdioDrv是Client Driver中SDIO与LINUX KERNEL中的MMC SDIO的接口。这三部分只需要关注一下SdioDrv就可以了,另外两层都只是对它的封装罢了。 


    在SdioDrv中提供了这几个功能:

     (1)static struct sdio_driver tiwlan_sdio_drv = {
        .probe          = tiwlan_sdio_probe,
        .remove         = tiwlan_sdio_remove,
        .name           = "sdio_tiwlan",
        .id_table       = tiwl12xx_devices,
    };


     (2)int sdioDrv_EnableFunction(unsigned int uFunc)  


     (3)int sdioDrv_EnableInterrupt(unsigned int uFunc)

     (4)SDIO的读写,实际是调用了MMC\Core中的  static int mmc_io_rw_direct_host()功能。

    SDIO功能部分简单了解下就可以,一般HOST部分芯片厂商都会做好。我的主要任务还是WIFI模块。

           首先从WIFI模块的入口函数wlanDrvIf_ModuleInit()看起,这里调用了wlanDrvIf_Create()。

    代码主体部分:

    static int wlanDrvIf_Create (void)
    {
        TWlanDrvIfObj *drv; //这个结构体为代表设备,包含LINUX网络设备结构体net_device

        pDrvStaticHandle = drv;  /* save for module destroy */

        drv->pWorkQueue = create_singlethread_workqueue (TIWLAN_DRV_NAME);//创建了工作队列

        /* Setup driver network interface. */
        rc = wlanDrvIf_SetupNetif (drv);  //这个函数超级重要,后面详细的看

        drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE );


        // 创建了接受wpa_supplicant的SOCKET接口


        /* Create all driver modules and link their handles */
        rc = drvMain_Create (drv,
                        &drv->tCommon.hDrvMain, 
                        &drv->tCommon.hCmdHndlr, 
                        &drv->tCommon.hContext, 
                        &drv->tCommon.hTxDataQ,
                        &drv->tCommon.hTxMgmtQ,
                        &drv->tCommon.hTxCtrl,
                        &drv->tCommon.hTWD,
                        &drv->tCommon.hEvHandler,
                        &drv->tCommon.hCmdDispatch,
                        &drv->tCommon.hReport,
                        &drv->tCommon.hPwrState);
       
        /* 
         *  Initialize interrupts (or polling mode for debug):
         */

        /* Normal mode: Interrupts (the default mode) */
        rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt);
       
       return 0;

    }

          在调用完wlanDrvIf_Create()这个函数后,实际上WIFI模块的初始化就结束了,下面分析如何初始化的。先看wlanDrvIf_SetupNetif (drv)这个函数的主体,

    static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv)
    {
       struct net_device *dev;
       int res;

       /* Allocate network interface structure for the driver */
       dev = alloc_etherdev (0);//申请LINUX网络设备
       if (dev == NULL)

       /* Setup the network interface */
       ether_setup (dev);//建立网络接口 ,这两个都是LINUX网络设备驱动的标准函数

       dev->netdev_ops = &wlan_netdev_ops;

       /* Initialize Wireless Extensions interface (WEXT) */
       wlanDrvWext_Init (dev);

       res = register_netdev (dev);

       /* Setup power-management callbacks */
       hPlatform_SetupPm(wlanDrvIf_Suspend, wlanDrvIf_Resume, pDrvStaticHandle);

    }

    注意,在这里初始化了wlanDrvWext_Inti(dev),这就说明wpa_supplicant与Driver直接的联系是走的WEXT这条路。也就是说event的接收,处理也应该是在WEXT部分来做的,确定这个,剩下的工作量顿减三分之一,哈哈哈。后面还注册了网络设备dev。而在wlan_netdev_ops中定义的功能如下:

    static const struct net_device_ops wlan_netdev_ops = {
            .ndo_open             = wlanDrvIf_Open,
            .ndo_stop             = wlanDrvIf_Release,
            .ndo_do_ioctl         = NULL,

            .ndo_start_xmit       = wlanDrvIf_Xmit,
            .ndo_get_stats        = wlanDrvIf_NetGetStat,
            .ndo_validate_addr    = NULL,

    };

    功能一看名字就知道了,不说了,这几个对应的都是LINUX网络设备驱动都有的命令字,详见《LINUX设备驱动开发详解》第十六章。

    在这之后,又调用了rc =drvMain_CreateI。

    在这个函数里完成了相关模块的初始化工作。具体不说了。接下来就是等待Android上层发送来的事件了。

    展开全文
  • 学习android wifi开发已经一周了,今天开始立帖,将每天的学习成果贴出来,以备以后查阅,从framework到wpa_supplicant的适配层(wifi.c)网上介绍的帖子很多,而且本身也并不复杂,其中framework部分需要注意的是...

           学习android wifi开发已经一周了,今天开始立帖,将每天的学习成果贴出来,以备以后查阅,从framework到wpa_supplicant的适配层(wifi.c)网上介绍的帖子很多,而且本身也并不复杂,其中framework部分需要注意的是wifiService和wifiMoniter两部分,这两快一个是转发AP的CMD另一个是接收来自wpa_supplicant的CMD。他们与本地库的连接都是通过JNI方法,具体实现方法在android_net_wifi_Wifi.cpp中。在这个文件中可以大致看出AP会给wpa_supplicant下哪些命令。这些命令通过wifi.c的wifi_command发送给wpa_supplicant,在发送命令的过程中实际是调用wpa_ctrl_request来完成命令发送的,wpa_ctrl_request是通过socket的方式与wpa_supplicant进行通信的,然后通过wpa_ctrl_recv来接收来自wpa_supplicant的命令,并返回标识给wifi_wait_for_event。

          但是命令发到wpa_supplicant后的流程网上提到的资料就非常少了,不过由于wpa_supplicant是一个标准的开源项目,已经被移植到很多平台上,它中间的过程我暂时还没有去细看。比较关心的是wpa_supplicant在接收到上层的命令后是怎么将命令发给DRIVER的,DRIVER在接收到命令后的解析的动作以及之后调用驱动功能函数的流程以及驱动对寄存器控制的细节。由于需要注意代码保密,之后不会提及具体使用了哪块WIFI芯片也不会提及此WIFI DRIVER是在什么平台什么产品。

           先贴一张wpa_supplicant的标准结构框图:


            重点关注框图的下半部分,即wpa_supplicant是如何与DRIVER进行联系的。整个过程暂以AP发出SCAN命令为主线。由于现在大部分WIFI DRIVER都支持wext,所以就假设我们的设备走的是wext这条线,其实用ndis也一样,流程感觉差不多。

           首先要说的是,在Driver.h文件中有个结构体wpa_driver_ops:

    /**
     * struct wpa_driver_ops - Driver interface API definition
     *
     * This structure defines the API that each driver interface needs to implement
     * for core wpa_supplicant code. All driver specific functionality is captured
     * in this wrapper.
     */
    struct wpa_driver_ops

             这个结构体在Driver.c中被声明为

    #ifdef CONFIG_DRIVER_WEXT
    extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */

           然后在driver_wext.c填写了结构体的成员,

    const struct wpa_driver_ops wpa_driver_wext_ops = {
        .name = "wext",
        .desc = "Linux wireless extensions (generic)",
        .get_bssid = wpa_driver_wext_get_bssid,
        .get_ssid = wpa_driver_wext_get_ssid,
        .set_wpa = wpa_driver_wext_set_wpa,
        .set_key = wpa_driver_wext_set_key,
        .set_countermeasures = wpa_driver_wext_set_countermeasures,
        .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
        .scan = wpa_driver_wext_scan,
        .combo_scan = wpa_driver_wext_combo_scan,
        .get_scan_results2 = wpa_driver_wext_get_scan_results,
        .deauthenticate = wpa_driver_wext_deauthenticate,
        .disassociate = wpa_driver_wext_disassociate,
        .set_mode = wpa_driver_wext_set_mode,
        .associate = wpa_driver_wext_associate,
        .set_auth_alg = wpa_driver_wext_set_auth_alg,
        .init = wpa_driver_wext_init,
        .deinit = wpa_driver_wext_deinit,
        .add_pmkid = wpa_driver_wext_add_pmkid,
        .remove_pmkid = wpa_driver_wext_remove_pmkid,
        .flush_pmkid = wpa_driver_wext_flush_pmkid,
        .get_capa = wpa_driver_wext_get_capa,
        .set_operstate = wpa_driver_wext_set_operstate,
    #ifdef ANDROID
        .driver_cmd = wpa_driver_priv_driver_cmd,
    #endif
    };

    这些成员其实都是驱动和wpa_supplicant的接口,以SCAN为例:

    int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)

    中的LINE1174:if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0)从这里可以看出wpa_cupplicant是通过IOCTL来调用SOCKET与DRIVER进行通信的,并给DRIVER下达SIOCSIWSCAN这个命令。

           这样,一个命令从AP到FRAMEWORK到C++本地库再到wpa_supplicant适配层,再由wpa_supplicant下CMD给DRIVER的路线就打通了,写起来虽然不多但也是一点小成果。

               时间过得很快,毕业已经三周了,后悔当初在实验室没有去学习关于WIFI的知识,现在只好从头看起。好在公司环境比较轻松,可以有时间抓抓细节,后面就要开始将DRIVER部分的结构和流程理理清楚了。


    展开全文
  • 一、什么是wifi 模块 百度百科上这样定义:  Wi-Fi模块又名串口Wi-Fi模块,属于物联网传输层,功能是将串口或TTL电平转为符合Wi-Fi无线网络通信标准的嵌入式模块,内置无线网络协议IEEE802.11b.g.n协议栈以及TCP/...

    一、什么是wifi 模块

            百度百科上这样定义:

            Wi-Fi模块又名串口Wi-Fi模块,属于物联网传输层,功能是将串口或TTL电平转为符合Wi-Fi无线网络通信标准的嵌入式模块,内置无线网络协议IEEE802.11b.g.n协议栈以及TCP/IP协议栈。传统的硬件设备嵌入Wi-Fi模块可以直接利用Wi-Fi联入互联网,是实现无线智能家居、M2M等物联网应用的重要组成部分。 


    二、WiFi 模块主要分类

          Wi-Fi模块可分为三类:

    a – 通用Wi-Fi模块

           比如手机、笔记本、平板电脑上的USBorSDIO接口模块,Wi-Fi协议栈和驱动是在安卓、Windows、iOS的系统里跑的,是需要非常强大的CPU来完成应用;

    b – 路由器方案Wi-Fi模块

          典型的是家用路由器,协议和驱动是借助拥有强大Flash和Ram资源的芯片加Linux操作系统

    c – 嵌入式Wi-Fi模块

          32位单片机,内置Wi-Fi驱动和协议,接口为一般的MCU接口如UART等。适合于各类智能家居或智能硬件单品。

           我觉得这里有必要了解一下普通Wi-Fi模块与嵌入式Wi-Fi模块的区别:

           我们都知道笔记本、手机、平板电脑等这类产品具有强大的CPU和大容量的存储器进行网络通信数据的处理和存储,因此在使用WIFI时不需要额外的MCU,完全借助其高速处理器和庞大的软件系统。但是对于家电,仪表,LED灯等智能家居产品,因为该类产品的主控芯片可能是成本很低、功能简单的MCU,因此这类产品无法支持普通Wi-Fi的功能。同时,还有一个重要的原因就是普通WIFI的功耗比较高,而嵌入式WIFI在功耗上做了很大的改善,比较适合对功耗要求高的无线家电设备。

           基于上述原因,各个无线厂商相继推出了嵌入式WIFI模块。嵌入式WIFI模块的特点是软硬件集成度高,整个嵌入式WIFI模块集成了射频收发器、MAC、WIFI驱动、所有WIFI协议、无线安全协议、一键连接等。总之,一句话:嵌入式WIFI应物联网而生!

         下面我们针对嵌入式WIFI与普通WIFI来进行对比,通过下表的对比,我们大致上可以理解到什么是嵌入式WIFI

     

    嵌入式WIFI模块

    普通WIFI模块

    适用范围

    无线家电、仪表、智能灯泡等智能家居设备

    笔记本、手机、平板电脑等

    主控芯片

    模块上集成的MCU

    x86 CPUARM等高速微处理器

    接口

    UARTSPII2CSDIO

    USBSDIO

    功耗

    产品

    TICC3200系列、MXCHIP系列、ASIX系列

    AtherosHF-LPA系列等

    瑞昱RTL81xx系列、威盛VT系列、雷凌RT系列、

    博通BCMMarvell、高通Atheros

    开发设计

    内置WIFI驱动、MACWIFI协议、无线安全协议等,

    所有的网络软件封装成一个UARTSPI接口的设备,

    使用简单,只需要往UART或者SPI收发数据即可。

    从整体软件层面上看,不属于网络设备。

    需要在主机添加WIFI驱动、同时需要依赖主机的网络协议栈等软件平台资源,

    从整体软件层面上看,属于网络设备,使用时需要遵循网络相关的协议。


    下面是笔者所用一款USB接口的WiFi模块原理图:




    三、WiFi模块主要功能

          Wifi 模块 包括两种类型的拓扑形式:基础网(Infra)自组网(Adhoc),要说明无线网络的拓扑形式,首先要了解两个基本概念:

    a – AP

           也就是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就是一个AP



    b – STA站点

           每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。


    1、基于AP组建的基础无线网络(Infra)

          Infra:也称为基础网,是由AP创建,众多STA加入所组成的无线网络,这种类型的网络的特点是AP是整个网络的中心,网络中所有的通信都通过AP来转发完成

    附:  

     笔者所用WiFi模块有两种系统设置:  无线网类型AP Infra   

    AP是将wifi模块当路由器使用,这样手机和电脑就可以直接连接wifi模块了。

     Infra 是将wifi模块当基础设备使用,用于连接别的路由器。

    2、基于自组网的无线网络(Adhoc)

          Adhoc:也称为自组网,是仅由两个及以上STA自己组成,网络中不存在AP,这种类型的网络是一种松散的结构,网络中所有的STA都可以直接通信

    3、安全机制

         本模块支持多种无线网络加密方式,能充分保证用户数据的安全传输,包括:WEP64/WEP128/ TKIP/CCMP(AES) WEP/WPA-PSK/WPA2-PSK。

    4、快速联网

          本模块支持通过指定信道号的方式来进行快速联网。在通常的无线联网过程中,会首先对当前的所有信道自动进行一次扫描,来搜索准备连接的目的AP创建的(或Adhoc)网络。本模块提供了设置工作信道的参数,在已知目的网络所在信道的条件下,可以直接指定模块的工作信道,从而达到加快联网速度的目的。

    5、地址绑定

         本模块支持在联网过程中绑定目的网络BSSID地址的功能。根据802.11协议规定,不同的无线网络可以具有相同的网络名称(也就是SSID/ESSID),但是必须对应一个唯一的BSSID 地址。非法入侵者可以通过建立具有相同的SSID/ESSID的无线网络的方法,使得网络中的STA联接到非法的AP上,从而造成网络的泄密。通过BSSID地址绑定的方式,可以防止STA 接入到非法的网络,从而提高无线网络的安全性。

    6、无线漫游

        本模块支持基于802.11协议的无线漫游功能。无线漫游指的是为了扩大一个无线网络的覆盖范围,由多个AP共同创建一个具有相同的SSID/ESSID的无线网络,每个AP用来覆盖不同的区域,接入到网络的STA可以根据所处位置的选择信号最强的AP接入,而且随着STA的移动自动在不同的AP之间切换。


    四、工作方式

    1、主动型串口设备联网

          主动型串口设备联网指的是由设备主动发起连接,并与后台服务器进行数据交互(上传或下载)的方式。典型的主动型设备,如无线POS机,在每次刷卡交易完成后即开始连接后台服务器,并上传交易数据。PUSH型串口设备联网的拓扑结构如右图所示。其中,后台服务器作为TCP Server端,设备通过无线AP/路由器接入到网络中,并作为TCP Client端。

    2、被动型串口设备联网

          被动型串口设备联网指的是,在系统中所有设备一直处于被动的等待连接状态,仅由后台服务器主动发起与设备的连接,并进行请求或下传数据的方式。典型的应用,如某些无线传感器网络,每个传感器终端始终实时的在采集数据,但是采集到的数据并没有马上上传,而是暂时保存在设备中。

          而后台服务器则周期性的每隔一段时间主动连接设备,并请求上传或下载数据。

         此时,后台服务器实际上作为TCP Client端,而设备则是作为TCP Server端主要特性2.4GHz, IEEE 802.11b/g内部PCB天线,可选外部天线支持基于AP的网络(Infrastructure)/对等网络Ad-Hoc (IBSS))/ 虚拟AP 模式 ,IPHONE/IPAD/Android 设备也能不用AP/路由器而直接连接支持802.11i加密方式:WEP-64/128,TKIP (WPA-PSK) and AES(WPA2-PSK)MCU内置TCP/IP协议栈3路UART串行接口(其中1路支持DMA 模式, 全功能串口,波特率最高支持921.6Kbps)SPI接口、I2S/PCM接口Digital Video端口高达24个GPIO口(部分GPIO将会和上述接口复用)全功能TCP/IP协议栈,TCP/IP传输带宽达到10Mbps以上支持三种带有定时自动唤醒功能的WiFi节能模式

    展开全文
  • 在分析WIFI驱动前,分享一下个人对Linux驱动的一些了解,其实纵观Linux众多的设备驱动,几乎都是以总线为载体,所有的数据传输都是基于总线形式的,即使设备没有所谓的总线接口,但是Linux还是会给它添加一条虚拟...
    在分析WIFI驱动前,分享一下个人对Linux驱动的一些了解,其实纵观Linux众多的设备驱动,几乎都是以总线为载体,所有的数据传输都是基于总线形式的,即使设备没有所谓的总线接口,但是Linux还是会给它添加一条虚拟总线,如platform总线等;介于WIFI的驱动实在是太庞大了,同时又是基于比较复杂的USB总线,所以建议读者在看此文章之前,先了解一下USB设备驱动和网络设备驱动。
    

             我们要看懂WIFI驱动,首先要明白WIFI的工作原理。所以前期有几篇文章都是讲解WIFI的工作原理。从这篇文章开始,我们将进入WIFI的代码世界。对于支持802.11n、802.11ac这些比较新的无线标准的WIFI芯片,其驱动程序也会越来越复杂。那么我们怎么入手去了解及分析它呢?

             特别声明:以下文章是以Station的角色去分析WIFI的驱动。

             网上很多文章分析Linux设备驱动都是从模块加载入手去分析它的驱动源码。以博主从事Linux设备驱动多年的经验,这确实是一条很直观又非常好的思路。但是这只局限于设备功能少、接口较简单、驱动源码较少的设备驱动。对于功能复杂、驱动源码庞大的设备驱动,根据这条思路,很多开发者可能会无耐心走下去,或者会走向死胡同。

             现在我们可以这样来看,从硬件层面上看,WIFI设备与CPU通信是通过USB接口的,与其他WIFI设备之间的通信是通过无线射频(RF)。从软件层面上看,Linux操作系统要管理WIFI设备,那么就要将WIFI设备挂载到USB总线上,通过USB子系统实现管理。而同时为了对接网络,又将WIFI设备封装成一个网络设备。

             我们以USB接口的WIFI模块进行分析:

             (1)从USB总线的角度去看,它是USB设备;

             (2)从Linux设备的分类上看,它又是网络设备;

             (3)从WIFI本身的角度去看,它又有自己独特的功能及属性,因此它又是一个私有的设备;

             通过上述的分析,我们只要抓住这三条线索深入去分析它的驱动源码,整个WIFI驱动框架就会浮现在你眼前。

             1、现在我们先从USB设备开始,要写一个USB设备驱动,那么大致步骤如下:

             (1)需要针对该设备定义一个USB驱动,对应到代码中即定义一个usb_driver结构体变量。代码如下:

                               struct usb_driver xxx_usb_wifi_driver;

             (2)填充该设备的usb_driver结构体成员变量。代码如下:

                               static struct usb_driver xxx_usb_wifi_driver = {

                                    .name =             "XXX_USB_WIFI",

                                    .probe=   xxx_probe,

                                    .disconnect=   xxx_disconnect,

                                    .suspend=        xxx_suspend,

                                    .resume=         xxx_resume,

                                    .id_table=        xxx_table,

                               };

              (3)将该驱动注册到USB子系统。代码如下:

                                usb_register(&xxx_usb_wifi_driver);

             以上步骤只是一个大致的USB驱动框架流程,而最大和最复杂的工作是填充usb_driver结构体成员变量。以上步骤的主要工作是将USB接口的WIFI设备挂载到USB总线上,以便Linux系统在USB总线上就能够找到该设备。

             2、接下来是网络设备的线索,网络设备驱动大致步骤如下:

             (1)定义一个net_device结构体变量ndev。代码如下:

                               struct net_device *ndev;

             (2)初始化ndev变量并分配内存。代码如下:

                               ndev=alloc_etherdev();

             (3)填充ndev -> netdev_ops结构体成员变量。代码如下:

                               static const struct net_device_ops xxx_netdev_ops= {

                                        .ndo_init= xxx_ndev_init,

                                        .ndo_uninit= xxx _ndev_uninit,

                                        .ndo_open= netdev_open,

                                        .ndo_stop= netdev_close,

                                        .ndo_start_xmit= xxx_xmit_entry,

                                        .ndo_set_mac_address= xxx_net_set_mac_address,

                                        .ndo_get_stats= xxx_net_get_stats,

                                        .ndo_do_ioctl= xxx_ioctl,

                               };

             (4)填充ndev->wireless_handlers结构体成员变量,该变量是无线扩展功能。代码如下:

                               ndev->wireless_handlers = (struct iw_handler_def *)&xxx_handlers_def;

             (5)将ndev设备注册到网络子系统。代码如下:

                                register_netdev(ndev);

             3、WIFI设备本身私有的功能及属性,如自身的配置及初始化、建立与用户空间的交互接口、自身功能的实现等。

             (1)自身的配置及初始化。代码如下:

                               xxx_read_chip_info();

                               xxx_chip_configure();

                               xxx_hal_init();

             (2)主要是在proc和sys文件系统上建立与用户空间的交互接口。代码如下:

                               xxx_drv_proc_init();

                               xxx_ndev_notifier_register();

             (3)自身功能的实现,在前面章节上我们已经讲解过WIFI的网络及接入原理,如扫描等。同时由于WIFI在移动设备中,相对功耗比较大,因此,对于功耗、电源管理也会在驱动中体现。

             本文章只是博主结合自身工作经验分享一个大致的对wifi驱动框架的理解,后期文章将会细化这些内容。敬请读者期待,谢谢!
    展开全文
  • Linux内核WIFI驱动详细源码,Linux下wifi实现,通过它可以学习无线相关知识,用于实践。
  • Android 开发之 ---- 底层驱动开发(一) 驱动概述  说到 android 驱动是离不开 Linux 驱动的。Android 内核采用的是 Linux2.6 内核 (最近Linux 3.3 已经包含了一些 Android 代码)。但 Android 并没有完全照搬 ...
  • 由于在这个项目中,WIFI模块是采用SDIO总线来控制的,所以先记录下CLIENT DRIVER的SDIO部分的结构,这部分的SDIO分为三层:SdioDrv、SdioAdapter、SdioBusDrv。其中SdioBusDrv是Client Driver中SDIO与WIFI
  • WIFI驱动结构介绍

    2014-02-19 15:19:05
    在drivers/mmc下面是mmc卡,SD卡和SDIO卡驱动部分,其中包括host驱动,card驱动和core部分,由于网络接口卡挂接在SDIO总线上,所以在此之前我们先看一下SDIO的驱动结构。其驱动在drivers/mmc目录下的结构为:   |--...
  • linux驱动开发 linux下驱动开发直接操作寄存器,不现实 根据Linux下的各种驱动框架,进行开发;一定要满足框架,也就是linux下各种驱动框架的掌握; 在linux下,驱动最终表现(对应的外设)是 /dev/xxx下的文件;...
  • Android 设备驱动(下)  MTD 驱动  Flash 驱动通常使用 MTD (memory technology device ),内存技术设备。  MTD 的字符设备:  /dev/mtdX  主设备号 90.
  • 本篇文章来跟大家一起了解一下Android中的wifi框架 二、WIFI框架 整体框架图 1、Java应用层 原生机目录:packages/apps/Settings/src/com/android/settings/wifi/ 主要的类: WifiSettings.java 负责显示Wifi的设置...
  • ... 说到 android 驱动是离不开 Linux 驱动的。Android 内核采用的是 Linux2.6 内核 (最近Linux 3.3 已经包含了一些 Android 代码)。但 Android 并没有完全照搬 Linux 系统内核,除了对Linux
  • WifiService: 由SystemServer启动的时候生成的ConnecttivityService创建,负责 启动关闭wpa_supplicant, 启动和关闭WifiMonitor线程,把命令下发给wpa_supplicant以及 更新WIFI的状态
  • Android驱动开发知识储备 Android软件层次结构 (1)操作系统层 显示驱动(Frame Buffer),Flash内存驱动,照相机驱动,音频驱动,WiFi驱动,键盘驱动,蓝牙驱动,Binder IPC驱动,Power Management ,这些都包括...
  • 具体的框架之前分析过,不熟悉的朋友可以看我这篇文章 Linux驱动学习–DRM框架介绍及基于DRM框架的HDMI开发,这里就结合源码来实际讲解一下 1、内核驱动 识别到对应类型的设备,我们这里是USB蓝牙接口的BT芯片,调用...
  • 一、WIFI的基本架构(代码路径) 1、WIFI Settings应用程序: packages/apps/Settings/src/com/android/settings/wifi/ 2、JAVA部分(framework): framewo...
1 2 3 4 5 ... 20
收藏数 5,407
精华内容 2,162
关键字:

底层wifi驱动开发