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

📄 rwr.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**********************************************************************
*                          Micrium, Inc.
*                      949 Crestview Circle
*                     Weston,  FL 33327-1848
*
*                           uC/USB-Bulk
*
*             (c) Copyright 2003 - 2004, Micrium, Inc.
*                      All rights reserved.
*
***********************************************************************

----------------------------------------------------------------------
File        : rwr.c
Purpose     : Part of the USB bulk driver
---------------------------END-OF-HEADER------------------------------
*/


#include "Main.h"


typedef struct {
    URB              * Urb;                  // ptr to URB
    MDL              * Mdl;                  // ptr to MDL buffer
    int                NumRemBytes;          // Number of remaining bytes to transfer
    ULONG              NumBytesTransferred;  // cumulate bytes transferred        
    ULONG_PTR          VirtualAddress; // va for next segment of xfer.
    DEVICE_EXTENSION * pDevExt;
    USBD_PIPE_HANDLE  PipeHandle;
} USB_RW_CONTEXT;


static NTSTATUS _OnRWCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
BOOLEAN MmIsAddressValid(IN PVOID VirtualAddress);   // "Forgotten" in header file by MS



/*********************************************************************
*
*       _FreeRWContext
*
* Function description
*/
void _FreeRWContext(USB_RW_CONTEXT * pRWContext) {
  if (pRWContext) {
    if (pRWContext->Urb) {
      ExFreePool    (pRWContext->Urb);
    }
    if (pRWContext->Mdl) {
      IoFreeMdl     (pRWContext->Mdl);
    }
    ExFreePool(pRWContext);
  }
}

/*********************************************************************
*
*       _ExAllocatePoolZeroed
*
* Function description
*/
static void * _ExAllocatePoolZeroed(IN POOL_TYPE  PoolType, IN SIZE_T  NumBytes) {
  void * p;
  p = ExAllocatePool(PoolType, NumBytes);
  if (p) {
    RtlZeroMemory(p, NumBytes);
  }
  return p;
}

/*********************************************************************
*
*       _CallUSBD
*
* Function description
*/
static NTSTATUS _CallUSBD(IRP * pIrp, USB_RW_CONTEXT * pRWContext, PIO_COMPLETION_ROUTINE pOnCompletion) {
  IO_STACK_LOCATION     * pNextStack;

  pNextStack = IoGetNextIrpStackLocation(pIrp);
  pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  pNextStack->Parameters.Others.Argument1 = pRWContext->Urb;
  pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  IoSetCompletionRoutine(pIrp, pOnCompletion, pRWContext, TRUE, TRUE, TRUE);
  return IoCallDriver(pRWContext->pDevExt->TopOfStackDeviceObject, pIrp);
}

/*********************************************************************
*
*       _CopyFromBuffer
*
* Function description
*   TBD
* Return value
*   1 if request has been satisfied from buffer
*/
static int _CopyFromBuffer(IN IRP * pIrp, DEVICE_EXTENSION * pDevExt, void * pDest, int NumBytesReq) {
  int r = 0;
  KIRQL oldIrql;
  KeAcquireSpinLock(&pDevExt->BufferLock, &oldIrql);
  if (NumBytesReq <= pDevExt->NumBytesInBuffer) {
    if (MmIsAddressValid(pDest)) {
      memcpy(pDest, pDevExt->acBuffer, NumBytesReq);
      pDevExt->NumBytesInBuffer -= NumBytesReq;
      memmove(&pDevExt->acBuffer[0], &pDevExt->acBuffer[NumBytesReq], pDevExt->NumBytesInBuffer);
      r = 1;                                  // Success !
    } else {
      DPRINT(("<usb> ERROR: MmIsAddressValid failed ! (SysBuffer : %x)\n", pIrp->AssociatedIrp.SystemBuffer));
    }
  }
  KeReleaseSpinLock(&pDevExt->BufferLock, oldIrql);
  return r;
}


