📄 tuner.cpp
字号:
/*+++ *******************************************************************\
*
* Copyright and Disclaimer:
*
* ---------------------------------------------------------------
* This software 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) 1999-2000 Conexant Systems, Inc.
* All Rights Reserved.
* ---------------------------------------------------------------
*
* Abstract:
*
* This module is responsible for handling tuner driver SRBs.
*
\******************************************************************* ---*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#define INITGUID
#include "tuner.h"
#include "prop.h"
#include "debug.h"
#include "drv2user.h"
#include "drv2002.h"
LONG gDebugLevel = 0;
BOOL gBreakOnError = TRUE;
// tuner pin guid definitions
KSPIN_MEDIUM TVTunerMediums[ 2 ] = {
{ M_GUID0, 0, 0}, // Pin 0
{ M_GUID1, 0, 0}, // Pin 1
};
// tuner pin directions
BOOL TVTunerPinDirection[ 2 ] = {
TRUE, // Output Pin 0
TRUE, // Output Pin 1
};
/*++ ********************************************************************\
*
* Function:
*
* ULONG GetSystemTime( )
*
* Purpose:
*
* Return the system tick time.
*
* Return:
* ULONG - system tick time.
*
* History:
*
*
\******************************************************************** --*/
ULONG GetSystemTime()
{
ULONGLONG ticks;
ULONGLONG rate;
ticks = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).
QuadPart;
//
// convert from ticks to 100ns clock
//
ticks = (ticks & 0xFFFFFFFF00000000) / rate * 10000000 + (ticks &
0xFFFFFFFF) * 10000000 / rate;
return (ULONG)(ticks);
}
/*++ ********************************************************************\
*
* Function:
*
* ULONG DriverEntry( PDRIVER_OBJECT pPDO,
* PUNICODE_STRING pRegistryPath )
*
* Purpose:
*
* Initializes the driver, and creates objects needed
* to process I/O
*
* Return:
* Return value from:
* StreamClassRegisterAdapter
*
* History:
*
*
\******************************************************************** --*/
ULONG DriverEntry( PDRIVER_OBJECT pPDO, PUNICODE_STRING pRegistryPath )
{
HW_INITIALIZATION_DATA HwInitData;
RtlZeroMemory( &HwInitData, sizeof(HwInitData) );
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
HwInitData.HwInterrupt = NULL;
HwInitData.HwReceivePacket = TunerReceivePacket;
HwInitData.HwCancelPacket = TunerCancelPacket;
HwInitData.HwRequestTimeoutHandler = TunerTimeoutPacket;
HwInitData.DeviceExtensionSize = sizeof(TUNER_DATA_EXTENSION);
HwInitData.PerRequestExtensionSize = sizeof(SRB_DATA_EXTENSION);
HwInitData.FilterInstanceExtensionSize = 4;
HwInitData.PerStreamExtensionSize = 0;
HwInitData.BusMasterDMA = FALSE;
HwInitData.Dma24BitAddresses = FALSE;
HwInitData.BufferAlignment = 4;
HwInitData.TurnOffSynchronization = TRUE;
HwInitData.DmaBufferSize = 0;
return( StreamClassRegisterAdapter( pPDO, pRegistryPath, &HwInitData ) );
}
/*++ ********************************************************************\
*
* Function:
*
* void TunerCompleteDeviceSrb( PHW_STREAM_REQUEST_BLOCK pSrb )
*
* Purpose:
*
* Notify the stream class that we completed the SRB
*
* Return:
* none
*
* History:
*
*
\******************************************************************** --*/
void TunerCompleteDeviceSrb( PHW_STREAM_REQUEST_BLOCK pSrb )
{
StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb );
}
/*++ ********************************************************************\
*
* AddToListIfBusy ( PHW_STREAM_REQUEST_BLOCK pSrb,
* KSPIN_LOCK *SpinLock,
* BOOL *BusyFlag,
* LIST_ENTRY *ListHead )
*
* Purpose:
*
* Grabs a spinlock, checks the busy flag, and if set adds an SRB to a queue
*
* Returns:
*
* The state of the busy flag on entry. This will be TRUE if we're already
* processing an SRB, and FALSE if no SRB is already in progress.
*
* History:
*
*
\******************************************************************** --*/
BOOL STREAMAPI AddToListIfBusy ( IN PHW_STREAM_REQUEST_BLOCK pSrb,
IN KSPIN_LOCK *SpinLock,
IN OUT BOOL *BusyFlag,
IN LIST_ENTRY *ListHead )
{
KIRQL Irql;
PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
KeAcquireSpinLock (SpinLock, &Irql);
// If we're already processing another SRB, add this current request
// to the queue and return TRUE
if (*BusyFlag == TRUE)
{
// Save the SRB pointer away in the SRB Extension
pSrbExt->pSrb = pSrb;
InsertTailList(ListHead, &pSrbExt->ListEntry);
KeReleaseSpinLock(SpinLock, Irql);
return TRUE;
}
// Otherwise, set the busy flag, release the spinlock, and return FALSE
*BusyFlag = TRUE;
KeReleaseSpinLock(SpinLock, Irql);
return FALSE;
}
/*++ ********************************************************************\
*
* RemoveFromListIfAvailable ( PHW_STREAM_REQUEST_BLOCK *pSrb,
* KSPIN_LOCK *SpinLock,
* BOOL *BusyFlag,
* LIST_ENTRY *ListHead )
*
* Purpose:
*
* Grabs a spinlock, checks for an available SRB, and removes it from the list
*
* Return:
*
* TRUE - if an SRB was removed from the list
* FALSE - if the list is empty
*
* History:
*
*
\******************************************************************** --*/
BOOL STREAMAPI RemoveFromListIfAvailable ( IN OUT PHW_STREAM_REQUEST_BLOCK *pSrb,
IN KSPIN_LOCK *SpinLock,
IN OUT BOOL *BusyFlag,
IN LIST_ENTRY *ListHead )
{
KIRQL Irql;
KeAcquireSpinLock (SpinLock, &Irql);
// If the queue is now empty, clear the busy flag, and return
if (IsListEmpty(ListHead))
{
*BusyFlag = FALSE;
KeReleaseSpinLock(SpinLock, Irql);
return FALSE;
}
// otherwise extract the SRB
else
{
PUCHAR ptr;
PSRB_EXTENSION pSrbExt;
ptr = (PUCHAR)RemoveHeadList(ListHead);
*BusyFlag = TRUE;
KeReleaseSpinLock(SpinLock, Irql);
// Get the SRB out of the SRB extension and return it
pSrbExt = (PSRB_EXTENSION) (((PUCHAR) ptr) -
FIELDOFFSET(SRB_EXTENSION, ListEntry));
*pSrb = pSrbExt->pSrb;
}
return TRUE;
}
/*++ ********************************************************************\
*
* Function:
*
* void TunerReceivePacket( PHW_STREAM_REQUEST_BLOCK pSrb )
*
* Purpose:
*
* Main function for handling all SRBs received by driver
*
* Return:
*
* none
*
* History:
*
*
\******************************************************************** --*/
void STREAMAPI TunerReceivePacket( PHW_STREAM_REQUEST_BLOCK pSrb)
{
BOOL Busy;
PTUNER_DATA_EXTENSION pTunerDataExt = (PTUNER_DATA_EXTENSION)pSrb->HwDeviceExtension;
if( ( pTunerDataExt == NULL ) || ( pSrb->SRBExtension == NULL ) )
{
KdBreakPoint();
pSrb->Status = STATUS_INVALID_PARAMETER;
TunerCompleteDeviceSrb( pSrb );
}
// The very first time through, we need to initialize the adapter spinlock
// and queue
if (!pTunerDataExt->bAdapterQueueInitialized)
{
InitializeListHead (&pTunerDataExt->leSrbQueueHead);
KeInitializeSpinLock (&pTunerDataExt->ksSpinLock);
pTunerDataExt->bAdapterQueueInitialized = TRUE;
pTunerDataExt->bProcessingAdapterSRB = FALSE;
}
// If we're already processing an SRB, add it to the queue
Busy = AddToListIfBusy (
pSrb,
&pTunerDataExt->ksSpinLock,
&pTunerDataExt->bProcessingAdapterSRB,
&pTunerDataExt->leSrbQueueHead );
if (Busy)
{
return; // queue is not empty
}
// This will run until the SRB queue is empty
while (TRUE)
{
// Assume success for now
pSrb->Status = STATUS_SUCCESS;
// process SRB
switch (pSrb->Command)
{
case SRB_INITIALIZE_DEVICE:
TunerInitialize( pSrb );
break;
case SRB_INITIALIZATION_COMPLETE:
TunerCompleteInitialization( pSrb );
break;
case SRB_UNINITIALIZE_DEVICE:
TunerUnInitialize( pSrb );
break;
case SRB_OPEN_STREAM:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_CLOSE_STREAM:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_GET_STREAM_INFO:
TunerGetStreamInfo( pSrb );
break;
case SRB_CHANGE_POWER_STATE:
pSrb->Status = TunerSetPowerState( pSrb );
pSrb->Status = STATUS_SUCCESS;
break;
case SRB_GET_DEVICE_PROPERTY:
AdapterGetProperty( pSrb );
break;
case SRB_SET_DEVICE_PROPERTY:
AdapterSetProperty( pSrb );
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -