搜档网
当前位置:搜档网 › 基于Linux的USB无线网卡通用驱动框架设计

基于Linux的USB无线网卡通用驱动框架设计

提要

本文在分析了Linux下USB无线网卡驱动程序的环境、职责及行为后,总结出来了这些驱动程序的相同或者类似的行为与性质。本文以软件复用及软件分层的思想为依据,提出并设计了基于Linux的USB无线网卡通用驱动框架程序。

本文通过研究不同类型USB无线网卡的驱动程序,寻找出了它们的相同点及不同点后对USB无线网卡通用驱动框架程序进行了整体设计,其中包括针对可复用部分的通用处理和针对不同点的参数文件部分处理。Linux的USB无线网卡驱动程序是工作在Linux的ieee802.11协议层之下,因此从某种角度上来说处理通用部分的框架程序是ieee802.11协议在驱动层的一种延伸,并为参数文件的编写创造了环境。针对不同点的参数或计算统统放到参数文件中,在每个参数文件中存放着某个型号USB无线网卡的硬件参数。当通用驱动框架程序发现了一个USB无线网卡后,从用户空间读取该硬件对应的参数文件并生成参数链。参数链中的参数都被包装成为指令的形式,每个参数都有一定的动作行为,通用驱动框架程序翻译并执行参数链中参数所要求动作。生成参数链后的通用驱动框架程序才是一个真正能够工作的驱动程序。参数链中的参数主要包含硬件初始化时需要的各种参数值和参数值的各种计算、硬件帧头部参数的添加与计算等等。然后添加各种锁来保护互斥资源。本文通过组建一个ad-hoc网络来测试驱动程序,实验结果证明:本文提出的通用驱动框架能够正确的生成参数链,能够正确处理参数链,并且驱动程序能够正常工作。

当本文设计的USB无线网卡通用驱动框架程序被演变进化成熟后之后,编写USB 无线网卡驱动程序的工作就转变为在用户空间编写硬件参数文件,这将大大的简化了编写USB无线网卡驱动程序的工作量及复杂度。

摘要

基于Linux的USB无线网卡通用驱动框架设计

Linux操作系统是开源世界的一面领军旗帜。正因为Linux是开源的,使它成为了嵌入式项目首选的最佳平台。因为在一个典型的嵌入式项目中要经历选购硬件、制作电路板、裁剪一个合适的操作系统、添加应用层软件这一过程。在具有一定特性硬件的基础上想选择一个合适的操作系统,而这个操作系统如果是封闭的,那困难是可想而知的。Linux操作系统本身支持很多USB无线网卡。每个类型的无线网卡都对应着自己的驱动程序,这些驱动程序从功能、职责、调用的接口函及服务的协议等数都有很多相同或者相似点。那么是否能够总结他们的相同点,处理他们的不同点来设计一个USB无线网卡通用驱动程序呢?

在一个嵌入式项目中,为了给硬件裁剪一个合适的Linux操作系统,使它支持特殊硬件的过程中,不得不提及驱动程序。在一个嵌入式项目中经常会遇到某某硬件不能工作的情况,这时如果不了解驱动程序,那问题将变得非常棘手。在Linux操作系统内核源代码中驱动程序的代码量所占的比重最大。因此驱动程序是非常值得学习研究的。本文的宗旨就是在深入学习研究Linux下的USB无线网卡的驱动程序后,利用软件复用和软件分层的思想把各个型号的USB无线网卡驱动程序的通用部分集中起来设计出一个通用驱动框架程序,该通用驱动框架程序也可以当做ieee802.11协议在驱动层的延伸。各个型号USB无线网卡的硬件差异部分则放到用户空间的参数文件中。当需要某网卡驱动的时候,通用驱动框架程序读取该网卡硬件参数文件动态的组成该型号的网卡驱动程序。在本文中这一过程是当一个USB无线网卡插到USB接口上去后,系统调用通用驱动框架程序,通用驱动框架程序到一个指定的路径目录下寻找该硬件的参数文件,读取参数文件并生成相应的参数链,这时通用驱动框架就变成了该硬件的专有驱动程序。这整个过程类似驱动程序寻找芯片固件的过程,寻找固件的过程也是先在指定路径目录下寻找固件,然后读入硬件芯片中去,只不过固件是经过编译后设备芯片要执行的指令。如果按照本文的方式组建驱动程序,那么参数链中的参数要能够处理自己硬件带来的所有差异。本文设计了参数链中参数的数据结构,在参数处理的核心部分设置了一个参数计算器,并封封装了驱动与USB设备通信的几个接口函数。参数处理部分还定义了参数的来源于去向。

