?? isostrm.c
字號:
/*++
Copyright (c) 2004 Microsoft Corporation
Module Name:
isostrm.c
Abstract:
This file has routines for stream transfers.
Stream transfers are initiated and stopped using
the IOCTLs exposed by this driver.
The stream transfer information is contained in
ISOUSB_STREAM_OBJECT structure which is securely
placed in the FileObject. The ISOUSB_STREAM_OBJECT
structure has links to ISOUSB_TRANSFER_OBJECT
(each TRANSFER_OBJECT corresponds to the number of
irp/urb pair circulating).
So if the user-mode app simply crashes or aborts or
does not terminate, we can cleanly abort the stream
transfers.
Environment:
Kernel mode
Notes:
Copyright (c) 2004 Microsoft Corporation.
All Rights Reserved.
--*/
#include "isousb.h"
#include "isopnp.h"
#include "isopwr.h"
#include "isodev.h"
#include "isousr.h"
#include "isowmi.h"
#include "isorwr.h"
#include "isostrm.h"
NTSTATUS
IsoUsb_StartIsoStream(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine create a single stream object and
invokes StartTransfer for ISOUSB_MAX_IRP number of
times.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
ULONG i;
ULONG info;
ULONG inputBufferLength;
ULONG outputBufferLength;
NTSTATUS ntStatus = STATUS_SUCCESS;
PFILE_OBJECT fileObject;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PISOUSB_STREAM_OBJECT streamObject;
PUSBD_PIPE_INFORMATION pipeInformation;
info = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
streamObject = NULL;
pipeInformation = NULL;
deviceExtension = DeviceObject->DeviceExtension;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
IsoUsb_DbgPrint(3, ("IsoUsb_StartIsoStream - begins\n"));
streamObject = ExAllocatePool(NonPagedPool,
sizeof(struct _ISOUSB_STREAM_OBJECT));
if(streamObject == NULL) {
IsoUsb_DbgPrint(1, ("failed to alloc mem for streamObject\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_StartIsoStream_Exit;
}
RtlZeroMemory(streamObject, sizeof(ISOUSB_STREAM_OBJECT));
// Find the first currently configured Isochronous IN Endpoint
//
for (i = 0; i < deviceExtension->NumberOfPipes; i++)
{
if ((deviceExtension->PipeInformation[i]->PipeType == UsbdPipeTypeIsochronous) &&
USBD_PIPE_DIRECTION_IN(deviceExtension->PipeInformation[i]))
{
pipeInformation = deviceExtension->PipeInformation[i];
break;
}
}
if (pipeInformation == NULL)
{
ntStatus = STATUS_INVALID_PARAMETER;
if (streamObject != NULL)
{
ExFreePool(streamObject);
streamObject = NULL;
}
goto IsoUsb_StartIsoStream_Exit;
}
// reset the pipe
//
IsoUsb_AbortResetPipe(DeviceObject,
pipeInformation->PipeHandle,
TRUE);
streamObject->DeviceObject = DeviceObject;
streamObject->PipeInformation = pipeInformation;
KeInitializeEvent(&streamObject->NoPendingIrpEvent,
NotificationEvent,
FALSE);
for(i = 0; i < ISOUSB_MAX_IRP; i++) {
ntStatus = IsoUsb_StartTransfer(DeviceObject,
streamObject,
i);
if(!NT_SUCCESS(ntStatus)) {
//
// we continue sending transfer object irps..
//
IsoUsb_DbgPrint(1, ("IsoUsb_StartTransfer [%d] - failed\n", i));
if(ntStatus == STATUS_INSUFFICIENT_RESOURCES) {
ASSERT(streamObject->TransferObjectList[i] == NULL);
}
}
}
if(fileObject && fileObject->FsContext) {
if(streamObject->PendingIrps) {
((PFILE_OBJECT_CONTENT)fileObject->FsContext)->StreamInformation
= streamObject;
}
else {
IsoUsb_DbgPrint(1, ("no transfer object irp sent..abort..\n"));
ExFreePool(streamObject);
streamObject = NULL;
((PFILE_OBJECT_CONTENT)fileObject->FsContext)->StreamInformation = NULL;
}
}
else {
if (streamObject != NULL) {
ExFreePool(streamObject);
streamObject = NULL;
}
}
IsoUsb_StartIsoStream_Exit:
Irp->IoStatus.Information = info;
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IsoUsb_DbgPrint(3, ("IsoUsb_StartIsoStream::"));
IsoUsb_IoDecrement(deviceExtension);
IsoUsb_DbgPrint(3, ("IsoUsb_StartIsoStream - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_StartTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_STREAM_OBJECT StreamObject,
IN ULONG Index
)
/*++
Routine Description:
This routine creates a transfer object for each irp/urb pair.
After initializing the pair, it sends the irp down the stack.
Arguments:
DeviceObject - pointer to device object.
StreamObject - pointer to stream object
Index - index into the transfer object table in stream object
Return Value:
NT status value
--*/
{
PIRP irp;
CCHAR stackSize;
ULONG packetSize;
ULONG maxXferSize;
ULONG numPackets;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION nextStack;
PISOUSB_TRANSFER_OBJECT transferObject;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
maxXferSize = StreamObject->PipeInformation->MaximumTransferSize;
packetSize = StreamObject->PipeInformation->MaximumPacketSize;
numPackets = maxXferSize / packetSize;
IsoUsb_DbgPrint(3, ("IsoUsb_StartTransfer - begins\n"));
transferObject = ExAllocatePool(NonPagedPool,
sizeof(struct _ISOUSB_TRANSFER_OBJECT));
if(transferObject == NULL) {
IsoUsb_DbgPrint(1, ("failed to alloc mem for transferObject\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(transferObject,
sizeof(struct _ISOUSB_TRANSFER_OBJECT));
transferObject->StreamObject = StreamObject;
stackSize = (CCHAR) (deviceExtension->TopOfStackDeviceObject->StackSize + 1);
irp = IoAllocateIrp(stackSize, FALSE);
if(irp == NULL) {
IsoUsb_DbgPrint(1, ("failed to alloc mem for irp\n"));
ExFreePool(transferObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
transferObject->Irp = irp;
transferObject->DataBuffer = ExAllocatePool(NonPagedPool,
maxXferSize);
if(transferObject->DataBuffer == NULL) {
IsoUsb_DbgPrint(1, ("failed to alloc mem for DataBuffer\n"));
ExFreePool(transferObject);
IoFreeIrp(irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
transferObject->Urb = ExAllocatePool(NonPagedPool,
GET_ISO_URB_SIZE(numPackets));
if(transferObject->Urb == NULL) {
IsoUsb_DbgPrint(1, ("failed to alloc mem for Urb\n"));
ExFreePool(transferObject->DataBuffer);
IoFreeIrp(irp);
ExFreePool(transferObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
IsoUsb_InitializeStreamUrb(DeviceObject, transferObject);
StreamObject->TransferObjectList[Index] = transferObject;
InterlockedIncrement((PLONG)&StreamObject->PendingIrps);
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoSetCompletionRoutine(irp,
IsoUsb_IsoIrp_Complete,
transferObject,
TRUE,
TRUE,
TRUE);
IsoUsb_DbgPrint(3, ("IsoUsb_StartTransfer::"));
IsoUsb_IoIncrement(deviceExtension);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
if(NT_SUCCESS(ntStatus)) {
ntStatus = STATUS_SUCCESS;
}
IsoUsb_DbgPrint(3, ("IsoUsb_StartTransfer - ends\n"));
return ntStatus;
}
NTSTATUS
IsoUsb_InitializeStreamUrb(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_TRANSFER_OBJECT TransferObject
)
/*++
Routine Description:
This routine initializes the irp/urb pair in the transfer object.
Arguments:
DeviceObject - pointer to device object
TransferObject - pointer to transfer object
Return Value:
NT status value
--*/
{
PURB urb;
ULONG i;
ULONG siz;
ULONG packetSize;
ULONG numPackets;
ULONG maxXferSize;
PISOUSB_STREAM_OBJECT streamObject;
UNREFERENCED_PARAMETER( DeviceObject );
urb = TransferObject->Urb;
streamObject = TransferObject->StreamObject;
maxXferSize = streamObject->PipeInformation->MaximumTransferSize;
packetSize = streamObject->PipeInformation->MaximumPacketSize;
numPackets = maxXferSize / packetSize;
IsoUsb_DbgPrint(3, ("IsoUsb_InitializeStreamUrb - begins\n"));
if(numPackets > 255) {
numPackets = 255;
maxXferSize = packetSize * numPackets;
}
siz = GET_ISO_URB_SIZE(numPackets);
RtlZeroMemory(urb, siz);
urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz;
urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
urb->UrbIsochronousTransfer.PipeHandle =
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -