要开始系统学习LINUX USB驱动了(通用的驱动流程)

来源:互联网 发布:起点数据网 龙空 编辑:程序博客网 时间:2024/06/03 02:23

以USB串口驱动pl2303为例子分析。


首先是要有一个总管usb设备的驱动,就是定义在generic.c中的 usb_device_driver;该结构在usb.c中注册:

int usb_register_device_driver(struct usb_device_driver *new_udriver,        struct module *owner){    int retval = 0;     if (usb_disabled())        return -ENODEV;    new_udriver->drvwrap.for_devices = 1;     new_udriver->drvwrap.driver.name = (char *) new_udriver->name;    new_udriver->drvwrap.driver.bus = &usb_bus_type;    new_udriver->drvwrap.driver.probe = usb_probe_device;    new_udriver->drvwrap.driver.remove = usb_unbind_device;    new_udriver->drvwrap.driver.owner = owner;    retval = driver_register(&new_udriver->drvwrap.driver);    if (!retval) {        pr_info("%s: registered new device driver %s\n",            usbcore_name, new_udriver->name);        usbfs_update_special();    } else {        printk(KERN_ERR "%s: error %d registering device "            "   driver %s\n",            usbcore_name, retval, new_udriver->name);    }        return retval;}

usb_register_device_driver(&usb_generic_driver, THIS_MODULE) -> driver_register(这是usb device驱动,for_devices = 1);

记住,整个usb驱动架构中就注册了一个这样的设备驱动。


其次是具体设备的usb驱动usb_driver(如PL2303),他们都是用usb_register ->usb_register_driver -> driver_register来注册的(这是注册USB interface驱动,for_devices = 0):

