shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1730回复:3

为什么超时不正确?

楼主#
更多 发布于:2002-06-12 10:44
请看下面的代码:

//***********************************************************************
//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秒的代码,当不知为什么出现蓝屏现象,做过超时的朋友请出手指点啊!

最新喜欢:

highwhighw
shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-06-12 10:49
对了,蓝屏错误代码:DRIVER_IRQL_NOT_LESS_OR_EQUAL
意思大概是IRQL 级别不对。
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于: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);





Tom_lyd
shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于: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 的方法,但在实际中去出现蓝屏的现象!
游客

返回顶部