rs-232转接usb接口转换器的全面设计论文(4)

2018-12-05 13:16

广西工学院鹿山学院本科生毕业设计(说明书)

批量输入端点2描述符(7字节) 0x07,0x05,0x82,0x02,0x40,0x00,0x00 批量输出端点2描述符(7字节) 0x07,0x05,0x02,0x02,0x40,0x00,0x00 语言描述符此处略去。

5.2 驱动程序开发环境—WinDDK的使用

WDM(Windows Driver Model)是Microsoft提出的一种全新的设备驱动程序模型。它是在Windows NT 内核驱动模型(Kernel-model Driver Model)的基础上发展起来的,增加了对即插即用(PnP)、高级电源管理(Power Management)、Windows管理接口(WMI)的支持,更重要的是,WDM是一种通用的驱动模式,提供了包括USB、IEEE1394、和HID等在内的一系列驱动程序类。在Windows 98 和Windows 2000/XP中,WDM驱动程序均可正常使用。

WDM技术通过提供一种灵活的方式来简化驱动程序的开发,在实现对新硬件支持的基础上减少并降低所必须开发的驱动程序的数量和复杂性,它支持USB、IEEE 1394、ACPI等全新的硬件标准。WDM引入功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件。一个真实硬件对应一个且只能有一个PDO,却可以拥有多个FDO,在驱动程序中直接操作的不是硬件而是相应的PDO与FDO。在用户态和内核态通信方面,系统将每一个用户请求打包形成一个IRP结构,然后发送至驱动程序,并通过识别IRP中的PDO来区别是发送给哪一个设备的。在驱动程序的加载方面,WDM不通过驱动程序名称识别,而是通过一个128位的全局唯一标识符GUID来实现驱动程序的识别。

一个完整的WDM驱动程序要完成以下工作:初始化设备:创建与删除设备(包括可热插拔设备的加入和删除事件):处理应用层程序的打开和关闭句柄的请求;处理应用层程序的输入/输出请求;串行化(获可称为排队)对设备硬件的访问:调用其他驱动程序;取消I/O请求:超时I/O请求;实现电源管理和WMI(Windows Management Instrumentation,即Windows管理诊断)。

16

广西工学院鹿山学院本科生毕业设计(说明书)

5.3 USB驱动程序、虚拟串口的实现方法

DDK已经为USB驱动开发人员提供了功能强大的USB物理总线驱动(PDO),程序员需要做的事情是完成功能驱动(FDO)的开发,驱动开发人员不需要了解USB如何将请求转化成数据包等细节,程序员只需要指定何种管道,发送何种数据即可。

当功能驱动想向某个管道发出读写请求时,首先构造请求发给USB总线驱动。这种是标准的USB请求,被称为URB(USB Request Block),即USB请求块。这种URB被发送到USB物理总线驱动以后,被USB总线驱动所解释,进而转化成请求发往USB HOST驱动或者USB HUB驱动。

USB驱动在与USB设备通信的时候,如在控制管理中获取设备描述符、配置描述符、端点描述符,或者在Bulk管道中获取大量数据,都是通过创建USB请求包(URB)来完成的。URB中填充需要对USB的请求,然后将URB作为IRP的一个参数传递给底层的USB总线驱动。在USB总线驱动中,能够解释不同的URB,并将其转化为USB总线上的相应的数据包。

DDK提供了构造URB的内核函数UsbBuildGetDescritorRequest,在功能驱动中,所有与USB的通信,都需要用这个函数创建URB,并通过IRP发送到底层USB总线驱动,其声明如下:

VOID UsbBuildGetDescritorRequest( IN OUT PURB Urb, IN USHORT Length, IN UCHAR DescriptorType,

IN UCHAR Index, IN USHORT LanguageId,

IN PVOID TransferBuffer OPTIONAL, IN PMDL TransferBufferMDL OPTIONAL, IN ULONG TransferBufferLength, IN PURB Link OPTIONAL );

URB:用来输出的URB结构的指针。 Length:用来描述该URB结构的大小。

DescriptorType:描述该URB的类型。它可以是USB_DEVICE_DESCRIPTOR_TYPE、

17

广西工学院鹿山学院本科生毕业设计(说明书)

USB_CONFIGURATION_DESCRIPTOR_TYPE 和 USB_STRING_DESCRIPTOR_TYPE。 Index:用来描述设备描述符的索引。 LanguageId:用来描述语言ID。

TransferBuffer:如果用缓冲区读取设备,TransferBuffer 是缓冲区内存的指针。 TransferBufferMDL:如果用直接读取内存时,TransferBufferMDL是直接读取内存时

MDL的指针。

TransferBufferLength:对于该URB所操作内存的大小。

功能驱动将URB包构造完毕后,就可以发送到底层总线驱动上了,URB包要和一个IRP相关联起来,这就需要用IoBuildDeviceControlRequest创建一个IO控制码的IRP,然后将URB作为IRP的参数,用IoCallDriver将URB发送到底层总线驱动上。 与一般的驱动类似,USB驱动的初始化入口函数为DriverEntry,在该函数中,分别指定各个IRP的派遣函数地址、指定AddDevice例程函数地址、指定Unload例程函数地址等。

