|
|
// $Header: G:/SwDev/WDM/Video/bt848/rcs/Capmain.c 1.19 1998/05/11 23:59:54 tomz Exp $
//==========================================================================;
//
// 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 - 1996 Microsoft Corporation. All Rights Reserved.
//
//==========================================================================;
#define INITGUID
#define BT848_MEDIUMS
#ifdef __cplusplus
extern "C" { #endif
#include "strmini.h"
#include "ksmedia.h"
#ifdef __cplusplus
} #endif
#include "device.h"
#include "capmain.h"
#include "capstrm.h"
#include "capdebug.h"
#include "capprop.h"
LONG PinTypes_ [MaxInpPins]; // just allocate maximum possible
DWORD xtals_ [2]; // no more than 2 xtals
extern PsDevice *gpPsDevice; extern BYTE *gpjBaseAddr; extern VOID *gpHwDeviceExtension;
void AdapterFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb ); VOID ReadRegistryValues( IN PDEVICE_OBJECT PhysicalDeviceObject ); inline void CompleteDeviceSRB( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb );
extern DWORD GetSizeHwDeviceExtension( ); extern DWORD GetSizeStreamEx( ); extern PsDevice *GetCurrentDevice( ); extern void SetCurrentDevice( PsDevice *dev );
extern BYTE *GetBase(); extern void SetBase(BYTE *base);
PHW_STREAM_REQUEST_BLOCK StreamIdxToSrb[4];
void CheckSrbStatus( PHW_STREAM_REQUEST_BLOCK pSrb ) { VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
DebugOut((1, " *** completing pSrb(%x) strm(%d) status(%x)\n", pSrb, StreamNumber, pSrb->Status ));
switch ( pSrb->Status ) { case STATUS_SUCCESS: case STATUS_CANCELLED: break; default: DebugOut((0, "*** pSrb->Status = %x\n", pSrb->Status )); DEBUG_BREAKPOINT(); } }
/* Function: GetRequestedSize
* Purpose: Figures out what the image size should be * Input: vidHdr: KS_VIDEOINFOHEADER & * size: MSize & * Output: None */ void GetRequestedSize2( const KS_VIDEOINFOHEADER2 &vidHdr, MSize &size ) { Trace t("GetRequestedSize()");
size.Set( vidHdr.bmiHeader.biWidth, abs(vidHdr.bmiHeader.biHeight) );
MRect dst( vidHdr.rcTarget ); // if writing to a DD surface maybe ?
if ( !dst.IsNull() && !dst.IsEmpty() ) size.Set( dst.Width(), dst.Height() ); }
void GetRequestedSize( const KS_VIDEOINFOHEADER &vidHdr, MSize &size ) { Trace t("GetRequestedSize()");
size.Set( vidHdr.bmiHeader.biWidth, abs(vidHdr.bmiHeader.biHeight) );
MRect dst( vidHdr.rcTarget ); // if writing to a DD surface maybe ?
if ( !dst.IsNull() && !dst.IsEmpty() ) size.Set( dst.Width(), dst.Height() ); }
/* Function: VerifyVideoStream
* Purpose: Checks the paramaters passed in for opening steam * Input: vidHDR: KS_DATAFORMAT_VIDEOINFOHEADER * Output: Success or Fail */ ErrorCode VerifyVideoStream( const KS_DATAFORMAT_VIDEOINFOHEADER &vidHDR ) { Trace t("VerifyVideoStream()");
// [WRK] - add guid for VideoInfoHeader2
// simply verify that major and format are of video nature...
if ( IsEqualGUID( vidHDR.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VIDEO ) && IsEqualGUID( vidHDR.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) ) {
MSize size; GetRequestedSize( vidHDR.VideoInfoHeader, size ); // ... and here see if the subtype is one of those supported by us
ColorSpace tmpCol( vidHDR.DataFormat.SubFormat ); MRect dst( vidHDR.VideoInfoHeader.rcTarget );
// make sure the dimentions are acceptable
if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) && tmpCol.CheckLeftTop( dst.TopLeft() ) ) { DebugOut((1, "VerifyVideoStream succeeded\n")); return Success; } } DebugOut((0, "VerifyVideoStream failed\n")); return Fail; }
ErrorCode VerifyVideoStream2( const KS_DATAFORMAT_VIDEOINFOHEADER2 &vidHDR ) { Trace t("VerifyVideoStream2()");
// [WRK] - add guid for VideoInfoHeader2
// simply verify that major and format are of video nature...
if ( IsEqualGUID( vidHDR.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VIDEO ) && IsEqualGUID( vidHDR.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) ) {
MSize size; GetRequestedSize2( vidHDR.VideoInfoHeader2, size ); // ... and here see if the subtype is one of those supported by us
ColorSpace tmpCol( vidHDR.DataFormat.SubFormat ); MRect dst( vidHDR.VideoInfoHeader2.rcTarget );
// make sure the dimentions are acceptable
if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) && tmpCol.CheckLeftTop( dst.TopLeft() ) ) { DebugOut((1, "VerifyVideoStream2 succeeded\n")); return Success; } } DebugOut((0, "VerifyVideoStream2 failed\n")); return Fail; }
/* Function: VerifyVBIStream
* Purpose: Checks that VBI stream info during open is correct * Input: rKSDataFormat: KS_DATAFORMAT & * Output: ErrorCode */ ErrorCode VerifyVBIStream( const KS_DATAFORMAT_VBIINFOHEADER &rKSDataFormat ) { Trace t("VerifyVBIStream()");
if ( IsEqualGUID( rKSDataFormat.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VBI ) && IsEqualGUID( rKSDataFormat.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VBI ) && rKSDataFormat.VBIInfoHeader.StartLine == VBIStart && rKSDataFormat.VBIInfoHeader.EndLine == VBIEnd && rKSDataFormat.VBIInfoHeader.SamplesPerLine == VBISamples ) return Success; return Fail; }
/*
** DriverEntry() ** ** This routine is called when an SRB_INITIALIZE_DEVICE request is received ** ** Arguments: ** ** Context1 and Context2 ** ** Returns: ** ** Results of StreamClassRegisterAdapter() ** ** Side Effects: none */
extern "C" ULONG DriverEntry( PVOID Arg1, PVOID Arg2 ) { Trace t("DriverEntry()");
//
// Entry points for Port Driver
//
HW_INITIALIZATION_DATA HwInitData; RtlZeroMemory( &HwInitData, sizeof( HwInitData )); HwInitData.HwInitializationDataSize = sizeof( HwInitData );
HwInitData.HwInterrupt = (PHW_INTERRUPT)&HwInterrupt;
HwInitData.HwReceivePacket = &AdapterReceivePacket; HwInitData.HwCancelPacket = &AdapterCancelPacket; HwInitData.HwRequestTimeoutHandler = &AdapterTimeoutPacket;
HwInitData.DeviceExtensionSize = GetSizeHwDeviceExtension( ); HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION); HwInitData.FilterInstanceExtensionSize = 0; // double to support alternating/interleaved
HwInitData.PerStreamExtensionSize = GetSizeStreamEx( ); HwInitData.BusMasterDMA = true; HwInitData.Dma24BitAddresses = FALSE; HwInitData.BufferAlignment = 4; HwInitData.TurnOffSynchronization = FALSE; HwInitData.DmaBufferSize = RISCProgramsSize;
return (StreamClassRegisterAdapter(Arg1, Arg2,&HwInitData)); }
/******************************************************************************
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 */ BOOLEAN HwInitialize( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("HwInitialize()");
DebugOut((1, "HwInitialize()\n"));
// initialize ourselves
PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
gpHwDeviceExtension = ConfigInfo->HwDeviceExtension; DebugOut((0, "*** gpHwDeviceExtension = %x\n", gpHwDeviceExtension));
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) gpHwDeviceExtension;
DWORD dwBase = ConfigInfo->AccessRanges[0].RangeStart.LowPart; SetBase((BYTE *)dwBase);
if ( ConfigInfo->NumberOfAccessRanges != 1 ) { DebugOut((1, "illegal config info\n")); pSrb->Status = STATUS_NO_SUCH_DEVICE; }
// read info from the registry
ReadXBarRegistryValues( ConfigInfo->PhysicalDeviceObject ); ReadXTalRegistryValues( ConfigInfo->PhysicalDeviceObject ); ReadTunerRegistryValues( ConfigInfo->PhysicalDeviceObject );
HwDeviceExtension->psdevice = new ( &(HwDeviceExtension->psdevicemem) ) PsDevice( dwBase );
DebugOut((0, "psdevice = %x\n", HwDeviceExtension->psdevice )); DebugOut((0, "&psdevicemem = %x\n", &HwDeviceExtension->psdevicemem ));
PsDevice *adapter = HwDeviceExtension->psdevice;
// save for later use when phys address if obtained
SetCurrentDevice( adapter );
// make sure initialization is successful
if ( !adapter->InitOK() ) { DebugOut((1, "Error initializing\n")); pSrb->Status = STATUS_INSUFFICIENT_RESOURCES; }
// save our PDO
adapter->PDO = ConfigInfo->PhysicalDeviceObject;
ConfigInfo->StreamDescriptorSize = sizeof( HW_STREAM_HEADER ) + DRIVER_STREAM_COUNT * sizeof( HW_STREAM_INFORMATION );
DebugOut((1, "Exit : HwInitialize()\n"));
// go to usual priority, completing the SRB at the same time
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( CompleteDeviceSRB ), pSrb );
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 */ void HwUnInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("HwUnInitialize()");
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
DebugOut((0, "HwUnInitialize - pSrb(%x)\n", pSrb));
PsDevice *adapter = HwDeviceExtension->psdevice; adapter->~PsDevice(); }
/*
** AdapterOpenStream() ** ** This routine is called when an OpenStream SRB request is received ** ** Arguments: ** ** pSrb - pointer to stream request block for the Open command ** ** Returns: ** ** Side Effects: none */
VOID AdapterOpenStream( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AdapterOpenStream()");
//
// the stream extension structure is allocated by the stream class driver
//
// retrieve the device object pointer
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
PsDevice *adapter = HwDeviceExtension->psdevice;
VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber; StreamIdxToSrb[StreamNumber] = pSrb;
DebugOut((1, "AdapterOpenStream(%d) - pSrb(%x)\n", StreamNumber, pSrb));
// [STRM] [!!!]
//if ( !( StreamNumber >= VS_Field1 && StreamNumber <= DRIVER_STREAM_COUNT ) ) {
// pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
// return;
//}
if ( StreamNumber == STREAM_IDX_ANALOG ) // [TMZ] [!!] was 3
{ pSrb->StreamObject->ReceiveDataPacket = AnalogReceiveDataPacket; pSrb->StreamObject->ReceiveControlPacket = AnalogReceiveCtrlPacket; return; // nothing to do for the analog stream
} PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; RtlZeroMemory( &pStrmEx->FrameInfo, sizeof( pStrmEx->FrameInfo ) ); pStrmEx->StreamNumber = StreamNumber;
// size of the media specific data
UINT MediaSpecific = sizeof( KS_FRAME_INFO );
// Always open VBI stream as Alternating fields
if ( StreamNumber == STREAM_IDX_VBI ) { const KS_DATAFORMAT_VBIINFOHEADER &rKSVBIDataFormat = *(PKS_DATAFORMAT_VBIINFOHEADER) pSrb->CommandData.OpenFormat;
if ( VerifyVBIStream( rKSVBIDataFormat ) != Success ) { DebugOut((0, "*** VerifyVBIStream failed - aborting\n")); pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } if ( adapter->OpenVBIChannel( pStrmEx ) != Success ) { DebugOut((0, "*** OpenVBIChannel failed - aborting\n")); pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; }
VBIAlterChannel *chan = (VBIAlterChannel *)pStrmEx->videochannel; //chan->pStrmEx = pStrmEx;
chan->SetVidHdr( rKSVBIDataFormat );
MediaSpecific = sizeof( KS_VBI_FRAME_INFO );
} else {
// is it where the size, fourcc, etc. are specified ? they should be settable
// via properies sets
const KS_DATAFORMAT_VIDEOINFOHEADER &rKSDataFormat = *(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat; const KS_VIDEOINFOHEADER &rVideoInfoHdrRequested = rKSDataFormat.VideoInfoHeader; const KS_DATAFORMAT_VIDEOINFOHEADER2 &rKSDataFormat2 = *(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat; const KS_VIDEOINFOHEADER2 &rVideoInfoHdrRequested2 = rKSDataFormat2.VideoInfoHeader2;
DebugOut((1, "AdapterOpenStream\n")); if ( IsEqualGUID( rKSDataFormat.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) ) { DebugOut((1, "StreamNumber=%d\n", pSrb->StreamObject->StreamNumber)); DebugOut((1, "FormatSize=%d\n", rKSDataFormat.DataFormat.FormatSize)); DebugOut((1, "MajorFormat=%x\n", rKSDataFormat.DataFormat.MajorFormat)); DebugOut((1, "pVideoInfoHdrRequested=%x\n", &rVideoInfoHdrRequested)); DebugOut((1, "Bpp =%d\n", rVideoInfoHdrRequested.bmiHeader.biBitCount ) ); DebugOut((1, "Width =%d\n", rVideoInfoHdrRequested.bmiHeader.biWidth)); DebugOut((1, "Height =%d\n", rVideoInfoHdrRequested.bmiHeader.biHeight)); DebugOut((1, "biSizeImage =%d\n", rVideoInfoHdrRequested.bmiHeader.biSizeImage)); if ( VerifyVideoStream( rKSDataFormat ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } } else { DebugOut((1, "StreamNumber=%d\n", pSrb->StreamObject->StreamNumber)); DebugOut((1, "FormatSize=%d\n", rKSDataFormat2.DataFormat.FormatSize)); DebugOut((1, "MajorFormat=%x\n", rKSDataFormat2.DataFormat.MajorFormat)); DebugOut((1, "pVideoInfoHdrRequested2=%x\n", &rVideoInfoHdrRequested2)); DebugOut((1, "Bpp =%d\n", rVideoInfoHdrRequested2.bmiHeader.biBitCount ) ); DebugOut((1, "Width =%d\n", rVideoInfoHdrRequested2.bmiHeader.biWidth)); DebugOut((1, "Height =%d\n", rVideoInfoHdrRequested2.bmiHeader.biHeight)); DebugOut((1, "biSizeImage =%d\n", rVideoInfoHdrRequested2.bmiHeader.biSizeImage)); if ( VerifyVideoStream2( rKSDataFormat2 ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } }
// at this point have to see what type of channel is to be opened:
// single field, alternating or interleaved
// algorithm is like this:
// 1. look at the video format Specifier guid. If it's a infoheader2, it
// will tell us type of stream to open.
// 2. else look at the vertical size to decide single field vs. interleaved
if ( IsEqualGUID( rKSDataFormat.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) ) {
MSize size;
GetRequestedSize( rVideoInfoHdrRequested, size );
// different video standards have different vertical sizes
int threshold = adapter->GetFormat() == VFormat_NTSC ? 240 : 288;
if ( size.cy > threshold ) { if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } } else { if ( adapter->OpenChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } } VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel; //chan->pStrmEx = pStrmEx;
chan->SetVidHdr( rVideoInfoHdrRequested ); } else if ( IsEqualGUID( rKSDataFormat2.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) ) { MSize size; GetRequestedSize2( rVideoInfoHdrRequested2, size );
// different video standards have different vertical sizes
int threshold = adapter->GetFormat() == VFormat_NTSC ? 240 : 288;
if ( size.cy > threshold ) { if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } } else { if ( adapter->OpenChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } } VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel; //chan->pStrmEx = pStrmEx;
chan->SetVidHdr2( rVideoInfoHdrRequested2 ); } else { if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } if ( adapter->OpenAlterChannel( pStrmEx, StreamNumber ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } // [WRK] - check the height of the image for alter channel !> threshold
VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel; //chan->pStrmEx = pStrmEx;
chan->SetVidHdr( rVideoInfoHdrRequested ); } }
#ifdef ENABLE_DDRAW_STUFF
//TODO: should we check to see what kind of stream type this is?
if( OpenKernelDirectDraw( pSrb ) ) { OpenKernelDDrawSurfaceHandle( pSrb ); RegisterForDirectDrawEvents( pSrb ); } #endif
// the structure of the driver is such that a single callback could be used
// for all stream requests. But the code below could be used to supply
// different entry points for different streams
pSrb->StreamObject->ReceiveDataPacket = VideoReceiveDataPacket; pSrb->StreamObject->ReceiveControlPacket = VideoReceiveCtrlPacket;
pSrb->StreamObject->Dma = true;
pSrb->StreamObject->Allocator = Streams[StreamNumber].hwStreamObject.Allocator;
//
// The PIO flag must be set when the mini driver will be accessing the data
// buffers passed in using logical addressing
//
pSrb->StreamObject->Pio = true; pSrb->StreamObject->StreamHeaderMediaSpecific = MediaSpecific; pSrb->StreamObject->HwClockObject.ClockSupportFlags = 0; pSrb->StreamObject->HwClockObject.HwClockFunction = 0;
DebugOut((1, "AdapterOpenStream Exit\n")); }
/*
** AdapterCloseStream() ** ** Close the requested data stream ** ** Arguments: ** ** pSrb the request block requesting to close the stream ** ** Returns: ** ** Side Effects: none */
VOID AdapterCloseStream( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AdapterCloseStream()");
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
DebugOut((1, "AdapterCloseStream(%d) - pSrb(%x)\n", StreamNumber, pSrb));
if ( !( StreamNumber >= 0 && StreamNumber < DRIVER_STREAM_COUNT ) ) { DebugOut((0, " AdapterCloseStream - failed to close stream %d\n", StreamNumber)); DEBUG_BREAKPOINT(); pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
return; } if ( StreamNumber == STREAM_IDX_ANALOG ) // nothing to close for analog
{ DebugOut((1, " AdapterCloseStream - doing nothing, stream (%d) was assumed to be analog\n", StreamNumber)); return; } #ifdef ENABLE_DDRAW_STUFF
//TODO: should we check to see what kind of stream type this is?
UnregisterForDirectDrawEvents( pSrb ); CloseKernelDDrawSurfaceHandle( pSrb ); CloseKernelDirectDraw( pSrb ); #endif
// CloseChannel() has a bit of ugly code to take care of paired channels
adapter->CloseChannel( chan ); }
/*
** 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 AdapterStreamInfo( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AdapterStreamInfo()");
//
// 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 stream information data structure
//
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 );
//
// 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 ( int j = 0; j < DRIVER_STREAM_COUNT; j++ ) { *pstrinfo++ = Streams[j].hwStreamInfo; }
} #ifdef HAUPPAUGEI2CPROVIDER
// new private members of PsDevice for Hauppauge I2C Provider:
// LARGE_INTEGER LastI2CAccessTime;
// DWORD dwExpiredCookie = 0;
//
//
/* Method: PsDevice::I2COpen
* Purpose: Tries to allocate I2C port to the caller */ NTSTATUS STDMETHODCALLTYPE PsDevice::I2COpen( PDEVICE_OBJECT pdo, ULONG ToOpen, PI2CControl ctrl ) { Trace t("PsDevice::I2COpen()");
DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension)); LARGE_INTEGER CurTime;
// need a way to obtain the device pointer
PsDevice *adapter = GetCurrentDevice();
KeQuerySystemTime( &CurTime );
ctrl->Status = I2C_STATUS_NOERROR;
// cookie is not NULL if I2C is open
if ( ToOpen && adapter->dwCurCookie_ ) { // Check time stamp against current time to detect if current Cookie has timed out.
// If it has remember the last timed out cookie and grant the new requestor access.
if ( ( adapter->dwI2CClientTimeout != 0 ) && ( (CurTime - adapter->LastI2CAccessTime) > adapter->dwI2CClientTimeout ) ) { adapter->dwExpiredCookie = adapter->dwCurCookie_; } else { ctrl->dwCookie = 0; return STATUS_INVALID_HANDLE; } }
// want to close ?
if ( !ToOpen ) { if ( adapter->dwCurCookie_ == ctrl->dwCookie ) { adapter->dwCurCookie_ = 0; ctrl->dwCookie = 0; return STATUS_SUCCESS; } else { if ( (adapter->dwExpiredCookie != 0 ) && (adapter->dwExpiredCookie == ctrl->dwCookie ) ) { ctrl->Status = I2C_STATUS_ERROR; } else { ctrl->dwCookie = 0; ctrl->Status = I2C_STATUS_NOERROR; } return STATUS_INVALID_HANDLE; } }
adapter->dwCurCookie_ = CurTime.LowPart; adapter->LastI2CAccessTime = CurTime; ctrl->dwCookie = adapter->dwCurCookie_; ctrl->ClockRate = 100000;
return STATUS_SUCCESS; }
NTSTATUS STDMETHODCALLTYPE PsDevice::I2CAccess( PDEVICE_OBJECT pdo, PI2CControl ctrl ) { Trace t("PsDevice::I2CAccess()");
DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension)); ErrorCode error; PsDevice *adapter = GetCurrentDevice();
ctrl->Status = I2C_STATUS_NOERROR;
if ( ctrl->dwCookie != adapter->dwCurCookie_ ) { if ( (adapter->dwExpiredCookie != 0 ) && (adapter->dwExpiredCookie == ctrl->dwCookie ) ) ctrl->Status = I2C_STATUS_ERROR; else ctrl->Status = I2C_STATUS_NOERROR; return STATUS_INVALID_HANDLE; }
// Record time of this transaction to enable checking for timeout
KeQuerySystemTime( &adapter->LastI2CAccessTime );
// Check for valid combinations of I2C command & flags
switch( ctrl->Command ) { case I2C_COMMAND_NULL: if ( ( ctrl->Flags & ~(I2C_FLAGS_START | I2C_FLAGS_STOP) ) || ( ( ctrl->Flags & (I2C_FLAGS_START | I2C_FLAGS_STOP) ) == (I2C_FLAGS_START | I2C_FLAGS_STOP) ) ) { // Illegal combination of Command & Flags
return STATUS_INVALID_PARAMETER; } if ( ctrl->Flags & I2C_FLAGS_START ) { if ( adapter->I2CSWStart() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } if ( ctrl->Flags & I2C_FLAGS_STOP ) { if ( adapter->I2CSWStop() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } break;
case I2C_COMMAND_READ: if ( ctrl->Flags & ~(I2C_FLAGS_STOP | I2C_FLAGS_ACK) ) { // Illegal combination of Command & Flags
return STATUS_INVALID_PARAMETER; } if ( adapter->I2CSWRead( &ctrl->Data ) ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } if ( ctrl->Flags & I2C_FLAGS_ACK ) { if ( adapter->I2CSWSendACK() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } else { if ( adapter->I2CSWSendNACK() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } if ( ctrl->Flags & I2C_FLAGS_STOP ) { if ( adapter->I2CSWStop() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } break;
case I2C_COMMAND_WRITE: if ( ctrl->Flags & ~(I2C_FLAGS_START | I2C_FLAGS_STOP | I2C_FLAGS_ACK | I2C_FLAGS_DATACHAINING) ) { // Illegal combination of Command & Flags
return STATUS_INVALID_PARAMETER; } if ( ctrl->Flags & I2C_FLAGS_DATACHAINING ) { if ( adapter->I2CSWStop() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } if ( adapter->I2CSWStart() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } if ( ctrl->Flags & I2C_FLAGS_START ) { if ( adapter->I2CSWStart() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } error = adapter->I2CSWWrite(ctrl->Data);
switch ( error ) {
case I2CERR_NOACK: if ( ctrl->Flags & I2C_FLAGS_ACK ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } break;
case I2CERR_OK: if ( ( ctrl->Flags & I2C_FLAGS_ACK ) == 0 ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } break;
default: ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; }
if ( ctrl->Flags & I2C_FLAGS_STOP ) { if ( adapter->I2CSWStop() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } } break;
case I2C_COMMAND_STATUS: // Flags are ignored
return STATUS_NOT_IMPLEMENTED;
case I2C_COMMAND_RESET: // Flags are ignored
if ( adapter->I2CSWStart() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } if ( adapter->I2CSWStop() ) { ctrl->Status = I2C_STATUS_ERROR; return STATUS_SUCCESS; } break;
default: return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS; }
#else
/* Method: PsDevice::I2COpen
* Purpose: Tries to allocate I2C port to the caller */ NTSTATUS STDMETHODCALLTYPE PsDevice::I2COpen( PDEVICE_OBJECT pdo, ULONG ToOpen, PI2CControl ctrl ) { Trace t("PsDevice::I2COpen()");
DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension)); // need a way to obtain the device pointer
PsDevice *adapter = GetCurrentDevice();
// cookie is not NULL if I2C is open
if ( ToOpen && adapter->dwCurCookie_ ) { ctrl->Flags = I2C_STATUS_BUSY; return STATUS_DEVICE_BUSY; }
// want to close ?
if ( !ToOpen ) if ( adapter->dwCurCookie_ == ctrl->dwCookie ) { adapter->dwCurCookie_ = 0; return STATUS_SUCCESS; } else { ctrl->Flags = I2C_STATUS_BUSY; return STATUS_DEVICE_BUSY; }
// now we are opening
LARGE_INTEGER CurTime; KeQuerySystemTime( &CurTime );
adapter->dwCurCookie_ = CurTime.LowPart; ctrl->dwCookie = adapter->dwCurCookie_; ctrl->ClockRate = 100000;
return STATUS_SUCCESS; }
NTSTATUS STDMETHODCALLTYPE PsDevice::I2CAccess( PDEVICE_OBJECT pdo , PI2CControl ctrl ) { Trace t("PsDevice::I2CAccess()");
DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension)); PsDevice *adapter = GetCurrentDevice();
if ( ctrl->dwCookie != adapter->dwCurCookie_ ) { ctrl->Flags = I2C_STATUS_BUSY; return I2C_STATUS_BUSY; }
ctrl->Flags = I2C_STATUS_NOERROR;
// 848 I2C API currently needs to have an address for both write and read
// commands. So, if START flag is set an address is passed. Cache it and use
// later
switch ( ctrl->Command ) { case I2C_COMMAND_READ: // got 'write' command first ( with the address )
if ( adapter->I2CHWRead( adapter->GetI2CAddress(), &ctrl->Data ) != Success ) ctrl->Flags = I2C_STATUS_ERROR; break; case I2C_COMMAND_WRITE: if ( ctrl->Flags & I2C_FLAGS_START ) { adapter->StoreI2CAddress( ctrl->Data ); } else adapter->I2CHWWrite2( adapter->GetI2CAddress(), ctrl->Data ); break; case I2C_COMMAND_STATUS: if ( adapter->I2CGetLastError() != I2CERR_OK ) ctrl->Flags = I2C_STATUS_ERROR; break; case I2C_COMMAND_RESET: adapter->I2CInitHWMode( 100000 ); // assume frequency = 100Khz
break; } return STATUS_SUCCESS; }
#endif
void HandleIRP( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("HandleIRP()");
DebugOut((1, "HandleIRP(%x)\n", pSrb));
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
PsDevice *adapter = HwDeviceExtension->psdevice;
PIRP Irp = pSrb->Irp; PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation( Irp ); switch ( IrpStack->MajorFunction ) { case IRP_MJ_PNP: if ( IrpStack->MinorFunction == IRP_MN_QUERY_INTERFACE ) {
if ( IsEqualGUID( *IrpStack->Parameters.QueryInterface.InterfaceType, GUID_I2C_INTERFACE ) && IrpStack->Parameters.QueryInterface.Size >= sizeof( I2CINTERFACE ) ) {
IrpStack->Parameters.QueryInterface.InterfaceType = &GUID_I2C_INTERFACE; IrpStack->Parameters.QueryInterface.Size = sizeof( I2CINTERFACE ); IrpStack->Parameters.QueryInterface.Version = 1; I2CINTERFACE *i2ciface = (I2CINTERFACE *)IrpStack->Parameters.QueryInterface.Interface; i2ciface->i2cOpen = &PsDevice::I2COpen; i2ciface->i2cAccess = &PsDevice::I2CAccess; IrpStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
// complete the irp
Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NO_INCREMENT );
break; } else { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER_1; IoCompleteRequest( Irp, IO_NO_INCREMENT ); } } default: pSrb->Status = STATUS_NOT_SUPPORTED; } }
/** CompleteInitialization()
** ** This routine is called when an SRB_COMPLETE_INITIALIZATION request is received ** ** Arguments: ** ** pSrb - pointer to stream request block ** ** Returns: ** ** Side Effects: none */ void STDMETHODCALLTYPE CompleteInitialization( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("CompleteInitialization()");
NTSTATUS Status; PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
PsDevice *adapter = HwDeviceExtension->psdevice;
// Create the Registry blobs that DShow uses to create
// graphs via Mediums
Status = StreamClassRegisterFilterWithNoKSPins ( adapter->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
);
Status = StreamClassRegisterFilterWithNoKSPins ( adapter->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 ( adapter->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 ( adapter->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,
CaptureCategories // IN GUID * CategoryList
);
// go to usual priority, completing the SRB at the same time
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( CompleteDeviceSRB ), pSrb ); }
/*
** AdapterReceivePacket() ** ** Main entry point for receiving adapter based request SRBs. This routine ** will always be called at High Priority. ** ** Note: This is an asyncronous entry point. The request does not 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 ) {
Trace t("AdapterReceivePacket()");
BOOL CompleteRequestSynchronously = TRUE;
//default to success
pSrb->Status = STATUS_SUCCESS;
PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
PsDevice *adapter = HwDeviceExtension->psdevice; //
// determine the type of packet.
//
DebugOut((1, "'AdapterReceivePacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
switch ( pSrb->Command ) { case SRB_INITIALIZE_DEVICE: DebugOut((1, " SRB_INITIALIZE_DEVICE\n"));
CompleteRequestSynchronously = FALSE; // have to schedule a low priority call to open the device because
// registry functions are used during initialization
StreamClassCallAtNewPriority( pSrb->StreamObject, pSrb->HwDeviceExtension, Low, PHW_PRIORITY_ROUTINE( HwInitialize ), pSrb );
break;
case SRB_UNINITIALIZE_DEVICE: DebugOut((1, " SRB_UNINITIALIZE_DEVICE\n"));
// close the device.
HwUnInitialize(pSrb);
break;
case SRB_OPEN_STREAM: DebugOut((1, " SRB_OPEN_STREAM\n"));
// open a stream
AdapterOpenStream( pSrb );
break;
case SRB_CLOSE_STREAM: DebugOut((1, " SRB_CLOSE_STREAM\n"));
// close a stream
AdapterCloseStream( pSrb );
break;
case SRB_GET_STREAM_INFO: DebugOut((1, " SRB_GET_STREAM_INFO\n"));
//
// return a block describing all the streams
//
AdapterStreamInfo(pSrb);
break;
case SRB_GET_DEVICE_PROPERTY: DebugOut((1, " SRB_GET_DEVICE_PROPERTY\n")); AdapterGetProperty( pSrb ); break;
case SRB_SET_DEVICE_PROPERTY: DebugOut((1, " SRB_SET_DEVICE_PROPERTY\n")); AdapterSetProperty( pSrb ); break;
case SRB_GET_DATA_INTERSECTION: DebugOut((1, " SRB_GET_DATA_INTERSECTION\n"));
//
// Return a format, given a range
//
AdapterFormatFromRange( pSrb );
break; case SRB_INITIALIZATION_COMPLETE: DebugOut((1, " SRB_INITIALIZATION_COMPLETE\n"));
//
// Stream class has finished initialization.
// Now create DShow Medium interface BLOBs.
// This needs to be done at low priority since it uses the registry, so use a callback
//
CompleteRequestSynchronously = FALSE;
StreamClassCallAtNewPriority( NULL /*pSrb->StreamObject*/, pSrb->HwDeviceExtension, Low, PHW_PRIORITY_ROUTINE( CompleteInitialization), pSrb );
break;
case SRB_PAGING_OUT_DRIVER: if ( (*(DWORD*)(gpjBaseAddr+0x10c) & 3) || (*(DWORD*)(gpjBaseAddr+0x104)) ) { DebugOut((0, " ****** SRB_PAGING_OUT_DRIVER ENB(%x) MSK(%x)\n", *(DWORD*)(gpjBaseAddr+0x10c) & 3, *(DWORD*)(gpjBaseAddr+0x104) ));
*(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
*(DWORD*)(gpjBaseAddr+0x104) = 0; // disable interrupts [TMZ] [!!!]
} break;
case SRB_UNKNOWN_DEVICE_COMMAND: DebugOut((1, " SRB_UNKNOWN_DEVICE_COMMAND\n")); HandleIRP( pSrb ); break;
// We should never get the following 2 since this is a single instance
// device
case SRB_OPEN_DEVICE_INSTANCE: case SRB_CLOSE_DEVICE_INSTANCE: default: //
// this is a request that we do not understand. Indicate invalid
// command and complete the request
//
DebugOut((0, "SRB(%x) not recognized by this driver\n", pSrb->Command)); pSrb->Status = STATUS_NOT_IMPLEMENTED; }
//
// Most, but not all SRBs are handled synchronously here
//
if ( CompleteRequestSynchronously ) { CompleteDeviceSRB( pSrb ); } }
/*
** 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 ) { Trace t("AdapterCancelPacket()");
VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
DebugOut((1, "AdapterCancelPacket - pSrb(%x) strm(%d)\n", pSrb, StreamNumber));
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
pSrb->Status = STATUS_CANCELLED; //
// it is necessary to call the request back correctly. Determine which
// type of command it is
//
switch ( pSrb->Flags & (SRB_HW_FLAGS_DATA_TRANSFER | SRB_HW_FLAGS_STREAM_REQUEST ) ) { //
// find all stream commands, and do stream notifications
//
case SRB_HW_FLAGS_STREAM_REQUEST | SRB_HW_FLAGS_DATA_TRANSFER: DebugOut((1, " Canceling data SRB\n" ) ); // adapter->Stop( *chan ); [!!!] [TMZ] [???] why is this commented out???
if (!chan->RemoveSRB( pSrb )) { DebugOut((0, " Canceling data SRB failed\n")); DEBUG_BREAKPOINT(); } break; case SRB_HW_FLAGS_STREAM_REQUEST: DebugOut((1, " Canceling control SRB\n" ) ); CheckSrbStatus( pSrb ); StreamClassStreamNotification( ReadyForNextStreamControlRequest, pSrb->StreamObject ); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); break; default: //
// this must be a device request. Use device notifications
//
DebugOut((1, " Canceling SRB per device request\n" ) ); StreamClassDeviceNotification( ReadyForNextDeviceRequest, pSrb->HwDeviceExtension );
StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb ); } }
/*
** 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 ) { Trace t("AdapterTimeoutPacket()");
DebugOut((0, "AdapterTimeoutPacket (incomplete) - pSrb(%x)\n", pSrb));
// [TMZ] Fix this
#if SHOW_BUILD_MSGS
#pragma message("*** AdapterTimeoutPacket needs to be completed")
#endif
DebugOut((0, " pSrb->Flags = %x\n", pSrb->Flags));
if ( pSrb->Flags & SRB_HW_FLAGS_STREAM_REQUEST ) { DebugOut((0, " SRB_HW_FLAGS_STREAM_REQUEST\n")); } if ( pSrb->Flags & SRB_HW_FLAGS_DATA_TRANSFER ) { DebugOut((0, " SRB_HW_FLAGS_DATA_TRANSFER\n")); }
//
// if we timeout while playing, then we need to consider this
// condition an error, and reset the hardware, and reset everything
// as well as cancelling this and all requests
//
//
// if we are not playing, and this is a CTRL request, we still
// need to reset everything as well as cancelling this and all requests
//
//
// if this is a data request, and the device is paused, we probably have
// run out of data buffer, and need more time, so just reset the timer,
// and let the packet continue
//
pSrb->TimeoutCounter = pSrb->TimeoutOriginal; }
/*
** HwInterrupt() ** ** Routine is called when an interrupt at the IRQ level specified by the ** ConfigInfo structure passed to the HwInitialize routine is received. ** ** Note: IRQs may be shared, so the device should ensure the IRQ received ** was expected ** ** Arguments: ** ** pHwDevEx - the device extension for the hardware interrupt ** ** Returns: ** ** Side Effects: none */
BOOLEAN HwInterrupt( IN PHW_DEVICE_EXTENSION HwDeviceExtension ) { Trace t("HwInterrupt()"); DebugOut((1, "HwInterrupt called by system\n")); PsDevice *adapter = (PsDevice *)(HwDeviceExtension->psdevice); BOOLEAN b = adapter->Interrupt(); return( b ); }
/* Function: CompleteDeviceSRB
* Purpose: Called to complete a device SRB * Input: pSrb */ inline void CompleteDeviceSRB( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("CompleteDeviceSRB()"); StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb ); StreamClassDeviceNotification( ReadyForNextDeviceRequest, pSrb->HwDeviceExtension ); }
/*
** AdapterCompareGUIDsAndFormatSize() ** ** Checks for a match on the three GUIDs and FormatSize ** ** Arguments: ** ** IN DataRange1 ** IN DataRange2 ** ** Returns: ** ** TRUE if all elements match ** FALSE if any are different ** ** Side Effects: none */
bool AdapterCompareGUIDsAndFormatSize( IN const PKSDATARANGE DataRange1, IN const PKSDATARANGE DataRange2 ) { Trace t("AdapterCompareGUIDsAndFormatSize()");
bool bCheckSize = false;
#if 1 // use old guid verify
return ( IsEqualGUID( DataRange1->MajorFormat, DataRange2->MajorFormat ) && IsEqualGUID( DataRange1->SubFormat, DataRange2->SubFormat ) && IsEqualGUID( DataRange1->Specifier, DataRange2->Specifier ) && ( DataRange1->FormatSize == DataRange2->FormatSize ) ); #else // use new guid verify from cc decoder
bool rval = false;
if ( IsEqualGUID(DataRange1->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD) || IsEqualGUID(DataRange2->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD) || IsEqualGUID(DataRange1->MajorFormat, DataRange2->MajorFormat) ) { if ( !IsEqualGUID(DataRange1->MajorFormat, DataRange2->MajorFormat) ) { DebugOut((0, "Match 1\n" )); }
if ( IsEqualGUID(DataRange1->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD) || IsEqualGUID(DataRange2->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD) || IsEqualGUID(DataRange1->SubFormat, DataRange2->SubFormat) ) { if ( !IsEqualGUID(DataRange1->SubFormat, DataRange2->SubFormat) ) { DebugOut((0, "Match 2\n" )); }
if ( IsEqualGUID(DataRange1->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD) || IsEqualGUID(DataRange2->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD) || IsEqualGUID(DataRange1->Specifier, DataRange2->Specifier) ) { if ( !IsEqualGUID(DataRange1->Specifier, DataRange2->Specifier) ) { DebugOut((0, "Match 3\n" )); }
if ( !bCheckSize || DataRange1->FormatSize == DataRange2->FormatSize) { DebugOut((0, "Victory !!!\n" )); rval = true; } else { DebugOut((0, "FormatSize Mismatch\n" )); } } else { DebugOut((0, "Specifier Mismatch\n" )); } } else { DebugOut((0, "SubFormat Mismatch\n" )); } } else { DebugOut((0, "MajorFormat Mismatch\n" )); }
DebugOut((0, "CompareGUIDsAndFormatSize(\n")); DebugOut((0, " DataRange1=%x\n", DataRange1)); DebugOut((0, " DataRange2=%x\n", DataRange2)); DebugOut((0, " bCheckSize=%s\n", bCheckSize ? "TRUE":"FALSE")); DebugOut((0, ")\n")); DebugOut((0, "returning %s\n", rval? "TRUE":"FALSE"));
return rval; #endif
}
/*
** AdapterFormatFromRange() ** ** Returns a DATAFORMAT from a DATARANGE ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** ** Returns: ** ** TRUE if the format is supported ** FALSE if the format cannot be suppored ** ** Side Effects: none */ void AdapterFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AdapterFormatFromRange()");
PSTREAM_DATA_INTERSECT_INFO IntersectInfo; PKSDATARANGE DataRange; ULONG FormatSize=0; 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; return; }
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?
//
bool 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 ) ) { 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;
//
// 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 ) ) ) { DebugOut(( 1, "AdapterFormatFromRange(): at least one field does not match\n" )); continue; }
// MATCH FOUND!
FormatSize = sizeof( KSDATAFORMAT ) + KS_SIZE_VIDEOHEADER( &DataRangeVideoToVerify->VideoInfoHeader );
if ( OnlyWantsSize ) { break; }
// Caller wants the full data format
if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize ) { DebugOut(( 1, "AdapterFormatFromRange(): STATUS_BUFFER_TOO_SMALL\n" )); pSrb->Status = STATUS_BUFFER_TOO_SMALL; return; }
// Copy over the KSDATAFORMAT, followed by the
// actual VideoInfoHeader
PKS_DATAFORMAT_VIDEOINFOHEADER InterVidHdr = (PKS_DATAFORMAT_VIDEOINFOHEADER)IntersectInfo->DataFormatBuffer;
RtlCopyMemory( &InterVidHdr->DataFormat, &DataRangeVideoToVerify->DataRange, sizeof( KSDATARANGE ) );
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
RtlCopyMemory( &InterVidHdr->VideoInfoHeader, &DataRangeVideoToVerify->VideoInfoHeader, KS_SIZE_VIDEOHEADER( &DataRangeVideoToVerify->VideoInfoHeader ) );
// report back the omage size as we know it
KS_VIDEOINFOHEADER &vidHDR = DataRangeVideoToVerify->VideoInfoHeader;
#ifdef HACK_FUDGE_RECTANGLES
// [!!!] [TMZ] - hack
if( vidHDR.rcTarget.bottom == 0 ) { vidHDR.rcTarget.left = 0; vidHDR.rcTarget.top = 0; vidHDR.rcTarget.right = vidHDR.bmiHeader.biWidth; vidHDR.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight); } if( InterVidHdr->VideoInfoHeader.rcTarget.bottom == 0 ) { InterVidHdr->VideoInfoHeader.rcTarget.left = 0; InterVidHdr->VideoInfoHeader.rcTarget.top = 0; InterVidHdr->VideoInfoHeader.rcTarget.right = vidHDR.bmiHeader.biWidth; InterVidHdr->VideoInfoHeader.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight); } #endif
MSize size; GetRequestedSize( vidHDR, size );
ColorSpace tmpCol( DataRange->SubFormat ); MRect dst( vidHDR.rcTarget );
// make sure the dimentions are acceptable
if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) && tmpCol.CheckLeftTop( dst.TopLeft() ) ) { // if width is different, use it ( in bytes ) to calculate the size
if ( vidHDR.bmiHeader.biWidth != size.cx ) { InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage = vidHDR.bmiHeader.biWidth * abs(vidHDR.bmiHeader.biHeight); } else { InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage = size.cx * tmpCol.GetBitCount() * abs(vidHDR.bmiHeader.biHeight) / 8; }
DebugOut((1, "InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage = %d\n", InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage)); break; } else { pSrb->Status = STATUS_BUFFER_TOO_SMALL; DebugOut((1, "AdapterFormatFromRange: Buffer too small\n")); return; } } // End of VIDEOINFOHEADER specifier
// -------------------------------------------------------------------
// Specifier FORMAT_VideoInfo2 for VIDEOINFOHEADER2
// -------------------------------------------------------------------
else if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) ) {
PKS_DATARANGE_VIDEO2 DataRangeVideoToVerify = (PKS_DATARANGE_VIDEO2) DataRange; PKS_DATARANGE_VIDEO2 DataRangeVideo = (PKS_DATARANGE_VIDEO2) *pAvailableFormats;
//
// 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 ) ) ) { DebugOut(( 1, "AdapterFormatFromRange(): at least one field does not match\n" )); continue; }
// MATCH FOUND!
FormatSize = sizeof( KSDATAFORMAT ) + KS_SIZE_VIDEOHEADER2( &DataRangeVideoToVerify->VideoInfoHeader );
if ( OnlyWantsSize ) { break; }
// Caller wants the full data format
if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize ) { DebugOut(( 1, "AdapterFormatFromRange(): STATUS_BUFFER_TOO_SMALL\n" )); pSrb->Status = STATUS_BUFFER_TOO_SMALL; return; }
// Copy over the KSDATAFORMAT, followed by the
// actual VideoInfoHeader
PKS_DATAFORMAT_VIDEOINFOHEADER2 InterVidHdr = (PKS_DATAFORMAT_VIDEOINFOHEADER2)IntersectInfo->DataFormatBuffer;
RtlCopyMemory( &InterVidHdr->DataFormat, &DataRangeVideoToVerify->DataRange, sizeof( KSDATARANGE ) );
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
RtlCopyMemory( &InterVidHdr->VideoInfoHeader2, &DataRangeVideoToVerify->VideoInfoHeader, KS_SIZE_VIDEOHEADER2( &DataRangeVideoToVerify->VideoInfoHeader ) );
// report back the omage size as we know it
KS_VIDEOINFOHEADER2 &vidHDR = DataRangeVideoToVerify->VideoInfoHeader;
#ifdef HACK_FUDGE_RECTANGLES
// [!!!] [TMZ] - hack
if( vidHDR.rcTarget.bottom == 0 ) { vidHDR.rcTarget.left = 0; vidHDR.rcTarget.top = 0; vidHDR.rcTarget.right = vidHDR.bmiHeader.biWidth; vidHDR.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight); } if( InterVidHdr->VideoInfoHeader.rcTarget.bottom == 0 ) { InterVidHdr->VideoInfoHeader.rcTarget.left = 0; InterVidHdr->VideoInfoHeader.rcTarget.top = 0; InterVidHdr->VideoInfoHeader.rcTarget.right = vidHDR.bmiHeader.biWidth; InterVidHdr->VideoInfoHeader.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight); } #endif
MSize size; GetRequestedSize2( vidHDR, size );
ColorSpace tmpCol( DataRange->SubFormat ); MRect dst( vidHDR.rcTarget );
// make sure the dimentions are acceptable
if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) && tmpCol.CheckLeftTop( dst.TopLeft() ) ) { // if width is different, use it ( in bytes ) to calculate the size
if ( vidHDR.bmiHeader.biWidth != size.cx ) { InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage = vidHDR.bmiHeader.biWidth * abs(vidHDR.bmiHeader.biHeight); } else { InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage = size.cx * tmpCol.GetBitCount() * abs(vidHDR.bmiHeader.biHeight) / 8; }
DebugOut((1, "InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage = %d\n", InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage)); break; } else { pSrb->Status = STATUS_BUFFER_TOO_SMALL; DebugOut((1, "AdapterFormatFromRange: Buffer too small\n")); return; } } // End of VIDEOINFOHEADER2 specifier
// -------------------------------------------------------------------
// 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 pDataRangeVideo = (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
// MATCH FOUND!
FormatSize = sizeof( KS_DATARANGE_ANALOGVIDEO );
if ( OnlyWantsSize ) { break; }
// Caller wants the full data format
if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize ) { pSrb->Status = STATUS_BUFFER_TOO_SMALL; DebugOut((1, "AdapterFormatFromRange: Buffer too small\n")); return; } RtlCopyMemory( IntersectInfo->DataFormatBuffer, pDataRangeVideo, sizeof( KS_DATARANGE_ANALOGVIDEO ) );
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
break;
} else { if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VBI ) ) { PKS_DATARANGE_VIDEO_VBI pDataRangeVBI = (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
FormatSize = sizeof( KS_DATAFORMAT_VBIINFOHEADER );
if ( OnlyWantsSize ) { break; }
// Caller wants the full data format
if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize ) { pSrb->Status = STATUS_BUFFER_TOO_SMALL; DebugOut((1, "AdapterFormatFromRange: Buffer too small\n")); return; } // Copy over the KSDATAFORMAT, followed by the
// actual VideoInfoHeader
PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr = (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;
RtlCopyMemory( &InterVBIHdr->DataFormat, &pDataRangeVBI->DataRange, sizeof( KSDATARANGE ) );
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
RtlCopyMemory( &InterVBIHdr->VBIInfoHeader, &pDataRangeVBI->VBIInfoHeader, sizeof( KS_VBIINFOHEADER ) );
break; } else { DebugOut(( 0, "AdapterFormatFromRange: STATUS_NO_MATCH\n" )); pSrb->Status = STATUS_NO_MATCH; return; } }
} // End of loop on all formats for this stream
if ( OnlyWantsSize ) { DebugOut(( 2, "AdapterFormatFromRange: only wants size\n" )); *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize; pSrb->ActualBytesTransferred = sizeof( ULONG ); return; } pSrb->ActualBytesTransferred = FormatSize; DebugOut(( 2, "AdapterFormatFromRange: done\n" ));
return; }
|