首先我们先来简单说一说USB的框架,之后在来具体分析源码,以便加深理解!其实USB的框架比较像“平台总线、设备、驱动”的框架,也分为总线、设备、驱动三大块。其中总线驱动是已经由内核完成的,一旦接入usb设备,总线驱动程序就会找到能处理该设备的驱动进行处理!我们进入文件系统的/sys/bus目录下可以看到很多总线目录,usb目录就在其中,我们进入usb目录,会看到devices和drivers!

 
下面我们来看源码:
 
#define subsys_initcall(fn) module_init(fn)
subsys_initcall(usb_init);
     bus_register(&usb_bus_type);//注释1
           __bus_register(subsys, &__key);
                 retval = kset_register(&priv->subsys);
                      kobject_add_internal(&k->kobj);
                            kobj_kset_join(kobj);
                                  //将usb总线加入到总线链表里面,sys/bus目录下就是所有的总线目录
                                  list_add_tail(&kobj->entry, &kobj->kset->list);
                            create_dir(kobj);
                                 sysfs_create_dir(kobj);//具体的目录在这里创建
                //在总线下创建了devices目录,据我分析这里并没有添加设备链表,因为还没有去发现设备
                priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
                //在总线下创建了drivers目录,据我分析这里并没有添加驱动链表,因为还没有去注册驱动
               klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); //初始化设备链表
               klist_init(&priv->klist_drivers, NULL, NULL); //初始化驱动链表
     retval = usb_major_init();//这里面注册了一个字符设备
          //#define USB_MAJOR  180,cat /proc/devices可以观察到
          register_chrdev(USB_MAJOR, "usb", &usb_fops);
     retval = usb_hub_init();
           usb_register(&hub_driver)//将hub.c里面的hub_driver加入到usb总线下的驱动链表里
                usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
                      driver_register(&new_driver->drvwrap.driver);
                           bus_add_driver(drv);
                                 driver_attach(drv);
                                       //匹配devices与drivers,调用__driver_attach
                                       bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
                                               __driver_attach
                                                      driver_match_device(drv, dev)
                                                              //调用总线上的match,检测驱动与设备是否匹配
                                                             drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                       driver_probe_device(drv, dev);
                                                              really_probe(dev, drv);
                                                                      drv->probe(dev); //调用hub.c里面的驱动的probe函数,这里的drv是device_driver结构体,其在usb_register_driver过程中通过new_driver->drvwrap.driver.probe = usb_probe_interface;来设置,这个probe会调用driver中的probe
                                                                            hub_probe
                                                                                  hub_configure(hub, endpoint)
                                                                                         //这里注册了中断,一旦接入新的usb设备就会调用hub_irq
                                                                                         usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp,
                                                                                                   hub_irq,hub, endpoint->bInterval);
           khubd_task = kthread_run(hub_thread, NULL, "khubd"); //启动hub_thread这个线程
                 hub_thread
                        //#define wait_event_freezable(wq, condition)   wait_event_interruptible(wq, condition)
                       //将当前进程加入到等待队列中,进程在这里停下来了,我们需要看看那里唤醒进程
                       wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_sto());
                       //一旦接入新的usb设备,就会调用hub_irq
                             hub_irq
                                   kick_khubd(hub);
                                          wake_up(&khubd_wait);//唤醒等待队列里面的进程,执行hub_events();
                             hub_events();
                                 hub_port_connect_change(hub, i,portstatus, portchange);
                                       hub_port_init(hub, udev, port1, i);
                                             udev = usb_alloc_dev(hdev, hdev->bus, port1);
                                             choose_devnum(udev);//选择usb设备地址
                                                   hub_set_address(udev, devnum);//将选择的地址告诉usb设备
                                                   usb_get_device_descriptor(udev, 8);//获得设备描述符
                                                   usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);//再次获得设备描述符
                                        usb_new_device(udev);
                                                usb_enumerate_device(udev);
                                                       usb_get_configuration(udev);//获得配置信息
                                                        //获得产品信息
                                                       udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
                                                        //获得制造商信息
                                                       udev->manufacturer = usb_cache_string(udev,udev->descriptor.iManufacturer);
                                                        //获得序列号信息
                                                       udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
                                                       device_add(&udev->dev);
                                                            bus_add_device(dev);//将usb设备加入到usb总线旗下的设备列表里面
                                                            bus_probe_device(dev);
                                                                    device_attach(dev);
                                                                           //对所有的驱动,调用__device_attach判断设备与驱动是否匹配
                                                                          bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
                                                                                 driver_match_device(drv, dev)
                                                                                          //调用总线下的match函数来判断设备与驱动时候是否匹配
                                                                                         drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                                                  driver_probe_device(drv, dev);
                                                                                         really_probe(dev, drv);
                            //说明://调用hub.c里面的驱动的probe函数,这里的drv是device_driver结构体,其在usb_register_driver过程中通过new_driver->drvwrap.driver.probe = usb_probe_interface;来设置,这个probe会调用driver中的probe
                                                                                                #drv->probe(dev);//一旦匹配的话就会调用驱动的probe函数(有问题)
     //将generic.c里面的 usb_generic_driver 加入到usb总线下的驱动链表里
     retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
 
下面我们来看看usb总线的match函数:
usb_device_match
        usb_match_id(intf, usb_drv->id_table)
               usb_match_one_id(interface, id)
                     usb_match_device(dev, id)
