windows98/2000 驱动程序编写方法
Post on 23-Feb-2016
81 Views
Preview:
DESCRIPTION
TRANSCRIPT
http://qsyang.yeah.net
现代微机原理与接口技术
1
Windows98/2000 驱动程序编写方法(下)杨全胜
http://qsyang.yeah.net
现代微机原理与接口技术
2
4.Driver Works 的使用1 )生成简单框架
http://qsyang.yeah.net
现代微机原理与接口技术
3
工程文件名工程文件目录
http://qsyang.yeah.net
现代微机原理与接口技术
4
选择驱动类型
http://qsyang.yeah.net
现代微机原理与接口技术
5
创建功能驱动程序 创建过滤器驱动程序
http://qsyang.yeah.net
现代微机原理与接口技术
6
选择相应总线
本例不驱动硬件
http://qsyang.yeah.net
现代微机原理与接口技术
7
驱动类名称驱动类文件名
http://qsyang.yeah.net
现代微机原理与接口技术
8
选择需要处理的消息句柄
http://qsyang.yeah.net
现代微机原理与接口技术
9
http://qsyang.yeah.net
现代微机原理与接口技术
10
http://qsyang.yeah.net
现代微机原理与接口技术
11
http://qsyang.yeah.net
现代微机原理与接口技术
12
添加和应用程序之间通信的控制代码
http://qsyang.yeah.net
现代微机原理与接口技术
13
http://qsyang.yeah.net
现代微机原理与接口技术
14
http://qsyang.yeah.net
现代微机原理与接口技术
15
测试用应用程序名称
http://qsyang.yeah.net
现代微机原理与接口技术
16
http://qsyang.yeah.net
现代微机原理与接口技术
17
http://qsyang.yeah.net
现代微机原理与接口技术
18
驱动类设备类
http://qsyang.yeah.net
现代微机原理与接口技术
19
驱动类文件设备类文件
测试用的控制台程序文件
驱动安装指导文件
http://qsyang.yeah.net
现代微机原理与接口技术
20
此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在 VC集成环境下区修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。
http://qsyang.yeah.net
现代微机原理与接口技术
21
该驱动程序框架包含了几个最基本的类,这些类是:class Sample : public KDriver // 驱动程序类,用于初始化驱动程序{ SAFE_DESTRUCTORSpublic: // 以下成员函数注意和 WDM 中有关例程联系起来看 virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath); virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo); void LoadRegistryParameters(KRegistryKey &Params);
int m_Unit;
// The following data members are loaded from the registry during DriverEntryULONG m_bBreakOnEntry;
};
http://qsyang.yeah.net
现代微机原理与接口技术
22
class SampleDevice : public KPnpDevice // 是设备类 KDvice 的派生类,用于在 WDM 环境下支持即插即用设备{
// Constructorspublic:
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);
http://qsyang.yeah.net
现代微机原理与接口技术
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.};
http://qsyang.yeah.net
现代微机原理与接口技术
24
先编译驱动程序工程
在 VC 的集成环境中
下面我们讲解编译、执行和调试这个驱动程序。
http://qsyang.yeah.net
现代微机原理与接口技术
25
http://qsyang.yeah.net
现代微机原理与接口技术
26
再编译测试应用程序工程
http://qsyang.yeah.net
现代微机原理与接口技术
27
http://qsyang.yeah.net
现代微机原理与接口技术
28
下面使用 DriverStudio 带的工具加载驱动程序和查看调试信息。 驱动程序监视,可实时看到驱动程序发出的调试输出语句
驱动程序装载器,可动态调用驱动程序
http://qsyang.yeah.net
现代微机原理与接口技术
29
驱动程序监视器界面
http://qsyang.yeah.net
现代微机原理与接口技术
30
驱动程序装载器界面
http://qsyang.yeah.net
现代微机原理与接口技术
31
http://qsyang.yeah.net
现代微机原理与接口技术
32
http://qsyang.yeah.net
现代微机原理与接口技术
33
http://qsyang.yeah.net
现代微机原理与接口技术
34
http://qsyang.yeah.net
现代微机原理与接口技术
35
http://qsyang.yeah.net
现代微机原理与接口技术
36
http://qsyang.yeah.net
现代微机原理与接口技术
37
下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:a. 使用 Read 和 Write 方式分别从驱动程序读入字符和 向驱动程序写字符。b. 使用 IO 控制代码方式分别从驱动程序读入字符和 向驱动程序写字符。c. 使用 IO 控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。 注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是 DriverWorks 自动生成的。语句中“ t<< xxxxx” 这样的语句是向调试软件输出信息,该信息可以再 DriverMonitor 或其他调试监视器中看到。
2 )完成应用程序和驱动程序之间的信息交换
http://qsyang.yeah.net
现代微机原理与接口技术
38
a. 使用 Read 和 Write 方式分别读写SampleDevice.cppvoid 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; i<n; i++, j=(j + 1)%26){ buff[i] = 'a' + j; }buff[dwTotalSize]=‘\0’; // 指定串尾strcpy((char *)pBuffer,buff);
// 把给应用程序的数据拷贝给返回 BUFFt << “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);
}
http://qsyang.yeah.net
现代微机原理与接口技术
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);
}
http://qsyang.yeah.net
现代微机原理与接口技术
40
Test_Sample.cppvoid 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, &nRead, NULL);// 参数分别是设备句柄、输入缓冲地址、缓冲大小(字节数)、实际读的数据字节数、覆盖结构指针。
http://qsyang.yeah.net
现代微机原理与接口技术
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);
}
这几句删除
http://qsyang.yeah.net
现代微机原理与接口技术
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; i<n; i++, j=(j + 1)%26){
buf[i] = 'a' + j;}
http://qsyang.yeah.net
现代微机原理与接口技术
43
// Write data to driverprintf("Writing to device - ");WriteFile(hDevice, buf, n, &nWritten, NULL);// 写数据 , 参数的含义是驱动程序句柄、写缓冲、写缓冲大小、实际驱动程序得到的信息的字节数、覆盖结构指针。printf("%d bytes written to device (%d attempted).\n",
nWritten, n);i = 0; // Print what was writtenwhile(i < n){
j = min((i+26),n);for(; i < j; i++) {
printf("%c, ", buf[i]);}printf("\n");
}free(buf);
}
http://qsyang.yeah.net
现代微机原理与接口技术
44
b. 使用 IO 控制代码方式分别读写SampleDevice.cppNTSTATUS SampleDevice::SAMPLE_IOCTL_Read_Handler(KIrp I){ // 对应用程序读驱动程序的请求作响应
NTSTATUS status = STATUS_SUCCESS;t << "Entering SampleDevice::SAMPLE_IOCTL_Read_Handler, " << I
<< EOL;char buff1[512]; ULONG fwLength=0;strcpy(buff1,"Welcome to driver!");fwLength = strlen(buff1)+1;if (I.IoctlOutputBufferSize() >= fwLength) {// 如果读入缓冲够长
strcpy((PCHAR)I.IoctlBuffer(),buff1); // 将信息拷给应用程序读入缓冲I.Information() = fwLength; // 返回信息长度
}else {
I.Information() = 0; // 否则信息长度为 0 t << "buff size too small" << EOL;
}return status;
}
http://qsyang.yeah.net
现代微机原理与接口技术
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;
}
http://qsyang.yeah.net
现代微机原理与接口技术
46
Test_Sample.cppvoid 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, &nOutput, NULL)){
printf("ERROR: DeviceIoControl returns %0x.", GetLastError());
Exit(1);}else printf("Return from driver is \"%s\"(%d)",bufOutput,nOutput);
}
http://qsyang.yeah.net
现代微机原理与接口技术
47
void Test_SAMPLE_IOCTL_Write(void){
CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHARbufOutput[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, &nOutput, NULL)) // 该函数参数分别是设备句柄、 IO 控制命令、写缓冲、写缓冲大小、读缓冲、读缓冲大小、实际读的字节数、覆盖结构指针(注意,这里的 bufInput 是指 Input 到设备,所以对应用软件这是写缓冲, bufOutput 是从设备 output 到应用程序,是读缓冲。{
printf("ERROR: DeviceIoControl returns %0x.", GetLastError());
Exit(1);}
}
http://qsyang.yeah.net
现代微机原理与接口技术
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,“\”“); // 以上是组织反馈的信息
http://qsyang.yeah.net
现代微机原理与接口技术
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;
}
http://qsyang.yeah.net
现代微机原理与接口技术
50
Test_Sample.cppvoid Test_SAMPLE_IOCTL_ReadWrite(void){
bufOutput is written by the device to return data to this application
CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to device
CHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from deviceULONG nOutput;// 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 %0x.", GetLastError());
Exit(1);}else
printf("Feedback is \"%s\"(%d)",bufOutput,nOutput); }
http://qsyang.yeah.net
现代微机原理与接口技术
51
http://qsyang.yeah.net
现代微机原理与接口技术
52
http://qsyang.yeah.net
现代微机原理与接口技术
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 种形式 )
http://qsyang.yeah.net
现代微机原理与接口技术
54
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 类。
http://qsyang.yeah.net
现代微机原理与接口技术
55
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 的实例。
http://qsyang.yeah.net
现代微机原理与接口技术
56
KIoRange::inbFORM 1:UCHAR inb( ULONG ByteOffset );FORM 2:VOID inb( ULONG ByteOffset, PUCHAR Buffer, ULONG Count);从映射空间读一个或多个字节。
http://qsyang.yeah.net
现代微机原理与接口技术
57
KIoRange::outbFORM 1:VOID outb( ULONG ByteOffset,// 以字节为单位的目标位置到 IO空间开始位置的偏移值 UCHAR Data // 要写的一个字节数据);FORM 2:VOID outb( ULONG ByteOffset, PUCHAR Buffer,// 指向包含要写数据的缓冲的指针 ULONG Count // 缓冲中要写数据的字节数);写一个或多个字节到映射的 IO空间。
http://qsyang.yeah.net
现代微机原理与接口技术
58
• 写端口( 索引信息 , 地址70H ) m_ParPortIos.outb(0,0x02); // 准备读分钟信息
• 读端口(读分钟信息,地址 71H )UCHAR data = m_ParPortIos.inb(1);
下面我们来访问 CMOS 的数据。• 首先定义类 KIoRange 的一个实例,以定义相关地址空间。
KIoRange m_ParPortIos;• 初始化实例(指定 CMOS 的端口首地址,并映射)
status = m_ParPortIos.Initialize( 0x70, // CMOS端口首地址是 70H
TRUE, // 在 CPU I/O空间内 8, // 设备读写数据的字节宽度 TRUE // 映射到系统空间 );
http://qsyang.yeah.net
现代微机原理与接口技术
59
4 )截获中断和挂接中断服务例程 DriverStudio提供了 KInterrupt 类来截获和挂接中断。 该类的成员函数主要有KInterrupt 构造函数 (3种格式 )Initialize 在无效状态下初始化一个对象 (3种格式 )Connect 绑定 ISR (中断服务例程)到中断InitializeAndConnect 一步完成初始化与绑定工作,要用资源列表作为输入。~KInterrupt 析构函数Invalidate 在初始化状态下删除对象IsValid 检查对象是否初始化Disconnect 使中断和 ISR 与中断分离Synchronize 当得到一个中断自旋锁时请求同步功能
http://qsyang.yeah.net
现代微机原理与接口技术
60
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 的实例。
http://qsyang.yeah.net
现代微机原理与接口技术
61
KInterrupt::Initialize (只介绍WDM形式)FORM 2: (WDM)VOID Initialize( KIRQL irql, ULONG vector, KINTERRUPT_MODE Mode, BOOLEAN bShareVector=FALSE, KAFFINITY affinity=1, BOOLEAN bSaveFloat=FALSE);初始化对象。只在对象没有初始化的时候使用。
http://qsyang.yeah.net
现代微机原理与接口技术
62
KInterrupt::ConnectFORM 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( 中断处理程序)。
http://qsyang.yeah.net
现代微机原理与接口技术
63
KInterrupt::InitializeAndConnectNTSTATUS InitializeAndConnect( PCM_RESOURCE_LIST pResourceList, // 指向资源列表的指针 PKSERVICE_ROUTINE Isr, PVOID IsrContext, ULONG Ordinal=0, BOOLEAN bSaveFloat=FALSE);初始化一个中断并绑定到一个 ISR上。对于 WDM 驱动程序, pResourceList 必须是一个转换资源表,例如是 KIrp::TranslatedResources 的返回值。
http://qsyang.yeah.net
现代微机原理与接口技术
64
下面我们来举例说明。• 首先定义类 KInterrupt 的一个实例 KInterrupt m_TheInterrupt; • 在设备类中声明一个成员函数 TheIsr 作为中断服务例程 ISR 。
class SampleDevice : public KPnpDevice{ …… public:
MEMBER_ISR (SampleDevice, TheIsr); ……
#ifdef _COMMENT_ONLY BOOLEAN TheIsr ( void ) { return TRUE ; };
#endif ……}
http://qsyang.yeah.net
现代微机原理与接口技术
65
• 在 OnStartDevice 例程中获取包括中断的设备资源并初始化中断和挂接 ISR SampleDevice ::OnStartDevice(KIrp I){……PCM_RESOURCE_LIST pResList =
I.TranslatedResources(); // 获取设备资源// 初始化中断并挂接中断服务例程 TheIsrstatus =
m_TheInterrupt.InitializeAndConnect(pResList, LinkTo(TheIsr), this);
……}
http://qsyang.yeah.net
现代微机原理与接口技术
66
5 )如何写 Win32 类型的驱动程序的测试程序 DriverStudio 自动生成的驱动程序的测试程序是一个控制台程序,下面我们将利用该控制台程序来写一个 Win32的程序。 第一步,在由 DriverStudio 自动生成一个驱动程序工作区 (Workspace) 中添加一个新的子工程,该子工程指定为一个 MFC 的 EXE 程序。 右键点击
http://qsyang.yeah.net
现代微机原理与接口技术
67
http://qsyang.yeah.net
现代微机原理与接口技术
68
第二步,手工在新的工程中添加几个文件这几个程序需要手工添加进去,实际上这几个程序都在 DriverStudio 自动生成的原来的两个工程文件中 ( 这个例子是 MyIOPort和 Test_MyIOPort 工程 ) 。将他们添加到新工程中,方法是右键点击新工程中的相关文件夹,在弹出菜单中选择 Add Files to Folder… ,然后找到要添加的文件并添加。
http://qsyang.yeah.net
现代微机原理与接口技术
69
第三步,打开 OpenByIntf.cpp 文件,在开始第一行添加#include "stdafx.h" 第四步, 1
2
3 4
5C:\PROGRAM FILES\COMPUWARE\SOFTICE DRIVER SUITE\DRIVERWORKS\INCLUDE
http://qsyang.yeah.net
现代微机原理与接口技术
70
第五步, 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
可以直接从自动生成的控制台工程的设置中拷贝这些库的名称
http://qsyang.yeah.net
现代微机原理与接口技术
71
最后,在控制台程序的 Test_XXXX.CPP 程序基础上进行必要的修改。注意要保留的是打开设备、关闭设备、读写设备有关的函数。界面部分应该全部换成 Windows 界面的代码,而不是保留控制台代码。
top related