如果按照本文的方式编写驱动,那么驱动程序的源代码所占的比重将大大的降低,并且在本文设计的USB无线网卡通用驱动框架程序日臻成熟后,编写USB无线网卡驱动程序的工作就转变为在用户空间中编写网卡的硬件参数文件。本文选择了两个不同型号

的USB无线网卡来检验通用驱动框架的工作效果,并测试其中一个网卡的工作情况,驱动程序工作基本正常。符合了当初设计的初衷。

关键词:

Linux操作系统,USB接口,USB无线网卡驱动,ieee802.11协议,软件复用,软件分层

Abstract

The Generic Driver Framework Design of USB Wireless Network

Adapter Based on Linux

The Linux operating system is one leader in open source world .Linux is the best choice for embedded projects that just because Linux is open source. To go through the purchase of hardware in a typical embedded project, the production of circuit boards, cutting a suitable operating system, add the process of application layer software. Want to choose a suitable operating system on the basis of certain characteristics of the hardware, if the operating system is closed that the difficulty can be imagined. Linux operating system supports many USB wireless card. Each Wireless card has it’s own driver, these drivers have the same or similar point from functions,responsibilities,the interface called and service agreements. Why not to summarize the same point, and deal with their differences to design a USB wireless card generic driver?

I must mention the driver in the process of cutting the Linux operating system which making it support special hardware. In an embedded project which will often encounter certain hardware can not work, if do not know the driver’s knowledge at this time, the problem will become very difficult. Driver source code occupy the largest proportion of the amount of code in the Linux operating system kernel. Therefore, the driver’s knowledge is very worth to study. The purpose of this paper is to design generic driver framework program under in-depth study Linux USB wireless network card drivers, which using software reuse and software layered technology to together the various types of USB wireless network card driver, The generic driver framework program also can be used as ieee802.11 an extension of the agreement in the driver layer. The various types of USB wireless network card puts the differences processing into the parameter file in user space. When need one network card driver, the generic driver framework program reads the wireless card’s hardware parameter file and dynamic composition of the network card driver. In this article, this process is that the system calls the generic driver framework program when a USB wireless card plugged into the USB interface, the generic driver framework program goes to a specified path directory to finds the parameter file of the hardware and reads the parameter file,generates the corresponding parameter chain, then the generic driver framework chang into a proprietary driver for this hardware. This whole process is similar to the driver to find the firmware, the process of looking for the firmware is also the first in the specified path directory to find firmware, and then read into the hardware chip, only the firmware is compiled device chip to execute instructions. If set up the driver accordance with this way , then the parameters in the

parameter chain to be able to handle all the differences of their own hardware. This article design parameters data structure which in the parameter chain, design a parameter calculator in the core part of the processing parameters, and seal the package several interface functions of the drive communicate to USB devices. Parameter processing section also defines the parameters from and whereabouts.

In this way to design the driver, then the proportion of the driver's source code will be greatly reduced. And USB wireless network card in this article the generic driver framework program has matured, the preparation work of the USB wireless network card driver into the preparation of the network card in the user space hardware parameter file. This paper selected two different types of USB wireless card to test the effect of the generic driver framework, and test a network card working conditions, the driver works normal. In line with the original intention of the original design.

Keywords:

Linux operating system, USB interface, USB wireless network card drivers, ieee802.11 agreement, software reuse, software layered

目录

第1章绪论 (1)

1.1 研究背景及意义 (1)

1.2 论文的主要工作 (3)

第2章USB无线网卡驱动的软件及硬件环境 (5)

2.1 Linux内核 (5)

2.2 USB接口 (7)

2.3 Ieee802.11协议层 (10)

2.4 USB无线网卡 (12)

第3章探索函数和参数处理 (14)

3.1 参数链功能设计 (14)

3.2 编写USB无线网卡驱动的任务 (15)

3.3 私有数据结构的设计 (16)

3.3.1 priv_dev私有数据结构 (16)

3.3.2 参数链节点数据结构 (19)

3.3.3 私有栈数据结构 (24)

3.4 读取参数文件 (30)

第4章驱动函数 (33)

4.1 驱动的start、接收及stop函数 (33)

4.1.1 安装固件 (33)

4.1.2 设置队列 (34)

4.1.3 接收函数 (36)

4.1.4 stop函数 (38)

4.2 添加删除接口函数 (38)

4.3 配置函数 (39)

4.4 配置接收过滤函数 (39)

4.5 发送函数 (40)

第5章测试及实验 (43)

5.1 测试目标 (43)

5.2 测试器件 (43)

5.3 测试方法 (43)

5.4 测试步骤 (43)

5.5 测试结果 (44)

第6章总结及展望 (48)

参考文献 (50)

致谢 (53)

第1章绪论

1.1 研究背景及意义

随着Linux操作系统的发展壮大,以及在嵌入式行业中的普遍应用,使得Linux操作系统逐渐得到更多人的青睐。而Linux驱动程序是Linux操作系统最庞大、最重要的组成部分之一[1]。一个好的驱动程序本身就非常具有含金量,它使用Linux内核提供的内存管理、并发和竞态管理、中断管理等等。只有对Linux内核的各种机制充分了解掌握后,才能设计出一个好的驱动程序。

Linux驱动程序按照传统区分为字符设备驱动程序、块设备驱动程序、网络设备驱动程序。USB无线网卡驱动程序属于网络设备驱动程序。Linux内核本身的源代码中就有大量的USB无线网卡驱动程序。通过对不同类型的USB无线网卡驱动程序的研究发现如下共同的特点:

1.它们都是驱动程序,在Linux内核中处于同一功能层中,都可以编译成为一个模块(module),挂载(insmod命令[2])到内核中。

2.它们都是USB接口的,它们本身是作为一个USB设备(具有USB接口的设备通常都叫做USB设备[3])工作在USB中央控制器驱动程序的上层。它们是在USB中央控制器驱动程序创造的环境中工作,调用USB中央控制器的统一接口函数。作为一个USB设备,那就要符号USB设备的一些标准,而这些标准是相同的[4]。

3.它们都是无线网络设备,都使用ieee802.11协议。因此作为一个ieee802.11设备也要符合ieee802.11设备的标准[5]。Linux操作系统中有ieee802.11协议子层,各个不同型号的硬件设备驱动程序都是实现ieee80211_op数据结构中的函数,例如打开是start()函数,发送是tx()函数,关闭都是stop()函数等。

4.它们都是网络设备[6],因此从功能的角度来看,它们要行使的义务是相同的。上层网络协议把数据传输给设备,设备负责发送出去;设备接收到数据后,要提交给它的上层协议,并且驱动程序还要向上层报告一些状态[7]。由于都是工作在网络的ieee802.11子层中,这些状态的数据结构是相同的。

以上4点是它们的主要相同点,通过分析后发现不同的USB无线网卡驱动程序各自做了很多相似或者相同的工作。那么它们的不同点分析如下:

1.对于不同的硬件最大的不同点就是电路不同,这就直接导致在初始化设备的时候寄存器的值是不同的。

2.无线网卡设备中也有个功能类似CPU的MAC控制器,如果它不相同,那么它需要

的固件程序是不相同的。

3.对于不同的硬件在发送和接收时,硬件帧头[8]也都不相同,硬件帧头是添加在要发送数据头部的一段数据,硬件可以识别这段数据,并从中提取参数和命令或者能够识别这段命令。

