您现在的位置是:首页 >技术教程 >EFI Driver Model(下)-USB 驱动设计网站首页技术教程

EFI Driver Model(下)-USB 驱动设计

miachen-空中飞鸟 2023-06-05 00:00:02
简介EFI Driver Model(下)-USB 驱动设计

1、USB简介

  通用串行总线(英语:Universal Serial Bus,缩写:USB)是一种串口总线标准,也是一种输入输出接口的技术规范,被广泛地应用于个人电脑和移动设备等信息通讯产品,并扩展至摄影器材、数字电视(机顶盒)、游戏机等其它相关领域。最新一代是USB4,传输速度为40Gbit/s,三段式电压5V/12V/20V,最大供电100W ,新型Type C接口允许正反盲插。
  USB是一个外部总线标准,规范电脑与外部设备的连接和通讯。USB接口具有热插拔功能。USB接口可连接多种外设,如鼠标和键盘等。USB是在1994年底由英特尔等多家公司联合在1996年推出后,已成功替代串口和并口,已成为当今电脑与大量智能设备的必配接口。USB版本经历了多年的发展,到如今已经发展为USB4版本。对于大多数工程师来说,开发USB2.0接口产品主要障碍在于:要面对复杂的USB2.0协议、自己编写USB设备的驱动程序、熟悉单片机的编程。这不仅要求有相当的VC编程经验、还能够编写USB接口的硬件(固件)程序。所以大多数人放弃了自己开发USB产品。

2、USB枚举

USB Host

  一个USB系统只有一个USB Host。主计算机中的USB接口称为主控制器(Host Controller)。这个接口不是指USB端口,而是指USB系统和主计算机之间的连接接口,可能是由硬件、固件、软件组成。

USB bus

  被实现为Host Controller,且集成有Root Hub
  USB 接入后,进行USB枚举过程

  • 1、 hub 通过status change 管道(寄存器)反馈给host有设备接入或移除,device处于powered状态,port处于disabled状态。
  • 2、host检查change状态来查询是有设备接入还是移除。
  • 3、host确定有新设备接入之后,等待至少100ms来等待接入状态稳定和供电稳定;然后host发送 reset 端口命令。
  • 4、hub执行reset 端口命令,reset完成后端口被enable。此时device处于default状态并能从端口获取电流。
  • 5、host给device分配一个唯一的address,device进入Address状态。
  • 6、host读取device的设备描述符信息来去确定设备所支持的最大数据包大小。
  • 7、host读取device的配置信息,从配置0开始读到配置n-1。
  • 8、host根据配置信息以及如何使用usb device来设置device使用哪种配置。此时device处于configured状态,也即处于可用状态了。

3、USB驱动设计

  有几个类别的USB驱动程序合作在一个平台上提供USB驱动程序堆栈。下表列出了这些USB驱动程序

驱动类别描述
USB主控制器驱动使用USB主机控制器句柄上的PCI I/O协议,并生成USB2主机控制器协议。
USB bus driver使用USB2主机控制器协议,并为USB总线上的每个USB控制器生成一个子句柄。在每个子句柄上安装设备路径协议和USB I/O协议。
USB 设备驱动使用USB I/O协议,并生成一个I/O抽象,该抽象为启动符合EFI的操作系统所需的控制台设备和引导设备提供服务。

  下图显示了一个USB驱动程序堆栈以及USB驱动程序使用和生成的协议的示例。因为USB集线器是一种特殊的设备,它只是作为一个信号中继器,所以它不包括在图21中。

  在此示例中,平台硬件在PCI总线上提供了单个USB主机控制器。PCI总线驱动程序为这个USB主机控制器安装了EFI_DEVICE_PATH_PROTOCOL和EFI_PCI_IO_PROTOCOL的句柄。然后,USB主机控制器驱动程序在该USB主机控制器设备句柄上使用EFI_PCI_IO_PROTOCOL,并将EFI_USB2_HC_PROTOCOL安装到同一句柄上。
  USB总线驱动程序使用EFI_USB2_HC_PROTOCOL的服务。它使用此服务来枚举USB总线。在此示例中,USB总线驱动程序检测USB键盘、USB鼠标和USB大容量存储设备。因此,USB总线驱动程序创建三个子句柄,并将EFI_DEVICE_PATH_PROTOCOL和EFI_USB_IO_PROTOCOL安装到每个句柄上。

  USB鼠标驱动程序消耗EFI_USB_IO_PROTOCOL并生成EFI_SIMPLE_POINTER_PROTOCOL。USB键盘驱动程序使用EFI_USB_IO_PROTOCOL来生成EFI_SIMPLE_TEXT_INPUT_PROTOCOL。

  USB大量存储驱动程序使用EFI_USB_IO_PROTOCOL来生成EFI_BLOCK_IO_PROTOCOL。
在这里插入图片描述
在这里插入图片描述

3.1、USB Host Controller Driver

USB主机控制器驱动程序取决于主机控制器所基于的哪个USB主机控制器规范。目前,USB主机控制器的主要类型如下:

  • Open Host Controller Interface (OHCI) (USB 1.0 and USB 1.1)
  • Universal Host Controller Interface (UHCI) (USB 1.0 and USB 1.1)
  • Enhanced Host Controller Interface (EHCI) (USB 2.0)
  • Extended Host Controller Interface (XHCI) (USB 3.0)

USB主机控制器驱动程序是一个设备驱动程序,并遵循UEFI驱动程序模型。它通常使用EFI_PCI_IO_PROTOCOL的服务并生成EFI_USB2_HC_PROTOCOL。以下部分提供了为USB主机控制器驱动程序实现EFI_DRIVER_BINDING_PROTOCOL服务和EFI_USB2_HC_PROTOCOL服务的指南。EDK II提供了UEFI驱动程序,在MdeModulePkg中实现UHCI、ECHI和XHCI的EFI_USB_HC2_PROTOCOL:

  • UHCI - MdeModulePkg/Bus/Pci/UhciDxe
  • EHCI - MdeModulePkg/Bus/Pci/EhciDxe
  • XHCI - MdeModulePkg/Bus/Pci/XhciDxe

3.1.1、EFI_USB2_HC_PROTOCOL

  EFI_USB2_HC_PROTOCOL提供USB主机控制器管理,基本通过USB总线的数据事务以及USB根集线器访问。设备驱动程序希望在系统中管理USB总线的检索EFI_USB2_HC_PROTOCOL与要管理的USB总线相关联的实例。设备句柄对于USB主机控制器,将至少包含一个EFI_DEVICE_PATH_PROTOCOL实例和EFI_USB2_HC_PROTOCOL实例。

struct _EFI_USB2_HC_PROTOCOL {
  EFI_USB2_HC_PROTOCOL_GET_CAPABILITY              GetCapability;
  EFI_USB2_HC_PROTOCOL_RESET                       Reset;
  EFI_USB2_HC_PROTOCOL_GET_STATE                   GetState;
  EFI_USB2_HC_PROTOCOL_SET_STATE                   SetState;
  EFI_USB2_HC_PROTOCOL_CONTROL_TRANSFER            ControlTransfer;
  EFI_USB2_HC_PROTOCOL_BULK_TRANSFER               BulkTransfer;
  EFI_USB2_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER    AsyncInterruptTransfer;
  EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER     SyncInterruptTransfer;
  EFI_USB2_HC_PROTOCOL_ISOCHRONOUS_TRANSFER        IsochronousTransfer;
  EFI_USB2_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER  AsyncIsochronousTransfer;
  EFI_USB2_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS     GetRootHubPortStatus;
  EFI_USB2_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE    SetRootHubPortFeature;
  EFI_USB2_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE  ClearRootHubPortFeature;

  ///
  /// The major revision number of the USB host controller. The revision information
  /// indicates the release of the Universal Serial Bus Specification with which the
  /// host controller is compliant.
  ///
  UINT16                                           MajorRevision;

  ///
  /// The minor revision number of the USB host controller. The revision information
  /// indicates the release of the Universal Serial Bus Specification with which the
  /// host controller is compliant.
  ///
  UINT16                                           MinorRevision;
};

GetCapability: 获取控制器的能力支持,如最大传输速度,root hub的端口数目,是否支持64位mem寻址等。
Rest: 复位host controller
GetState: 获取host controller的状态,如halt,suspend还是operational
SetState: 设置host controller的状态
ControlTransfer: 控制传输函数
**BulkTransfer:**块传输函数
**AsyncInterruptTransfer:**异步中断传输函数,以固定的速率获取设备的状态,即提交一次传输请求之后会周期性执行。
**SyncInterruptTransfer:**同步中断传输函数,提交一次中断传输请求,只执行一次。
IsochronousTransfer: 同步传输函数。用于host和device之间周期性的,连续的通信。一个frame之内完成,未完成返回timeout。
AsyncIsochronousTransfer: 异步类型的同步传输。提交一次传输请求后立刻返回,传输真正完成时触发回调函数,查看传输结果和数据。
**GetRootHubPortStatus:**获取root hub port状态,包括connect, enable, suspend, oc, reset ,power, speed以及change状态。
SetRootHubPortFeature: 设置root hub port 特性。包括enable, suspend, power等。
**ClearRootHubPortFeature:**清除root hub port特性。包括enable, suspend, reset, power, owner, connectchange, enable change…

