jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
阅读:2158回复:14

应用程序与驱动的交互问题(DeviceIoControl()函数)

楼主#
更多 发布于:2003-04-06 19:29
我现在要用DeviceIoControl()函数来向设备写数据,我把数据存放在如下函数中的buffer里。
bResult = DeviceIoControl (hDevice,
IOCTL_EZUSB_BULK_WRITE,//写数据
&bulkControl,//管道(pipes)
sizeof (BULK_TRANSFER_CONTROL),
buffer,//存储数据的缓冲区
length,//读取的字节数
(unsigned long *)&nBytes,
NULL);

在驱动程序中,我要UsbBuildInterruptOrBulkTransferRequest()生成一个urb发给usbd,那么存储要传输数据的buffer地址存放在那个参数里?是Irp->AssociatedIrp.SystemBuffer还是Irp->MdlAddress?或者是其他的?还请知道的指点一下,多谢了。

最新喜欢:

wdy9927wdy992... lmhhlmhhlmhhlm...
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-04-06 23:10
那要看你的IOCTL_EZUSB_BULK_WRITE是怎么定义的了。DW Help里面有个How to就对此有详细的解释。
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-04-08 13:28
斑竹就是斑竹,一语中的,偶在msdn上找不到ioctl code的参数说明,原来在ddk的帮助里,多谢斑竹了!
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-04-09 16:13
在应用程序中:
typedef struct _BULK_TRANSFER_CONTROL
{
   ULONG pipeNum;

} BULK_TRANSFER_CONTROL, *PBULK_TRANSFER_CONTROL;

bResult = DeviceIoControl(hFile,//设备句柄
IOCTL_ISP1581_BULK_WRITE,//ctl code
&bulkControl,//选择端点
sizeof(BULK_TRANSFER_CONTROL),
threadParam->pcIoBuffer,//传输数据存储地址是个char型指针
           threadParam->uiLength,//传输数据长度(uint)
&nBytes,//实际传输的数据
NULL);
在驱动程序中:
PVOID   ioBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG   bufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

UsbBuildInterruptOrBulkTransferRequest(urb, //ptr to urb
(USHORT) urbSize, //size of urb
           pipeHandle,      //usbd pipe handle这个参数没问题
ioBuffer,        //TransferBuffer
           NULL,           //mdl
bufferLength,   //bufferlength
          USBD_SHORT_TRANSFER_OK,   //flags
           NULL);          //link

ntStatus = D12_CallUSBD(DeviceObject, urb);
if (NT_SUCCESS(ntStatus))
{
   Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
   D12_KdPrint((\"Successfully transfered 0x%x bytes\\n\",Irp->IoStatus.Information));
}


我用softice跟踪了一下,发现ioBuffer指向的地址中的数据不是我在应用程序中传过去的数据地址,
但是运行后有数据发送到设备方,而且urb->UrbBulkOrInterruptTransfer.TransferBufferLength中的数据也是我要求传输的数据数量,但是返回到app后,bResult却是0 !不知道为什么???希望知道的大虾给小弟指点指点,先谢过了


kilroy_guo
驱动大牛
驱动大牛
  • 注册日期2002-10-29
  • 最后登录2005-11-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-04-09 17:19
当应用程序发起一个读或写操作时,通过给出一个用户模式虚拟地址和长度,应用程序向I/O管理器提供了一个数据缓冲区。正如我在第三章中提到的,内核模式驱动程序几乎从不使用用户模式虚拟地址访问内存,因为你不能把线程上下文确定下来。Windows 2000为驱动程序访问用户模式数据缓冲区提供了三种方法:

在buffered方式中,I/O管理器先创建一个与用户模式数据缓冲区大小相等的系统缓冲区。而你的驱动程序将使用这个系统缓冲区工作。I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据。
在direct方式中,I/O管理器锁定了包含用户模式缓冲区的物理内存页,并创建一个称为MDL(内存描述符表)的辅助数据结构来描述锁定页。因此你的驱动程序将使用MDL工作。
在neither方式中,I/O管理器仅简单地把用户模式的虚拟地址传递给你。而使用用户模式地址的驱动程序应十分小心。


-----此文中得“我”,是waltoney,不知道这段话可不可以解释
“我用softice跟踪了一下,发现ioBuffer指向的地址中的数据不是我在应用程序中传过去的数据地址,”


bResult却是0 !我想可能是Irp->IoStatus.Status没有正确的填充。

我是菜鸟,不对的地方请指正。
二姑家的猫想......
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-04-09 19:07
首先感谢kilroy_guo大虾的热心回答,但是我还有一些问题,根据下面这段话:

“在buffered方式中,I/O管理器先创建一个与用户模式数据缓冲区大小相等的系统缓冲区。而你的驱动程序将使用这个系统缓冲区工作。I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据。 ”

是不是说复制数据的过程我是无法监测到的?因为我发现ioBuffer指向地址中的内容也不是我期望的呀,难道我用softice跟进去也不能得到传到驱动中的数据吗?还有就是我根据上面的方法传到设备的数据是不正确的,也就是说传过去的根本不是我之前确定的数据,因为我在设备方存储了这些数据并作了比较

可是根据ddk帮助里所说的,我用的方法没有错呀,而且我也用第二种方法试了(就是direct),问题是一样的,所以怀疑是UsbBuildInterruptOrBulkTransferRequest里面的ioBuffer里的数据根本就不是我要传输的!
kilroy_guo
驱动大牛
驱动大牛
  • 注册日期2002-10-29
  • 最后登录2005-11-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-04-10 11:38
METHOD_BUFFERED方式:
应用程序中的输入输出缓冲在驱动程序中用一个指针访问,即IRP中的AssociatedIrp.SystemBuffer指针,当应用程序的数据传入到驱动时,驱动先从AssociatedIrp.SystemBuffer中取得应用程序的数据,在irp完成之前,驱动将要传给应用程序的数据考入AssociatedIrp.SystemBuffer中并设置IoStatus.Information为要传给应用程序的数据长度即可。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT模式:
他们都以相同方式处理。仅有的不同是它们访问用户模式缓冲区时所需的访问权限;METHOD_IN_DIRECT需要读权限;METHOD_OUT_DIRECT既需要读权限又需要写权限,驱动程序以AssociatedIrp.SystemBuffer访问输入缓冲区,以MDL访问输出缓冲区,MDL缓冲地址可以用MmGetSystemAddressForMdl(Irp->MdlAddress)获得。

你的做法应该是对得阿,数据应该能够正确的传到kernel里面,你的ioBuffer指向的数据是什么?你用这个指针的时候有没有把他转换成PBULK_TRANSFER_CONTROL,也就是说你是怎么在设备方存储的?

我也不是大虾,我是菜鸟,上面这些话是我乱猜得,不对的地方请多多包涵
二姑家的猫想......
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-04-10 11:49
你比我厉害,虽然代码不是你写的,但是你还是看出了问题在那,我想问题出现在deviceiocontrol函数上,我用的是buffer方式。我想往设备写数据,所以应该把要写的数据地址和长度放在&bulkcontrol和sizeof(bulkcontrol)的位置上,但是我在这两个位置上放的是个端点信息,所以要传输的数据地址根本就没有传到驱动里!你觉得是不是这样呢,多谢你了!等问题解决了开帖子放分给你! :)
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-04-10 11:50
threadParam->pcIoBuffer指向的数据,是不是被别的thread修改了?
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-04-10 11:57
先谢谢斑竹,我觉得应该是没传过去吧,因为我想传的pipe信息(在bulkcontrol里)都传过去了,所以我要是把数据的地址放在它的位置上,一定也能传到驱动里,是我没想清楚函数的参数用法,害你们费神,真该打! :)
kilroy_guo
驱动大牛
驱动大牛
  • 注册日期2002-10-29
  • 最后登录2005-11-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-04-10 12:05
