分类:
2012-08-20 11:53:55
原文地址:Linux系统下USB驱动入门 作者:xuxiyao8888
USB主要的相关的硬件软件成分:
Transactions generated by the host controller are forwarded to the root hub to
be transmitted to the USB. Consequently, every USB transaction originates at
the root hub. The root hub provides the connection points for USB devices and
performs the following key operations:
• 控制每个端口的电压。
• 使能和停止USb每个端口。
• 确定设备连接到每个端口。
• 设置和报告每个连接的端口的状态。(when polled by host software)
The root hub consists of a hub controller and repeater as illustrated above.
Hub Controller
The hub controller contains a USB interface, or serial interface engine (SIE). It
also contains the descriptors that software reads to identify the device as a hub.
The hub controller gathers hub and port status information also read by the
USB host software to detect the connection and removal of devices and to determine
other status information. The controller also receives commands from host
software to control various aspects of the hub’s operation (e.g., powering and
enabling the ports).
Hub Repeater
Refer to Figure above. Bus traffic arriving at the hub must be forwarded on in
either the upstream (toward the host) or downstream (away from the host)
direction. Transmissions originating at the host will arrive on the hub’s root
port and must be forwarded to all enabled ports. When a target device responds
to a host-initiated transaction, it must transmit a response upstream, which the
hub must forward from the downstream port to the root port.
从我们driver的角度来讲,它也属于一种设备,也要分配相应的地址。它也包含了用于识别设备的描述符,如设备描述符,配置描述符,接口描述符等等。
USB共有四种传输方式,控制传输,等时传输,中断传输,批量传输(他们具体的区别下面会提到)。关于USB带宽的问题只有在等时传输和中断传输中含有。
USB控制器会把一秒钟分成1000份,每份只占1ms,1ms就是一个大包,一个大包有多个小包,所以呢,就在这一毫秒的时间就有可能是多个设备在接
受。这样就会产生一个问题,就是带宽,如音频设备需要的数据流比较稳定,所以在组织一帧的包的时候,首先考虑的是给这样的设备足够的空间,然后会在考虑其
他的设备,当这样的设备多的时候就会产生带宽不足的问题。
The theoretical bandwidth available during each 1ms interval is 12,000 bits/ms,
or 1.5KB/ms (1.5MB/s). However, overhead associated with performing transactions
significantly reduces the efficiency of the bus. Consider the typical overhead
associated with different types of transfers (including worst-case
propagation delay):
• Isochronous transactions = 9 bytes
• Interrupt transactions = 13 bytes (FS) and 19 bytes (LS)
• Bulk transactions = 13 bytes
• Control (3 stage transfer) = 45 bytes (FS) and 63 bytes (LS)
To promote fairness during bandwidth sharing, the specification defines maximum
packet sizes for various types of transfers. In general, isochronous transfers
can have a maximum data payload of 1023 bytes and all others have a
maximum payload of 64 bytes. Bus efficiency when performing transfers with
various packet sizes is listed in follow picture.
Another important aspect of USB performance is the available bandwidth
relative
to the maximum data packet size. For example, while the bus efficiency
is
high for an isochronous transaction with a maximum payload of 1023
bytes, this
transfer takes roughly 87% of the overall bus bandwidth. In contrast, a
single
bulk transaction with a maximum data payload of 64 bytes takes just
over 5% of
the available bandwidth. Thus, when a maximum bandwidth isochronous
transaction is running, the remaining bandwidth permits just two more
maximum-sized bulk transfers. Now imagine a scenario such as the one
illustrated in Figure above. In this example, the bandwidth available
may not be sufficient
to support even the isochronous devices, without regard to the other
devices requiring bus bandwidth.
The USB specification permits up to 90% of the overall bandwidth to be allocated
to periodic transactions (isochronous and interrupt), while control transfers
have a guaranteed reservation for up to 10% of the overall bandwidth. Bulk
transfers simply get the bandwidth that is left over after all of the currently
scheduled transactions complete. Considering the bandwidth limitations, the
number of devices that can be supported adequately by USB 1.x is much lower
than might be expected.
Transactions typically consist of three packets as illustrated follow. However,
a transaction may consist of one, two, or three packets depending on the
type:
below illustrates the basic format of a USB packet. Immediately
preceding
each packet is a synchronization sequence that permits USB devices to
synchronize
to the data rate of the incoming bits within the packet. The type of
packet is
defined by a bit pattern called a packet ID (PID). Following the PID is
packetspecific
information (e.g., an address or data) that varies depending on the
packet type. Finally, each packet ends with a sequence of Cyclic
Redundancy Check (CRC) bits, used to verify correct delivery of the
packet-specific information.The end of each packet is identified by an
end of packet (EOP). Each type of packet is detailed in the following
sections.
• Token Packet — 每一个交换的过程都是以令牌包开始的,令牌包中的信息包含目标设备,终端数量,和方向的数据传输,开始的帧是包含了当前帧的编号,广播给所有的设备。
• Data Packet — The data consists of a data packet that carries the payload
associated with the transfer. A data packet can carry a maximum payload of
1023 bytes of data (isochronous transactions) during a single transaction;
while the other transfer types have maximum data payloads of 64 bytes at
full speed.
• Handshake Packet — 所有的usb传输(除了同步)都是保证数据的正确性的,使用握手数据包来验证是不是成功传输了一个数据,如果数据包传输错误,没与数据包传输给发送者,并标记错误。主机将要求发送者从新发送,直至错误三次。
The format and length of a packet depends on its type. Token packets are all 4
bytes in length, but contain different information that describes some aspect of
the transaction that it defines. Data packets are variable length depending on
the transfer type associated with the transaction. For example, at the data payload
for bulk transfers is limited to 64 bytes during each transaction, while the
data payload limit for isochronous transfers is 1023 bytes.
Token packets define the type of transaction that is to be broadcast over the
USB. All transactions begin with a token packet. Four types of token packets are defined by the USB specification:
• SOF (Start of Frame) — indicates start of the next 1ms frame.
• IN — specifies a USB transaction used to transfer data from a target USB device to the system.
• OUT — specifies a USB transaction used to transfer data from the system to a target USB device.
• SETUP — indicates the start of a control transfer. SETUP is the first
stage of a control transfer and is used to send a request from the
system to the target USB device.
Data packets carry the data payload associated with a given transaction. Direction
of a data packet transfer is specified by the transaction type and may be
used to transfer data either to or from a target USB device as listed in Table below.
Two types of data packets (DATA0 and DATA1) are defined to support synchronization
of long transfers between the sender and receiver. For example, if a
long transfer is being sent from the host to a printer, the transfer will be performed
in small blocks, usually over large number of frames. To verify that a
data transaction is not missed during a long transfer, a technique called data
toggle can be employed.
DATA0 Packet Format:
DATA1 Packet Format:
USB devices use handshake packets to report the completion status of a given
transaction. The receiver of the data payload (either the target device or the root
hub) is responsible for sending a handshake packet back to the sender. Three
possible results can be reported via different handshake packets:
• Acknowledge packet (ACK) — 数据包已经正确传输.
• No Acknowledge packet (NAK) — 向主机报告没有数据接收到或没有数据返回。在中断传输中,没有可用的数据返还给主机。 (i.e., no interrupt request is currently pending).
• Stall packet (STALL) — used by the target to report that it is unable to complete
the transfer and that software intervention will be required for the
device to recover from the stall condition.
Control transfers are used to issue commands (also called requests) to USB
devices. For example, control transfers are performed during USB device configuration
to read the standard descriptors and assign a unique address to a
device. Control transfers always begin with a setup transaction, called the setup
stage. The setup stage defines the nature of the control transfer. Some control
transfers include a data stage consisting of one or more IN or OUT transactions
that are used to deliver the payload of the control transfer. Whether data is sent
to or received from the device is defined by the setup stage. The final stage of a
control transfer is the status stage. This stage confirms that the requested operation
has been completed successfully. Control transfers exist in two basic forms:
• Transfers consisting of a setup stage and status stage.
• Transfers consisting of a setup stage, data stage, and status stage.
packet setup
当鼠标放在Time Stamp的框上时,会跳出一个对话框,如下图所示。
在Time Stamp上显示的数字(如00000.0152
0058)是由三个部分组成的,小数点前面的是秒数,小数点后面的四个数字是uFrameCount,以125uSec的间隔计数,两个frame的
count为0160-0152=8,125uSec×8=1mSec。即USB frame的时间间隔。
由最后的四位数字uFrameOffset可以计算出该包相对于该FRAME的相对时间,计算过程,该包的uFrameCount减去该FRAME
的uFrameCount 然后乘以125uSec 乘以1000 最后加上
16.66(uFrameOffset的计数取样为60MHz,即(1000/60)= 16.66nSec) 乘以
该包的uFrameOffset减去该FRAME的uFrameOffset的差的积,如果uFrameOffset不够减,可以向
uFrameCount借位,7500进制。最后得到的值的单位为nSec。
例如:如下图所示,3526-4025为负值,所以需要借位,((2026-1)-2024)*125*1000 +
((3526+7500)-4025)*(1000/60) = 241683(nSec) =
241.683(uSec).该包相对于sof的时间差为241.683(uSec)
Host software is responsible for detecting and configuring all
devices attached
to the root hub. The process of identifying and configuring a USB
device is commonly
referred to as USB device enumeration. Device enumeration begins at
the root hub. Each hub port must be reset and enabled in turn. When
powered,
the hub determines if a low-, full-, or high-speed device is attached
or no device
at all. If a device is present, status bits within the root hub are set
to reflect
device attachment. Software recognizes that a device is attached,
enables the
port, resets the USB device, assigns a unique address, and completes
the configuration.
This operation is performed for each port until all devices attached to
the root hub have been identified and configured. The following list
specifies actions taken by host software and the root hub when
configuring a device that is connected to a root hub port:
• 如果还没有供电,主机向设备供电。
• Hub探测设备的连接和设备的速度,和设置状态标志位。
• Host polls hub and identifies that a device is attached.
• Host控制设备复位。
• Host checks hub status again if the device originally reported full-speed operation.
This is done to see if the device is now operating at high speed.
• USB device now answers to default address (zero).
• Host performs GetDescriptor requests to fetch the standard descriptors that contain
configuration information. These descriptors are parsed by software to determine the
characteristics of the device. The configuration information includes bus power and bus
bandwidth requirements, and device class information.
• Host assigns unique address to USB device.
• Host verifies that the USB resources needed by the device are available.
• Host发送控制信息,要求得到设备如何使用的详细设备信息。
Default Control Pipe
The default control pipe accesses endpoint zero within each device.
Root Hub Configuration
Host software begins USB device enumeration by configuring the root hub. The
root hub must implement a status change endpoint that can be
used by the hub client to detect status changes pertaining to each port. Once the
hub is configured, software can poll the status change endpoint to detect which
ports currently have devices attached to them.
Bus Bandwidth
Host software must also verify that the bus bandwidth required by the USB
device can be satisfied. Each configuration defines the set of endpoints that
must be accessible by client software. Each endpoint descriptor specifies the
maximum amount of USB bandwidth it requires. If sufficient bandwidth is
available for all endpoints, a communications pipe is setup by software, reserving
the specified bus bandwidth for each device endpoint. After successfully
allocating bandwidth to all endpoints within the device, the device can be configured.
If the bus bandwidth needed is not available, then other configurations are
checked. If every configuration exceeds the bus bandwidth available, the device
is not configured.
Prior to configuring a device, the hub to which the device is attached must have
already been configured and power must be applied to the port. Next, the hub
and configuration software must detect the connected device:
• The hub recognizes that a device has been attached by monitoring the Dand
D+ port signals.
• The hub sets status information for the port indicating device connect and
speed.
• Configuration software reads port status and recognizes that a full-speed
device is connected.
• Software then enables the port so that the hub will pass bus traffic to the
device.
• Configuration software then issues a Reset Port request, forcing the device
into its default state. In the default state the device is unconfigured and
responds only to accesses targeted for device zero and endpoint zero.
Configuration software can now begin the device configuration process. This
process is similar to that used when configuring a hub.
• Host queries device’s control endpoint (zero) at address zero to determine
maximum payload supported by the default pipe.
• Host assigns unique address to USB device.
• Host reads and evaluates configuration information from descriptors.
• Host verifies that the USB resources needed by the device are available.
• Host issues a configuration value to USB device specifying how it’s to be
used. When the configuration value is received, the device assumes its
described characteristics. Device is now ready to be accessed by client software
and can draw the amount of Vbus power described in the configuration.
• Device Descriptor — 关于设备的通用信息,如厂商的ID,产品ID,支持设备的类,子类和适用的协议以及默认端点的最大包的大小。
• Configuration Descriptors — 吃配置中的接口数,支持的挂起和恢复能力,以及功率要求。
• Interface Descriptors — 接口类,子类和适用的协议,接口备用配置的数目和端点数。
• Endpoint Descriptors — 端点地址,方向和类型,支持的最大包的大小,如果是中断类型的端点则还包含轮询的频率。
• String Descriptors — 在其他描述符中会为某些字段提供字符串索引,他们可以被用来检索描述性字符串,可以以多种语言形式提供。
• Class-Specific Descriptors — a given device class may require additional
descriptors as defined by a particular device class specification.
for example:
Hub Class-Specific Reset Port Request:
Once the hub client has detected the device, it must issue a port reset request,
and when this happens, the attached device is reset. Port reset is accomplished
via a control transfer delivered to the hub, called SetPortFeature. The format of
the 8-byte setup transaction is shown in Table below.
发送过程如下:
然后程序根据上表的格式发送一个命令:
static int set_port_feature(struct usb_device *hdev, int port1, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1, //USB_REQ_SET_FEATURE = 0x03
//USB_RT_PORT = 00100011B; feature = 0x4
NULL, 0, 1000);
}
命令的结构体为:
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__ ((packed));
定义变量,给变量赋值,发送出去:
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
__u8 requesttype, __u16 value, __u16 index, void *data,
__u16 size, int timeout)
{
…………
struct usb_ctrlrequest *dr;
dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16p(&value);
dr->wIndex = cpu_to_le16p(&index);
dr->wLength = cpu_to_le16p(&size);
ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
//(在函数usb_internal_control_msg里,申请了一个urb内存空间,然后根据需要填充,
//最后由usb_submit_urb向USB核心子系统提交一个异步请求,添加到发送队列里)
………………
usb规范中规定的标准概念由Linux USB core 来实现处理。
端点endpoint:
端点是USB总线传输最基本的概念,一个端点可以单方向传输数据。可以把端点看作是一个单方向的管道。
接口interfaces:
若干端点可以捆绑起来,成为一个端口,端口可以作为完整的逻辑设备连接,例如鼠标设备,键盘设备。
需要指出的是,一个硬件设备可以包含多个逻辑设备。
接口可以有多个预设值,用来指定不同的参数。
配置configurations:
接口捆绑起来形成配置,一个usb设备可以在不同的配置之间切换,一次只能激活一个配置。
可结合下图.
在Linux的USB内核子系统中,提供了几个与设备驱动开发密切相关的数据结构,它们在实现USB 的体系结构、完成USB设备的即插即用、构建驱动程序的框架方面都起着灵魂的作用。
struct usb_driver是对USB 设备的最高层次的抽象。这个结构用于向USBD层注册USB
设备驱动程序。总线上有设备接入的时候,USBD通过该结构查找相关的设备驱动程序,而对于断开操作,USBD同样通过这个结构来断开设备与驱动的连接。
与其它驱动结构最大的不同就在于它指向probe和disconnect 的指针,当驱动正确安装以后,如果相应的USB
设备接入主机,系统自动调用probe进行探测,设备卸载时disconnect函数被调用。这2个函数作为USB
设备安装和卸载的入口点,保证了USB 设备的即插即用。下面给出一个在系统中注册的usb_driver结构:
static struct usb_driver d12_usb_driver = {
name : "d12usb", //驱动名字
probe : d12_usb_probe, //探测函数进入指针
disconnect : d12_usb_disconnect, //撤销函数进入指针
fops : &d12_fops, //设备的操作列表指针
minor :192, //次设备号必须为16的倍数。
//主设备号可以通过cat /proc/device可以看到,180:usb,189:usb device
id_table : &d12_usb_id, //描述该驱动所适用设备信息的指针,包含着厂商的ID号和设备的ID号。
};
struct usb_device是对系统中所有USB设备的抽象,这个数据结构不仅包含了USB设备必要的硬件信息,而且据此可以了解到USB设备具体的配置信息。 USB标准中以层次化的结构定义设备的描述符。一个USB设备只能有一个设备描述符,内容直接由具体的硬件提供,但是却可以有多个配置描述符,每个配置描 述符又由一个或多个接口描述符以及相应的端点描述符构成。Linux中的USB核心子系统通过几个数据结构之间的对应关系充分体现了这种层次化的结构。具 体如下图对比所示。
USB信息传输包含4种传输类型:控制传输,等时传输,中断传输,批量传输。为了给设备驱动完成USB通信提供统一的接口,USB设备驱动与
USBD,以及USBD与HCD之间的数据传输都是通过数据结构URB来实现的。因此URB中包含了数据传输在各个层次中的必要信息,下面列出结构中的部
分定义,其中的pipe参数代表了进行传输的逻辑通道,直接反映了该URB所发生的数据端点,以及传输类型。
typedef struct urb{ …
struct usb_device *dev; //请求的设备
unsigned int pipe; //传输管道
int status; //返回状态
unsigned int transfer_flags; //传输标志
void *transfer_buffer; //传输数据
int transfer_buffer_length; //传输数据长度
int actual_length; //实际长度
int timeout; //超时期限
… }
对于这个结构的处理通常由4个函数来进行:
(1)purb_t usb_alloc_urb(int iso_packets) 为USB传输分配URB结构,参数iso_packets是用于等时传输的数据包数目,对于其他传输该参数为0。
(2)void usb_free-urb(purb_t purb) 释放URB数据结构。
(3)int usb_submit_urb(purb_t purb) 用于向USB核心子系统提交一个异步请求。
(4)int usb_unlink_urb(purb_t purb) 在URB没有处理之前,通过这个函数取消相关的数据处理。
USBD层为USB设备驱动提供了统一接口的API,方便了用户自己编写适合的驱动程序。
为了实现USB设备即插即用的特性,所有的USB设备驱动都要在USBD中注册或注销。具体由函数usb_register和
usb_deregister来实现。当驱动程序调用int usb_register(struct usb_driver
*new_driver)时,系统将这个新的驱动程序加入驱动链表(usb_driver_list)的尾部完成注册,同时扫描总线上的所有设备,与驱动
程序关联。注销函数的功能与此刚好相反,usb_deregister()关闭设备,撤销为设备在内核中分配的一切资源,然后把驱动结构从驱动链表中摘
除。
使用实例如下所示:
int init_module(void)
{
if(usb_register(&d12_usb_driver)<0){
printk("unable to register device !\n");
return -1;
}
return 0;
}
USB协议定义了一系列的标准设备请求用来完成USB设备的枚举、配置等操作。USB设备以缺省的控制管道响应主机的请求。USBD提供了部分接口
函数支持USB标准请求,其余的控制传输由函数usb_control_msg完成。表1列出了USB设备请求与对应的接口函数。下表描述标准设备请求接
口:
USBD提供了3种用于数据传输的接口:usb_control_msg
(用于控制传输);usb_bulk_msg(用于批量传输);直接提交URB。但其实在usb_control_msg()、
usb_bulk_msg()内部,也是由提交URB
来完成的,只不过填充请求的工作由系统来完成。以批量传输为例介绍USB设备读写模块的设计与具体实现。
static int usb_write(struct file * file, char * buf, size_t count, loff_t *ppos)
{ int this_write;
int partial;//实际写的长度
int result;//操作结果
if(device_plug_1==0){
printk(“No device in!\n”);
return -1;
}
while(count>0){
this_write = (count >= OBUF_SIZE)?OBUFSIZE :count
result=usb_bulk_msg(d12->dev, usb_sndbulkpipe(d12-> dev,2),d12->obuf,
this_write , HZ*TIMEOUT);
…//根据result的结果进行相应处理
if(partial != thiswrite) {…}
//判断是否成功写入,并进行相应的处理
…}//end while
return 1;
}
用户调用标准接口usb_bulk_msg完成批量传输。填充好相应的URB结构后,进入下面的调用序列——usb_bulk_msg()
> usb_start_wait_urb() > usb_submit_urb() > uhci_submit_urb()
>
uhci_submit_bulk()——USB控制器把具体的请求转化为交互队列(假设USB驱动采用UHCI层面)根据总线时间、带宽、传输类型等综
合因素调度队列,执行相应的总线动作与设备进行交互,完成通信任务。下图给出了USB设备与主机的通信模型。
USB设备之所以可以即插即用,就是因为USB内核子系统即时对总线反馈的设备状态做出相应的处理。相应地在设备驱动方面也要提供probe和disconnect函数对设备进行初始化和断开操作。
USB设备接入主机后,主机通过总线枚举来识别和管理必要的设备状态变化。首先检测设备在总线上的上拉电阻判断是否有新设备连接,并获悉该设备是全速设备
还是低速设备,然后主机向该端口发送一个复位信号。设备只有在收到这个复位信号后,才能对总线的处理做出响应。此时设备采用的是默认地址(00H),主机
接收到设备对默认地址(00H)的响应,就为设备分配一个空闲的地址,以后设备就只对这个地址进行响应。接下来,主机读取USB设备描述符,确认USB设
备的属性。根据读取的设备描述符对设备进行配置,设备如果可以达到要求就发送配置完毕的信号给主机。然后调用设备驱动的probe函数对设备进行初始化。
下面给出一个简单的probe函数的写法。
static void *naked_usb_probe(struct usb_interface *intf, struct usb_device_id *id)
{//检查硬件定义与驱动是否相符
#if 0
if(dev->descriptor.idVendor==0x0471 && dev->descriptor. idProduct == 0x0222)
{
device_plug_in = 1;//设备插入标志
//初始化设备相关资源
if(d12->obuf=(char*)kmalloc(OBUF_SIZE,GFP_KERNEL)){…}
d12->dev=dev;
…
printk("My usb device pluged in.\n");
return ;
}
#endif
if (usb_usual_check_type(id, USB_US_TYPE_STOR))
return -ENXIO;
}
USB设备卸载的时候,将释放HCD层为该设备分配的资源,调用设备驱动的disconnect函数断开与设备的连接。
在2.4内核中,虽然引进了devfs设备文件系统,但是对设备的管理主要还是采用主、次设备号的方法。为了使设备在系统中可以被应用程序访问,必 须建立一个设备文件节点。可以通过“mknod /dev/usb d12usb c 180 192”命令添加自己设备的节点,相对地在应用程序中通过系统调用open(“/dev/usb/d12usb”,O_RDWR)打开设备,之后就可以根 据需要对设备进行读写操作。
Linux下USB驱动函数快速参考
#include
所有和 USB 相关的头文件. 它必须被所有的 USB 设备驱动包含.
struct usb_driver;
描述 USB 驱动的结构.
struct usb_device_id;
描述这个驱动支持的 USB 设备的结构.
int usb_register(struct usb_driver *d);
用来从USB核心注册和注销一个 USB 驱动的函数.
struct usb_device *interface_to_usbdev(struct usb_interface *intf);
从 struct usb_interface 获取控制 struct usb_device *.
#define interface_to_usbdev(intf) \
container_of(intf->dev.parent, struct usb_device, dev)
struct usb_device;
控制完整 USB 设备的结构.
struct usb_interface;
主 USB 设备结构, 所有的 USB 驱动用来和 USB 核心通讯的.
static inline void usb_set_intfdata(struct usb_interface *intf, void *data);
static inline void *usb_get_intfdata(struct usb_interface *intf)
{.... return dev->driver_data; ....}
设置和获取在 struct usb_interface 中的私有数据指针部分的函数.
struct usb_class_driver;
描述 USB 驱动的一个结构, 这个驱动要使用 USB 主编号来和用户空间程序通讯.
int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver);
void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver);
用来注册和注销一个特定 struct usb_interface * 结构到 struct usb_class_driver 结构的函数.
struct urb;
描述一个 USB 数据传输的结构.
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
void usb_free_urb(struct urb *urb);
用来创建和销毁一个 struct usb urb*的函数.
int usb_submit_urb(struct urb *urb, int mem_flags);
int usb_kill_urb(struct urb *urb);
int usb_unlink_urb(struct urb *urb);
用来启动和停止一个 USB 数据传输的函数.
对usb_unlink_urb而言,如果urb结构体中的URB_ASYNC_UNLINK(即异步unlink)的标志被置位,则对该urb的usb_unlink_urb()调用将立即返回,具体的unlink动作将在后台进行,否则,此函数一直等到urb被解开连接或结束时才返回。usb_kill_urb()会彻底终止urb的生命周期,它通常是在设备的disconnect()函数中被调用。
void usb_fill_int_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void
*transfer_buffer, int buffer_length, usb_complete_t complete, void *context, int interval);
void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void
*transfer_buffer, int buffer_length, usb_complete_t complete, void *context);
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
unsigned char *setup_packet, void *transfer_buffer, int buffer_ length, usb_complete_t
complete, void *context);
用来在被提交给 USB 核心之前初始化一个 struct urb 的函数.
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int
*actual_length, int timeout);
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8
requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
用来发送和接受 USB 数据的函数, 不必使用一个 struct urb.
在USB的数据传送的方式下,有四种的传输方式:控制(Control)同步(isochronous)中断(interrupt)大量
(bulk)。如果你是从硬件开始来设计整个的系统,你还要正确选择传送的方式,而作为一个驱动程序的书写者,就只需要弄清楚他是采用的什么工作方式就行
了。
通常所有的传送方式下的主动权都在host边。
控制(Control)方式传送:控制传送是双向传送,数据量通常较小。USB系统软件用来主要进行查询、配置和给USB设备发送通用的命令。控制传送方
式可以包括8、16、32和64字节的数据,这依赖于设备和传输速度。控制传输典型地用在主计算机和USB外设之间的端点(Endpoint)0之间的传
输,但是指定供应商的控制传输可能用到其它的端点。
同步(isochronous)方式传送:同步传输提供了确定的带宽和间隔时间(latency)。它被用于时间严格并具有较强容错性的流
数据传输,或者用于要求恒定的数据传送率的即时应用中。例如执行即时通话的网络电话应用时,使用同步传输模式是很好的选择。同步数据要求确定的带宽值和确
定的最大传送次数。对于同步传送来说,即时的数据传递比完美的精度和数据的完整性更重要一些。
中断(interrupt)方式传送:中断方式传输主要用于定时查询设备是否有中断数据要传送。设备的端点模式器的结构决定了它的查询频
率,从1到255ms之间。这种传输方式典型的应用在少量的分散的、不可预测数据的传输。键盘、操纵杆和鼠标就属于这一类型。中断方式传送是单向的并且对
于host来说只有输入的方式。
大量(bulk)传送:主要应用在数据大量传送传送和接受数据上,同时又没有带宽和间隔时间要求的情况下,要求保证传输。打印机和扫描仪属于这种类型。这种类型的设备适合于传输非常慢和大量被延迟的传输,可以等到所有其它类型的数据的传送完成之后再传送和接收数据。
USB将其有效的带宽分成各个不同的桢(frame),每桢通常是1ms时间长。每个设备每桢只能传送一个同步的传送包。在完成了系统的配
置信息和连接之后,USB的host就会对不同的传送点和传送方式做一个统筹安排,用来适应整个的USB的带宽。通常情况下,同步方式和中断方式的传送会
占据整个带宽的90%,剩下的就安排给控制方式传送数据。
驱动编程上的区别:
使用usb_alloc_urb创建号urb后可使用系统提供的函数初始化:
1. usb_fill_int_urb是用于初始化中断urb:
static inline void usb_fill_int_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context,
int interval)
{
urb->dev = dev;
urb->pipe = pipe;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = buffer_length;
urb->complete = complete_fn;
urb->context = context;
if (dev->speed == USB_SPEED_HIGH)
urb->interval = 1 << (interval - 1);
else
urb->interval = interval;
urb->start_frame = -1;
}
dev指向这个urb要发送的设备;pipe是这个urb要发送的usb设备的特定端点;transfer_buffer是指向发送数据或
接受数据的缓冲区指针,和urb一样它也不能是静态缓冲区,必须使用kmalloc()来分配,buffer_length是
transfer_buffer指针所指向缓冲区的大小;complete指针指向当这个urb完成时被调用的完成处理函数,context是完成处理函
数的“上下文”;interval是这个urb应当被调度的时间间隔。
上述函数参数中的pipe使用usb_sndintpipe()或usb_rcvintpipe()创建。
2. usb_fill_bulk_urb是用于初始化批量urb:
static inline void usb_fill_bulk_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context)
{
urb->dev = dev;
urb->pipe = pipe;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = buffer_length;
urb->complete = complete_fn;
urb->context = context;
}
除了没有对应的调度时间间隔的interval参数以外,该函数的参数和usb_fill_int_urb()函数的参数含义相同。
上述函数参数中的pipe使用usb_sndbulkpipe()或usb_rcvbulkpipe()创建。
3. usb_fill_control_urb是用于初始化控制urb:
static inline void usb_fill_control_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
unsigned char *setup_packet,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context)
{
urb->dev = dev;
urb->pipe = pipe;
urb->setup_packet = setup_packet;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = buffer_length;
urb->complete = complete_fn;
urb->context = context;
}
除了增加了新的setup_packet参数以外,该函数的参数和usb_fill_bulk_urb()函数是的参数含义是相同的,setup_packet参数是指向即将被发送到端点的设置数据包。
上述函数参数中的pipe使用usb_sndctrlpipe()或usb_rcvctrlpipe()创建。
4. 等时urb没有像中断那样子的初始化函数,我们只能手动的初始化urb,而后才能提交给usb核心。(可参考drivers/media/video/usbvideo/usbvideo.c中的1767~1783行,(linux_kernel_2.6.26)
urb 处理流程:
1. 我们通过cat /proc/bus/usb/devices得到当前系统探测到的USB总线上的设备信息。它包括Vendor、ProdID、Product等。下面是我是插入一个hub后的信息片断:
T: Bus=03 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 2 Spd=480 MxCh= 4
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=058f ProdID=6254 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
2. 厂商的ID号也可以通过lsusb命令获取:
Bus 001 Device 001: ID 0000:0000
Bus 003 Device 002: ID 058f:6254 Alcor Micro Corp.
Bus 003 Device 001: ID 0000:0000
Bus 002 Device 001: ID 0000:0000
3. lspci查看PCI插槽信息
00:03.0 USB Controller: Silicon Integrated Systems [SiS] USB 1.0 Controller (rev 0f)
00:03.1 USB Controller: Silicon Integrated Systems [SiS] USB 1.0 Controller (rev 0f)
00:03.3 USB Controller: Silicon Integrated Systems [SiS] USB 2.0 Controller
4. 在有些板子上没有上述命令或上述文件,也可以通过/sys/bus/usb/devices 中的文件来分析:
当在板子上插上一个hub时,会在/sys/bus/usb/devices文件夹下多出一个目录1-1,在这个目录下包含了该hub的所有信息。
如:厂商ID和产品ID
cat idProduct idVendor
6254
058f