int usb_register_driver(struct usb_driver *new_driver, struct module *owner,            const char *mod_name){    int retval = 0;    if (usb_disabled())        return -ENODEV;    new_driver->drvwrap.for_devices = 0;    new_driver->drvwrap.driver.name = (char *) new_driver->name;    new_driver->drvwrap.driver.bus = &usb_bus_type;    new_driver->drvwrap.driver.probe = usb_probe_interface;    new_driver->drvwrap.driver.remove = usb_unbind_interface;    new_driver->drvwrap.driver.owner = owner;                                                                                                                      new_driver->drvwrap.driver.mod_name = mod_name;    spin_lock_init(&new_driver->dynids.lock);    INIT_LIST_HEAD(&new_driver->dynids.list);    retval = driver_register(&new_driver->drvwrap.driver);    if (retval)        goto out;    usbfs_update_special();    retval = usb_create_newid_file(new_driver);    if (retval)        goto out_newid;    retval = usb_create_removeid_file(new_driver);    if (retval)        goto out_removeid;............................................................

这样,driver就已经添加到USB总线上来。但是还没有device;这是因为deivce是动态创建加载的。USB子系统加载后,会启动一个内核线程:kthread_run(hub_thread, NULL, "khubd")来监控usb设备的热拔插事件,其发现设备的大体流程是:

hub_events -> hub_port_connect_change -> usb_alloc_dev -> 创建udev,并且赋值:

    dev->dev.bus = &usb_bus_type;
    dev->dev.type = &usb_device_type;//这是以后匹配device_driver的依据
    dev->dev.groups = usb_device_groups;

                                                                             ->usb_new_device(udev) -> device_add,这样,就将检测到的USB设备添加到USB总线usb_bus_type上了。

而接着在device_add -> bus_probe_device中会用bus_for_each_drv遍历前面注册在usb总线上的驱动,这个时候总线上有很多device_driver,但是我们要调用前面usb_register_device_driver注册的通用设备描述符解析驱动。

这是如何匹配到的呢?进入USB总线usb_bus_type的match函数看看匹配规则就知道了:

static int usb_device_match(struct device *dev, struct device_driver *drv)                                                                                     {    /* devices and interfaces are handled separately */    if (is_usb_device(dev)) {        /* 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)) {        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;}

可以猜想,现在要匹配的是设备驱动,而不是接口驱动,而is_usb_device函数的定义为:

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

根据前面usb_alloc_dev的赋值,该条件已经符合;接着is_usb_device_driver函数的定义:

static inline int is_usb_device_driver(struct device_driver *drv)                                                                                              {               return container_of(drv, struct usbdrv_wrap, driver)->            for_devices;} 

刚好这里for_devices前面赋值为1,这样usb_device_match就匹配成功了,找到了new_driver->drvwrap.driver这个device_driver,并调用他的probe方法->usb_probe_device:

static int usb_probe_device(struct device *dev)                                                                                                                {.......        error = udriver->probe(udev);.......}

做一些简单的判断然后调用generic.c的usb_device_driver结构体的probe。再次强调,这是通用的配置描述符驱动是根据上述分,所有的usb插入设备都析的规则找到它,并调用他的probe方法来获得配置描述符:

static int generic_probe(struct usb_device *udev){                                                                                                                                                                  int err, c;    /* Choose and set the configuration.  This registers the interfaces     * with the driver core and lets interface drivers bind to them.     */    if (usb_device_is_owned(udev))        ;       /* Don't configure if the device is owned */    else if (udev->authorized == 0)        dev_err(&udev->dev, "Device is not authorized for usage\n");    else {        c = usb_choose_configuration(udev);        if (c >= 0) {            err = usb_set_configuration(udev, c);             if (err) {                dev_err(&udev->dev, "can't set config #%d, error %d\n",                    c, err);                /* This need not be fatal.  The user can try to                 * set other configurations. */            }           }       }       /* USB device state == configured ... usable */    usb_notify_add_device(udev);    return 0;}

主要工作是在usb_set_configuration中,它根据选择到的配置描述符,设置到设备中,使该配置下的接口生效,并将每个接口抽象成一个device,用device_add(&intf->dev)添加到USB总线上去。重要的代码片段如下:

int usb_set_configuration(struct usb_device *dev, int configuration){    int i, ret;     struct usb_host_config *cp = NULL;    struct usb_interface **new_interfaces = NULL;    struct usb_hcd *hcd = bus_to_hcd(dev->bus);    int n, nintf;。。。。。。 new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),。。。。。。        for (; n < nintf; ++n) {            new_interfaces[n] = kzalloc(                    sizeof(struct usb_interface),                    GFP_NOIO);。。。。。。        usb_enable_interface(dev, intf, true);        intf->dev.parent = &dev->dev;        intf->dev.driver = NULL;        intf->dev.bus = &usb_bus_type;        intf->dev.type = &usb_if_device_type;        intf->dev.groups = usb_interface_groups;        intf->dev.dma_mask = dev->dev.dma_mask;        INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);。。。。。。    for (i = 0; i < nintf; ++i) {        struct usb_interface *intf = cp->interface[i];        dev_dbg(&dev->dev,            "adding %s (config #%d, interface %d)\n",            dev_name(&intf->dev), configuration,            intf->cur_altsetting->desc.bInterfaceNumber);        device_enable_async_suspend(&intf->dev);        ret = device_add(&intf->dev);        if (ret != 0) {            dev_err(&dev->dev, "device_add(%s) --> %d\n",                dev_name(&intf->dev), ret);            continue;        }        create_intf_ep_devs(intf);。。。。。。

这一次device_add又将匹配总线上的那个device_driver呢?回去看前面的match方法可知:

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

这个条件成立,调用usb_match_id(intf, usb_drv->id_table)和usb_match_dynamic_id匹配,这样说吧,这里是把从USB设备读取道德PID,VID和驱动中定义的进行匹配,如果有则匹配成功。我们PL2303的id_table定义了很多,如果还要添加新的ID,则在该id_table添加即可。

匹配成功后,调用通用的usb_probe_interface:

static int usb_probe_interface(struct device *dev){。。。。。。    if (intf->needs_altsetting0) {        error = usb_set_interface(udev, intf->altsetting[0].                desc.bInterfaceNumber, 0);。。。。。。    error = driver->probe(intf, id);。。。。。。

调用具体驱动的probe,这里就是PL2303的probe了:

static struct usb_driver pl2303_driver = {                                                                                                                         .name =     "pl2303",    .probe =    usb_serial_probe,    .disconnect =   usb_serial_disconnect,    .id_table = id_table,    .suspend =      usb_serial_suspend,    .resume =       usb_serial_resume,    .no_dynamic_id =    1,    .supports_autosuspend = 1,};

usb_serial_probe,这里看到有趣的事情,usb-serial.c 中的probe也指向usb_serial_probe,按理说应该是先找到usb-serial.c 的porbe,然后再通过它找到pl2303的probe。这里可能是usb-serial.c 作为一个通用的函数接口代码,并没有定义PID,VID;但是USB核心的匹配规则偏偏是匹配该ID,所以为了迎合USB的架构,usb serial也没有别的好办法,只好把PL2303的probe指向了usb-serial.c 的porbe,在该probe中统一处理端点描述符。

从上面可以看出,USB子系统已经为我们实现了大部分架构,我们驱动要做的事情只要实现接口描述符(interface descriptor)的处理即可,这就要求根据USB协议规则和具体的USB芯片手册来操作。

下一篇就来分析常用的USB协议和一个具体的接口描述符驱动。










0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑软件显示无效应用程序怎么办 美的滚筒洗衣机打不开门怎么办 手机存储卡坏了怎么办 回南天地板潮湿怎么办 lg滚筒洗衣机门打不开怎么办 西门子滚桶洗衣机门打不开怎么办 洗衣机离合器螺丝卸不动怎么办 门锁保险栓坏了怎么办 小车电瓶没电了怎么办 重装机兵战车底盘坏了怎么办 父亲沉迷安利十年该怎么办 脚的大脚骨痛怎么办 自考准考证号忘记了怎么办 有桌子老师不出马怎么办 电商遇到职业打假人怎么办 超市遇到职业打假人怎么办 阿里巴巴碰到职业打假人怎么办 商家遇到职业打假人怎么办 买过期食品不赔怎么办 淘宝卖假货遇到打假师怎么办 网店遇到职业打假人怎么办 职业打假师把我起诉法院怎么办 被职业打假举报了怎么办 车档杆拉不动显示不在p档怎么办 宜人贷还不起了怎么办 买高跟鞋一只脚合适一只脚挤怎么办 脚瘦穿高跟鞋撑不起来怎么办 银川市阅海幼儿园进不去怎么办 考编专业不对口怎么办 北京55中国际部怎么办 初中数学没学好高中怎么办 靴子大了一码怎么办 靴子买大了一码怎么办 马丁靴大了一码怎么办 社保掌上通登录密码忘记怎么办 录微课时忘词怎么办 微课掌上通看不到信息怎么办 五年级学生上课很吵新老师怎么办 跟财务老师吵起来怎么办 qq把微信冻结了怎么办 微信给封号了怎么办