⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rwr.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 2 页
字号:
  if (pRWContext) {
    DevIoDecrement(pRWContext->pDevExt);
    _FreeRWContext(pRWContext);
  }
  return ntS;
}


/*********************************************************************
*
*       DispatchRW
*
* Function description
*   Execute read/write IRPs.
*/
static NTSTATUS _DispatchRW(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, BOOLEAN Read) {
  URB                    * Urb;
  ULONG                    totalLength;
  NTSTATUS                 ntS;
  ULONG_PTR                virtualAddress;
  PFILE_OBJECT             fileObject;
  DEVICE_EXTENSION       * pDevExt;
  IO_STACK_LOCATION      * irpStack;
  USB_RW_CONTEXT         * pRWContext;
  USBD_PIPE_INFORMATION  * pipeInformation;
  ULONG                  stageLength;

  Urb = NULL;
  pRWContext = NULL;
  totalLength = 0;
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  fileObject = irpStack->FileObject;
  pDevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);

  //
  // Assert that device is working
  //
  if (pDevExt->DeviceState != Working) {
    DPRINT(("<usb> error: invalid device state\n"));
    ntS = STATUS_INVALID_DEVICE_STATE;
    goto OnError;
  }
  //
  // More assertions
  //
  if (!fileObject) {
    DPRINT(("<usb> File Object invalid\n"));
    ntS = STATUS_INVALID_HANDLE;
    goto OnError;
  }
  if (!fileObject->FsContext) {
    DPRINT(("<usb> error: invalid Fscontext\n"));
    ntS = STATUS_INVALID_HANDLE;
    goto OnError;
  }
  pipeInformation = fileObject->FsContext;
  if (pipeInformation->PipeType != UsbdPipeTypeBulk) {
    DPRINT(("<usb> error: pipe not BULK type\n"));
    ntS = STATUS_INVALID_HANDLE;
    goto OnError;
  }
  //
  // Get TotalLenght ... What happens if (Irp->MdlAddress == NULL) ??? Error handling ??? (RS)
  //
  if (Irp->MdlAddress) {
    totalLength = MmGetMdlByteCount(Irp->MdlAddress);
  }
  //
  // Assert transfer size is in valid range
  //
  if (totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {
    DPRINT(("<usb> error: transfer size excesss limit\n"));
    ntS = STATUS_INVALID_PARAMETER;
    goto OnError;
  }
  if (totalLength == 0) {
    DPRINT(("<usb> transfer is 0 bytes\n"));
    ntS = STATUS_SUCCESS;
    goto OnError;
  }

  //
  // In read mode, check if there is enough data in our intermediate buffer
  // If so, then we are done.
  //
  if (Read) {
    if (_CopyFromBuffer(Irp, pDevExt, (void*)virtualAddress, totalLength)) {
      DPRINT(("<usb> Request satisfied from buffer\n"));
      Irp->IoStatus.Information = totalLength;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      Irp->IoStatus.Status = STATUS_SUCCESS;
      return STATUS_SUCCESS;
    }
  }



  //
  // In write mode, output debug info
  //
  #if DBG
  if (!Read) {
    int i;
    int iMax;
    char ac[2000];
    char acHex[] = "0123456789ABCDEF";
    char * s = ac;
    char * pData = (char*)virtualAddress;
    iMax = (totalLength < 100) ? totalLength : 100;
    for (i = 0; i < iMax; i++) {
      unsigned char Data = *(i + pData);
      *s++ = ' ';
      *s++ = acHex[Data >> 4];
      *s++ = acHex[Data & 15];
    }
    *s = '\0';
    DPRINT(("<usb> Writing (%s)\n", ac));
  }
  #endif

  //
  // Allocate RWContext
  //
  pRWContext = (USB_RW_CONTEXT *) _ExAllocatePoolZeroed(NonPagedPool, sizeof(USB_RW_CONTEXT));
  if (pRWContext == NULL) {
    DPRINT(("<usb> error: allocating USB_RW_CONTEXT\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
    goto OnError;
  }
  //
  // Allocate URB
  //
  Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
  if (Urb == NULL) {
    DPRINT(("<usb> error: allocating urb\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
    goto OnError;
  }
  pRWContext->Urb                  = Urb;


  /* Read uses buffered mode, write uses MDL */
  if (Read) {
    UsbBuildInterruptOrBulkTransferRequest(Urb,
                                           sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                           pipeInformation->PipeHandle,
                                           &pDevExt->acBuffer[pDevExt->NumBytesInBuffer],
                                           NULL,
                                           BULKUSB_MAX_TRANSFER_SIZE_READ,
                                           USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN,
                                           NULL);
  } else {
    //
    // map the portion of user-buffer described by an mdl to another mdl
    //
    // Allocate MDL
    //
    MDL * Mdl;
    stageLength = (totalLength > BULKUSB_MAX_TRANSFER_SIZE_WRITE ? BULKUSB_MAX_TRANSFER_SIZE_WRITE : totalLength);
    Mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
    if (Mdl == NULL) {
      DPRINT(("<usb> allocating mdl\n"));
      ntS = STATUS_INSUFFICIENT_RESOURCES;
      goto OnError;
    }
    IoBuildPartialMdl(Irp->MdlAddress, Mdl, (PVOID) virtualAddress, stageLength);
    pRWContext->Mdl                  = Mdl;

    UsbBuildInterruptOrBulkTransferRequest(Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                           pipeInformation->PipeHandle, NULL, Mdl, stageLength,
                                           /*USBD_SHORT_TRANSFER_OK | */USBD_TRANSFER_DIRECTION_OUT, NULL);
  }

  // set USB_RW_CONTEXT parameters.
  pRWContext->NumRemBytes          = totalLength;
  pRWContext->NumBytesTransferred  = 0;
  pRWContext->VirtualAddress       = virtualAddress;
  pRWContext->pDevExt              = pDevExt;
  pRWContext->PipeHandle           = pipeInformation->PipeHandle;
  // always mark IRP pending for safety purpose :)
  IoMarkIrpPending(Irp);
  DevIoIncrement(pDevExt);

  // use the original read/write irp as an internal device control irp
  if (Read) {
    ntS = _CallUSBD(Irp, pRWContext, _OnReadCompletion);
  } else {
    ntS = _CallUSBD(Irp, pRWContext, _OnWriteCompletion);
  }

  if (!NT_SUCCESS(ntS)) {
    DPRINT(("<usb> error: DispatchReadWrite::IoCallDriver %x\n", ntS));
    // if the device was yanked out, then the pipeInformation field is invalid.
    // similarly if the request was cancelled, then we need not invoked reset pipe/device.
    if ((ntS != STATUS_CANCELLED) && (ntS != STATUS_DEVICE_NOT_CONNECTED)) {
      ntS = ResetPipe(DeviceObject, pipeInformation);
      if(!NT_SUCCESS(ntS)) {
          DPRINT(("<usb> error: DispatchReadWrite::ResetPipe %x (we now reset device)\n", ntS));
          ntS = ResetDevice(DeviceObject);
      }
    } else {
      DPRINT(("<usb> error: operation canceled or device not connected\n"));
    }
  }
  // we return STATUS_PENDING and not the status returned by the lower layer.
  return STATUS_PENDING;

  //
  // Error handling
  //
OnError:
  _FreeRWContext(pRWContext);
  return(CompleteRequest(Irp, ntS, 0));
}

/*********************************************************************
*
*       DispatchWrite
*
* Function description
*   Execute write IRPs.  (Callback for IRP_MJ_WRITE)
*/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  DPRINT(("<usb> IRP_MJ_WRITE\n"));
  return _DispatchRW(DeviceObject, Irp, 0);
}

/*********************************************************************
*
*       DispatchRead
*
* Function description
*   Execute read IRPs.  (Callback for IRP_MJ_READ)
*/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  DPRINT(("<usb> IRP_MJ_READ\n"));
  return _DispatchRW(DeviceObject, Irp, 1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -