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

📄 ctrlpkt.c

📁 1394 摄像头驱动程序源代码,学习驱动程序的人可以看看
💻 C
📖 第 1 页 / 共 2 页
字号:
        pStrmEx->FrameInfo.DropCount      = 0;     
        pStrmEx->FrameInfo.PictureNumber  = 0;
        pStrmEx->FrameInfo.dwFrameFlags   = 0;
       
        // Make it cancellable
        pStrmEx->CancelToken              = 0;

        // Advanced one frame.
        pStrmEx->FirstFrameTime           = pStrmEx->pVideoInfoHeader->AvgTimePerFrame; 
        DbgMsg2(("\'DCamSetKSStatePAUSE: FirstFrameTime(%d)\n", pStrmEx->FirstFrameTime));
        break;

    case KSSTATE_RUN:
    //
    // Will ask controll to stop listening.
    // All the pening buffer(s) are kept in the controller.
    // Before it completely stop (some latency here), 
    // we might get some IsochCallback() with data.
    //      
        if(!pDevExt->hResource) {
            pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

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

        // Set to KSSTATE_PAUSE at the beginning to prvent CancelPacket being processed thinking
        // it is still in KSSTATE_RUN state.
        pStrmEx->KSState            = KSSTATE_PAUSE;
        pDCamIoContext->DeviceState = DCAM_PAUSESTATE_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,
            DCamToPauseStateCR,
            pDCamIoContext,
            TRUE,
            TRUE,
            TRUE
            );

        Status =\
            IoCallDriver(
                pDevExt->BusDeviceObject,
                pIrp
                );
        return;  // Do StreamClassStreamNotification() in IoCompletionRoutine

    case KSSTATE_PAUSE:
        ERROR_LOG(("DCamSetKSStatePAUSE: Already in KSSTATE_PAUSE state.\n"));
        ASSERT(pStrmEx->KSState != KSSTATE_PAUSE);
        break;
    }     

    pStrmEx->KSState = KSSTATE_PAUSE;

    COMPLETE_SRB(pSrb)
}


IO_COMPLETION_ROUTINE DCamToRunStateCR;

NTSTATUS
DCamToRunStateCR(
    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;
    NTSTATUS Status;
    PIRB pIrb;
    PIO_STACK_LOCATION NextIrpStack;

    if(!pDCamIoContext) {
        return STATUS_MORE_PROCESSING_REQUIRED;
    }


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

    // Free MDL
    if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
        DbgMsg3(("DCamToRunStateCR: IoFreeMdl\n"));
        IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
    }

    //
    // CAUTION:
    //    STATUS_TIMEOUT can be a valid return that we may to try again.
    //    But should it be a HW issue that it is not responding to our write.
    //    Controller should have made many reties before return STATUS_TIMEOUT.
    //       
    if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
       if(DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN != pDCamIoContext->DeviceState ||
           STATUS_INSUFFICIENT_RESOURCES != pIrp->IoStatus.Status  ) {

            ERROR_LOG(("DCamToRunStateCR:  pIrp->IoStatus.Status=%x; free resoruce and STOP\n", pIrp->IoStatus.Status));
            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; 
        } else {
            //
            // This is OK:
            //   If we get an insufficient resources error that means
            //   we don't have any Reads down yet.  Set flag to TRUE
            //   indicating that when we do get a Read down we'll 
            //   actually need to begin the listening process.
            //
            pDevExt->bNeedToListen = TRUE;
            DbgMsg1(("DCamToRunStateCR: ##### no read yet! set pDevExt->bNeedToListen = TRUE\n"));
        }
    } 

#ifdef WAIT_FOR_SLOW_DEVICE
    KeStallExecutionProcessor(5000);  // 5 msec
