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

📄 datapkt.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 3 页
字号:
//===========================================================================
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996 - 2000  Microsoft Corporation.  All Rights Reserved.
//
//===========================================================================
/*++

Module Name:

    DataPkt.c

Abstract:

    Stream class based WDM driver for 1934 Desktop Camera.
    This file contains code to handle the stream class packets.

Author:

    Yee J. Wu 24-Jun-98

Environment:

    Kernel mode only

Revision History:


--*/


#include "strmini.h"
#include "ksmedia.h"
#include "1394.h"
#include "wdm.h"       // for DbgBreakPoint() defined in dbg.h
#include "dbg.h"
#include "dcamdef.h"
#include "dcampkt.h"
#include "sonydcam.h"

extern CAMERA_ISOCH_INFO IsochInfoTable[];



#ifdef ALLOC_PRAGMA
    #pragma alloc_text(PAGE, DCamSurpriseRemoval)
    #pragma alloc_text(PAGE, DCamReceiveDataPacket)
#endif



NTSTATUS
DCamCancelOnePacketCR(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp,
    PISOCH_DESCRIPTOR IsochDescriptor
    )
/*++

Routine Description:

    Completion routine for detach an isoch descriptor associate with a pending read SRB.
    Will cancel the pending SRB here if detaching descriptor has suceeded.

Arguments:

    DriverObject - Pointer to driver object created by system.
    pIrp - Allocated locally, need to be free here.
    IsochDescriptor - Isoch descriptor containing the SRB to be cancelled.

Return Value:

    None.

--*/
{
    PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
    PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
    PDCAM_EXTENSION pDevExt;


    if(STATUS_SUCCESS != pIrp->IoStatus.Status) {
        ERROR_LOG(("DCamCancelOnePacketCR: Detach buffer failed with pIrp->IoStatus.Status= %x (! STATUS_SUCCESS) \n", pIrp->IoStatus.Status));
        ASSERT(STATUS_SUCCESS == pIrp->IoStatus.Status);

    } else {
        IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
        pSrbToCancel = IsochDescriptorReserved->Srb;
        pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;

        IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;

        pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
        pSrbToCancel->ActualBytesTransferred = 0;
        pSrbToCancel->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED;

        DbgMsg2(("DCamCancelOnePacketCR: SRB %x, Status %x, IsochDesc %x, Reserved %x cancelled\n",
            pSrbToCancel, pSrbToCancel->Status, IsochDescriptor, IsochDescriptorReserved));

        StreamClassStreamNotification(
            StreamRequestComplete,
            pSrbToCancel->StreamObject,
            pSrbToCancel);

        ExFreePool(IsochDescriptor);
    }

    // Allocated locally so free it.
    IoFreeIrp(pIrp);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID
DCamDetachAndCancelOnePacket(
    IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel,
    PISOCH_DESCRIPTOR           IsochDescriptorToDetach,
    HANDLE                      hResource,
    PDEVICE_OBJECT              pBusDeviceObject
    )
/*++

Routine Description:

    Detach an isoch descriptor and then cancel pending SRB in the completion routine.

Arguments:

    pSrbToCancel - Pointer to SRB to cancel
    IsochDescriptorToDetach - Iosch descriptor to detach
    hResource - isoch resource allocated
    hBusDeviceObject - bus device object

Return Value:

    None.

--*/
{
    PDCAM_EXTENSION pDevExt;
    PIO_STACK_LOCATION NextIrpStack;
    NTSTATUS Status;
    PIRB     pIrb;
    PIRP     pIrp;


    DbgMsg2(("\'DCamDetachAndCancelOnePacket: pSrbTocancel %x, detaching IsochDescriptorToDetach %x\n", pSrbToCancel, IsochDescriptorToDetach));

    pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
    pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
    ASSERT(pIrp);
    if(!pIrp)
        return;

    pIrb = pSrbToCancel->SRBExtension;

    pIrb->Flags           = 0;
    pIrb->FunctionNumber  = REQUEST_ISOCH_DETACH_BUFFERS;
    pIrb->u.IsochDetachBuffers.hResource            = hResource;
    pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
    pIrb->u.IsochDetachBuffers.pIsochDescriptor     = IsochDescriptorToDetach;

    NextIrpStack = IoGetNextIrpStackLocation(pIrp);
    NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
    NextIrpStack->Parameters.Others.Argument1 = pIrb;

    IoSetCompletionRoutine(
        pIrp,
        DCamCancelOnePacketCR,
        IsochDescriptorToDetach,
        TRUE,
        TRUE,
        TRUE
        );

    Status =
        IoCallDriver(
            pBusDeviceObject,
            pIrp
            );

    ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
}


VOID
DCamCancelOnePacket(
    IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel
    )
/*++

Routine Description:

    This routine is called to cancel a pending streaming SRB.  This is likely to
    happen when transitioning from PAUSE to STOP state.
    Note: This routine is called at DISPATCH_LEVEL !!

Arguments:

    pSrbToCancel - Pointer to SRB to cancel

Return Value:

    None.

--*/
{
    PHW_STREAM_REQUEST_BLOCK pSrbInQ;
    PISOCH_DESCRIPTOR        IsochDescriptorToDetach;

    PDCAM_EXTENSION pDevExt;
    PSTREAMEX       pStrmEx;
    PLIST_ENTRY     pEntry;  // Pointer to an isoch decriptor reserved structure

    KIRQL oldIrql;
    BOOL  Found;


    pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
    ASSERT(pDevExt);
    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
    ASSERT(pStrmEx);

    // Nothing to cancel
    if(pStrmEx == NULL) {
        return;
    }


    //
    // We only expect stream SRB, but not device SRB.
    //
    if ( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
        ERROR_LOG(("DCamCancelOnePacket: Cannot cancel Device SRB %x\n", pSrbToCancel));
        ASSERT( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) == SRB_HW_FLAGS_STREAM_REQUEST );
        return;
    }


    //
    // Loop through the linked list from the beginning to end,
    // trying to find the SRB to cancel
    //
    KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);

    Found = FALSE;
    pEntry = pDevExt->IsochDescriptorList.Flink;

    while (pEntry != &pDevExt->IsochDescriptorList) {

        pSrbInQ = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
        IsochDescriptorToDetach = \
            (PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
            FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));

        if(pSrbToCancel == pSrbInQ) {
            // If we are in RUN state, we could be competing with IsochCallback;
            // Whichever grabs and change STATE_DETACHING_BUFFERS will detach.
            if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
                Found = FALSE; // IsochCallback are detaching it (we lost our chance).
                ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x, Descriptor %x,  Reserved %x already detaching or completed\n",
                    pSrbToCancel, IsochDescriptorToDetach, pEntry));

            } else {
                ((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags |= STATE_DETACHING_BUFFERS;
#if DBG
                // Should not have been detached.
                ASSERT((IsochDescriptorToDetach->DeviceReserved[7] == 0x87654321));
                IsochDescriptorToDetach->DeviceReserved[7]++;
#endif
                RemoveEntryList(pEntry);
                InterlockedDecrement(&pDevExt->PendingReadCount);
                Found = TRUE;
            }
            break;
        }

        pEntry = pEntry->Flink;  // Next
    }
    KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);


    //
    // Since we are in DISPATCH level, we cannot do sync operation;
    // so we will complete this asynchronously in the completion routine.
    //
    if (Found) {

        DCamDetachAndCancelOnePacket(
            pSrbToCancel,
            IsochDescriptorToDetach,
            pDevExt->hResource,
            pDevExt->BusDeviceObject);

    } else {
        ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x is not in our list!\n", pSrbToCancel));
        ASSERT(Found);
    }
}

VOID
DCamCancelAllPackets(
    PHW_STREAM_REQUEST_BLOCK pSrb,
    PDCAM_EXTENSION pDevExt,
    LONG *plPendingReadCount
    )
/*++

Routine Description:

    This routine is use to cancel all pending IRP.
    Can be called at DISPATCH_LEVEL.

Arguments:

    pSrbToCancel - Pointer to SRB to cancel
    pDevExt - Device's contect
    plPendingReadCount - Number of pending read

Return Value:

    None.

--*/
{
    PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
    PISOCH_DESCRIPTOR        IsochDescriptorToDetach;
    PLIST_ENTRY pEntry;
    KIRQL       oldIrql;

    PSTREAMEX pStrmEx;


    pStrmEx = pDevExt->pStrmEx;

    // Nothing to cancel
    if(pStrmEx == NULL) {
        return;
    }


    //
    // Loop through the linked list from the beginning to end,
    // trying to find the SRB to cancel
    //
    KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
    pEntry = pDevExt->IsochDescriptorList.Flink;

    while (pEntry != &pDevExt->IsochDescriptorList) {

        pSrbToCancel = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
        IsochDescriptorToDetach = \
            (PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
            FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));


        if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
            // Skip this one since it is already in detaching phase or completed.
            ERROR_LOG(("DCamCancelAllPacket: pSrbToCancel %x, Descriptor %x,  Reserved %x already detaching or completed\n",
                pSrbToCancel, IsochDescriptorToDetach, pEntry));

            pEntry = pEntry->Flink;  // next

        } else {
            ((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags |= STATE_DETACHING_BUFFERS;
#if DBG
            // Should not have been detached.
            ASSERT((IsochDescriptorToDetach->DeviceReserved[7] == 0x87654321));
            IsochDescriptorToDetach->DeviceReserved[7]++;
#endif
            RemoveEntryList(pEntry);
            InterlockedDecrement(plPendingReadCount);
            DbgMsg2(("DCamCancelAllPackets: pSrbToCancel %x, Descriptor %x, Reserved %x\n",
                pSrbToCancel, IsochDescriptorToDetach, pEntry));

            pEntry = pEntry->Flink;  // pEntry is deleted in DCamDetachAndCancelOnePacket(); so get next here.

            DCamDetachAndCancelOnePacket(
                pSrbToCancel,
                IsochDescriptorToDetach,
                pDevExt->hResource,
                pDevExt->BusDeviceObject);
        }
    }

    KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);


    pSrb->Status = STATUS_SUCCESS;
    DbgMsg1(("DCamCancelAllPackets: Complete pSrb %x, Status %x\n", pSrb, pSrb->Status));

    COMPLETE_SRB(pSrb)
}



VOID
DCamSurpriseRemoval(
    IN PHW_STREAM_REQUEST_BLOCK pSrb
    )

/*++

Routine Description:

    Response to SRB_SURPRISE_REMOVAL.

Arguments:

    pSrb - Pointer to the stream request block


Return Value:

    None.

--*/

{

    PIRP pIrp;
    PIRB pIrb;
    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;
    NTSTATUS Status, StatusWait;

    PAGED_CODE();

    pIrb = (PIRB) pSrb->SRBExtension;
    ASSERT(pIrb);
    pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
    ASSERT(pDevExt);

⌨️ 快捷键说明

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