Chinaunix首页 | 论坛 | 博客
  • 博客访问: 522554
  • 博文数量: 252
  • 博客积分: 6057
  • 博客等级: 准将
  • 技术积分: 1635
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-21 10:17
文章分类

全部博文(252)

文章存档

2013年(1)

2012年(1)

2011年(32)

2010年(212)

2009年(6)

分类:

2010-03-19 13:42:06

作者:

  驱动程序是为设备的硬件层编程服务的,但同样需要提供和应用程序进行通信的能力,从而最终达到应用程序控制设备的目的。本文主要讨 论应用程序与驱动程序的通信和驱动程序与应用程序的通信。
  在Windows中,应用程序实现与WDM通信的过程是:应用程序先用CreateFile函数打开设备,然后用DeviceIoControl和 WDM进行通信,包括从WDM读数据和写数据给WDM两种情况,也可用ReadFile从WDM中读数据或用WriteFile写数据给WDM。当应用程 序退出时,用CloseHandle关闭设备。

以下是用DeviceIoControl写数据给WDM的源代码:

void Test_P9052_IOCTL_805_WriteBase3(void)
{
ULONG nOutput; // Count written to bufOutput

// 传给驱动程序要写入的参数和数据
// 数组的第一个元素为写入的偏移地址,第二个元素为数据的个数,其它元素为写入的数据
ULONG bufInput[IOCTL_INBUF_SIZE+2];
ULONG offset; // 写入的偏移地址
ULONG num; // 写入的初始数据,以此来产生一个数组

printf("\n----------- ready for writing to Base3 -----------");

//获取写入的偏移地址
printf("\nPlease input the offset of the write operation(Hex):");
scanf("%x",&offset);
// //获取写入的数据个数
bufInput[0]=offset;
bufInput[1]=IOCTL_INBUF_SIZE;
//获取写入的数据
printf("\nPlease input the initial data to write(Hex):");
scanf("%x",&num);
for(ULONG j=0;j {
bufInput[2+j]=num;
num+=0x0;
}
//显示生成的数组
for(ULONG i=0;i {
printf("\nwrite data[%d]=%x",i,bufInput[i]);
}
// Call device IO Control interface in driver
if (!DeviceIoControl(hDevice,
P9052_IOCTL_805_WriteBase3,
bufInput,
(IOCTL_INBUF_SIZE+2)*4,//sizeof(bufInput),
NULL,//bufOutput,
0,//sizeof(bufOutput),
&nOutput,
NULL)
)
{
printf("\nERROR: DeviceIoControl returns %0x.", GetLastError());
Exit(1);
}
printf("\n\n");
}
以下是用DeviceIoControl从WDM中读数据的源代码:
void Test_P9052_IOCTL_804_ReadBase3(void)
{
ULONG bufOutput[IOCTL_OUTBUF_SIZE]; // 传出读取的数据缓冲区
ULONG nOutput; // 实际读取的数据个数
ULONG bufInput[2]; // 传入读取的参数
ULONG offset; // 要读取的偏移地址
printf("\n----------- ready for reading from Base3 -----------");
//获取读取的偏移地址:
printf("\nPlease input the offset of read operation(Hex):");
scanf("%x",&offset);
// //获取读取的数据个数:
// printf("\nPlease input the number of data to read(Dec):");
// scanf("%d",&number);
bufInput[0]=offset;
bufInput[1]=IOCTL_OUTBUF_SIZE;
// Call device IO Control interface (PCI9054_IOCTL_804_ReadBase3) in driver
if (!DeviceIoControl(hDevice,
P9052_IOCTL_804_ReadBase3,
bufInput,
2*4, // 字节
bufOutput,
IOCTL_OUTBUF_SIZE*4,//sizeof(bufOutput),
&nOutput,
NULL)
)
{
printf("\nERROR: DeviceIoControl returns %0x.", GetLastError());
Exit(1);
}
printf("\n------>>>>>> data read <<<<<<------");
for(ULONG i=0;i {
printf("\nread data[%d]=%x",i,bufOutput[i]);
}
printf("\n\n");
}

驱动程序与应用程序的通信:
与此相对应,当驱动程序捕捉到特点事件(如中断)发生时,应当可以与应用程序进行通信。 以下是通过I/O请求包(IRP),驱动程序的读数据函数:
VOID P9052Device::Serial_P9052_IOCTL_804_ReadBase3_Handler(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering P9052Device::Serial_P9052_IOCTL_804_ReadBase3_Handler, " << I << EOL;
KMemory Mem(I.Mdl());
// Use the memory object to create a pointer to the caller''s buffer
PULONG pOutBuffer = (PULONG) Mem.MapToSystemSpace(); //输出缓冲区指针,传出读取的数据
PULONG pInBuffer = (PULONG) I.IoctlBuffer(); //输入缓冲区指针
ULONG Offset; //读取的偏移地址
Offset = *pInBuffer;
ULONG count; //读取的数据个数
count = *(pInBuffer+1);
m_IoPortRange1_ForBase3.ind(Offset,pOutBuffer,count);
I.Information() = count;
I.Status() = status;
m_DriverManagedQueue.PnpNextIrp(I);
}
以下是通过IRP,驱动程序的写数据函数:
VOID P9052Device::Serial_P9052_IOCTL_805_WriteBase3_Handler(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering P9052Device::Serial_P9052_IOCTL_805_WriteBase3_Handler, " << I << EOL;
PULONG pInBuffer = (PULONG) I.IoctlBuffer(); //输入缓冲区指针
ULONG count; //从输入缓冲区要写入的数据个数
count=*(pInBuffer+1);
ULONG offset; //偏移地址
offset=*pInBuffer;
PULONG pBuffer = pInBuffer+2; //指向要写入的数据
m_IoPortRange1_ForBase3.outd(offset,pBuffer,count);
I.Information() = count;
I.Status() = status;
m_DriverManagedQueue.PnpNextIrp(I);
}
下图是运行时的界面:


图一 VC运行界面

  本文通过DriverWorks实现对PCI9052的数据写入、读出。读写方式是DirectIO方式。这是一种简单的方式,速度只能达到几M,如 果是大批量的数据写入可以采用buffer的方式。

下面给出上个用vc写的操作PCI9054 IO设备的源程序

pci9054实现IO操作.rar

http://blogimg.chinaunix.net/blog/upfile2/100417015224.rar

文件:pci9054实现IO操作.rar
大小:593KB
下载:下载
阅读(1283) | 评论(12) | 转发(0) |
给主人留下些什么吧!~~

chulia200020012010-04-17 01:24:30

不访问注册表,如何用 CreateFile("\\\\.\\HPYSICALDRIVE1",…… )的 HANDLE 获取硬盘的设备 http://topic.csdn.net/t/20040930/14/3421564.html

chulia200020012010-04-17 00:56:01

一个简单IO的驱动 http://www.delphibbs.com/keylife/iblog_show.asp?xid=22093 KeyLife富翁笔记 作者 : Amoeba 标题 : 一个简单IO的驱动 关键字: IO 驱动 分类 : 局域网 / 通讯 密级 : 公开 (评分: , 回复: 0, 阅读: 1098) »» 网友 hotboys 介绍 来源:http://dev.csdn.net/article/17/17296.shtm NT/2000/XP从安全性、可靠性、稳定性上考虑,应用程序和操作系统是分开的,操作系统代码运行在核心态,有权访问系统数据和硬件,能执行特权指令;应用程序运行在用户态,能够使用的接口和访问系统数据的权限都受到严格限制。当用户程序调用系统服务时,处理器捕获该调用,然后把调用的线程切换到核心态。当系统服务完成后,操作系统将线程描述表切换回用户态,调用者继续运行。 想在用户态应用程序中实现I/O读写,直接存取硬件,可以通过编写驱动程序,实现CreateFile、CloseHandle

chulia200020012010-04-17 00:54:40

http://www.wenhei.com/document/1317925/ 40 设备对象的命名 Windows系统中有一个称为“对象管理器”的执行模块复杂集中管理系统中所有的内核对象,其中包括驱动对象和设备对象。 对象管理器给大多数内核对象都起了名字,并把这些名字组织为具有树形结构的命名空间。 设备对象一般都位于该命名空间的\Device子目录下 其他内核模块和驱动程序都可以通过设备的名字获得该设备对象的指针(利用IoGetDeviceObjectPointer),并通过该指针向驱动对象发送IRP。 用户模式的应用程序对\Device子目录没有访问权 41 设备对象的命名(续) 为了给自己的设备对象命名,必须将名字存放在一个UNCODE_STRING型的字符串中,并将其作为IoCreateDevice的第3个参数传入。 UNICODE_STRING devname; RtlInitUnicodeString(&devname, L"\\Device\\Simple0"); IoCreateDevice(DriverObject, sizeof(D

chulia200020012010-04-17 00:42:25

http://www.pudn.com/downloads80/sourcecode/windows/vxd/detail309216.html PCI9054实现io操作的源代码

chulia200020012010-04-17 00:40:58

http://www.wenhei.com/document/1317925/ 应用程序如何通过设备名打开设备 在用户模式下 “\??”子目录叫做“\\.\”子目录,因此通过“\\.\”子目录下的符号链接名就可以找到设备对象,并打开指向设备对象的句柄。 hDevice = CreateFile("\\\\.\\Simple1", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ReadFile( hDevice, lpBuffer, ……..); WriteFile(hDevice, lpBuffer, ……..); ………..