linux usb 子系统(一)

  • 了解usb 子系统

1.USB 概述

  USB,Universal Serial Bus(通用串行总线),是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。USB接口支持设备的即插即用和热插拔功能。USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出的。

1.1.usb 接口
在这里插入图片描述
1.2.USB标准
在这里插入图片描述
1.3.USB总线结构
在这里插入图片描述

  USB总线的拓扑结构如下图所示:USB主机控制器(USB Host Controller)通过根集线器(Root Hub)与其他USB设备相连。集线器也属于USB设备,通过它可以在一个USB接口上扩展出多个接口。除根集线器外,最多可以层叠5个根集线器。一条USB主线上最多可以外接127个设备,当然包括根集线器和其他集线器。整个结构图是一个星型结构,一条USB总线上所有设备共享一条通往主机的数据通道,同一时刻只能有一个设备与主机通讯。

  通过USB主机控制器来管理外接的USB设备。USB控制器实际上由USB控制器硬件+USB控制器软件组成的。USB主机控制器分为3种:UHCI、OHCI、EHCI。UHCI与OHCI支持USB1.1协议;EHCI支持USB2.0协议。UHCI,它的硬件比较简单,所以软件相对就比较复杂;而OHCI,它的硬件具备更多性能,相反的软件做的事情就比较少。

1.4.USB 热插拔
在这里插入图片描述
1.5.USB Architecture

  USB is a master-slave protocol where a host controller communicates with client devices. The USB host controller is part of the South Bridge chipset and communicates with the processor over the PCI bus.
在这里插入图片描述
Figure 1. USB in the PC environment.

2.USB 驱动架构
在这里插入图片描述
  根据以上知识可以知道其实USB驱动程序可以分为两类:USB主机控制器驱动程序(Host Controller Drivers)、USB设备驱动程序(USB device drivers)。

2.1.USB HCD(Host Controller Driver)

  USB主机控制器属于南桥芯片的一部分,通过PCI总线和处理器通信。USB主机控制器分为UHCI(英特尔提出)、OHCI(康柏和微软提出)、 EHCI。其中OHCI驱动程序用来为非PC系统上以及带有SiS和ALi芯片组的PC主办上的USB芯片提供支持。UHCI驱动程序多用来为大多数其他PC主板(包括Intel和Via)上的USB芯片提供支持。ENCI兼容OHCI和UHCI。UHCI的硬件线路比OHCI简单,所以成本较低,但需要较复杂的驱动程序,CPU负荷稍重。主机控制器驱动程序完成的功能主要包括:解析和维护URB,根据不同的端点进行分类缓存URB;负责不同USB传输类型的调度工作;负责USB数据的实际传输工作;实现虚拟跟HUB的功能。

  硬件主机控制器Host Controller之上运行的是HCD,是对主机控制器硬件的一个抽象,实现核心层与控制器之间的对话接口,USB HCD包含多种USB接口规范:

  • UHCI:Intel提供,通用主机控制接口,USB1.0/1.1;

  • OHCI:微软提供,开放主机控制接口,USB1.0/1.1;

  • EHCI:增强主机控制接口,USB2.0;

2.2.USB Core

  USB Core这个模块是纯软件部分,并不代表一个设备,是独立于硬件的协议栈,它是所有USB设备赖以生存的模块,即USB子系统的核心。代码位于kernel/drivers/usb/core目录下。

  USB Core为设备驱动程序提供服务,提供一个用于访问和控制USB硬件的接口,而不用考虑系统当前使用的哪种HOST Controller。USB Core将用户的请求映射到相关的HCD,用户不能直接访问HCD。USB Core就是HCD与USB设备的桥梁。

2.3.USB Device Driver

USB设备驱动框架如下图所示:
在这里插入图片描述
  USB设备是由一些配置(configuration)、接口(interface)和端点(endpoint)组成,,即一个USB设备可以含有一个或多个配置,在每个配置中可含有一个或多个接口,在每个接口中可含有若干个端点。一个USB设备驱动可能包含多个子驱动。一个USB设备子驱动程序对应一个USB接口,而非整个USB设备。

  USB设备使用各种描述符来说明其设备架构,包括设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符。后面单独讨论USB设备描述符。

  USB传输的对象为端点(endpoint),每一个端点都有传输类型,传输方向,除了端点0外,每一个端点只支持一个方向的数据传输,端点0用于控制传输,既能输出也能输入。输入(IN)、输出(OUT) “都是” 基于USB主机的立场说的。比如鼠标的数据是从鼠标传到PC机, 对应的端点称为"输入端点"。

  USB的传输类型:

  • a. 控制传输:可靠,时间有保证,比如:USB设备的识别过程

  • b. 批量传输: 可靠, 时间没有保证, 比如:U盘

  • c. 中断传输:可靠,实时,比如:USB鼠标

  • d. 实时传输:不可靠,实时,比如:USB摄像头

  针对不同类型的USB设备,需要实现特定的USB驱动程序。如HID(Human Interface Device), 属于人机交互类的设备,如USB鼠标,USB键盘等。该类设备必须遵循HID设计规范。

3.USB设备识别过程

  定时轮询方式,当定时时间到了运行定时器程时指定的定时器rh_timer的function函数rh_timer_func。

->rh_timer_func 
  ->usb_hcd_poll_rh_status                    //hcd.c
    ->hcd->driver->hub_status_data(hcd, buffer)
    ->usb_hcd_unlink_urb_from_ep(hcd, urb);
    ->usb_hcd_giveback_urb(hcd, urb, 0)
         ->usb_giveback_urb_bh();            //tasklet_hi_schedule(&bh->bh);
            ->__usb_hcd_giveback_urb(urb);
              ->urb->complete(urb);       //hub_irq
                ->hub_irq //hub.c  usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
                  ->kick_hub_wq(hub);
                    ->hub_event //INIT_WORK(&hub->events, hub_event);
                      ->port_event(hub, i);
                        ->hub_port_connect_change
                          ->hub_port_connect
                            ->hub_port_init
                            ->usb_new_device(udev);
                              ->usb_enumerate_device(udev);//开始枚举
                              ->device_add(&udev->dev);//枚举完毕后加载设备驱动

Note:
使用定时器查询的主要原因是USB没有中断USB控制器的能力,所以当USB设备接入之后,获取USB输入的信息是无法通过中断方式来获取,只能通过定时器定时轮训获取。当USB设备未插入时,定时器rh_timer会停止,直到USB插入之后,再次开启定时查询USB设备输入的信息。

refer to

  • https://zhuanlan.zhihu.com/p/61079354

猜你喜欢

转载自blog.csdn.net/weixin_41028621/article/details/109121099