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

📄 ctrlpkt.c

📁 1394 摄像头驱动程序源代码,学习驱动程序的人可以看看
💻 C
📖 第 1 页 / 共 2 页
字号:
//===========================================================================
//
// 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:

    CtrlPkt.c

Abstract:

    Stream class based WDM driver for 1934 Desktop Camera.
    This file contains code to handle the stream class control 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"

#define WAIT_FOR_SLOW_DEVICE

#ifdef ALLOC_PRAGMA   
     #pragma alloc_text(PAGE, DCamSetKSStateSTOP)
     #pragma alloc_text(PAGE, DCamSetKSStatePAUSE)
     #pragma alloc_text(PAGE, DCamReceiveCtrlPacket)
#endif

IO_COMPLETION_ROUTINE DCamToStopStateCR;

NTSTATUS
DCamToStopStateCR(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp,
    IN PDCAM_IO_CONTEXT pDCamIoContext
    )
/*++

Routine Description:

    
    This is the state machine to set the streaming state to STOP.
    It start at PASSIVE_LEVEL and the lower driver may have raised it to DISPATCH_LEVEL.

Arguments:

    DriverObject - Pointer to driver object created by system.

    pIrp - Irp that just completed

    pDCamIoContext - A structure that contain the context of this IO completion routine.

Return Value:

    None.

--*/

{
    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;
    NTSTATUS Status;
    PIRB pIrb;
    PIO_STACK_LOCATION NextIrpStack;
    PIO_WORKITEM pIOWorkItem;



    if(!pDCamIoContext) {
        return STATUS_MORE_PROCESSING_REQUIRED;
    }

#if DBG
    if( KeGetCurrentIrql() < DISPATCH_LEVEL ) {
        ERROR_LOG( ( "[%s] DevState:%d raised IRQL:%d by callback\n", __FUNCTION__, pDCamIoContext->DeviceState, KeGetCurrentIrql() ) );
    }
#endif


    pIrb    = pDCamIoContext->pIrb;
    pDevExt = pDCamIoContext->pDevExt;
    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;    

    DbgMsg2(("\'DCamToStopStateCR: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n", 
        pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
    
    // Free MDL
    if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
        DbgMsg3(("DCamToStopStateCR: IoFreeMdl\n"));
        IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
    }


    // Return error status and free resoruce.
    if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
        if(pDCamIoContext->pSrb) {
            ERROR_LOG(("DCamToStopStateCR: pIrp->IoStatus.Status %x; cancel all packets\n", pIrp->IoStatus.Status));
            // In order to stop streaming, we must cancel all pending IRPs
            // Cancel pending IRPS and complete SRB.
            if( InterlockedExchange( &pStrmEx->CancelToken, 1 ) == 0 ) {

                //
                // Start a work item to cancel all pending request
                //
                pIOWorkItem = IoAllocateWorkItem( pDevExt ->PhysicalDeviceObject );

                if( !pIOWorkItem ) {
                    // Could not do it, release the token.
                    InterlockedExchange( &pStrmEx->CancelToken, 0 );
                }
                else {
                    IoQueueWorkItem( pIOWorkItem, AbortWorkItem, DelayedWorkQueue, pDevExt );
                }
            }
            COMPLETE_SRB( pDCamIoContext->pSrb );
        }
        DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
        return STATUS_MORE_PROCESSING_REQUIRED; 
    } 

    switch (pDCamIoContext->DeviceState) {   

    case DCAM_STOPSTATE_SET_REQUEST_ISOCH_STOP:
    //
    // Now stop the stream at the device itself
    //
        // Next state:
        pDCamIoContext->DeviceState = DCAM_STOPSTATE_SET_STOP_ISOCH_TRANSMISSION;  // Keep track of device state that we just set.

        pDCamIoContext->RegisterWorkArea.AsULONG = STOP_ISOCH_TRANSMISSION;
        pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
        pIrb->Flags = 0;
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =  
              pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable);
        pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
        pIrb->u.AsyncWrite.nBlockSize = 0;
        pIrb->u.AsyncWrite.fulFlags = 0;
        InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
        
        pIrb->u.AsyncWrite.Mdl = 
            IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
        MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);

        // Set once and used again in the completion routine.
        NextIrpStack = IoGetNextIrpStackLocation(pIrp);
        NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
        NextIrpStack->Parameters.Others.Argument1 = pIrb;

        IoSetCompletionRoutine(
            pIrp,
            DCamToStopStateCR,
            pDCamIoContext,
            TRUE,
            TRUE,
            TRUE
            );

        Status = 
            IoCallDriver(
                pDevExt->BusDeviceObject,
                pIrp
                );
        return STATUS_MORE_PROCESSING_REQUIRED; 
        

    case DCAM_STOPSTATE_SET_STOP_ISOCH_TRANSMISSION:
    //
    // Detach all buffers that might still be attached.
    //
        DbgMsg2(("\'DCamToStopStateCR: IsListEmpty()=%s; PendingRead=%d\n",
            IsListEmpty(&pDevExt->IsochDescriptorList) ? "Yes" : "No", pDevExt->PendingReadCount));

        if(pDCamIoContext->pSrb) {
            //
            // Cancel all pending and waiting buffers;
            // and Complete DCamSetKSStateSTOP's SRB
            //
            if( InterlockedExchange( &pStrmEx->CancelToken, 1 ) == 0 ) {
                //
                // Start a work item to cancel all pending request
                //
                pIOWorkItem = IoAllocateWorkItem( pDevExt ->PhysicalDeviceObject );

                if( !pIOWorkItem ) {
                    // Could not do it, release the token.
                    InterlockedExchange( &pStrmEx->CancelToken, 0 );
                }
                else {
                    IoQueueWorkItem( pIOWorkItem, AbortWorkItem, DelayedWorkQueue, pDevExt );
                }
            }

            COMPLETE_SRB( pDCamIoContext->pSrb );
            DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
            return STATUS_MORE_PROCESSING_REQUIRED; 

        } else {
            ERROR_LOG(("DCamToStopStateCR:CanNOT call DCamCancelPacket() with a null pSrb\n"));
        }

        break;

    default:
        ERROR_LOG(("\'DCamToStopStateCR: Unknown pDCamIoContext->DeviceState=%d\n", pDCamIoContext->DeviceState));
        ASSERT(FALSE);
        break;
    }

    if(pDCamIoContext->pSrb) {
        pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;        
        COMPLETE_SRB(pDCamIoContext->pSrb)  
    }
    DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);


    return STATUS_MORE_PROCESSING_REQUIRED; 

}



