linux 下wifi 驱动开发 usb接口wifi驱动浅析.docx
LINUX下WIFI驱动开发(四)USB接口WIFI驱动浅析前面学习了SDIO接口的WIFI驱动,现在我们来学习一下USB接口的WIFI驱动,二者的区别在于接口不同。而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动、USB鼠标驱动,同样都符合LINUXUSB驱动结构USB设备驱动(字符设备、块设备、网络设备)|USB核心|USB主机控制器驱动不同之处只是在于USB摄像头驱动是字符设备,而我们今天要学习的WIFI驱动是网络设备;当然由我们编写的部分还是USB设备驱动部分,下面进入USB接口WIFI驱动的分析,如何分析呢我们下面从这几个方面入手从硬件层面上看,WIFI设备与CPU通信是通过USB接口的,与其他WIFI设备之间的通信是通过无线射频(RF)。从软件层面上看,LINUX操作系统要管理WIFI设备,那么就要将WIFI设备挂载到USB总线上,通过USB子系统实现管理。而同时为了对接网络,又将WIFI设备封装成一个网络设备。我们以USB接口的WIFI模块进行分析A从USB总线的角度去看,它是USB设备;B从LINUX设备的分类上看,它又是网络设备;C从WIFI本身的角度去看,它又有自己独特的功能及属性,因此它又是一个私有的设备;通过上述的分析,我们只要抓住这三条线索深入去分析它的驱动源码,整个WIFI驱动框架就会浮现在你眼前。一、框架整理1、USB设备驱动现在我们先从USB设备开始,要写一个USB设备驱动,那么大致步骤如下A需要针对该设备定义一个USB驱动,对应到代码中即定义一个USB_DRIVER结构体变量代码如下CPPVIEWPLAINCOPY1STRUCTUSB_DRIVERXXX_USB_WIFI_DRIVERB填充该设备的USB_DRIVER结构体成员变量代码如下CPPVIEWPLAINCOPY1STATICSTRUCTUSB_DRIVERXXX_USB_WIFI_DRIVER{2NAME“XXX_USB_WIFI“,3PROBEXXX_PROBE,4DISCONNECTXXX_DISCONNECT,5SUSPENDXXX_SUSPEND,6RESUMEXXX_RESUME,7ID_TABLEXXX_TABLE,8}C将该驱动注册到USB子系统代码如下CPPVIEWPLAINCOPY1USB_REGISTER以上步骤只是一个大致的USB驱动框架流程,而最大和最复杂的工作是填充USB_DRIVER结构体成员变量。以上步骤的主要工作是将USB接口的WIFI设备挂载到USB总线上,以便LINUX系统在USB总线上就能够找到该设备。2、网络设备驱动接下来是网络设备的线索,网络设备驱动大致步骤如下A定义一个NET_DEVICE结构体变量NDEV代码如下CPPVIEWPLAINCOPY1STRUCTNET_DEVICENDEVB初始化NDEV变量并分配内存代码如下CPPVIEWPLAINCOPY1NDLOC_ETHERDEVC填充NDEVNETDEV_OPS结构体成员变量代码如下CPPVIEWPLAINCOPY1STATICCONSTSTRUCTNET_DEVICE_OPSXXX_NETDEV_OPS{2NDO_INITXXX_NDEV_INIT,3NDO_UNINITXXX_NDEV_UNINIT,4NDO_OPENNETDEV_OPEN,5NDO_STOPNETDEV_CLOSE,6NDO_START_XMITXXX_XMIT_ENTRY,7NDO_SET_MAC_ADDRESSXXX_NET_SET_MAC_ADDRESS,8NDO_GET_STATSXXX_NET_GET_STATS,9NDO_DO_IOCTLXXX_IOCTL,10}D填充NDEVWIRELESS_HANDLERS结构体成员变量,该变量是无线扩展功能代码如下CPPVIEWPLAINCOPY1NDEVWIRELESS_HANDLERSSTRUCTIW_HANDLER_DEFE将NDEV设备注册到网络子系统代码如下CPPVIEWPLAINCOPY1REGISTER_NETDEVNDEV3、WIFI设备本身私有的功能及属性如自身的配置及初始化、建立与用户空间的交互接口、自身功能的实现等。A自身的配置及初始化代码如下CPPVIEWPLAINCOPY1XXX_READ_CHIP_INFO23XXX_CHIP_CONFIGURE45XXX_HAL_INITB主要是在PROC和SYS文件系统上建立与用户空间的交互接口代码如下CPPVIEWPLAINCOPY1XXX_DRV_PROC_INIT23XXX_NDEV_NOTIFIER_REGISTERC自身功能的实现WIFI的网络及接入原理,如扫描等。同时由于WIFI在移动设备中,相对功耗比较大,因此,对于功耗、电源管理也会在驱动中体现。二、USB设备驱动分析在分析之前,我们需要理解在整个WIFI模块中,USB充当什么角色它的作用是什么实质上WIFI模块上的数据传输有两端,一端是WIFI芯片与WIFI芯片之间,通过无线射频(RF)进行数据传输;另一端则是WIFI芯片与CPU之间,通过USB进行数据传输。了解LINUX的USB驱动的读者都知道,USB驱动分为两种一种是USB主机驱动;另一种是USB设备驱动。而我们的USB接口的WIFI模块对于CPU(主机)来说,属于USB设备,因此采用USB设备驱动。有了以上信息之后,我们先让LINUX系统识别该USB接口的WIFI模块,首先我们在驱动源码中大致添加以下几步工作前面分析过,这里只看步骤,不看代码A定义一个USB_DRIVER结构体变量B填充该设备的USB_DRIVER结构体成员变量C将该驱动注册到USB子系统简单完成以上几步工作,再加上板级文件(ARCH/MACHXXXC)对USB设备的支持,LINUX的USB子系统几乎可以挂载该WIFI模块为USB设备了。但是这并不是我们最终想要的结果。我们还要让LINUX系统知道它挂载的USB设备属于无线网络设备,同时能够访问它,利用它实施无线网络的工作。我们都知道,若要让USB设备真正工作起来,需要对USB设备的4个层次(设备、配置、接口、端点)进行初始化。当然这四个层次并不是一定都要进行初始化,而是根据你的USB设备的功能进行选择的,大致初始化流程如下伪代码CPPVIEWPLAINCOPY1STATICSTRUCTDVOBJ_PRIVUSB_DVOBJ_INITSTRUCTUSB_INTERFACEUSB_INTF2{3INTI4U8VAL85INTSTATUS_FAIL6STRUCTDVOBJ_PRIVPDVOBJPRIV78//设备9STRUCTUSB_DEVICEPUSBD10STRUCTUSB_DEVICE_DESCRIPTORPDEV_DESC1112//配置13STRUCTUSB_HOST_CONFIGPHOST_CONF14STRUCTUSB_CONFIG_DESCRIPTORPCONF_DESC1516//接口17STRUCTUSB_HOST_INTERFACEPHOST_IFACE18STRUCTUSB_INTERFACE_DESCRIPTORPIFAC