USB驱动分析

USB概念:
1. USB是主从结构:所有的传输都由主机发起, USB设备没有主动告知主机的能力,
即使是“中断传输“,它也不是去"中断"主机,而是主机轮询USB设备

2. USB有4种传输类型
a. 控制传输(control): 比如"设置地址", "读取设备信息(描述符)", 都是USB HOST使用控制传输来实现
b. 批量传输(bulk): 数据是可靠的,时间没有保证. 比如打印机
c. 中断传输(interrupt): 数据是可靠的,时间有保证。比如USB鼠标。
d. 实时传输: 数据是不可靠的,时间有保证。比如USB摄像头

USB HOST CONTROLLER把1秒分为若干帧(对于ohci,uhci,每秒有1024帧;对于EHCI,每秒有8096帧),
在每帧开始,先启动a,c,d,有时间的话,再启动b

3. 一个系统里接有一大堆USB设备,怎么分辨?每个设备都有一个地址。
这个地址由USB HOST CONTROLLER分配。
刚开始接上到设备,使用0地址。USB HOST CONTROLLER要先分配出地址,然后把地址告诉设备(set address)。

4. 一个USB设备接入系统,还没有安装设备驱动程序,就能识别出它的ID等信息。为什么?
因为USB设备里有固定的信息,称为描述符。






一. USB BUS DRIVER简述
1. drivers\usb\host\ohci-hcd.c里:
#include "ohci-s3c2410.c"
#define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
……
retval = platform_driver_register(&PLATFORM_DRIVER);

2. drivers\usb\host\ohci-s3c2410.c:
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,

ohci_hcd_s3c2410_drv_probe:
usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
// 构造一个usb_hcd结构
// hcd->driver = &ohci_s3c2410_hc_driver
// ohci_s3c2410_hc_driver
struct usb_hcd *hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");

// 注册usb_hcd
usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);


static const struct hc_driver ohci_s3c2410_hc_driver = {
/*
* basic lifecycle operations
*/
.start = ohci_s3c2410_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,

/*
* managing i/o requests and associated device resources (urb: usb request block)
*/
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,





二. USB DEVICE的枚举
1. 接上一个U盘:
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 Kingston DataTraveler G3 1.00 PQ: 0 ANSI: 2
sd 0:0:0:0: [sda] 15663104 512-byte hardware sectors (8020 MB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Assuming drive cache: write through
sd 0:0:0:0: [sda] 15663104 512-byte hardware sectors (

8020 MB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Assuming drive cache: write through
sda: sda1
sd 0:0:0:0: [sda] Attached SCSI removable disk

取出:usb 1-1: USB disconnect, address 2

2. 接上一个USB串口
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: configuration #1 chosen from 1 choice

取出:usb 1-1: USB disconnect, address 3

3. 接上USB鼠标
usb 1-1: new low speed USB device using s3c2410-ohci and address 4
usb 1-1: configuration #1 chosen from 1 choice
input: Logitech Optical USB Mouse as /class/input/input1
input: USB HID v1.10 Mouse [Logitech Optical USB Mouse] on usb-s3c24xx-1

取出:usb 1-1: USB disconnect, address 4

分析:
1. 接上USB设备,会给这个设备分配一个地址
刚接上的设备的地址是0
USB BUS DRIVER分配一个新地址
然后把新地址告诉设备,以后USB BUS DRIVER就使用这个地址与该设备通信

hub_port_connect_change(drivers/usb/core/hub.c)
udev = usb_alloc_dev(hdev, hdev->bus, port1);
/* set the address */
choose_address(udev);
udev->devnum = devnum; /* 1~127 */

/* reset and get descriptor */
status = hub_port_init(hub, udev, port1, i);
retval = hub_set_address(udev);

retval = usb_get_device_descriptor(udev, 8);




2. 读设备的信息(描述符)
status = hub_port_init(hub, udev, port1, i);
……
/* 现在还不知道ep0一次能传输的数据的最大长度
* ep的一次传输数据量一般都会>=8
*/
retval = usb_get_device_descriptor(udev, 8);
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
usb_control_msg
/* 读出的这8字节数据里有bMaxPacketSize0(ep0的最大传输长度) */
/* 设置udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); */

/* 读出整个device_descriptor */
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

usb_new_device
err = usb_get_configuration(udev); /* 读出所有的描述符, 然后解析 */



3. 给这个设备找一个设备驱动
usb_new_device
err = usb_get_configuration(udev); /* 读出所有的描述符, 然后解析 */
……
err = device_add(&udev->dev);
bus_attach_device(dev);
device_attach(dev);
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);


a. 设备驱动通过usb_register把一个usb_driver结构体挂到usb_bus_type的driver链表下;
b. 当usb bus driver发现一个新设备时,就会使用us

b_new_device构造一个usb_device结构体,
并放入usb_bus_type的device链表下,然后取出driver链表里的每个usb_driver,看能否支持这个设备,
如果能支持,调用usb_driver.probe





三. USB DEVICE DRIVER



四. 写一个例子:把USB鼠标用作键盘(l,s,回车)








相关文档
最新文档