分析了各个型号USB 无线网卡驱动处理的相同点和不同点后。假设有一个通用驱动的话,那一定是分为两层:相同点的处理和不同点的处理。因此本文的驱动分层如图1.1所示。

(a)传统驱动分层 (b)本文驱动分层

图1.1 驱动的分层

Figure 1.1 Driven layered

内核空间

用户空间 …… 图1.2 通用驱动组成部分

Figure 1.2 Universal drive components

图1.1中(a)是传统的驱动分层结构,在传统驱动分层结构下,虽然都是USB 无线网卡但因为型号不同导致每个网卡都需要自己的驱动程序。图1.1中(b)是本文的驱动分层,本文把传统的USB 无线网卡驱动层划分出了USB 无线网卡通用驱动框架和参数文件两个部分。如果有多个网卡参数文件,就会有图1.2所示的场景,通用驱动框架和任意一个参数文件组合,就成为了该型号网卡的专用驱动程序。这样设计后通用驱动框架程序的软件复用率将相当高,并且简化了安装大量驱动程序的工作,只要安装一个通用驱动框架程序就可以了,不同型号的网卡在用户空间都有一个自己的参数文件。如果本次探索合理可行的话,那将减少了Linux 内核的驱动代码量,也大大简化了编写USB 无线网卡驱动程序的工作量,降低了编写USB 无线网卡驱动的难度,也不用再考虑和关注Linux 内核编程的一些环境和注意事项了。因为通用驱动框架程序已经处理上文提到的所有相同点的问题。而剩下的工作就是在通用驱动框架程序创造的环境中编写参数文

802.11协议层 USB 无线网卡 驱动层 USB 无线网卡硬件 802.11协议层 USB 无线网卡通用驱动框架 参数文件 USB 无线网卡硬件

USB 无线网卡通用驱动框架 某网卡参数文件 某网卡参数文件 某网卡参数文件

件。只要编写符合通用驱动框架要求的硬件参数文件就可以了。本文根据USB设备通信的特点、USB硬件的特点及ieee802.11协议传递下来的数据结构定义了参数的格式,并在USB无线网卡通用驱动框架程序中读取、翻译、执行参数文件中的命令。

1.2 论文的主要工作

前文提到通用驱动程序是分为两个部分:内核中的通用驱动框架和存放在用户空间的硬件参数文件。本文主要的工作按照功能模块分为两大部分,内核中的驱动框架编写和定义硬件参数文件格式及参数文件的读取和执行。本文的主要工作可概括为如下几点:

1.首先在探索函数中分配内存空间,并把用户空间的参数文件读入到内存中,按照参数所属的时段生成各个时段的参数链。内核读取文件有自己的特点,这部分主要工作量和难点在于寻找每一段参数并识别出来,分配数据结构并存放。

2.在得到了参数链以后,ieee80211_ops数据结构中的函数成员在执行完了相同部分或者相似部分的处理后,处理自己时段的参数链,参数链中的参数是各个硬件要求的差异处理。普通的驱动程序是把自己的硬件参数编写到驱动程序中去,本文的通用驱动框架程序是把参数从用户空间的参数文件读入到内核的内存中并生成参数链。参数链的功能类似火车的铁轨,先铺好铁路,然后ieee80211_ops中的函数成员就像一辆火车在事先铺好的铁轨上行驶。用参数链这种设计来屏蔽硬件的差异性,即不同的硬件有各自不同的参数链。参数链是属于硬件自己的,你愿意怎么走就怎么走。

