标题:
Linux那些事儿 之 戏说USB(19)设备
[打印本页]
作者:
bingchentiao
时间:
2013-5-22 10:01
标题:
Linux那些事儿 之 戏说USB(19)设备
第一眼看到
struct
usb_device
这个结构,我仿佛置身于衡山路的酒吧里,盯着舞池里扭动的符号,眼神迷离。
交大里苟了几年,毕业了又是住在学校附近的徐虹北路上,沿着虹桥路走过去,到徐家汇不过
10
多分钟,再溜达几步就可以到衡山路。学校里睡的就比较晚,毕业了仍然一样,其它好习惯还是坏习惯扔掉了不少,就这个保持的还不错,于是经常穷极无聊的晚上,只好和同学沿着虹桥路也好,沿着番愚路再走到广元路或淮海路也好,慢慢的向东走。走着走着就会到衡山路,有时遇到许多老年人在衡山电影院对面的小广场上跳各种各样的舞,就会在旁边一曲一曲的看,感慨咱们爬到
60
岁,爬到那般年纪是否会有那样的乐趣。有时想疯了,就会到旁边的酒吧坐坐,麻醉一下别人眼里的自己。有时只是在旁边儿安静的巷子里四处走走。
衡山路的夜晚杂乱而又冗长,
struct
usb_device
结构冗长而又杂乱。衡山路还是会去,
struct
usb_device
还是得说。
328
/*
329
* struct usb_device - kernel's representation of a USB device
330
*
331
* FIXME: Write the kerneldoc!
332
*
333
* Usbcore drivers should not set usbdev->state directly. Instead use
334
* usb_set_device_state().
335
*/
336
struct
usb_device
{
337
int devnum; /* Address on USB bus */
338
char devpath [16]; /* Use in messages: /port/port/... */
339
enum
usb_device_state
state
; /* configured, not attached, etc */
340
enum
usb_device_speed
speed
; /* high/full/low (or error) */
341
342
struct
usb_tt
*tt; /* low/full speed dev, highspeed hub */
343
int ttport; /* device port on that tt hub */
344
345
unsigned int
toggle
[2]; /* one bit for each endpoint
346
* ([0] = IN, [1] = OUT) */
347
348
struct
usb_device
*
parent
; /* our hub, unless we're the root */
349
struct
usb_bus
*
bus
; /* Bus we're part of */
350
struct
usb_host_endpoint
ep0;
351
352
struct
device
dev
; /* Generic device interface */
353
354
struct
usb_device_descriptor
descriptor
;/* Descriptor */
355
struct
usb_host_config
*
config
; /* All of the configs */
356
357
struct
usb_host_config
*actconfig;/* the active configuration */
358
struct
usb_host_endpoint
*ep_in[16];
359
struct
usb_host_endpoint
*ep_out[16];
360
361
char **rawdescriptors; /* Raw descriptors for each config */
362
363
unsigned short bus_mA; /* Current available from the bus */
364
u8
portnum; /* Parent port number (origin 1) */
365
u8
level; /* Number of USB hub ancestors */
366
367
unsigned discon_suspended:1; /* Disconnected while suspended */
368
unsigned have_langid:1; /* whether string_langid is valid */
369
int string_langid; /* language ID for strings */
370
371
/* static strings from the device */
372
char *
product
; /* iProduct string, if present */
373
char *
manufacturer
; /* iManufacturer string, if present */
374
char *
serial
; /* iSerialNumber string, if present */
375
376
struct
list_head
filelist;
377
#ifdef CONFIG_USB_DEVICE_CLASS
378
struct
device
*usb_classdev;
379
#endif
380
#ifdef CONFIG_USB_DEVICEFS
381
struct
dentry
*usbfs_dentry; /* usbfs dentry entry for the device */
382
#endif
383
/*
384
* Child devices - these can be either new devices
385
* (if this is a hub device), or different instances
386
* of this same device.
387
*
388
* Each instance needs its own set of data structures.
389
*/
390
391
int maxchild; /* Number of ports if hub */
392
struct
usb_device
*children[
USB_MAXCHILDREN
];
393
394
int pm_usage_cnt; /* usage counter for autosuspend */
395
u32
quirks
; /* quirks of the whole device */
396
397
#ifdef
CONFIG_PM
398
struct
delayed_work
autosuspend; /* for delayed autosuspends */
399
struct
mutex
pm_mutex
; /* protects PM operations */
400
401
unsigned long last_busy; /* time of last use */
402
int autosuspend_delay; /* in jiffies */
403
404
unsigned auto_pm:1; /* autosuspend/resume in progress */
405
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
406
unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
407
unsigned autoresume_disabled:1; /* disabled by the user */
408
#endif
409
};
337
行,
devnum
,设备的地址。此地址非彼地址,和咱们写程序时说的地址是不一样的,
devnum
只是
usb
设备在一条
usb
总线上的编号。你的
usb
设备插到
hub
上时,
hub
观察到这个变化,于是来了精神,会在一个漫长而又曲折的处理过程中调用一个名叫
choose_address
的函数,为你的设备选择一个地址。就像在那个浪漫的季节的一个温馨的下午,你去吃港汇下边儿的那个必胜客,同样会领取一个属于自己的编号陪伴自己度过一个漫长的过程。有人说我没有用
hub
,我的
usb
设备直接插到主机的
usb
接口上了。我哭,即使你没有用
hub
,也总要明白主机里还会有个叫
root hub
的东东吧,不管是一般的
hub
还是
root hub
,你的
usb
设备总要通过一个
hub
才能在
usb
的世界里生活。
现在来认识一下
usb
子系统里面关于地址的游戏规则。在
usb
世界里,一条总线就是大树一棵,一个设备就是叶子一片。为了记录这棵树上的每一个叶子节点,每条总线设有一个地址映射表,即
struct usb_bus
结构体里有一个成员
struct usb_devmap devmap
,
268
/* USB device number allocation bitmap */
269
struct
usb_devmap
{
270
unsigned long devicemap[128 / (8*sizeof(unsigned long))];
271
};
什么是
usb_bus
?前面不是已经有了一个
struct bus_type
类型的
usb_bus_type
了么?没错,在
usb
子系统的初始化函数
usb_init
里已经注册了
usb_bus_type
,不过那是让系统知道有这么一个类型的总线。而一个总线类型和一条总线是两码子事儿。从硬件上来讲,一个
host controller
就会连出一条
usb
总线,而从软件上来讲,不管你有多少个
host controller
,或者说有多少条总线,它们通通属于
usb_bus_type
这么一个类型,只是每一条总线对应一个
struct usb_bus
结构体变量,这个变量在
host controller
的驱动程序中去申请。
上面的
devmap
地址映射表就
表示了一条总线上设备连接的情况,假设
unsigned long=4bytes
,那么
unsigned long devicemap[128/(8*sizeof(unsigned long)]]
就等价于
unsigned long devicemap[128/(8*4)]
,进而等价于
unsigned long devicemap[4]
,而
4bytes
就是
32
个
bits
,因此这个数组最终表示的就是
128
个
bits
。而这也对应于一条总线可以连接
128
个
usb
设备。之所以这里使用
sizeof(unsigned long)
,就是为了跨平台应用,不管
unsigned long
到底是几,总之这个
devicemap
数组最终可以表示
128
位,也就是说每条总线上最多可以连上
128
个设备。
338
行,
devpath [16]
,它显然是用来记录一个字符串的,这个字符串啥意思?给你看个直观的东西
localhost:~ # ls /sys/bus/usb/devices/
1-0:1.0 2-1 2-1:1.1 4-0:1.0 4-5:1.0 usb2 usb4
2-0:1.0 2-1:1.0 3-0:1.0 4-5 usb1 usb3
Sysfs
文件系统下,我们看到这些乱七八糟的东西,它们都是啥?
usb1/usb2/usb3/usb4
表示哥们的计算机上接了
4
条
usb
总线,即
4
个
usb
主机控制器,事物多了自然就要编号,就跟我们中学或大学里面的学号一样,就是用于区分多个个体,而
4-0:1.0
表示什么?
4
表示是
4
号总线,或者说
4
号
Root Hub
,
0
就是这里我们说的
devpath
,
1
表示配置为
1
号,
0
表示接口号为
0
。也即是说,
4
号总线的
0
号端口的设备,使用的是
1
号配置,接口号为
0
。那么
devpath
是否就是端口号呢?显然不是,这里我列出来的这个例子是只有
Root Hub
没有级联
Hub
的情况,如果在
Root Hub
上又接了别的
Hub
,然后一级一级连下去,子又生孙,孙又生子,子又有子,子又有孙。子子孙孙,无穷匮也。那么如何在
sysfs
里面来表征这整个大家族呢?这就是
devpath
的作用,顶级的设备其
devpath
就是其连在
Root Hub
上的端口号,而次级的设备就是其父
Hub
的
devpath
后面加上其端口号,即如果
4-0:1.0
如果是一个
Hub
,那么它下面的
1
号端口的设备就可以是
4-0.1:1.0
,
2
号端口的设备就可以是
4-0.2:1.0
,
3
号端口就可以是
4-0.3:1.0
。总的来说,就是端口号一级一级往下加。这个思想是很简单的,也是很朴实的。
339
行,
state
,设备的状态。这是个枚举类型
557
enum
usb_device_state
{
558
/* NOTATTACHED isn't in the USB spec, and this state acts
559
* the same as ATTACHED ... but it's clearer this way.
560
*/
561
USB_STATE_NOTATTACHED = 0,
562
563
/* chapter 9 and authentication (wireless) device states */
564
USB_STATE_ATTACHED,
565
USB_STATE_POWERED, /* wired */
566
USB_STATE_UNAUTHENTICATED, /* auth */
567
USB_STATE_RECONNECTING, /* auth */
568
USB_STATE_DEFAULT, /* limited function */
569
USB_STATE_ADDRESS,
570
USB_STATE_CONFIGURED, /* most functions */
571
572
USB_STATE_SUSPENDED
573
574
/* NOTE: there are actually four different SUSPENDED
575
* states, returning to POWERED, DEFAULT, ADDRESS, or
576
* CONFIGURED respectively when SOF tokens flow again.
577
*/
578
};
上面定义了
9
种状态,
spec
里只定义了
6
种,
Attached
,
Powered
,
Default
,
Address
,
Configured
,
Suspended
,对应于
Table 9.1
。
Attached
表示设备已经连接到
usb
接口上了,是
hub
检测到设备时的初始状态。那么这里所谓的
USB_STATE_NOTATTACHED
就是表示设备并没有
Attached
。
Powered
是加电状态。
USB
设备的电源可以来自外部电源,协议里叫做
self-powered
,也可以来自
hub
,叫
bus-powered
。尽管
self-powered
的
USB
设备可能在连接上
USB
接口以前已经上电,但它们直到连上
USB
接口后才能被看作是
Powered
的,你觉得它已经上电了那是站在你的角度看,可是现在你看的是
usbcore
,所以要放弃个人的成见,团结在
core
的周围。
Default
缺省状态,在
Powered
之后,设备必须在收到一个复位(
reset
)信号并成功复位后,才能使用缺省地址回应主机发过来的设备和配置描述符的请求。
Address
状态表示主机分配了一个唯一的地址给设备,此时设备可以使用缺省管道响应主机的请求。真羡慕这些
usb
设备,住的地方都是包分配的,哪像咱们辛辛苦苦一路小跑着也不一定能达到
Address
状态。
Configured
状态表示设备已经被主机配置过了,也就是协议里说的处理了一个带有非
0
值的
SetConfiguration()
请求,此时主机可以使用设备提供的所有功能。
Suspended
挂起状态,为了省电,设备在指定的时间内,
3ms
吧,如果没有发生总线传输,就要进入挂起状态。此时,
usb
设备要自己维护包括地址、配置在内的信息。
USB
设备从生到死都要按照这么几个状态,遵循这么一个过程。它不可能像咱们的房价,林志伶的胸部一样跳跃式的发展。
340
行,
speed
,设备的速度,这也是个枚举变量
548
/* USB 2.0 defines three speeds, here's how Linux identifies them */
549
550
enum
usb_device_speed
{
551
USB_SPEED_UNKNOWN = 0, /* enumerating */
552
USB_SPEED_LOW
,
USB_SPEED_FULL
, /* usb 1.1 */
553
USB_SPEED_HIGH
, /* usb 2.0 */
554
USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
555
};
地球人都知道,
USB
设备有三种速度,低速,全速,高速。
USB1.1
那会儿只有低速,全速,后来才出现了高速,就是所谓的
480Mbps/s
。这里还有个
USB_SPEED_VARIABLE
,是无线
USB
的,号称
usb 2.5
,还在发展中,据说小黑的
T61
已经支持了,向往中。
USB_SPEED_UNKNOWN
只是表示现阶段还不知道这个设备究竟什么速度。
342
行,
tt
,
343
行,
ttport
。知道
tt
干嘛的吗?
tt
叫做
transaction translator
。你可以把它想成一块特殊的电路,是
hub
里面的电路,确切的说是高速
hub
中的电路,我们知道
usb
设备有三种速度的,分别是
low speed
,
full speed
,
high speed
。即所谓的低速
/
全速
/
高速,抗日战争那会儿,这个世界上只有
low speed/full speed
的设备,没有
high speed
的设备,后来解放后,国民生产力的大幅度提升催生了一种
high speed
的设备,包括主机控制器,以前只有两种接口的,
OHCI/UHCI
,这都是在
usb spec 1.0
的时候,后来
2.0
推出了
EHCI
,高速设备应运而生。
Hub
也有高速
hub
和过去的
hub
,但是这里就有一个兼容性问题了,高速的
hub
是否能够支持低速
/
全速的设备呢?一般来说是不支持的,于是有了一个叫做
TT
的电路,它就负责高速和低速
/
全速的数据转换,于是,如果一个高速设备里有这么一个
TT
,那么就可以连接低速
/
全速设备,如不然,那低速
/
全速设备没法用,只能连接到
OHCI/UHCI
那边出来的
hub
口里。
345
行,
toggle[2]
,这个数组只有两个元素,分别对应
IN
和
OUT
端点,每一个端点占一位。似乎这么说仍是在雾中看花,黑格尔告诉我们,存在就是有价值的,那么这个数组存在的价值是什么?一言难尽,说来话长,那就长话长说好了。
咱们前边儿说,你要想和你的
usb
通信,创建一个
urb
,为它赋好值,交给咱们的
usb core
就可以了。这个
urb
是站在咱们的角度,实际上在
usb cable
里流淌的根本就不是那么回事儿,咱们提交的是
urb
,
usb cable
里流淌的是一个一个的数据包(
packet
),就像咱们吃的是社会主义的粮,身体里流淌的是无产阶级的鲜血。咱们无产阶级的鲜血里,虽说不包括房产财产什么的,但是还是有许多的成分一定的结构的,
usb
底层传输的
packets
也一样。
咱们凄苦的人生是从第一声哭开始,所有的
packets
都从一个
SYNC
同步字段开始,
SYNC
是一个
8
位长的二进制串,只是用来同步用的,它的最后两位标志了
SYNC
的结束和
PID
(
Packet Identifer
)的开始,就像咱们的大四标志了梦想的结束和现实的开始。
PID
也是一个
8
位的二进制串,前四位用来区分不同的
packet
类型,后面四位只是前四位的反码,校验用的。
packet
的类型主要有四种,在
spec
的
Table 8-1
里有说明
主机和设备都是纯理性的东东,完全通过
PID
来判断送过来的
packet
是不是自己所需要的,不像咱们,往往缺乏这么一个用来判断的标准,不知道自己究竟需要的是什么。
PID
之后紧跟着的是地址字段,每个
packet
都需要知道自己要往哪里去,它们是一个一个目的明确的精灵,行走在
usb cable
里,而我们的前方在哪里?这个地址实际上包括两部分,
7
位表示了总线上连接的设备或接口的地址,
4
位表示端点的地址,这就是为什么前面说每条
usb
总线最多只能有
128
个设备,即使是高速设备每个接口除了
0
号端点也最多只能有
15
个
in
端点和
15
个
out
端点。地址字段再往后是
11
位的帧号(
frame number
),值达到
7FFH
时归零,像一个个无聊的夜晚一样循环往复。这个帧号并不是每一个
packet
都会有,它只在每帧或微帧(
Mircoframe
)开始的
SOF Token
包里发送。帧是对于低速和全速模式来说的,一帧就是
1ms
,对于高速模式的称呼是微帧,一个微帧为
125
微妙,每帧或微帧当然不会只能传一个
packet
。帧号再往后就是千呼万唤始出来的
Data
字段了,它可以有
0
到
1024
个字节不等。最后还有
CRC
校验字段来做扫尾工作。
咱们要学习
packet
,做一个有理想有目标的人,所以这里只看看
Data
类型的
packet
。前面的
Table 8-1
里显示,有四种类型的
Data
包,
DATA0
,
DATA1
,
DATA2
和
MDATA
。存在就是有价值的,这里分成
4
种数据包自然有里面的道理,其中
DATA0
和
DATA1
就可以用来实现
data toggle
同步,看到
toggle
,好像有点接近不久之前留下的疑问了。
对于批量传输、控制传输和中断传输来说,数据包最开始都是被初始化为
DATA0
的,然后为了传输的正确性,就一次传
DATA0
,一次传
DATA1
,一旦哪次打破了这种平衡,主机就可以认为传输出错了。对于等时传输来说,
data toggle
并不被支持。
USB
就是在使用这种简单的哲学来判断对于错,而我们的生活中有的只是复杂,即使一个馒头都能引起一个两亿多的血案。
我们的
struct usb_device
中的数组
unsigned int toggle[2]
就是为了支持这种简单的哲学而生的,它里面的每一位表示的就是每个端点当前发送或接收的数据包是
DATA0
还是
DATA1
。
348
行,
parent
,
struct usb_device
结构体的
parent
自然也是一个
struct usb_device
指针。对于
Root Hub
,前面说过,它是和
Host Controller
是绑定在一起的,它的
parent
指针在
Host Controller
的驱动程序中就已经赋了值,这个值就是
NULL
,换句话说,对于
Root Hub
,它不需要再有父指针了,这个父指针就是给从
Root Hub
连出来的节点用的。
USB
设备是从
Root Hub
开始,一个一个往外面连的,比如
Root Hub
有
4
个口,每个口连一个
USB
设备,比如其中有一个是
Hub
,那么这个
Hub
有可以继续有多个口,于是一级一级的往下连,最终连成了一棵树。
349
行,
bus
,没什么说的,设备所在的那条总线。
350
行,
ep0
,端点
0
的特殊地位决定了她必将受到特殊的待遇,在
struct usb_device
对象产生的时候它就要初始化。
353
行,
dev
,嵌入到
struct usb_device
结构里的
struct device
结构。
354
行,
desc
,设备描述符,四大描述符的第三个姗姗而来。它在
include/linux/usb/ch9.h
里定义
203
/* USB_DT_DEVICE: Device descriptor */
204
struct
usb_device_descriptor
{
205
__u8
bLength;
206
__u8
bDescriptorType;
207
208
__le16
bcdUSB;
209
__u8
bDeviceClass;
210
__u8
bDeviceSubClass;
211
__u8
bDeviceProtocol;
212
__u8
bMaxPacketSize0;
213
__le16
idVendor
;
214
__le16
idProduct
;
215
__le16
bcdDevice
;
216
__u8
iManufacturer
;
217
__u8
iProduct
;
218
__u8
iSerialNumber
;
219
__u8
bNumConfigurations;
220
}
__attribute__
((packed));
221
222
#define
USB_DT_DEVICE_SIZE
18
205
行,
bLength
,描述符的长度,可以自己数数,或者看紧接着的定义
USB_DT_DEVICE_SIZE
。
206
行,
bDescriptorType
,这里对于设备描述符应该是
USB_DT_DEVICE
,
0x01
。
208
行,
bcdUSB
,
USB spec
的版本号,一个设备如果能够进行高速传输,那么它设备描述符里的
bcdUSB
这一项就应该为
0200H
。
209
行,
bDeviceClass
,
210
行,
bDeviceSubClass
,
211
行,
bDeviceProtocol
,和接口描述符的意义差不多,前面说了这里就不再罗唆了。
212
行,
bMaxPacketSize0
,端点
0
一次可以处理的最大字节数,端点
0
的属性却放到设备描述符里去了,更加彰显了它突出的江湖地位,它和机器人公敌里的机器人
Sonny
,交大南门外的老赵烤肉一样特别一样独一无二。
前面说端点的时候说了端点
0
并没有一个专门的端点描述符,因为不需要,基本上它所有的特性都在
spec
里规定好了的,然而,别忘了这里说的是“基本上”,有一个特性则是不一样的,这叫做
maximum packet size
,每个端点都有这么一个特性,即告诉你该端点能够发送或者接收的包的最大值。对于通常的端点来说,这个值被保存在该端点描述符中的
wMaxPacketSize
这一个
field
,而对于端点
0
就不一样了,由于它自己没有一个描述符,而每个设备又都有这么一个端点,所以这个信息被保存在了设备描述符里,所以我们在设备描述符里可以看到这么一项,
bMaxPacketSize0
。而且
spec
还规定了,这个值只能是
8
,
16
,
32
或者
64
这四者之一,如果一个设备工作在高速模式,这个值还只能是
64
,如果是工作在低速模式,则只能是
8
,取别的值都不行。
213
行,
idVendor
,
214
行,
idProduct
,分别是厂商和产品的
ID
。
215
行,
bcdDevice
,设备的版本号。
216
行,
iManufacturer
,
217
行,
iProduct
,
218
行,
iSerialNumber
,分别是厂商,产品和序列号对应的字符串描述符的索引值。
219
行,
bNumConfigurations
,设备当前速度模式下支持的配置数量。有的设备可以在多个速度模式下操作,这里包括的只是当前速度模式下的配置数目,不是总的配置数目。
这就是设备描述符,它和
spec Table 9-8
是一一对应的。咱们回到
struct
usb_device
的
355
行,
config
,
357
行,
actconfig
,分别表示设备拥有的所有配置和当前激活的,也就是正在使用的配置。
usb
设备的配置用
struct usb_host_config
结构来表示,下节再说。
358
行,
ep_in[16]
,
359
行,
ep_out[16]
,除了端点
0
,一个设备即使在高速模式下也最多只能再有
15
个
IN
端点和
15
个
OUT
端点,端点
0
太特殊了,对应的管道是
Message
管道,又能进又能出特能屈能伸的那种,所以这里的
ep_in
和
ep_out
数组都有
16
个值。
361
行,
rawdescriptors
,这是个字符指针数组,数组里的每一项都指向一个使用
GET_DESCRIPTOR
请求去获得配置描述符时所得到的结果。考虑下,为什么我只说得到的结果,而不直接说得到的配置描述符?不是请求的就是配置描述符么?这是因为你使用
GET_DESCRIPTOR
去请求配置描述符时,设备返回给你的不仅仅只有配置描述符,它把该配置所包括的所有接口的接口描述符,还有接口里端点的端点描述符一股脑的都塞给你了。第一个接口的接口描述符紧跟着这个配置描述符,然后是这个接口下面端点的端点描述符,如果有还有其它接口,它们的接口描述符和端点描述符也跟在后面,这里面,专门为一类设备定义的描述符和厂商定义的描述符跟在它们对应的标准描述符后面。这和我们去买水果,买了
5
斤苹果却只有
5
个真实天壤之别,现实生活中的愤懑在
USB
世界里得到了发泄。
这里提到了
GET_DESCRIPTOR
请求,就顺便简单提一下
USB
的设备请求(
device request
)。协议里说了,所有的设备通过缺省的控制管道来响应主机的请求,既然使用的是控制管道,那当然就是控制传输了,这些请求的底层
packet
属于
Setup
类型,前面的那张表里也可以看到它,在
Setup
包里包括了请求的各种参数。协议里同时也定义了一些标准的设备请求,并规定所有的设备必须响应它们,即使它们还处于
Default
或
Address
状态。这些标准的设备请求里,
GET_DESCRIPTOR
就赫然在列。
363
行,
bus_mA
,
这个值是在
host controller
的驱动程序中设置的
,
通常来讲
,
计算机的
usb
端口可以提供
500mA
的电流
。
364
行,
portnum
,不管是
root hub
还是一般的
hub
,你的
USB
设备总归要插在一个
hub
的端口上才能用,
portnum
就是那个端口号。当然,对于
root hub
这个
usb
设备来说它本身没有
portnum
这么一个概念,因为它不插在别的
Hub
的任何一个口上。所以对于
Root Hub
来说,它的
portnum
在
Host Controller
的驱动程序里给设置成了
0
。
365
行,
level
,层次,也可以说是级别,表征
usb
设备树的级连关系。
Root Hub
的
level
当然就是
0
,其下面一层就是
level 1
,再下面一层就是
level 2
,依此类推。
366
行,
discon_suspended
,
Disconnected while suspended
。
368
行,
have_langid
,
369
行,
string_langid
,
usb
设备里的字符串描述符使用的是
UNICODE
编码,可以支持多种语言,
string_langid
就是用来指定使用哪种语言的,
have_langid
用来判断
string_langid
是否有效。
372
行,
product
,
373
行,
manufacturer
,
374
行,
serial
,分别用来保存产品、厂商和序列号对应的字符串描述符信息。
376~382
行,
usbfs
相关的,不可知的未来说
usbfs
的时候再聊它们。
391
行,
maxchild
,
hub
的端口数,注意可不包括上行端口。
392
行,
children[USB_MAXCHILDREN]
,
USB_MAXCHILDREN
是
include/linux/usb.h
里定义的一个宏,值为
31
315
/* This is arbitrary.
316
* From USB 2.0 spec Table 11-13, offset 7, a hub can
317
* have up to 255 ports. The most yet reported is 10.
318
*
319
* Current Wireless USB host hardware (Intel i1480 for example) allows
320
* up to 22 devices to connect. Upcoming hardware might raise that
321
* limit. Because the arrays need to add a bit for hub status data, we
322
* do 31, so plus one evens out to four bytes.
323
*/
324
#define
USB_MAXCHILDREN
(31)
其实
hub
可以接一共
255
个端口
,
不过实际上遇到的
usb hub
最多的也就是说自己支持
10
个端口的
,
所以
31
基本上够用了
。
394
行,
pm_usage_cnt
,
struct usb_interface
结构里也有,想知道吗?想知道回那儿看吧。
396
行,
quirks
,祭起我们法宝金山词霸看看,怪僻的意思,白了说就是大家的常用语“毛病”。本来指定
usb spec
就是让大家团结一致好办事,但总是有些厂商不太守规矩,拿出一些有点毛病的产品给我们用,你说它大毛病吧,也不是,就像俺这儿的厦
X
彩电一样,绝对能看,只是动不动就罢次工。不说远了,总之这里的
quirk
就是用来判断这些有毛病的产品啥毛病的。谁去判断?不像咱们的中国足协,把中国足球折腾成这样子,也就是出来声明一下完事儿,咱们
usb
这儿实行的可是责任制,你的设备接哪儿哪儿负责,也就是说
hub
去判断,就不用咱费心了。
397
行,看到
#ifdef CONFIG_PM
这个标志,我们就知道从这里直到最后的那个
#endif
都是关于电源管理的。让我们先大胆的忽略它们,
struct usb_device
这个结构已经够让我们疲惫了,还是换换口味吧。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0