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; }
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; } } }