diff options
| author | Daniel Rugerio <[email protected]> | 2019-06-28 16:08:54 -0700 |
|---|---|---|
| committer | Adonais Romero González <[email protected]> | 2019-06-28 16:08:54 -0700 |
| commit | 8ffcdad009e4d410f92fabc4e322a76a0be3a69d (patch) | |
| tree | 378b2d98a4210c61e2bc34f5b8959e87e4be5c6c /audio/sysvad/EndpointsCommon/minwavert.cpp | |
| parent | 75b2290f2a4ece68739d07135d352cdfec3a9e89 (diff) | |
Update audio samples (#387)
* Update SysVAD public sample.
* Add WaveTest public sample.
Diffstat (limited to 'audio/sysvad/EndpointsCommon/minwavert.cpp')
| -rw-r--r-- | audio/sysvad/EndpointsCommon/minwavert.cpp | 574 |
1 files changed, 550 insertions, 24 deletions
diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index 1ad029f7..4cabc7c4 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -1214,6 +1214,8 @@ BOOL CMiniportWaveRT::IsKeywordDetectorPin(ULONG nPinId) return (pinType == KeywordCapturePin); } + +//============================================================================= #pragma code_seg("PAGE") NTSTATUS CMiniportWaveRT::StreamCreated @@ -1739,7 +1741,24 @@ CMiniportWaveRT::PropertyHandlerProposedFormat ntStatus = STATUS_SUCCESS; } } + else #endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) + if (IsKeywordDetectorPin(kspPin->PinId)) + { + KSDATAFORMAT_WAVEFORMATEXTENSIBLE *propFormat = (KSDATAFORMAT_WAVEFORMATEXTENSIBLE *)PropertyRequest->Value; + ULONG numModes = 0; + MODE_AND_DEFAULT_FORMAT *modeInfo = NULL; + + numModes = GetPinSupportedDeviceModes(kspPin->PinId, &modeInfo); + if (numModes == 0 || modeInfo->DefaultFormat == NULL) + { + return STATUS_NOT_SUPPORTED; + } + + RtlCopyMemory(propFormat, modeInfo->DefaultFormat, modeInfo->DefaultFormat->FormatSize); + PropertyRequest->ValueSize = modeInfo->DefaultFormat->FormatSize; + ntStatus = STATUS_SUCCESS; + } } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { @@ -1815,6 +1834,49 @@ Arguments: } //============================================================================= +#pragma code_seg() +VOID +CMiniportWaveRT::SendPNPNotification( + _In_ const GUID * NotificationId, + _In_ PVOID NotificationBuffer, + _In_ USHORT NotificationBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PPCNOTIFICATION_BUFFER buffer = NULL; + + PAGED_CODE(); + + DPF_ENTER(("[SendPNPNotification]")); + + // Allocate a notification buffer. + status = m_pPortClsNotifications->AllocNotificationBuffer(PagedPool, + NotificationBufferCb, + &buffer); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + // Notification buffer is only guaranteed to be LONG aligned, + // it is received as ULONGLONG aligned on the receiving end. + RtlCopyMemory(buffer, NotificationBuffer, NotificationBufferCb); + + // + // Generate notification (async). + // + m_pPortClsNotifications->SendNotification(NotificationId, buffer); + +exit: + if (buffer != NULL) + { + // Free notification buffer. + m_pPortClsNotifications->FreeNotificationBuffer(buffer); + buffer = NULL; + } +} + +//============================================================================= #pragma code_seg("PAGE") NTSTATUS CMiniportWaveRT::PropertyHandlerAudioEffectsDiscoveryEffectsList @@ -2675,7 +2737,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns) // No items so clear the configuration. if (itemsHeader->Count == 0) { - m_KeywordDetector.ResetDetector(); + m_KeywordDetector.ResetDetector(CONTOSO_KEYWORD1); return STATUS_SUCCESS; } @@ -2722,9 +2784,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns) pattern = (CONTOSO_KEYWORDCONFIGURATION*)(patternHeader); // Program the hardware. - m_KeywordDetector.DownloadDetectorData(pattern->ContosoDetectorConfigurationData); - - return STATUS_SUCCESS; + return m_KeywordDetector.DownloadDetectorData(CONTOSO_KEYWORD1, pattern->ContosoDetectorConfigurationData); } DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed) @@ -2736,9 +2796,8 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed) NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); - *(BOOL*)PropertyRequest->Value = m_KeywordDetector.GetArmed(); - return STATUS_SUCCESS; + return m_KeywordDetector.GetArmed(CONTOSO_KEYWORD1, (BOOL*)PropertyRequest->Value); } DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) @@ -2754,7 +2813,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) armed = ((*(BOOL*)PropertyRequest->Value) != 0); - ntStatus = m_KeywordDetector.SetArmed(armed); + ntStatus = m_KeywordDetector.SetArmed(CONTOSO_KEYWORD1, armed); if (NT_SUCCESS(ntStatus) && armed) { @@ -2762,7 +2821,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) // it is armed, but later, find a better way to demonstrate this from // within CKeywordDetector. m_pPortEvents->GenerateEventList(const_cast<GUID*>(&KSEVENTSETID_SoundDetector), KSEVENT_SOUNDDETECTOR_MATCHDETECTED, FALSE, 0, FALSE, 0); - m_KeywordDetector.SetArmed(FALSE); + m_KeywordDetector.SetArmed(CONTOSO_KEYWORD1, FALSE); } return ntStatus; @@ -2785,15 +2844,297 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorMatchResult) value->Header.Size = sizeof(CONTOSO_KEYWORDDETECTIONRESULT); value->Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER; - value->ContosoDetectorResultData = m_KeywordDetector.GetDetectorData(); value->KeywordStartTimestamp = m_KeywordDetector.GetStartTimestamp(); value->KeywordStopTimestamp = m_KeywordDetector.GetStopTimestamp(); PropertyRequest->ValueSize = sizeof(*value); - + + return m_KeywordDetector.GetDetectorData(CONTOSO_KEYWORD1, &(value->ContosoDetectorResultData)); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns2) +{ + CONTOSO_SUPPORTEDPATTERNSVALUE *value; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(*value)); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // There is currently only support for 1 OEM DLL, and that CLSID is returned when + // the EventID is GUID_NULL. + if (propertyInstance->EventId != GUID_NULL) + { + return STATUS_INVALID_PARAMETER; + } + + // Does this filter support a sound detector? + if ((m_DeviceFlags & ENDPOINT_SOUNDDETECTOR_SUPPORTED) == 0) + { + return STATUS_NOT_SUPPORTED; + } + + value = (CONTOSO_SUPPORTEDPATTERNSVALUE*)PropertyRequest->Value; + + RtlZeroMemory(value, sizeof(*value)); + + value->MultipleItem.Size = sizeof(*value); + value->MultipleItem.Count = 1; + value->PatternType[0] = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + + PropertyRequest->ValueSize = sizeof(*value); + return STATUS_SUCCESS; } +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns2) +{ + KSMULTIPLE_ITEM *itemsHeader; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + SOUNDDETECTOR_PATTERNHEADER *patternHeader; + CONTOSO_KEYWORDCONFIGURATION *pattern; + ULONG cbRemaining; // Tracks bytes remaining in property value + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + cbRemaining = PropertyRequest->ValueSize; + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof KSMULTIPLE_ITEM. + if (cbRemaining < sizeof(KSMULTIPLE_ITEM)) + { + return STATUS_INVALID_PARAMETER; + } + + itemsHeader = (KSMULTIPLE_ITEM*)PropertyRequest->Value; + + // Verify property value is large enough to include the items + if (itemsHeader->Size > cbRemaining) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + // No items so clear the configuration. + if (itemsHeader->Count == 0) + { + m_KeywordDetector.ResetDetector(propertyInstance->EventId); + return STATUS_SUCCESS; + } + + // This sample supports only 1 pattern type. + if (itemsHeader->Count > 1) + { + PropertyRequest->ValueSize = 0; + return STATUS_NOT_SUPPORTED; + } + + // Bytes remaining after the items header + cbRemaining = itemsHeader->Size - sizeof(*itemsHeader); + + // Verify the property value is large enough to include the pattern header. + if (cbRemaining < sizeof(SOUNDDETECTOR_PATTERNHEADER)) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + patternHeader = (SOUNDDETECTOR_PATTERNHEADER*)(itemsHeader + 1); + + // Verify the pattern type is supported. + if (patternHeader->PatternType != CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2) + { + PropertyRequest->ValueSize = 0; + return STATUS_NOT_SUPPORTED; + } + + // Verify the property value is large enough for the pattern. + if (cbRemaining < patternHeader->Size) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + // Verify the pattern is large enough. + if (patternHeader->Size != sizeof(CONTOSO_KEYWORDCONFIGURATION)) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + pattern = (CONTOSO_KEYWORDCONFIGURATION*)(patternHeader); + + return m_KeywordDetector.DownloadDetectorData(propertyInstance->EventId, pattern->ContosoDetectorConfigurationData); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed2) +{ + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); + return m_KeywordDetector.GetArmed(propertyInstance->EventId, (BOOL*)PropertyRequest->Value); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed2) +{ + NTSTATUS ntStatus; + BOOL armed; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + armed = ((*(BOOL*)PropertyRequest->Value) != 0); + + ntStatus = m_KeywordDetector.SetArmed(propertyInstance->EventId, armed); + + // THIS BLOCK IS FOR SYSVAD TESTING ONLY AND WILL NEED TO BE REMOVED + if (NT_SUCCESS(ntStatus) && armed && + (propertyInstance->EventId == CONTOSO_KEYWORD1 || + propertyInstance->EventId == CONTOSO_KEYWORD2)) + { + CONTOSO_KEYWORDDETECTIONRESULT value = {0}; + + m_KeywordDetector.NotifyDetection(); + + value.EventId = propertyInstance->EventId; + value.Header.Size = sizeof(CONTOSO_KEYWORDDETECTIONRESULT); + value.Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + value.KeywordStartTimestamp = m_KeywordDetector.GetStartTimestamp(); + value.KeywordStopTimestamp = m_KeywordDetector.GetStopTimestamp(); + m_KeywordDetector.GetDetectorData(propertyInstance->EventId, &(value.ContosoDetectorResultData)); + + SendPNPNotification(&KSNOTIFICATIONID_SoundDetector, &value, sizeof(value)); + } + + return ntStatus; +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorReset2) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + BOOL reset; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + reset = ((*(BOOL*)PropertyRequest->Value) != 0); + + if (reset) + { + ntStatus = m_KeywordDetector.ResetDetector(propertyInstance->EventId); + } + + return ntStatus; +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorStreamingSupport2) +{ + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); + return m_KeywordDetector.GetStreamingSupport(propertyInstance->EventId, (BOOL*)PropertyRequest->Value); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_InterleavedFormatInformation) +{ + PAGED_CODE(); + + PKSP_PIN propertyInstance = NULL; + + // being a SYSVADPROPERTY, the property item is a SYSVADPROPERTY_ITEM, which contains + // some context information from the endpoint + SYSVADPROPERTY_ITEM* item = (SYSVADPROPERTY_ITEM*)PropertyRequest->PropertyItem; + + // retrieve the pin information, so we can validate that this was called on the keyword pin + if (PropertyRequest->InstanceSize < (sizeof(KSP_PIN) - RTL_SIZEOF_THROUGH_FIELD(KSP_PIN, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSP_PIN, PinId); + + // Only Keyword burst pins may support interleaving loopback and microphone audio + if (!IsKeywordDetectorPin(propertyInstance->PinId)) + { + return STATUS_INVALID_PARAMETER; + } + + // If the context data provided for this endpoint is invalid, or if it is larger than the amount + // of data requested, then we have an invalid parameter + if (NULL == item->ContextData || item->ContextDataSize > PropertyRequest->ValueSize) + { + return STATUS_INVALID_PARAMETER; + } + + // copy the context data (which is interleaving information), into the output. + RtlCopyMemory(PropertyRequest->Value, item->ContextData , item->ContextDataSize); + + return STATUS_SUCCESS; +} + + #pragma code_seg() NTSTATUS CMiniportWaveRT_EventHandler_SoundDetectorMatchDetected ( @@ -3101,10 +3442,13 @@ exit: #pragma code_seg("PAGE") CKeywordDetector::CKeywordDetector() : + m_streamRunning(FALSE), m_qpcStartCapture(0), m_nLastQueuedPacket(-1), - m_SoundDetectorArmed(FALSE), - m_SoundDetectorData(0), + m_SoundDetectorArmed1(FALSE), + m_SoundDetectorArmed2(FALSE), + m_SoundDetectorData1(0), + m_SoundDetectorData2(0), m_ullKeywordStartTimestamp(0), m_ullKeywordStopTimestamp(0) { @@ -3165,29 +3509,96 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -VOID CKeywordDetector::ResetDetector() +NTSTATUS CKeywordDetector::ResetDetector(_In_ GUID eventId) { PAGED_CODE(); - m_SoundDetectorData = 0; + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else if(eventId == GUID_NULL) + { + // When DownloadDetectorData is called to set the pattern for multiple keywords + // at once, all keyword detectors must be reset. Also used during keyword detector + // initialization and cleanup to restore it back to initial state and power down. + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; } #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -VOID CKeywordDetector::DownloadDetectorData(_In_ LONGLONG Data) +NTSTATUS CKeywordDetector::DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data) { PAGED_CODE(); - m_SoundDetectorData = Data; + // reset the detector for this event Id + ResetDetector(eventId); + + // In this example, the driver supports detection data + // set with a single call for both detectors, or each + // detector set individually. + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = Data; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = Data; + } + else if(eventId == GUID_NULL) + { + // in this simplified example "Data" is set on both detectors, + // however in a real system "Data" could be a data structure which + // contains different values for each detector. + m_SoundDetectorData1 = m_SoundDetectorData2 = Data; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; } +// The following function is only applicable to single keyword detection systems, +// and assumes keyword detector #1. #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -LONGLONG CKeywordDetector::GetDetectorData() +NTSTATUS CKeywordDetector::GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data) { PAGED_CODE(); - return m_SoundDetectorData; + if (eventId == CONTOSO_KEYWORD1) + { + *Data = m_SoundDetectorData1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Data = m_SoundDetectorData2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + + return STATUS_SUCCESS; } #pragma code_seg("PAGE") @@ -3228,30 +3639,85 @@ VOID CKeywordDetector::ResetFifo() #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS CKeywordDetector::SetArmed(_In_ BOOL Arm) +NTSTATUS CKeywordDetector::SetArmed(_In_ GUID eventId, _In_ BOOL Arm) { PAGED_CODE(); - BOOL previousArming = m_SoundDetectorArmed; + BOOL previousArming = FALSE; NTSTATUS ntStatus = STATUS_SUCCESS; - m_SoundDetectorArmed = Arm; + // the previous state is "armed" if either detector is armed. + // this reflects the fact that both detectors are sharing the + // same stream. + previousArming = m_SoundDetectorArmed1 || m_SoundDetectorArmed2; + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorArmed1 = Arm; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorArmed2 = Arm; + } + else + { + return STATUS_INVALID_PARAMETER; + } if (Arm && !previousArming && m_qpcStartCapture == 0) { - ntStatus = ReadKeywordTimestampRegistry(); StartBufferingStream(); } + else if (!Arm && previousArming && !m_streamRunning) + { + // if it's not actively streaming and everything has been disarmed, + // then stop buffering. + ResetFifo(); + } + return ntStatus; } #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -BOOL CKeywordDetector::GetArmed() +NTSTATUS CKeywordDetector::GetArmed(_In_ GUID eventId, _Out_ BOOL *Arm) { PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; - return m_SoundDetectorArmed; + if (eventId == CONTOSO_KEYWORD1) + { + *Arm = m_SoundDetectorArmed1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Arm = m_SoundDetectorArmed2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetStreamingSupport(_In_ GUID eventId, _Out_ BOOL *Support) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (eventId == GUID_NULL) + { + *Support = TRUE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; } #pragma code_seg("PAGE") @@ -3264,6 +3730,8 @@ VOID CKeywordDetector::Run() { StartBufferingStream(); } + + m_streamRunning = TRUE; } #pragma code_seg("PAGE") @@ -3273,6 +3741,7 @@ VOID CKeywordDetector::Stop() PAGED_CODE(); ResetFifo(); + m_streamRunning = FALSE; } #pragma code_seg("PAGE") @@ -3289,6 +3758,63 @@ VOID CKeywordDetector::StartBufferingStream() qpc = KeQueryPerformanceCounter(&qpcFrequency); m_qpcStartCapture = qpc.QuadPart; + m_qpcFrequency = qpcFrequency.QuadPart; + + return; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::NotifyDetection() +{ + PAGED_CODE(); + + // A detection will only happen if armed and the + // stream is already running. If there isn't a client + // running, then set the stream start time to align + // with this detection. + if (!m_streamRunning) + { + StartBufferingStream(); + + // The following code is for testing purposes only. + // m_qpcFrequency is defined to be the number of ticks in 1 second. + // Use the stream start time (the current time retrieved in StartBufferStream) to + // mark when the keyword ended, and the start time minus 1 second worth of ticks + // to mark when the keyword started. Also, adjust the stream start time to align + // to this new keyword start time, so that the simulated stream contains the full keyword. + + m_ullKeywordStopTimestamp = m_qpcStartCapture; // stop time is the current time + m_qpcStartCapture = m_qpcStartCapture - m_qpcFrequency; // buffer start time is 1 second ago + m_ullKeywordStartTimestamp = m_qpcStartCapture; // buffer start time = keyword start time + + } + else + { + // The following code is for testing purposes only. + // If the stream is running, we cannot modify qpcStartCapture to be in + // the past, so instead make the keyword start & stop times fit within the + // time period that the keyword has been running. If it has been running + // for more than 1 second, then set the keyword start time to be 1 second back + // into the stream, as though we just figured out there was a keyword there. + // If it has been running less than one second, then the keyword size ends + // up being however long the stream has been running. + + LARGE_INTEGER qpc; + qpc = KeQueryPerformanceCounter(NULL); + + m_ullKeywordStopTimestamp = qpc.QuadPart; // stop time is the current time + + if (m_qpcStartCapture < (qpc.QuadPart - m_qpcFrequency)) + { + m_ullKeywordStartTimestamp = (qpc.QuadPart - m_qpcFrequency); + } + else + { + m_ullKeywordStartTimestamp = m_qpcStartCapture; + } + + } return; } |