3.设计参数链的数据结构及意义,这个数据结构要功能丰富,最好能处理所有的硬件差异。这是本文通用驱动框架程序的核心部分。现在的硬件在配置寄存器的时候有很多分支操作,向一个寄存器写一个固定的值这种方式已经是最平常的了。有好多寄存器的参数值是需要计算的。因此必须在通用驱动框架中设置一个计算器。这个计算器要专门用来计算各个寄存器的参数值、发送接收时的硬件帧头以及驱动程序向上层协议报告的数据结构成员。处于通用框架程序中的这个计算器有自己的特点,在放入计算器栈的各个操作数中,有的是读硬件寄存器的数值、有的是直接从参数文件中读取的、有的是从硬件的EEPROM中读取的(如果硬件有EEPROM)、有的是从某个数据结构中得到的等等。另外有些寄存器要查看某个或者某些寄存器的某种状态才能写入某些值,如果用代码表示就是if{}else{},这当中可能还有嵌套。计算器也要支持这种运算,支持这样的操作,参数文件中的参数就能够代替if else 这种语句了。

4.本文集成了与USB设备的控制端点、中断端点、批量端点通信的系统接口函数。并设计了USB通用驱动框架程序,该程序是驱动的主体程序,它负责接收发送数据,在需要差异的地方调用参数链处理函数。

5.自己封装了一些函数,首先驱动程序是在内核中运行的,因此它的调试特别艰苦,不能单步调试。调试驱动的基本方法就是观察。Linux内核观察打印函数是int printk(const char *fmt, ...),这个函数默认打印到/var/log/目录下的日志文件中去。日志文件中有各种系统运行的信息,而且非常庞大,很难从中找到自己驱动的信息。而且就算把它重定向到控制台,它还有一个弊端,那就是在调试驱动代码的时候很可能刚刚运行,机器就死掉了,在这种情况下,你是很难观察到有用的信息的。因此封装一个打印函数int debut(char *fmt,...);它是向一个固定的文件中写入信息,debout()封装的函数是int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)接口函数。这样做的好处是即使死机了,重启后也还能看到有用的信息。封装的第二个函数是主机和设备的大小端转换的函数,因为有8位、16位、32位的数据,把它们封装成一个void lex_to_cpu(u32 *data,void *tmp,u16 size)和void cpu_to_lex(u32 *data,void *tmp,u16 size)两个函数。封装的第三个函数就是int test_psflag_bit(int i,struct pstack *ps),内部函数是int test_bit (int nr, const volatile void *addr),这个函数只能测试32位数的某个bit位是否为1,封装了一个测试128位的函数。

第2章USB无线网卡驱动的软件及硬件环境

2.1 Linux内核

Linux操作系统把整个机器空间分为用户空间和内核空间。不同级别的程序在各自空间中运行。从功能的角度来看Linux内核,它就是一个庞大的驱动程序。它的任务就是让人们怎样能更好的使用电脑硬件,它是应用程序和硬件之间的纽带,它主要负责管理系统的所有资源。Linux下的驱动程序都是工作在Linux内核中的,Linux操作系统功能模块如图2.1所示。

用户空间应用程序C 库

内核空间

系统调用接口

虚拟文件系统网

各文件子系统

驱动程序

硬件设备

图2.1 Linux操作系统功能模块

Figure 2.1 Linux operating system function module

图2.1中用户空间运行的是各个应用程序的进程,而内核大致划分为四大功能模块:内存管理、进程管理、文件管理、网络系统。内存管理模块负责管理物理内存的分配和回收等。进程管理模块负责管理用户空间应用程序的运行,例如创建进程、给进程分配资源、进程调度、进程间通信等。文件系统负责管理文件及文件目录的创建、删除等等。Linux的文件系统是非常优秀的,Linux的文件系统分为两层:上层是VFS(Virual Filesystem Switch)虚拟文件层[9],其他功能层和文件系统打交道都是向VFS层提出请求;下层是各个具体子文件系统层,例如ntfs(windows NT的文件系统)、nfs(网络文件系统)、ext2和ext3(Linux自身的文件系统)等等。Linux支持众多文件系统,VFS 是个虚拟的文件系统,正因为有它的存在使得系统调用文件的接口得到了统一。当其他

