zengwn
驱动牛犊
驱动牛犊
  • 注册日期2001-05-26
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望59点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1633回复:6

[请教]Windows下USB BULK 工作机制

楼主#
更多 发布于:2008-11-10 20:26
Windows 是如何检测到USB口有数据从而生成Dispatch IRP?
现在正在做USB转串口驱动,是采用DS生成框架后改的,现在我的驱动程序可以发数据,但收不了数据,怎么样才能知道USB口有数据到达?

最新喜欢:

julyjackiejulyja...
zengwn
驱动牛犊
驱动牛犊
  • 注册日期2001-05-26
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望59点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-11-14 12:57
???
gutian98
禁止发言
禁止发言
  • 注册日期2003-01-12
  • 最后登录2016-12-11
  • 粉丝4
  • 关注2
  • 积分760分
  • 威望8026点
  • 贡献值1点
  • 好评度364点
  • 原创分0分
  • 专家分21分
  • 金点子奖
  • 社区居民
板凳#
发布于:2008-11-14 13:44
用户被禁言,该主题自动屏蔽!
zengwn
驱动牛犊
驱动牛犊
  • 注册日期2001-05-26
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望59点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-11-14 18:41
我有几个疑问:
1. IRP_MJ_READ, IRP_MJ_WRITE等例程应该是操作系统或类驱动程序来调用的了,现在我的IRP_MJ_WRITE例程会被调用,但IRP_MJ_READ,没有反应。这些例程是如何被调用的?
2. 如果自己去创建IRP来接收数据,Irp->MdlAddress怎么得到?

我现在是在WriteDispatch后去创建IRP,自己调用ReadDispatch来收数据,但程序运行到IoCallDriver就蓝屏。下面是我的部分代码,请帮忙分析一下,谢谢!

NTSTATUS USBSerialWriteDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
  PIRP                           readIrp;
  KEVENT                         readEvent;
  PMDL                           readMdl;
  IO_STATUS_BLOCK                ioStatus;
  PUSBSERIAL_DEVICE_EXTENSION    eviceExtension;
  NTSTATUS                       status;
  PUCHAR                         readBuffer;

  USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"=> IRP 0x%p", Irp);

  deviceExtension = (PUSBSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  status = USBSerialCheckIoLock(&deviceExtension->IoLock, Irp);
  if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
      USBSerialDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"<= IRP 0x%p STATUS 0x%08X", Irp, status);

        return status;
    }
    
    ;;;
    
    status = USBSerialBulkOutIo(
          DeviceObject,
          Irp,
          &deviceExtension->InterfaceInformation->Pipes[0]
          );

  if (NT_SUCCESS(status))
  {
    KeInitializeEvent(&readEvent, NotificationEvent, FALSE);

    readIrp = IoBuildDeviceIoControlRequest(
      IRP_MJ_READ,
      deviceExtension->LowerDeviceObject,
      NULL,
      0,
      NULL/ *OutputBuffer* /,
      0/ *OutputBufferLength* /,
      TRUE,
      &readEvent,
      &ioStatus
      );
    if (readIrp != NULL)
    {
      readBuffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, USBSERIAL_POOL_TAG);
      if (writeBuffer != NULL)
      {
        readMdl = IoAllocateMdl(writeBuffer, sizeof(writeBuffer), FALSE, FALSE, NULL);  // 可以这样吗?
        if (readMdl != NULL)
        {
          readIrp->MdlAddress = readMdl;  // ???
          USBSerialReadDispatch(DeviceObject,readIrp);
      }

      //IoFreeIrp(readIrp);
      ExFreePool(writeBuffer);
    }
  }
  
    USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"<= IRP 0x%p STATUS 0x%08X", Irp, status);

    return status;
}

NTSTATUS USBSerialReadDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
  PUSBSERIAL_DEVICE_EXTENSION     deviceExtension;
  NTSTATUS                        status;
  ULONG                           readLength;
  PUCHAR                          readBuffer;

  USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"=> IRP 0x%p", Irp);

  deviceExtension = (PUSBSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  status = USBSerialCheckIoLock(&deviceExtension->IoLock, Irp);
  if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
        USBSerialDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"<= IRP 0x%p STATUS 0x%08X", Irp, status);
        return status;
    }

    ...
    
  status = USBSerialBulkInIo(
          DeviceObject,
          Irp,
          &deviceExtension->InterfaceInformation->Pipes[1]
          );
          
    USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"<= IRP 0x%p STATUS 0x%08X", Irp, status);

    return status;
}

NTSTATUS USBSerialBulkInIo(
  IN  PDEVICE_OBJECT                DeviceObject,
    IN  PIRP                          Irp,
  IN  PUSBD_PIPE_INFORMATION        PipeInformation
    )
{
    PUSBSERIAL_DEVICE_EXTENSION DeviceExtension;
    PUSBSERIAL_IO_CONTEXT       ioContext;
    NTSTATUS                    status;
    PUCHAR                      virtualAddress;
    ULONG                       totalLength;
    ULONG                       transferLength;
    PMDL                        mdl;
    PURB                        urb;
    PIO_STACK_LOCATION          irpStack;

    USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"=> IRP 0x%p", Irp);

    DeviceExtension = (PUSBSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // we will use do{}while(FALSE); structure
    // for resources cleanup
    status = STATUS_SUCCESS;
    ioContext = NULL;
    mdl = NULL;

    do
    {
        Irp->IoStatus.Information = 0;

        // allocate io context to pass to completion routine
        ioContext = (PUSBSERIAL_IO_CONTEXT)ExAllocatePoolWithTag(
                                                    NonPagedPool,
                                                    sizeof(USBSERIAL_IO_CONTEXT),
                                                    USBSERIAL_POOL_TAG
                                                    );

        ...

        IoSetCompletionRoutine(
            Irp,
            USBSerialBulkInIoCompletionRoutine,
            ioContext,
            TRUE,
            TRUE,
            TRUE
            );

      IoMarkIrpPending(Irp);
      status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);  // 运行到这里就蓝屏了
      }

    ...
    }
    while (FALSE);

    if (status != STATUS_PENDING)
    {
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        USBSerialDecrementIoCount(&DeviceExtension->IoLock);
    }

    USBSerialDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"<= IRP 0x%p STATUS 0x%08X", Irp, status);

    return status;
}
byteman
驱动牛犊
驱动牛犊
  • 注册日期2005-12-15
  • 最后登录2009-07-12
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望7点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-11-16 12:34
1.当应用程序调用ReadFile 时候就会发出IRP_MJ_READ包,也就会触发驱动程序的ReadDisptach,当调用WriteFile函数的时候会发出IRP_MJ_WRITE包,所以这两个例程都是由应用程序调用api函数的时候触发的。
2.你的程序的这种做法应该是错误的,建议你看看DDK自带的bulk例程

呵呵,我也是才学,不正确的地方还请各位大虾指正
zengwn
驱动牛犊
驱动牛犊
  • 注册日期2001-05-26
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望59点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-11-18 20:09
Irp->MdlAddress如何得到?
gutian98
禁止发言
禁止发言
  • 注册日期2003-01-12
  • 最后登录2016-12-11
  • 粉丝4
  • 关注2
  • 积分760分
  • 威望8026点
  • 贡献值1点
  • 好评度364点
  • 原创分0分
  • 专家分21分
  • 金点子奖
  • 社区居民
6楼#
发布于:2008-11-21 14:43
用户被禁言,该主题自动屏蔽!
游客

返回顶部