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

📄 isostrm.c

📁 WINDDK开发代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 2000  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) 2000 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;
    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));

    //
    // The Isoch IN pipe for the board is the 5th pipe
    //
    pipeInformation = &(deviceExtension->UsbInterface->Pipes[ISOCH_IN_PIPE_INDEX]);

    // reset the pipe
    //
    IsoUsb_ResetPipe(DeviceObject, pipeInformation);
    
    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);
            ((PFILE_OBJECT_CONTENT)fileObject->FsContext)->StreamInformation = 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(&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;

    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 =
                                streamObject->PipeInformation->PipeHandle;

    urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN;

    urb->UrbIsochronousTransfer.TransferBufferMDL = NULL;
    urb->UrbIsochronousTransfer.TransferBuffer = TransferObject->DataBuffer;
    urb->UrbIsochronousTransfer.TransferBufferLength = numPackets * packetSize;

    urb->UrbIsochronousTransfer.TransferFlags |= USBD_START_ISO_TRANSFER_ASAP;

    urb->UrbIsochronousTransfer.NumberOfPackets = numPackets;
    urb->UrbIsochronousTransfer.UrbLink = NULL;

⌨️ 快捷键说明

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