应用程序或者其他功能层调用VFS的接口时,VFS的接口函数调用某个文件子系统的函数,这个文件子系统的函数才是真正的执行读写文件的函数。Linux下所有设备(网络设备除外)都抽象成为一个设备文件[10],字符设备驱动和块设备驱动也是工作在VFS层之下的,当读写一个设备文件时,VFS就调用具体设备的驱动程序的读写函数。这样处理驱动程序的好处是使得接口得到了统一,也使得驱动程序受到了Linux文件系统的保护。而网络驱动工作在协议栈的底层,它和字符和块驱动不同,它没有设备文件。它的调用者是上层网络协议。内核中的网络子系统是负责管理系统的网络连接、网络协议栈的实现等等。图2.1中驱动是和硬件紧密联系在一起的,因为驱动程序在某种情形下有点像个翻译官,把要求设备要做的事告诉设备,把设备的状态告诉上层协议。

在开发驱动程序之前,要做的第一件事情就是打造一个内核树[11]。本文所使用的Linux系统是Fedora11。在安装完毕后,内核是厂商提供的,厂商提供的内核通常会有很多的补丁,或者做了某些优化等等。所以要更换系统的内核。本文使用的内核是Linux-2.6.32版本,内核源代码可以从https://www.sodocs.net/doc/1a7115679.html,/网站上下载。下载完成后解压文件后一般建议放到/usr/src/目录下建立一个Linux-2.6.32目录。因为安装厂商的内核时,源代码也放在这个目录下。拷贝完成后,一般按照如下步骤[12]来处理:

1.进入到源代码目录中,在本文中是cd /usr/src/Linux-

2.6.32,进入到目录后,要先清理一下不必要的文件,运行make clean命令。例如你已经编译过内核,则这一命令将清理一些目标文件。

2.第二步是配置内核,在配置内核时,最主要的是确定CPU的型号。在这个过程中,如果你知道CPU的型号,你可以直接进入到第三步骤,如果不知道,则到系统的/boot 目录下把config文件拷贝到内核源代码目录中,例如运行如下cp /boot/config ./.config命令。注意在内核源代码中拷贝的文件是.config文件,它是个隐藏文件。

3.运行make menuconfig命令来配置内核选项。运行命令后就进入配置界面了,当选中一个配置项后可以有空格键来改变该选项,当该选项前面的尖括号是空的时候,就是不把该选项加入到内核中去,当该选项为*时,是把该选项加入内核中,编译完成后,它和内核是一个整体。当该选项为M时,是把它作为一个编译成一个模块,它和星的区别是它和编译后的内核不是一个整体,当内核用到该模块时,才把它加载到内核中去。进入到配置界面后,就会发现有很多的配置项,例如,CPU类型、USB配置、网络配置等等。可以查一些说明来配置这些选项。本文是把USB和ieee802.11的一般选项都选中了,并且把它们选择为*号,这样做的好处是,当用insmod命令挂载的驱动时候,不用去找支持它的模块了。

4.配置好配置文件后,就开始编译内核了运行make bzImage命令了,这个命令是编译一个大的适合PC机的内核。如果给嵌入式开发板编译内核那就运行make zImage

命令,它编译的是个小内核。完成后运行make modules命令编译选择为模块的部分。编译模块完成后运行make modules install命令,这条命令主要是拷贝模块的可执行代码文件到系统的某一特定目录下(/lib/modules)。

5.最后运行make install命令,这条命令的功能是把编译的新内核及一些文件拷贝到指定的位置。当运行完成make install命令后就可以重启机器了。的新内核就安装上了。这就是所说的构造一棵内核树。

2.2 USB接口

USB(Universal Serial Bus)总线又叫通用串行外部总线,它是20世纪90年代发展起来的。USB接口现在得到了广泛的应用和普及,现在的PC机中都带有大量的USB 接口。它最大的特点就是方便通用、支持热插拔并且可以在一个接口上插上多个设备。当设备用电量小的时候,它还可以充当电源。它的众多优点使得它得到了广泛的应用[13]。在PC机器内部有个USB中央控制器,这个中央控制器负责管理插到USB接口上的设备。当主机要向设备发送或接受数据时,都是向USB中央控制器发出命令[14],USB设备不具备主动与主机通信的能力。编写USB设备驱动不用考虑申请设备地址空间,因为USB中央控制器会给设备分配一个设备号,这个设备号就代表这个设备。

