Windows2000下USB接口的IC卡读写装置客户程序设计
2008-12-04
作者:张建新
摘 要: 分析了Windows2000下USB客户程序的框架,并就如何开发Windows2000下USB接口的IC卡读写装置客户程序进行了阐述。
关键词: USB总线 客户程序 IC卡 Windows2000
IC卡是高科技的产物,它广泛用于银行、电信、交通运输、小区管理、校园管理等领域,体现了它的巨大优越性。作者在开发一个IC卡机房收费系统时遇到了新问题,那就是当计算机和IC卡装置通信的时候,如果采用传统的串行通信方式固然可行,但供电必须采用单独的外置电源,这样加大了读卡装置的体积。通过翻阅资料发现USB接口可以输出5V电压、500mA的电流,能满足IC卡装置对电源的要求。另外,USB接口和Windows2000操作系统能良好地融合,支持即插即用和电源管理的新特性,使得其与主机的相连日趋简单和轻松。因此决定开发USB接口的IC卡读写装置,一方面可以解决供电问题,使读写装置使用方便;另一方面也可以满足其它方面的性能需求。
USB需要主机硬件、操作系统和外部设备三个方面的支持才能工作。目前主板一般都有支持USB功能的控制芯片组和USB接口插座。微软" title="微软">微软Win9x操作系统以及Windows2000均支持USB,并提供了底层的驱动程序,新版的Linux也支持USB。在USB设备方面,目前有许多公司生产支持USB的微控制器" title="微控制器">微控制器,比较著名的有Motorola公司的MC68HC05系列,Intel公司的80931HA,Cypress公司的CY7C63系列等。可以说,USB的发展已得到各软硬件厂商的支持,前景光明。
1 Windows2000下的USB架构
主机要使用USB设备,必须有驱动程序。微软操作系统中,Windows98支持USB,WindowsNT4.0不支持USB,NT5.0(Windows2000)支持USB。Windows2000和Windows98对USB的支持主要是基于WDM(Windows驱动程序模型)技术,因此USB驱动程序是WDM驱动程序。WDM驱动程序采用分层结构,由两部分组成,一个为功能驱动程序,即通常所说的驱动程序,它负责指挥硬件工作,由类驱动程序和小类驱动程序构成;另外一个为总线驱动程序,它负责管理计算机和硬件之间的连接。在功能驱动程序上层和下层,一些设备还具有过滤驱动程序。它们的作用是监视功能驱动程序执行I/O操作及修改已有的功能驱动程序。
Windows2000 USB驱动程序框架由USB功能驱动程序和USB总线驱动程序组成。USB总线驱动程序由Windows2000提供,包括USB主控制器驱动程序(OPENHCI.SYS 或 UHCD.SYS,它们分别支持不同的USB主控制器)、USB HUB驱动程序(USBHUB.SYS)以及为控制器驱动程序使用的类驱动程序 (USBD.SYS)。它们一起组成了USB驱动程序栈,可为所有的USB设备驱动程序共用。用户或厂商所写的针对特定USB设备的WDM 驱动程序称为功能驱动程序或客户驱动程序(位于USB驱动程序栈的上层)。它并不直接访问硬件,而是调用驱动程序栈完成对硬件的操作。USB驱动程序栈通过USBDI(USB Driver Interface)向客户驱动程序提供WDM系统服务。
Windows2000下USB驱动程序栈如图1所示。
有过驱动程序编制经验的人都知道,编写驱动程序是一项需要较高技巧并且很繁琐的工作。对于某一些USB规范定义的类设备,微软提供了类驱动程序,负责该类设备的设备驱动。对于这类设备,系统能够自动识别它们,并不需要附加额外的驱动程序,用户只需编写普通的Win32程序即可对其进行访问。目前,Windows2000为HID(Human Input Device人工输入设备)类、音频设备类等提供了类驱动程序。
HID设备,顾名思义是指那些能被人们用来直接输入数据给计算机的设备,例如键盘、鼠标、游戏杆及其他虚拟现实设备如数据手套等。尽管HID设备概指人工输入设备,但是那些传输数据量较小、传输速度" title="传输速度">传输速度较慢的设备,因与输入设备类似,也可归类为人工输入设备,例如远程控制设备、面板等。IC卡读写装置与计算机之间的数据交换具有量小、传输速度慢、双向传输的特点,因而可归类为HID设备。HID设备包括USB接口的设备及其他接口的设备。USB类规范中详细定义了USB接口的人工输入设备类标准及HID设备的用法表,任何USB接口的HID应该遵循这个规范。
Windows98仅支持USB接口的HID设备;Windows 2000支持USB接口的HID及其他接口的HID设备,Windows2000为人工输入设备类提供的支持包括:
(1)Windows2000包含HID驱动程序(hidclass.sys 及hidusb.sys,Hidparse.sys)文件,为USB接口的HID设备提供内置的驱动程序支持。
(2)Windows2000提供了HID.dll,为用户模式及内核模式的程序提供了一些可用的API(应用程序接口)和DDI(设备驱动程序接口),可用来编写基于HID类的应用程序。
(3)对非USB接口或非HID设备可通过编写小类驱动程序间接使用HID类驱动程序,省去了重新编写类驱动程序的麻烦。
因此,对于USB接口的HID设备,通常用户只需要编写用户模式的客户程序,使用Win32 API函数对USB HID设备进行操作,不需要再编写额外的驱动程序。但在有些情况下,用户也需要编写一些基于HID类驱动程序的内核客户驱动程序。譬如,需要向HID设备发送命令而不仅仅是读取或写入数据时,可能需要编写内核模式的HID程序。对于本IC卡读写装置,由于只涉及到一般的数据读写操作(将数据在IC卡和主机之间双向传递),以及较少量的控制操作,并不需要编写内核模式的客户驱动程序。
图2是客户程序与IC卡读写装置的交互过程。
2 USB接口的 HID客户程序
这里说的客户程序是指在主机上运行,负责和USB设备通信的那部分程序。包括两种类型:用户模式下的客户程序以及内核模式下的客户驱动程序。USB HID客户程序执行两大主要任务:设备枚举和设备操作。设备枚举是指客户程序和USB设备交互,获取其配置信息,譬如设备有几个配置,每个配置包括多少接口等,并执行一些操作如选择配置,这期间主要是与各类描述符" title="描述符">描述符结构打交道。在设备操作的时候,客户程序处理从用户程序发出的请求,并与设备进行通信,完成操作。
USB HID客户驱动程序并不直接和硬件打交道,而是通过调用HID类以及USB设备栈提供的DDI服务控制USB硬件的操作。USB客户驱动程序将有关的控制信息包装在URB(USB请求块)结构中,作为IRP的一个参数传递给HID类驱动程序,类驱动程序再调用USB设备栈的下层驱动程序,获取有关的控制信息,与具体的USB设备进行交互,并返回结果给USB客户驱动程序。
USB接口HID内核模式的客户驱动程序是WDM驱动程序,它们支持即插即用和电源管理。其结构和普通WDM驱动程序一样,由很多例程" title="例程">例程构成。在这些例程中可以调用HID类提供的各种DDI函数(一般以HIDP开头)完成设备的操作。
3 USB接口的IC卡读写装置用户模式客户程序
IC卡读写装置采用Cypress公司生产的CY7C63001A微控制器。该芯片是8位一次性编程的微控制器,内置1.5Mbps 的USB串行接口引擎。该芯片有35条专门用于USB操作的指令,20个引脚,128字节的RAM以及4K字节的可编程空间,可以满足IC卡读写程序存储的需要。CY7C63001A芯片与主机USB端口的互连如图3所示。
3.1 IC卡设备部分的描述符结构
按HID类规范的规定,对于每一个USB接口的HID设备,应包含以下几个描述符:设备描述符、配置描述符、接口描述符、HID类描述符及端点描述符。这些描述符定义了本USB设备的基本信息,如零售商ID(应该向USB组织申请,本设备采用0X4242H)、产品ID、配置数目(1个)、接口数目(1个)、端点数目(1个,控制端点为缺省的,还包括一个中断输入端点)及设备类别等。对于HID设备,在接口描述符中需要规定其类ID为3,在HID类描述符中需要规定其描述符类型为0X21。HID类设备的基本通信机制是HID报告。每一个HID设备必须定义一个报告描述符,用以详细描述该设备报告的数据协议及数据类型。报告描述符由主项目、局部项目和全局项目组成。一个报告必须包含下列项目:Input(Output或 Feature),Usage,Usage Page,Logical Minimum,Logical Maximum,Report Size,Report Count。每一个数据项的位长度等于Report Size × Report Count。不同的报告通过报告ID相互区分,用法(Usage)表明该用法页(Usage Page)下各个数据的具体含义或目的。报告的大小并不受端点的约束,主机会自动将报告分解成适合传输大小的数据包。
本系统中,IC卡数据以字节为单位读出、写入。一次最多读取或写入8个字节,再加上命令字(表明数据的含义)及结束标志,最长为13个字节。输入报告描述符如下所示:
usage 01-vendor defined
usage 02-vendor defined
Logical Minimum (-128)
Logical Maximum (127)
Physical Minimum (0)
Physical Maximum (255)
Report Size(8) (bits) //一个字节为8位
Report Count(13) (fields) //最大为13个字节
Input(Data, Variable, Absolute)
为了更好地说明设备的信息,还可以为USB设备定义可选的字符串描述符。定义字符串描述符的好处是可以让主机显示有意义的设备信息,如厂商名称、产品名称等,这对于非通用设备很有好处。本IC卡设备为非通用设备,因此也定义了字符串描述符。另外,字符串语言可通过LanguageID设定,微软规定中文的LanguageID为0804H,美国英语的LanguageID为0409H。
3.2 用户模式客户程序的编制步骤
HID类驱动程序及HID.DLL提供了两类读写USB设备的函数。一类是以HidP为前缀,适用于内核模式的客户驱动程序。另外一类是以HidD为前缀,适用于用户模式的客户程序。利用这些函数编制读写USB设备的步骤如下:
第一步,检测已安装的HID设备,或称USB设备枚举。在和USB设备通信之前,必须得知设备的配置、接口及所用的端点信息,还要获取设备名。
·首先调用HidD_GetHidGuid函数获取HID设备的类标识(GUID);
·调用SetupDiGetClassDevs函数查询所有已安装的HID设备,得到一个指向该HID设备集合的句柄;
·调用SetupDiEnumDeviceInterfaces函数查询HID设备集中每一个设备的接口信息;
·对每一个接口,调用SetupDiGetDeviceInterfaceDetail函数获取其详细的信息,包括设备名称(头四个字节),CreateFile用此设备名打开设备。
·调用SetupDiDestroyDeviceInfoList函数释放设备信息集合。
第二步,打开设备,获取设备的属性值以及设备能力描述。
·调用CreateFile函数打开本设备。
·调用HidD_GetAttributes函数,获取USB设备的有关属性。它包含了设备的零售商ID、产品ID及产品的版本号等。可以根据这些信息判断该设备是否为目标设备。
·调用HidD_GetPreparsedData函数,获取USB设备的预解析数据。这些数据存放在缓冲区内,该缓冲区的数据也可以为其它API函数使用;
·调用HidP_GetCaps函数从上述缓冲区中获取关于该设备能力(如用法、报告描述符的大小等)的描述。调用HidP_GetValueCaps函数得到每一个设备的输入、输出及特征报告的属性值。调用HidD_GetXXXString函数,获取设备的字符串描述信息。
第三步,与HID设备交互。
主机在接收报告的时候,需要从报告中提取数据。由于报告中包含了各种类型的数据,为了方便辨别不同类型的数据,HID类提供了HidP_GetXxx例程,从设备中读取不同类型的数据。如果程序员知道各个数据的含义,则可直接使用ReadFile函数读出数据。本程序直接使用ReadFile函数读出数据。同样,主机发送数据给设备的时候,也要先创建报告;为了方便发送不同类型的数据给设备,HID类提供了HidP_SetXxx 函数。当然,如果程序员知道各个数据的含义,也可以直接使用WriteFile函数将报告传给设备。
完成设备操作后,应关闭设备句柄,释放预解析数据所占用的内存区域。
微软为了方便串行通信,提供了一个MSCom控件。同样,为了方便类似USB接口的HID设备通信,可以将以上的通信程序制作成控件,供不同的HID设备使用。
参考文献
1 USB Implementers' Forum.Device Class Definition for Human Interface Devices (HID),1999
2 USB Implementers' Forum.HID Usage Tables,1999
3 Microsoft Corporation.Microsoft Windows 2000 Driver Development Kit,2000
4 http://www.usb.org
5 http://www.lvr.com
6 Cypress Semiconductor Corporation.CY7C63001A Universal Serial Bus Microcontroller Datasheet,2000
7 王卓人,邓晋钧,刘宗祥.IC卡的技术及其应用.北京:电子工业出版社,1999