11. 1.0.5 关于描述符 对 1.0.2 的补充描述
概述: USB devices report their attributes using descriptors. A
descriptor is a data structure with a defined format.Each
descriptor begins with a byte-wide field that contains the total
number of bytes in the descriptor followed by a byte-wide field
that identifies the descriptor type.
设备描述符: A device descriptor describes general information
about a USB device. It includes information that applies globally
to the device and all of the device’s configurations. A USB
device has only one device descriptor.
配置描述符: The configuration descriptor describes information
about a specific device configuration.
接口描述符: The interface descriptor describes a specific
interface within a configuration. A configuration provides one or
more interfaces, each with zero or more endpoint descriptors
describing a unique set of endpoints within the configuration.
端点描述符: This descriptor contains the information required by
the host to determine the bandwidth requirements of each
endpoint
还有一个字符串描述符 不重要
这些描述符存储在什么地方呢?如何报告给主机呢?这是一个什么过程呢?
简单描述下 u 盘的存储 eeprom flash 单片机
13. 1.1 关于 usb 设备的 request 命令
This bitmapped field identifies the
characteristics of the specific request.
This field specifies the
particular request
这三个域根据不同的
命令而定
比如 get_address
set_address
方向是不同的
16. 1.2.0 逻辑通信和物理通信 对 1.2 的补充
Usb 协议中说:
A USB logical device appears to the USB system as a
collection of endpoints. Endpoints are grouped into endpoint
sets that implement an interface. Interfaces are views to the
function. The USB System Software manages the device
using the Default Control Pipe. Client software manages an
interface using pipe bundles (associated with an endpoint
set). Client software requests that data be moved across the
USB between a buffer on the host and an endpoint on the
USB device. The Host Controller (or USB device, depending
on transfer direction) packetizes the data to move it over the
USB. The Host Controller also coordinates when bus access
is used to move the packet of data over the USB.
19. 1.3.1 对 1.3 事物,传输,帧,包的祥解
Usb 协议中规定传输方式:控制传输,批量传输,同步传输,中
断传输
传输可以由一个或多个事物构成。控制传输: setup 事物,可选
数据阶段,状态阶段。批量传输:一个或多个 in 事物或者 out 事
物。
事物是不能被中断的,否则会 conflict 。事物由令牌包,数据包
,状态包组成。 In 事物, out 事物, setup 事物。事物的传输只
能由主机发起 (otg 设备除外 ) ,还有远程唤醒是设备能唯一主动
发起的,比如 usb 键盘可以在电脑休眠时唤醒它
The Host Controller produces SOF tokens at a period of 1ms. 协
议中说主控 1ms 发送一帧。但是现在高速主控每 1/8ms 发送一
帧。
包包括令牌包,数据包,状态包,帧起始包等。组成:同步域,
pid 域, address 域, endpoint 域, crc 域,帧号域
20. 1.3.1.0 usb 事物 对 1.3.1 的补充
事物细节在传输那边讲述
控制传输和批量传输
协议中说
The packets that comprise a transaction
varies depending on the endpoint type.
There are four endpoint types: bulk,
control, interrupt, and isochronous.
21. 1.3.1.1 us 4 种传输方式 对 1.3.1 的补充
控制传输
Control transfers are intended to support configuration/ command/
status type communication flows between client software and its
function. A control transfer is composed of a Setup bus transaction
moving request information from host to function,zero or more Data
transactions sending data in the direction indicated by the Setup
transaction, and a Status transaction returning status information
from function to host.
批量传输
The bulk transfer type is designed to support devices that need to
communicate relatively large amounts of data at highly variable times where
the transfer can use any available bandwidth
同步传输
为实时传输准备的
中断传输
不是我们通常所说的中断 而是每隔一段时间主机询问设备有没有数据 如 usb 鼠标
通过 default pipe 来进行
主要讲述
这两个, u
盘传输只用
这两个
22. Control transfers setup stage
Control tansfers data stage
Control transfer status stage
数据阶段不是每个控制传输都有的,举例
Set address 命令, get descriptor 会有 dat
阶段
1.3.1.2
控制传输分析
(setup 事物
in 事物
out 事物 )
对 1.3.1 补充
Usb 协议规定的命
令格式如:
Get Status ,
Set address 等
事物讲述 传输是多个事物的集合
23. 1.3.1.3 批量传输分析 ( 本质是 in 事物和 out 事物 ) 对
1.3.1 补充
这个图只列出了具有
一个事物的批量传输
24. 1.3.1.4 关于包的分析
其实每个包的前面都应该有同步域 sync why ?异步传输和同步传输的不同是因为使用不同的
时钟,所以要同步。还有帧起始包 SOF 。
还有一个 PRE 包,这个包是告诉 hub ,接下来的包是发给低速设备的, pre 包是发给 hub 的
其它 usb 设备会忽略它。关于 pre ,协议中说 :
All downstream packets transmitted to low-speed devices require a preamble. The
preamble consists of a SYNC followed by a PRE PID, both sent at full-speed.
现在 2.0 的协议还有很多其它的包
30. 1.4.1.2BULK 命令字
Bulk 还支持两个命令字和 usb 协议中的命令字一样,
前提是外设可以识别这两个命令:
Bulk Reset :软件层面的复位,协议中说: bulk
reset 使外设恢复到能准确接收下一个 CBW 的状
态
Get Max Lun :如果给 u 盘发这个命令返回值为 0.
如果 u 盘固件识别这个命令。
For Reset Recovery the host shall issue in the
following order: :
(a) a Bulk-Only Mass Storage Reset
(b) a Clear Feature HALT to the Bulk-In endpoint
(c) a Clear Feature HALT to the Bulk-Out endpoint
31. 1.5 u 盘 主机是怎么知道设备的 是如何通信的
把 u 盘插上的那一刻,到 u 盘开始工作
是怎样一个过程呢,主机是如何知道
usb 设备已经插到电脑上了呢,又是如
何知道 usb 设备已经不存在了呢,主机
又是如何开始与 usb 设备进行通讯的呢
,带着这些疑问开始这节的讲述
41. 2.0.1 注册 usb
设备驱动
所有的 usb 设备驱动都必须有
一个 struct usb_driver 的结构体
。
struct usb_driver {
const char *name;
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
int (*ioctl) (struct usb_interface *intf, unsigned int code,
void *buf);
int (*suspend) (struct usb_interface *intf, pm_message_t
message);
int (*resume) (struct usb_interface *intf);
int (*reset_resume)(struct usb_interface *intf);
int (*pre_reset)(struct usb_interface *intf);
int (*post_reset)(struct usb_interface *intf);
const struct usb_device_id *id_table;
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int soft_unbind:1;
};
42. 2.0.1.0 对 2.1.0 部分成员描述 来自内核代码
@name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular
* interface on a device. If it is, probe returns zero and uses
* usb_set_intfdata() to associate driver-specific data with the
* interface. It may also use usb_set_interface() to specify the
* appropriate altsetting. If unwilling to manage the interface,
* return -ENODEV, if genuine IO errors occured, an appropriate
* negative errno value.
* @disconnect: Called when the interface is no longer accessible, usually
* because its device has been (or is being) disconnected or the
* driver module is being unloaded.
* @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem.
* @suspend: Called when the device is going to be suspended by the
system.
* @resume: Called when the device is being resumed by the system.
* @supports_autosuspend: if set to 0, the USB core will not allow
autosuspend for interfaces bound to this driver.
44. 2.0.2 驱动中结构体的分析 ( 一 )
struct usb_skel {
struct usb_device *udev;
struct usb_interface *interface;
unsigned char *bulk_buffer; /* the buffer to receive send data */
size_t bulk_size; /* the size of the receive send buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
int errors; /* the last request tanked */
int open_count; /* count the number of openers */
spinlock_t err_lock; /* lock for errors */
struct kref kref;
struct mutex io_mutex; /* synchronize I/O with disconnect */
atomic_t skel_available; /* 只允许应用打开设备一次 */
};
在 linux 代码骨架代码中解释是 Structure to hold all of our device specific stuff
这个结构体是驱动程序的编写者自己定义的 ,但是有一个成员是必须有的 struct
usb_device *udev ; 因为这是 usb 设备驱动 ,没它,这个驱动还有什么意义。
45. 2.0.3 驱动中结构体的分析 ( 二 )
static const struct file_operations skel_fops = {
.owner = THIS_MODULE,
.read = skel_read,
.write = skel_write,
.open = skel_open,
.ioctl = skel_ioctl,
.release = skel_release,
.flush = skel_flush,
};// 这个结构体定义对设备进行操作的函数 一切都是文件 (linux
中 )
static struct usb_class_driver skel_class = {
.name = “udisk%d",
.fops = &skel_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};//identifies a USB driver that wants to use the USB major
number (我觉的这个是给 udev 用的 猜测)
46. 2.0.3.0 补充 2.0.3 结构体分析
identifies a USB driver that wants to use the USB major number
内核中这样说的。那么从另一个层面我们就会知道有的 usb 驱动
不会是用 usb 主设备号,那这就会给人带来疑问? Linux 把一切
都当作文件来操作,设备在 linux 中表示为设备文件每个设备文
件都由主设备号和次设备号来唯一确定一个设备,没有主设备
号??这是因为有的 usb 设备驱动会挂接在其它的驱动下。拿我
们的 u 盘为例:如果你的 linux 内核中编译了 usb mass storage
驱动和 scsi 驱动,那么 u 盘在 /dev 目录下会显示 sda* 也就说 u
盘被模拟为一个 scsi 设备,这当然就不用 usb 主设备号了,看看
usb mass storage 驱动你肯定找不到用 struct usb_class_driver
定义的结构体。还有的 usb 设备驱动会挂接在 input 驱动上,也
不会使用 usb 主设备号。
如果你的驱动只是一个单纯的 usb 驱动,不挂接其他的驱动,用这
个结构体定义一个变量,并且向 usb core 进行注册是必须 DI 。
50. 2.0.4 不使用 urb 的 usb 传输
在 linux usb 设备驱动层 如果采用同步传
输
核心函数是:
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, __index, void *data, __u16 size, int timeout);
这里说的不使用并不是真的不使用 只不过不需要驱动编
写者来操作 urb
Cscope
51. 2.0.4.0 usb_bulk_msg 解析
注释中说: Builds a bulk urb, sends it off and waits
for completion
This function sends a simple bulk message to a
specified endpoint and waits for the message to
complete, or timeout. This function sends a simple
bulk message to a specified endpoint and waits for
the message to complete, or timeout.
我们要实现对 u 盘的读取或写入如果以同步方式来实
现,就需要执行 3 次 usb_bulk_msg() ,分别完成
CBW, DATA in or out , CSW 的传输。
注:以这种方式实现可能会对系统性能产生影响,并
且会容易宕机,但是我在用异步实现写的时候也没少
宕机过。主要还是看代码的编写问题。还有涉及 dma
的问题 。一点个人看法。
53. 2.0.4.1usb_control_msg
usb_control_msg - Builds a control urb,
sends it off and waits for completion.
This function sends a simple control message
to a specified endpoint and waits for the
message to complete, or timeout.
和 usb_bulk_msg 中的注解基本相同,但是这
个函数在给 u 盘发送控制请求时比驱动开发人
员自己分配 urb 然后初始化方便的多,也不容
易出错
图片中有实际的物理通信流 也有逻辑通信流, usb 设备驱动层其实处理的是最上层,处理接口之间的通信。 图中的管道 pipe :有两种一种是消息管道,一种流管道。消息管道指的 usb 协议中规定好了格式,其中传输的数据必须是 usb 协议规定的格式才能被接收方所解析。 协议中说: Stream: Data moving through a pipe has no USB-defined structure Message: Data moving through a pipe has some USB-defined structure. 控制传输需要的