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

📄 isorwr.c

📁 传说中的 usb 端口 驱动 源码 啊啊啊啊啊啊啊
💻 C
📖 第 1 页 / 共 4 页
字号:
    // Resource allocation failure, or the main request Irp was
    // cancelled before the cancel routine was set.  Free any resource
    // allocations and complete the main request Irp.
    //
    // No sub requests were ever called down the driver stack in this
    // case.
    //

PerformHighSpeedIsochTransfer_Free:

    if (subRequestContextArray != NULL)
    {
        for (i = 0; i < numIrps; i++)
        {
            subRequestContext = subRequestContextArray[i];

            if (subRequestContext != NULL)
            {
                if (subRequestContext->SubIrp != NULL)
                {
                    IoFreeIrp(subRequestContext->SubIrp);
                }

                if (subRequestContext->SubUrb != NULL)
                {
                    ExFreePool(subRequestContext->SubUrb);
                }

                if (subRequestContext->SubMdl != NULL)
                {
                    IoFreeMdl(subRequestContext->SubMdl);
                }

                ExFreePool(subRequestContext);
            }
        }

        ExFreePool(subRequestContextArray);
    }

PerformHighSpeedIsochTransfer_Exit:

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

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

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

    return ntStatus;
}


NTSTATUS
IsoUsb_SubRequestComplete(
    IN PDEVICE_OBJECT DeviceObjectIsNULL,
    IN PIRP           Irp,
    IN PVOID          Context
    )
