从总线模型看USB架构

来源:互联网 发布:社交软件盈利模式 编辑:程序博客网 时间:2024/04/30 20:48

1、模型


USB总线:

struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
#ifdef CONFIG_USB_SUSPEND
.pm = &usb_bus_pm_ops,
#endif
};

USB设备模型:usb_device结构体,通过两个函数实现,即usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)和usb_new_device(struct usb_device *udev)函数。

USB驱动模型:usb_driver结构体,通过函数usb_register(struct usb_driver *driver)来实现。


3、USB总线注册在:

static int __init usb_init(void)

          retval = bus_register(&usb_bus_type);

USB设备注册:我们内核已经含有一个主机控制器驱动(也叫做USB总线驱动),主机控制器包含有一个HUB接口,当我们把USB设备插入HUB接口的时候,就会产生中断:

hub_irq(struct urb *urb)

            kick_khubd(hub);  //kick就是踢的意思,表示HUB有动作了

                         wake_up(&khubd_wait);  //唤醒线程,HUB活动的处理事件,内核创建了一个线程来专门负责的!

  static int hub_thread(void *__unused)
{

do {
hub_events();                                                    //hub事件调用
wait_event_freezable(khubd_wait,                 //唤醒
!list_empty(&hub_event_list) ||
kthread_should_stop());
} while (!kthread_should_stop() || !list_empty(&hub_event_list));

 }

HUB事件调用具体如下:

hub_events(void)

            hub_port_connect_change(hub, i,portstatus, portchange);

                        usb_alloc_dev(hdev, hdev->bus, port1);           //USB设备分配函数

                       hub_port_init(hub, udev, port1, i);

                                       usb_control_msg(udev, usb_rcvaddr0pipe(),USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,USB_DT_DEVICE << 8, 0,buf,GET_DESCRIPTOR_BUFSIZE,initial_descriptor_timeout);  //获取USB设备设备描述符,使用0地址来获取

                                    hub_set_address(udev, devnum);  //给USB设备分配一个唯一的地址

                                    retval = usb_get_device_descriptor(udev, 8); //再次获取设备描述符,知道端点0的最大传输包大小

                                    retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

                     status = usb_new_device(udev);  //这里将注册USB设备

                                  err = usb_enumerate_device(udev);  //把多有描述符读取出来

                                                      err = usb_get_configuration(udev);

                                                                            result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,   bigbuffer, length);  //读取所有描述符

                                                                           usb_parse_configuration(dev, cfgno, &dev->config[cfgno], bigbuffer, length); //解析所有描述符并填充结构体

                                err = device_add(&udev->dev);  //将通过USB总线的匹配函数来匹配USB驱动,匹配成功调用driver驱动(不是usb_driver)的probe函数!



4、USB总线匹配函数:

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
。。。。。。。。。。

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

匹配的原则就是驱动的id_table和恰年描述解析出来接口描述符进行匹配,切记是接口,而不是USB设备!!!


5、匹配成功调用USB驱动的driver驱动的probe函数,切记是driver而不是usb_driver

那么driver如何和usb_driver挂钩,看驱动的注册过程:

usb_register(struct usb_driver *driver)

               usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);

                               new_driver->drvwrap.driver.probe = usb_probe_interface;  //driver内嵌在usb_driver的

                              retval = driver_register(&new_driver->drvwrap.driver);  //注册usb_driver.driver

所以USB总线匹配成功是调用函数usb_probe_interface,这一点很重要!!!

usb_probe_interface(struct device *dev)

          id = usb_match_id(intf, driver->id_table);  //得到匹配的接口

          error = driver->probe(intf, id);  //这里才调用usb_driver的配备函数,参数是匹配的接口intf


到这里USB架构就搞定