Chinaunix首页 | 论坛 | 博客
  • 博客访问: 829009
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: LINUX

2015-12-09 15:07:19

USB驱动分析:【usb驱动分析之自己理解.txt

1. 在USB驱动中,当USB设备插入USB host时候,会发生USB主机枚举的过程,主机会自动找到该设备配置信息,描述符,将该设备挂接到相应的USB总线上;
   在device这一层上,是由内核自动完成的;
2. 用户要写的是usb driver端的驱动程序。

这和输入子系统有区别。
在输入子系统中,driver是做好的( input_handler ),在内核中已经存在input_handler,比如uevent等,
用户需要编写设备端device 的驱动程序。


工作平台: linux-2.6.22.6
USB设备枚举过程:
预备工作:linux先把驱动注册进内核

看文件:\drivers\usb\core\usb.c
入口函数:
    subsys_initcall(usb_init);  // 系统初始化化时,注册进内核
    usb_init(void)
        bus_register(&usb_bus_type);  // 注册了USB总线类型:usb_bus_type
        usb_hub_init();
            kthread_run(hub_thread, NULL, "khubd");
            
        // 这里注册的是整个USB device的driver,而不是USB interface,所以是USB device通用的设备驱动。
        // 那么USB interface什么时候进行匹配呢?
        usb_register_device_driver(&usb_generic_driver, THIS_MODULE);            (struct usb_device_driver)
            // USB device driver进一步封装:usb_generic_driver->drvwrap.driver  (struct device_driver)
            usb_generic_driver->drvwrap.for_devices = 1;
            usb_generic_driver->drvwrap.driver.name = (char *) new_udriver->name;
            usb_generic_driver->drvwrap.driver.bus = &usb_bus_type;
            usb_generic_driver->drvwrap.driver.probe = usb_probe_device;
            usb_generic_driver->drvwrap.driver.remove = usb_unbind_device;
            usb_generic_driver->drvwrap.driver.owner = owner;    
                
            // 这里注册driver:usb_generic_driver->drvwrap.driver,
            // 该驱动里面.bus, .probe, .remove函数上面已经进行重新赋值了
            driver_register(&usb_generic_driver->drvwrap.driver);
                // 将一个driver绑定到指定的总线bus上
                bus_add_driver(&usb_generic_driver->drvwrap.driver);
                    if (drv->bus->drivers_autoprobe) {   // 这个变量有设置吗?
                        error = driver_attach(drv);      // 这里是注册driver (对应的是usb device)
                            // 从usb_generic_driver->drvwrap.driver所在的bus总线usb_bus_type上的device链表上,
                            // 取出device来一一和该usb_generic_driver->drvwrap.driver进行比较
                            bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)
                            __driver_attach(struct device * dev, void * data)
                                driver_probe_device(drv, dev);
                                    drv->bus->match(dev, drv)  // 调用函数:usb_device_match
                                    // 如果匹配,则调用下面的probe函数
                                    really_probe(dev, drv);
                                        drv->probe(dev);  // 调用函数:usb_generic_driver->drvwrap.driver.probe = usb_probe_device (注:这里是USB device)
                                        =》usb_probe_device
                                            // 从driver转化为:usb_device_driver, 重新转化为:usb_generic_driver
                                            // 所以这里 udriver = usb_generic_driver
                                            struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
                                            // 相当于调用函数:usb_generic_driver->probe = generic_probe
                                            udriver->probe(udev);
                                            =》generic_probe
                                                // 选择,设置配置信息
                                                choose_configuration(udev);
                                                usb_set_configuration(udev, c);
                                                // 通知内核,USB设备配置完成,可以使用了。
                                                usb_notify_add_device(udev);
                    }
        
    
初始化到此结束


问题1: USB host是一直查询USB端口的变化的,那么是谁在查询呢?
回答1:hub_thread
    usb_init(void)
            kthread_run(hub_thread, NULL, "khubd");
    在初始化usb_init函数中,内核建立一个线程hub_thread,一直在运行,监测USB端口的变化状态
    
