2022年USB驱动程序的编写采用WDM驱动程序 .pdf
USB驱动程序的编写采用WDM 驱动程序。WDM 驱动程序是一些例程的集合, 它们被动地存在,等待主机系统软件(PnP 管理器、 I/O 管理器、电源管理器等)来调用或激活它们。具体驱动程序不同,其所包含的例程也不同。一个WDM 驱动程序的基本组成包括以下5 个例程:(1)驱动程序入口例程:处理驱动程序的初始化。(2)即插即用例程:处理PnP 设备的添加、删除和停止。(3)分发例程:处理用户应用程序发出的各种 I/O 请求。(4)电源管理例程:处理电源管理请求。(5)卸载例程:处理驱动程序的卸载。包含文件:ezusbsys.c, ezusbsys.h, ezusbsys.rc, resource.h, version.h, makefile,sources) 在 ezusbsys.c 文件中,包含了上述五个例程:ezusbsys.h 中定义了各种数据结构还有各种IOCTL控制码,用于不同数据的读写。Ezusbsys.c 中实现了各种驱动例程。包含了上述五个所说例程外还包含了其他例程,课程从下面的驱动程序入口例程得出一些信息。驱动程序入口例程:NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; DriverObject-MajorFunctionIRP_MJ_CREATE = Ezusb_Create; DriverObject-MajorFunctionIRP_MJ_CLOSE = Ezusb_Close; / 分发例程DriverObject-MajorFunctionIRP_MJ_DEVICE_CONTROL = Ezusb_ProcessIOCTL; / 即插即用例程DriverObject-MajorFunctionIRP_MJ_PNP = Ezusb_DispatchPnp; / 电源管理例程DriverObject-MajorFunctionIRP_MJ_POWER = Ezusb_DispatchPower; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 6 页 - - - - - - - - - / 设备添加例程DriverObject-DriverExtension-AddDevice = Ezusb_PnPAddDevice; / 卸载例程DriverObject-DriverUnload = Ezusb_Unload; return ntStatus; 在原有框架下,主要实现了的代码段在于ezusbsys.c 文件中的如下例程:NTSTATUS Ezusb_Read_Write( IN PDEVICE_OBJECT fdo, IN PIRP Irp ) 在该例程中实现对大数据块的读写控制和实现。具体实现代码在ezusbsys.c 文件中。编译生成驱动文件:最用利用 Windows 2000 DDK工具进行编译。编译 WDM 程序的时候,有两个文件是必须要有的,它们是:1、Makefile :它的内容是:# # DO NOT EDIT THIS FILE! Edit .sources. If you want to add a new source # file to this component. This file merely indirects to the real make file # that is shared by all the driver components of the Windows NT DDK # !INCLUDE $(NTMAKEENV)makefile.def 不要编辑这个文件。 事实上每个 WDM 程序所需要的 makefile的内容都是一样的,只需要简单地copy 一个 makefile到新的项目中就可以了2、Sources TARGETNAME=jtag_usb_1.0 TARGETTYPE=DRIVER DRIVERTYPE=WDM TARGETPATH=lib INCLUDES=$(BASEDIR)inc; $(BASEDIR)incddk; TARGETLIBS=$(BASEDIR)lib*freeusbd.lib SOURCES=ezusbsys.c resource.r 这个文件指定了驱动程序目标名是jtag_usb_1.0.sys,是一个 WDM 驱动程序,生成的文件存放在lib目录名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 6 页 - - - - - - - - - 中。值得注意的是,“ =”前后不能有空格,否则编译的时候会出错。开始编译:“开始”-“程序”-“Development Kits ”- “Window s 2000 DDK ”-“Checked Build Environment”屏幕将显示:(有“回车”的那行是需要读者你亲自打进去的)New or updated MSVC detected. Updating DDK environment,. Setting environment for using Microsoft Visual C+ tools. Starting dirs creation,Completed. D:NTDDKcd jtag_usb (回车)D:HelloWDMbuild (回车)如果源代码没有错误的话,生成的jtag_usb_1.0.sys将存放在 lib目录中。安装驱动程序:利用 INF 文件实现驱动的安装。我们一般是采用INF 文件, inf文件如下所示:jtag_usb.inf:Version Signature = $CHICAGO$ Class = USB DriverVer = 11/11/2007,1.00.00 ClassGUID = 36FC9E60-C465-11CF-8056-444553540000 provider = %ECICT% SourceDisksNames 1=% CYUSB_INSTALL%, SourceDisksFiles jtag_usb_1.0.sys = 1 Manufacturer %MfgName%=ECICT Ecict %VID_0547&PID_1002.DeviceDesc%=CyUsb, USBVID_0547&PID_1002 DestinationDirs CyUsb.Files.Ext = 10,System32Drivers CyUsb.HW AddReg=CyUsb.AddReg.Guid CyUsb.NT CopyFiles=CyUsb.Files.Ext AddReg=CyUsb.AddReg CyUsb.NT.HW AddReg=CyUsb.AddReg.Guid CyUsb.NT.Services Addservice = CyUsb, 0 x00000002, CyUsb.AddService CyUsb.AddService DisplayName = %CyUsb.SvcDesc% ServiceType = 1 ; SERVICE_KERNEL_DRIVER StartType = 3 ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 6 页 - - - - - - - - - SERVICE_DEMAND_START ErrorControl = 1 ; SERVICE_ERROR_NORMAL ServiceBinary = %10%System32 Driversjtag_usb_1.0.sys LoadOrderGroup = Base CyUsb.AddReg HKR,DevLoader,*ntkern HKR,NTMPDriver,jtag_usb_1.0.sys CyUsb.Files.Ext jtag_usb_1.0.sys CyUsb.AddReg.Guid HKR,DriverGUID,%CyUsb.GUID% ;- -; Strings CYUSB_INSTALL = Your Device Installation Disk ECICT = ECICT MfgName = ECICT VID_0547&PID_1002.DeviceDesc = USB_Jtag Controler ;-Replace GUID below with custom GUID-; CyUsb.GUID= 07BBF83D-D0B2-4915-870C-FC5B0B049DFC 准备好这个 jtag_usb.INF 文件后,插入控制器, 然后跳出设备驱动安装的对话框 。 我 想 从 列 表 选 择 硬 件 ”-“ 其 它 设 备 ”- “ 从 磁 盘 安 装 ” , 选 择jtag_usb.INF 所在的路径,然后安装。当安装完成后,系统就会添加上你写好的驱动程序了。(可以在“设备管理器”中查看到),这个驱动程序就投入使用。驱动程序与应用程序的接口对用户来说,所用的应用程序都通过I/O 控制来访问设备驱动程序。用户的应用程序首先通过调用Win32 函数 CreateFile()来取得访问设备驱动的句柄。然后,用户程序使用Win32函数 DeviceIoControl()来提交 I/O 控制码,并为 CreateFile 函数返回的设备句柄设置I/O 缓冲区。下面的例程验证所获取的EZ-USB设备的句柄:HANDLE DeviceHandle; DeviceHandle=CreateFile( “.ezusb-0”, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 随后,用户的应用程序通过调用Win32函数 DeviceIoControl()来向设备驱动程序发送请求。 下面显示的是 DeviceIoControl()函数的原型。 EZ-USB 设备驱动程序 IOCTL使用相同的函数参数名。BOOL DeviceIoControl() HANDLE hDevice, /外设句柄DWORD dwIoControlCode, /I/O操作控制代码名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 6 页 - - - - - - - - - LPVOID lpInBuffer, /输入缓冲区指针DWORD nInBufferSize, /输入缓冲区大小LPVOID lpOutBufferSize, /输出缓冲区指针DWORD nOutBufferSize, /输出缓冲区大小LPDWORD lpBytesReturned, /实际返回的字节数LPOVRLAPPER lpOverLapper /用于异步操作的重叠指针 其中 I/O 操作控制代码是在USB设备驱动程序中定义和实施实际数据操作的 , 如 在 驱 动 程 序 中 定 义 的 : IOCTL_EZUSB_GET_DEVICE_DESCRIPTOR, IOCTL_EZUSB_BULK_READ, IOCTL_EZUSB_BULK_WRITE 等控制代码。例如:( 1)通过红色标注的ioctl控制码写入一个地址值。/* VENDOR_OR_CLASS_REQUEST_CONTROL myRequest; / 在 ezusbsys.h 中定义的数据结构ULONG nBytes; WORD pvBuffer1; /temp for data and address pvBuffer0=Addr; /地址/-写地址- myRequest.direction=0 x00;/0-HOST T0 DEVICE,1-DEVICE TO HOST myRequest.requestType=2;/1-class,2-vendor myRequest.recepient=0;/0-device,1-interface,2-endpoint,3-ot her myRequest.request=0 xb4; myRequest.value=0 x00;/在这里不起作用myRequest.index=0 x00; DeviceIoControl (hDevice, IOCTL_EZUSB_VENDOR_OR_CLASS_REQUEST, /ioctl控制码 &myRequest, sizeof(VENDOR_OR_CLASS_REQUEST_CONTROL), pvBuffer, 2, &nBytes, NULL); */ (2)大块数据的写/* BULK_TRANSFER_CONTROL bulkControl; / pipe type selected PWORD pData bulkControl.pipeNum=0; /通道 0 用于写,通道 1 用于读。pData=(PWORD)malloc(lenth*2); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 6 页 - - - - - - - - - DeviceIoControl (hDevice, IOCTL_EZUSB_BULK_WRITE, /数据块的写 IOCTL码 &bulkControl, sizeof(BULK_TRANSFER_CONTROL), pData, length*2, &nBytes, NULL); */ (2)大块数据的读/* BULK_TRANSFER_CONTROL bulkControl; / pipe type selected PWORD pData bulkControl.pipeNum=1; /通道 0 用于写,通道 1 用于读。pData=(PWORD)malloc(lenth*2); DeviceIoControl (hDevice, IOCTL_EZUSB_BULK_READ, /数据块的读IOCTL 码&bulkControl, sizeof(BULK_TRANSFER_CONTROL), pData, length*2, &nBytes, NULL); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 6 页 - - - - - - - - -