收藏 分销(赏)

驱动开发下.ppt

上传人:精*** 文档编号:14518150 上传时间:2026-10-05 格式:PPT 页数:70 大小:965.04KB 下载积分:10 金币
下载 相关
驱动开发下.ppt_第1页
第1页 / 共70页
驱动开发下.ppt_第2页
第2页 / 共70页


点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,现代微机原理与接口技术,驱动开发下,1,4.Driver Works的使用,1)生成简单框架,2,工程文件名,工程文件目录,3,选择驱动类型,4,创建功能驱动程序,创建过滤器驱动程序,5,选择相应总线,本例不驱动硬件,6,驱动类名称,驱动类文件名,7,选择需要处理的消息句柄,8,9,10,11,添加和应用程序之间通信的控制代码,12,13,14,测试用应用程序名称,15,16,17,驱动类,设备类,18,驱动类文件,设备类文件,测试用的控制台程序文件,驱动安装指导文件,19,此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在VC集成环境下修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。,20,该驱动程序框架包含了几个最基本的类,这些类是:,class Sample:public KDriver,/驱动程序类,用于初始化驱动程序,SAFE_DESTRUCTORS,public:,/以下成员函数注意和WDM中有关例程联系起来看,virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath);,virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo);,void LoadRegistryParameters(KRegistryKey,intm_Unit;,/The following data members are loaded from the registry during DriverEntry,ULONG m_bBreakOnEntry;,;,21,class SampleDevice:public KPnpDevice,/是设备类KDvice的派生类,用于在WDM环境下支持即插即用设备,/Constructors,public:,SAFE_DESTRUCTORS;,SampleDevice(PDEVICE_OBJECT Pdo,ULONG Unit);,SampleDevice();,/Member Functions 注意和PNP的次功能代码联系起来看,public:,DEVMEMBER_DISPATCHERS,virtual NTSTATUS OnStartDevice(KIrp I);,virtual NTSTATUS OnStopDevice(KIrp I);,virtual NTSTATUS OnRemoveDevice(KIrp I);,virtual NTSTATUS DefaultPnp(KIrp I);,virtual NTSTATUS DefaultPower(KIrp I);,virtual NTSTATUS OnDevicePowerUp(KIrp I);,virtual NTSTATUS OnDeviceSleep(KIrp I);,void SerialRead(KIrp I);,void SerialWrite(KIrp I);,22,NTSTATUS SAMPLE_IOCTL_Read_Handler(KIrp I);,NTSTATUS SAMPLE_IOCTL_Write_Handler(KIrp I);,NTSTATUS SAMPLE_IOCTL_ReadWrite_Handler(KIrp I);,#ifdef _COMMENT_ONLY,virtual NTSTATUS Create(KIrp I);,virtual NTSTATUS Close(KIrp I);,virtual NTSTATUS DeviceControl(KIrp I);,virtual NTSTATUS SystemControl(KIrp I);,virtual NTSTATUS Read(KIrp I);virtual NTSTATUS Write(KIrp I);,#endif,/Member Data,protected:,/Unit number for this device(0-9),ULONGm_Unit;,KPnpLowerDevicem_Lower;,SampleDevice_DriverManagedQueue m_DriverManagedQueue;,/TODO:Create additional driver managed queues.These might be,/of the same class(SampleDevice_DriverManagedQueue),/or you might choose to derive another class.,;,23,先编译驱动程序工程,在VC的集成环境中,下面我们讲解编译、执行和调试这个驱动程序。,24,25,再编译测试应用程序工程,26,27,下面使用DriverStudio带的工具加载驱动程序和查看调试信息。,驱动程序监视,可实时看到驱动程序发出的调试输出语句,驱动程序装载器,可动态调用驱动程序,28,驱动程序监视器界面,29,驱动程序装载器界面,30,31,32,33,34,35,36,下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:,使用,Read,和,Write,方式分别从驱动程序读入字符和 向驱动程序写字符。,使用,IO,控制代码方式分别从驱动程序读入字符和 向驱动程序写字符。,使用,IO,控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。,注意,:程序中,暗红色显示的部分,是我们添加或修改过的语句,其他是DriverWorks自动生成的。语句中“t xxxxx”这样的语句是向调试软件输出信息,该信息可以再DriverMonitor或其他调试监视器中看到。,2)完成应用程序和驱动程序之间的信息交换,37,使用,Read,和,Write,方式分别读写,SampleDevice,.,cpp,void,SampleDevice,:,SerialRead,(,KIrp,I),t Entering,SampleDevice,:,SerialRead,I EOL;,NTSTATUS status=STATUS_SUCCESS;,PUCHAR,pBuffer,=(PUCHAR)I.,BufferedReadDest,();,/,取得返回数据,BUFF,的指针,ULONG,dwTotalSize,=I.,ReadSize,(CURRENT);,/Requested read size,char buff512;,int,n=512,j=(n%26);,for(,int,i=0;in;i+,j=(j+1)%26),buffi=a+j;,buff,dwTotalSize,=0;,/,指定串尾,strcpy,(char*),pBuffer,buff);,/,把给,应用程序的数据拷贝给返回,BUFF,t “The string you will read is”“buff ”“”EOL;,/,输出调试信息,ULONG,dwBytesRead,=,strlen,(buff);,/Count of bytes read,I.Information()=,dwBytesRead,;,/,返回给应用程序的信息的字节个数,I.Status()=status;,m_,DriverManagedQueue,.,PnpNextIrp,(I);,38,void SampleDevice:SerialWrite(KIrp I),t Entering SampleDevice:SerialWrite,I EOL;,NTSTATUS status=STATUS_SUCCESS;,PUCHAR pBuffer=(PUCHAR)I.BufferedWriteSource();,/取得存放应用程序写给驱动程序的数据的BUFF的指针,ULONG dwTotalSize=I.WriteSize(CURRENT);,/获得应用程序写给驱动程序的信息的字节数。,ULONG dwBytesSent=dwTotalSize,;,char buff512;,strcpy(buff,(char*)pBuffer);,/应用程序写给驱动程序的数据在I.BufferedWriteSource()返回的指针中。,buffdwBytesSent=0;,t Write to driver is buff EOL;,I.Information()=dwBytesSent;,/返回用户实际写的字节数,I.Status()=status;,m_DriverManagedQueue.PnpNextIrp(I);,39,void doRead(int n),/从驱动程序中读数据,char*buf;,ULONG nRead;,inti,j;,buf=(char*)malloc(n);,if(buf=NULL),printf(Failed to allocate buffer for read);,Exit(1);,/Read data from driver,printf(Reading from device-);,ReadFile(hDevice,buf,n,/参数分别是设备句柄、输入缓冲地址、缓冲大小(字节数)、实际读的数据字节数、覆盖结构指针。,40,printf(%d bytes read from device(%d requested).n,nRead,nRead);,/Print what was read,while(i,nRead,),/j=min(i+26),n);,/for(;i j;i+),/,/printf(%c,bufi);,/,/printf(n);,printf(%c,bufi+);,printf(n);,free(buf);,这几句删除,41,void doWrite(int n)/向驱动程序中写数据,char*buf;,ULONGnWritten;,inti,j;,buf=(char*)malloc(n);,if(buf=NULL),printf(Failed to allocate buffer for write);,Exit(1);,/start with the mod26 letter of the number of bytes to write,j=(n%26);,/load buffer with dummy data(abcdefg.),for(i=0;in;i+,j=(j+1)%26),bufi=a+j;,42,/Write data to driver,printf(Writing to device-);,WriteFile(hDevice,buf,n,/写数据,参数的含义是驱动程序句柄、写缓冲、写缓冲大小、实际驱动程序得到的信息的字节数、覆盖结构指针。,printf(%d bytes written to device(%d attempted).n,nWritten,n);,i=0;,/Print what was written,while(i n),j=min(i+26),n);,for(;i j;i+),printf(%c,bufi);,printf(n);,free(buf);,43,FORM 5(WDM):,Connect 绑定ISR(中断服务例程)到中断,virtual NTSTATUS Close(KIrp I);,Initialize(PCM_RESOURCE_LIST pTranslatedResourceList,PCM_RESOURCE_LIST pRawResourceList,ULONG Ordinal=0,BOOLEAN MapToSystemVirtual=TRUE,printf(Reading from device-);,CHARbufInputIOCTL_INBUF_SIZE;/Input to device,FORM 4(WDM):(注意:这种形式不被 DriverStudio 2.,m_DriverManagedQueue.,KInterrupt:Initialize(只介绍WDM形式),该驱动程序框架包含了几个最基本的类,这些类是:,ULONG Count/缓冲中要写数据的字节数,t InputPut Data is buff EOL;,/printf(%c,bufi);,PCM_RESOURCE_LIST pRawResourceList,/指向原始资源表的指针,写一个或多个字节到映射的IO空间。,for(;i j;i+),strcpy(bufInput,Now let us write this string.,b.使用IO控制代码方式分别读写,NTSTATUS SampleDevice:SAMPLE_IOCTL_Read_Handler(KIrp I),/对应用程序读驱动程序的请求作响应,NTSTATUS status=STATUS_SUCCESS;,t Entering SampleDevice:SAMPLE_IOCTL_Read_Handler,I=fwLength),/如果读入缓冲够长,strcpy(PCHAR)I.IoctlBuffer(),buff1);,/将信息拷给应用程序读入缓冲,I.Information()=fwLength;,/返回信息长度,else,I.Information()=0;,/否则信息长度为0,t buff size too small EOL;,return status;,44,NTSTATUS SampleDevice:SAMPLE_IOCTL_Write_Handler(KIrp I),/接受从应用程序中来的信息,NTSTATUS status=STATUS_SUCCESS;,t Entering SampleDevice:SAMPLE_IOCTL_Write_Handler,I EOL;,char buff512;,ULONG fwLength=0;,strcpy(buff,(PCHAR)I.IoctlBuffer();,/拷贝从应用程序得到的命令串到驱动程序局部数据区,t “InputPut Data is”“buff ”“”EOL;,/显示从应用程序得到的命令串。,I.Information()=0;,return status;,45,void Test_SAMPLE_IOCTL_Read(void),CHARbufInputIOCTL_INBUF_SIZE;/Input to device,CHARbufOutputIOCTL_OUTBUF_SIZE;/Output from device,ULONGnOutput;/Count written to bufOutput,/Call device IO Control interface(SAMPLE_IOCTL_Read)in driver,printf(Issuing Ioctl to device-);,strcpy(bufInput,This is a sample.);,if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_Read,NULL,0,bufOutput,IOCTL_OUTBUF_SIZE,&nOutput,NULL),printf(ERROR:DeviceIoControl returns%0 x.,GetLastError();,Exit(1);,else,printf(Return from driver is%s(%d),bufOutput,nOutput);,46,void Test_SAMPLE_IOCTL_Write(void),CHARbufInputIOCTL_INBUF_SIZE;/Input to device,CHAR,bufOutputIOCTL_OUTBUF_SIZE;/Output from device,ULONGnOutput;/Count written to bufOutput,/Call device IO Control interface(SAMPLE_IOCTL_Write)in driver,printf(Issuing Ioctl to device-);,strcpy(bufInput,Now let us write this string.);,if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_Write,bufInput,strlen(bufInput),NULL,0,&nOutput,NULL),/该函数参数分别是设备句柄、IO控制命令、写缓冲、写缓冲大小、读缓冲、读缓冲大小、实际读的字节数、覆盖结构指针(注意,这里的bufInput是指Input到设备,所以对应用软件这是写缓冲,bufOutput是从设备output到应用程序,是读缓冲。,printf(ERROR:DeviceIoControl returns%0 x.,GetLastError();,Exit(1);,47,c.使用IO控制代码方式写并且读,NTSTATUS SampleDevice:SAMPLE_IOCTL_ReadWrite_Handler(KIrp I),NTSTATUS status=STATUS_SUCCESS;,t Entering SampleDevice:SAMPLE_IOCTL_ReadWrite_Handler,I EOL;,char buff512,buff1512;,ULONG fwLength=0;,strcpy(buff,(PCHAR)I.IoctlBuffer();,/拷贝应用程序来的信息,t InputPut Data is buff =fwLength),strcpy(PCHAR)I.IoctlBuffer(),buff1);,/拷贝反馈信息,I.Information()=fwLength;,/设置反馈信息字节数,else,I.Information()=0;,t buff size too small EOL;,return status;,49,void Test_SAMPLE_IOCTL_ReadWrite(void),bufOutput is written by the device to return data to this application,CHARbufInputIOCTL_INBUF_SIZE;/Input to device,CHARbufOutputIOCTL_OUTBUF_SIZE;/Output from device,ULONGnOutput;/Count written to bufOutput,/Call device IO Control interface(SAMPLE_IOCTL_ReadWrite)in driver,printf(Issuing Ioctl to device-);,strcpy(bufInput,This is a sample.);,if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_ReadWrite,bufInput,strlen(bufInput),bufOutput,IOCTL_OUTBUF_SIZE,&nOutput,NULL),printf(ERROR:DeviceIoControl returns%0 x.,GetLastError();,Exit(1);,else,printf(Feedback is%s(%d),bufOutput,nOutput);,50,51,首先定义类KIoRange的一个实例,以定义相关地址空间。,KIoRange(PCM_RESOURCE_LIST pTranslatedResourceList,/可通过KIrp:TranslatedResources获得,/of the same class(SampleDevice_DriverManagedQueue),for(i=0;in;i+,j=(j+1)%26),此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在VC集成环境下修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。,ULONG fwLength=0;,/printf(%c,bufi);,KIoRange:inb,CHARbufInputIOCTL_INBUF_SIZE;/Input to device,ULONG Ordinal=0,/指定pTranslatedResourceList指向的资源列表中的一个特殊端口资源,WriteFile(hDevice,buf,n,NTSTATUS SAMPLE_IOCTL_ReadWrite_Handler(KIrp I);,使用IO控制代码方式分别从驱动程序读入字符和 向驱动程序写字符。,CHARbufOutputIOCTL_OUTBUF_SIZE;/Output from device,FORM 2:(WDM),52,3)直接对端口寄存器读写,DriverStudio提供了KIoRange类来将外部总线的I/O地址空间范围映射到处理器总线的地址空间范围。,该类的成员函数主要有,KIoRange,构造函数(4 种格式),Initialize,初始化和重新初始化一个实例(3种格式),KIoRange,析构函数,Invalidate,从已初始化状态删除该对象,IsValid,测试该对象是否已经初始化,inb,读一个或多个字节(2 种形式),Outb,写一个或多个字节(2 种形式),Inw,读一个或多个字(2 种形式),Outw,写一个或多个字(2 种形式),ind,读一个或多个双字(2 种形式),outd,写一个或多个双字(2 种形式),53,KIoRange:KIoRange(只介绍WDM形式),FORM 3(WDM):,KIoRange,(,ULONGLONG,CpuPhysicalAddress,/转换成外围设备地址的CPU总线上的物理地址,BOOLEAN,InCpuIoSpace,/如果IO范围是在CPU总线的IO空间中为TRUE,否则为FALSE,ULONG,Count,/以字节计的区域的大小,BOOLEAN,MapToSystemVirtual,=TRUE,/指定是否需要构造函数创建一个非页系统空间的地址空间映射,如果驱动程序读写设备中的数据,就需要这种映射,);,FORM 4(WDM):(,注意:这种形式不被,DriverStudio 2.0支持。,),KIoRange,(,PCM_RESOURCE_LIST,pTranslatedResourceList,/指向转换资源表的指针,ULONG,Ordinal,=0,/指定,pTranslatedResourceList,指向的资源列表中的一个特殊端口资源,BOOLEAN,MapToSystemVirtual,=TRUE);,FORM 5(WDM),:,KIoRange,(,PCM_RESOURCE_LIST,pTranslatedResourceList,/可通过KIrp:TranslatedResources获得,PCM_RESOURCE_LIST,pRawResourceList,/指向原始资源表的指针,ULONG,Ordinal,=0,BOOLEAN,MapToSystemVirtual,=TRUE);,构造 KIoRange类。,54,KIoRange:Initialize,(只介绍WDM形式),FORM 2(WDM):,NTSTATUS Initialize,(,ULONGLONG,CpuPhysicalAddress,BOOLEAN,InCpuIoSpace,ULONG,Count,BOOLEAN,MapToSystemVirtual,=TRUE);,FORM 3(WDM):,(,注意:这种形式不被,DriverStudio 2.0支持。,),NTSTATUS Initialize,(,PCM_RESOURCE_LIST,pTranslatedResourceList,ULONG,Ordinal,=0,BOOLEAN,MapToSystemVirtual,=TRUE);,FORM 4(WDM),:,Initialize,(,PCM_RESOURCE_LIST,pTranslatedResourceList,PCM_RESOURCE_LIST,pRawResourceList,ULONG,Ordinal,=0,BOOLEAN,MapToSystemVirtual,=TRUE,);,初始化或重新初始化KIoRange的实例。,55,KIoRange:inb,FORM 1:,UCHAR inb(ULONG,ByteOffset,);,FORM 2:,VOID inb(ULONG,ByteOffset,PUCHAR,Buffer,ULONG,Count,);,从映射空间读一个或多个字节。,56,KIoRange:outb,FORM 1:,VOID outb,(,ULONG,ByteOffset,/以字节为单位的目标位置到IO空间开始位置的偏移值,UCHAR,Data,/要写的一个字节数据,);,FORM 2:,VOID outb,(,ULONG,ByteOffset,PUCHAR,Buffer,/指向包含要写数据的缓冲的指针,ULONG,Count,/缓冲中要写数据的字节数,);,写一个或多个字节到映射的IO空间。,57,写,端口(索引信息,地址70,H)m_,ParPortIos,.,outb,(0,0 x02);,/,准备读分钟信息,读端口(读分钟信息,地址71,H)UCHAR data=m_,ParPortIos,.,inb,(1);,下面我们来访问CMOS的数据。,首先定义类,KIoRange,的一个实例,,以定义相关地址空间。,KIoRange m_,ParPortIos,;,初始化实例(指定,CMOS,的端口首地址,并映射),status=m_,ParPortIos,.Initialize(0 x70,/CMOS,端口首地址是70,H,TRUE,/,在,CPU I/O,空间内,8,/设备读写数据的字节宽度,TRUE,/,映射到系统空间,);,58,4),截获中断和挂接中断服务例程,DriverStudio提供了KInterrupt类来截获和挂接中断。,该类的成员函数主要有,KInterrupt,构造函数(3种格式),Initialize,在无效状态下初始化一个对象(3种格式),Connect,绑定ISR(中断服务例程)到中断,InitializeAndConnect,一步完成初始化与绑定工作,要用资源列表作为输入。,KInterrupt,析构函数,Invalidate,在初始化状态下删除对象,IsValid,检查对象是否初始化,Disconnect,使中断和ISR与中断分离,Synchronize,当得到一个中断自旋锁时请求同步功能,59,KInterrupt:KInterrupt(只介绍WDM形式),FORM 3:(WDM),KInterrupt,(,KIRQL,irql,/即插即用设备提供的IRQL值,ULONG,vector,/即插即用设备提供的向量值,KINTERRUPT_MODE,Mode,/LevelSensitive,或,Latched中选一,.,BOOLEAN,bShareVector,=FALSE,/该向量是否被几个设备共享,KAFFINITY,affinity,=1,/this is the processor affinity mask.,BOOLEAN,bSaveFloat,=FALSE,/是否需要在中断到来使保存浮点处理器上下文,X86平台下必须使FALSE,);,构造类Kinterrupt的实例。,60,KInterrupt:Initialize(只介绍WDM形式),FORM 2:(WDM),VOID Initialize,(,KIRQL,irql,ULONG,vector,KINTERRUPT_MODE,Mode,BOOLEAN,bShareVector,=FALSE,KAFFINITY,affinity,=1,BOOLEAN,bSaveFloat,=FALSE);,初始化对象。只在对象没有初始化的时候使用。,61,KInterrupt:Connect,FORM 1:,NTSTATUS Connect,(,PKSERVICE_ROUTINE,Isr,/作为ISR服务的函数的地址,PVOID,Context,/当系统调用ISR的时候传递给他的无类型的参数,);,FORM 2:,NTSTATUS Connect,(,PKSERVICE_ROUTINE,Isr,PVOID,Context,PKSPIN_LOCK,pSpin,KIRQL,SynchIrql,);,绑定一个中断到ISR(中断处理程序)。,62,KInterrupt:InitializeAndConnect,NTSTATUS InitializeAndConnect,(,PCM_RESOURCE_LIST,pResourceList,/指向资源列表的指针,PKSERVICE_ROUTINE,Isr,PVOID,IsrContext,ULONG,Ordinal,=0,BOOLEAN,bSaveFloat,=FALSE);,初始化一个中断并绑定到一个ISR上。,对于 WDM 驱动程序,,pResourceList,必须是一个转换资源表,例如是KIrp:TranslatedResources的返回值。,63,下面我们来举例说明。,首先,定义类,KInterrupt,的一个实例,KInterrupt,m_,TheInterrupt,;,在设备类中声明一个成员函数,TheIsr,作为中断服务例程,ISR,。,class,SampleDevice,:public,KPnpDevice,public:MEMBER_ISR(,SampleDevice,TheIsr,);,#,ifdef,_COMMENT_ONLY,BOOLEAN,TheIsr,(void)return TRUE;#,endif,64,在,OnStartDevic,e,例程中获取包括中断的设备资源并初始化中断和挂接,ISR,SampleDevice,:,OnStartDevice,(,KIrp,I),PCM_RESOURCE_LIST,pResList,=I.,TranslatedResources,();,/,获取设备资源,/,初始化中断并挂接中断服务例程,TheIsr,status=m_,TheInterrupt,.,InitializeAndConnect,(,pResList,LinkTo,(,TheIsr,),this,);,65,5),如何写,Win32类型的驱动程序的测试,程序,DriverStudio自动生成的驱动程序的测试程序是一个控制台程序,下面我们将利用该控制台程序来写一个Win32的程序。,第一步,在由DriverStudio自动生成一个驱动程序工作区(Workspace)中添加一个新的子工程,该子工程指定为一个MFC的EXE程序。,右键点击,66,67,第二步,手工在新的工程中添加几个文件,这几个程序需要手工添加进去,实际上这几个程序都在DriverStudio自动生成的原来的两个工程文件中(这个例子是MyIOPort和Test_MyIOPort工程)。将他们添加到新工程中,方法是右键点击新工程中的相关文件夹,在弹出菜单中选择Add Files to Folder,然后找到要添加的文件并添加。,68,第三步,打开OpenByIntf.cpp文件,在开始第一行添加,#include stdafx.h,第四步,,1,2,3,4,5,C:PROGRAM FILESCOMPUWARESOFTICE DRIVER SUITEDRIVERWORKSINCLUDE,69,第五步,,1,2,3,4,setupapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib,可以直接从自动生成的控制台工程的设置中拷贝这些库的名称,70,
展开阅读全文

开通  VIP、SVIP  下载更划算
下载10份以上建议开通 VIP 会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        关注我们

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服