/***************************************************************************** Company : Shree Ganesha Inc. File Name : SkyWalker1Device.cpp Author : Date : Purpose : Main Skywalker Device level Implementation Revision History: =============================================================================== DATE VERSION AUTHOR REMARK =============================================================================== 01 Initial Version *****************************************************************************/ /* Include the Library and Other header file */ #include "SkyWalker1Main.h" //Header for the Tuner related definitions /* End of Inclusion the Library and Other header file */ /* Macro Definitions */ /* End of Macro Definitions */ /* Global & Static variables Declaration */ static ULONG ulDeviceInstance = 0; /* End of Global & Static variables Declaration */ /* External Variable Declaration */ /* End of External Variable Declaration */ /* Declare Enumerations here */ /* End of Enumeration declaration */ /* Function Prototypes */ void PrintDMAAdapter(PDMA_ADAPTER pDMAAdapter); void PrintMappingInfo(IN PKSMAPPING pMapping); /* End of Function prototype definitions */ /***************************************************************************** Function : CSkyWalker1Device::Create Description : This Function is called during the Add Device IRP Processing IN PARAM : Pointer to the Enumerated Physical Device KSDEVICE is a WDM Functional Device which is managed by the AVStream OUT PARAM : ntStatus of the Device Addition STATUS_SUCCESS when the Device added to the System Reason for Failure incase of Error PreCondition : Driver is Loaded without Functional/ Filter Device Objects PostCondtion : Functional Device Object [FDO] or Filter Device Object [FiDO] are created Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Create(IN PKSDEVICE pKSDeviceObject) { NTSTATUS ntCreateStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); if (pKSDeviceObject) { //Point the KSDEVICE at our device class. pKSDeviceObject->Context = this; m_pKSDevice = pKSDeviceObject; //Make the resource available for a filter to use. m_ulcResourceUsers = 0; m_ulCurResourceID = 0; //Get the instance number of this device. m_ulDeviceInstance = ulDeviceInstance++; //Hold requests until the device is started QueueState = HoldRequests; //Initialize the stop event to signaled. KeInitializeEvent(&EvDeviceStopOk, //PKEVENT NotificationEvent, //Type TRUE); //State //Initialize the remove event to not-signaled. KeInitializeEvent(&EvDeviceRemoveOk, //PKEVENT NotificationEvent, //Type FALSE); //State //The KeInitializeSpinLock routine initializes a variable of //type KSPIN_LOCK. KeInitializeSpinLock(&DeviceStateLock); INITIALIZE_PNP_STATE(this); //OutstandingIo count biased to 1. //Transition to 0 during remove device means IO is finished. //Transition to 1 means the device can be stopped ulOutStandingIoCount = 1; KeInitializeSpinLock(&kIoCountLock); } else { SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid KS Device Object Received\n")); ntCreateStatus = STATUS_INVALID_PARAMETER; } PrintFunctionExit(__FUNCTION__,ntCreateStatus); return ntCreateStatus; } /***************************************************************************** Function : CSkyWalker1Device::Start Description : This function Initializes the Tuner Hardware IN PARAM : Reference to Device to be Started IoRequest Packet Resource List Translated Resource List OUT PARAM : ntStatus of the Tuner Start STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : Stopped Device or Device Enumerated for the First Time PostCondtion : Device Initialized with the Newly allocated Resources, Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Start( IN PKSDEVICE pKSDeviceObject, IN PIRP pIoRequestPacket, IN PCM_RESOURCE_LIST pResourceList OPTIONAL, IN PCM_RESOURCE_LIST pTranslatedResourceList OPTIONAL ) { NTSTATUS ntStartStatus = STATUS_SUCCESS; CSkyWalker1Device * pDevice = NULL; PKSFILTERFACTORY pKSFilterFactory = NULL; PrintFunctionEntry(__FUNCTION__); pDevice = reinterpret_cast(pKSDeviceObject->Context); //Initialize the Tuner Hardware. ntStartStatus = pDevice->InitializeTuner(pKSDeviceObject,pIoRequestPacket); SkyWalkerDebugPrint(EXTREME_LEVEL,("USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE = %d",USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE)); if (ntStartStatus == STATUS_SUCCESS) { //Create the the Filter Factory. This factory is used to //create instances of the filter. ntStartStatus = BdaCreateFilterFactoryEx( pKSDeviceObject, &SkyWalker1TunerFilterDescriptor, &TunerFilterTemplate, &pKSFilterFactory ); } if ((ntStartStatus == STATUS_SUCCESS) && pKSFilterFactory) { BdaFilterFactoryUpdateCacheData( pKSFilterFactory, TunerFilterTemplate.pFilterDescriptor ); } PrintFunctionExit(__FUNCTION__,ntStartStatus); return ntStartStatus; } /***************************************************************************** Function : CSkyWalker1Device::Stop Description : This routine is invoked when the device is stopped. This routine services Irp of minor type IRP_MN_STOP_DEVICE IN PARAM : Pointer to KS Device Object STOP DEVICE Irp OUT PARAM : ntStatus of the Device Stop STATUS_SUCCESS on Successful execution else Error PreCondition : NONE PostCondtion : USB Device Stopped Logic : NONE Assumption : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Stop( IN PKSDEVICE pKSDeviceObject, IN PIRP pIoRequestPacket) { NTSTATUS ntDeviceStopStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); if(m_pDMAAdapter) { m_pDMAAdapter->DmaOperations->PutDmaAdapter(m_pDMAAdapter); m_pDMAAdapter = NULL; } //Maintain the USB ntStatus i.e Remove the Selected Configuration by sending Null descriptor ntDeviceStopStatus = StopUsbDevice(pKSDeviceObject,pIoRequestPacket); PrintFunctionExit(__FUNCTION__,ntDeviceStopStatus); return ntDeviceStopStatus; } /***************************************************************************** Function : CSkyWalker1Device::Close Description : This routine is invoked when the device is Removed. This routine services Irp of minor type IRP_MN_REMOVE_DEVICE IN PARAM : Pointer to KS Device Object STOP DEVICE Irp OUT PARAM : ntStatus of the Device Remove STATUS_SUCCESS on Successful execution else Error PreCondition : NONE PostCondtion : USB Device Removed Logic : NONE Assumption : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Close( IN PKSDEVICE pKSDeviceObject, IN PIRP pIoRequestPacket) { NTSTATUS ntDeviceCloseStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); ntDeviceCloseStatus = RemoveUsbDevice(pKSDeviceObject,pIoRequestPacket); PrintFunctionExit(__FUNCTION__,ntDeviceCloseStatus); return ntDeviceCloseStatus; } /***************************************************************************** Function : CSkyWalker1Device::SetPower Description : This routine is invoked when the Power Irp is received This routine services Irp of minor type IRP_MJ_POWER IN PARAM : Pointer to KS Device Object STOP DEVICE Irp OUT PARAM : ntStatus of the Set POwer STATUS_SUCCESS on Successful execution else Error PreCondition : NONE PostCondtion : Power Condition Managed Logic : NONE Assumption : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::SetPower( IN PKSDEVICE pKSDeviceObject, //Pointer to the device object //provided by the system. IN PIRP pIoRequestPacket, //Pointer to the IRP related to this request. IN DEVICE_POWER_STATE To, //Requested power state. IN DEVICE_POWER_STATE From //Current power state. ) { NTSTATUS ntSetPowerStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Set USB Power condition from here PrintFunctionExit(__FUNCTION__,ntSetPowerStatus); return ntSetPowerStatus; } /***************************************************************************** Function : CSkyWalker1Device::InitializeTuner Description : This function is used to setup and initialize the Tuner Interface IN PARAM : Reference to Device to be Started IoRequest Packet OUT PARAM : ntStatus of the Tuner Initializations STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : Stopped Device or Device Enumerated for the First Time PostCondtion : Device Initialized with the Newly allocated Resources, Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::InitializeTuner( IN PKSDEVICE pKSDeviceObject, IN PIRP pIoRequestPacket) { NTSTATUS ntInitStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Initialize the USB hardware here. ntInitStatus = InitializeUsbDevice(pKSDeviceObject,pIoRequestPacket); if(!NT_SUCCESS(ntInitStatus)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("Failed to Initialize the USB Device\n")); goto ExitInitTuner; } //Setup the SkyWalker1 Device ntInitStatus = SetupTunerPower(pKSDeviceObject,SWITCH_ON_TUNER); if(!NT_SUCCESS(ntInitStatus)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("Failed to Setup the SkyWalker1 Device\n")); goto ExitInitTuner; } //Initialize Adapter ntInitStatus = InitializeAdapterStream(pKSDeviceObject); if(!NT_SUCCESS(ntInitStatus)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("Failed to Initialize the Adapter Stream\n")); goto ExitInitTuner; } ExitInitTuner: PrintFunctionExit(__FUNCTION__,ntInitStatus); return ntInitStatus; } /***************************************************************************** Function : CSkyWalker1Device::InitializeAdapterStream Description : This function is used to Register the Adapter Object and setup the Private Memory for the Streams IN PARAM : Reference to KS Device Object OUT PARAM : ntStatus of the Adapter Stream Initialization STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Adapter Object Registered with the AVStream and Streaming Memory allocated Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::InitializeAdapterStream( IN PKSDEVICE pKSDeviceObject) { NTSTATUS ntInitStatus = STATUS_SUCCESS; DEVICE_DESCRIPTION DeviceDescription; //Object to hold the Device description ULONG ulMaxDMAMapRegisters = 0L; PrintFunctionEntry(__FUNCTION__); //Create DMA adapter memset(&DeviceDescription, 0, sizeof(DeviceDescription)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.Master = TRUE; DeviceDescription.ScatterGather = TRUE; DeviceDescription.Dma32BitAddresses = TRUE; DeviceDescription.Dma64BitAddresses = FALSE; DeviceDescription.DmaChannel = ((ULONG) ~0); DeviceDescription.InterfaceType = PCIBus; DeviceDescription.MaximumLength = 0xfffffff8; //not used DeviceDescription.IgnoreCount; DeviceDescription.DemandMode; DeviceDescription.AutoInitialize; DeviceDescription.DmaWidth; DeviceDescription.Reserved1; DeviceDescription.DmaSpeed; DeviceDescription.DmaPort; //The IoGetDmaAdapter routine returns a pointer to the DMA adapter structure //for a physical device object. m_pDMAAdapter = IoGetDmaAdapter( pKSDeviceObject->PhysicalDeviceObject, //Pointer to Physical Device Object //requesting the DMA Adapter structure &DeviceDescription, //Pointer to the Device Descriptor Structure which //describes the attributes of the Structure &ulMaxDMAMapRegisters); //Maximum Map registers that driver can allocate for //Dma transfer if(!IS_VALID(m_pDMAAdapter)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("Unable to get the Dma Adapter for the Device\n")); ntInitStatus = STATUS_UNSUCCESSFUL; goto ExitInitAdapter; } if(!IS_VALID(m_pDMAAdapter->DmaOperations)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("No Dma Operatios found for the DMA Adapter\n")); ntInitStatus = STATUS_UNSUCCESSFUL; goto ExitInitAdapter; } //Print the DMA Adapter details PrintDMAAdapter(m_pDMAAdapter); SkyWalkerDebugPrint(EXTREME_LEVEL,("Number of Map Registers = %lu\n",ulMaxDMAMapRegisters)); //Register the DMA Adapter with the AVStream //The KsDeviceRegisterAdapterObject function registers a DMA adapter object with //AVStream for performing scatter/gather DMA on the specified device. KsDeviceRegisterAdapterObject( pKSDeviceObject, //Device For which to register an adapter object m_pDMAAdapter, //Pointer to DMA Adapter (IoGetDmaAdapter) 0xfffffff8, //Maximum number of bytes that device can handle for a single mapping sizeof(KSMAPPING)); //Number of bytes each entry in the mapping table requires //Allocate the Space for storing the Streaming contents KeInitializeEvent (&m_HardwareEvent,SynchronizationEvent,FALSE); RtlZeroMemory(pUsbStreamIrp,sizeof(pUsbStreamIrp)); ExitInitAdapter: PrintFunctionExit(__FUNCTION__,ntInitStatus); return ntInitStatus; } /***************************************************************************** Function : CSkyWalker1Device::ReadStream Description : This function is called when streaming data from the USb is requested to read.This function is called when the streaming is started and every time after Stream processing to read a new Stream IN PARAM : Index of the Stream to Read OUT PARAM : ntStatus of the Read Stream STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Stream Read Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::ReadStream(IN ULONG ulStreamIndex) { NTSTATUS ntReadStreamStatus = STATUS_SUCCESS; PUCHAR pStreamBuffer = NULL; ULONG ulPacketCount = PACKET_PER_FRAME; ULONG ulPacketSize = MAX_BULK_PACKET_SIZE ; PrintFunctionEntry(__FUNCTION__); //Get the Stream buffer related to the Current Stream index pStreamBuffer = m_SynthesisBuffer[ulStreamIndex]; //Set the number of Bytes read m_NumberOfBytesRead[ulStreamIndex] = 0; //Send the Read request of the 4K Size Each for(ULONG ulPacketIndex = 0; ulPacketIndex <= ulPacketCount-1 ; ulPacketIndex++) { SkyWalkerDebugPrint(EXTREME_LEVEL,("pStreamBuffer[%03lu] = 0x%p",ulPacketIndex,pStreamBuffer)); SkyWalkerDebugPrint(EXTREME_LEVEL,("m_SampleSize = %lu",m_SampleSize)); if(IS_VALID(pStreamBuffer)) { if(ulPacketIndex == 23) { ulPacketSize = 2048; } ntReadStreamStatus = ReadWriteUsbDevice( m_pKSDevice, ulStreamIndex, ulPacketIndex, pStreamBuffer, ulPacketSize , true ); if(NT_SUCCESS(ntReadStreamStatus)) { SkyWalkerDebugPrint(EXTREME_LEVEL, ("Sent the Stream Read Request\n")); } else { SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Send Stream Read from the Device")); } pStreamBuffer += ulPacketSize; } else { SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid Stream Aborting Stream Read\n")); break; } } PrintFunctionExit(__FUNCTION__,ntReadStreamStatus); return ntReadStreamStatus; } /***************************************************************************** Function : CSkyWalker1Device::GetStatus Description : This function is used to Get the Current ntStatus of the Tuner i.e. Current Carrier Freq. Signal Locked status etc. IN PARAM : Device ntStatus OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Device ntStatus updated and returned Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::GetStatus(OUT PBDATUNER_DEVICE_STATUS pDeviceStatus) { NTSTATUS ntStatus = STATUS_SUCCESS; pDeviceStatus->fCarrierPresent = FALSE; pDeviceStatus->fSignalLocked = FALSE; pDeviceStatus->dwSignalQuality = 0; pDeviceStatus->dwSignalStrength = 0; PrintFunctionEntry(__FUNCTION__); if(m_HardwareState != HardwareRunning) { SkyWalkerDebugPrint(EXTREME_LEVEL,("Streaming is not started yet\n")); ntStatus = STATUS_UNSUCCESSFUL; goto ExitGetStatus; } if(TimeToReadSignalStatus()) { //It's Time to read Signal Status //Get the signal status from the HW here ReadTunerSignalStrength(m_pKSDevice, &m_TunerStatus.dwSignalStrength); m_TunerStatus.dwSignalQuality = (m_TunerStatus.dwSignalStrength * 100)/65535; GetSignalStatus(m_pKSDevice, &m_TunerStatus.fSignalLocked); if(m_TunerStatus.fSignalLocked) { m_TunerStatus.fCarrierPresent = TRUE; } } *pDeviceStatus = m_TunerStatus; #ifdef FAKE_SIGNAL pDeviceStatus->dwSignalStrength = 2; pDeviceStatus->dwSignalQuality = 99; pDeviceStatus->fCarrierPresent = TRUE; pDeviceStatus->fSignalLocked = TRUE; #endif ExitGetStatus : PrintFunctionExit(__FUNCTION__,ntStatus); return ntStatus; } /***************************************************************************** Function : CSkyWalker1Device::TimeToReadSignalStatus Description : This function is used Check whether time to read the status from device has occurred or not IN PARAM : NONE OUT PARAM : TRUE = Time to read status from Device, FALSE otherwise PreCondition : None PostCondtion : Whether time to read from device has occurred or not is checked Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ BOOLEAN CSkyWalker1Device::TimeToReadSignalStatus(void) { LARGE_INTEGER CurrentTime; ULONG ulReadPeriod = 10 * 1000 * 1000; KeQuerySystemTime (&CurrentTime); //If Current time is greater than the last if(m_TunerStatus.fSignalLocked == FALSE) { SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Not Locked Reading Status @ 100msec\n")); ulReadPeriod = 10 * 1000 * 100; } if(CurrentTime.QuadPart - m_PreviousStatusReadTime.QuadPart >= ulReadPeriod) { m_PreviousStatusReadTime.QuadPart = CurrentTime.QuadPart; SkyWalkerDebugPrint(EXTREME_LEVEL,("Time to read signal status\n")); return TRUE; } return FALSE; } /***************************************************************************** Function : CSkyWalker1Device::Acquire Description : This function is used to set the Tuner parameters and called once when the tuner resources are acquired From this function various device related command are executed to set the device parameters IN PARAM : New Device Parameters to be set Resource ID OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Device ntStatus updated and returned Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Acquire( IN PBDATUNER_DEVICE_PARAMETER pNewResource, OUT PULONG pulAcquiredResourceID ) { NTSTATUS ntAcquireStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Continue only if the Device is acquired currently if (!m_ulcResourceUsers) { m_CurResource = *pNewResource; //Generate a new resource ID and hand it back. m_ulCurResourceID += 25; *pulAcquiredResourceID = m_ulCurResourceID; m_ulcResourceUsers += 1; //Configure the new resource on the hardware here. //Send the Tune, SetLnbVoltage etc Commands from here ConfigureTuner(m_pKSDevice,pNewResource); } else { //Only one active filter is allowed ntAcquireStatus = STATUS_DEVICE_BUSY; } PrintFunctionExit(__FUNCTION__,ntAcquireStatus); return ntAcquireStatus; } /***************************************************************************** Function : CSkyWalker1Device::Update Description : This function is used to set the Tuner parameters and called everytime after the tuner resources are acquired From this function various device related command are executed to set the device parameters IN PARAM : New Device Parameters to be set Resource ID OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Device ntStatus updated and returned Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Update( IN PBDATUNER_DEVICE_PARAMETER pNewResource, IN ULONG ulResourceID ) { NTSTATUS ntUpdateStatus = STATUS_SUCCESS; LONGLONG ulhzFrequency; PrintFunctionEntry(__FUNCTION__); //Continue only if the Device is acquired currently if (m_ulcResourceUsers && (ulResourceID == m_ulCurResourceID)) { m_CurResource = *pNewResource; //Configure the new resource on the hardware here. //Send the Tune, SetLnbVoltage etc Commands from here ConfigureTuner(m_pKSDevice,pNewResource); } else { //Only one active filter is allowed ntUpdateStatus = STATUS_INVALID_DEVICE_REQUEST; } PrintFunctionExit(__FUNCTION__,ntUpdateStatus); return ntUpdateStatus; } /***************************************************************************** Function : CSkyWalker1Device::SendDiseqcCommand Description : This function is used to send the Diseqc Command to the Tuner IN PARAM : Diseqc Command to be sent to the Tuner Resource ID OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Diseqc Command sent to the Tuner Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::SendDiseqcCommand( IN PDISEQC_COMMAND pDiseqcCommand, IN ULONG ulResourceID ) { NTSTATUS ntStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Continue only if the Device is acquired currently //if (m_ulcResourceUsers && (ulResourceID == m_ulCurResourceID)) { SkyWalkerDebugPrint(EXTREME_LEVEL,("m_ulcResourceUsers = %lu\n",m_ulcResourceUsers)); SkyWalkerDebugPrint(EXTREME_LEVEL,("ulResourceID = %lu\n",ulResourceID)); SkyWalkerDebugPrint(EXTREME_LEVEL,("m_ulCurResourceID = %lu\n",m_ulCurResourceID)); //Send the Diseqc Command to the Tuner device DiseqcCommand(m_pKSDevice,pDiseqcCommand); } //else //{ // //Only one active filter is allowed // ntStatus = STATUS_INVALID_DEVICE_REQUEST; // } PrintFunctionExit(__FUNCTION__,ntStatus); return ntStatus; } /***************************************************************************** Function : CSkyWalker1Device::Release Description : This function is used to decrement the Resource User count to allow other filters to use the resources IN PARAM : Resource ID OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Device ntStatus updated and returned Logic : NONE Assumption : NONE Note : This is called from the PASSIVE_LEVEL_IRQL Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::Release(IN ULONG ulResourceID) { NTSTATUS ntStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); if(m_ulcResourceUsers && (ulResourceID == m_ulCurResourceID)) { //Free the resource to be used by another filter. m_ulcResourceUsers--; } else { ntStatus = STATUS_INVALID_DEVICE_REQUEST; } PrintFunctionExit(__FUNCTION__,ntStatus); return ntStatus; } /***************************************************************************** Function : CSkyWalker1Device::StartStream Description : This function is used to Initialize the Prestreaming parameters and also it sends the Streaming command to the Tuner IN PARAM : NONE OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Streaming Started on successful execution Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::StartStream () { NTSTATUS ntStreamStartStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Initializing the Streaming Parameters m_TimePerFrame = m_TransportInfo->AvgTimePerFrame; m_SampleSize = m_TransportInfo->ulcbPhyiscalFrame; m_PacketSize = m_TransportInfo->ulcbPhyiscalPacket; m_PacketsPerSample = m_TransportInfo->ulcbPhyiscalFrame / m_TransportInfo->ulcbPhyiscalPacket; m_TunerStatus.fCarrierPresent = FALSE; m_TunerStatus.fSignalLocked = FALSE; m_TunerStatus.dwSignalQuality = 0; m_TunerStatus.dwSignalStrength = 0; //Allocate a scratch buffer for the Streaming Buffer. for(int nBufferIndex = 0 ; nBufferIndex < SIZEOF_ARRAY(m_SynthesisBuffer); nBufferIndex++) { m_SynthesisBuffer[nBufferIndex] = reinterpret_cast ( ExAllocatePoolWithTag ( NonPagedPool, m_SampleSize, CAPTURE_MEM_TAG ) ); if (!IS_VALID(m_SynthesisBuffer)) { SkyWalkerDebugPrint(ENTRY_LEVEL,("Insufficient Resource for Scatter/Gather DMA\n")); ntStreamStartStatus = STATUS_INSUFFICIENT_RESOURCES; goto ExitStreamStart; } } //Send Device Streaming Start Control SetStreamingControl(m_pKSDevice,1); m_HardwareState = HardwareRunning; ExitStreamStart: PrintFunctionExit(__FUNCTION__,ntStreamStartStatus); return ntStreamStartStatus; } /***************************************************************************** Function : CSkyWalker1Device::PauseStream Description : This function is used to Pause/Run the Streaming if On/Off. IN PARAM : True : Pause Streaming , False : Start Streaming OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Streaming Paused/Started on successful execution Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::PauseStream (BOOLEAN bPausing) { NTSTATUS ntStreamPauseStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //If Streaming is in Progress then Stop the Streaming by //Stop sending read requests and Cancelling any on going IRP if (bPausing && (m_HardwareState == HardwareRunning)) { m_StopHardware = TRUE; //Stop Streaming SetStreamingControl(m_pKSDevice,0); for(int ulPacketIndex = 0; ulPacketIndex < SIZEOF_ARRAY(pUsbStreamIrp) ; ulPacketIndex++) { if(pUsbStreamIrp[ulPacketIndex]) { SkyWalkerDebugPrint(EXTREME_LEVEL,("Cancelling pUsbStreamIrp[%lu] = 0x%p\n", ulPacketIndex,pUsbStreamIrp[ulPacketIndex])); IoCancelIrp(pUsbStreamIrp[ulPacketIndex]); pUsbStreamIrp[ulPacketIndex] = NULL; KeWaitForSingleObject ( &m_HardwareEvent, Suspended, KernelMode, FALSE, NULL ); KeResetEvent(&m_HardwareEvent); m_StopHardware = TRUE; } } m_HardwareState = HardwarePaused; } else if (!bPausing && (m_HardwareState == HardwarePaused) ) { m_HardwareState = HardwareRunning; //Start Streaming SetStreamingControl(m_pKSDevice,1); } PrintFunctionExit(__FUNCTION__,ntStreamPauseStatus); return ntStreamPauseStatus; } /***************************************************************************** Function : CSkyWalker1Device::StopStream Description : This function is used to Stop the Streaming if On. IN PARAM : NONE OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Streaming Stopped on successful execution Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device::StopStream () { NTSTATUS ntStreamStopStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //Stop the Streaming in case it's already on if (m_HardwareState == HardwareRunning) { m_StopHardware = TRUE; //Stop Streaming SetStreamingControl(m_pKSDevice,0); SkyWalkerDebugPrint(EXTREME_LEVEL,("SIZEOF_ARRAY[pUsbStreamIrp] = %d\n", SIZEOF_ARRAY(pUsbStreamIrp))); for(int ulPacketIndex = 0; ulPacketIndex < SIZEOF_ARRAY(pUsbStreamIrp) ; ulPacketIndex++) { if(pUsbStreamIrp[ulPacketIndex]) { SkyWalkerDebugPrint(EXTREME_LEVEL,("Cancelling pUsbStreamIrp[%lu] = 0x%p\n", ulPacketIndex,pUsbStreamIrp[ulPacketIndex])); IoCancelIrp(pUsbStreamIrp[ulPacketIndex]); pUsbStreamIrp[ulPacketIndex] = NULL; KeWaitForSingleObject ( &m_HardwareEvent, Suspended, KernelMode, FALSE, NULL ); KeResetEvent(&m_HardwareEvent); m_StopHardware = TRUE; } } } m_HardwareState = HardwareStopped; for(int nBufferIndex = 0 ; nBufferIndex < SIZEOF_ARRAY(m_SynthesisBuffer) ; nBufferIndex++) { if (m_SynthesisBuffer[nBufferIndex]) { SkyWalkerDebugPrint(EXTREME_LEVEL,("Freeing Streaming Buffer m_SynthesisBuffer[%lu] = 0x%p\n", nBufferIndex,m_SynthesisBuffer[nBufferIndex])); ExFreePool (m_SynthesisBuffer[nBufferIndex]); m_SynthesisBuffer[nBufferIndex] = NULL; } } PrintFunctionExit(__FUNCTION__,ntStreamStopStatus); return ntStreamStopStatus; } /***************************************************************************** Function : CSkyWalker1Device::ProcessStream Description : This function is used to Process the Streaming Data after reading it.This function is called from the USB Read Write Completion routine IN PARAM : Index of the Stream whose read completed OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Read Stream is processed and Streaming data is filled into the used Buffer. Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ void CSkyWalker1Device::ProcessStream(ULONG ulStreamIndex) { PrintFunctionEntry(__FUNCTION__); //The hardware can be in a pause state in which case, it issues interrupts //but does not complete mappings. In this case, don't bother synthesizing //a frame and doing the work of looking through the mappings table. if (m_HardwareState == HardwareRunning) { SkyWalkerDebugPrint(EXTREME_LEVEL,("(%d * %d) = %lu\n", TRANSPORT_PACKET_SIZE, TRANSPORT_PACKET_COUNT, m_SampleSize)); SkyWalkerDebugPrint(EXTREME_LEVEL,("m_NumberOfBytesRead[%lu] = %lu\n", ulStreamIndex, m_NumberOfBytesRead[ulStreamIndex])); if (InterlockedCompareExchange((LONG *)&m_NumberOfBytesRead[ulStreamIndex], m_SampleSize, m_SampleSize) == m_SampleSize) { //Inform the capture sink m_CaptureSink->ReleaseStream(ulStreamIndex); } } if (m_StopHardware) { //If someone is waiting on the hardware to stop, raise the stop //event and clear the flag. SkyWalkerDebugPrint(EXTREME_LEVEL,("Sending the Stop Event\n")); m_StopHardware = FALSE; KeSetEvent (&m_HardwareEvent, IO_NO_INCREMENT, FALSE); } PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS); } /***************************************************************************** Function : CSkyWalker1Device::SetupCaptureSink Description : Acquire hardware resources for the capture hardware. If the resources are already acquired, this will return an error.The hardware configuration must be passed as a VideoInfoHeader. IN PARAM : The capture sink attempting to acquire resources. When scatter /gather mappings are completed, the capture sink specified here is what is notified of the completions. Information about the capture stream. This **MUST** remain stable until the caller releases hardware resources. Note that this could also be guaranteed by bagging it in the device object bag as well. OUT PARAM : STATUS_SUCCESS in case of successful execution Failure Code in other cases PreCondition : None PostCondtion : Capture Pin to the notified and Video Info Header set in case of successful execution Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ NTSTATUS CSkyWalker1Device:: SetupCaptureSink( IN ICaptureSink *CaptureSink, IN PBDA_TRANSPORT_INFO TransportInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PrintFunctionEntry(__FUNCTION__); //If we're the first pin to go into acquire (remember we can have //a filter in another graph going simultaneously), grab the resources. if (InterlockedCompareExchange(&m_PinsWithResources,1,0) == 0) { m_TransportInfo = TransportInfo; m_CaptureSink = CaptureSink; } else { ntStatus = STATUS_SHARING_VIOLATION; } PrintFunctionExit(__FUNCTION__,ntStatus); return ntStatus; } /***************************************************************************** Function : CSkyWalker1Device::RemoveCaptureSink Description : Release hardware resources. This should only be called by an object which has acquired them. IN PARAM : NONE OUT PARAM : NONE PreCondition : None PostCondtion : Video Info Header and Capture Sink info cleared Logic : NONE Assumption : NONE Note : NONE Revision History: *****************************************************************************/ void CSkyWalker1Device::RemoveCaptureSink() { PrintFunctionEntry(__FUNCTION__); m_TransportInfo = NULL; m_CaptureSink = NULL; //Release our "lock" on hardware resources. This will allow another //pin (perhaps in another graph) to acquire them. InterlockedExchange(&m_PinsWithResources,0); PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS); } void PrintDMAAdapter(PDMA_ADAPTER pDMAAdapter) { SkyWalkerDebugPrint(ENTRY_LEVEL,("pDMAAdapter->Version = %u\n",pDMAAdapter->Version)); SkyWalkerDebugPrint(ENTRY_LEVEL,("pDMAAdapter->Size = %u\n",pDMAAdapter->Size)); SkyWalkerDebugPrint(ENTRY_LEVEL,("pDMAAdapter->DmaOperations = 0x%p\n",pDMAAdapter->DmaOperations)); } void PrintMappingInfo(IN PKSMAPPING pMapping) { SkyWalkerDebugPrint(ENTRY_LEVEL,("pMapping->PhysicalAddress = %llu\n",pMapping->PhysicalAddress.QuadPart)); SkyWalkerDebugPrint(ENTRY_LEVEL,("pMapping->ByteCount = %lu\n",pMapping->ByteCount)); SkyWalkerDebugPrint(ENTRY_LEVEL,("pMapping->Alignment = %lu\n",pMapping->Alignment)); }