阅读:1730回复:3
为什么超时不正确?
请看下面的代码:
//*********************************************************************** //function:Evk_CallUSBD //parameter: fdo ----- next lower function device object // urb ----- usb request block,already formatted //purpose: the following one routine is to forward a urb to usb bus driver // The client device driver passes USB request block (URB) structures // to the class driver as a parameter in an IRP with Irp->MajorFunction // set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location // Parameters.DeviceIoControl.IoControlCode field set to // IOCTL_INTERNAL_USB_SUBMIT_URB. // //return: if the operation is successful,return STATUS_SUCCESS // //revision: date,2002,6,10. by shenlei // purpose: 增加超时的处理: 超时情况是经常出现的,主要源于 // 设备端对主机提出的要求没有响应。当设备由于不可预料原因 没有响应 时, // 就无法正常处理 // // Note that we create our own IRP here and use it to send the request to // the USB software subsystem. This means that this routine is essentially // independent of the IRP that caused this driver to be called in the first // place. The IRP for this transfer is created, used, and then destroyed // in this routine. //******************************************************************** NTSTATUS Evk_CallUSBD(IN PDEVICE_OBJECT fdo, IN PURB urb) { NTSTATUS ntStatus,status=STATUS_SUCCESS; PDEVICE_EXTENSION pdx; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION nextStack; KEVENT event; Evk_KdPrint((\"enter Evk_CallUSBD()\\n\")); pdx=fdo->DeviceExtension; //issue a synchronous request(同步请求) KeInitializeEvent(&event,NotificationEvent,FALSE); //build irp which will be send to bus driver irp=IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE, //internal &event, &ioStatus); //newly added for timeout IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)HUSBDCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE); //prepare for calling the usb bus driver nextStack=IoGetNextIrpStackLocation(irp); ASSERT(nextStack!=NULL); nextStack->Parameters.Others.Argument1=urb; Evk_KdPrint((\"Calling USB driver stack\")); //call the USB driver stack to perform the operation.if the return value is //PENDING ,wait for request to complete ntStatus=IoCallDriver(pdx->LowerDeviceObject,irp); Evk_KdPrint ((\"return from IoCallDriver USBD %x\\n\", ntStatus)); //STATUS_PENDING means the lower driver have not finished processing the IRP, //yet.we must wait. if(ntStatus==STATUS_PENDING) { LARGE_INTEGER timeout5second; timeout5second.QuadPart=-5*10000000; //5秒 Evk_KdPrint ((\"Wait for single object\\n\")); status=KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); if(status==STATUS_TIMEOUT) { IoCancelIrp(irp); KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"Wait for single object, returned %x\\n\", status)); } else { ioStatus.Status=ntStatus; //added here //KeClearEvent(&event); //IoCompleteRequest(irp,IO_NO_INCREMENT); //KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"URB status = %x status = %x irp status %x\\n\", urb->UrbHeader.Status, status, ioStatus.Status)); //USBD maps the error code for us,USBD uses error codes in its URB structure, //that are more insightful into USB behavior.in order to match the //NT status code,USBD maps its error codes into more general NT // error categories so higher level drivers can decipher the error codes // based on standard NT error code definitions. // ntStatus=ioStatus.Status; // // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the // URB status in the device extension. After a failure, another IOCTL, // IOCTL_EVK_GET_LAST_ERROR can be used to retrieve the URB status // for the most recently failed URB. Of course, this status gets // overwritten by subsequent failures, but it\'s better than nothing. // if(NT_SUCCESS(ntStatus)) { if(!USBD_SUCCESS(urb->UrbHeader.Status)) ntStatus=STATUS_UNSUCCESSFUL; } Evk_KdPrint((\"exit Evk_CallUSBD (%x)\\n\", ntStatus)); return ntStatus; } //************************************************************************** //function : HUSBDCompletionRoutine //parameter: //************************************************************************** NTSTATUS HUSBDCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PKEVENT pEvent = (PKEVENT)Context; KeSetEvent(pEvent, 0, TRUE); return STATUS_MORE_PROCESSING_REQUIRED; } 在上面的代码中,涵数用以递交一个URB 到usb bus driver 上面加入了超时5秒的代码,当不知为什么出现蓝屏现象,做过超时的朋友请出手指点啊! |
|
最新喜欢:highw |
沙发#
发布于:2002-06-12 10:49
对了,蓝屏错误代码:DRIVER_IRQL_NOT_LESS_OR_EQUAL
意思大概是IRQL 级别不对。 |
|
板凳#
发布于:2002-06-12 11:26
你的代码本身都有问题,如下:
NTSTATUS Evk_CallUSBD(IN PDEVICE_OBJECT fdo, IN PURB urb) { NTSTATUS ntStatus,status=STATUS_SUCCESS; PDEVICE_EXTENSION pdx; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION nextStack; KEVENT event; Evk_KdPrint((\"enter Evk_CallUSBD()\\n\")); pdx=fdo->DeviceExtension; //issue a synchronous request(同步请求) KeInitializeEvent(&event,NotificationEvent,FALSE); //build irp which will be send to bus driver irp=IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE, //internal &event, &ioStatus); //newly added for timeout IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)HUSBDCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE); //prepare for calling the usb bus driver nextStack=IoGetNextIrpStackLocation(irp); ASSERT(nextStack!=NULL); nextStack->Parameters.Others.Argument1=urb; Evk_KdPrint((\"Calling USB driver stack\")); //call the USB driver stack to perform the operation.if the return value is //PENDING ,wait for request to complete ntStatus=IoCallDriver(pdx->LowerDeviceObject,irp); Evk_KdPrint ((\"return from IoCallDriver USBD %x\\n\", ntStatus)); //STATUS_PENDING means the lower driver have not finished processing the IRP, //yet.we must wait. if(ntStatus==STATUS_PENDING) { LARGE_INTEGER timeout5second; timeout5second.QuadPart=-5*10000000; //5秒 Evk_KdPrint ((\"Wait for single object\\n\")); status=KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); if(status==STATUS_TIMEOUT) { IoCancelIrp(irp); KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"Wait for single object, returned %x\\n\", status)); } else { ioStatus.Status=ntStatus; //added here //KeClearEvent(&event); //IoCompleteRequest(irp,IO_NO_INCREMENT); //KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"URB status = %x status = %x irp status %x\\n\", urb->UrbHeader.Status, status, ioStatus.Status)); //USBD maps the error code for us,USBD uses error codes in its URB structure, //that are more insightful into USB behavior.in order to match the //NT status code,USBD maps its error codes into more general NT // error categories so higher level drivers can decipher the error codes // based on standard NT error code definitions. // ntStatus=ioStatus.Status; // // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the // URB status in the device extension. After a failure, another IOCTL, // IOCTL_EVK_GET_LAST_ERROR can be used to retrieve the URB status // for the most recently failed URB. Of course, this status gets // overwritten by subsequent failures, but it\'s better than nothing. // if(NT_SUCCESS(ntStatus)) { if(!USBD_SUCCESS(urb->UrbHeader.Status)) ntStatus=STATUS_UNSUCCESSFUL; } Evk_KdPrint((\"exit Evk_CallUSBD (%x)\\n\", ntStatus)); return ntStatus; } //************************************************************************** //function : HUSBDCompletionRoutine //parameter: //************************************************************************** NTSTATUS HUSBDCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PKEVENT pEvent = (PKEVENT)Context; KeSetEvent(pEvent, 0, TRUE); return STATUS_MORE_PROCESSING_REQUIRED; } 1.黑体部分应该放在IoCallDriver调用之后吧 2.既然设了超时,超时参数怎么设了NULL? status=KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); status=KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, &timeout5second); |
|
|
地板#
发布于:2002-06-12 14:30
请看下面的代码:
//*********************************************************************** //function:Evk_CallUSBD //parameter: fdo ----- next lower function device object // urb ----- usb request block,already formatted //purpose: the following one routine is to forward a urb to usb bus driver // The client device driver passes USB request block (URB) structures // to the class driver as a parameter in an IRP with Irp->MajorFunction // set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location // Parameters.DeviceIoControl.IoControlCode field set to // IOCTL_INTERNAL_USB_SUBMIT_URB. // //return: if the operation is successful,return STATUS_SUCCESS // //revision: date,2002,6,10. by shenlei // purpose: 增加超时的处理: 超时情况是经常出现的,主要源于 // 设备端对主机提出的要求没有响应。当设备由于不可预料原因 没有响应 时, // 就无法正常处理 // // Note that we create our own IRP here and use it to send the request to // the USB software subsystem. This means that this routine is essentially // independent of the IRP that caused this driver to be called in the first // place. The IRP for this transfer is created, used, and then destroyed // in this routine. //******************************************************************** NTSTATUS Evk_CallUSBD(IN PDEVICE_OBJECT fdo, IN PURB urb) { NTSTATUS ntStatus,status=STATUS_SUCCESS; PDEVICE_EXTENSION pdx; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION nextStack; KEVENT event; Evk_KdPrint((\"enter Evk_CallUSBD()\\n\")); pdx=fdo->DeviceExtension; //issue a synchronous request(同步请求) KeInitializeEvent(&event,NotificationEvent,FALSE); //build irp which will be send to bus driver irp=IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE, //internal &event, &ioStatus); //newly added for timeout IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)HUSBDCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE); //prepare for calling the usb bus driver nextStack=IoGetNextIrpStackLocation(irp); ASSERT(nextStack!=NULL); nextStack->Parameters.Others.Argument1=urb; Evk_KdPrint((\"Calling USB driver stack\")); //call the USB driver stack to perform the operation.if the return value is //PENDING ,wait for request to complete ntStatus=IoCallDriver(pdx->LowerDeviceObject,irp); Evk_KdPrint ((\"return from IoCallDriver USBD %x\\n\", ntStatus)); //STATUS_PENDING means the lower driver have not finished processing the IRP, //yet.we must wait. if(ntStatus==STATUS_PENDING) { LARGE_INTEGER timeout5second; timeout5second.QuadPart=-5*10000000; //5秒 Evk_KdPrint ((\"Wait for single object\\n\")); status=KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, &timeout5second); if(status==STATUS_TIMEOUT) { IoCancelIrp(irp); KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"Wait for single object, returned %x\\n\", status)); } else { ioStatus.Status=ntStatus; //added here KeClearEvent(&event); IoCompleteRequest(irp,IO_NO_INCREMENT); KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); } Evk_KdPrint ((\"URB status = %x status = %x irp status %x\\n\", urb->UrbHeader.Status, status, ioStatus.Status)); //USBD maps the error code for us,USBD uses error codes in its URB structure, //that are more insightful into USB behavior.in order to match the //NT status code,USBD maps its error codes into more general NT // error categories so higher level drivers can decipher the error codes // based on standard NT error code definitions. // ntStatus=ioStatus.Status; // // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the // URB status in the device extension. After a failure, another IOCTL, // IOCTL_EVK_GET_LAST_ERROR can be used to retrieve the URB status // for the most recently failed URB. Of course, this status gets // overwritten by subsequent failures, but it\'s better than nothing. // if(NT_SUCCESS(ntStatus)) { if(!USBD_SUCCESS(urb->UrbHeader.Status)) ntStatus=STATUS_UNSUCCESSFUL; } Evk_KdPrint((\"exit Evk_CallUSBD (%x)\\n\", ntStatus)); return ntStatus; } //************************************************************************** //function : HUSBDCompletionRoutine //parameter: //************************************************************************** NTSTATUS HUSBDCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PKEVENT pEvent = (PKEVENT)Context; KeSetEvent(pEvent, 0, TRUE); return STATUS_MORE_PROCESSING_REQUIRED; } 有没有人在USB中处理过超时的问题? 我觉得有必要啊,但不知怎么办? 上面的代码基本上是Walter Oney 的方法,但在实际中去出现蓝屏的现象! |
|