USB设备和USB中央控制器之间的通信是通过端点来完成的。端点的职能有点类似一栋大楼的传达室。例如每个楼层都有一个传达室,当要访问5楼的10号房间时,那就是向5号端点发起对话,并提供偏移量,也就10号房间。USB接口的端点按传输信息的类型分为以下4种[15]:

1.控制端点,主要用来传输控制信息的,例如配置设备时发出的控制信息。控制端点一般都是双向,既可以输入又可以输出。其他端点的输出方向一般是单向的,要么是输入,要么是输出的。这里是站在主机的角度来谈论输入输出的。

2.中断端点,主要用来传输中断信息的,由于USB设备是受USB中央控制器管理的,因此USB设备没有向主机发出中断的能力,并且USB设备不能主动向主机发出请求,只有主机可以向USB设备发出命令请求,因此所谓的中断是指主机周期性的查询USB设备。

3.批量端点,主要用来传输批量信息的,批量信息就意味着大量的信息。U盘一般主要使用的就是批量断点。本文研究的USB无线网卡也是使用批量断点来传输数据的。发送和接收函数都是使用批量端点和USB设备传输数据的。

4.等时端点,主要用来传输等时信息的,主要用于传输实时性要求较高的信息,例如实时的音频、视频等信息。有代表性的USB设备是USB摄像头等。

在一个具体的USB设备中不要求一定都存在这4种类型的端点,例如U盘一般就只有批量端点和控制端点。在Linux内核中用来描述USB设备端点信息的数据结构如下:

struct usb_endpoint_descriptor {

__u8 bLength;

__u8 bDescriptorType;

__u8 bEndpointAddress;

__u8 bmAttributes;

__le16 wMaxPacketSize;

__u8 bInterval;

__u8 bRefresh;

__u8 bSynchAddress;

} __attribute__ ((packed));

成员bLength描述本数据结构共有多少字节,因为后两个成员是针对音频设备的,如果不是音频设备则可以没有后两个成员。成员bDescriptorType是描述本数据结构要描述的类型,这里是描述端点的,在内核中0x05就代表端点。成员bEndpointAddress 包含端点号和输出方向,bits0-bits3表示的是端点号,从这里可以看出一个USB设备最多只能有不超过16个端点,bits8是代表传输方向的,如果该位是1就代表输入,也就是读设备;如果该位为0就代表输出,也就是写设备。成员bmAttributes 表示该端点的类型,如上述的4种类型。成员wMaxPacketSize表示该端点一次可以传输的最多字节数。如果要传输的数据大于这个数字,那就要分多次传输。成员bInterval代表的是该端点希望主机轮询自己的时间间隔,这只是一种希望,具体还要看主机怎么做。该数据结构最后的__attribute__((packed))代表在分配该数据结构时数据成员之间不要为了内存对齐而留下空隙,例如有这样一个数据结构的相邻两个成员类型是u8 和u16,在一般情况下u8后面要空一个字节,然后才是u16成员,如果有上面attribute的要求后,在u8后面就不要留空间,紧接着就是u16成员。在内核中有很多需要访问设备的数据结构都有这样的要求,因为在一个设备中一般没有内存对齐的要求。

下面初步查看一下本文涉及两种硬件信息,本文所使用的USB无线网卡硬件是rt3070和zd1211b两种网卡,当把USB设备插入到USB接口后,进入/proc/bus/usb目录中,运行cat devices命令来查看USB接口上的信息,proc目录中的文件都是无持久文件系统,在这个目录下的文件不是真正存储在硬盘上的,而是系统运行时内存中的信息。图2.2和2.3是rt3070和zd1211b两种硬件的信息。两图最左侧标有C的行代表配置,一个设备允许有多个配置,一个配置又允许有多个接口,一般不同的配置就有不同的功能。标有I的行是描述接口的信息。一个接口就代表一项功能,具有多个接口的设备叫做混合设备,每一个接口就需要有一个自己的驱动程序。例如一个USB键盘带有一个扩音器,这两种功能相差十万八千里,因此各自都要有自己的驱动程序。一个接口又可以包含多个端点。上面的信息中最左侧标有E的行就是描述端点的信息。从图2.2

