USB驱动

1. USB固件

        USB设备中有一个模块叫固件,固件是固化在集成电路内部的程序代码,USB固件中包含了USB设备的出厂信息,标识该设备的厂商ID、产品ID、主版本号和次版本号等。另外固件中还包含一组程序,这组程序主要完成USB协议的处理和设备的读写操作,USB设备固件和USB驱动之间通信的规范是通过USB协议来完成的。

2. USB device识别过程

        定时轮询方式,当定时时间到了,运行定时器rh_timer的function函数rh_timer_func。

        使用定时器查询的主要原因是USB没有中断USB控制器的能力,所以当USB设备接入之后,获取USB输入的信息是无法通过中断方式来获取,只能通过定时器定时轮训获取。

->rh_timer_func //usb/core/hcd.c
  ->usb_hcd_poll_rh_status
    ->hcd->driver->hub_status_data(hcd, buffer)
    ->usb_hcd_unlink_urb_from_ep(hcd, urb);
    ->usb_hcd_giveback_urb(hcd, urb, 0)
         ->usb_giveback_urb_bh();            //tasklet_hi_schedule(&bh->bh);
            ->__usb_hcd_giveback_urb(urb);
              ->urb->complete(urb);       //hub_irq
                ->hub_irq //hub.c  usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
                  ->kick_hub_wq(hub);
                    ->hub_event //INIT_WORK(&hub->events, hub_event);
                      ->port_event(hub, i);
                        ->hub_port_connect_change
                          ->hub_port_connect
                            ->hub_port_init
                            ->usb_new_device(udev);
                              ->usb_enumerate_device(udev);//开始枚举
                              ->device_add(&udev->dev);//枚举完毕后加载设备驱动

3. USB device的枚举过程

        内核辅助线程khubd用来监视与该集线器连接的所有端口,通常情况下,该线程处于休眠状态,当集线器驱动程序检测到USB端口状态变化后,该内核线程立马唤醒。

        USB的枚举过程:USB的枚举过程是热插拔USB设备的起始步骤,该过程中,主机控制器获取设备的相关信息并配置好设备,集线器驱动程序负责该枚举过程。枚举过程主要分如下几步:

Step1:根集线器报告插入设备导致的端口电流变化,集线器驱动程序检测到这一状态变化后,唤醒khubd线程。
Step2:khubd识别出电流变化的那个端口。
Step3:khubd通过给控制端点0发送控制URB来实现从1-127中选出一个数作为插入设备的批量端点。
Step4:khubd利用端口0使用的控制URB从插入的设备那里获得设备描述符,然后获得配置描述符,并选择一个合适的。
Step5:khubd请求USB核心把对应的客户驱动程序和该USB设备挂钩。

        Step4对应usb_enumerate_device(udev)函数

        Step5对应device_add(&udev->dev)函数

        所以,如果USB设备被正常识别(即枚举过程中成功读取到了USB设备的厂商信息)以后,就会根据设备中的厂商信息调用具体USB设备的驱动程序,比如U盘就会调用U盘的驱动程序。

4. USB driver

        在USB device枚举完成之后通过device_add(&udev->dev)将usb device挂载到usb总线上,然后调用usb总线的match函数匹配usb_device和usb_driver,usb_bus_type总线的match函数对两类设备区别对待,usb_device和usb_device_driver配对,而usb_interface和usb_driver配对。

struct bus_type usb_bus_type = {
	.name =		"usb",
	.match =	usb_device_match,
	.uevent =	usb_uevent,
};
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
	/* devices and interfaces are handled separately */
	if (is_usb_device(dev)) { /*hub创建的usb_device和 usb_generic_driver 匹配走这个分支*/

		/* interface drivers never match devices */
		if (!is_usb_device_driver(drv))
			return 0;

		/* TODO: Add real matching code */
		return 1;

	} else if (is_usb_interface(dev)) {/* usb_interface 和 usb_driver匹配走这个分支  */
		struct usb_interface *intf;
		struct usb_driver *usb_drv;
		const struct usb_device_id *id;

		/* device drivers never match interfaces */
		if (is_usb_device_driver(drv))
			return 0;

		intf = to_usb_interface(dev);
		usb_drv = to_usb_driver(drv);

		id = usb_match_id(intf, usb_drv->id_table);
		if (id)
			return 1;

		id = usb_match_dynamic_id(intf, usb_drv);
		if (id)
			return 1;
	}

	return 0;
}
static inline int is_usb_device(const struct device *dev)
{
	return dev->type == &usb_device_type;
}
static inline int is_usb_interface(const struct device *dev)
{
	return dev->type == &usb_if_device_type;
}

        整个usb子系统只定义了一个struct usb_device_driver驱动,它定义在drivers/usb/core/generic.c文件中,在usb_init中注册,所以HUB会和usb_generic_driver匹配并调用其probe函数。

//drivers/usb/core/usb.c
static int __init usb_init(void)
{
	int retval;
 
	usb_init_pool_max();
	retval = usb_debugfs_init();
	usb_acpi_register();
	retval = bus_register(&usb_bus_type);
	retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
	retval = usb_major_init();
	retval = usb_register(&usbfs_driver);
	retval = usb_devio_init();
	retval = usb_hub_init();
   //向usb核心注册这个usb_device_driver驱动
	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
	usb_hub_cleanup();

	return retval;
}
subsys_initcall(usb_init);

//drivers/usb/core/generic.c
struct usb_device_driver usb_generic_driver = {
	.name =	"usb",
	.probe = generic_probe,
	.disconnect = generic_disconnect,
#ifdef	CONFIG_PM
	.suspend = generic_suspend,
	.resume = generic_resume,
#endif
	.supports_autosuspend = 1,
};

        搜索usb_driver就有很多了,比如鼠标,键盘,u盘,usb转串口,音频,视频等各种各种的设备,usb_driver通过usb_register函数注册。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值