摘要:从问题的由来、类驱动程序、通信协议、描述符、驱动开发等对USB的驱动进行分析和讨论,提出USB设备使用操作系统嵌入的通用类驱动程序成为趋势。
关键词:USB
类驱动程序 人工接口设备(HID) Windows驱动程序模型(WDM) 最初设计USB(Universal Serial Bus)这种外设总线的目的之一就是为了便于使用,这是计算机发展的产物。外设总线最重要的就是操作系统对外设的自动识别、配置,实现热插拔,即插即用。本文试图以人工接口设备(Human
interface device,简称HID)为主,从问题的由来、类驱动程序、通信协议、描述符、驱动开发等几个方面来探讨一下USB设备的驱动问题。 1 问题的由来 一个非常简单的设备安装有时得花用户好几天时间,原因何在?设备的驱动与其他的驱动程序或软件不兼容,或隐有bug。如果操作系统本身就含有用户需要的驱动程序,设备一插就能使用,这是最好不过的事情。 现已有上千种不同的设备, 通过定义不同的设备类型,USB试图实现通用驱动程序这一目标。在USB规范里,除定义了基本的协议和构造用来配置设备和传输数据,还为所有的USB设备定义了机械和电器件性能要求。USB规范定义了通信、打印、图像、储存、音频和人工接口设备等类。一些设备是单一的类,一些是多种类的综合体。具有多种类的设备称为混合设备,在USB规范对设备有详细的划分。 2 类驱动程序 由于一些类尚未形成标准,Win2000只包含了部分USB类的驱动程序。一旦形成标准得到认可,通用的驱动程序也就自然嵌入到操作系统了。图1为操作系统中USB驱动接口框图。这是一个标准的Windows驱动程序模型(WDM),是一种分层模式。核心USB
Driver Stack模型描述设备如何安装和启动,以及如何为用户请求服务和与硬件打交道,并为上层USB驱动提供接口。上层驱动完成设备功能并为用户层提供接口,这使得向USB总线发出请求是通过多层结构。 HID类是为一些人工的输入或输出设备而设计的,最常用的象键盘、鼠标、游戏控制器。这种类同时也包含了前面板显示区和键盘区(象电话或VCR远程控制),还有触觉和听觉反馈设备。对于HID类的设备,操作系统已经给出了相应的驱动程序。 连接到计算机的USB设备几乎都包含HID类,用以信号控制。比如一个USB扬声器,音量、音调控制用HID类,但音频数据传输用音频类。 通常情况下,USB设备与主机通信是经过USB端口,类驱动程序无须担心或考虑ISA总线、PCI总线、SCSI、IDE或ATAPI接口、串口、并口、键盘或鼠标口、游戏接口及相关的一些东西。类驱动程序甚至不需要了解SUB端口,这个物理接口被USB主机驱动程序管理形成抽象层,也正因为这个抽象层及其他相应层,使通用使驱动程序成为可能。每一层有自己的功能,并为上一层提供了API接口,上层没有必要了解下一层如何工作及内部体系结构,各层为一个封装体。 图2所示为USB各层之间通信流程。USB用明确定义了的层协议来减少复杂化且有利于标准化,各层均有连接,但大多为逻辑型的。最低层的是USB主机控制器和USB设备接口之间的物理连接,包括连接线、连接器、状态机。其次在计算机方面为USB主机驱动程序,这是操作系统所必须的。在设备方是用于设备管理和请求的固件程序(Firmware),此层是配和和控制USB接口的逻辑连接。第三层在主机方是设备驱动程序,通常称为类驱动程序;在设备方是类属性的固件程序,通过逻辑连接用于特殊类的控制和请求。最顶层为用户层,为用户所关心和考虑,比如在主机客户方为飞行模拟仿真,在设备方则为操纵杆。此时用户所关心的是操纵杆的输入,不用考虑这些输入如何读、如何打包、如何传输。 3 通信协议 与USB设备进行通信,主机软件打开一系列的管道来传输数据。不同的管道对应于USB的不同端口(endpoint)。USB有四种传输方式,分别为控制、中断、同步和批量,每种方式对应各自的管道。除同步方式外,均有握手信号,保证了数据传输的准确性。 一般的USB设备通常用控制、中断或数据管理,如图3所示。 每一种数据传输方式中包含了多个事务数据,这些数据被综合完成一定功能。一个事务数据由三个部分组成:信令包段(Token
Packet phase)、数据包段(Data Packet phase)、握手信号包段(Handshade
Packet phase)。信令包定义了事务的类型,设备的地址也包含在其中。一些信令包单独存在,后面没有跟别的包。数据包里包含了与传输有关的负载。在单个的事务数据最大承载1023个字节。 基于相同的管道配置和命令、通用的API接口,USB设备通用驱动程序得以实现,设备之间的差异则使返回的数据结构不同。 4 描述符 USB设备用预先定义好的数据结构来表示他们的标识符、性能、请求和协议,通常称为描述符。设备一插入到主机,操作系统就能立刻根据描述符找到与之相对应的类驱动程序,完成USB设备的枚举及其他功能。在USB规范里定义了必要的设备、配置、接口、端口、字符串描述。HID类除些之外又定义了报告描述符。报告描述符提供了HID类驱动程序能理解和解释的报告,报告虽然灵活但却很复杂。描述符可用固件程序来写,编译生成二进格式后储存到设备中使用,便于类驱动识别和解释。 下面是作者设计的一个利用EZUSB芯片提供的I2C连接多部医监设备的报告描述符。图4为报告描述符所表达的数据结构。 ReportDescriptor: ; Generated with HID
Tool,copoed to here DB 6,0,0FFH ; Usage_Page (Vendor Defined) DB 9,1 ; Usage (I/O Device) DB 0A1H,1 ;Collection (Application) DB 19H,1 ; Usage_Minimum DB 29H,2 ; Usage_Maximum DB 15H,0 ;Logical_Minimum (0) DB 26H,255,0 ; Logical_Maximum (255) DB 75H,8 ; Report_Size (8) DB 95H,1 ; Report_Count (1) = Read Address DB 81H,2 ; Input (Data,Var,Abs) DB 19H,1 ; Usage_Minimum DB 29H,2 ; Usage_Maximum DB 95H,2 ; Report_Count (2) =Write
Address+Data DB 91H,2 ; Output (Data,Var,Abs) DB 0C0H ; End_Collection ReportLength EQU $-ReportDescriptor 5 驱动程序的开发 对于USB设备来说,开发驱动程序是一件比较复杂的事情。通常驱动程序要实现以下的功能: ·设备的初始化; ·即插即用创建和删除设备; ·处理Win32打开和关闭文件句柄的请求; ·类功能定义IOCTL(I/O Control)、功能实现; ·IRP(I/O Request Packet)的调用处理; ·调用其他的驱动程序; ·访问硬件。 USB驱动程序设计的核心是端点(Endpoint)及数据传输类型的选择,通过端点建立起管道通信,实现定义的功能。这样,在应用层和设备之间就建立起了虚拟的通道,所有这些通过多线程的句柄调用实现。 每个驱动程序都必须有一个DriverEntry入口函数,用于系统调用。 NTSTATUS DriverEntry(IN PDRIVER_OBJECT
DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; // Export other driver entry points... DriverObject->DriverUnload = USBUnload; DriverObject->MajorFunction[IRP_MJ_CREATE]=USBCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE]=USBClose; DriverObject->MajorFunction[IRP_MJ_READ]=USBRead; DriverObject->MajorFunction[IRP_MJ_WRITE]=USBWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=USBDeviceControl; RegisterForPnpNotification(DriverObject); Return status; } 写驱动程序的软件较多,目前比较流行的软件是DriverStudio、WinDriver等。它们均提供用于生成USB驱动的代码生成器,用户按照提示可以定义设备的配置和功能,然后做功能修改即可。利用软件提供的例子进行修改也是一个比较好的捷径。 USB技术的应用,是计算机产业的一大发展。目前以微软为代表的各大公司积极对其进行开发,使得应用越来越广泛。微软操作系统集成了HID类、音频类的USB驱动程序。作者用EZUSB以HID类连接医监设备,不用写驱动程序在Win2000上运行良好。针对开发USB器件的需要,作者根据HID规范定义了自己特殊的类并重新写上写的类驱动程序,测试较为满意。从长远的角度来看,操作系统通过集成类驱动程序来支持各种USB设备势在必行。 |