📄 dcampkt.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:
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
#include "ntintsafe.h"
static
NTSTATUS
RTL_SAFE_KS_SIZE_VIDEOHEADER(const KS_VIDEOINFOHEADER* pvih, ULONG* pulSize)
{
return RtlULongAdd(pvih->bmiHeader.biSize, KS_SIZE_PREHEADER, pulSize);
}
#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
--*/
{
PSTREAMEX pStrmEx;
PAGED_CODE();
switch (IrpStack->MinorFunction) {
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;
case IRP_MN_QUERY_CAPABILITIES:
ERROR_LOG(("\'SonyDCamProcessPnpIrp: IRP_MN_QUERY_CAPABILITIES: Srb->Status = STATUS_NOT_IMPLEMENTED.\n"));
// Purposely pass thru
case IRP_MN_BUS_RESET: // no longer use; instead, Use bus reset callback to reclaim isoch resource.
default:
Srb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
VOID
DCamChangePower(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
/*++
Routine Description:
Process chnaging this device's power state.
Arguments:
Srb - Pointer to Stream request block
Return Value:
Nothing
--*/
{
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
DEVICE_POWER_STATE DevicePowerState = pSrb->CommandData.DeviceState;
PAGED_CODE();
pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
DbgMsg2(("\'DCamChangePower: pSrb=%x; pDevExt=%x\n", pSrb, pDevExt));
ASSERT(pDevExt != NULL);
if(!pDevExt) {
pSrb->Status = STATUS_INVALID_PARAMETER;
ERROR_LOG(("DCamChangePower: pDevExt is NULL!\n"));
return;
}
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
if (pStrmEx ==NULL) {
pSrb->Status = STATUS_SUCCESS;
pDevExt->CurrentPowerState = DevicePowerState;
DbgMsg2(("DCamChangePower: pStrmEx is NULL => Stream is not open. That is Ok!!\n"));
return;
}
//
// We can honor power state change:
//
// D0: device is on and running
// D1,D2: not implemented.
// D3: device is off and not running. Device context is lost.
// Power can be removed from the device.
// when power is back on, we will get a bus reset.
//
// (0) Remove DontSuspendIfStreamsAreRunning from INF
// save current state.
// (1) ->D3, to PAUSE/STOP state (depends on if pending buffers can be kept by its lower driver)
// (2) ->D0, to restore saved state
//
// We can do the above but we do not know at this point
// how our client application react
//
if(IrpStack->MinorFunction == IRP_MN_SET_POWER) {
DbgMsg2(("DCamChangePower: changin power state from %d to %d.\n", pDevExt->CurrentPowerState, DevicePowerState));
pSrb->Status = STATUS_SUCCESS;
if(pDevExt->CurrentPowerState != DevicePowerState) {
switch (DevicePowerState) {
case PowerDeviceD3: // D0->D3: save state, stop streaming and Sleep
if( pDevExt->CurrentPowerState == PowerDeviceD0 ) {
DbgMsg1(("DCamChangePower: Switching from D0 to D3; Save current state.\n"));
// Save current state to be restored when awake
pStrmEx->KSSavedState = pStrmEx->KSState;
}
break;
case PowerDeviceD0: // to Wakeup, restore state and running
if( pDevExt->CurrentPowerState == PowerDeviceD3 ) {
DbgMsg1(("DCamChangePower: Switching from D3 to D0; restore state.\n"));
pStrmEx->KSState = pStrmEx->KSSavedState;
}
break;
// These state are not defined and noe used.
case PowerDeviceD1:
case PowerDeviceD2:
default:
ERROR_LOG(("DCamChangePower: Invalid PowerState %d\n", DevicePowerState));
pSrb->Status = STATUS_INVALID_PARAMETER;
break;
}
}
if(pSrb->Status == STATUS_SUCCESS)
pDevExt->CurrentPowerState = DevicePowerState;
} else {
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
}
VOID
DCamGetStreamInfo(
IN PHW_STREAM_REQUEST_BLOCK Srb
)
/*++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -