📄 rwr.c
字号:
/*
**********************************************************************
* 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 + -