Beispiel #1
0
NTSTATUS CMiniportWaveRTStream::SetState
(
    _In_    KSSTATE State_
)
{
    PAGED_CODE();

    NTSTATUS        ntStatus        = STATUS_SUCCESS;
    PADAPTERCOMMON  pAdapterComm    = m_pMiniport->GetAdapterCommObj();

    // Spew an event for a pin state change request from portcls
    //Event type: eMINIPORT_PIN_STATE
    //Parameter 1: Current linear buffer position	
    //Parameter 2: Current WaveRtBufferWritePosition	
    //Parameter 3: Pin State 0->KS_STOP, 1->KS_ACQUIRE, 2->KS_PAUSE, 3->KS_RUN 
    //Parameter 4:0
    pAdapterComm->WriteEtwEvent(eMINIPORT_PIN_STATE, 
                                100, // replace with the correct "Current linear buffer position"	
                                m_ulCurrentWritePosition, // replace with the previous WaveRtBufferWritePosition that the drive received	
                                State_, // repalce with the correct "Data length completed"
                                0);  // always zero

    switch (State_)
    {
        case KSSTATE_STOP:
            // Reset DMA
            m_ullPlayPosition = 0;
            m_ullWritePosition = 0;
            m_ullLinearPosition = 0;
            
            // Wait until all work items are completed.
            if (!m_bCapture && !g_DoNotCreateDataFiles)
            {
                m_SaveData.WaitAllWorkItems();
            }

#ifdef SYSVAD_BTH_BYPASS
            if (m_ScoOpen)
            {
                PBTHHFPDEVICECOMMON bthHfpDevice;
                
                ASSERT(m_pMiniport->IsBthHfpDevice());
                bthHfpDevice = m_pMiniport->GetBthHfpDevice(); // weak ref.
                ASSERT(bthHfpDevice != NULL);

                //
                // Close the SCO connection.
                //
                ntStatus = bthHfpDevice->StreamClose();
                if (!NT_SUCCESS(ntStatus))
                {
                    DPF(D_ERROR, ("SetState: KSSTATE_STOP, StreamClose failed, 0x%x", ntStatus));
                }
                
                m_ScoOpen = FALSE;
            }
#endif // SYSVAD_BTH_BYPASS
            break;

        case KSSTATE_ACQUIRE:
#ifdef SYSVAD_BTH_BYPASS
            if (m_pMiniport->IsBthHfpDevice())
            {
                if(m_ScoOpen == FALSE)
                {
                    PBTHHFPDEVICECOMMON bthHfpDevice;

                    bthHfpDevice = m_pMiniport->GetBthHfpDevice(); // weak ref.
                    ASSERT(bthHfpDevice != NULL);

                    //
                    // Open the SCO connection.
                    //
                    ntStatus = bthHfpDevice->StreamOpen();
                    IF_FAILED_ACTION_JUMP(
                        ntStatus,
                        DPF(D_ERROR, ("SetState: KSSTATE_ACQUIRE, StreamOpen failed, 0x%x", ntStatus)),
                        Done);

                    m_ScoOpen = TRUE;
                }
            }
#endif // SYSVAD_BTH_BYPASS
            break;

        case KSSTATE_PAUSE:
            ULONGLONG ullPositionTemp;
            
            // Pause DMA
            if (m_ulNotificationIntervalMs > 0)
            {
                KeCancelTimer(m_pNotificationTimer);
                KeFlushQueuedDpcs(); 
            }

            // This call updates the linear buffer position.
            GetLinearBufferPosition(&ullPositionTemp, NULL);
            break;

        case KSSTATE_RUN:
            // Start DMA
            LARGE_INTEGER ullPerfCounterTemp;
            ullPerfCounterTemp = KeQueryPerformanceCounter(&m_ullPerformanceCounterFrequency);
            m_ullDmaTimeStamp = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, ullPerfCounterTemp);
            m_hnsElapsedTimeCarryForward  = 0;

            if (m_ulNotificationIntervalMs > 0)
            {
                LARGE_INTEGER   delay;
                delay.HighPart  = 0;
                delay.LowPart   = m_ulNotificationIntervalMs * HNSTIME_PER_MILLISECOND * -1;

                KeSetTimerEx
                (
                    m_pNotificationTimer,
                    delay,
                    m_ulNotificationIntervalMs,
                    m_pNotificationDpc
                );
            }

            break;
    }

    m_KsState = State_;