/*++

Routine Description:

    This routine handles the completion of a Sub Request Irp that was
    created to handle part (or all) of the transfer for a Main Request
    Irp.

    It updates the transfer length (IoStatus.Information) of the Main
    Request Irp, and completes the Main Request Irp if this Sub Request
    Irp is the final outstanding one.

    The Sub Request Irp and Sub Request Context may either be freed
    here, or by IsoUsb_CancelReadWrite(), according to which routine is
    the last one to reference the Sub Request Irp.

Arguments:

    DeviceObject - NULL as this Sub Request Irp was allocated without a
    stack location for this driver to use itself.

    Irp - Sub Request Irp

    Context - Sub Request Context (PSUB_REQUEST_CONTEXT)

Return Value:

    STATUS_MORE_PROCESSING_REQUIRED - Tells IoMgr not to free the Sub
    Request Irp as it is either explicitly freed here, or by
    IsoUsb_CancelReadWrite()

--*/
{
    PSUB_REQUEST_CONTEXT    subRequestContext;
    PURB                    subUrb;
    PIRP                    mainIrp;
    PMAIN_REQUEST_CONTEXT   mainRequestContext;
    PDEVICE_OBJECT          deviceObject;
    NTSTATUS                ntStatus;
    ULONG                   information;
    ULONG                   i;
    KIRQL                   irql;
    BOOLEAN                 completeMainRequest;

    subRequestContext = (PSUB_REQUEST_CONTEXT)Context;

    subUrb = subRequestContext->SubUrb;

    mainIrp = subRequestContext->MainIrp;

    // The main request Irp context is overlaid on top of
    // Irp->Tail.Overlay.DriverContext.  Get a pointer to it.
    //
    mainRequestContext = (PMAIN_REQUEST_CONTEXT)
                         mainIrp->Tail.Overlay.DriverContext;

    deviceObject = IoGetCurrentIrpStackLocation(mainIrp)->DeviceObject;

    ntStatus = Irp->IoStatus.Status;

    if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(subUrb->UrbHeader.Status))
    {
        information = subUrb->UrbIsochronousTransfer.TransferBufferLength;

        IsoUsb_DbgPrint(1, ("TransferBufferLength = %d\n", information));
    }
    else
    {
        information = 0;

        IsoUsb_DbgPrint(1, ("read-write irp failed with status %X\n", ntStatus));
        IsoUsb_DbgPrint(1, ("urb header status %X\n", subUrb->UrbHeader.Status));
    }

    for (i = 0; i < subUrb->UrbIsochronousTransfer.NumberOfPackets; i++)
    {
        IsoUsb_DbgPrint(3, ("IsoPacket[%d].Length = %X IsoPacket[%d].Status = %X\n",
                            i,
                            subUrb->UrbIsochronousTransfer.IsoPacket[i].Length,
                            i,
                            subUrb->UrbIsochronousTransfer.IsoPacket[i].Status));
    }

    // Prevent the cancel routine from executing simultaneously
    //
    IoAcquireCancelSpinLock(&irql);

    mainIrp->IoStatus.Information += information;

    // Remove the sub request from the main request sub request list.
    //
    RemoveEntryList(&subRequestContext->ListEntry);

    // If the sub request list is now empty clear the main request
    // cancel routine and note that the main request should be
    // completed.
    //
    if (IsListEmpty(&mainRequestContext->SubRequestList))
    {
        completeMainRequest = TRUE;

        IoSetCancelRoutine(mainIrp, NULL);
    }
    else
    {
        completeMainRequest = FALSE;
    }

    // The cancel routine may now execute simultaneously, unless of
    // course the cancel routine was just cleared above.
    //
    // Do not access the main Irp or the mainRequestContext in any way
    // beyond this point, unless this is the single instance of the sub
    // request completion routine which will complete the main Irp.
    //
    IoReleaseCancelSpinLock(irql);

    if (InterlockedDecrement(&subRequestContext->ReferenceCount) == 0)
    {
        // If the reference count is now zero then the cancel routine
        // will not free the sub request.  (Either the cancel routine
        // ran and accessed the sub request and incremented the
        // reference count and the decremented it again without freeing
        // the sub request, or the cancel routine did not access the
        // sub request and can no longer access it because it has been
        // removed from the main request sub request list.)
        //
        IoFreeIrp(subRequestContext->SubIrp);

        ExFreePool(subRequestContext->SubUrb);

        IoFreeMdl(subRequestContext->SubMdl);

        ExFreePool(subRequestContext);

        // Decrement the device object reference that was incremented
        // before this sub request was called down the driver stack.
        //
        IsoUsb_IoDecrement(deviceObject->DeviceExtension);
    }
    else
    {
        // In this case the cancel routine for the main request must be
        // executing and is accessing the sub request after
        // incrementing its reference count.  When the cancel routine
        // decrements the reference count again it will take care of
        // freeing the sub request.
    }

    if (completeMainRequest)
    {
        // The final sub request for the main request has completed so
        // now complete the main request.
        //
        mainIrp->IoStatus.Status = STATUS_SUCCESS;

        IoCompleteRequest(mainIrp, IO_NO_INCREMENT);

        IsoUsb_IoDecrement(deviceObject->DeviceExtension);
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}


VOID
IsoUsb_CancelReadWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

    This is the cancellation routine for the main read/write Irp.

    It cancels all currently outstanding sub requests for the main
    request.

    Completing the main request is the responsibility of the sub
    request completion routine after all outstanding sub requests have
    completed.

Return Value:

    None

