Presentation is loading. Please wait.

Presentation is loading. Please wait.

一个端口访问器的编写 — Windows XP驱动程序举例 VS.NET+WIN XP DDK+DriverStudio3.2开发环境版

Similar presentations


Presentation on theme: "一个端口访问器的编写 — Windows XP驱动程序举例 VS.NET+WIN XP DDK+DriverStudio3.2开发环境版"— Presentation transcript:

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

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

3

4

5

6

7

8

9

10 2次

11

12

13

14

15

16

17

18

19

20

21

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

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

24 修改下面函数代码: 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; }

25 下面的函数保留和添加下述语句,其他全部删除
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 );

26 // 从端口读一个字节的数据 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;

27 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; }

28

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

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

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

32

33 在“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

34 在“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) )

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

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

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

38 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, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );

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

40 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")); // Setup the device interface struct deviceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

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

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

43 void Sound(DWORD freq )
{ UCHAR data; if(freq>=20 && freq<=20000) freq = / 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));

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

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

46 "状态寄存器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 =Anti-Virus 硬盘Boot区写保护 0=disable .xxx.... 软驱2类型 ....xxxx 软驱3类型",

47 "所安装设备的类型:xx. 00=1个软驱,01=2个软驱,. xx
"所安装设备的类型:xx =1个软驱,01=2个软驱,..xx =单显 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 CPU Cache 0=disable 1= enable ", "(海洋板)x =键盘使用缺省参数 0=使用本单元值 .xx..... 键盘延时00=0.25秒01=0.5秒10=0.75秒11=1秒 ...xxxxx 键盘重发速率,单位cps",

48 "(海洋板)硬盘1的柱面数", "(海洋板)硬盘1的磁头数", "(海洋板)硬盘1的扇区数", "(海洋板)硬盘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", "串口配置", "并口配置", "未使用",

49 "标准CMOS校验和", "扩充内存容量低字节,单位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",

50 "xx. 口令检测方式 0=Disable 1=Setup only 2=Powerup&Setup 3=Bootup&Setup
"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单元 ", "保留",

51 "保留",

52 "保留",

53 "保留",

54 "保留", "保留" }; LVITEM lvitem; HWND hWnd; hWnd = GetDlgItem(hDlg, IDC_CMOSLIST); BOOL qu; UCHAR index,value,tmp; for(i=0;i<128;i++) { lvitem.mask = LVIF_TEXT|LVIF_STATE; lvitem.iItem = i; lvitem.iSubItem = 0; sprintf(buff,"%02XH",i); lvitem.pszText = buff;

55 SendMessage(hWnd,LVM_INSERTITEM,0,(LPARAM)&lvitem);
lvitem.mask = LVIF_TEXT; lvitem.iItem = i; lvitem.iSubItem = 1; tmp = (UCHAR)i; index = 0x80 | tmp; WriteOneByte(0x70,index); value = ReadOneByte(0x71); sprintf(buff,"%02XH",value); SendMessage(hWnd,LVM_SETITEM,0,(LPARAM)&lvitem); lvitem.iSubItem = 2; lvitem.pszText = cmosram[i]; }

56 下面增加关键的消息处理: LRESULT CALLBACK MyIOPortMainDlgProc(
HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { …… switch (uMsg) case WM_INITDIALOG: g_hDevice = INVALID_HANDLE_VALUE; // 初始化List Control hWnd = GetDlgItem(hDlg, IDC_CMOSLIST); RECT rect; GetWindowRect(hWnd,&rect); LVCOLUMN lvm;

57 strcpy(lvm.pszText,"偏移"); lvm.cx = (rect.right - rect.left)/10;
lvm.iSubItem = 0; lvm.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; lvm.fmt = LVCFMT_CENTER; SendMessage(hWnd,LVM_INSERTCOLUMN,0,(LPARAM)&lvm); strcpy(lvm.pszText,"值"); lvm.iSubItem = 1; SendMessage(hWnd,LVM_INSERTCOLUMN,1,(LPARAM)&lvm); lvm.cx = (rect.right - rect.left)*4/5; lvm.iSubItem = 2; SendMessage(hWnd,LVM_INSERTCOLUMN,2,(LPARAM)&lvm);

58 if(OpenMyDevice()) { EnableWindow(GetDlgItem(hDlg, IDC_READCMOS), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_SPEAKER), TRUE); } else EnableWindow(GetDlgItem(hDlg, IDC_READCMOS), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_SPEAKER), FALSE); // 此处还有DS自动生成的程序段,需全部删除 return 1; case WM_COMMAND: switch (LOWORD(wParam)) case IDOK: if (g_hDevice != INVALID_HANDLE_VALUE)

59 CloseHandle(g_hDevice);
g_hDevice = INVALID_HANDLE_VALUE; } // Terminate our I/O completion thread SetEvent(g_hIoCompletionThreadTerminationEvent); WaitForSingleObject(g_hIoCompletionThread, INFINITE); UnregisterDeviceNotification(g_hInterfaceNotification); EndDialog(hDlg, 0); PostQuitMessage(0); break; case IDC_SPEAKER: // C调 Sound(262); // 1 = 262 Hz Sleep(200); Silence(); Sound(288); // 2 = 294 Hz

60 Sound(330); // 3 = 330 Hz Sleep(200); Silence(); break; case IDC_READCMOS: OnReadcmos(hDlg); default: } ……

61 做完上述添加后,将下列在MyIOPortApp.cpp文件中DS自动生成的部分删除:
DWORD MyIOPortEnumerateDevices(HWND hDlg) { …… // 该函数全部删除 } HANDLE MyIOPortOpenDevice(HWND hDlg) 删除下列消息的处理程序: WM_DEVICECHANGE,IDC_OPEN_BUTTON,IDC_CLOSE_BUTTON,IDC_OP_TYPE_COMBO IDC_DEVICE_INSTANCE_LIST,IDC_EXECUTE_BUTTON,IDC_CANCEL_IO_BUTTON

62 1)右键点击 2)选择该项目

63 1)右键点击 2)选择该项目


Download ppt "一个端口访问器的编写 — Windows XP驱动程序举例 VS.NET+WIN XP DDK+DriverStudio3.2开发环境版"

Similar presentations


Ads by Google