#ifdef SYSVAD_BTH_BYPASS
Done:
#endif  // SYSVAD_BTH_BYPASS
    return ntStatus;
}
Beispiel #2
0
void
TimerNotifyRT
(
    _In_      PKDPC         Dpc,
    _In_opt_  PVOID         DeferredContext,
    _In_opt_  PVOID         SA1,
    _In_opt_  PVOID         SA2
)
{
    UNREFERENCED_PARAMETER(Dpc);
    UNREFERENCED_PARAMETER(SA1);
    UNREFERENCED_PARAMETER(SA2);

    CMiniportWaveRTStream* _this = (CMiniportWaveRTStream*)DeferredContext;
    
    if (NULL == _this)
    {
        return;
    }
    
#ifdef SYSVAD_BTH_BYPASS
    if (_this->m_ScoOpen)
    {
        if (!NT_SUCCESS(_this->GetScoStreamNtStatus()))
        {
            return;
        }
    }
#endif  // SYSVAD_BTH_BYPASS

    if (_this->m_KsState != KSSTATE_RUN)
    {
        return;
    }
    
    PADAPTERCOMMON  pAdapterComm = _this->m_pMiniport->GetAdapterCommObj();

    // Simple buffer underrun detection.
    if (!_this->IsCurrentWaveRTWritePositionUpdated())
    {
        //Event type: eMINIPORT_GLITCH_REPORT
        //Parameter 1: Current linear buffer position 
        //Parameter 2: the previous WaveRtBufferWritePosition that the drive received 
        //Parameter 3: major glitch code: 1:WaveRT buffer is underrun
        //Parameter 4: minor code for the glitch cause
        pAdapterComm->WriteEtwEvent(eMINIPORT_GLITCH_REPORT, 
                                    100,    // replace with the correct "Current linear buffer position"   
                                    _this->GetCurrentWaveRTWritePosition(),
                                    1,      // WaveRT buffer is underrun
                                    0); 
    }

    if (!IsListEmpty(&_this->m_NotificationList))
    {
        PLIST_ENTRY leCurrent = _this->m_NotificationList.Flink;
        while (leCurrent != &_this->m_NotificationList)
        {
            NotificationListEntry* nleCurrent = CONTAINING_RECORD( leCurrent, NotificationListEntry, ListEntry);
            //Event type: eMINIPORT_BUFFER_COMPLETE
            //Parameter 1: Current linear buffer position	
            //Parameter 2: the previous WaveRtBufferWritePosition that the drive received
            //Parameter 3: Data length completed	
            //Parameter 4:0
            pAdapterComm->WriteEtwEvent(eMINIPORT_BUFFER_COMPLETE, 
                                        100, // replace with the correct "Current linear buffer position"	
                                        _this->GetCurrentWaveRTWritePosition(), 	
                                        300, // repalce with the correct "Data length completed"
                                        0);  // always zero

            KeSetEvent(nleCurrent->NotificationEvent, 0, 0);

            leCurrent = leCurrent->Flink;
        }
    }
}
Beispiel #3
0
/*****************************************************************************
 * StartDevice
 *****************************************************************************
 * This function is called by the operating system when the device is started.
 * It is responsible for starting the miniports.  This code is specific to
 * the adapter because it calls out miniports for functions that are specific
 * to the adapter.
 */