VOID
DCamSetKSStateSTOP(
    IN PHW_STREAM_REQUEST_BLOCK pSrb
    )

/*++

Routine Description:

    Into STOP streaming state.
       (1) Stop device from steaming (!ISO_ENABLE)
       (2) Stop listening (controller)
       (3) Detach pending read buffer and return with Cancel, and 
           start the waiting read to be put into the pengin read and then Cancel.

Arguments:

    pSrb - Pointer to Stream request block

Return Value:

    Nothing

--*/

{

    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;
    PIRB pIrb;
    PIRP pIrp;
    PDCAM_IO_CONTEXT pDCamIoContext;
    PIO_STACK_LOCATION NextIrpStack;
    NTSTATUS Status, StatusWait;

    PAGED_CODE();

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


    DbgMsg1(("\'DCamSetKSStateSTOP: Frame captured:%d\n", (DWORD) pStrmEx->FrameCaptured));
    //
    // After this, no more read will be accepted.
    //
    pStrmEx->KSState = KSSTATE_STOP;


    //
    // First stop the stream internally inside the PC's 1394
    // stack
    //
    if(!pDevExt->hResource) {
        pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
        COMPLETE_SRB(pSrb)
        return;
    }

    //
    // Wait for last read to complete.  
    // After KState == KSSTATE_STOP, we will return all SRB_READ.
    //
    StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );  
    KeReleaseMutex(&pStrmEx->hMutex, FALSE);


    if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
        pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
        COMPLETE_SRB(pSrb)
        return;
    } 

    pDCamIoContext->DeviceState = DCAM_STOPSTATE_SET_REQUEST_ISOCH_STOP;
    pDCamIoContext->pSrb        = pSrb;               // To do StreamClassStreamNotification()
    pDCamIoContext->pDevExt     = pDevExt;
    pIrb->FunctionNumber        = REQUEST_ISOCH_STOP;
    pIrb->Flags                 = 0;
    pIrb->u.IsochStop.hResource = pDevExt->hResource;
    pIrb->u.IsochStop.fulFlags  = 0;

    NextIrpStack = IoGetNextIrpStackLocation(pIrp);
    NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
    NextIrpStack->Parameters.Others.Argument1 = pIrb;
      
    IoSetCompletionRoutine(
        pIrp,
        DCamToStopStateCR,
        pDCamIoContext,
        TRUE,
        TRUE,
        TRUE
        );

    Status = 
        IoCallDriver(
            pDevExt->BusDeviceObject,
            pIrp
            );

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

    return;  // Do StreamClassStreamNotification() in IoCompletionRoutine
}

