📄 bulkrwr.c
字号:
/*++
Module Name:
bulkrwr.c
Abstract:
This file has routines to perform reads and writes.
The read and writes are for bulk transfers.
Environment:
Kernel mode
Notes:
--*/
#include "bulkusb.h"
#include "bulkpnp.h"
#include "bulkpwr.h"
#include "bulkdev.h"
#include "bulkrwr.h"
#include "bulkwmi.h"
#include "bulkusr.h"
PINTUSB_PIPE_CONTEXT
BulkUsb_PipeWithName(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FileName
)
/*++
Routine Description:
This routine will pass the string pipe name and
fetch the pipe number.
Arguments:
DeviceObject - pointer to DeviceObject
FileName - string pipe name
Return Value:
The device extension maintains a pipe context for
the pipes on the board.
This routine returns the pointer to this context in
the device extension for the "FileName" pipe.
--*/
{
LONG ix;
ULONG uval;
ULONG nameLength;
ULONG umultiplier;
PDEVICE_EXTENSION deviceExtension;
PINTUSB_PIPE_CONTEXT pipeContext;
//
// initialize variables
//
pipeContext = NULL;
//
// typedef WCHAR *PWSTR;
//
nameLength = (FileName->Length / sizeof(WCHAR));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
KdPrint( ("BulkUsb_PipeWithName - begins\n"));
if(nameLength != 0) {
KdPrint( ("Filename = %ws nameLength = %d\n", FileName->Buffer, nameLength));
//
// Parse the pipe#
//
ix = nameLength - 1;
// if last char isn't digit, decrement it.
while((ix > -1) &&
((FileName->Buffer[ix] < (WCHAR) '0') ||
(FileName->Buffer[ix] > (WCHAR) '9'))) {
ix--;
}
if(ix > -1) {
uval = 0;
umultiplier = 1;
// traversing least to most significant digits.
while((ix > -1) &&
(FileName->Buffer[ix] >= (WCHAR) '0') &&
(FileName->Buffer[ix] <= (WCHAR) '9')) {
uval += (umultiplier *
(ULONG) (FileName->Buffer[ix] - (WCHAR) '0'));
ix--;
umultiplier *= 10;
}
if(uval < 6 && deviceExtension->PipeContext) {
pipeContext = &deviceExtension->PipeContext[uval];
}
}
}
KdPrint( ("BulkUsb_PipeWithName - ends\n"));
return pipeContext;
}
NTSTATUS
BulkUsb_DispatchReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for read and write.
This routine creates a BULKUSB_RW_CONTEXT for a read/write.
This read/write is performed in stages of BULKUSB_MAX_TRANSFER_SIZE.
once a stage of transfer is complete, then the irp is circulated again,
until the requested length of tranfer is performed.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
PMDL mdl;
PURB urb;
ULONG totalLength;
ULONG stageLength;
ULONG urbFlags;
BOOLEAN read;
NTSTATUS ntStatus;
ULONG_PTR virtualAddress;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PIO_STACK_LOCATION nextStack;
PBULKUSB_RW_CONTEXT rwContext;
PUSBD_PIPE_INFORMATION pipeInformation;
//
// initialize variables
//
urb = NULL;
mdl = NULL;
rwContext = NULL;
totalLength = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
read = (irpStack->MajorFunction == IRP_MJ_READ) ? TRUE : FALSE;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
BulkUsb_DbgPrint(3, ("BulkUsb_DispatchReadWrite - begins\n"));
if(deviceExtension->DeviceState != Working) {
BulkUsb_DbgPrint(1, ("Invalid device state\n"));
ntStatus = STATUS_INVALID_DEVICE_STATE;
goto BulkUsb_DispatchReadWrite_Exit;
}
//
// It is true that the client driver cancelled the selective suspend
// request in the dispatch routine for create Irps.
// But there is no guarantee that it has indeed completed.
// so wait on the NoIdleReqPendEvent and proceed only if this event
// is signalled.
//
BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
//
// make sure that the selective suspend request has been completed.
//
if(deviceExtension->SSEnable) {
KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
if(fileObject && fileObject->FsContext) {
pipeInformation = fileObject->FsContext;
if((UsbdPipeTypeBulk != pipeInformation->PipeType) &&
(UsbdPipeTypeInterrupt != pipeInformation->PipeType)) {
BulkUsb_DbgPrint(1, ("Usbd pipe type is not bulk\n"));
ntStatus = STATUS_INVALID_HANDLE;
goto BulkUsb_DispatchReadWrite_Exit;
}
}
else {
BulkUsb_DbgPrint(1, ("Invalid handle\n"));
ntStatus = STATUS_INVALID_HANDLE;
goto BulkUsb_DispatchReadWrite_Exit;
}
rwContext = (PBULKUSB_RW_CONTEXT)
ExAllocatePool(NonPagedPool,
sizeof(BULKUSB_RW_CONTEXT));
if(rwContext == NULL) {
BulkUsb_DbgPrint(1, ("Failed to alloc mem for rwContext\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto BulkUsb_DispatchReadWrite_Exit;
}
if(Irp->MdlAddress) {
totalLength = MmGetMdlByteCount(Irp->MdlAddress);
}
if(totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {
BulkUsb_DbgPrint(1, ("Transfer length > circular buffer\n"));
ntStatus = STATUS_INVALID_PARAMETER;
ExFreePool(rwContext);
goto BulkUsb_DispatchReadWrite_Exit;
}
if(totalLength == 0) {
BulkUsb_DbgPrint(1, ("Transfer data length = 0\n"));
ntStatus = STATUS_SUCCESS;
ExFreePool(rwContext);
goto BulkUsb_DispatchReadWrite_Exit;
}
urbFlags = USBD_SHORT_TRANSFER_OK;
virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
if(read) {
urbFlags |= USBD_TRANSFER_DIRECTION_IN;
BulkUsb_DbgPrint(3, ("Read operation\n"));
}
else {
urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
BulkUsb_DbgPrint(3, ("Write operation\n"));
}
//
// the transfer request is for totalLength.
// we can perform a max of BULKUSB_MAX_TRANSFER_SIZE
// in each stage.
//
if(totalLength > BULKUSB_MAX_TRANSFER_SIZE) {
stageLength = BULKUSB_MAX_TRANSFER_SIZE;
}
else {
stageLength = totalLength;
}
mdl = IoAllocateMdl((PVOID) virtualAddress,
totalLength,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -