wifi驱动的理解(2)——usb接口在wifi模块中的角色
来源:互联网 发布:淘宝商城品牌故事范文 编辑:程序博客网 时间:2024/06/03 17:20
上一篇文章我们已经通过三条线索简单地描述了wifi驱动的框架,现在我们开始深入到每条线索中。首先我们从USB设备这条线索开始。在分析之前,我们需要理解在整个wifi模块中,USB充当什么角色?它的作用是什么?实质上wifi模块上的数据传输有两端,一端是wifi芯片与wifi芯片之间,通过无线射频(RF)进行数据传输;另一端则是wifi芯片与CPU之间,通过USB进行数据传输。
了解Linux的USB驱动的读者都知道,USB驱动分为两种:一种是USB主机驱动;另一种是USB设备驱动。而我们的USB接口的wifi模块对于CPU(主机)来说,属于USB设备,因此采用USB设备驱动。 有了以上信息之后,我们先让Linux系统识别该USB接口的wifi模块,首先我们在驱动源码中大致添加以下几步工作: (1)定义一个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_init_wifi, .disconnect = xxx_remove, .suspend = xxx_suspend, .resume = xxx_resume, .id_table= xxx_table, }; (3)将该驱动注册到USB子系统: usb_register(&xxx_usb_wifi_driver); 简单完成以上几步工作,再加上板级文件(arch/mach-xxx.c)对USB设备的支持,Linux的USB子系统几乎可以挂载该wifi模块为USB设备了。但是这并不是我们最终想要的结果。我们还要让Linux系统知道它挂载的USB设备属于无线网络设备,同时能够访问它,利用它实施无线网络的工作。 我们都知道,若要让USB设备真正工作起来,需要对USB设备的4个层次(设备、配置、接口、端点)进行初始化。当然这四个层次并不是一定都要进行初始化,而是根据你的USB设备的功能进行选择的,大致初始化流程如下伪代码: static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) { int i; u8 val8; int status= _FAIL; struct dvobj_priv *pdvobjpriv; //设备 struct usb_device *pusbd; struct usb_device_descriptor *pdev_desc; //配置 struct usb_host_config *phost_conf; struct usb_config_descriptor *pconf_desc; //接口 struct usb_host_interface *phost_iface; struct usb_interface_descriptor *piface_desc; //端点 struct usb_host_endpoint *phost_endp; struct usb_endpoint_descriptor *pendp_desc; //设备的初始化 pdvobjpriv->pusbintf = usb_intf ; pusbd =pdvobjpriv->pusbdev = interface_to_usbdev(usb_intf); usb_set_intfdata(usb_intf, pdvobjpriv); pdev_desc =&pusbd->descriptor; //配置的初始化 phost_conf =pusbd->actconfig; pconf_desc =&phost_conf->desc; //接口的初始化 phost_iface =&usb_intf->altsetting[0]; piface_desc =&phost_iface->desc; 端点的初始化,由于wifi模块属于网络设备,传输批量数据,因此需要初始化为批量端点,端点方向(输入、输出)等。同时,由于wifi驱动功能比较多,需要初始化几个输入输出端点。 for (i = 0; i <pdvobjpriv->nr_endpoint; i++) { phost_endp = phost_iface->endpoint +i; if (phost_endp) { pendp_desc =&phost_endp->desc; //检查是否为输入端点 usb_endpoint_is_bulk_in(pendp_desc); //检查是否为输出端点 usb_endpoint_is_bulk_out(pendp_desc); } } usb_get_dev(pusbd); } 完成以上的初始化工作之后,接下来我们需要理清一下USB接口的作用,它是wifi芯片内部的固件程序与主机上的Linux系统进行数据通信。USB设备通信不像普通字符设备那样采用I/O内存和I/O端口的访问,而是采用一种称为URB(USB Request Block)的USB请求块,URB在整个USB子系统中,相当于通电设备中的“电波”,USB主机与设备的通信,通过“电波”来传递。下面我们就来编写USB接口的读写操作函数,伪代码如下: void xxx_wifi_usb_intf_ops(struct _io_ops *pops) { //当需要进行简单数据的读取时,采用以下操作 pops->_read8 = &usb_read8; pops->_read16 = &usb_read16; pops->_read32 = &usb_read32; //当需要进行批量数据的读取时,采用以下操作 pops->_read_port = &usb_read_port; //当需要进行简单数据的写时,采用以下操作 pops->_write8 = &usb_write8; pops->_write16 = &usb_write16; pops->_write32 = &usb_write32; pops->_writeN = &usb_writeN; //当需要进行批量数据的写时,采用以下操作 pops->_write_port = &usb_write_port; //取消读写urb pops->_read_port_cancel = &usb_read_port_cancel; pops->_write_port_cancel = &usb_write_port_cancel; } 在进行批量数据的读写时,如usb_read_port()和usb_write_port()函数,需要完成urb创建、初始化、提交、完成处理这个完整的流程。伪代码如下: (1)批量读操作 static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) { int err; unsigned intpipe; PURB purb =NULL; structrecv_buf *precvbuf = (structrecv_buf *)rmem; structusb_device *pusbd = pdvobj->pusbdev; //创建urb,这里是在其它地方创建完成之后,传递过来 purb =precvbuf->purb; //初始化批量urb usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pbuf, MAX_RECVBUF_SZ, usb_read_port_complete, precvbuf);//contextis precvbuf //提交urb err =usb_submit_urb(purb, GFP_ATOMIC); } (2)批量写操作 u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) { unsigned int pipe; intstatus; PURB purb = NULL; structxmit_priv *pxmitpriv =&padapter->xmitpriv; structxmit_buf *pxmitbuf = (struct xmit_buf *)wmem; structxmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; structusb_device *pusbd = pdvobj->pusbdev; structpkt_attrib *pattrib = &pxmitframe->attrib; //创建urb,这里是在其它地方创建完成之后,传递过来 purb = pxmitbuf->pxmit_urb[0]; //初始化批量urb usb_fill_bulk_urb(purb, pusbd, pipe, pxmitframe->buf_addr,//= pxmitbuf->pbuf cnt, usb_write_port_complete, pxmitbuf);//contextis pxmitbuf //提交urb status = usb_submit_urb(purb,GFP_ATOMIC); return ret; } 完成以上批量数据的读写操作之后,大家可能会疑问:这不是一般USB设备驱动的操作流程吗?貌似和wifi没有半毛钱的关系啊! 从这篇文章上看,确实和wifi没有任何联系,但是以上只是一个铺垫。我们一直强调USB接口在wifi模块中充当什么角色,既然是接口,那么它就是为数据传输而生。所以,和wifi扯上关系的就在于usb_read_port()和usb_write_port()这两个函数。 读者可结合USB设备驱动和网络设备驱动细心思考,它们之间是如何联系上的? 鉴于文章篇幅有限,以上问题将在下篇文章进行详细讲解,敬请期待!
0 0
- wifi驱动的理解(2)——usb接口在wifi模块中的角色
- wifi驱动的理解(2)——usb接口在wifi模块中的角色
- wifi驱动的理解(2)——usb接口在wifi模块中的角色
- wifi驱动的理解(3)——usb接口在wifi模块中的角色
- wifi驱动的理解(3)——usb接口在wifi模块中的角色
- wifi驱动的理解(4)——usb接口在wifi模块中的角色
- 【智能家居篇】wifi驱动的理解(2)——usb接口在wifi模块中的角色
- 【智能家居篇】wifi驱动的理解(3)——usb接口在wifi模块中的角色
- 【智能家居篇】wifi驱动的理解(4)——usb接口在wifi模块中的角色
- USB接口WIFI模块在嵌入式Linux下的驱动安装及测试
- Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
- Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
- Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
- Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
- wifi驱动的理解(1)——驱动架构
- wifi驱动的理解(1)——驱动架构
- wifi驱动的理解(1)——驱动架构
- wifi驱动的接口
- 快速排序
- Codeforces Round #326 (Div. 2) E. Duff in the Army
- 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
- Android-Resources-Hodgepodge(Android资源大杂烩)
- Word2Vec原理详解
- wifi驱动的理解(2)——usb接口在wifi模块中的角色
- At Commands:从白痴到大师的修炼历程(三)
- 计算机视觉方向的一些顶级会议和期刊
- iOS获取设备标识符
- 使用Github Page和Hexo快速构建个人博客,以及插件安装及主题优化总结
- 二分插入排序
- Struts2实现文件上传和下载
- 你应该知道的 RPC 原理
- 简单分享下阿里面试经验