-
Notifications
You must be signed in to change notification settings - Fork 45
/
USB设备驱动程序
212 lines (154 loc) · 10.3 KB
/
USB设备驱动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
WINDOWS 现象:把USB设备接到PC
1. 右下角弹出"发现android phone"
2. 跳出一个对话框,提示你安装驱动程序
问1. 既然还没有"驱动程序",为何能知道是"android phone"
答1. windows里已经有了USB的总线驱动程序,接入USB设备后,是"总线驱动程序"知道你是"android phone"
提示你安装的是"设备驱动程序"
USB总线驱动程序负责:识别USB设备, 给USB设备找到对应的驱动程序
问2. USB设备种类非常多,为什么一接入电脑,就能识别出来?
答2. PC和USB设备都得遵守一些规范。
比如:USB设备接入电脑后,PC机会发出"你是什么"?
USB设备就必须回答"我是xxx", 并且回答的语言必须是中文
USB总线驱动程序会发出某些命令想获取设备信息(描述符),
USB设备必须返回"描述符"给PC
问3. PC机上接有非常多的USB设备,怎么分辨它们?
USB接口只有4条线: 5V,GND,D-,D+
答3. 每一个USB设备接入PC时,USB总线驱动程序都会给它分配一个编号
接在USB总线上的每一个USB设备都有自己的编号(地址)
PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)
问4. USB设备刚接入PC时,还没有编号;那么PC怎么把"分配的编号"告诉它?
答4. 新接入的USB设备的默认编号是0,在未分配新编号前,PC使用0编号和它通信。
问5. 为什么一接入USB设备,PC机就能发现它?
答5. PC的USB口内部,D-和D+接有15K的下拉电阻,未接USB设备时为低电平
USB设备的USB口内部,D-或D+接有1.5K的上拉电阻;它一接入PC,就会把PC USB口的D-或D+拉高,从硬件的角度通知PC有新设备接入
其他概念:
1. USB是主从结构的
所有的USB传输,都是从USB主机这方发起;USB设备没有"主动"通知USB主机的能力。
例子:USB鼠标滑动一下立刻产生数据,但是它没有能力通知PC机来读数据,只能被动地等得PC机来读。
2. USB的传输类型:
a. 控制传输:可靠,时间有保证,比如:USB设备的识别过程
b. 批量传输: 可靠, 时间没有保证, 比如:U盘
c. 中断传输:可靠,实时,比如:USB鼠标
d. 实时传输:不可靠,实时,比如:USB摄像头
3. USB传输的对象:端点(endpoint)
我们说"读U盘"、"写U盘",可以细化为:把数据写到U盘的端点1,从U盘的端点2里读出数据
除了端点0外,每一个端点只支持一个方向的数据传输
端点0用于控制传输,既能输出也能输入
4. 每一个端点都有传输类型,传输方向
5. 术语里、程序里说的输入(IN)、输出(OUT) "都是" 基于USB主机的立场说的。
比如鼠标的数据是从鼠标传到PC机, 对应的端点称为"输入端点"
6. USB总线驱动程序的作用
a. 识别USB设备
b. 查找并安装对应的设备驱动程序
c. 提供USB读写函数
USB驱动程序框架:
app:
-------------------------------------------
USB设备驱动程序 // 知道数据含义
内核 --------------------------------------
USB总线驱动程序 // 1. 识别, 2. 找到匹配的设备驱动, 3. 提供USB读写函数 (它不知道数据含义)
-------------------------------------------
USB主机控制器
UHCI OHCI EHCI
硬件 -----------
USB设备
UHCI: intel, 低速(1.5Mbps)/全速(12Mbps)
OHCI: microsoft 低速/全速
EHCI: 高速(480Mbps)
USB总线驱动程序的作用
1. 识别USB设备
1.1 分配地址
1.2 并告诉USB设备(set address)
1.3 发出命令获取描述符
描述符的信息可以在include\linux\usb\Ch9.h看到
2. 查找并安装对应的设备驱动程序
3. 提供USB读写函数
把USB设备接到开发板上,看输出信息:
usb 1-1: new full speed USB device using s3c2410-ohci and address 2
usb 1-1: configuration #1 chosen from 1 choice
scsi0 : SCSI emulation for USB Mass Storage devices
scsi 0:0:0:0: Direct-Access HTC Android Phone 0100 PQ: 0 ANSI: 2
sd 0:0:0:0: [sda] Attached SCSI removable disk
拔掉
usb 1-1: USB disconnect, address 2
再接上:
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: configuration #1 chosen from 1 choice
scsi1 : SCSI emulation for USB Mass Storage devices
scsi 1:0:0:0: Direct-Access HTC Android Phone 0100 PQ: 0 ANSI: 2
sd 1:0:0:0: [sda] Attached SCSI removable disk
在内核目录下搜:
grep "USB device using" * -nR
drivers/usb/core/hub.c:2186: "%s %s speed %sUSB device using %s and address %d\n",
hub_irq
kick_khubd
hub_thread
hub_events
hub_port_connect_change
udev = usb_alloc_dev(hdev, hdev->bus, port1);
dev->dev.bus = &usb_bus_type;
choose_address(udev); // 给新设备分配编号(地址)
hub_port_init // usb 1-1: new full speed USB device using s3c2410-ohci and address 3
hub_set_address // 把编号(地址)告诉USB设备
usb_get_device_descriptor(udev, 8); // 获取设备描述符
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
usb_new_device(udev)
usb_enumerate_device
err = usb_get_configuration(udev); // 把所有的描述符都读出来,并解析
usb_parse_configuration
device_add // 把device放入usb_bus_type的dev链表,
// 从usb_bus_type的driver链表里取出usb_driver,
// 把usb_interface和usb_driver的id_table比较
// 如果能匹配,调用usb_driver的probe
<LINUX内核源代码情景分析>
怎么写USB设备驱动程序?
1. 分配/设置usb_driver结构体
.id_table
.probe
.disconnect
2. 注册
测试1th/2th:
1. make menuconfig去掉原来的USB鼠标驱动
-> Device Drivers
-> HID Devices
<> USB Human Interface Device (full HID) support
2. make uImage 并使用新的内核启动
3. insmod usbmouse_as_key.ko
4. 在开发板上接入、拔出USB鼠标
测试3th:
1. insmod usbmouse_as_key.ko
2. ls /dev/event*
3. 接上USB鼠标
4. ls /dev/event*
5. 操作鼠标观察数据
测试4th:
1. insmod usbmouse_as_key.ko
2. ls /dev/event*
3. 接上USB鼠标
4. ls /dev/event*
5. cat /dev/tty1 然后按鼠标键
6. hexdump /dev/event0
///////////////////////////////////////////////////////////////
Linux USB device 枚举过程分析 (2012-08-16 16:26:12)转载▼
标签: linux usb device 枚举过程分析 杂谈 分类: linux学习笔记
原文链接:http://emlinux.name/?p=50
枚举命令
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.设置地址:指示设备更改其当前的地址设置
2.取设备描述符
3.取配置描述符
4.取接口描述符
5.取字符串描述符
枚举过程
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*device 插入HUB
*HUB开始让HOST每秒产生的帧开始包(SOF)能通过该HUB设备枚举。
默认使用地址0(HOST会子枚举过程中为设备分配新的地址,其实就是ID号)端口0(Spec规定)开始与主机通信。
* Host向地址0端口0发出GET_DESCRIPTOR,设备回复描述符信息。
* Host向地址0端口0发出SET_ADDRESS,设备修改地址信息。
* Host将地址和描述符通知OS,OS开始软件枚举动作。
* OS使用 新地址和端口0 重新 获取设备描述符、配置描述符、接口描述符、端口描述符
* OS通过probe函数与已注册的ID进行匹配。以确定对应的Driver,,将设备描述符&设备地址等告知Driver,由Driver控制设备
* Driver使用新地址向设备端口0发送配置命令:指定配置 ->接口->端口的设置
*至此,设备已经成为Driver所OS需要的配置的设备,通过driver指定的端口传送数据
以上过程是通过wireshark 抓包分析来的,想要彻底了解,请君抓一下包就一目了然了!