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

📄 dcampkt.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 5 页
字号:
//===========================================================================
//
// 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:

    dcampkt.c

Abstract:

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

Author:
    
    Shaun Pierce 25-May-96

Modified:

    Yee J. Wu 15-Oct-97

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 "strmdata.h"  // stream format and data ranges; static data
#include "capprop.h"   // Video and camera property function prototype

#define WAIT_FOR_SLOW_DEVICE


#ifdef ALLOC_PRAGMA
    #pragma alloc_text(PAGE, DCamProcessPnpIrp)
    #pragma alloc_text(PAGE, DCamGetStreamInfo)
    #pragma alloc_text(PAGE, DCamFreeIsochResource)    
    #pragma alloc_text(PAGE, InitializeStreamExtension)    
    #pragma alloc_text(PAGE, DCamOpenStream)   
    #pragma alloc_text(PAGE, DCamCloseStream)           
    #pragma alloc_text(PAGE, AdapterCompareGUIDsAndFormatSize)    
    #pragma alloc_text(PAGE, AdapterVerifyFormat)    
    #pragma alloc_text(PAGE, AdapterFormatFromRange)    
    #pragma alloc_text(PAGE, VideoGetProperty)    
    #pragma alloc_text(PAGE, VideoGetState)    
    #pragma alloc_text(PAGE, VideoStreamGetConnectionProperty)    
    #pragma alloc_text(PAGE, VideoStreamGetDroppedFramesProperty)    
    #pragma alloc_text(PAGE, VideoIndicateMasterClock)    
    #pragma alloc_text(PAGE, DCamReceivePacket)
    #pragma alloc_text(PAGE, DCamChangePower)
#endif

void 
tmGetStreamTime(
    IN PHW_STREAM_REQUEST_BLOCK Srb,
    PSTREAMEX pStrmEx, 
    ULONGLONG * ptmStream) 
/*++

Routine Description:

   Query the current time used to timestamp the frame or calculating the dropped frame.
   This is used in IsochCallback so must be paged in always.

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/
{

    HW_TIME_CONTEXT TimeContext;

    TimeContext.HwDeviceExtension = (PVOID) Srb->HwDeviceExtension;
    TimeContext.HwStreamObject    = Srb->StreamObject;
    TimeContext.Function          = TIME_GET_STREAM_TIME;
    TimeContext.Time              = 0;
    TimeContext.SystemTime        = 0;

    StreamClassQueryMasterClockSync(
        pStrmEx->hMasterClock,
        &TimeContext);

    *ptmStream = TimeContext.Time;
}

BOOL
DCamAllocateIrbAndIrp(
    PIRB * ppIrb,
    PIRP * ppIrp,
    CCHAR StackSize
    )
{

    // Allocate Irb and Irp
    *ppIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
    if(!*ppIrb) {           
        return FALSE;
    }

    *ppIrp = IoAllocateIrp(StackSize, FALSE);
    if(!*ppIrp) {
        ExFreePool(*ppIrb);
        *ppIrb = NULL;
        return FALSE;
    }

    // Initialize IRB
    RtlZeroMemory(*ppIrb, sizeof(IRB));

    return TRUE;
}


BOOL
DCamAllocateIrbIrpAndContext(
    PDCAM_IO_CONTEXT * ppDCamIoContext,
    PIRB * ppIrb,
    PIRP * ppIrp,
    CCHAR StackSize
    )
{

    // Allocate DCamIoContext
    *ppDCamIoContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(DCAM_IO_CONTEXT), 'macd');
    if(!*ppDCamIoContext) {            
        return FALSE;
    }

    // Allocate Irb and Irp
    *ppIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
    if(!*ppIrb) {
        ExFreePool(*ppDCamIoContext);            
        *ppDCamIoContext = NULL;
        return FALSE;
    }

    *ppIrp = IoAllocateIrp(StackSize, FALSE);
    if(!*ppIrp) {
        ExFreePool(*ppDCamIoContext);
        *ppDCamIoContext = NULL;
        ExFreePool(*ppIrb);
        *ppIrb = NULL;
        return FALSE;
    }


    // Initialize this context
    RtlZeroMemory(*ppDCamIoContext, sizeof(DCAM_IO_CONTEXT));
    (*ppDCamIoContext)->dwSize      = sizeof(DCAM_IO_CONTEXT);
    (*ppDCamIoContext)->pIrb        = *ppIrb;

    // Initialize IRB
    RtlZeroMemory(*ppIrb, sizeof(IRB));

    return TRUE;
}

void
DCamFreeIrbIrpAndContext(
    PDCAM_IO_CONTEXT pDCamIoContext,
    PIRB pIrb,
    PIRP pIrp   
    )
{
    if(pIrp)
        IoFreeIrp(pIrp);
    if(pIrb)
        ExFreePool(pIrb);
    if(pDCamIoContext)
        ExFreePool(pDCamIoContext);
}


BOOL
DCamIsoEnable(
    PIRB pIrb,
    PDCAM_EXTENSION pDevExt,
    BOOL Enable  
    ) 
/*
    Start or start isoch transmission by setting the ISOEnable bit.
    TRUE: Start transmission; 
    FALSE: Stop transmission.
*/
{
    BOOL EnableVerify;
    DCamRegArea RegArea;
    NTSTATUS Status;
    LARGE_INTEGER stableTime;
    LONG lRetries = MAX_READ_REG_RETRIES;

    do {
        RegArea.AsULONG = (Enable ? START_ISOCH_TRANSMISSION : STOP_ISOCH_TRANSMISSION);
        Status = DCamWriteRegister(pIrb, pDevExt, FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable), RegArea.AsULONG);
        EnableVerify = DCamDeviceInUse(pIrb, pDevExt);
        if(!NT_SUCCESS(Status) || EnableVerify != Enable) {
            ERROR_LOG(("\'DCAmIsoEnable: St:%x; Enable:%d vs EnableVerify:%d\n", Status, Enable, EnableVerify));
            if(lRetries >= 1) {
                stableTime.LowPart = DCAM_REG_STABLE_DELAY;
                stableTime.HighPart = -1;
                KeDelayExecutionThread(KernelMode, TRUE, &stableTime);
                ERROR_LOG(("\'DCamIsoEnable: delayed and try again...\n"))
            }
        }
    } while (--lRetries > 0 && (!NT_SUCCESS(Status) || (EnableVerify != Enable)) );

    return (EnableVerify == Enable);
}

