阅读:2121回复:5
很急:IoCallDriver返回STATUS_PENDING,KeWaitForSingleObject永远不返回,怎么解决?(详细见内)
在获得配置描述表时,调用IoCallDriver返回STATUS_PENDING,KeWaitForSingleObject永远不返回,直到设备拔掉。
有没有办法使其返回? 如果在KeWaitForSingleObject设上timeout参数,是否在超时返回后IoCallDriver传递下去的irp依旧没完成?这样可以吗? 我的需求是程序能正常的退出,不要总等在那里。请大虾给予点拨。 |
|
沙发#
发布于:2004-07-16 09:37
Yes. completion function is called by IO manager after the IRP is done in lower level driver.
Did you fix your problem? I have sample code in hand. So here is a improved CallUSBDI() NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT pev) { if (Irp->PendingReturned) KeSetEvent(pev, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS CallUSBDI( IN PCNSECUSB_DEVICE_EXTENSION dx, IN PVOID UrbEtc, IN ULONG IoControlCode,IN ULONG Arg2) { IO_STATUS_BLOCK IoStatus; KEVENT event; // Initialise IRP completion event KeInitializeEvent(&event, NotificationEvent, FALSE); // Build Internal IOCTL IRP PIRP Irp = IoBuildDeviceIoControlRequest(IoControlCode, dx->NextStackDevice,NULL, 0,NULL, 0,TRUE, &event, &IoStatus); // Get IRP stack location for next driver down (already set up) PIO_STACK_LOCATION NextIrpStack = IoGetNextIrpStackLocation(Irp); // Store pointer to the URB etc NextIrpStack->Parameters.Others.Argument1 = UrbEtc; NextIrpStack->Parameters.Others.Argument2 = (PVOID)Arg2; IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,(PVOID) &event, TRUE, TRUE, TRUE); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This function is the key // Call the driver and wait for completion if necessary NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp); if (status == STATUS_PENDING) { status = KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); status = IoStatus.Status; } IoCompleteRequest(irp, IO_NO_INCREMENT); ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is another one you missed return status; } [编辑 - 7/16/04 by windrv] [编辑 - 7/16/04 by windrv] |
|
板凳#
发布于:2004-07-15 16:31
据我理解, Completion函数应是在底层的驱动完成irp后才会调用的.
不知道是不是? |
|
地板#
发布于:2004-07-15 14:29
CallUSBDI函数有问题. 在IoCallDriver之前,应该设置一个Completion函数,在这个函数调用KeSetEvent().要不然,KeWaitForSingleObject()永远等不到那个event.Walter Oney特意在书中指出了这个问题,你可以参考他的书或看看DDK的例子.
[编辑 - 7/15/04 by windrv] |
|
地下室#
发布于:2004-07-15 14:22
有一批硬件,是有一部分出错.
NTSTATUS CallUSBDI( IN PCNSECUSB_DEVICE_EXTENSION dx, IN PVOID UrbEtc, IN ULONG IoControlCode/*=IOCTL_INTERNAL_USB_SUBMIT_URB*/, IN ULONG Arg2/*=0*/) { IO_STATUS_BLOCK IoStatus; KEVENT event; // Initialise IRP completion event // DebugPrintMsg("Start Init IRP"); KeInitializeEvent(&event, NotificationEvent, FALSE); // Build Internal IOCTL IRP // DebugPrintMsg("start build IRP"); PIRP Irp = IoBuildDeviceIoControlRequest( IoControlCode, dx->NextStackDevice, NULL, 0, // Input buffer NULL, 0, // Output buffer TRUE, &event, &IoStatus); // Get IRP stack location for next driver down (already set up) // DebugPrintMsg("start Get IRP location"); PIO_STACK_LOCATION NextIrpStack = IoGetNextIrpStackLocation(Irp); // Store pointer to the URB etc NextIrpStack->Parameters.Others.Argument1 = UrbEtc; NextIrpStack->Parameters.Others.Argument2 = (PVOID)Arg2; // Call the driver and wait for completion if necessary // DebugPrintMsg("start call the driver"); NTSTATUS status = IoCallDriver( dx->NextStackDevice, Irp); if (status == STATUS_PENDING) { // DebugPrintMsg("CallUSBDI: waiting for URB completion"); /* ULONGLONG TimeOut100nSec; PLARGE_INTEGER pTimeOut; // Calculate wait as 100ns intervals. Negative is relative TimeOut100nSec = dx->UsbTimeout; TimeOut100nSec *= -10000; // convert units pTimeOut = PLARGE_INTEGER(&TimeOut100nSec); */ // DebugPrintMsg("start waitforsingle"); status = KeWaitForSingleObject( ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ &event, Suspended, KernelMode, FALSE, NULL); status = IoStatus.Status; } // DebugPrintMsg("return "); // return IRP completion status // DebugPrint("CallUSBDI returned %x",status); return status; } NTSTATUS UsbGetConfigurationDescriptors( IN PCNSECUSB_DEVICE_EXTENSION dx, OUT PUSB_CONFIGURATION_DESCRIPTOR& descriptors, IN UCHAR ConfigIndex, OUT ULONG& DescriptorsSize) { // Allocate memory for URB USHORT UrbSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); PURB urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize); if( urb==NULL) { DebugPrintMsg("No URB memory"); return STATUS_INSUFFICIENT_RESOURCES; } // Allocate memory just for basic config descriptor DescriptorsSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); descriptors = (PUSB_CONFIGURATION_DESCRIPTOR)ExAllocatePool(NonPagedPool, DescriptorsSize+16); if( descriptors==NULL) { DebugPrintMsg("No initial descriptor memory"); return STATUS_INSUFFICIENT_RESOURCES; } // Build the Get Descriptor URB UsbBuildGetDescriptorRequest( urb, UrbSize, USB_CONFIGURATION_DESCRIPTOR_TYPE, ConfigIndex, 0, descriptors, NULL, DescriptorsSize, NULL); // Call the USB driver DebugPrintMsg("Getting basic configuration descriptor"); NTSTATUS status = CallUSBDI( dx, urb); // Check statuses if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status)) { DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status); status = STATUS_UNSUCCESSFUL; goto fail; } DebugPrint("Got basic config descr. MaxPower %d units of 2mA", descriptors->MaxPower); // Reallocate memory for config descriptor and associated descriptors DescriptorsSize = descriptors->wTotalLength; ExFreePool(descriptors); descriptors = (PUSB_CONFIGURATION_DESCRIPTOR)ExAllocatePool(NonPagedPool, DescriptorsSize+16); if( descriptors==NULL) { DebugPrintMsg("No full descriptors memory"); return STATUS_INSUFFICIENT_RESOURCES; } // Build the Get Descriptor URB UsbBuildGetDescriptorRequest( urb, UrbSize, USB_CONFIGURATION_DESCRIPTOR_TYPE, ConfigIndex, 0, descriptors, NULL, DescriptorsSize, NULL); // Call the USB driver DebugPrintMsg("Getting full configuration descriptors"); status = CallUSBDI( dx, urb);//调用处 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .... |
|
5楼#
发布于:2004-07-15 13:56
把你调用IoCallDriver的那段程序以及Completion程序贴上来看看.按Walter Oney所说,如果 IoCallDriver之前的设置不对,KeWaitForSingleObject等不到那个Event.
|
|