• / 57
  • 下载费用:10 金币  

WINDOWS98-2000驱动程序编写方法(下).ppt

关 键 词:
WINDOWS98-2000驱动程序编写方法(下).ppt
资源描述:
1,Windows98/2000驱动程序编写方法,(下),2,4.Driver Works的使用,1)生成简单框架,3,,,工程文件名,工程文件目录,4,,,选择驱动类型,5,,,创建功能驱动程序,创建过滤器驱动程序,6,,,选择相应总线,本例不驱动硬件,7,驱动类名称,驱动类文件名,,8,,,选择需要处理的消息句柄,9,,,,10,,11,,,,12,添加和应用程序之间通信的控制代码,13,14,,15,测试用应用程序名称,,16,,17,,18,驱动类,设备类,19,驱动类文件,设备类文件,测试用的控制台程序文件,驱动安装指导文件,20,此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在VC集成环境下区修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。,21,该驱动程序框架包含了几个最基本的类,这些类是: class Sample : public KDriver // 驱动程序类,用于初始化驱动程序 {SAFE_DESTRUCTORS public:// 以下成员函数注意和WDM中有关例程联系起来看virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath);virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo);void LoadRegistryParameters(KRegistryKey ,22,class SampleDevice : public KPnpDevice // 是设备类KDvice的派生类,用于在WDM环境下支持即插即用设备 {// Constructors public:SAFE_DESTRUCTORS;SampleDevice(PDEVICE_OBJECT Pdo, ULONG Unit);~SampleDevice();// Member Functions 注意和PNP的次功能代码联系起来看 public:DEVMEMBER_DISPATCHERSvirtual 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);,23,NTSTATUS SAMPLE_IOCTL_Read_Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_Write_Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_ReadWrite_Handler(KIrp I); #ifdef _COMMENT_ONLYvirtual 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)ULONG m_Unit;KPnpLowerDevice m_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. };,24,先编译驱动程序工程,在VC的集成环境中,下面我们讲解编译、执行和调试这个驱动程序。,25,,26,再编译测试应用程序工程,27,,28,下面使用DriverStudio带的工具加载驱动程序和查看调试信息。,驱动程序监视,可就看到驱动程序发出的调试输出语句,驱动程序装载器,可动态调用驱动程序,29,驱动程序监视器界面,30,驱动程序装载器界面,,,31,,,32,,,33,,,,,34,,35,,36,,,,,37,下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:,使用Read和Write方式分别从驱动程序读入字符和 向驱动程序写字符。 使用IO控制代码方式分别从驱动程序读入字符和 向驱动程序写字符。 使用IO控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。,注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是DriverWorks自动生成的。语句中“t xxxxx”这样的语句是向调试软件输出信息,该信息可以再DriverMonitor或其他调试监视器中看到。,2)完成应用程序和驱动程序之间的信息交换,38,使用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 sizechar buff[512]; int n =512, j = (n % 26);for (int i=0; in; i++, j=(j + 1)%26){ buff[i] = 'a' + j; }buff[dwTotalSize]=‘\0’; //指定串尾strcpy((char *)pBuffer,buff);// 把给应用程序的数据拷贝给返回BUFFt “The string you where read is \”“ buff ”\“” EOL; // 输出调试信息ULONG dwBytesRead = strlen(buff); // Count of bytes read I.Information() = dwBytesRead; // 返回给应用程序的信息的字节个数I.Status() = status;m_DriverManagedQueue.PnpNextIrp(I); },39,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 buff[512];strcpy(buff, (char *)pBuffer); // 应用程序写给驱动程序的数据在I.BufferedWriteSource()返回的指针中。buff[dwBytesSent] = '\0'; t “Write to driver is \““ buff “\““ EOL;I.Information() = dwBytesSent; // 返回用户实际写的字节数I.Status() = status;m_DriverManagedQueue.PnpNextIrp(I); },40,Test_Sample.cpp,void doRead(int n) // 从驱动程序中读数据 {char *buf;ULONG nRead;int i, j;buf = (char *) malloc(n);if (buf == NULL){printf(“Failed to allocate buffer for read“);Exit(1);}// Read data from driverprintf(“Reading from device - “);ReadFile(hDevice, buf, n, // 参数分别是设备句柄、输入缓冲地址、缓冲大小(字节数)、实际读的数据字节数、覆盖结构指针。,41,printf(“%d bytes read from device (%d requested).\n“, nRead, nRead);// Print what was readwhile(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); },,这几句删除,42,void doWrite(int n) // 向驱动程序中写数据 {char *buf;ULONG nWritten;int i, 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 writej = (n % 26);// load buffer with dummy data (abcdefg.)for (i=0; in; i++, j=(j + 1)%26){buf[i] = 'a' + j;},43,// Write data to driverprintf(“Writing to device - “);WriteFile(hDevice, buf, n, },44,b. 使用IO控制代码方式分别读写,SampleDevice.cpp,NTSTATUS SampleDevice::SAMPLE_IOCTL_Read_Handler(KIrp I) { // 对应用程序读驱动程序的请求作响应NTSTATUS status = STATUS_SUCCESS;t = fwLength) {// 如果读入缓冲够长strcpy((PCHAR)I.IoctlBuffer(),buff1); // 将信息拷给应用程序读入缓冲I.Information() = fwLength; // 返回信息长度} else {I.Information() = 0; // 否则信息长度为0t “buff size too small“ EOL;}return status; },45,NTSTATUS SampleDevice::SAMPLE_IOCTL_Write_Handler(KIrp I) { // 接受从应用程序中来的信息NTSTATUS status = STATUS_SUCCESS;t “Entering SampleDevice :: SAMPLE_IOCTL_Write_Handler , “ I EOL;char buff[512]; ULONG fwLength=0; strcpy(buff,(PCHAR)I.IoctlBuffer()); // 拷贝从应用程序得到的命令串到驱动程序局部数据区t “InputPut Data is \”“ buff ”\“” EOL; // 显示从应用程序得到的命令串。I.Information() = 0;return status; },46,Test_Sample.cpp,void Test_SAMPLE_IOCTL_Read(void) {CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from deviceULONG nOutput; // Count written to bufOutput// Call device IO Control interface (SAMPLE_IOCTL_Read) in driverprintf(“Issuing Ioctl to device - “);strcpy(bufInput,“This is a sample.“); if (!DeviceIoControl(hDevice,SAMPLE_IOCTL_Read, NULL, 0,bufOutput, IOCTL_OUTBUF_SIZE, },47,void Test_SAMPLE_IOCTL_Write(void) {CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHAR bufOutput[IOCTL_OUTBUF_SIZE];// Output from deviceULONG nOutput; // Count written to bufOutput// Call device IO Control interface (SAMPLE_IOCTL_Write) in driverprintf(“Issuing Ioctl to device - “);strcpy(bufInput,“Now let us write this string.“); if (!DeviceIoControl(hDevice, SAMPLE_IOCTL_Write, bufInput, strlen(bufInput), NULL, 0, } },48,c. 使用IO控制代码方式写并且读,SampleDevice.cpp,NTSTATUS SampleDevice::SAMPLE_IOCTL_ReadWrite_Handler(KIrp I) {NTSTATUS status = STATUS_SUCCESS;t “Entering SampleDevice::SAMPLE_IOCTL_ReadWrite_Handler, “ I EOL;char buff[512],buff1[512]; ULONG fwLength=0; strcpy(buff,(PCHAR)I.IoctlBuffer());// 拷贝应用程序来的信息t “InputPut Data is \““ buff “\““ EOL; strcpy(buff1,“this is feedback from driver! Application give me this string \““);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 “buff size too small“ EOL;}return status; },50,Test_Sample.cpp,void Test_SAMPLE_IOCTL_ReadWrite(void) {bufOutput is written by the device to return data to this applicationCHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from deviceULONG nOutput; // Count written to bufOutput// Call device IO Control interface (SAMPLE_IOCTL_ReadWrite) in driverprintf(“Issuing Ioctl to device - “);strcpy(bufInput,“This is a sample.“);if (!DeviceIoControl(hDevice, SAMPLE_IOCTL_ReadWrite, bufInput, strlen(bufInput),bufOutput, IOCTL_OUTBUF_SIZE, },51,,,,52,,,,,,,53,3)直接对端口寄存器读写,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) UCHAR data = m_ParPortIos.inb(1);,下面我们来访问8259A的屏蔽寄存器。首先定义类KIoRange的一个实例,以定义相关地址空间。 KIoRange m_ParPortIos;初始化实例(指定8259A的端口首地址,并映射) status = m_ParPortIos.Initialize( 0x20, // 主8259A端口首地址是20H TRUE, //在CPU I/O空间内 8, // 设备读写数据的字节宽度 TRUE // 映射到系统空间 );,55,4)截获中断和挂接中断服务例程,DriverStudio提供了KInterrupt类来截获和挂接中断。,该类的成员函数主要有 KInterrupt 构造函数(3种格式) Initialize 在无效状态下初始化一个对象 (3种格式) Connect 捆绑ISR(中断服务例程)到中断 InitializeAndConnect 一步完成初始化与捆绑工作,要用资源列表作为输入。 ~KInterrupt 析构函数 Invalidate 在初始化状态下删除对象 IsValid 检查对象是否初始化 Disconnect 使中断和ISR与中断分离 Synchronize 当得到一个中断自旋锁时请求同步功能,56,下面我们来举例说明。首先定义类KInterrupt的一个实例 KInterrupt m_TheInterrupt; 在设备类中声明一个成员函数TheIsr作为中断服务例程ISR。 class SampleDevice : public KPnpDevice { …… public: MEMBER_ISR (SampleDevice, TheIsr); …… #ifdef _COMMENT_ONLY BOOLEAN TheIsr(void); #endif …… },57,在OnStartDevice例程中获取包括中断的设备资源并初始化中断和挂接ISR SampleDevice ::OnStartDevice(KIrp I) { …… PCM_RESOURCE_LIST pResList = I.TranslatedResources(); //获取设备资源 //初始化中断并挂接中断服务例程TheIsr status = m_TheInterrupt.InitializeAndConnect(pResList, LinkTo(TheIsr), this); …… },
展开阅读全文
  微传网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
0条评论

还可以输入200字符

暂无评论,赶快抢占沙发吧。

关于本文
本文标题:WINDOWS98-2000驱动程序编写方法(下).ppt
链接地址:https://www.weizhuannet.com/p-10211796.html
微传网是一个办公文档、学习资料下载的在线文档分享平台!

网站资源均来自网络,如有侵权,请联系客服删除!

 网站客服QQ:80879498  会员QQ群:727456886

copyright@ 2018-2028 微传网络工作室版权所有

     经营许可证编号:冀ICP备18006529号-1 ,公安局备案号:13028102000124

收起
展开