根据驱动id和设备信息是否匹配来判断是否匹配
 
关于判断匹配,上面的分析中涉及到了两次,第一次匹配时hub.c里面定义的驱动与匹配,第二次是我们自己定义的驱动匹配具体的设备!
第一次hub中也是调用usb_register来注册,发现hub设备匹配id_table时调用hub的probe函数,第二次是设备和我们的驱动
 
由此我们的usb框架就很清楚了,虽然是分为三大块,但是涉及具体的驱动,我们可以分为两层:usb总线驱动层和usb设备驱动层。系统初始化过程中会使usb进程进入休眠,一旦接入usb设备,就会唤醒进程,获取设备的相关信息,然后遍历驱动链表,调用总线的match函数来寻找与设备相匹配的驱动,一旦找到,就会调用驱动的porbe函数!框架很简单,我们写usb驱动,要做的就是写usb设备驱动,而主要的工作就在probe函数里面完成!

12.2 linux USB框架分析(详细注册match匹配过程)的更多相关文章

  1. 【原创】Linux v4l2框架分析

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  2. Android/Linux Thermal框架分析及其Governor对比

    图表 1 Thermal框架 随着SoC性能的快速提升,功耗也极大提高,带来的负面影响是SoC的温度提高很快,甚至有可能造成物理损坏.同时功耗浪费也降低了电池寿命. 从上图可知,Thermal框架可以 ...

  3. Linux Netfilter框架分析

    目录 Netfilter框架 Netfilter的5个hook点 netfilter协议栈数据流分析 连接跟踪conntrack conntrack连接跟踪表条目 连接跟踪表大小 管理连接跟踪表 ip ...

  4. Linux gadget驱动分析1------驱动加载过程

    为了解决一个问题,简单看了一遍linux gadget驱动的加载流程.做一下记录. 使用的内核为linux 2.6.35 硬件为芯唐NUC950. gadget是在UDC驱动上面的一层,如果要编写ga ...

  5. Linux 驱动框架---input子系统框架

    前面从具体(Linux 驱动框架---input子系统)的工作过程学习了Linux的input子系统相关的架构知识,但是前面的学习比较实际缺少总结,所以今天就来总结一下输入子系统的架构分层,站到远处来 ...

  6. Python实例---抽屉后台框架分析

    1.1. 抽屉框架分析 --登陆注册分析 1.2. 前台获取form表单补充知识: <!DOCTYPE html> <html lang="en"> < ...

  7. Linux USB驱动框架分析(2)【转】

    转自:http://blog.chinaunix.net/uid-23046336-id-3243543.html   看了http://blog.chinaunix.net/uid-11848011 ...

  8. Linux USB驱动框架分析 【转】

    转自:http://blog.chinaunix.net/uid-11848011-id-96188.html 初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结 ...

  9. Linux下USB驱动框架分析【转】

    转自:http://blog.csdn.net/brucexu1978/article/details/17583407 版权声明:本文为博主原创文章,未经博主允许不得转载. http://www.c ...

随机推荐

  1. 禁止input输入空格

    仅适用于PC端:$("input").attr("onKeypress","javascript:if(event.keyCode == 32)eve ...

  2. pstree---树状图的方式展现进程

    pstree命令以树状图的方式展现进程之间的派生关系,显示效果比较直观. 语法 pstree(选项) 选项 -a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示: -c:不使用精简标示法: ...

  3. 洛谷 P1981 表达式求值

    P1981 表达式求值 题目描述 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入输出格式 输入格式: 输入文件为 expr.in. 输入仅有一行,为需要你计算的表达式,表达式中只 ...

  4. Android 控件:CheckBox

    首先,在布局文件里注冊CheckBox activity_main.xml <LinearLayout xmlns:android="http://schemas.android.co ...

  5. 利用zip格式实现手机客户端二维码扫描分享识别

    场景: 用户A想要将某应用推荐给用户B,用户B扫描用户A的手机app中的二维码进行下载和安装, 并且需要识别用户B是扫描了用户A的二维码,进而给用户A一定的奖励. (例如:健一网app) zip格式: ...

  6. .NET Entity Framework入门操作

    Entity Framework是微软借鉴ORM思想开发自己的一个ORM框架. ORM就是将数据库表与实体对象(相当于三层中的Model类)相互映射的一种思想. 最大的优点就是非常方便的跨数据库平台. ...

  7. HDU 1007 Quoit Design 平面内最近点对

    http://acm.hdu.edu.cn/showproblem.php?pid=1007 上半年在人人上看到过这个题,当时就知道用分治但是没有仔细想... 今年多校又出了这个...于是学习了一下平 ...

  8. Bag of Features (BOF)图像检索算法

    1.首先.我们用surf算法生成图像库中每幅图的特征点及描写叙述符. 2.再用k-means算法对图像库中的特征点进行训练,生成类心. 3.生成每幅图像的BOF.详细方法为:推断图像的每一个特征点与哪 ...

  9. 微信消息体加解密及EncodingAESKey

    公众平台消息体签名及加解密方案概述 1.新增消息体签名验证,用于公众平台和公众账号验证消息体的正确性 2.针对推送给微信公众账号的普通消息和事件消息,以及推送给设备公众账号的设备消息进行加密 3.公众 ...

  10. 动态规划例子:Maximal Square

    Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...