1 / 63

一个端口访问器的编写

一个端口访问器的编写. — Windows XP 驱动程序举例. VS.NET+WIN XP DDK+DriverStudio3.2 开发环境版. 东南大学计算机科学与工程学院 杨全胜. 本讲义假设阅读者已经熟悉 VC++.NET 和 VS.NET(2002) 的使用。如果对 Window XP 驱动程序的编写尚不熟悉,请参阅本人所编写的 《Windows XP 驱动程序编写方法 ——Step by Step》 电子讲义。.

zlata
Download Presentation

一个端口访问器的编写

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 一个端口访问器的编写 — Windows XP驱动程序举例 VS.NET+WIN XP DDK+DriverStudio3.2开发环境版 东南大学计算机科学与工程学院 杨全胜

  2. 本讲义假设阅读者已经熟悉VC++.NET和VS.NET(2002)的使用。如果对Window XP驱动程序的编写尚不熟悉,请参阅本人所编写的《Windows XP驱动程序编写方法——Step by Step》电子讲义。 注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是DriverWorks自动生成的。蓝色显示的部分是要删除的语句。省略号的部分是不变的。语句中T.Trace(TraceInfo, __FUNCTION__“xxxx”)这样的语句是向调试软件输出信息,该信息可在DriverMonitor或其他调试监视器中看到。

  3. 2次

  4. 由于一个可能是DriverStudio 3.2中的BUG,所以及时生成的一个空工程项目也无法编译通过,需要对生成的工程文件做以下手工修改: 把MyIOPort项目中的sources文件中的:TARGETLIBS=$ (DDK_LIB_PATH)\ntstrsafe.lib $ (DDK_LIB_PATH)\csq.lib这一行去掉就可以编译通过了

  5. 在“MyIOPortDevice.h”文件的 class MyIOPortDevice : public KPnpDevice定义中添加下面的变量定义。 protected: // Member data KIoRange m_ParPortIos; 注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是DriverWorks自动生成的。蓝色显示的部分是要删除的语句。省略号的部分是不变的。语句中T.Trace(TraceInfo, __FUNCTION__“xxxx”)这样的语句是向调试软件输出信息,该信息可在DriverMonitor或其他调试监视器中看到。

  6. 修改下面函数代码: NTSTATUS MyIOPortDevice::OnStartDevice(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; // Get the list of raw resources from the IRP PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources(); // Get the list of translated resources from the IRP PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources(); // TODO: Add device-specific code to initialize/start your hardware device. // The base class will handle completion of the IRP status = m_ParPortIos.Initialize( 0x00,// PC机I/O地址空间的首地址是00H TRUE,// 在CPU I/O空间内 8,// 设备读写数据的字节宽度 TRUE// 映射到系统空间 ); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; }

  7. 下面的函数保留和添加下述语句,其他全部删除下面的函数保留和添加下述语句,其他全部删除 NTSTATUS MyIOPortDevice::MYIOPORT_IOCTL_Read_Handler(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; ULONG outputSize = I.IoctlOutputBufferSize(); char buff1[50],buff2[50]; struct ioport { int port; UCHAR data; } *iopt; ULONG fwLength=0; iopt=(ioport *)I.IoctlBuffer();// 指针直接指向IRP的BUFF区域这里进 //来的时候有用户程序的信息,出去的时候放返回信息 //显示从应用程序得到的要读的端口号。 T.Trace(TraceInfo, __FUNCTION__"Read port is 0x%d\n", iopt->port );

  8. // 从端口读一个字节的数据 iopt->data= (UCHAR)m_ParPortIos.inb(iopt->port); fwLength = 8; if (outputSize >= fwLength) // 如果读入缓冲够长 { I.Information() = fwLength;// 返回信息长度 T.Trace(TraceInfo, __FUNCTION__"Read Data is 0x%d\n", iopt->data);// 显示从应用程序得到的命令串。 } else { I.Information() = 0;// 否则信息长度为0 T.Trace(TraceInfo, __FUNCTION__"buff size too small\n"); } T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; }

  9. NTSTATUS MyIOPortDevice::MYIOPORT_IOCTL_Write_Handler(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; char buff1[50],buff2[50]; struct ioport { int port; UCHAR data; } *iopt; ULONG fwLength=0; iopt=(ioport *)I.IoctlBuffer();// 指针直接指向IRP的BUFF区域这里进来的时候有用户程序的信息,出去的时候放返回信息 T.Trace(TraceInfo, __FUNCTION__"Write port is 0x%d, Write data is 0x%d\n", iopt->port , iopt->data ); // 显示从应用程序得到的命令串。 m_ParPortIos.outb(iopt->port,iopt->data);// 向端口写一个字节的数据 I.Information() = 0; T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; }

  10. 下面我们来修改应用程序,该程序访问硬件端口来获得CMOS中的数据以及让主板小喇叭发声。首先要修改一下应用程序项目的属性中的字符集。缺省的字符集是“使用 Unicode 字符集”,把它改成“未设置”。 右键点击

  11. 接下来我们修改资源文件。下图是系统自动生成的应用程序界面,这并不适合我们的需要。删除这些控件,换上下页显示的控件。接下来我们修改资源文件。下图是系统自动生成的应用程序界面,这并不适合我们的需要。删除这些控件,换上下页显示的控件。 全部删除

  12. List Control Static Text Button 在对话框中分别建立如图的三个按钮,一个列表控件(List Control)和一个静态文本框。其中,列表控件和按钮的属性如下页的图设置。

  13. 在“MyIOPortApp.h”文件中增加下列函数声明 UCHAR ReadOneByte(int port); // 从port读一个字节 void WriteOneByte(int port, UCHAR value); // 向端口port写一个字节 BOOL OpenMyDevice(); // 打开设备 void Silence( void ); // 静音 void Sound(DWORD freq ); // 发频率为freq的声音 void OnReadcmos(HWND hDlg); // 读CMOS

  14. 在“MyIOPortApp.cpp”文件中增加下列函数: UCHAR ReadOneByte(int port) { char buff[200]; ULONG nOutput; // Count written to bufOutput struct ioport { int port; UCHAR data; } iopt,iopt2; iopt.port=port; if (!DeviceIoControl(g_hDevice, MYIOPORT_IOCTL_Read, &iopt, //输出到驱动程序 sizeof(iopt), //IOCTL_INBUF_SIZE, &iopt2, // 从驱动程序得到返回值 8, &nOutput, NULL) )

  15. { sprintf(buff,"ERROR: DeviceIoControl returns %0x.", GetLastError()); ::MessageBox(NULL,buff,"错误", MB_OK|MB_ICONSTOP); return 0; } else { return iopt2.data; } }

  16. void WriteOneByte(int port, UCHAR value) { char buff[200]; ULONG nOutput; struct ioport { int port; UCHAR data; } iopt,iopt2; iopt.port=port; iopt.data=value; if (!DeviceIoControl(g_hDevice, MYIOPORT_IOCTL_Write, &iopt, //输出到驱动程序 sizeof(iopt), //IOCTL_INBUF_SIZE, &iopt2, // 从驱动程序得到返回值 8, &nOutput, NULL) )

  17. { sprintf(buff,"ERROR: DeviceIoControl returns %0x.", GetLastError()); ::MessageBox(NULL,buff,"错误", MB_OK|MB_ICONSTOP); return ; } }

  18. BOOL OpenMyDevice() { DWORD lastError; HDEVINFO hDeviceInfo; DWORD bufferSize; SP_DEVICE_INTERFACE_DATA interfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail; // Find devices that have our interface hDeviceInfo = SetupDiGetClassDevs( (LPGUID)&GUID_DEVINTERFACE_MYIOPORT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );

  19. if (hDeviceInfo == INVALID_HANDLE_VALUE) { lastError = GetLastError(); MyIOPortOutputText(_T("SetupDiGetClassDevs failed, GetLastError() = %d"), lastError); return FALSE; } // Setup the interface data struct interfaceData.cbSize = sizeof(interfaceData); if(SetupDiEnumDeviceInterfaces(hDeviceInfo,NULL, (LPGUID)&GUID_DEVINTERFACE_MYIOPORT, 0,&interfaceData)) { if (!SetupDiGetDeviceInterfaceDetail( hDeviceInfo,&interfaceData, NULL,0,&bufferSize,NULL)) {

  20. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { MyIOPortOutputText(_T("Error: couldn't get interface detail, (%d)"), GetLastError()); return FALSE; } } // Allocate a big enough buffer to get detail data deviceDetail= (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(bufferSize); if (deviceDetail == NULL) { MyIOPortOutputText(_T("Error: Buffer allocation failed")); return FALSE; } // Setup the device interface struct deviceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

  21. // Try again to get the device interface detail info if (!SetupDiGetDeviceInterfaceDetail( hDeviceInfo, &interfaceData, deviceDetail, bufferSize, NULL, NULL)) { MyIOPortOutputText(_T("Error: SetupDiGetDeviceInterfaceDetail failed (%d)"), GetLastError()); free(deviceDetail); return FALSE; } SetupDiDestroyDeviceInfoList(hDeviceInfo);

  22. g_hDevice = CreateFile( (LPCTSTR)deviceDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,0); if (g_hDevice == INVALID_HANDLE_VALUE) { MyIOPortOutputText(_T("Error: CreateFile failed for device %s (%d)\n"), deviceDetail->DevicePath, GetLastError()); return FALSE; } MyIOPortOutputText(_T("Opened device %s"), deviceDetail->DevicePath); return TRUE; } MyIOPortOutputText(_T("No devices found")); return FALSE; }

  23. void Sound(DWORD freq ) { UCHAR data; if(freq>=20 && freq<=20000) { freq = 1193181 / freq; data = ReadOneByte(0x61); if((data & 3) == 0) { WriteOneByte(0x61, data | 3); WriteOneByte(0x43, 0xb6); } WriteOneByte(0x42, (UCHAR)(freq%256)); WriteOneByte(0x42, (UCHAR)(freq/256)); } }

  24. void Silence( void ) { UCHAR data; data = ReadOneByte(0x61); WriteOneByte(0x61, data & 0xfc); }

  25. void OnReadcmos(HWND hDlg) { // TODO: Add your control notification handler code here int i,it; char buff[23]; char cmosram[128][200]={ // CMOS每个字节的含义 "目前系统时间的秒", "报警时间秒值", "目前系统时间的分", "报警时间分值", "目前系统时间的小时", "报警时间小时值", "目前星期几", "目前系统日期", "目前系统月份", "目前系统年的后两位",

  26. "状态寄存器A", "状态寄存器B", "状态寄存器C", "状态寄存器D", "诊断状态记录值", "当机复位指示字节", "磁盘驱动器类型:xxxx.... 软驱0类型 0001=360K 0010=1.2M ....xxxx 软驱1类型 0011=720K 0100=1.44M 0110=2.88M", "(海洋板)..x..... 硬盘0Translate 1=Yes 0=No ...x.... 硬盘1Translate 1=Yes 0=No .....x.. 1=Step rate fast 0=Step rate slow ......xx 软驱个数00=1个 01=2个 10=三个 11=四个 ", "硬盘类型:xxxx.... 硬盘驱动器0的类型 1111=使用19h单元 ....xxxx 硬盘驱动器1的类型 1111=使用1Ah单元", "字节 x....... 1=Anti-Virus 硬盘Boot区写保护 0=disable .xxx.... 软驱2类型 ....xxxx 软驱3类型",

  27. "所安装设备的类型:xx...... 00=1个软驱,01=2个软驱,..xx.... 00=单显 01=CGA 10=CGA 11=VGA/EGA,后四位高到低是显示、键盘、协处理器与软件机使能(=1)", "基本内存容量低字节,单位KB", "基本内存容量高字节,单位KB", "扩充内存容量低字节,单位KB", "扩充内存容量高字节,单位KB", "(海洋板)硬盘驱动器0的类型", "(海洋板)硬盘驱动器1的类型", "(海洋板)显示卡类型 VGA/monochrome", "(海洋板)....xxxx 启动顺序0=A:C: 1=C:A: 2=Screen prompt 3=Auto search 4=Network .x...... 486-CPU Cache 0=disable 1= enable ", "(海洋板)x....... 1=键盘使用缺省参数 0=使用本单元值 .xx..... 键盘延时00=0.25秒01=0.5秒10=0.75秒11=1秒 ...xxxxx 键盘重发速率,单位cps",

  28. "(海洋板)硬盘1的柱面数", "(海洋板)硬盘1的柱面数", "(海洋板)硬盘1的磁头数", "(海洋板)硬盘1的扇区数", "(海洋板)硬盘0的柱面数", "(海洋板)硬盘0的柱面数", "(海洋板)硬盘0的磁头数", "(海洋板)硬盘0的扇区数", "(海洋板)AT-Bus clock 0=16.7Mhz 1=13.3Mhz 2=11.1Mhz 3=8.3Mhz 4=6.7Mhz 5=5.6Mhz 6=4.2Mhz", "(海洋板)memory type 00h=60nS 20h=70nS", "串口配置", "并口配置", "未使用", "未使用", "未使用", "未使用",

  29. "标准CMOS校验和", "标准CMOS校验和", "扩充内存容量低字节,单位KB", "扩充内存容量低字节,单位KB", "BCD码的世纪值(年的高2位,如19,20等)", "信息标志", "xxxx.... Shadow of D000 0=Vacant ....xxxx Shadow of C000 0=ROM ", "xxxx.... Shadow of F000 0=ROM ....xxxx Shadow of E000 0=Vacant ", "xxxx.... Shadow of D000 1=WP 0=Read/Write ....xxxx Shadow of C000 1=WP 0=Read/Write ", "xxxx.... Shadow of F000 1=WP 0=Read/Write ....xxxx Shadow of E000 1=WP 0=Read/Write ", "内存大小,单位兆", "(内存大小有关=160/前一单元 )", "口令代码Security Code", "口令代码Security Code",

  30. "xx...... 口令检测方式 0=Disable 1=Setup only 2=Powerup&Setup 3=Bootup&Setup ..xxxxxx Cold-Boot Delay 冷启动延时(单位秒)*2 ", "xxxx.... 4=Full test 5=Quick scan 7=Skip test ....xx.. Xfer-Mode of 硬盘0 0=Standard 1=Poll ......xx Xfer-Mode of 硬盘1 2=Block 3=32-Bit Block ", "10h-3Dh部分单元的按字节检查和,不包括17h,18h,19h,1Ah,26h, 27h,30h,31h,32h,38h,3Ah,3Ch,3Dh单元 ", "10h-3Dh部分单元的按字节检查和,不包括17h,18h,19h,1Ah,26h, 27h,30h,31h,32h,38h,3Ah,3Ch,3Dh单元 ", "保留", "保留", "保留", "保留", "保留", "保留", "保留",

More Related