• USB主机驱动器分析


    一、USB总线

            系统启动 -》初始化usb子系统 -》向内核注册USB总线 -》向USB总线中注册3个usb驱动(分别是USB接口驱动、HUB驱动、USB设备驱动)。

            主机驱动注册为platform平台驱动 -》遍历平台总线的设备链表,执行platform的.match函数(platform_match)进行匹配,成功后执行.probe函数(ohci_hcd_s3c2410_drv_probe) -》在此函数中再遍历usb总线的驱动链表,执行.match函数(usb_device_match),成功后执行.probe函数(预先注册的3个usb驱动) -》检测其他usb设备插拔。。。

    //----------------------------------------USB BUS------------------------------------

    【USB总线注册】

    // usb_bus_type提供了驱动和设备匹配的匹配函数

    1. retval = bus_register(&usb_bus_type);
    2. struct bus_type usb_bus_type = {
    3.         .name =     "usb",
    4.         .match =    usb_device_match, // 内部会将 设备驱动 和 接口驱动 分开匹配(提高效率)
    5.         ... ...
    6. };

    //使用bus_register接口注册USB总线,会创建出两条链表用来分别存放向USB总线注册的设备和驱动。

    1. klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
    2. klist_init(&bus->klist_drivers, NULL, NULL);

    1、在usb总线注册USB接口驱动,该驱动被放在usb总线的驱动链表中。(一个设备可以注册多个接口驱动

    // 注册usbfs接口驱动,提供了在用户空间直接访问USB硬件设备的接口,完成USB设备在用户空间的映射

    1. retval = usb_register(&usbfs_driver);
    2. struct usb_driver usbfs_driver = {
    3.     .name =     "usbfs",
    4.     .probe =    driver_probe, // .match成功后,执行
    5.     .disconnect =   driver_disconnect,
    6. ... ...
    7. };

    2、在usb总线注册一个hub接口驱动,该驱动被放在usb总线的驱动链表中。

    1. retval = usb_register(&hub_driver);
    2. khubd_task = kthread_run(hub_thread, NULL, "khubd");// 创建一个死循环线程hub_thread,用来处理USB设备的断开、连接等事件
    3. static struct usb_driver hub_driver = {
    4.     .name =     "hub",
    5.     .probe =    hub_probe, // 通过usb_fill_int_urb创建urb请求块同时注册了一个中断处理函数hub_irq,用来唤醒hub_thread线程来处理USB设备事件(热插拔)
    6.     .disconnect =   hub_disconnect,
    7. ... ...
    8. };

    3、在usb总线注册通用USB设备驱动,该驱动被放在usb总线的驱动链表中。

    1. retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
    2. struct usb_device_driver usb_generic_driver = {
    3.     .name = "usb",
    4.     .probe = generic_probe, // 通用USB设备匹配成功后执行
    5.     .disconnect = generic_disconnect,
    6. ... ...
    7. };

    二、USB主机驱动

    【主机驱动器HCD】——platform模型

    USB HCD注册在 平台总线 上。用来处理主机控制器的初始化以及数据的传输,并监测外部设备插入、拔出,完成设备枚举。

    1、设备(或者采用设备树描述

    1. struct platform_device s3c_device_usb = {
    2.     .name       = "s3c2410-ohci",
    3. .resource     = s3c_usb_resource
    4. ... ...
    5. };
    6. platform_add_devices(); // 注册设备信息

    2、主机驱动注册

    1. retval = platform_driver_register(&ohci_hcd_s3c2410_driver); //内部会调用platform_match 进行驱动-设备匹配
    2. struct platform_driver ohci_hcd_s3c2410_driver = {
    3.     .probe      = ohci_hcd_s3c2410_drv_probe,
    4.     .remove     = ohci_hcd_s3c2410_drv_remove,
    5.     .shutdown   = usb_hcd_platform_shutdown,
    6.     .driver     = {
    7.         .owner  = THIS_MODULE,
    8.         .name   = "s3c2410-ohci",
    9.     },
    10. ... ...
    11. };

    3、 平台总线:此处的platform总线(虚拟总线)完成 USB主机控制器 的驱动和设备匹配.

           USB BUS的USB总线是完成 设备驱动与设备信息 的匹配.

    1. struct bus_type platform_bus_type = {
    2. .name = "platform",
    3. .match = platform_match,
    4. ... ...
    5. };

            调用platform_driver_register函数注册主机控制器驱动后,遍历平台总线的设备链表,调用platform_match进行设备-驱动匹配,匹配上后会调用驱动的ohci_hcd_s3c2410_drv_probe函数。

           ohci_hcd_s3c2410_drv_probe流程解析:遍历usb总线的驱动链表,调用usb_device_match进行匹配(第一节的USB总线),匹配成功后执行设备驱动的.probe函数。如执行USB通用设备驱动函数generic_probe。

     

    //-------------------------------------------------------------------------------------------------------

    驱动开发中,所有注册的USB设备,都是向USB总线注册,由USB总线实现驱动-设备的匹配。

    入门级的设备驱动程序可以看上篇文章的分析—— 内核鼠标驱动源码。

     

  • 相关阅读:
    二手物品交易管理系统
    【827. 最大人工岛】
    Pytorch实现MNIST字符识别
    教程 - 深度探讨在 Vue3 中引入 CesiumJS 的最佳方式
    JS中Class类的静态属性和静态方法
    辉芒微IO单片机FT60F12F-MRB
    uniapp模仿下拉框实现文字联想功能 - uniapp输入联想(官方样式-附源码)
    农业产业谋定颠覆与重构-国稻种芯-万祥军:现代农业发展前景
    AHP层次分析法在水利中的实践
    Css实现文字的高亮
  • 原文地址:https://blog.csdn.net/qq_42911741/article/details/132833794