android wifi驱动开发日记(二)(三)

来源:互联网 发布:淘宝提前收款服务费 编辑:程序博客网 时间:2024/05/29 12:50

http://blog.csdn.net/zoe6553/article/details/6657473

由于在这个项目中,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 DRIVER 开发日记(三)

http://blog.csdn.net/zoe6553/article/details/6825187

WIFI已经可以工作了,大部分android wifisetting里要求的功能也都实现了,不过还有两个问题在这里记录一下:

1. Softap无法使用

2. 通过WPS联网的时候有一定几率会失败。

        对于softap,当在setting中选下WIFI TETHERING时,softapcontroller就会给DRIVER发送私有命令,不过在发送私有命令前会先通过IOCTL发送SIOCGIWPRIV这个命令字给DRIVER。这个命令的作用是获得当前DRIVER所支持的私有命令。(因为SOFTAP并不是standard cmd, 所以如果要支持的话必须放在私有命令中)

        而DRIVER是否支持私有命令,或者说支持哪些私有命令就要看DRIVER中关于结构体iw_handler_def的赋值:

const struct iw_handler_def wl_iw_handler_def =
{
    .num_standard = ARRAYSIZE(wl_iw_handler),
    .standard = (iw_handler *) wl_iw_handler,
    .num_private = ARRAYSIZE(wl_iw_priv_handler),
    .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
    .private = (iw_handler *)wl_iw_priv_handler,
    .private_args = (void *) wl_iw_priv_args,

};

而我这边由于不知到手上的模块支持哪些private cmd。所以这块自己没办法加,只有联系供应厂商提供支援,现在暂时空下,等支援OK了再该过来。

         可是对于问题2我就头大了,有时候好有时候不好,不好的时候就是硬件返回了一个fail,这个让我无从解起。不知道是不是WPS本来联网就不稳定还是其他什么情况我也不得而知。这可能也是我没有选择在设备商公司工作而是转投到制造商的悲哀之一吧。一旦设备本身出了问题,作为制造商只能等待设备商自己来解决,除了催促其他什么也做不了!可是在设备商公司工作又无法接触到这么多好玩的终端产品这就交鱼和熊掌不可兼得吧。


查看评论
2楼 卧石青篱 2013-07-29 21:29发表 [回复] [引用] [举报]
wps受周围的环境干扰影响比较大,如果丢包比较严重就可能造成wps失败。按理说协议里有规定退避算法的,但是有些wifi芯片厂家为了显得自己的芯片信号好,重发的的概率大,搞的按照标准来的就受干扰严重,做wifi p2p的时候formation失败很多时间就是受干扰。。。
PS:博主现在是不是已经不做wifi了?
Re: zoe6553 2013-08-02 16:55发表 [回复]
回复greatwh:是的,现在不做WIFI了,从两个月前开始被公司安排转做音视频这部分的BSP了。不过WIFI上的事情也可以拿出来大家一起探讨下。
1楼 jianzhengzhouzjz 2012-01-05 18:59发表 [回复]
好文章,我最近也在处理一些wifi的问题,感觉很有参考价值。