IO_COMPLETION_ROUTINE DCamToPauseStateCR;

NTSTATUS
DCamToPauseStateCR(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp,
    IN PDCAM_IO_CONTEXT pDCamIoContext
    )

/*++

Routine Description:

    This routine is for use with synchronous IRP processing.  
    All it does is signal an event, so the driver knows it
    can continue.

Arguments:

    DriverObject - Pointer to driver object created by system.

    pIrp - Irp that just completed

    pDCamIoContext - A structure that contain the context of this IO completion routine.

Return Value:

    None.

--*/

{
    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;
    PIRB pIrb;

    if(!pDCamIoContext) {
        return STATUS_MORE_PROCESSING_REQUIRED;
    }

    pIrb    = pDCamIoContext->pIrb;
    pDevExt = pDCamIoContext->pDevExt;
    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;                  
    ASSERT(pStrmEx);

    DbgMsg2(("\'DCamToPauseStateCR: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n", 
        pDCamIoContext->DeviceState, pIrp->IoStatus.Status));

    // No reason it would failed.
    ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);

    switch (pDCamIoContext->DeviceState) {   

    case DCAM_PAUSESTATE_SET_REQUEST_ISOCH_STOP:
         break;
    default:
         ERROR_LOG(("DCamToPauseStateCompletionRoutine: Unknown or unexpected pDCamIoContext->DeviceState=%d\n", pDCamIoContext->DeviceState)); 
         ASSERT(FALSE);
         break;
    }

    //
    // We are here only if switching from RUN->PAUSE,
    // It is alreay set to PAUSE state in DCamSetKSStatePAUSE
    //



    if(pDCamIoContext->pSrb) {
        pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 
        COMPLETE_SRB(pDCamIoContext->pSrb)
    }

    DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
    return STATUS_MORE_PROCESSING_REQUIRED;     

}




VOID
DCamSetKSStatePAUSE(
    IN PHW_STREAM_REQUEST_BLOCK pSrb
    )
/*++

Routine Description:

    Set KSSTATE to KSSTATE_PAUSE.

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/
{
    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;
    PIRB pIrb;
    PIRP pIrp;
    PDCAM_IO_CONTEXT pDCamIoContext;
    PIO_STACK_LOCATION NextIrpStack;
    NTSTATUS Status;

    PAGED_CODE();

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

    pSrb->Status = STATUS_SUCCESS;

    switch(pStrmEx->KSState) {
    case KSSTATE_ACQUIRE:
    case KSSTATE_STOP:
    //
    // Out of STOP state, 
    // initialize frame and timestamp information.  
    // (Master's clock's stream time is also reset.)
    //
        pStrmEx->FrameCaptured            = 0;     // Actual count

⌨️ 快捷键说明

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