1968 lines
56 KiB
C
1968 lines
56 KiB
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) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
|
||
//
|
||
//==========================================================================;
|
||
|
||
#include "strmini.h"
|
||
#include "ksmedia.h"
|
||
#include "capmain.h"
|
||
#include "mediums.h"
|
||
#include "capstrm.h"
|
||
#include "capprop.h"
|
||
#include "capdebug.h"
|
||
#ifdef TOSHIBA
|
||
#include "bert.h"
|
||
|
||
ULONG CurrentOSType; // 0:Win98 1:NT5.0
|
||
#endif//TOSHIBA
|
||
|
||
#ifdef TOSHIBA
|
||
VOID
|
||
DevicePowerON (
|
||
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
DWORD dwAddr;
|
||
|
||
CameraChkandON(pHwDevExt, MODE_VFW);
|
||
VC_Delay(100);
|
||
ImageSetInputImageSize(pHwDevExt, &(pHwDevExt->SrcRect));
|
||
ImageSetOutputImageSize(pHwDevExt, pHwDevExt->ulWidth, pHwDevExt->ulHeight);
|
||
BertFifoConfig(pHwDevExt, pHwDevExt->Format);
|
||
ImageSetHueBrightnessContrastSat(pHwDevExt);
|
||
if ( pHwDevExt->ColorEnable ) {
|
||
if ( get_AblFilter( pHwDevExt ) ) {
|
||
set_filtering( pHwDevExt, TRUE );
|
||
} else {
|
||
set_filtering( pHwDevExt, FALSE );
|
||
pHwDevExt->ColorEnable = 0;
|
||
}
|
||
} else {
|
||
set_filtering( pHwDevExt, FALSE );
|
||
}
|
||
dwAddr = (DWORD)pHwDevExt->pPhysRpsDMABuf.LowPart;
|
||
#if 0
|
||
dwAddr = (dwAddr + 0x1FFF) & 0xFFFFE000;
|
||
#endif
|
||
pHwDevExt->s_physDmaActiveFlag = dwAddr + 0X1860;
|
||
|
||
if( pHwDevExt->dblBufflag ){
|
||
BertTriBuildNodes(pHwDevExt); // Add 97-04-08(Tue)
|
||
}
|
||
else{
|
||
BertBuildNodes(pHwDevExt); // Add 97-04-08(Tue)
|
||
}
|
||
pHwDevExt->IsRPSReady = TRUE;
|
||
BertInterruptEnable(pHwDevExt, TRUE);
|
||
BertDMARestart(pHwDevExt);
|
||
}
|
||
|
||
VOID
|
||
CameraPowerON (
|
||
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
|
||
CameraChkandON(pHwDevExt, MODE_VFW);
|
||
VC_Delay(100);
|
||
}
|
||
|
||
VOID
|
||
CameraPowerOFF (
|
||
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
|
||
CameraChkandOFF(pHwDevExt, MODE_VFW);
|
||
}
|
||
|
||
VOID
|
||
QueryOSTypeFromRegistry()
|
||
{
|
||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
LONG RegVals[2];
|
||
PLONG pRegVal;
|
||
WCHAR BasePath[] = L"\\Registry\\MACHINE\\SOFTWARE\\Toshiba\\Tsbvcap";
|
||
RTL_QUERY_REGISTRY_TABLE Table[2];
|
||
UNICODE_STRING RegPath;
|
||
|
||
//
|
||
// Get the actual values for the controls
|
||
//
|
||
|
||
RtlZeroMemory (Table, sizeof(Table));
|
||
|
||
CurrentOSType = 1; // Assume NT5.0
|
||
RegVals[0] = CurrentOSType;
|
||
|
||
pRegVal = RegVals; // for convenience sake
|
||
RegPath.Buffer = BasePath;
|
||
#ifdef TOSHIBA // '99-01-08 Modified
|
||
RegPath.MaximumLength = sizeof(BasePath) + (32 * sizeof(WCHAR)); //32 chars for keys
|
||
#else //TOSHIBA
|
||
RegPath.MaximumLength = sizeof(BasePath + 32); //32 chars for keys
|
||
#endif//TOSHIBA
|
||
RegPath.Length = 0;
|
||
|
||
Table[0].Name = L"CurrentOSType";
|
||
Table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[0].EntryContext = pRegVal++;
|
||
|
||
ntStatus = RtlQueryRegistryValues(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
Table,
|
||
NULL,
|
||
NULL );
|
||
|
||
if( NT_SUCCESS(ntStatus))
|
||
{
|
||
CurrentOSType = RegVals[0];
|
||
}
|
||
}
|
||
|
||
VOID
|
||
QueryControlsFromRegistry(
|
||
PHW_DEVICE_EXTENSION pHwDevExt
|
||
)
|
||
{
|
||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
LONG RegVals[6];
|
||
PLONG pRegVal;
|
||
WCHAR BasePath[] = L"\\Registry\\MACHINE\\SOFTWARE\\Toshiba\\Tsbvcap";
|
||
RTL_QUERY_REGISTRY_TABLE Table[6];
|
||
UNICODE_STRING RegPath;
|
||
|
||
//
|
||
// Get the actual values for the controls
|
||
//
|
||
|
||
RtlZeroMemory (Table, sizeof(Table));
|
||
|
||
RegVals[0] = pHwDevExt->Brightness;
|
||
RegVals[1] = pHwDevExt->Contrast;
|
||
RegVals[2] = pHwDevExt->Hue;
|
||
RegVals[3] = pHwDevExt->Saturation;
|
||
RegVals[4] = pHwDevExt->ColorEnable;
|
||
|
||
pRegVal = RegVals; // for convenience sake
|
||
RegPath.Buffer = BasePath;
|
||
#ifdef TOSHIBA // '99-01-08 Modified
|
||
RegPath.MaximumLength = sizeof(BasePath) + (32 * sizeof(WCHAR)); //32 chars for keys
|
||
#else //TOSHIBA
|
||
RegPath.MaximumLength = sizeof(BasePath + 32); //32 chars for keys
|
||
#endif//TOSHIBA
|
||
RegPath.Length = 0;
|
||
|
||
Table[0].Name = L"Brightness";
|
||
Table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[0].EntryContext = pRegVal++;
|
||
|
||
Table[1].Name = L"Contrast";
|
||
Table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[1].EntryContext = pRegVal++;
|
||
|
||
Table[2].Name = L"Hue";
|
||
Table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[2].EntryContext = pRegVal++;
|
||
|
||
Table[3].Name = L"Saturation";
|
||
Table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[3].EntryContext = pRegVal++;
|
||
|
||
Table[4].Name = L"FilterEnable";
|
||
Table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
Table[4].EntryContext = pRegVal++;
|
||
|
||
ntStatus = RtlQueryRegistryValues(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
Table,
|
||
NULL,
|
||
NULL );
|
||
|
||
if( NT_SUCCESS(ntStatus))
|
||
{
|
||
pHwDevExt->Brightness = RegVals[0];
|
||
pHwDevExt->Contrast = RegVals[1];
|
||
pHwDevExt->Hue = RegVals[2];
|
||
pHwDevExt->Saturation = RegVals[3];
|
||
pHwDevExt->ColorEnable = RegVals[4];
|
||
}
|
||
}
|
||
|
||
VOID
|
||
SaveControlsToRegistry(
|
||
PHW_DEVICE_EXTENSION pHwDevExt
|
||
)
|
||
{
|
||
LONG Value;
|
||
WCHAR BasePath[] = L"\\Registry\\MACHINE\\SOFTWARE\\Toshiba\\Tsbvcap";
|
||
UNICODE_STRING RegPath;
|
||
|
||
|
||
RegPath.Buffer = BasePath;
|
||
#ifdef TOSHIBA // '99-01-08 Modified
|
||
RegPath.MaximumLength = sizeof(BasePath) + (32 * sizeof(WCHAR)); //32 chars for keys
|
||
#else //TOSHIBA
|
||
RegPath.MaximumLength = sizeof(BasePath + 32); //32 chars for keys
|
||
#endif//TOSHIBA
|
||
RegPath.Length = 0;
|
||
|
||
Value = pHwDevExt->Brightness;
|
||
RtlWriteRegistryValue(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
L"Brightness",
|
||
REG_DWORD,
|
||
&Value,
|
||
sizeof (ULONG));
|
||
|
||
Value = pHwDevExt->Contrast;
|
||
RtlWriteRegistryValue(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
L"Contrast",
|
||
REG_DWORD,
|
||
&Value,
|
||
sizeof (ULONG));
|
||
|
||
Value = pHwDevExt->Hue;
|
||
RtlWriteRegistryValue(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
L"Hue",
|
||
REG_DWORD,
|
||
&Value,
|
||
sizeof (ULONG));
|
||
|
||
Value = pHwDevExt->Saturation;
|
||
RtlWriteRegistryValue(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
L"Saturation",
|
||
REG_DWORD,
|
||
&Value,
|
||
sizeof (ULONG));
|
||
|
||
Value = pHwDevExt->ColorEnable;
|
||
RtlWriteRegistryValue(
|
||
RTL_REGISTRY_ABSOLUTE,
|
||
RegPath.Buffer,
|
||
L"FilterEnable",
|
||
REG_DWORD,
|
||
&Value,
|
||
sizeof (ULONG));
|
||
}
|
||
#endif//TOSHIBA
|
||
|
||
/*
|
||
** DriverEntry()
|
||
**
|
||
** This routine is called when the driver is first loaded by PnP.
|
||
** It in turn, calls upon the stream class to perform registration services.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** DriverObject -
|
||
** Driver object for this driver
|
||
**
|
||
** RegistryPath -
|
||
** Registry path string for this driver's key
|
||
**
|
||
** Returns:
|
||
**
|
||
** Results of StreamClassRegisterAdapter()
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
ULONG
|
||
DriverEntry (
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
{
|
||
|
||
HW_INITIALIZATION_DATA HwInitData;
|
||
ULONG ReturnValue;
|
||
|
||
|
||
KdPrint(("TsbVcap: DriverEntry\n"));
|
||
|
||
RtlZeroMemory(&HwInitData, sizeof(HwInitData));
|
||
|
||
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
|
||
|
||
//
|
||
// Set the Adapter entry points for the driver
|
||
//
|
||
|
||
#ifdef TOSHIBA
|
||
QueryOSTypeFromRegistry();
|
||
|
||
HwInitData.HwInterrupt = HwInterrupt;
|
||
#else //TOSHIBA
|
||
HwInitData.HwInterrupt = NULL; // HwInterrupt;
|
||
#endif//TOSHIBA
|
||
|
||
HwInitData.HwReceivePacket = AdapterReceivePacket;
|
||
HwInitData.HwCancelPacket = AdapterCancelPacket;
|
||
HwInitData.HwRequestTimeoutHandler = AdapterTimeoutPacket;
|
||
|
||
HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
|
||
HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION);
|
||
HwInitData.FilterInstanceExtensionSize = 0;
|
||
HwInitData.PerStreamExtensionSize = sizeof(STREAMEX);
|
||
HwInitData.BusMasterDMA = FALSE;
|
||
HwInitData.Dma24BitAddresses = FALSE;
|
||
HwInitData.BufferAlignment = 3;
|
||
#ifdef TOSHIBA
|
||
if ( CurrentOSType ) { // NT5.0
|
||
HwInitData.DmaBufferSize = 8192 * 2;
|
||
} else {
|
||
HwInitData.DmaBufferSize = 8192 * 2 + MAX_CAPTURE_BUFFER_SIZE;
|
||
}
|
||
#else //TOSHIBA
|
||
HwInitData.DmaBufferSize = 0;
|
||
#endif//TOSHIBA
|
||
|
||
// Don't rely on the stream class using raised IRQL to synchronize
|
||
// execution. This single paramter most affects the overall structure
|
||
// of the driver.
|
||
|
||
HwInitData.TurnOffSynchronization = TRUE;
|
||
|
||
ReturnValue = StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
|
||
|
||
KdPrint(("TsbVcap: StreamClassRegisterAdapter = %x\n", ReturnValue));
|
||
|
||
return ReturnValue;
|
||
}
|
||
|
||
//==========================================================================;
|
||
// Adapter Based Request Handling Routines
|
||
//==========================================================================;
|
||
|
||
/*
|
||
** HwInitialize()
|
||
**
|
||
** This routine is called when an SRB_INITIALIZE_DEVICE request is received
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block for the Initialize command
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOL
|
||
STREAMAPI
|
||
HwInitialize (
|
||
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
STREAM_PHYSICAL_ADDRESS adr;
|
||
ULONG Size;
|
||
PUCHAR pDmaBuf;
|
||
int j;
|
||
|
||
PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
|
||
|
||
PHW_DEVICE_EXTENSION pHwDevExt =
|
||
(PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
|
||
|
||
KdPrint(("TsbVcap: HwInitialize()\n"));
|
||
|
||
#ifdef TOSHIBA
|
||
if (ConfigInfo->NumberOfAccessRanges == 0) {
|
||
#else //TOSHIBA
|
||
if (ConfigInfo->NumberOfAccessRanges != 0) {
|
||
#endif//TOSHIBA
|
||
KdPrint(("TsbVcap: illegal config info\n"));
|
||
|
||
pSrb->Status = STATUS_NO_SUCH_DEVICE;
|
||
return (FALSE);
|
||
}
|
||
|
||
KdPrint(("TsbVcap: Number of access ranges = %lx\n", ConfigInfo->NumberOfAccessRanges));
|
||
KdPrint(("TsbVcap: Memory Range = %lx\n", pHwDevExt->ioBaseLocal));
|
||
KdPrint(("TsbVcap: IRQ = %lx\n", ConfigInfo->BusInterruptLevel));
|
||
|
||
if (ConfigInfo->NumberOfAccessRanges != 0) {
|
||
pHwDevExt->ioBaseLocal
|
||
= (PULONG)(ConfigInfo->AccessRanges[0].RangeStart.LowPart);
|
||
}
|
||
|
||
pHwDevExt->Irq = (USHORT)(ConfigInfo->BusInterruptLevel);
|
||
|
||
ConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) +
|
||
DRIVER_STREAM_COUNT * sizeof (HW_STREAM_INFORMATION);
|
||
|
||
pDmaBuf = StreamClassGetDmaBuffer(pHwDevExt);
|
||
|
||
adr = StreamClassGetPhysicalAddress(pHwDevExt,
|
||
NULL, pDmaBuf, DmaBuffer, &Size);
|
||
|
||
#ifdef TOSHIBA
|
||
if ( CurrentOSType ) { // NT5.0
|
||
pHwDevExt->pRpsDMABuf = pDmaBuf;
|
||
pHwDevExt->pPhysRpsDMABuf = adr;
|
||
pHwDevExt->pCaptureBufferY = NULL;
|
||
pHwDevExt->pCaptureBufferU = NULL;
|
||
pHwDevExt->pCaptureBufferV = NULL;
|
||
pHwDevExt->pPhysCaptureBufferY.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferY.HighPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferU.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferU.HighPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferV.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferV.HighPart = 0;
|
||
pHwDevExt->BufferSize = 0;
|
||
} else {
|
||
pHwDevExt->pRpsDMABuf = pDmaBuf;
|
||
pHwDevExt->pCaptureBufferY = pDmaBuf + (8192 * 2);
|
||
pHwDevExt->pPhysRpsDMABuf = adr;
|
||
adr.LowPart += 8192 * 2;
|
||
pHwDevExt->pPhysCaptureBufferY = adr;
|
||
pHwDevExt->BufferSize = 0;
|
||
}
|
||
|
||
InitializeConfigDefaults(pHwDevExt);
|
||
pHwDevExt->NeedHWInit = TRUE;
|
||
if(!SetupPCILT(pHwDevExt))
|
||
{
|
||
pSrb->Status = STATUS_NO_SUCH_DEVICE;
|
||
return (FALSE);
|
||
}
|
||
pHwDevExt->dblBufflag=FALSE;
|
||
BertInitializeHardware(pHwDevExt);
|
||
if(SetASICRev(pHwDevExt) != TRUE )
|
||
{
|
||
pSrb->Status = STATUS_NO_SUCH_DEVICE;
|
||
return (FALSE);
|
||
}
|
||
BertSetDMCHE(pHwDevExt);
|
||
#if 0 // move to CameraPowerON()
|
||
if( !CameraChkandON(pHwDevExt, MODE_VFW) )
|
||
{
|
||
pSrb->Status = STATUS_NO_SUCH_DEVICE;
|
||
return (FALSE);
|
||
}
|
||
#endif
|
||
HWInit(pHwDevExt);
|
||
#endif//TOSHIBA
|
||
|
||
#ifdef TOSHIBA
|
||
// Init VideoProcAmp properties
|
||
pHwDevExt->Brightness = 0x80;
|
||
pHwDevExt->BrightnessFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
pHwDevExt->Contrast = 0x80;
|
||
pHwDevExt->ContrastFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
pHwDevExt->Hue = 0x80;
|
||
pHwDevExt->HueFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
pHwDevExt->Saturation = 0x80;
|
||
pHwDevExt->SaturationFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
pHwDevExt->ColorEnable = ColorEnableDefault;
|
||
pHwDevExt->ColorEnableFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
|
||
#ifdef TOSHIBA // '98-12-09 Added, for Bug-Report 253529
|
||
pHwDevExt->BrightnessRange = BrightnessRangeAndStep[0].Bounds;
|
||
pHwDevExt->ContrastRange = ContrastRangeAndStep[0].Bounds;
|
||
pHwDevExt->HueRange = HueRangeAndStep[0].Bounds;
|
||
pHwDevExt->SaturationRange = SaturationRangeAndStep[0].Bounds;
|
||
#endif//TOSHIBA
|
||
|
||
// Init VideoControl properties
|
||
pHwDevExt->VideoControlMode = 0;
|
||
#else //TOSHIBA
|
||
// Init Crossbar properties
|
||
pHwDevExt->VideoInputConnected = 0; // TvTuner video is the default
|
||
pHwDevExt->AudioInputConnected = 5; // TvTuner audio is the default
|
||
|
||
// Init VideoProcAmp properties
|
||
pHwDevExt->Brightness = BrightnessDefault;
|
||
pHwDevExt->BrightnessFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
|
||
pHwDevExt->Contrast = ContrastDefault;
|
||
pHwDevExt->ContrastFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
|
||
pHwDevExt->ColorEnable = ColorEnableDefault;
|
||
pHwDevExt->ColorEnableFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
|
||
|
||
// Init CameraControl properties
|
||
pHwDevExt->Focus = FocusDefault;
|
||
pHwDevExt->FocusFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
|
||
pHwDevExt->Zoom = ZoomDefault;
|
||
pHwDevExt->ZoomFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
|
||
|
||
// Init TvTuner properties
|
||
pHwDevExt->TunerInput = 0;
|
||
pHwDevExt->Busy = 0;
|
||
|
||
// Init TvAudio properties
|
||
pHwDevExt->TVAudioMode = KS_TVAUDIO_MODE_MONO |
|
||
KS_TVAUDIO_MODE_LANG_A ;
|
||
|
||
// Init AnalogVideoDecoder properties
|
||
pHwDevExt->VideoDecoderVideoStandard = KS_AnalogVideo_NTSC_M;
|
||
pHwDevExt->VideoDecoderOutputEnable = FALSE;
|
||
pHwDevExt->VideoDecoderVCRTiming = FALSE;
|
||
|
||
// Init VideoControl properties
|
||
pHwDevExt->VideoControlMode = 0;
|
||
#endif//TOSHIBA
|
||
|
||
// Init VideoCompression properties
|
||
pHwDevExt->CompressionSettings.CompressionKeyFrameRate = 15;
|
||
pHwDevExt->CompressionSettings.CompressionPFramesPerKeyFrame = 3;
|
||
pHwDevExt->CompressionSettings.CompressionQuality = 5000;
|
||
|
||
pHwDevExt->PDO = ConfigInfo->PhysicalDeviceObject;
|
||
KdPrint(("TsbVcap: Physical Device Object = %lx\n", pHwDevExt->PDO));
|
||
|
||
#ifdef TOSHIBA
|
||
IoInitializeDpcRequest(pHwDevExt->PDO, DeferredRoutine);
|
||
#endif//TOSHIBA
|
||
|
||
for (j = 0; j < MAX_TSBVCAP_STREAMS; j++){
|
||
|
||
// For each stream, maintain a separate queue for data and control
|
||
InitializeListHead (&pHwDevExt->StreamSRBList[j]);
|
||
InitializeListHead (&pHwDevExt->StreamControlSRBList[j]);
|
||
KeInitializeSpinLock (&pHwDevExt->StreamSRBSpinLock[j]);
|
||
pHwDevExt->StreamSRBListSize[j] = 0;
|
||
}
|
||
|
||
|
||
KdPrint(("TsbVcap: Exit, HwInitialize()\n"));
|
||
|
||
pSrb->Status = STATUS_SUCCESS;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
/*
|
||
** HwUnInitialize()
|
||
**
|
||
** This routine is called when an SRB_UNINITIALIZE_DEVICE request is received
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block for the UnInitialize command
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOL
|
||
STREAMAPI
|
||
HwUnInitialize (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
#ifdef TOSHIBA
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
|
||
if ( CurrentOSType ) { // NT5.0
|
||
if ( pHwDevExt->pCaptureBufferY )
|
||
{
|
||
// free frame buffer
|
||
MmFreeContiguousMemory(pHwDevExt->pCaptureBufferY);
|
||
pHwDevExt->pCaptureBufferY = NULL;
|
||
pHwDevExt->pPhysCaptureBufferY.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferY.HighPart = 0;
|
||
}
|
||
if ( pHwDevExt->pCaptureBufferU )
|
||
{
|
||
// free frame buffer
|
||
MmFreeContiguousMemory(pHwDevExt->pCaptureBufferU);
|
||
pHwDevExt->pCaptureBufferU = NULL;
|
||
pHwDevExt->pPhysCaptureBufferU.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferU.HighPart = 0;
|
||
}
|
||
if ( pHwDevExt->pCaptureBufferV )
|
||
{
|
||
// free frame buffer
|
||
MmFreeContiguousMemory(pHwDevExt->pCaptureBufferV);
|
||
pHwDevExt->pCaptureBufferV = NULL;
|
||
pHwDevExt->pPhysCaptureBufferV.LowPart = 0;
|
||
pHwDevExt->pPhysCaptureBufferV.HighPart = 0;
|
||
}
|
||
}
|
||
#endif//TOSHIBA
|
||
|
||
pSrb->Status = STATUS_SUCCESS;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
** AdapterPowerState()
|
||
**
|
||
** This routine is called when an SRB_CHANGE_POWER_STATE request is received
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block for the Change Power state command
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOLEAN
|
||
STREAMAPI
|
||
AdapterPowerState (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
#ifdef TOSHIBA
|
||
int Counter;
|
||
PSTREAMEX pStrmEx;
|
||
#endif//TOSHIBA
|
||
|
||
pHwDevExt->DeviceState = pSrb->CommandData.DeviceState;
|
||
|
||
#ifdef TOSHIBA
|
||
for (Counter = 0; Counter < DRIVER_STREAM_COUNT; Counter++) {
|
||
if ( pStrmEx = (PSTREAMEX)pHwDevExt->pStrmEx[Counter] ) {
|
||
//
|
||
// Only when it is not streaming, its power state can be changed.
|
||
// We have "DontSuspendIfStreamsAreRunning" turn on in the INF.
|
||
//
|
||
if (pStrmEx->KSState == KSSTATE_PAUSE ||
|
||
pStrmEx->KSState == KSSTATE_RUN) {
|
||
if (pHwDevExt->DeviceState == PowerDeviceD3) {
|
||
if (pHwDevExt->bVideoIn == TRUE) {
|
||
// disable the RPS_INT and field interrupts
|
||
BertInterruptEnable(pHwDevExt, FALSE);
|
||
BertDMAEnable(pHwDevExt, FALSE);
|
||
// wait for the current data xfer to complete
|
||
pHwDevExt->bVideoIn = FALSE;
|
||
}
|
||
VideoQueueCancelAllSRBs (pStrmEx);
|
||
break;
|
||
} else if (pHwDevExt->DeviceState == PowerDeviceD0) {
|
||
pHwDevExt->bVideoIn = TRUE;
|
||
#ifdef TOSHIBA // '99-01-20 Modified
|
||
DevicePowerON( pSrb );
|
||
#else //TOSHIBA
|
||
StreamClassCallAtNewPriority(
|
||
NULL,
|
||
pSrb->HwDeviceExtension,
|
||
Low,
|
||
(PHW_PRIORITY_ROUTINE) DevicePowerON,
|
||
pSrb
|
||
);
|
||
#endif//TOSHIBA
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endif//TOSHIBA
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
** AdapterSetInstance()
|
||
**
|
||
** This routine is called to set all of the Medium instance fields
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterSetInstance (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
int j;
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
|
||
// Use our HwDevExt as the instance data on the Mediums
|
||
// This allows multiple instances to be uniquely identified and
|
||
// connected. The value used in .Id is not important, only that
|
||
// it is unique for each hardware connection
|
||
|
||
#ifdef TOSHIBA
|
||
for (j = 0; j < SIZEOF_ARRAY (CaptureMediums); j++) {
|
||
CaptureMediums[j].Id = 0; //(ULONG) pHwDevExt;
|
||
}
|
||
#else //TOSHIBA
|
||
for (j = 0; j < SIZEOF_ARRAY (TVTunerMediums); j++) {
|
||
TVTunerMediums[j].Id = 0; //(ULONG) pHwDevExt;
|
||
}
|
||
for (j = 0; j < SIZEOF_ARRAY (TVAudioMediums); j++) {
|
||
TVAudioMediums[j].Id = 0; //(ULONG) pHwDevExt;
|
||
}
|
||
for (j = 0; j < SIZEOF_ARRAY (CrossbarMediums); j++) {
|
||
CrossbarMediums[j].Id = 0; //(ULONG) pHwDevExt;
|
||
}
|
||
for (j = 0; j < SIZEOF_ARRAY (CaptureMediums); j++) {
|
||
CaptureMediums[j].Id = 0; //(ULONG) pHwDevExt;
|
||
}
|
||
|
||
pHwDevExt->AnalogVideoInputMedium = CaptureMediums[2];
|
||
#endif//TOSHIBA
|
||
}
|
||
|
||
/*
|
||
** AdapterCompleteInitialization()
|
||
**
|
||
** This routine is called when an SRB_COMPLETE_INITIALIZATION request is received
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterCompleteInitialization (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
KIRQL KIrql;
|
||
|
||
KIrql = KeGetCurrentIrql();
|
||
|
||
// The following allows multiple instance of identical hardware
|
||
// to be installed
|
||
AdapterSetInstance (pSrb);
|
||
|
||
// Create the Registry blobs that DShow uses to create
|
||
// graphs via Mediums
|
||
|
||
#ifndef TOSHIBA
|
||
// Register the TVTuner
|
||
Status = StreamClassRegisterFilterWithNoKSPins (
|
||
pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
|
||
&KSCATEGORY_TVTUNER, // IN GUID * InterfaceClassGUID,
|
||
SIZEOF_ARRAY (TVTunerMediums), // IN ULONG PinCount,
|
||
TVTunerPinDirection, // IN ULONG * Flags,
|
||
TVTunerMediums, // IN KSPIN_MEDIUM * MediumList,
|
||
NULL // IN GUID * CategoryList
|
||
);
|
||
|
||
// Register the Crossbar
|
||
Status = StreamClassRegisterFilterWithNoKSPins (
|
||
pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
|
||
&KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID,
|
||
SIZEOF_ARRAY (CrossbarMediums), // IN ULONG PinCount,
|
||
CrossbarPinDirection, // IN ULONG * Flags,
|
||
CrossbarMediums, // IN KSPIN_MEDIUM * MediumList,
|
||
NULL // IN GUID * CategoryList
|
||
);
|
||
|
||
// Register the TVAudio decoder
|
||
Status = StreamClassRegisterFilterWithNoKSPins (
|
||
pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
|
||
&KSCATEGORY_TVAUDIO, // IN GUID * InterfaceClassGUID,
|
||
SIZEOF_ARRAY (TVAudioMediums), // IN ULONG PinCount,
|
||
TVAudioPinDirection, // IN ULONG * Flags,
|
||
TVAudioMediums, // IN KSPIN_MEDIUM * MediumList,
|
||
NULL // IN GUID * CategoryList
|
||
);
|
||
|
||
// Register the Capture filter
|
||
// Note: This should be done automatically be MSKsSrv.sys,
|
||
// when that component comes on line (if ever) ...
|
||
Status = StreamClassRegisterFilterWithNoKSPins (
|
||
pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
|
||
&KSCATEGORY_CAPTURE, // IN GUID * InterfaceClassGUID,
|
||
SIZEOF_ARRAY (CaptureMediums), // IN ULONG PinCount,
|
||
CapturePinDirection, // IN ULONG * Flags,
|
||
CaptureMediums, // IN KSPIN_MEDIUM * MediumList,
|
||
NULL // IN GUID * CategoryList
|
||
);
|
||
#endif//TOSHIBA
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
** AdapterOpenStream()
|
||
**
|
||
** This routine is called when an OpenStream SRB request is received.
|
||
** A stream is identified by a stream number, which indexes an array
|
||
** of KSDATARANGE structures. The particular KSDATAFORMAT format to
|
||
** be used is also passed in, which should be verified for validity.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to stream request block for the Open command
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterOpenStream (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
//
|
||
// the stream extension structure is allocated by the stream class driver
|
||
//
|
||
|
||
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
int StreamNumber = pSrb->StreamObject->StreamNumber;
|
||
PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
|
||
#ifdef TOSHIBA
|
||
int Counter;
|
||
BOOL First = TRUE;
|
||
#endif//TOSHIBA
|
||
|
||
|
||
RtlZeroMemory(pStrmEx, sizeof(STREAMEX));
|
||
|
||
KdPrint(("TsbVcap: ------- ADAPTEROPENSTREAM ------- StreamNumber=%d\n", StreamNumber));
|
||
|
||
//
|
||
// check that the stream index requested isn't too high
|
||
// or that the maximum number of instances hasn't been exceeded
|
||
//
|
||
|
||
if (StreamNumber >= DRIVER_STREAM_COUNT || StreamNumber < 0) {
|
||
|
||
pSrb->Status = STATUS_INVALID_PARAMETER;
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Check that we haven't exceeded the instance count for this stream
|
||
//
|
||
|
||
if (pHwDevExt->ActualInstances[StreamNumber] >=
|
||
Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances) {
|
||
|
||
pSrb->Status = STATUS_INVALID_PARAMETER;
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Check the validity of the format being requested
|
||
//
|
||
|
||
if (!AdapterVerifyFormat (pKSDataFormat, StreamNumber)) {
|
||
|
||
pSrb->Status = STATUS_INVALID_PARAMETER;
|
||
|
||
return;
|
||
}
|
||
|
||
#ifdef TOSHIBA
|
||
QueryControlsFromRegistry(pHwDevExt);
|
||
#endif//TOSHIBA
|
||
|
||
//
|
||
// And set the format for the stream
|
||
//
|
||
|
||
if (!VideoSetFormat (pSrb)) {
|
||
|
||
return;
|
||
}
|
||
|
||
ASSERT (pHwDevExt->pStrmEx [StreamNumber] == NULL);
|
||
|
||
#ifdef TOSHIBA
|
||
for (Counter = 0; Counter < DRIVER_STREAM_COUNT; Counter++) {
|
||
if ( pHwDevExt->pStrmEx[Counter] ) {
|
||
First = FALSE;
|
||
break;
|
||
}
|
||
} // for all streams
|
||
#endif//TOSHIBA
|
||
|
||
// Maintain an array of all the StreamEx structures in the HwDevExt
|
||
// so that we can cancel IRPs from any stream
|
||
|
||
pHwDevExt->pStrmEx [StreamNumber] = (PSTREAMX) pStrmEx;
|
||
|
||
// Set up pointers to the handlers for the stream data and control handlers
|
||
|
||
pSrb->StreamObject->ReceiveDataPacket =
|
||
(PVOID) Streams[StreamNumber].hwStreamObject.ReceiveDataPacket;
|
||
pSrb->StreamObject->ReceiveControlPacket =
|
||
(PVOID) Streams[StreamNumber].hwStreamObject.ReceiveControlPacket;
|
||
|
||
//
|
||
// The DMA flag must be set when the device will be performing DMA directly
|
||
// to the data buffer addresses passed in to the ReceiceDataPacket routines.
|
||
//
|
||
|
||
pSrb->StreamObject->Dma = Streams[StreamNumber].hwStreamObject.Dma;
|
||
|
||
//
|
||
// The PIO flag must be set when the mini driver will be accessing the data
|
||
// buffers passed in using logical addressing
|
||
//
|
||
|
||
pSrb->StreamObject->Pio = Streams[StreamNumber].hwStreamObject.Pio;
|
||
|
||
//
|
||
// How many extra bytes will be passed up from the driver for each frame?
|
||
//
|
||
|
||
pSrb->StreamObject->StreamHeaderMediaSpecific =
|
||
Streams[StreamNumber].hwStreamObject.StreamHeaderMediaSpecific;
|
||
|
||
pSrb->StreamObject->StreamHeaderWorkspace =
|
||
Streams[StreamNumber].hwStreamObject.StreamHeaderWorkspace;
|
||
|
||
//
|
||
// Indicate the clock support available on this stream
|
||
//
|
||
|
||
pSrb->StreamObject->HwClockObject =
|
||
Streams[StreamNumber].hwStreamObject.HwClockObject;
|
||
|
||
//
|
||
// Increment the instance count on this stream
|
||
//
|
||
pHwDevExt->ActualInstances[StreamNumber]++;
|
||
|
||
|
||
// Retain a private copy of the HwDevExt and StreamObject in the stream extension
|
||
// so we can use a timer
|
||
|
||
pStrmEx->pHwDevExt = pHwDevExt; // For timer use
|
||
pStrmEx->pStreamObject = pSrb->StreamObject; // For timer use
|
||
|
||
// Initialize the compression settings
|
||
// These may have been changed from the default values in the HwDevExt
|
||
// before the stream was opened
|
||
pStrmEx->CompressionSettings.CompressionKeyFrameRate =
|
||
pHwDevExt->CompressionSettings.CompressionKeyFrameRate;
|
||
pStrmEx->CompressionSettings.CompressionPFramesPerKeyFrame =
|
||
pHwDevExt->CompressionSettings.CompressionPFramesPerKeyFrame;
|
||
pStrmEx->CompressionSettings.CompressionQuality =
|
||
pHwDevExt->CompressionSettings.CompressionQuality;
|
||
|
||
// Init VideoControl properties
|
||
pStrmEx->VideoControlMode = pHwDevExt->VideoControlMode;
|
||
|
||
#ifdef TOSHIBA
|
||
if ( First ) {
|
||
#ifdef TOSHIBA // '99-01-20 Modified
|
||
CameraPowerON( pSrb );
|
||
#else //TOSHIBA
|
||
StreamClassCallAtNewPriority(
|
||
NULL,
|
||
pSrb->HwDeviceExtension,
|
||
Low,
|
||
(PHW_PRIORITY_ROUTINE) CameraPowerON,
|
||
pSrb
|
||
);
|
||
#endif//TOSHIBA
|
||
}
|
||
#endif//TOSHIBA
|
||
|
||
KdPrint(("TsbVcap: AdapterOpenStream Exit\n"));
|
||
|
||
}
|
||
|
||
/*
|
||
** AdapterCloseStream()
|
||
**
|
||
** Close the requested data stream.
|
||
**
|
||
** Note that a stream could be closed arbitrarily in the midst of streaming
|
||
** if a user mode app crashes. Therefore, you must release all outstanding
|
||
** resources, disable interrupts, complete all pending SRBs, and put the
|
||
** stream back into a quiescent condition.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb the request block requesting to close the stream
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterCloseStream (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
int StreamNumber = pSrb->StreamObject->StreamNumber;
|
||
PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
|
||
KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader;
|
||
#ifdef TOSHIBA
|
||
int Counter;
|
||
BOOL ClosedAll = TRUE;
|
||
#endif//TOSHIBA
|
||
|
||
|
||
KdPrint(("TsbVcap: -------- ADAPTERCLOSESTREAM ------ StreamNumber=%d\n", StreamNumber));
|
||
|
||
if (pHwDevExt->StreamSRBListSize > 0) {
|
||
VideoQueueCancelAllSRBs (pStrmEx);
|
||
KdPrint(("TsbVcap: Outstanding SRBs at stream close!!!\n"));
|
||
}
|
||
|
||
pHwDevExt->ActualInstances[StreamNumber]--;
|
||
|
||
ASSERT (pHwDevExt->pStrmEx [StreamNumber] != 0);
|
||
|
||
pHwDevExt->pStrmEx [StreamNumber] = 0;
|
||
|
||
//
|
||
// the minidriver should free any resources that were allocate at
|
||
// open stream time etc.
|
||
//
|
||
|
||
// Free the variable length VIDEOINFOHEADER
|
||
|
||
if (pVideoInfoHdr) {
|
||
ExFreePool(pVideoInfoHdr);
|
||
pStrmEx->pVideoInfoHeader = NULL;
|
||
}
|
||
|
||
// Make sure we no longer reference the clock
|
||
pStrmEx->hMasterClock = NULL;
|
||
|
||
// Make sure the state is reset to stopped,
|
||
pStrmEx->KSState = KSSTATE_STOP;
|
||
|
||
#ifdef TOSHIBA
|
||
for (Counter = 0; Counter < DRIVER_STREAM_COUNT; Counter++) {
|
||
if ( pHwDevExt->pStrmEx[Counter] ) {
|
||
ClosedAll = FALSE;
|
||
break;
|
||
}
|
||
} // for all streams
|
||
if ( ClosedAll ) {
|
||
if( pHwDevExt->dblBufflag ){
|
||
Free_TriBuffer(pHwDevExt);
|
||
pHwDevExt->IsRPSReady = FALSE;
|
||
pHwDevExt->dblBufflag = FALSE;
|
||
}
|
||
#ifdef TOSHIBA // '99-01-20 Modified
|
||
CameraPowerOFF( pSrb );
|
||
#else //TOSHIBA
|
||
StreamClassCallAtNewPriority(
|
||
NULL,
|
||
pSrb->HwDeviceExtension,
|
||
Low,
|
||
(PHW_PRIORITY_ROUTINE) CameraPowerOFF,
|
||
pSrb
|
||
);
|
||
#endif//TOSHIBA
|
||
SaveControlsToRegistry(pHwDevExt);
|
||
}
|
||
#endif//TOSHIBA
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
** AdapterStreamInfo()
|
||
**
|
||
** Returns the information of all streams that are supported by the
|
||
** mini-driver
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - Pointer to the STREAM_REQUEST_BLOCK
|
||
** pSrb->HwDeviceExtension - will be the hardware device extension for
|
||
** as initialised in HwInitialise
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterStreamInfo (
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
int j;
|
||
|
||
PHW_DEVICE_EXTENSION pHwDevExt =
|
||
((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
|
||
//
|
||
// pick up the pointer to header which preceeds the stream info structs
|
||
//
|
||
|
||
PHW_STREAM_HEADER pstrhdr =
|
||
(PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
|
||
|
||
//
|
||
// pick up the pointer to the array of stream information data structures
|
||
//
|
||
|
||
PHW_STREAM_INFORMATION pstrinfo =
|
||
(PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
|
||
|
||
|
||
//
|
||
// verify that the buffer is large enough to hold our return data
|
||
//
|
||
|
||
DEBUG_ASSERT (pSrb->NumberOfBytesToTransfer >=
|
||
sizeof (HW_STREAM_HEADER) +
|
||
sizeof (HW_STREAM_INFORMATION) * DRIVER_STREAM_COUNT);
|
||
|
||
#ifndef TOSHIBA
|
||
// Ugliness. To allow mulitple instances, modify the pointer to the
|
||
// AnalogVideoMedium and save it in our device extension
|
||
|
||
Streams[STREAM_AnalogVideoInput].hwStreamInfo.Mediums =
|
||
&pHwDevExt->AnalogVideoInputMedium;
|
||
pHwDevExt->AnalogVideoInputMedium = CrossbarMediums[9];
|
||
pHwDevExt->AnalogVideoInputMedium.Id = 0; //(ULONG) pHwDevExt;
|
||
#endif//TOSHIBA
|
||
|
||
//
|
||
// Set the header
|
||
//
|
||
|
||
StreamHeader.NumDevPropArrayEntries = NUMBER_OF_ADAPTER_PROPERTY_SETS;
|
||
StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) AdapterPropertyTable;
|
||
*pstrhdr = StreamHeader;
|
||
|
||
//
|
||
// stuff the contents of each HW_STREAM_INFORMATION struct
|
||
//
|
||
|
||
for (j = 0; j < DRIVER_STREAM_COUNT; j++) {
|
||
*pstrinfo++ = Streams[j].hwStreamInfo;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
** AdapterReceivePacket()
|
||
**
|
||
** Main entry point for receiving adapter based request SRBs. This routine
|
||
** will always be called at Passive level.
|
||
**
|
||
** Note: This is an asyncronous entry point. The request does not necessarily
|
||
** complete on return from this function, the request only completes when a
|
||
** StreamClassDeviceNotification on this request block, of type
|
||
** DeviceRequestComplete, is issued.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - Pointer to the STREAM_REQUEST_BLOCK
|
||
** pSrb->HwDeviceExtension - will be the hardware device extension for
|
||
** as initialised in HwInitialise
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterReceivePacket(
|
||
IN PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
|
||
BOOL Busy;
|
||
|
||
DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||
|
||
KdPrint(("TsbVcap: Receiving Adapter SRB %8x, %x\n", pSrb, pSrb->Command));
|
||
|
||
// The very first time through, we need to initialize the adapter spinlock
|
||
// and queue
|
||
if (!pHwDevExt->AdapterQueueInitialized) {
|
||
InitializeListHead (&pHwDevExt->AdapterSRBList);
|
||
KeInitializeSpinLock (&pHwDevExt->AdapterSpinLock);
|
||
pHwDevExt->AdapterQueueInitialized = TRUE;
|
||
pHwDevExt->ProcessingAdapterSRB = FALSE;
|
||
}
|
||
|
||
//
|
||
// If we're already processing an SRB, add it to the queue
|
||
//
|
||
Busy = AddToListIfBusy (
|
||
pSrb,
|
||
&pHwDevExt->AdapterSpinLock,
|
||
&pHwDevExt->ProcessingAdapterSRB,
|
||
&pHwDevExt->AdapterSRBList);
|
||
|
||
if (Busy) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// This will run until the queue is empty
|
||
//
|
||
while (TRUE) {
|
||
//
|
||
// Assume success
|
||
//
|
||
pSrb->Status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// determine the type of packet.
|
||
//
|
||
|
||
switch (pSrb->Command)
|
||
{
|
||
|
||
case SRB_INITIALIZE_DEVICE:
|
||
|
||
// open the device
|
||
|
||
HwInitialize(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_UNINITIALIZE_DEVICE:
|
||
|
||
// close the device.
|
||
|
||
HwUnInitialize(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_OPEN_STREAM:
|
||
|
||
// open a stream
|
||
|
||
AdapterOpenStream(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_CLOSE_STREAM:
|
||
|
||
// close a stream
|
||
|
||
AdapterCloseStream(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_GET_STREAM_INFO:
|
||
|
||
//
|
||
// return a block describing all the streams
|
||
//
|
||
|
||
AdapterStreamInfo(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_GET_DATA_INTERSECTION:
|
||
|
||
//
|
||
// Return a format, given a range
|
||
//
|
||
|
||
AdapterFormatFromRange(pSrb);
|
||
|
||
break;
|
||
|
||
case SRB_OPEN_DEVICE_INSTANCE:
|
||
case SRB_CLOSE_DEVICE_INSTANCE:
|
||
|
||
//
|
||
// We should never get these since this is a single instance device
|
||
//
|
||
|
||
TRAP
|
||
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
||
break;
|
||
|
||
case SRB_GET_DEVICE_PROPERTY:
|
||
|
||
//
|
||
// Get adapter wide properties
|
||
//
|
||
|
||
AdapterGetProperty (pSrb);
|
||
break;
|
||
|
||
case SRB_SET_DEVICE_PROPERTY:
|
||
|
||
//
|
||
// Set adapter wide properties
|
||
//
|
||
|
||
AdapterSetProperty (pSrb);
|
||
break;
|
||
|
||
case SRB_PAGING_OUT_DRIVER:
|
||
|
||
//
|
||
// The driver is being paged out
|
||
// Disable Interrupts if you have them!
|
||
//
|
||
KdPrint(("'TsbVcap: Receiving SRB_PAGING_OUT_DRIVER -- SRB=%x\n", pSrb));
|
||
break;
|
||
|
||
case SRB_CHANGE_POWER_STATE:
|
||
|
||
//
|
||
// Changing the device power state, D0 ... D3
|
||
//
|
||
KdPrint(("'TsbVcap: Receiving SRB_CHANGE_POWER_STATE ------ SRB=%x\n", pSrb));
|
||
AdapterPowerState(pSrb);
|
||
break;
|
||
|
||
case SRB_INITIALIZATION_COMPLETE:
|
||
|
||
//
|
||
// Stream class has finished initialization.
|
||
// Now create DShow Medium interface BLOBs.
|
||
// This needs to be done at low priority since it uses the registry
|
||
//
|
||
KdPrint(("'TsbVcap: Receiving SRB_INITIALIZATION_COMPLETE-- SRB=%x\n", pSrb));
|
||
|
||
AdapterCompleteInitialization (pSrb);
|
||
break;
|
||
|
||
|
||
case SRB_UNKNOWN_DEVICE_COMMAND:
|
||
default:
|
||
|
||
//
|
||
// this is a request that we do not understand. Indicate invalid
|
||
// command and complete the request
|
||
//
|
||
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
||
|
||
}
|
||
|
||
//
|
||
// Indicate back to the Stream Class that we're done with this SRB
|
||
//
|
||
CompleteDeviceSRB (pSrb);
|
||
|
||
//
|
||
// See if there's anything else on the queue
|
||
//
|
||
Busy = RemoveFromListIfAvailable (
|
||
&pSrb,
|
||
&pHwDevExt->AdapterSpinLock,
|
||
&pHwDevExt->ProcessingAdapterSRB,
|
||
&pHwDevExt->AdapterSRBList);
|
||
|
||
if (!Busy) {
|
||
break;
|
||
}
|
||
} // end of while there's anything in the queue
|
||
}
|
||
|
||
/*
|
||
** AdapterCancelPacket ()
|
||
**
|
||
** Request to cancel a packet that is currently in process in the minidriver
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to request packet to cancel
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterCancelPacket(
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
|
||
PSTREAMEX pStrmEx;
|
||
int StreamNumber;
|
||
BOOL Found = FALSE;
|
||
|
||
//
|
||
// Run through all the streams the driver has available
|
||
//
|
||
|
||
for (StreamNumber = 0; !Found && (StreamNumber < DRIVER_STREAM_COUNT); StreamNumber++) {
|
||
|
||
//
|
||
// Check to see if the stream is in use
|
||
//
|
||
|
||
if (pStrmEx = (PSTREAMEX) pHwDevExt->pStrmEx[StreamNumber]) {
|
||
|
||
Found = VideoQueueCancelOneSRB (
|
||
pStrmEx,
|
||
pSrb
|
||
);
|
||
|
||
} // if the stream is open
|
||
} // for all streams
|
||
|
||
KdPrint(("TsbVcap: Cancelling SRB %8x Succeeded=%d\n", pSrb, Found));
|
||
}
|
||
|
||
/*
|
||
** AdapterTimeoutPacket()
|
||
**
|
||
** This routine is called when a packet has been in the minidriver for
|
||
** too long. The adapter must decide what to do with the packet
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to the request packet that timed out
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
AdapterTimeoutPacket(
|
||
PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
//
|
||
// Unlike most devices, we need to hold onto data SRBs indefinitely,
|
||
// since the graph could be in a pause state indefinitely
|
||
//
|
||
|
||
KdPrint(("TsbVcap: Timeout Adapter SRB %8x\n", pSrb));
|
||
|
||
pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
|
||
|
||
}
|
||
|
||
/*
|
||
** CompleteDeviceSRB ()
|
||
**
|
||
** This routine is called when a packet is being completed.
|
||
** The optional second notification type is used to indicate ReadyForNext
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pSrb - pointer to the request packet that timed out
|
||
**
|
||
** Returns:
|
||
**
|
||
** Side Effects:
|
||
**
|
||
*/
|
||
|
||
VOID
|
||
STREAMAPI
|
||
CompleteDeviceSRB (
|
||
IN PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
KdPrint(("TsbVcap: Completing Adapter SRB %8x\n", pSrb));
|
||
|
||
StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
|
||
}
|
||
|
||
/*
|
||
** AdapterCompareGUIDsAndFormatSize()
|
||
**
|
||
** Checks for a match on the three GUIDs and FormatSize
|
||
**
|
||
** Arguments:
|
||
**
|
||
** IN DataRange1
|
||
** IN DataRange2
|
||
** BOOL fCompareFormatSize - TRUE when comparing ranges
|
||
** - FALSE when comparing formats
|
||
**
|
||
** Returns:
|
||
**
|
||
** TRUE if all elements match
|
||
** FALSE if any are different
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOL
|
||
STREAMAPI
|
||
AdapterCompareGUIDsAndFormatSize(
|
||
IN PKSDATARANGE DataRange1,
|
||
IN PKSDATARANGE DataRange2,
|
||
BOOL fCompareFormatSize
|
||
)
|
||
{
|
||
return (
|
||
IsEqualGUID (
|
||
&DataRange1->MajorFormat,
|
||
&DataRange2->MajorFormat) &&
|
||
IsEqualGUID (
|
||
&DataRange1->SubFormat,
|
||
&DataRange2->SubFormat) &&
|
||
IsEqualGUID (
|
||
&DataRange1->Specifier,
|
||
&DataRange2->Specifier) &&
|
||
(fCompareFormatSize ?
|
||
(DataRange1->FormatSize == DataRange2->FormatSize) : TRUE ));
|
||
}
|
||
|
||
|
||
/*
|
||
** AdapterVerifyFormat()
|
||
**
|
||
** Checks the validity of a format request by walking through the
|
||
** array of supported KSDATA_RANGEs for a given stream.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** pKSDataFormat - pointer of a KSDATAFORMAT structure.
|
||
** StreamNumber - index of the stream being queried / opened.
|
||
**
|
||
** Returns:
|
||
**
|
||
** TRUE if the format is supported
|
||
** FALSE if the format cannot be suppored
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOL
|
||
STREAMAPI
|
||
AdapterVerifyFormat(
|
||
PKSDATAFORMAT pKSDataFormatToVerify,
|
||
int StreamNumber
|
||
)
|
||
{
|
||
BOOL fOK = FALSE;
|
||
ULONG j;
|
||
ULONG NumberOfFormatArrayEntries;
|
||
PKSDATAFORMAT *pAvailableFormats;
|
||
|
||
|
||
//
|
||
// Check that the stream number is valid
|
||
//
|
||
|
||
if (StreamNumber >= DRIVER_STREAM_COUNT) {
|
||
TRAP;
|
||
return FALSE;
|
||
}
|
||
|
||
NumberOfFormatArrayEntries =
|
||
Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
|
||
|
||
//
|
||
// Get the pointer to the array of available formats
|
||
//
|
||
|
||
pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
|
||
|
||
|
||
KdPrint(("TsbVcap: AdapterVerifyFormat, Stream=%d\n", StreamNumber));
|
||
KdPrint(("TsbVcap: FormatSize=%d\n", pKSDataFormatToVerify->FormatSize));
|
||
KdPrint(("TsbVcap: MajorFormat=%x\n", pKSDataFormatToVerify->MajorFormat));
|
||
|
||
//
|
||
// Walk the formats supported by the stream
|
||
//
|
||
|
||
for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
|
||
|
||
// Check for a match on the three GUIDs and format size
|
||
|
||
if (!AdapterCompareGUIDsAndFormatSize(
|
||
pKSDataFormatToVerify,
|
||
*pAvailableFormats,
|
||
FALSE /* CompareFormatSize */ )) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Now that the three GUIDs match, switch on the Specifier
|
||
// to do a further type-specific check
|
||
//
|
||
|
||
// -------------------------------------------------------------------
|
||
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
|
||
// -------------------------------------------------------------------
|
||
|
||
if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
|
||
&KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
|
||
|
||
PKS_DATAFORMAT_VIDEOINFOHEADER pDataFormatVideoInfoHeader =
|
||
(PKS_DATAFORMAT_VIDEOINFOHEADER) pKSDataFormatToVerify;
|
||
PKS_VIDEOINFOHEADER pVideoInfoHdrToVerify =
|
||
(PKS_VIDEOINFOHEADER) &pDataFormatVideoInfoHeader->VideoInfoHeader;
|
||
PKS_DATARANGE_VIDEO pKSDataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
|
||
KS_VIDEO_STREAM_CONFIG_CAPS *pConfigCaps = &pKSDataRangeVideo->ConfigCaps;
|
||
RECT rcImage;
|
||
|
||
KdPrint(("TsbVcap: AdapterVerifyFormat\n"));
|
||
KdPrint(("TsbVcap: pVideoInfoHdrToVerify=%x\n", pVideoInfoHdrToVerify));
|
||
KdPrint(("TsbVcap: KS_VIDEOINFOHEADER size=%d\n",
|
||
KS_SIZE_VIDEOHEADER (pVideoInfoHdrToVerify)));
|
||
KdPrint(("TsbVcap: Width=%d Height=%d BitCount=%d\n",
|
||
pVideoInfoHdrToVerify->bmiHeader.biWidth,
|
||
pVideoInfoHdrToVerify->bmiHeader.biHeight,
|
||
pVideoInfoHdrToVerify->bmiHeader.biBitCount));
|
||
KdPrint(("TsbVcap: biSizeImage=%d\n",
|
||
pVideoInfoHdrToVerify->bmiHeader.biSizeImage));
|
||
|
||
/*
|
||
** HOW BIG IS THE IMAGE REQUESTED (pseudocode follows)
|
||
**
|
||
** if (IsRectEmpty (&rcTarget) {
|
||
** SetRect (&rcImage, 0, 0,
|
||
** BITMAPINFOHEADER.biWidth,
|
||
BITMAPINFOHEADER.biHeight);
|
||
** }
|
||
** else {
|
||
** // Probably rendering to a DirectDraw surface,
|
||
** // where biWidth is used to expressed the "stride"
|
||
** // in units of pixels (not bytes) of the destination surface.
|
||
** // Therefore, use rcTarget to get the actual image size
|
||
**
|
||
** rcImage = rcTarget;
|
||
** }
|
||
*/
|
||
|
||
if ((pVideoInfoHdrToVerify->rcTarget.right -
|
||
pVideoInfoHdrToVerify->rcTarget.left <= 0) ||
|
||
(pVideoInfoHdrToVerify->rcTarget.bottom -
|
||
pVideoInfoHdrToVerify->rcTarget.top <= 0)) {
|
||
|
||
rcImage.left = rcImage.top = 0;
|
||
rcImage.right = pVideoInfoHdrToVerify->bmiHeader.biWidth;
|
||
rcImage.bottom = pVideoInfoHdrToVerify->bmiHeader.biHeight;
|
||
}
|
||
else {
|
||
rcImage = pVideoInfoHdrToVerify->rcTarget;
|
||
}
|
||
|
||
//
|
||
// TODO, perform all other verification tests here!!!
|
||
//
|
||
|
||
//
|
||
// HOORAY, the format passed all of the tests, so we support it
|
||
//
|
||
|
||
fOK = TRUE;
|
||
break;
|
||
|
||
} // End of VIDEOINFOHEADER specifier
|
||
|
||
#ifndef TOSHIBA
|
||
// -------------------------------------------------------------------
|
||
// Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
|
||
// -------------------------------------------------------------------
|
||
|
||
else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
|
||
&KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
|
||
|
||
//
|
||
// For analog video, the DataRange and DataFormat
|
||
// are identical, so just copy the whole structure
|
||
//
|
||
|
||
PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
|
||
(PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
|
||
|
||
//
|
||
// TODO, perform all other verification tests here!!!
|
||
//
|
||
|
||
fOK = TRUE;
|
||
break;
|
||
|
||
} // End of KS_ANALOGVIDEOINFO specifier
|
||
#endif//TOSHIBA
|
||
|
||
} // End of loop on all formats for this stream
|
||
|
||
return fOK;
|
||
}
|
||
|
||
/*
|
||
** AdapterFormatFromRange()
|
||
**
|
||
** Produces a DATAFORMAT given a DATARANGE.
|
||
**
|
||
** Think of a DATARANGE as a multidimensional space of all of the possible image
|
||
** sizes, cropping, scaling, and framerate possibilities. Here, the caller
|
||
** is saying "Out of this set of possibilities, could you verify that my
|
||
** request is acceptable?". The resulting singular output is a DATAFORMAT.
|
||
** Note that each different colorspace (YUV vs RGB8 vs RGB24)
|
||
** must be represented as a separate DATARANGE.
|
||
**
|
||
** Generally, the resulting DATAFORMAT will be immediately used to open a stream
|
||
** in that format.
|
||
**
|
||
** Arguments:
|
||
**
|
||
** IN PHW_STREAM_REQUEST_BLOCK pSrb
|
||
**
|
||
** Returns:
|
||
**
|
||
** TRUE if the format is supported
|
||
** FALSE if the format cannot be suppored
|
||
**
|
||
** Side Effects: none
|
||
*/
|
||
|
||
BOOL
|
||
STREAMAPI
|
||
AdapterFormatFromRange(
|
||
IN PHW_STREAM_REQUEST_BLOCK pSrb
|
||
)
|
||
{
|
||
PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
|
||
PKSDATARANGE DataRange;
|
||
BOOL OnlyWantsSize;
|
||
BOOL MatchFound = FALSE;
|
||
ULONG FormatSize;
|
||
ULONG StreamNumber;
|
||
ULONG j;
|
||
ULONG NumberOfFormatArrayEntries;
|
||
PKSDATAFORMAT *pAvailableFormats;
|
||
|
||
IntersectInfo = pSrb->CommandData.IntersectInfo;
|
||
StreamNumber = IntersectInfo->StreamNumber;
|
||
DataRange = IntersectInfo->DataRange;
|
||
|
||
//
|
||
// Check that the stream number is valid
|
||
//
|
||
|
||
if (StreamNumber >= DRIVER_STREAM_COUNT) {
|
||
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
||
TRAP;
|
||
return FALSE;
|
||
}
|
||
|
||
NumberOfFormatArrayEntries =
|
||
Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
|
||
|
||
//
|
||
// Get the pointer to the array of available formats
|
||
//
|
||
|
||
pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
|
||
|
||
//
|
||
// Is the caller trying to get the format, or the size of the format?
|
||
//
|
||
|
||
OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
|
||
|
||
//
|
||
// Walk the formats supported by the stream searching for a match
|
||
// of the three GUIDs which together define a DATARANGE
|
||
//
|
||
|
||
for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
|
||
|
||
if (!AdapterCompareGUIDsAndFormatSize(
|
||
DataRange,
|
||
*pAvailableFormats,
|
||
TRUE /* CompareFormatSize */)) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Now that the three GUIDs match, switch on the Specifier
|
||
// to do a further type-specific check
|
||
//
|
||
|
||
// -------------------------------------------------------------------
|
||
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
|
||
// -------------------------------------------------------------------
|
||
|
||
if (IsEqualGUID (&DataRange->Specifier,
|
||
&KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
|
||
|
||
PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
|
||
(PKS_DATARANGE_VIDEO) DataRange;
|
||
PKS_DATARANGE_VIDEO DataRangeVideo =
|
||
(PKS_DATARANGE_VIDEO) *pAvailableFormats;
|
||
PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;
|
||
|
||
//
|
||
// Check that the other fields match
|
||
//
|
||
if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
|
||
(DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
|
||
(DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
|
||
(DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
|
||
(RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
|
||
&DataRangeVideo->ConfigCaps,
|
||
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
|
||
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS))) {
|
||
continue;
|
||
}
|
||
|
||
// MATCH FOUND!
|
||
MatchFound = TRUE;
|
||
FormatSize = sizeof (KSDATAFORMAT) +
|
||
KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader);
|
||
|
||
if (OnlyWantsSize) {
|
||
break;
|
||
}
|
||
|
||
// Caller wants the full data format
|
||
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
|
||
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
|
||
return FALSE;
|
||
}
|
||
|
||
// Copy over the KSDATAFORMAT, followed by the
|
||
// actual VideoInfoHeader
|
||
|
||
DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;
|
||
|
||
// Copy over the KSDATAFORMAT
|
||
RtlCopyMemory(
|
||
&DataFormatVideoInfoHeaderOut->DataFormat,
|
||
&DataRangeVideoToVerify->DataRange,
|
||
sizeof (KSDATARANGE));
|
||
|
||
DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;
|
||
|
||
// Copy over the callers requested VIDEOINFOHEADER
|
||
|
||
RtlCopyMemory(
|
||
&DataFormatVideoInfoHeaderOut->VideoInfoHeader,
|
||
&DataRangeVideoToVerify->VideoInfoHeader,
|
||
KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader));
|
||
|
||
// Calculate biSizeImage for this request, and put the result in both
|
||
// the biSizeImage field of the bmiHeader AND in the SampleSize field
|
||
// of the DataFormat.
|
||
//
|
||
// Note that for compressed sizes, this calculation will probably not
|
||
// be just width * height * bitdepth
|
||
|
||
DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
|
||
DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
|
||
KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
|
||
|
||
//
|
||
// TODO Perform other validation such as cropping and scaling checks
|
||
//
|
||
|
||
break;
|
||
|
||
} // End of VIDEOINFOHEADER specifier
|
||
|
||
#ifndef TOSHIBA
|
||
// -------------------------------------------------------------------
|
||
// Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
|
||
// -------------------------------------------------------------------
|
||
|
||
else if (IsEqualGUID (&DataRange->Specifier,
|
||
&KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
|
||
|
||
//
|
||
// For analog video, the DataRange and DataFormat
|
||
// are identical, so just copy the whole structure
|
||
//
|
||
|
||
PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
|
||
(PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
|
||
|
||
// MATCH FOUND!
|
||
MatchFound = TRUE;
|
||
FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);
|
||
|
||
if (OnlyWantsSize) {
|
||
break;
|
||
}
|
||
|
||
// Caller wants the full data format
|
||
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
|
||
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
|
||
return FALSE;
|
||
}
|
||
|
||
RtlCopyMemory(
|
||
IntersectInfo->DataFormatBuffer,
|
||
DataRangeVideo,
|
||
sizeof (KS_DATARANGE_ANALOGVIDEO));
|
||
|
||
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
|
||
|
||
break;
|
||
|
||
} // End of KS_ANALOGVIDEOINFO specifier
|
||
#endif//TOSHIBA
|
||
|
||
else {
|
||
pSrb->Status = STATUS_NO_MATCH;
|
||
return FALSE;
|
||
}
|
||
|
||
} // End of loop on all formats for this stream
|
||
|
||
if (OnlyWantsSize) {
|
||
*(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
|
||
pSrb->ActualBytesTransferred = sizeof(ULONG);
|
||
return TRUE;
|
||
}
|
||
pSrb->ActualBytesTransferred = FormatSize;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|