/*********************************************************************
*
*       _OnWriteCompletion
*
* Function description
*/
static NTSTATUS _OnWriteCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
  ULONG                 stageLength;
  NTSTATUS              ntS;
  USB_RW_CONTEXT      * pRWContext;

  pRWContext = (USB_RW_CONTEXT*) Context;
  ntS        = Irp->IoStatus.Status;

  // check if we need to recirculate the irp.
  if (NT_SUCCESS(ntS)) {
    if (pRWContext) {

      int NumBytesTransfered = pRWContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

      pRWContext->NumBytesTransferred += NumBytesTransfered;
      pRWContext->VirtualAddress      += NumBytesTransfered;
      pRWContext->NumRemBytes         -= NumBytesTransfered;

      DPRINT(("<usb> %d bytes written\n", pRWContext->NumBytesTransferred));

      if (pRWContext->NumRemBytes > 0) {
        // new part of transfer
        stageLength = (pRWContext->NumRemBytes > BULKUSB_MAX_TRANSFER_SIZE_WRITE ? BULKUSB_MAX_TRANSFER_SIZE_WRITE : pRWContext->NumRemBytes);
        DPRINT(("<usb>    _OnWriteCompletion: New transfer : 0x%x", stageLength));
        IoBuildPartialMdl(Irp->MdlAddress, pRWContext->Mdl, (PVOID) pRWContext->VirtualAddress, stageLength);
        
        // reinitialize the urb
        pRWContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;

        _CallUSBD(Irp, pRWContext, _OnWriteCompletion);

        // we need to be recalled
        return (STATUS_MORE_PROCESSING_REQUIRED);
      } else {
        // last transfer
        Irp->IoStatus.Information = pRWContext->NumBytesTransferred;
      }
    }
  } else {
    DPRINT(("<usb>     _OnWriteCompletion: error: %x\n", ntS));
  }
  if (pRWContext) {
    DevIoDecrement(pRWContext->pDevExt);
    _FreeRWContext(pRWContext);
  }
  return(ntS);
}


/*********************************************************************
*
*       _OnReadCompletion
*
* Function description
*/
static NTSTATUS _OnReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
  NTSTATUS               ntS;
  USB_RW_CONTEXT       * pRWContext;
  DEVICE_EXTENSION     * pDevExt;

  pRWContext = (USB_RW_CONTEXT*) Context;
  pDevExt    = pRWContext->pDevExt;
  ntS        = Irp->IoStatus.Status;

  // check if we need to recirculate the irp.
  if (NT_SUCCESS(ntS)) {
    if (pRWContext) {
      void * pVirtAddr = MmGetSystemAddressForMdl(Irp->MdlAddress);
      

      int NumBytesTransfered = pRWContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

      #if DBG
      {
        int i;
        int iMax;
        char ac[2000];
        char acHex[] = "0123456789ABCDEF";
        char * s = ac;
        iMax = (NumBytesTransfered < 100) ? NumBytesTransfered : 100;
        for (i = 0; i < iMax; i++) {
          unsigned char Data = *(i + (char*)pRWContext->Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
          *s++ = ' ';
          *s++ = acHex[Data >> 4];
          *s++ = acHex[Data & 15];
        }
        *s = '\0';
        DPRINT(("<usb> %d bytes Read (%s)\n", NumBytesTransfered, ac));
      }
      #endif

      pDevExt->NumBytesInBuffer += NumBytesTransfered;
      if (_CopyFromBuffer(Irp, pDevExt, pVirtAddr, pRWContext->NumRemBytes)) {
        //
        // We finally have enough data, no more transfers are required.
        //
        Irp->IoStatus.Information = pRWContext->NumRemBytes;
      } else {
        //
        // We need one more packet
        //
        DPRINT(("<usb>    _OnReadCompletion: Initiate new transfer"));
        UsbBuildInterruptOrBulkTransferRequest(pRWContext->Urb,
                                               sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                               pRWContext->PipeHandle,
                                               &pDevExt->acBuffer[pDevExt->NumBytesInBuffer],
                                               NULL,
                                               BULKUSB_MAX_TRANSFER_SIZE_READ,
                                               USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN,
                                               NULL);
        _CallUSBD(Irp, pRWContext, _OnReadCompletion);
        return (STATUS_MORE_PROCESSING_REQUIRED);        // we need to be recalled
      }
    }

  } else {
    DPRINT(("<usb>     _OnReadCompletion: error: %x\n", ntS));
  }

⌨️ 快捷键说明

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