kthread_run(hub_thread, NULL, "khubd");
            线程: hub_thread(void *__unused)
            
                    /** 处理hub 口上发生的事情: 比如USB 插入或者拔下
                      * 如果有此类事情发生,则调用: hub_port_connect_change();
                      * 在函数hub_port_connect_change 中就完成USB 设备的枚举过程,
                      * 实现USB 设备的查找,获取描述符,以及安装USB设备相对应驱动的过程。
                      */
                    hub_events();
                        // 如果端口连接发生变化(USB设备插入或者拔出等)
                        hub_port_connect_change(hub, i, portstatus, portchange);
                            usb_alloc_dev(hdev, hdev->bus, port1);
                            choose_address(udev);                       // 分配一个地址给USB设备
                            hub_port_init(hub, udev, port1, i);
                                hub_set_address(udev);               // 设置USB设备的地址
                                usb_get_device_descriptor(udev, 8);  // 获取需要的设备描述符
                                usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
                                
                            usb_new_device(udev);  // udev: struct usb_device
                                usb_get_configuration(udev)   // 获取配置信息
                                device_add(&udev->dev)
                                    device_add(&udev->dev);                  // udev->dev: struct device
                                    bus_attach_device(dev)                   // 将设备(usb device)绑定到bus上去
                                        struct bus_type *bus = dev->bus;     // usb_bus_type
                                        if (bus->drivers_autoprobe)          // 这个变量哪里设置了??
                                            device_attach(dev)               // 这里是注册device (对应的是usb interface)
                                                /* 从dev指定bus的drv链表上,取出drv和dev一一进行比较
                                                *  调用__device_attach, 如果匹配则最终会调用bus中的.match 函数 */
                                                bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
                                                => __device_attach
                                                    driver_probe_device(drv, dev)
                                                        //从bus 的drv 链表取出drv 和dev 进行比较匹配,调用函数:usb_device_match
                                                        drv->bus->match(dev, drv)  // 相当于调用:usb_device_match
                                                        really_probe(dev, drv);    // 如果drv 和dev 匹配,则调用probe 函数
                                                            drv->probe(dev)        // 调用drv上的probe函数:usb_probe_interface (注:这里是USB interface)
                                                            => usb_probe_interface
                                                                intf = to_usb_interface(dev);
                                                                udev = interface_to_usbdev(intf);
                                                                usb_match_id(intf, driver->id_table);
                                                                usb_match_dynamic_id(intf, driver);
                                                                usb_autoresume_device(udev);
                                                                usb_autosuspend_device(udev);
                                                            
                    // 如果hub上没有event事件发生,则进入休眠状态,谁来唤醒?                                
                    wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)||kthread_should_stop());

问题2:谁来唤醒队列: khubd_wait
回答2:
static void hub_irq(struct urb *urb)
    static void kick_khubd(struct usb_hub *hub)
        wake_up(&khubd_wait);
问题3: 谁来调用: hub_irq
回答3:
static int hub_configure(struct usb_hub *hub,
    // 当提交完成urb后,将调用完成函数: hub_irq, 这里只是初始化该函数
    usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval);

USB driver端代码流程分析:
 usb_register(struct usb_driver *driver)                        // (struct usb_driver)
    usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
        new_driver->drvwrap.driver.bus = &usb_bus_type;         // (new_driver->drvwrap.driver: struct device_driver driver)
        new_driver->drvwrap.driver.probe = usb_probe_interface;
        new_driver->drvwrap.driver.remove = usb_unbind_interface;
        driver_register(&new_driver->drvwrap.driver);           // 注册struct device_driver driver结构体 --> usb_driver
            bus_add_driver(drv);  
                if (drv->bus->drivers_autoprobe)
                    driver_attach(drv);
                        // 从usb_bus_type总线的dev链表中取出dev,和该driver进行一一比较
                        bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
                        // 执行该函数
                        __driver_attach(struct device * dev, void * data)
                            if (!dev->driver)
                                driver_probe_device(drv, dev);
                                    // 从usb_bus_type总线中取出.match函数,进行比较
                                    drv->bus->match(dev, drv)  // 这里:drv->bus->match = usb_bus_type.match = usb_device_match
                                    => usb_device_match(struct device *dev, struct device_driver *drv)
                                        // 比较接口(USB的接口intf)和driver中的id_table是否对应
                                        usb_match_id(intf, usb_drv->id_table);
                                    really_probe(dev, drv);
                                    drv->probe(dev);   // drv->probe = usb_probe_interface
                                    => usb_probe_interface
                                            // 从struct device找到usb_interface和usb_device
                                            intf = to_usb_interface(dev);
                                            udev = interface_to_usbdev(intf);
                                            
                                            // 比较intf和driver中的id_table
                                            // 因为在usb驱动中,需要建立usb intf 和 usb driver的对应关系
                                            usb_match_id(intf, driver->id_table);
                                            usb_match_dynamic_id(intf, driver);
                                            
                                            //
                                            usb_autoresume_device(udev);
                                            driver->probe(intf, id); // 这个是用户自己编写驱动需要提供的probe函数
                                            usb_autosuspend_device(udev);




阅读(1686) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~