NTSTATUS
Ezusb_Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
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;
PVOID IoBuffer;
//
// 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;
IoBuffer = Irp-> AssociatedIrp.SystemBuffer;
if(fileObject && fileObject-> FsContext) {
pipeInformation = fileObject-> FsContext;
if((UsbdPipeTypeBulk != pipeInformation-> PipeType) &&
(UsbdPipeTypeInterrupt != pipeInformation-> PipeType)) {
ntStatus = STATUS_INVALID_HANDLE;
goto BulkUsb_DispatchRead_Exit;
}
}
else {
ntStatus = STATUS_INVALID_HANDLE;
goto BulkUsb_DispatchRead_Exit;
}
rwContext = (PBULKUSB_RW_CONTEXT)
ExAllocatePool(NonPagedPool,
sizeof(BULKUSB_RW_CONTEXT));
if(rwContext == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto BulkUsb_DispatchRead_Exit;
}
if(Irp-> MdlAddress) {
totalLength = MmGetMdlByteCount(Irp-> MdlAddress);
}
if(totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {
ntStatus = STATUS_INVALID_PARAMETER;
ExFreePool(rwContext);
goto BulkUsb_DispatchRead_Exit;
}
if(totalLength == 0) {
ntStatus = STATUS_SUCCESS;
ExFreePool(rwContext);
goto BulkUsb_DispatchRead_Exit;
}
urbFlags = USBD_SHORT_TRANSFER_OK;
virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp-> MdlAddress);
if(read) {
urbFlags |= USBD_TRANSFER_DIRECTION_IN;
}
else {
urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
}
//
// 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,
FALSE,
FALSE,
NULL);
if(mdl == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(rwContext);
goto BulkUsb_DispatchRead_Exit;
}
//
// map the portion of user-buffer described by an mdl to another mdl
//
IoBuildPartialMdl(Irp-> MdlAddress,
mdl,
(PVOID) virtualAddress,
stageLength);
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
if(urb == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(rwContext);
IoFreeMdl(mdl);
goto BulkUsb_DispatchRead_Exit;
}
UsbBuildInterruptOrBulkTransferRequest(
urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeInformation-> PipeHandle,
NULL,
mdl,
stageLength,
urbFlags,
NULL);
//
// set BULKUSB_RW_CONTEXT parameters.
//
rwContext-> Urb = urb;
rwContext-> Mdl = mdl;
rwContext-> Length = totalLength - stageLength;
rwContext-> Numxfer = 0;
rwContext-> VirtualAddress = virtualAddress + stageLength;
rwContext-> DeviceExtension = deviceExtension;
//
// use the original read/write irp as an internal device control irp
//
nextStack = IoGetNextIrpStackLocation(Irp);
nextStack-> MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack-> Parameters.Others.Argument1 = (PVOID) urb;
nextStack-> Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE)Ezusb_ReadWriteCompletion,
rwContext,
TRUE,
TRUE,
TRUE);
//
// since we return STATUS_PENDING call IoMarkIrpPending.
// This is the boiler plate code.
// This may cause extra overhead of an APC for the Irp completion
// but this is the correct thing to do.
//
IoMarkIrpPending(Irp);
//BulkUsb_IoIncrement(deviceExtension);
ntStatus = IoCallDriver(deviceExtension-> StackDeviceObject,
Irp);
if(!NT_SUCCESS(ntStatus)) {
//
// 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((ntStatus != STATUS_CANCELLED) &&
(ntStatus != STATUS_DEVICE_NOT_CONNECTED)) {
ULONG pipenum = *((PULONG) irpStack);
/*ntStatus = UsbResetPipe(DeviceObject,
pipeInformation);*/
ntStatus = UsbResetPipe(DeviceObject,
pipenum);
if(!NT_SUCCESS(ntStatus)) {
//ntStatus = BulkUsb_ResetDevice(DeviceObject);
}
}
else {
}
}
//
// we return STATUS_PENDING and not the status returned by the lower layer.
//
return STATUS_PENDING;
BulkUsb_DispatchRead_Exit:
Irp-> IoStatus.Status = ntStatus;
Irp-> IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
这是我找资料写的一个写例程.我用softIce进行调试时if(fileObject && fileObject-> FsContext) 这里就没有往下执行,直接跳到
else {
ntStatus = STATUS_INVALID_HANDLE;
goto BulkUsb_DispatchRead_Exit;
} |