--*/
{
    PMAIN_REQUEST_CONTEXT   mainRequestContext;
    LIST_ENTRY              cancelList;
    PLIST_ENTRY             subRequestEntry;
    PSUB_REQUEST_CONTEXT    subRequestContext;

    // The main request Irp context is overlaid on top of
    // Irp->Tail.Overlay.DriverContext.  Get a pointer to it.
    //
    mainRequestContext = (PMAIN_REQUEST_CONTEXT)
                         Irp->Tail.Overlay.DriverContext;

    // The mainRequestContext SubRequestList cannot be simultaneously
    // changed by anything else as long as the cancel spin lock is still
    // held, but can be changed immediately by the completion routine
    // after the cancel spin lock is released.
    //
    // Iterate over the mainRequestContext SubRequestList and add all of
    // the currently outstanding sub requests to the list of sub
    // requests to be cancelled.
    //
    InitializeListHead(&cancelList);

    subRequestEntry = mainRequestContext->SubRequestList.Flink;

    while (subRequestEntry != &mainRequestContext->SubRequestList)
    {
        subRequestContext = CONTAINING_RECORD(subRequestEntry,
                                              SUB_REQUEST_CONTEXT,
                                              ListEntry);

        // Prevent the sub request from being freed as soon as the
        // cancel spin lock is released by incrementing the reference
        // count on the sub request.
        //
        InterlockedIncrement(&subRequestContext->ReferenceCount);

        InsertTailList(&cancelList, &subRequestContext->CancelListEntry);

        subRequestEntry = subRequestEntry->Flink;
    }

    // The main read/write Irp can be completed immediately after
    // releasing the cancel spin lock.  Do not access the main
    // read/write Irp or the mainRequestContext in any way beyond this
    // point.
    //
    IoReleaseCancelSpinLock(Irp->CancelIrql);



    // Iterate over the list that was built of sub requests to cancel
    // and cancel each sub request.
    //
    while (!IsListEmpty(&cancelList))
    {
        subRequestEntry = RemoveHeadList(&cancelList);

        subRequestContext = CONTAINING_RECORD(subRequestEntry,
                                              SUB_REQUEST_CONTEXT,
                                              CancelListEntry);

        IoCancelIrp(subRequestContext->SubIrp);


        if (InterlockedDecrement(&subRequestContext->ReferenceCount) == 0)
        {
            // If the reference count is now zero then the completion
            // routine already ran for the sub request but did not free
            // the sub request so it can be freed now.
            //
            IoFreeIrp(subRequestContext->SubIrp);

            ExFreePool(subRequestContext->SubUrb);

            IoFreeMdl(subRequestContext->SubMdl);

            ExFreePool(subRequestContext);

            // Decrement the device object reference that was
            // incremented before this sub request was called down the
            // driver stack.
            //
            IsoUsb_IoDecrement(DeviceObject->DeviceExtension);
        }
        else
        {
            // The completion routine for the sub request has not yet
            // executed and decremented the sub request reference count.
            // Do not free the sub request here.  It will be freed when
            // the sub request completion routine executes.
        }
    }
}


ULONG
IsoUsb_GetCurrentFrame(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

    This routine send an irp/urb pair with
    function code URB_FUNCTION_GET_CURRENT_FRAME_NUMBER
    to fetch the current frame

Arguments:

    DeviceObject - pointer to device object
    PIRP - I/O request packet

Return Value:

    Current frame

--*/
{
    KEVENT                               event;
    PDEVICE_EXTENSION                    deviceExtension;
    PIO_STACK_LOCATION                   nextStack;
    struct _URB_GET_CURRENT_FRAME_NUMBER urb;

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    //
    // initialize the urb
    //

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

    urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER;
    urb.Hdr.Length = sizeof(urb);
    urb.FrameNumber = (ULONG) -1;

    nextStack = IoGetNextIrpStackLocation(Irp);
    nextStack->Parameters.Others.Argument1 = (PVOID) &urb;
    nextStack->Parameters.DeviceIoControl.IoControlCode =
                                IOCTL_INTERNAL_USB_SUBMIT_URB;
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

    KeInitializeEvent(&event,
                      NotificationEvent,
                      FALSE);

    IoSetCompletionRoutine(Irp,
                           IsoUsb_StopCompletion,
                           &event,
                           TRUE,
                           TRUE,
                           TRUE);

    IsoUsb_DbgPrint(3, ("IsoUsb_GetCurrentFrame::"));
    IsoUsb_IoIncrement(deviceExtension);

    IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                 Irp);

    KeWaitForSingleObject((PVOID) &event,
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

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

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

    return urb.FrameNumber;
}


NTSTATUS
IsoUsb_StopCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN PVOID          Context
    )
/*++

Routine Description:

    This is the completion routine for request to retrieve the frame number

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    Context - context passed to the completion routine

Return Value:

    NT status value

--*/
{
    PKEVENT event;

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

    event = (PKEVENT) Context;

    KeSetEvent(event, IO_NO_INCREMENT, FALSE);

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

    return STATUS_MORE_PROCESSING_REQUIRED;
}

⌨️ 快捷键说明

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