void
DCamProcessPnpIrp(
    IN PHW_STREAM_REQUEST_BLOCK Srb,
    PIO_STACK_LOCATION IrpStack,
    PDCAM_EXTENSION pDevExt
    )

/*++

Routine Description:

    Process PnP Irp. 

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/
{
    NTSTATUS Status, StatusWait;
    PIRB pIrb;
    PIRP pIrp;
    PSTREAMEX pStrmEx;

    PAGED_CODE();

    switch (IrpStack->MinorFunction) {
#if 1
    case IRP_MN_QUERY_POWER:
        pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
        ERROR_LOG(("IRP_MN_QUERY_POWER: pStrmEx:%x\n", pStrmEx));
        if(!pStrmEx) {
            Srb->Status = STATUS_SUCCESS;
            break;
        }

        if(pStrmEx->KSState == KSSTATE_PAUSE || pStrmEx->KSState == KSSTATE_RUN) {
            ERROR_LOG(("Does not support hibernation while streaming!\n"));
            Srb->Status = STATUS_NOT_SUPPORTED;
        } else {
            ERROR_LOG(("OK to hibernation if not streaming\n"));
            Srb->Status = STATUS_SUCCESS;
        }
        break;
#endif
    case IRP_MN_BUS_RESET:
    //
    // We will realocate the resource (bandwith and channel) in IRQL PASSIVE level.
    //
        Srb->Status = STATUS_SUCCESS;
        Status = STATUS_SUCCESS;

        //
        // The generation count is updated in the bus reset callback notification only.
        // Continue iff the generation count has been updated.
        // Else, we are assuming another bus reset has occurred,
        // and we will pass to us later.
        //
        if(pDevExt->CurrentGeneration != *((PULONG) &IrpStack->Parameters.Others.Argument4)) {
            ERROR_LOG(("DCamProcessPnpIrp: Generation count old (%d) != new (%d); STOP!\n", 
               pDevExt->CurrentGeneration, *((PULONG) &IrpStack->Parameters.Others.Argument4)) );
            break;
        }

        pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
        DbgMsg2(("\'%d:%s) SonyDCamProcessPnpIrp: pDevExt %x; pStrmEx %x; CurGen %d\n", 
            pDevExt->idxDev, pDevExt->pchVendorName, pDevExt, pStrmEx, pDevExt->CurrentGeneration));

        //
        // If the stream was open (pStrmEx != NULL && pStrmEx->pVideoInfoHeader != NULL);
        // We need to ask controller to allocate bandwidth and channel. 
        //
        if(pStrmEx &&
           pStrmEx->pVideoInfoHeader != NULL) {

            DbgMsg2(("\'%d:%s) DCamProcessPnpIrp: Stream was open so re-allocate resource.\n", pDevExt->idxDev, pDevExt->pchVendorName));


            // Allocate Irb 
            pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
            if(!pIrb) {            
                ERROR_LOG(("\'DCamProcessPnpIrp: allocate IRB failed; insufficient resource.\n"));
                Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            } else {
                ULONG ulChannel;
                HANDLE hResource;

                pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
                if(!pIrp) {
                    ExFreePool(pIrb);
                    Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
                    break;
                }

                RtlZeroMemory(pIrb, sizeof(IRB));

                //
                // Bus reset will free the bandwidth but not the bandwidth structure allocated by the lower driver                
                //
                if (pDevExt->hBandwidth) {

                    DbgMsg2(("\'DCamProcessPnpIrp: Attempt to free ->hBandwidth\n"));

                    pIrb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
                    pIrb->Flags = 0;
                    pIrb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
                    Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);

                    if (Status) {
                        ERROR_LOG(("DCamProcessPnpIrp: Error %x while trying to free Isoch bandwidth\n", Status));
                        ASSERT(Status == STATUS_SUCCESS || Status ==  STATUS_INVALID_GENERATION);
                    }

                    pDevExt->hBandwidth = NULL;
                }


                //
                // Before we assign the new hResource, we wait for it attaching buffer to complete.
                // For buffer that completed with previous hResource,
                // It will complete with error ?
                //

                StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 ); 


                //
                // Reallocate bandwidth and channel, and resource if necessary.
                // IF THIS FAIL, we are consider illegally streaming, and need to STOP streaming.
                //

                ulChannel = pDevExt->IsochChannel;
                hResource = pDevExt->hResource;

                Status = DCamAllocateIsochResource(pDevExt, pIrb, FALSE);
 
                if(Status) {

                    ERROR_LOG(("\'%d:%s) DCamProcessPnpIrp: Re-AllocateIsochResource failed! Status=%x; Treat as device removed.\n\n", 
                        pDevExt->idxDev, pDevExt->pchVendorName, Status));
                    ASSERT(Status == STATUS_SUCCESS);

                    //
                    // No resource so let's treat this situation as
                    // Device has been removed because there is no
                    // way to restart this.
                    // This will stop future SRB_READ until stream is STOP and RUN again.
                    //

                    pDevExt->bDevRemoved = TRUE;                   
                    Srb->Status = STATUS_INSUFFICIENT_RESOURCES;

                    // 
                    // Stop tranmission so it will not send data to the old channel,
                    // which might be "owned" by other device.
                    //

                    if(pStrmEx->KSState == KSSTATE_RUN) {
                        // Disable EnableISO
                        DCamIsoEnable(pIrb, pDevExt, FALSE);
                    }

                    KeReleaseMutex(&pStrmEx->hMutex, FALSE);                
                    ExFreePool(pIrb);
                    IoFreeIrp(pIrp);
                    return;
                }

                //
                // If channel number change due to bus reset, we must
                //    - continue to blocking incoming SRB_READ (with mutex)
                //    - if RUN state, stop transmission
                //    - detach all pending buffer(s)
                //    - free "stale" isoch resource
                //    - if RUN state, program device to use the new channel
                //    - if RUN state, restart transmission
                //

                if(pDevExt->IsochChannel != ISOCH_ANY_CHANNEL &&

⌨️ 快捷键说明

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