我是半路出家搞usb驱动,以前是搞vc做app的,最近一个月开始研究usb驱动,我主要是做iso传输的,最近碰到不少头疼的事,都是和PVOID指针乱用有关,我对这个有切肤之痛。交个朋友,共同学习,共同进步。

 :) :) :)
二姑家的猫想......
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2003-04-10 22:09
呵呵,我也是半路出家呀,而且是被逼的,没办法呀,说不想做一些轻松的活呀,我现在对固件、驱动和app都多少有点了解,大家多交流交流吧,我的qq:36180633,邮箱:jinghuiren@163.com
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2003-04-19 12:38
我对程序进行了修改,现在数据是传输正确了,可是ioctl函数的返回值总是0,我没觉得我的程序那里除了问题呀!
在应用程序中:
bResult = DeviceIoControl(hFile,//设备句柄
IOCTL_ISP1581_BULK_WRITE,//ctl code,用的是buffer方式
Buffer,//传输数据存储地址是个char型指针
Length,//传输数据长度(uint)
NULL,
0,
&nBytes,//实际传输的数据
NULL);


在驱动程序中:

PVOID ioBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG bufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
urb = ExAllocatePool(NonPagedPool,urbSize);

UsbBuildInterruptOrBulkTransferRequest(urb, //ptr to urb
(USHORT) urbSize, //size of urb
pipeHandle, //usbd pipe handle这个参数没问题
ioBuffer, //TransferBuffer
NULL, //mdl
bufferLength, //bufferlength
USBD_SHORT_TRANSFER_OK, //flags
NULL); //link

ntStatus = D12_CallUSBD(DeviceObject, urb);
//返回至是正确的
if (NT_SUCCESS(ntStatus))
{
Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
//上面这个值也是正确的
D12_KdPrint((\"Successfully transfered 0x%x bytes\\n\",Irp->IoStatus.Information));
}
Irp->IoStatus.Status = ntStatus;

ExFreePool(urb);
return ntStatus;//这个返回值也没问题

可是我的app中ioctl函数获得的返回值却总是0,我看了固件中的得到数据,和我主机发过去的一模一样!


[编辑 -  4/21/03 by  jinghuiren]

[编辑 -  4/23/03 by  jinghuiren]
BRANDER
驱动牛犊
驱动牛犊
  • 注册日期2002-09-29
  • 最后登录2009-05-01
  • 粉丝0
  • 关注0
  • 积分52分
  • 威望15点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2003-04-19 14:51
你对deviceiocontrol()函数理解错误。你开始用的方法是对的。写到设备的数据还是应该在OUTBUFFER中,INBUFFER中的东西是与操作有关的,是给驱动部分的信息。
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2003-04-23 13:53
首先感谢楼上老兄的回复,我由仔细看了该函数的相关描述,觉得系到设备的数据应该放在deviceiocontrol的inputbuffer中,关于函数返回值总是0我觉得是不是我没有提供outputbuffer的原因呀。真是郁闷呀 :(
游客

返回顶部