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

📄 isostrm.c

📁 WINDDK开发代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    for(i=0; i<urb->UrbIsochronousTransfer.NumberOfPackets; i++) {

        urb->UrbIsochronousTransfer.IsoPacket[i].Offset = i * packetSize;

        //
        // For input operation, length is set to whatever the device supplies.
        //
        urb->UrbIsochronousTransfer.IsoPacket[i].Length = 0;
    }

    IsoUsb_DbgPrint(3, ("IsoUsb_InitializeStreamUrb - ends\n"));

    return STATUS_SUCCESS;
}

NTSTATUS
IsoUsb_IsoIrp_Complete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN PVOID          Context
    )
/*++
 
Routine Description:

    This is the completion routine of the irp in the irp/urb pair
    passed down the stack for stream transfers.

    If the transfer was cancelled or the device yanked out, then we
    release resources, dump the statistics and return 
    STATUS_MORE_PROCESSING_REQUIRED, so that the cleanup module can
    free the irp.

    otherwise, we reinitialize the transfers and continue recirculaiton 
    of the irps.

Arguments:

    DeviceObject - pointer to device object below us.
    Irp - I/O completion routine.
    Context - context passed to the completion routine

Return Value:

--*/
{
    NTSTATUS                ntStatus;
    PDEVICE_OBJECT          deviceObject;
    PDEVICE_EXTENSION       deviceExtension;
    PIO_STACK_LOCATION      nextStack;
    PISOUSB_STREAM_OBJECT   streamObject;
    PISOUSB_TRANSFER_OBJECT transferObject;

    transferObject = (PISOUSB_TRANSFER_OBJECT) Context;
    streamObject = transferObject->StreamObject;
    deviceObject = streamObject->DeviceObject;
    deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;

    IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete - begins\n"));

    ntStatus = IsoUsb_ProcessTransfer(transferObject);

    if((ntStatus == STATUS_CANCELLED) ||
       (ntStatus == STATUS_DEVICE_NOT_CONNECTED)) {
    
        IsoUsb_DbgPrint(3, ("Isoch irp cancelled/device removed\n"));

        //
        // this is the last irp to complete with this erroneous value
        // signal an event and return STATUS_MORE_PROCESSING_REQUIRED
        //
        if(InterlockedDecrement(&streamObject->PendingIrps) == 0) {

            KeSetEvent(&streamObject->NoPendingIrpEvent,
                       1,
                       FALSE);

            IsoUsb_DbgPrint(3, ("-----------------------------\n"));
        }

        IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete::"));
        IsoUsb_IoDecrement(deviceExtension);

        transferObject->Irp = NULL;
        IoFreeIrp(Irp);

        return STATUS_MORE_PROCESSING_REQUIRED;
    }

    //
    // otherwise circulate the irps.
    //

    IsoUsb_InitializeStreamUrb(deviceObject, transferObject);

    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);

    transferObject->TimesRecycled++;

    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                            Irp);

    IsoUsb_DbgPrint(3, ("IsoUsb_IsoIrp_Complete - ends\n"));
    IsoUsb_DbgPrint(3, ("-----------------------------\n"));

    return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS
IsoUsb_ProcessTransfer(
    IN PISOUSB_TRANSFER_OBJECT TransferObject
    )
/*++
 
Routine Description:

    This routine is invoked from the completion routine to check the status
    of the irp, urb and the isochronous packets.

    updates statistics

Arguments:

    TranferObject - pointer to transfer object for the irp/urb pair which completed.

Return Value:

    NT status value

--*/
{
    PIRP        irp;
    PURB        urb;
    ULONG       i;
    NTSTATUS    ntStatus;
    USBD_STATUS usbdStatus;

    irp = TransferObject->Irp;
    urb = TransferObject->Urb;
    ntStatus = irp->IoStatus.Status;

    IsoUsb_DbgPrint(3, ("IsoUsb_ProcessTransfer - begins\n"));

    if(!NT_SUCCESS(ntStatus)) {

        IsoUsb_DbgPrint(3, ("Isoch irp failed with status = %X\n", ntStatus));
    }

    usbdStatus = urb->UrbHeader.Status;

    if(!USBD_SUCCESS(usbdStatus)) {

        IsoUsb_DbgPrint(3, ("urb failed with status = %X\n", usbdStatus));
    }

    //
    // check each of the urb packets
    //
    for(i = 0; i < urb->UrbIsochronousTransfer.NumberOfPackets; i++) {

        TransferObject->TotalPacketsProcessed++;

        usbdStatus = urb->UrbIsochronousTransfer.IsoPacket[i].Status;

        if(!USBD_SUCCESS(usbdStatus)) {

//            IsoUsb_DbgPrint(3, ("Iso packet %d failed with status = %X\n", i, usbdStatus));
            
            TransferObject->ErrorPacketCount++;
        }
        else {
            
            TransferObject->TotalBytesProcessed += urb->UrbIsochronousTransfer.IsoPacket[i].Length;
        }
    }

    IsoUsb_DbgPrint(3, ("IsoUsb_ProcessTransfer - ends\n"));

    return ntStatus;
}

NTSTATUS
IsoUsb_StopIsoStream(
    IN PDEVICE_OBJECT        DeviceObject,
    IN PISOUSB_STREAM_OBJECT StreamObject,
    IN PIRP                  Irp
    )
/*++
 
Routine Description:

    This routine is invoked from the IOCTL to stop the stream transfers.

Arguments:

    DeviceObject - pointer to device object
    StreamObject - pointer to stream object
    Irp - pointer to Irp

Return Value:

    NT status value

--*/
{
    ULONG              i;
    KIRQL              oldIrql;
    PDEVICE_EXTENSION  deviceExtension;
    PIO_STACK_LOCATION irpStack;

    //
    // initialize vars
    //
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    IsoUsb_DbgPrint(3, ("IsoUsb_StopIsoStream - begins\n"));

    if((StreamObject == NULL) ||
       (StreamObject->DeviceObject != DeviceObject)) {

        IsoUsb_DbgPrint(1, ("invalid streamObject\n"));
        return STATUS_INVALID_PARAMETER;
    }

    IsoUsb_StreamObjectCleanup(StreamObject, deviceExtension);

    IsoUsb_DbgPrint(3, ("IsoUsb_StopIsoStream - ends\n"));

    return STATUS_SUCCESS;
}

NTSTATUS
IsoUsb_StreamObjectCleanup(
    IN PISOUSB_STREAM_OBJECT StreamObject,
    IN PDEVICE_EXTENSION     DeviceExtension
    )
/*++
 
Routine Description:

    This routine is invoked either when the user-mode app passes an IOCTL to
    abort stream transfers or when the the cleanup dispatch routine is run.
    It is guaranteed to run only once for every stream transfer.

Arguments:

    StreamObject - StreamObject corresponding to stream transfer which
    needs to be aborted.

    DeviceExtension - pointer to device extension

Return Value:

    NT status value

--*/
{
    ULONG                   i;
    ULONG                   timesRecycled;
    ULONG                   totalPacketsProcessed;
    ULONG                   totalBytesProcessed;
    ULONG                   errorPacketCount;
    PISOUSB_TRANSFER_OBJECT xferObject;

    //
    // initialize the variables
    //
    timesRecycled = 0;
    totalPacketsProcessed = 0;
    totalBytesProcessed = 0;
    errorPacketCount = 0;

    //
    // cancel transferobject irps/urb pair
    // safe to touch these irps because the 
    // completion routine always returns 
    // STATUS_MORE_PRCESSING_REQUIRED
    // 
    //
    for(i = 0; i < ISOUSB_MAX_IRP; i++) {

        if(StreamObject->TransferObjectList[i] &&
           StreamObject->TransferObjectList[i]->Irp) {
        
            IoCancelIrp(StreamObject->TransferObjectList[i]->Irp);
        }
    }

    //
    // wait for the transfer objects irps to complete.
    //
    KeWaitForSingleObject(&StreamObject->NoPendingIrpEvent,
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

    //
    // dump the statistics
    //
    for(i = 0; i < ISOUSB_MAX_IRP; i++) {

        xferObject = StreamObject->TransferObjectList[i];

        if(xferObject) {

            timesRecycled += xferObject->TimesRecycled;
            totalPacketsProcessed += xferObject->TotalPacketsProcessed;
            totalBytesProcessed += xferObject->TotalBytesProcessed;
            errorPacketCount += xferObject->ErrorPacketCount;
        }
    }

    IsoUsb_DbgPrint(3, ("TimesRecycled = %d\n", timesRecycled));
    IsoUsb_DbgPrint(3, ("TotalPacketsProcessed = %d\n", totalPacketsProcessed));
    IsoUsb_DbgPrint(3, ("TotalBytesProcessed = %d\n", totalBytesProcessed));
    IsoUsb_DbgPrint(3, ("ErrorPacketCount = %d\n", errorPacketCount));


    //
    // free all the buffers, urbs and transfer objects 
    // associated with stream object
    //
    for(i = 0; i < ISOUSB_MAX_IRP; i++) {
        
        xferObject = StreamObject->TransferObjectList[i];

        if(xferObject) { 
            
            if(xferObject->Urb) {

                ExFreePool(xferObject->Urb);
                xferObject->Urb = NULL;
            }

            if(xferObject->DataBuffer) {
    
                ExFreePool(xferObject->DataBuffer);
                xferObject->DataBuffer = NULL;
            }

            ExFreePool(xferObject);
            StreamObject->TransferObjectList[i] = NULL;
        }
    }

    ExFreePool(StreamObject);

//    IsoUsb_ResetParentPort(DeviceObject);

    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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