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