NTSTATUS StartDevice
(
    IN  PDEVICE_OBJECT  DeviceObject,   // Device object.
    IN  PIRP            Irp,            // IO request packet.
    IN  PRESOURCELIST   ResourceList    // List of hardware resources.
)
{
    PAGED_CODE ();

    ASSERT (DeviceObject);
    ASSERT (Irp);
    ASSERT (ResourceList);

    NTSTATUS ntStatus;

    DOUT (DBG_PRINT, ("[StartDevice]"));

    //
    // Determine which version of the OS we are running under.  We don't want
    // to run under Win98G.
    //

    // create a wave cyclic port
    PPORT pPort = 0;
    ntStatus = PcNewPort (&pPort,CLSID_PortWaveCyclic);

    // check error code
    if (NT_SUCCESS (ntStatus))
    {
        // query for the event interface which is not supported in Win98 gold.
        PPORTEVENTS pPortEvents = 0;
        ntStatus = pPort->QueryInterface (IID_IPortEvents,
                                         (PVOID *)&pPortEvents);
        if (!NT_SUCCESS (ntStatus))
        {
            DOUT (DBG_ERROR, ("This driver is not for Win98 Gold!"));
            ntStatus = STATUS_UNSUCCESSFUL;     // change error code.
        }
        else
        {
            pPortEvents->Release ();
        }
        pPort->Release ();
    }

    // now return in case it was Win98 Gold.
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    //
    // Validate the resources.
    // We don't have to split the resources into several resource lists cause
    // the topology miniport doesn't need a resource list, the wave pci miniport
    // needs all resources like the adapter common object.
    //
    ntStatus = ValidateResources (ResourceList);

    //
    // return immediately in case of an error
    //
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    //
    // If the adapter has the right resources...
    //
    PADAPTERCOMMON pAdapterCommon = NULL;
    PUNKNOWN       pUnknownCommon;

    // create a new adapter common object
    ntStatus = NewAdapterCommon (&pUnknownCommon, IID_IAC97AdapterCommon,
                                 NULL, NonPagedPool);

    if (NT_SUCCESS (ntStatus))
    {
        // query for the IAC97AdapterCommon interface
        ntStatus = pUnknownCommon->QueryInterface (IID_IAC97AdapterCommon,
                                                   (PVOID *)&pAdapterCommon);
        if (NT_SUCCESS (ntStatus))
        {
            // Initialize the object
            ntStatus = pAdapterCommon->Init (ResourceList, DeviceObject);

            if (NT_SUCCESS (ntStatus))
            {
                // register with PortCls for power-management services
                ntStatus = PcRegisterAdapterPowerManagement ((PUNKNOWN)pAdapterCommon,
                                                             DeviceObject);
            }
        }

        // release the IID_IAC97AdapterCommon on adapter common
        pUnknownCommon->Release ();
    }

    // print error message.
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_ERROR, ("Could not create or query AdapterCommon."));
    }

    //
    // These are the port driver pointers we are keeping around for registering
    // physical connections.
    //
    PMINIPORT               miniTopology            = NULL;
    PUNKNOWN                unknownWave             = NULL;
    PUNKNOWN                unknownTopology         = NULL;
    PAC97MINIPORTTOPOLOGY   pMiniportTopology       = NULL;

    //
    // Start the topology miniport.
    //
    if (NT_SUCCESS (ntStatus))
    {
        ntStatus = InstallSubdevice (DeviceObject,
                                     Irp,
                                     L"Topology",
                                     CLSID_PortTopology,
                                     CLSID_PortTopology, // not used
                                     CreateAC97MiniportTopology,
                                     pAdapterCommon,
                                     NULL,
                                     GUID_NULL,
                                     &miniTopology,
                                     &unknownTopology);

        if (NT_SUCCESS (ntStatus))
        {
            // query for the IAC97MiniportTopology interface
            ntStatus = miniTopology->QueryInterface (IID_IAC97MiniportTopology,
                                                    (PVOID *)&pMiniportTopology);
            miniTopology->Release ();
            miniTopology = NULL;
        }

        // print error message.
        if (!NT_SUCCESS (ntStatus))
        {
            DOUT (DBG_ERROR, ("Could not create or query TopologyICH"));
        }
    }

    //
    // Start the wave miniport.
    //
    if (NT_SUCCESS (ntStatus))
    {
#if (NTDDI_VERSION >= NTDDI_VISTA)
        ntStatus = InstallSubdevice (DeviceObject,
                                     Irp,
                                     L"Wave",
                                     CLSID_PortWaveRT,
                                     CLSID_PortWaveRT,      // not used
                                     CreateAC97MiniportWaveRT,
                                     pAdapterCommon,
                                     ResourceList,
                                     IID_IPortWaveRT,
                                     NULL,
                                     &unknownWave);

        if (!NT_SUCCESS (ntStatus))
        {
#endif
            //
            // If creation of the RT port failed we can fall back to the WavePCI
            // or WaveCyc port of portcls. In this case, we try the WavePCI port.
            //
            ntStatus = InstallSubdevice (DeviceObject,
                                         Irp,
                                         L"Wave",
                                         CLSID_PortWavePci,
                                         CLSID_PortWavePci,   // not used
                                         CreateAC97MiniportWavePCI,
                                         pAdapterCommon,
                                         ResourceList,
                                         IID_IPortWavePci,
                                         NULL,
                                         &unknownWave);
#if (NTDDI_VERSION >= NTDDI_VISTA)
        }
#endif
        // print error message.
        if (!NT_SUCCESS (ntStatus))
        {
            DOUT (DBG_ERROR, ("WaveRT and WavePCI miniport installation failed!"));
        }
    }

    //
    // Establish physical connections between filters as shown.
    //
    //              +------+    +------+
    //              | Wave |    | Topo |
    //  Capture <---|2    3|<===|x     |<--- CD
    //              |      |    |      |
    //   Render --->|0    1|===>|y     |<--- Line In
    //              |      |    |      |
    //      Mic <---|4    5|<===|z     |<--- Mic
    //              +------+    |      |
    //                          |      |---> Line Out
    //                          +------+
    //
    // Note that the pin numbers for the nodes to be connected
    // vary depending on the hardware/codec configuration.
    // Also, the mic input may or may not be present.
    //
    // So,
    //      Do a QI on unknownTopology to get an interface to call
    //          a method on to get the topology miniport pin IDs.

    if (NT_SUCCESS (ntStatus))
    {
        ULONG ulWaveOut, ulWaveIn, ulMicIn;

        // get the pin numbers.
        DOUT (DBG_PRINT, ("Connecting topo and wave."));
        ntStatus = pMiniportTopology->GetPhysicalConnectionPins (&ulWaveOut,
                                            &ulWaveIn, &ulMicIn);

        // register wave render connection
        if (NT_SUCCESS (ntStatus))
        {
            ntStatus = PcRegisterPhysicalConnection (DeviceObject,
                                                     unknownWave,
                                                     PIN_WAVEOUT_BRIDGE,
                                                     unknownTopology,
                                                     ulWaveOut);
            // print error message.
            if (!NT_SUCCESS (ntStatus))
            {
                DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
                                  " (render)!"));
            }
        }


        if (NT_SUCCESS (ntStatus))
        {
            // register wave capture connection
            ntStatus = PcRegisterPhysicalConnection (DeviceObject,
                                                     unknownTopology,
                                                     ulWaveIn,
                                                     unknownWave,
                                                     PIN_WAVEIN_BRIDGE);
            // print error message.
            if (!NT_SUCCESS (ntStatus))
            {
                DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
                                  " (capture)!"));
            }
        }

        if (NT_SUCCESS (ntStatus))
        {
            // register mic capture connection
            if (pAdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
            {
                ntStatus = PcRegisterPhysicalConnection (DeviceObject,
                                                         unknownTopology,
                                                         ulMicIn,
                                                         unknownWave,
                                                         PIN_MICIN_BRIDGE);
                // print error message.
                if (!NT_SUCCESS (ntStatus))
                {
                    DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
                                      " (MIC)!"));
                }
            }
        }
    }

    //
    // Release the adapter common object.  It either has other references,
    // or we need to delete it anyway.
    //
    if (pAdapterCommon)
        pAdapterCommon->Release ();

    //
    // Release the unknowns.
    //
    if (unknownTopology)
        unknownTopology->Release ();
    if (unknownWave)
        unknownWave->Release ();

    // and the AC97 miniport.
    if (pMiniportTopology)
        pMiniportTopology->Release ();


    return ntStatus;    // whatever this is ...
}
Beispiel #4
0
//=============================================================================
NTSTATUS StartDevice(
    IN  PDEVICE_OBJECT          DeviceObject,     
    IN  PIRP                    Irp,              
    IN  PRESOURCELIST           ResourceList      
)  
/*++
Routine Description:
  This function is called by the operating system when the device is 
  started.
  It is responsible for starting the miniports.  This code is specific to    
  the adapter because it calls out miniports for functions that are specific 
  to the adapter.                                                            

Arguments:
  DeviceObject - pointer to the driver object
  Irp - pointer to the irp 
  ResourceList - pointer to the resource list assigned by PnP manager

Return Value:
  NT status code.
--*/
{
    UNREFERENCED_PARAMETER(ResourceList);

    PAGED_CODE();
    
    ASSERT(DeviceObject);
    ASSERT(Irp);
    ASSERT(ResourceList);

    NTSTATUS       ntStatus        = STATUS_SUCCESS;
    PUNKNOWN       unknownTopology = NULL;
    PUNKNOWN       unknownWave     = NULL;
    PADAPTERCOMMON pAdapterCommon  = NULL;
    PUNKNOWN       pUnknownCommon  = NULL;

    DPF_ENTER(("[StartDevice]"));

    // create a new adapter common object
    ntStatus = NewAdapterCommon(&pUnknownCommon, IID_IAdapterCommon, NULL, NonPagedPool);
    if (NT_SUCCESS(ntStatus)) {
        ntStatus = pUnknownCommon->QueryInterface(IID_IAdapterCommon, (PVOID *) &pAdapterCommon);
        if (NT_SUCCESS(ntStatus)) {
            ntStatus = pAdapterCommon->Init(DeviceObject);
            if (NT_SUCCESS(ntStatus)) {
                // register with PortCls for power-management services
                ntStatus = PcRegisterAdapterPowerManagement(PUNKNOWN(pAdapterCommon), DeviceObject);
            }
        }
    }

    // install MSVAD topology miniport.
    if (NT_SUCCESS(ntStatus)) {
        ntStatus = InstallSubdevice(DeviceObject, Irp, L"Topology", CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyMSVAD, pAdapterCommon, NULL, IID_IPortTopology, NULL, &unknownTopology);
    }

    // install MSVAD wavecyclic miniport.
    if (NT_SUCCESS(ntStatus)) {
        ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCyclicMSVAD, pAdapterCommon, NULL, IID_IPortWaveCyclic, pAdapterCommon->WavePortDriverDest(), &unknownWave);
    }

    if (unknownTopology && unknownWave) {
        // register wave <=> topology connections
        // This will connect bridge pins of wavecyclic and topology
        // miniports.
        if ((TopologyPhysicalConnections.ulTopologyOut != (ULONG)-1) && (TopologyPhysicalConnections.ulWaveIn != (ULONG)-1)) {
            ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownTopology, TopologyPhysicalConnections.ulTopologyOut, unknownWave, TopologyPhysicalConnections.ulWaveIn);
        }

        if (NT_SUCCESS(ntStatus)) {
            if ((TopologyPhysicalConnections.ulWaveOut != (ULONG)-1) && (TopologyPhysicalConnections.ulTopologyIn != (ULONG)-1)) {
                ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownWave, TopologyPhysicalConnections.ulWaveOut, unknownTopology, TopologyPhysicalConnections.ulTopologyIn);
            }
        }
    }

    // Release the adapter common object.  It either has other references,
    // or we need to delete it anyway.
    if (pAdapterCommon) {
        pAdapterCommon->Release();
    }

    if (pUnknownCommon) {
        pUnknownCommon->Release();
    }
    
    if (unknownTopology) {
        unknownTopology->Release();
    }

    if (unknownWave) {
        unknownWave->Release();
    }

    return ntStatus;
} // StartDevice
Beispiel #5
0
_Use_decl_annotations_
NTSTATUS
StartDevice
( 
    PDEVICE_OBJECT          DeviceObject,     
    PIRP                    Irp,              
    PRESOURCELIST           ResourceList      
)  
{
/*++

Routine Description:

    This function is called by the operating system when the device is 
    started.
    It is responsible for starting the miniports.  This code is specific to    
    the adapter because it calls out miniports for functions that are specific 
    to the adapter.                                                            

Arguments:

    DeviceObject - pointer to the driver object

    Irp - pointer to the irp 

    ResourceList - pointer to the resource list assigned by PnP manager

Return Value:

    NT status code

--*/
    PAGED_CODE();

    UNREFERENCED_PARAMETER(ResourceList);

    ASSERT(DeviceObject);
    ASSERT(Irp);
    ASSERT(ResourceList);

    NTSTATUS                    ntStatus        = STATUS_SUCCESS;

    PADAPTERCOMMON              pAdapterCommon  = NULL;
    PUNKNOWN                    pUnknownCommon  = NULL;
    PortClassDeviceContext*     pExtension      = static_cast<PortClassDeviceContext*>(DeviceObject->DeviceExtension);

    DPF_ENTER(("[StartDevice]"));

    //
    // create a new adapter common object
    //
    ntStatus = NewAdapterCommon( 
                                &pUnknownCommon,
                                IID_IAdapterCommon,
                                NULL,
                                NonPagedPoolNx 
                                );
    IF_FAILED_JUMP(ntStatus, Exit);

    ntStatus = pUnknownCommon->QueryInterface( IID_IAdapterCommon,(PVOID *) &pAdapterCommon);
    IF_FAILED_JUMP(ntStatus, Exit);

    ntStatus = pAdapterCommon->Init(DeviceObject);
    IF_FAILED_JUMP(ntStatus, Exit);

    //
    // register with PortCls for power-management services
    ntStatus = PcRegisterAdapterPowerManagement( PUNKNOWN(pAdapterCommon), DeviceObject);
    IF_FAILED_JUMP(ntStatus, Exit);

    //
    // Install wave+topology filters for render devices
    //
    ntStatus = InstallAllRenderFilters(DeviceObject, Irp, pAdapterCommon);
    IF_FAILED_JUMP(ntStatus, Exit);

Exit:

    //
    // Stash the adapter common object in the device extension so
    // we can access it for cleanup on stop/removal.
    //
    if (pAdapterCommon)
    {
        ASSERT(pExtension != NULL);
        pExtension->m_pCommon = pAdapterCommon;
    }

    //
    // Release the adapter IUnknown interface.
    //
    SAFE_RELEASE(pUnknownCommon);
    
    return ntStatus;
}