USB驱动(一、概念介绍及USB总线驱动程序代码分析)

时间:2022-03-13 16:10:35

USB驱动程序分为两个层次
(1) USB总线驱动=》系统自带的;
USB总线驱动程序负责:
识别USB设备,给USB设备找到对应的驱动程序。
USB总线驱动程序作用:
a.识别USB设备;
b.查找并安装对应的设备驱动程序;
c.提供USB读写函数。不了解数据含义。
USB总线驱动程序可以通过调用libUSB(libUSB封装了端口函数)跳过USB设备驱动程序,来访问USB设备。
(2) 设备驱动=》需要我们自己编写;
设备驱动知道数据含义。
PC和USB设备都遵守一定的规范。
USB设备接入电脑后,USB总线驱动程序会发出某些命令来获取设备信息(描述符);
USB设备必须返回“描述符”给PC。
USB接口只有4条线:5V,GND,D+,D-。
每一个USB设备接入PC时,USB总线驱动程序都会给他分配一个编号;
接在USB总线上的每一个USB设备都有自己的编号(地址);
PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)。
新接入的USB 设备的默认编号是0,在未分配新编号前,PC使用0编号和它通信。
为了快速识别硬件,在USB主机上的D+和D-一般都会接15k的下拉电阻,而在USB从机上的D+和D-都会接1.5K的上拉电阻。
USB驱动(一、概念介绍及USB总线驱动程序代码分析)
USB驱动(一、概念介绍及USB总线驱动程序代码分析)
USB驱动(一、概念介绍及USB总线驱动程序代码分析)
USB主机控制器,USB总线驱动程序是来支持USB主机控制器,也可以看做是USB总线驱动程序是USB主机控制器驱动程序,USB主机控制器下接有USB设备,设备驱动程序用来支持USB设备,为了能够访问USB设备,设备驱动程序必须调用USB总线驱动程序提供的函数,把那些命令、包,发给USB主机控制器,由USB主机控制器产生的信号发给USB设备。
USB驱动(一、概念介绍及USB总线驱动程序代码分析)
插入和拔出USB设备后,会看到输出信息:
usb 1-1 :new full speed USB device using s3c2410-ohci and address 2
在系统的内核中查找
USB device using (grep “USB device using” * -nR),
发现在device /usb/core/hub.c :2186:
“%s %s speed %sUSB device using %s and address %d\n”,

每一个USB主机控制器内部都自带一个USB hub,可以认为hub为特殊的USB控制器。
USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动(一、概念介绍及USB总线驱动程序代码分析)
USB驱动(一、概念介绍及USB总线驱动程序代码分析)

static void hub_irq(struct urb *urb)
{
......
kick_khubd(hub);
......
}/*主机控制器产生的中断,不是USB设备产生的中断*/
static void kick_khubd(struct usb_hub *hub)
{
unsigned long flags;

/* Suppress autosuspend until khubd runs */
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;

spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
wake_up(&khubd_wait);/*唤醒队列*/
}
spin_unlock_irqrestore(&hub_event_lock, flags);
}
static int hub_thread(void *__unused)
{
do {
hub_events();
wait_event_interruptible(khubd_wait,
!list_empty(&hub_event_list) ||
kthread_should_stop());/*hub 线程一般是在这个队列里面休眠,*/
try_to_freeze();
} while (!kthread_should_stop() || !list_empty(&hub_event_list));

pr_debug("%s: khubd exiting\n", usbcore_name);
return 0;
}
static void hub_events(void)
.......
if (connect_change)
hub_port_connect_change(hub, i,
portstatus, portchange);
........
static void hub_port_connect_change(struct usb_hub *hub, int port1,
u16 portstatus, u16 portchange)
{
......
udev = usb_alloc_dev(hdev, hdev->bus, port1);
......
/* set the address */
choose_address(udev);/*给新设备分配地址*/
......
status = hub_port_init(hub, udev, port1, i);
......
status = usb_new_device(udev);
......
}

在linux/device/usb/core/Usb.c下

usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
......
dev->dev.bus = &usb_bus_type;
......
}

在F:\linux-2.6.22.6\drivers\usb\core\driver.c下

struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
.suspend = usb_suspend,
.resume = usb_resume,
};

在F:\linux-2.6.22.6\drivers\usb\core\driver.c下

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
.......
id = usb_match_dynamic_id(intf, usb_drv);
/*在usb_driver里面会有一个probe函数*/

.......

}
    hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter)
{
.....
dev_info (&udev->dev,
"%s %s speed %sUSB device using %s and address %d\n",
(udev->config) ? "reset" : "new", speed, type,
udev->bus->controller->driver->name, udev->devnum);
......
retval = hub_set_address(udev);/*把编号(或地址)告诉给USB设备*/
......
retval = usb_get_device_descriptor(udev, 8);
/*获取设备描述符,此时获得的是8个字节的,linux/include/linux/usb/ch9.h下usb_device_descriptor结构体中 */
......

retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
......
}

在linux/include/linux/usb/ch9.h下


/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;

__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
} __attribute__ ((packed));
int usb_new_device(struct usb_device *udev)
{
......
err = usb_get_configuration(udev);/*把所有的配置读取出来并解析*/
......
err = device_add(&udev->dev);
......
}

在linux/device/usb/core/Config.c下

int usb_get_configuration(struct usb_device *dev)
{
......
result = usb_parse_configuration(&dev->dev, cfgno,
&dev->config[cfgno], bigbuffer, length);
/*解析配置信息*/
.......
}