在AddDevice例程中,创建功能设备对像,然后将该对象挂载在总线设备对像之上,从而形成设备栈。另外为设备创建一个设备链接,以便于应用程序可以找到这个设备。 插拔USB设备时会与4个IRP相关,即IRP_MN_START_DEVICE、IRP_MN_STOP_DEVICE、IRP_MN_EJECT、IRP_MN_SURPRISE_REMOVAL。其中,IRP_MN_START_DEVICE消息是当驱动争取加载并运行时,操作系统的PnP管理器会将这个IRP发往设备驱动。当获得这个IRP后,USB驱动需要获得USB设备类别描述符,如设备描述符、配置描述符、接口描述符、端点描述符等。并通过这些描述符有用的信息,记录在设备扩展中。

IRP_MN_STOP_DEVICE 是设备关闭前,PnP管理器发出的IRP。USB驱动获得这个IRP时,应该尽快结束当前执行的IRP,并将其逐个取消掉。另外,在设备扩展中还应该有表示当前状态的变量,当IRP_MN_STOP_DEVICE来临时,将当前状态记录成停止状态。IRP_MN_EJECT是设备被正常弹出,而IRP_MN_SURPRISE_REMOVAL则是设备非自然弹出,有可能是意外掉电或者强行拔出等。在这种IRP到来的时候,应该强迫所有未完成的读写IRP结束并取消,并且将当前设备状态设置成设备被拔掉。

USB设备大部分数据的传送是通过Bulk管道来传输的,Bulk管理的读取是在IRP_MJ_READ各IRP_MJ_WRITE的派遣函数中,应用程序可以通过ReadFile、WriteFile等API对设备进行操作。

在IRP_MJ_READ各IRP_MJ_WRITE的派遣例程中设置了完成例程,如图5-2所示,其原理是将读写的大小分成单位为BULKUSB_MAX_TRANSFER_SIZE的若干块,依次将请求发

18

广西工学院鹿山学院本科生毕业设计(说明书)

往底层USB总线驱动。

图5.2 USB总线驱动

虚拟串口就是当本地并没有对应的串口硬件设备,而为应用层提供串口设备一样的系统调用接口,以兼容原本使用本地串口的应用软件的“虚”设备。本文作者给出了一种在Windows平台上实现虚拟串口的方法,由此实现的“串口”具有真实串口完全相同的系统调用接口。

DDK对串口驱动提供了专门接口。只要编写的驱动满足这些接口,并按照串口标准的命名方法,不管是真实的还是虚拟的串口设备,Windows操作系统都会认为这个设备是一个标准的串口设备。用标准的串口调试工具都可以与这个设备进行通信。

串口驱动的入口函数依然是DriverEntry,并在其中指定各种IRP的派遣函数、AddDevice例程、Unload例程等。其中在AddDevice例程中,需要创建设备对像,创建完设备对象之后,需要将设备对象指定一个符号链接,以便客户程序(串口调试工具)能够识别,该符号以COM开头,并接一个数字就可以了。

编写串口驱动的核心是对应用程序发出的IO控制码和读写命令(即接口)进行处理。这些控制码分别是:

(1)、IOCTL_SERIAL_SET_QUEUE_SIZE

这个控制码是应用程序向驱动请求设置串口驱动内部的缓冲区大小,它是向驱动传递SERIAL_QUEUE_SIZE数据结构来进行设置的。对于虚拟串口驱动来说,这是不需要关心的。

(2)、IOCTL_SERIAL_GET_BAUD_RATE

应用程序向驱动程序IOCTL_SERIAL_GET_BAUD_RATE命令,这主要是询问驱动这个设备的波特率。驱动应该回应给应用程序SERIAL_BAUD_RATE的数据结构来通知波特率的数值。

(3)、IOCTL_SERIAL_GET_LINE_CONTROL

19

广西工学院鹿山学院本科生毕业设计(说明书)

应用程序向驱动程序IOCTL_SERIAL_GET_LINE_CONTROL命令,这要是为了返回串口的行控制信息,行控制信息用SERIAL_LINE_CONTROL数据结构表示

typedef struct _SERIAL_LINE_CONTROL{ UCHAR StopBits; UCHAR Parity; UCHAR WordLength;

} SERIAL_LINE_CONTROL, *PSERIAL_LINE_CONTROL; (4)、IOCTL_SERIAL_GET_CHARS

这个命令是应用程序向驱动请求特殊字符,用来与控制信号握手,用数据结构SERIAL_CHARS表示

Typedef struct _SERIAL_CHARS { UCHAR EofChar; UCHAR ErrorChar; UCHAR BreakChar; UCHAR EventChar; UCHAR XonChar; UCHAR XoffChar;

} SERIAL_CHARS,*PSERIAL_CHARS;

其中EofChar代表是否是传送结束、ErrorChar代表是否传送中有错误、BreakChar代表是否传送有停止等。

(5)、IOCTL_SERIAL_GET_HANDFLOW

这个命令是负责向驱动程序获得串口驱动的握手信号,握手信号用SERIAL_HANDFLOW数据结构表示。

Typedef struct _SERIAL_HANDFLOW{

ULONG ControlHandShake; ULONG FlowReplace; ULONG XonLimit; ULONG XoffLimit;

} SERIAL_HANDFLOW,*PSERIAL_HANDFLOW; (6)、IOCTL_SERIAL_SET_WAIT_MASK

这个命令主要是设置串口驱动的某些事件发生时,需要向应用程序通知。这些事件

20


rs-232转接usb接口转换器的全面设计论文(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:专业技能型职业农民培训考试试卷

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: