📄 ctrlpkt.c
字号:
//===========================================================================
//
// 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 + -