summaryrefslogtreecommitdiff
path: root/audio/sysvad/EndpointsCommon/minwavert.cpp
diff options
context:
space:
mode:
authorDaniel Rugerio <[email protected]>2019-06-28 16:08:54 -0700
committerAdonais Romero González <[email protected]>2019-06-28 16:08:54 -0700
commit8ffcdad009e4d410f92fabc4e322a76a0be3a69d (patch)
tree378b2d98a4210c61e2bc34f5b8959e87e4be5c6c /audio/sysvad/EndpointsCommon/minwavert.cpp
parent75b2290f2a4ece68739d07135d352cdfec3a9e89 (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.cpp574
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;
}