可以看到rt3070只有一个配置、一个接口、7个端点。端点标号分别从1-6,其中1号端点是输入端点,其他是输出端点,它们的类型都是批量端点。从图 2.3中可以看到zd1211b只有一个配置、一个接口、4个端点,其中端点号1和4是输出端点,2和3号端点是输入端点,1和2号端点是批量端点,3和4是中断端点。

图2.2 rt3070硬件信息

Table 2.2 rt3070 hardware information

图2.3 zd1211b硬件信息

Table 2.3 zd1211b hardware information

图2.2和图2.3中没有描述0号端点,0号端点是一个特殊的端点,每个USB设备都必须有0号端点,0号端点没有自己的端点描述符数据结构。0号端点是属于控制传输端点,因此0号端点是双向的,即可以输入又可以输出。在表2.1和2.2中看到I行中Driver=(none)即表示没有驱动程序支持该设备,那么怎么还能观察到这些设备的信息呢?这就是0号端点的作用。当设备插在主机USB接口上后,主机要探测这个设备,因为每个设备都必须有0号端点,所以探测时期主机都是在和0号端点通信的。图2.2和图2.3中的信息都是从USB标准要求的寄存器或者EEPROM中读到的。Linux提供了访

问控制端口的接口函数int usb_control_msg()和访问其他类型端口函数int usb_submit_urb(),0号端口是控制端口因此它使用usb_control_msg()函数,usb_submit_urb()将在下文介绍。

2.3 Ieee802.11协议层

Ieee802.11协议标准是IEEE(电气和电子工程师协会)开发的无线局域网标准。该标准包括ieee802.11a 、ieee802.11b 、ieee802.11g 、ieee802.11h 及ieee802.11n 等子标准[16]。最常见的无线设备是支持b 、g 协议的设备。802.11b/g 设备使用的是

2.4-2.5GHz 的ISM 频带,ISM(industrial scientific medical)是保留给工业、科学与医疗领域使用的频带,一般不需要授权,是免费使用的[17]。802.11的网络类型基本上就有两种,第一种是没有接入点(通常是路由器)参与的网络叫做点对点的网络,在这种网络中安装了无线设备(无线网卡)的主机只能与无线设备能探测到的主机相互连接通讯。第二种就是有接入点参与的网络,在这种网络中安装了无线设备的主机可以通过接入点和Internet 相连接。本论文所使用的测试网络是第一种,第一种也叫做ad-hc 网络[18]。

802.11使用载波监听多路访问(carrier sense multiple access,简称CSMA )机制来对媒介的访问。由于冲突会浪费传输资源,因此80211使用冲突避免机制CSMA/CA [19]。由于802.11具有无线、移动等特性,它也有自己特有的问题。那就是隐藏主机的问题,如图[20]2.4所示。

图2.4 隐藏主机

Figure 2.4 Hidden Host

在图2.4中主机A 可以直接与主机B 通信,但它探测不到主机C ,同样主机C 可以与B 通信,但探测不到A 。主机B 是可以和A 、C 通信的。这样问题就产生了,A 和C 可能同时向主机B 发送信息,而自认为只有自己在给B 发送信息。而主机B 在同一时间只能接收一个主机的信息,这就是802.11的隐藏节点问题。为了解决这个问题802.11引入了虚拟载波监听技术,它是由网络分配矢量[21](Network Allocation Vector,简称NAV )所提供的。在802.11帧的头部有一个字段Duration 记录本帧要持续的时间,其他主机接收到这个消息后,就把定时器时间设置为这个数,在这段时间中其他主机是不会发送C 可探测的范围 A 可探测的范围 主机A 主机B 主机C

B 可探测的范围

相关主题