3.2、USB Bus Driver

  EDK II包含一个通用的USB总线驱动程序。该驱动程序使用EFI_USB2_HC_PROTOCOL的服务来枚举USB设备,并使用EFI_DEVICE_PATH_PROTOCOL和EFI_USB_IO_PROTOCOL产生子句柄。USB总线驱动程序的实现可以在MdeModulePkg的目录下的MdeModulePkg/总线/Usb/UsbBusDxe中找到。
  USB集线器,包括USB根集线器和公共集线器,是一种USB设备。USB总线驱动程序负责管理所有的USB集线器设备。USB集线器设备不需要USB设备驱动程序。
  如果基于UEFI的系统固件移植到一个新平台,大多数与USB相关的更改都发生在USB主机控制器驱动程序的实现中。如果引入了提供控制台或UEFI引导功能的新型USB设备,则还需要实现新的USB设备驱动程序。
USB总线驱动程序被设计为一个通用的、与平台无关的驱动程序。因此,我们强烈反对自定义USB总线驱动程序。

3.2.1 EFI_USB_IO_PROTOCOL

  EFI_USB_IO_PROTOCOL提供了描述的四种基本传输类型在USB 1.1规范中。其中包括控制传输、中断转移、批量转移和同步转移。EFI_USB_IO_PROTOCOL还提供了一些基本的USB设备/控制器管理和配置接口。USB设备驱动程序使用此协议的服务来管理USB设备。

struct _EFI_USB_IO_PROTOCOL {
  //
  // IO transfer
  //
  EFI_USB_IO_CONTROL_TRANSFER           UsbControlTransfer;
  EFI_USB_IO_BULK_TRANSFER              UsbBulkTransfer;
  EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER   UsbAsyncInterruptTransfer;
  EFI_USB_IO_SYNC_INTERRUPT_TRANSFER    UsbSyncInterruptTransfer;
  EFI_USB_IO_ISOCHRONOUS_TRANSFER       UsbIsochronousTransfer;
  EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER UsbAsyncIsochronousTransfer;

  //
  // Common device request
  //
  EFI_USB_IO_GET_DEVICE_DESCRIPTOR      UsbGetDeviceDescriptor;
  EFI_USB_IO_GET_CONFIG_DESCRIPTOR      UsbGetConfigDescriptor;
  EFI_USB_IO_GET_INTERFACE_DESCRIPTOR   UsbGetInterfaceDescriptor;
  EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR    UsbGetEndpointDescriptor;
  EFI_USB_IO_GET_STRING_DESCRIPTOR      UsbGetStringDescriptor;
  EFI_USB_IO_GET_SUPPORTED_LANGUAGE     UsbGetSupportedLanguages;

  //
  // Reset controller's parent port
  //
  EFI_USB_IO_PORT_RESET                 UsbPortReset;
};

UsbGetDeviceDescriptor:获取设备描述符。
UsbGetConfigDescriptor:获取配置描述符。
UsbGetInterfaceDescriptor:获取接口描述符。
UsbGetEndpointDescriptor:获取断点描述符。
UsbGetStringDescriptor:获取字符串描述符。
UsbGetSupportedLanguages:获取设备支持的语言。

3.3、USB Device Driver

  USB设备驱动程序使用EFI_USB_IO_PROTOCOL提供的服务来产生一个或多个协议,以提供USB设备的I/O抽象。USB设备驱动程序必须遵循UEFI驱动程序模型。如上所述,USB设备驱动程序不管理集线器设备,因为这些集线器设备是由USB总线驱动程序管理。EDK II在MdeModulePkg中提供了许多USB设备驱动程序,设备通常用于提供UEFI控制台和UEFI启动设备。EDK II MdePkg还提供了一个名为UefiUbLib的库,它提供了使用USB I/O协议简化USB设备驱动程序的实现的功能。在EDK II中提供的一些USB设备驱动程序实现如下:

  • USB Keyboard: MdeModulePkg/Bus/Usb/UsbKbDxe
  • USB Mouse: MdeModulePkg/Bus/Usb/UsbMouseDxe
  • USB Mouse: MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe
  • USB Mass Storage: MdeModulePkg/Bus/Usb/UsbMassStorageDxe
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。