#endif


    switch (pDCamIoContext->DeviceState) {   

    case DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN:
        //
        // Bit[24..26]0:0000 = CurrentFrameRate
        //
        pDCamIoContext->RegisterWorkArea.AsULONG = pDevExt->FrameRate << 5;
        DbgMsg2(("\'DCamToRunState: FrameRate %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
        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, CurrentVFrmRate);
        pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
        pIrb->u.AsyncWrite.nBlockSize = 0;
        pIrb->u.AsyncWrite.fulFlags = 0;
        InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
        break;

    case DCAM_RUNSTATE_SET_FRAME_RATE:
        //
        // Bit[24..26]0:0000 = CurrentVideoMode
        //
        pDCamIoContext->RegisterWorkArea.AsULONG = pDevExt->CurrentModeIndex << 5;
      DbgMsg2(("\'DCamToRunState: CurrentVideoMode %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =  
                  pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, CurrentVMode);
        break;

    case DCAM_RUNSTATE_SET_CURRENT_VIDEO_MODE:
        pDCamIoContext->RegisterWorkArea.AsULONG = FORMAT_VGA_NON_COMPRESSED;
      DbgMsg2(("\'DCamToRunState: VideoFormat %x\n", pDCamIoContext->RegisterWorkArea.AsULONG));
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =  
                  pDevExt->BaseRegister +  FIELDOFFSET(CAMERA_REGISTER_MAP, CurrentVFormat);
        break;

    case DCAM_RUNSTATE_SET_CURRENT_VIDEO_FORMAT:
        //
        // Bit [24..27]:00[30..31] = IsoChannel:00SpeedCode
        // 
        pDCamIoContext->RegisterWorkArea.AsULONG = (pDevExt->IsochChannel << 4) | pDevExt->SpeedCode;
      DbgMsg2(("\'DCamToRunState: pDevExt->SpeedCode 0x%x, Channel+SpeedCode %x\n", pDevExt->SpeedCode, pDCamIoContext->RegisterWorkArea.AsULONG));
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =  
                  pDevExt->BaseRegister +  FIELDOFFSET(CAMERA_REGISTER_MAP, IsoChannel);         
        break;

    case DCAM_RUNSTATE_SET_SPEED:
        //
        // Bit[24]000:0000 = start ? 1 : 0;
        //

        pDCamIoContext->RegisterWorkArea.AsULONG = START_ISOCH_TRANSMISSION;
        pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =  
                  pDevExt->BaseRegister +  FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable);         
        break;


    case DCAM_RUNSTATE_SET_START:
        pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;                  
        ASSERT(pStrmEx);
        pStrmEx->KSState = KSSTATE_RUN; 

        // If this is called from a SRB, then completed it.
        if(pDCamIoContext->pSrb) {
            pDCamIoContext->pSrb->Status = pIrp->IoStatus.Status == STATUS_SUCCESS ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 
            COMPLETE_SRB(pDCamIoContext->pSrb);
        }

        //
        // This is last stop; so
        // we free what we allocated.
        //
        DbgMsg2(("\'DCamToRunStateCR: DONE!\n"));
        DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
        return STATUS_MORE_PROCESSING_REQUIRED; 

    default:
        ERROR_LOG(("DCamToRunStateCR:DeviceState(%d) is not defined!\n\n", pDCamIoContext->DeviceState));        
        ASSERT(FALSE);
        return STATUS_MORE_PROCESSING_REQUIRED;
        
    }

    pDCamIoContext->DeviceState++;  // Keep track of device state that we just set.

    if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
        pIrb->u.AsyncWrite.Mdl = 
            IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
        MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);
    }


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

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

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

    DbgMsg2(("\'DCamToRunStateCR: IoCallDriver, Status=%x; STATUS_PENDING(%x)\n", Status, STATUS_PENDING));

    return STATUS_MORE_PROCESSING_REQUIRED;
}



VOID
DCamSetKSStateRUN(
    PDCAM_EXTENSION pDevExt,
    IN PHW_STREAM_REQUEST_BLOCK pSrb // Needed only to complete the SRB; for bus reset, there is no SRB.
    )
/*++

Routine Description:

    Set KSSTATE to KSSTATE_RUN.
    Can be called at DISPATCH level for initializing the device after a bus reset.

Arguments:

    pSrb - Pointer to Stream request block

Return Value:

    Nothing

--*/
{

    PSTREAMEX pStrmEx;
    PIRB pIrb;
    PIRP pIrp;
    PDCAM_IO_CONTEXT pDCamIoContext;
    PIO_STACK_LOCATION NextIrpStack;
    NTSTATUS Status;


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

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

    pStrmEx->KSStateFinal       = KSSTATE_RUN;
    pDCamIoContext->DeviceState = DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN;
    pDCamIoContext->pSrb        = pSrb;               // To do StreamClassStreamNotification()
    pDCamIoContext->pDevExt     = pDevExt;
    pIrb->FunctionNumber        = REQUEST_ISOCH_LISTEN;
    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;
          
    // In case we time out, we will try again; apply only to start listen;
    // With little change, it can work with other operation as well.
    pDevExt->lRetries = 0;

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

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



VOID
DCamReceiveCtrlPacket(
    IN PHW_STREAM_REQUEST_BLOCK pSrb
    )

/*++

Routine Description:

    Called with packet commands that control the video stream

Arguments:

    pSrb - Pointer to Stream request block

Return Value:

    Nothing

--*/

{

    PDCAM_EXTENSION pDevExt;
    PSTREAMEX pStrmEx;


    //
    // determine the type of packet.
    //

    PAGED_CODE();

    pSrb->Status = STATUS_SUCCESS;  // default; called functions depends on this.
    pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;     
    ASSERT(pDevExt);
    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
    ASSERT(pStrmEx);

    switch (pSrb->Command) {
    case SRB_GET_STREAM_STATE:         
         VideoGetState (pSrb);
         break;

    case SRB_SET_STREAM_STATE:   
         if(pStrmEx == NULL) {
            ERROR_LOG(("\'DCamReceiveCtrlPacket: SRB_SET_STREAM_STATE but pStrmEx is NULL.\n"));
            ASSERT(pStrmEx);
            pSrb->Status = STATUS_UNSUCCESSFUL;
            break;      
         }

         DbgMsg2(("\'DCamReceiveCtrlPacket: Setting state from %d to %d; PendingRead %d\n", 
                     pStrmEx->KSState, pSrb->CommandData.StreamState, pDevExt->PendingReadCount));               


         //
         // The control packet and data packet are not serialized by the stream class.
         // We need to watch for PAUSE->STOP transition.
         // In this transition, SRB_READ can still come in in a separate thread if
         // the client application has separate threads for setting state and read data.
         //
         // A "stop data packet" flag and a mutex is used for this synchronization.       
         // So we set "stop data packet" flag to stop future read, and
         // wait to own the mutex (if read is in progress) and then set stream to STOP state.
         // This "stop data packet" flag can be the stream state.
         //
         switch (pSrb->CommandData.StreamState) {
         case KSSTATE_STOP:
              DCamSetKSStateSTOP(pSrb);
              return;  // Complete Asynchronously in IoCompletionRoutine*

         case KSSTATE_PAUSE:
              DCamSetKSStatePAUSE(pSrb);
              return;  // Complete Asynchronously in IoCompletionRoutine*

         case KSSTATE_RUN:
              DCamSetKSStateRUN(pDevExt, pSrb);
              return;  // Complete Asynchronously in IoCompletionRoutine*

         case KSSTATE_ACQUIRE:
              pSrb->Status = STATUS_SUCCESS;
              break;

         default:
              ERROR_LOG(("\'DCamReceiveCtrlPacket: Error unknown state\n"));
              pSrb->Status = STATUS_NOT_IMPLEMENTED;
              break;
         }

         pStrmEx->KSState = pSrb->CommandData.StreamState;
         break;

    case SRB_GET_STREAM_PROPERTY:
         DbgMsg3(("\'DCamReceiveCtrlPacket: SRB_GET_STREAM_PROPERTY\n"));
         VideoGetProperty(pSrb);
         break;

    case SRB_INDICATE_MASTER_CLOCK:
         //
         // Assigns a clock to a stream
         //
         VideoIndicateMasterClock (pSrb);
         break;

    default:
         //
         // invalid / unsupported command. Fail it as such
         //    
         pSrb->Status = STATUS_NOT_IMPLEMENTED;    
         break;
    }

    StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
}

⌨️ 快捷键说明

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