版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1Windows98/2000驱动程序编写方法(下)24.DriverWorks的使用1)生成简单框架3工程文件名工程文件目录4选择驱动类型5创建功能驱动程序创建过滤器驱动程序6选择相应总线本例不驱动硬件7驱动类名称驱动类文件名8选择需要处理的消息句柄9101112添加和应用程序之间通信的控制代码131415测试用应用程序名称161718驱动类设备类19驱动类文件设备类文件测试用的控制台程序文件驱动安装指导文件20
此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在VC集成环境下区修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。21
该驱动程序框架包含了几个最基本的类,这些类是:classSample:publicKDriver//驱动程序类,用于初始化驱动程序{SAFE_DESTRUCTORSpublic:
//以下成员函数注意和WDM中有关例程联系起来看
virtualNTSTATUSDriverEntry(PUNICODE_STRINGRegistryPath);virtualNTSTATUSAddDevice(PDEVICE_OBJECTPdo);void LoadRegistryParameters(KRegistryKey&Params);int m_Unit;//ThefollowingdatamembersareloadedfromtheregistryduringDriverEntry ULONGm_bBreakOnEntry;
};22classSampleDevice:publicKPnpDevice//是设备类KDvice的派生类,用于在WDM环境下支持即插即用设备{ //Constructorspublic: SAFE_DESTRUCTORS; SampleDevice(PDEVICE_OBJECTPdo,ULONGUnit); ~SampleDevice(); //MemberFunctions注意和PNP的次功能代码联系起来看public: DEVMEMBER_DISPATCHERS virtualNTSTATUSOnStartDevice(KIrpI); virtualNTSTATUSOnStopDevice(KIrpI); virtualNTSTATUSOnRemoveDevice(KIrpI); virtualNTSTATUSDefaultPnp(KIrpI); virtualNTSTATUSDefaultPower(KIrpI); virtualNTSTATUSOnDevicePowerUp(KIrpI); virtualNTSTATUSOnDeviceSleep(KIrpI); voidSerialRead(KIrpI); voidSerialWrite(KIrpI);23 NTSTATUSSAMPLE_IOCTL_Read_Handler(KIrpI); NTSTATUSSAMPLE_IOCTL_Write_Handler(KIrpI); NTSTATUSSAMPLE_IOCTL_ReadWrite_Handler(KIrpI);#ifdef_COMMENT_ONLY virtualNTSTATUSCreate(KIrpI); virtualNTSTATUSClose(KIrpI); virtualNTSTATUSDeviceControl(KIrpI); virtualNTSTATUSSystemControl(KIrpI); virtualNTSTATUSRead(KIrpI);
virtualNTSTATUSWrite(KIrpI);#endif
//MemberDataprotected:
//Unitnumberforthisdevice(0-9) ULONG m_Unit; KPnpLowerDevice m_Lower; SampleDevice_DriverManagedQueuem_DriverManagedQueue;//TODO: Createadditionaldrivermanagedqueues.Thesemightbe// ofthesameclass(SampleDevice_DriverManagedQueue),// oryoumightchoosetoderiveanotherclass.};24先编译驱动程序工程在VC的集成环境中下面我们讲解编译、执行和调试这个驱动程序。2526再编译测试应用程序工程2728
下面使用DriverStudio带的工具加载驱动程序和查看调试信息。驱动程序监视,可就看到驱动程序发出的调试输出语句驱动程序装载器,可动态调用驱动程序29驱动程序监视器界面30驱动程序装载器界面31323334353637
下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:使用Read和Write方式分别从驱动程序读入字符和向驱动程序写字符。使用IO控制代码方式分别从驱动程序读入字符和向驱动程序写字符。使用IO控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。
注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是DriverWorks自动生成的。语句中“t<<xxxxx”这样的语句是向调试软件输出信息,该信息可以再DriverMonitor或其他调试监视器中看到。2)完成应用程序和驱动程序之间的信息交换38使用Read和Write方式分别读写SampleDevice.cppvoidSampleDevice::SerialRead(KIrpI){ t<<"EnteringSampleDevice::SerialRead,"<<I<<EOL; NTSTATUSstatus =STATUS_SUCCESS; PUCHAR pBuffer =(PUCHAR)I.BufferedReadDest();//取得返回数据BUFF的指针
ULONGdwTotalSize=I.ReadSize(CURRENT); //Requestedreadsize charbuff[512]; intn=512,j=(n%26); for(inti=0;i<n;i++,j=(j+1)%26) { buff[i]='a'+j; } buff[dwTotalSize]=‘\0’;//指定串尾
strcpy((char*)pBuffer,buff);
//把给应用程序的数据拷贝给返回BUFF t<<“Thestringyouwherereadis\”“<<buff<<”\“”<<EOL;//输出调试信息
ULONGdwBytesRead=strlen(buff); //Countofbytesread
I.Information()=dwBytesRead;//返回给应用程序的信息的字节个数
I.Status()=status; m_DriverManagedQueue.PnpNextIrp(I);}39voidSampleDevice::SerialWrite(KIrpI){ t<<"EnteringSampleDevice::SerialWrite,"<<I<<EOL; NTSTATUSstatus=STATUS_SUCCESS; PUCHARpBuffer=(PUCHAR)I.BufferedWriteSource();//取得存放应用程序写给驱动程序的数据的BUFF的指针
ULONGdwTotalSize=I.WriteSize(CURRENT);//获得应用程序写给驱动程序的信息的字节数。
ULONGdwBytesSent=dwTotalSize;
charbuff[512]; strcpy(buff,(char*)pBuffer); //应用程序写给驱动程序的数据在I.BufferedWriteSource()返回的指针中。
buff[dwBytesSent]='\0';
t<<"Writetodriveris\""<<buff<<"\""<<EOL; I.Information()=dwBytesSent;//返回用户实际写的字节数
I.Status()=status; m_DriverManagedQueue.PnpNextIrp(I);}40Test_Sample.cppvoiddoRead(intn)//从驱动程序中读数据{ char *buf; ULONGnRead; int i,j; buf=(char*)malloc(n); if(buf==NULL) { printf("Failedtoallocatebufferforread"); Exit(1); }
//Readdatafromdriver printf("Readingfromdevice-"); ReadFile(hDevice,buf,n,&nRead,NULL);
//参数分别是设备句柄、输入缓冲地址、缓冲大小(字节数)、实际读的数据字节数、覆盖结构指针。41 printf("%dbytesreadfromdevice(%drequested).\n",nRead,nRead); //Printwhatwasread while(i<nRead) {// j=min((i+26),n);// for(;i<j;i++)// {// printf("%c,",buf[i]);// }// printf("\n"); printf("%c,",buf[i++]); } printf("\n"); free(buf);}这几句删除42voiddoWrite(intn)//向驱动程序中写数据{ char *buf; ULONG nWritten; int i,j; buf=(char*)malloc(n); if(buf==NULL) { printf("Failedtoallocatebufferforwrite"); Exit(1); } //startwiththemod26letterofthenumberofbytestowrite j=(n%26); //loadbufferwithdummydata(abcdefg...) for(i=0;i<n;i++,j=(j+1)%26) { buf[i]='a'+j; }43
//Writedatatodriver printf("Writingtodevice-"); WriteFile(hDevice,buf,n,&nWritten,NULL);
//写数据,参数的含义是驱动程序句柄、写缓冲、写缓冲大小、实际驱动程序得到的信息的字节数、覆盖结构指针。
printf("%dbyteswrittentodevice(%dattempted).\n",nWritten,n); i=0;//Printwhatwaswritten while(i<n) { j=min((i+26),n); for(;i<j;i++){ printf("%c,",buf[i]); } printf("\n"); } free(buf);}44b.使用IO控制代码方式分别读写SampleDevice.cppNTSTATUSSampleDevice::SAMPLE_IOCTL_Read_Handler(KIrpI){ //对应用程序读驱动程序的请求作响应
NTSTATUSstatus=STATUS_SUCCESS; t<<"EnteringSampleDevice::SAMPLE_IOCTL_Read_Handler,"<<I<<EOL; charbuff1[512]; ULONGfwLength=0; strcpy(buff1,"etodriver!"); fwLength=strlen(buff1)+1; if(I.IoctlOutputBufferSize()>=fwLength) {//如果读入缓冲够长
strcpy((PCHAR)I.IoctlBuffer(),buff1); //将信息拷给应用程序读入缓冲
I.Information()=fwLength; //返回信息长度
} else { I.Information()=0; //否则信息长度为0 t<<"buffsizetoosmall"<<EOL; } returnstatus;}45NTSTATUSSampleDevice::SAMPLE_IOCTL_Write_Handler(KIrpI){ //接受从应用程序中来的信息
NTSTATUSstatus=STATUS_SUCCESS; t<<"EnteringSampleDevice::SAMPLE_IOCTL_Write_Handler,"<<I<<EOL; charbuff[512]; ULONGfwLength=0; strcpy(buff,(PCHAR)I.IoctlBuffer());//拷贝从应用程序得到的命令串到驱动程序局部数据区
t<<“InputPutDatais\”“<<buff<<”\“”<<EOL; //显示从应用程序得到的命令串。
I.Information()=0; returnstatus;}46Test_Sample.cppvoidTest_SAMPLE_IOCTL_Read(void){ CHAR bufInput[IOCTL_INBUF_SIZE]; //Inputtodevice CHAR bufOutput[IOCTL_OUTBUF_SIZE]; //Outputfromdevice ULONG nOutput; //CountwrittentobufOutput
//CalldeviceIOControlinterface(SAMPLE_IOCTL_Read)indriver printf("IssuingIoctltodevice-");
strcpy(bufInput,"Thisisasample.");
if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_Read,NULL,
0, bufOutput,IOCTL_OUTBUF_SIZE,&nOutput,NULL)) { printf("ERROR:DeviceIoControlreturns%0x.",GetLastError()); Exit(1); }
else printf("Returnfromdriveris\"%s\"(%d)",bufOutput,nOutput);}47voidTest_SAMPLE_IOCTL_Write(void){ CHAR bufInput[IOCTL_INBUF_SIZE]; //Inputtodevice
CHAR bufOutput[IOCTL_OUTBUF_SIZE];//Outputfromdevice ULONG nOutput; //CountwrittentobufOutput //CalldeviceIOControlinterface(SAMPLE_IOCTL_Write)indriver printf("IssuingIoctltodevice-");
strcpy(bufInput,"Nowletuswritethisstring.");
if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_Write,bufInput,
strlen(bufInput), NULL,0,&nOutput,NULL))//该函数参数分别是设备句柄、IO控制命令、写缓冲、写缓冲大小、读缓冲、读缓冲大小、实际读的字节数、覆盖结构指针(注意,这里的bufInput是指Input到设备,所以对应用软件这是写缓冲,bufOutput是从设备output到应用程序,是读缓冲。
{ printf("ERROR:DeviceIoControlreturns%0x.", GetLastError()); Exit(1); }}48c.使用IO控制代码方式写并且读SampleDevice.cppNTSTATUSSampleDevice::SAMPLE_IOCTL_ReadWrite_Handler(KIrpI){ NTSTATUSstatus=STATUS_SUCCESS; t<<"EnteringSampleDevice::SAMPLE_IOCTL_ReadWrite_Handler,"<<I<<EOL; charbuff[512],buff1[512]; ULONGfwLength=0; strcpy(buff,(PCHAR)I.IoctlBuffer());//拷贝应用程序来的信息
t<<"InputPutDatais\""<<buff<<"\""<<EOL; strcpy(buff1,"thisisfeedbackfromdriver!Applicationgivemethisstring\""); strcat(buff1,buff); strcat(buff1,“\”“);//以上是组织反馈的信息49 fwLength=strlen(buff1)+1; if(I.IoctlOutputBufferSize()>=fwLength) { strcpy((PCHAR)I.IoctlBuffer(),buff1);//拷贝反馈信息
I.Information()=fwLength; //设置反馈信息字节数
} else { I.Information()=0; t<<"buffsizetoosmall"<<EOL; } returnstatus;}50Test_Sample.cppvoidTest_SAMPLE_IOCTL_ReadWrite(void){ bufOutputiswrittenbythedevicetoreturndatatothisapplication CHAR bufInput[IOCTL_INBUF_SIZE]; //Inputtodevice CHAR bufOutput[IOCTL_OUTBUF_SIZE]; //Outputfromdevice ULONG nOutput; //CountwrittentobufOutput //CalldeviceIOControlinterface(SAMPLE_IOCTL_ReadWrite)indriver printf("IssuingIoctltodevice-");
strcpy(bufInput,"Thisisasample."); if(!DeviceIoControl(hDevice,SAMPLE_IOCTL_ReadWrite,bufInput, strlen(bufInput),bufOutput, IOCTL_OUTBUF_SIZE,&nOutput,NULL)) { printf("ERROR:DeviceIoControlreturns%0x.",GetLastError()); Exit(1); } else printf("Feedbackis\"%s\"(%d)",bufOutput,nOutput);}5152533)直接对端口寄存器读写DriverStudio提供了KIoRange类来将外部总线的I/O地址空间范围映射到处理器总线的地址空间范围。该类的成员函数主要有KIoRange 构造函数(4种格式)Initialize
初始化和重新初始化一个实例(3种格式)~KIoRange
析构函数Invalidate
从已初始化状态删除该对象IsValid 测试该对象是否已经初始化inb
读一个或多个字节(2种形式)Outb 写一个或多个字节(2种形式)Inw 读一个或多个字(2种形式)Outw 写一个或多个字(2种形式)ind 读一个或多个双字(2种形式)outd
写一个或多个双字(2种形式)54写端口(OCW1,设置中断屏蔽,地址21H)m_ParPortIos.outb(1,0x00);//OCW1,打开所有中断读端口(读屏蔽寄存器,地址21H)
UCHARdata=m_ParPortIos.inb(1);下面我们来访问8259A的屏蔽寄存器。首先定义类KIoRange的一个实例,以定义相关地址空间。
KIoRangem_ParPortIos;
初始化实例(指定8259A的端口首地址,并映射)
status=m_ParPortIos.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年初级会计职称模拟考试试题(全套)
- 压力容器发生泄漏人员疏散撤离实施方案
- 2025年GIS气体绝缘设备检漏检修人员上岗题库答案
- 拆除工程扬尘失控应急预案
- 2026年农业面源污染治理政策试题及答案
- 2026‑2031年中国山西房地产行业市场调查研究及发展前景预测报告
- 2025年餐饮行业后厨部厨师长厨师管理手册
- 高尿酸血症诊疗共识要点
- 年回收与暂存2万吨废铅酸电池项目环评报告表
- 2025-2026年重庆市北师大版初中英语下册第6单元同步练习题
- 男女平等课件
- QGDW10936-2018物料主数据分类与编码规范
- DB21-T2205-2013LED照明工程安装与质量验收规程
- 高级职称护理竞聘
- 初中生人防知识主题班会
- 2025年《管理学》考试题库及参考答案
- 风光储储能项目PCS舱、电池舱吊装方案
- 研究生三年规划汇报
- 牵手混声合唱谱
- 建筑企业舆情应对培训课件
- 泌尿外科学教案:泌尿、男生殖系统其他疾病
评论
0/150
提交评论