原创 驱动开发流程

2009-6-2 22:05 4351 7 7 分类: 通信
驱动开发流程

  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->MajorFunction[IRP_MJ_CREATE] = Ezusb_Create;

DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ezusb_Close;



//分发例程

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ezusb_ProcessIOCTL;



//即插即用例程

DriverObject->MajorFunction[IRP_MJ_PNP] = Ezusb_DispatchPnp;



//电源管理例程

DriverObject->MajorFunction[IRP_MJ_POWER] = Ezusb_DispatchPower;



//设备添加例程

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目录中。值得注意的是,“=”前后不能有空格,否则编译的时候会出错。



开始编译:

“开始”->“程序”->“Development Kits”->“Windows 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:NTDDK>cd jtag_usb (回车) D:HelloWDM>build
(回车)     

如果源代码没有错误的话,生成的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,
USB\VID_0547&PID_1002 [DestinationDirs] CyUsb.Files.Ext =
10,System32\Drivers [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,
0x00000002, CyUsb.AddService [CyUsb.AddService] DisplayName =
%CyUsb.SvcDesc% ServiceType = 1 ; SERVICE_KERNEL_DRIVER StartType = 3 ;
SERVICE_DEMAND_START ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\jtag_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}"   &n bsp; 



准备好这个 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操作控制代码

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 pvBuffer[1]; //temp for data and address



pvBuffer[0]=Addr; //地址

//------------写地址--------------------------

myRequest.direction=0x00;//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=0xb4;

myRequest.value=0x00;//在这里不起作用

myRequest.index=0x00;



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);



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);

**********************************************************//
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /4 下一条