summaryrefslogtreecommitdiff
path: root/Sensors/Pedometer/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Sensors/Pedometer/client.cpp')
-rw-r--r--Sensors/Pedometer/client.cpp1242
1 files changed, 1242 insertions, 0 deletions
diff --git a/Sensors/Pedometer/client.cpp b/Sensors/Pedometer/client.cpp
new file mode 100644
index 00000000..debce7d1
--- /dev/null
+++ b/Sensors/Pedometer/client.cpp
@@ -0,0 +1,1242 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of driver callback function
+// from clx to pedometer.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "HardwareSimulator.h"
+
+#include <timeapi.h>
+#include <Intsafe.h>
+
+#include "Client.tmh"
+
+// This routine is called by worker thread to read a single sample, compare threshold
+// and push it back to CLX. It simulates hardware thresholding by only generating data
+// when the change of data is greater than threshold.
+NTSTATUS
+PedometerDevice::GetData(
+)
+{
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
+ BOOLEAN DataReady = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG CachedStepCountLimit = 0;
+ ULONG LastStepCountLimit = 0;
+ PedometerSample Sample = {};
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ Status = pSimulator->GetSample(&Sample);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! GetSample failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (FALSE != m_FirstSample)
+ {
+ Status = GetPerformanceTime(&m_StartTime);
+ if (!NT_SUCCESS(Status))
+ {
+ m_StartTime = 0;
+ TraceError("PED %!FUNC! GetPerformanceTime failed %!STATUS!", Status);
+ }
+
+ m_SampleCount = 0;
+
+ DataReady = TRUE;
+ }
+ else
+ {
+ if (0 == m_CachedThreshold || FALSE != Sample.IsFirstAfterReset)
+ {
+ // Streaming mode
+ DataReady = TRUE;
+ }
+ else
+ {
+ if (FAILED(ULongAdd(Sample.UnknownStepCount, Sample.WalkingStepCount, &CachedStepCountLimit)) ||
+ FAILED(ULongAdd(Sample.RunningStepCount, CachedStepCountLimit, &CachedStepCountLimit)))
+ {
+ // If an overflow happened, we assume we reached the threshold
+ // in other words, there is no threshold value that can be larger
+ // than an overflowed value.
+ DataReady = TRUE;
+ }
+ else if (FAILED(ULongAdd(m_LastSample.UnknownStepCount, m_LastSample.WalkingStepCount, &LastStepCountLimit)) ||
+ FAILED(ULongAdd(m_LastSample.RunningStepCount, LastStepCountLimit, &LastStepCountLimit)))
+ {
+ // If an overflow happened, we assume we reached the threshold
+ // in other words, there is no threshold value that can be larger
+ // than an overflowed value.
+ DataReady = TRUE;
+ }
+ else if ((LastStepCountLimit < m_CachedThreshold && CachedStepCountLimit >= m_CachedThreshold) ||
+ (FALSE != Sample.IsFirstAfterReset))
+ {
+ // Compare the change of data to threshold, and only push the data back to
+ // clx if the change exceeds threshold or if this is the first sample after reset. This is usually done in HW.
+ DataReady = TRUE;
+ }
+ }
+ }
+
+ if (FALSE != DataReady)
+ {
+ // update last sample
+ m_LastSample = Sample;
+
+ // push to clx
+ InitPropVariantFromBoolean(m_LastSample.IsFirstAfterReset, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));
+ InitPropVariantFromUInt32(PedometerStepType_Unknown, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));
+ InitPropVariantFromInt64(m_LastSample.UnknownStepDurationMs, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));
+ InitPropVariantFromUInt32(m_LastSample.UnknownStepCount, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));
+ InitPropVariantFromUInt32(PedometerStepType_Walking, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));
+ InitPropVariantFromInt64(m_LastSample.WalkingStepDurationMs, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));
+ InitPropVariantFromUInt32(m_LastSample.WalkingStepCount, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));
+ InitPropVariantFromUInt32(PedometerStepType_Running, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));
+ InitPropVariantFromInt64(m_LastSample.RunningStepDurationMs, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));
+ InitPropVariantFromUInt32(m_LastSample.RunningStepCount, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));
+
+ // reset IsFirstAfterReset
+ m_LastSample.IsFirstAfterReset = FALSE;
+
+ InitPropVariantFromFileTime(&m_LastSample.Timestamp, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));
+
+ SensorsCxSensorDataReady(m_SensorInstance, m_pData);
+ m_FirstSample = FALSE;
+ }
+ else
+ {
+ Status = STATUS_DATA_NOT_ACCEPTED;
+ TraceInformation("PED %!FUNC! Data did NOT meet the threshold");
+ }
+
+ SENSOR_FunctionExit(Status);
+
+Exit:
+ return Status;
+}
+
+
+
+// This callback is called when interval wait time has expired and driver is ready
+// to collect new sample. The callback reads current value, compare value to threshold,
+// pushes it up to CLX framework, and schedule next wake up time.
+VOID
+PedometerDevice::OnTimerExpire(
+ _In_ WDFTIMER Timer // WDF timer object
+ )
+{
+ PPedometerDevice pDevice = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ pDevice = GetPedometerContextFromSensorInstance(WdfTimerGetParentObject(Timer));
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetPedometerContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Get data and push to clx
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ Status = pDevice->GetData();
+ if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
+ {
+ TraceError("PED %!FUNC! GetData Failed %!STATUS!", Status);
+ }
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ // Schedule next wake up time
+ if (FALSE != pDevice->m_PoweredOn &&
+ FALSE != pDevice->m_Started)
+ {
+ LONGLONG WaitTimeHundredNanoseconds = 0; // in unit of 100ns
+
+ if (0 == pDevice->m_StartTime)
+ {
+ // in case we fail to get sensor start time, use static wait time
+ WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
+ }
+ else
+ {
+ ULONG CurrentTimeMs = 0;
+
+ // dynamically calculate wait time to avoid jitter
+ Status = GetPerformanceTime (&CurrentTimeMs);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! GetPerformanceTime %!STATUS!", Status);
+ WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
+ }
+ else
+ {
+ pDevice->m_SampleCount++;
+ if (CurrentTimeMs > (pDevice->m_StartTime + (pDevice->m_Interval * (pDevice->m_SampleCount + 1))))
+ {
+ // If we skipped two or more beats, reschedule the timer with a zero due time to catch up on missing samples
+ WaitTimeHundredNanoseconds = 0;
+ }
+ else
+ {
+ WaitTimeHundredNanoseconds = (pDevice->m_StartTime +
+ (pDevice->m_Interval * (pDevice->m_SampleCount + 1))) - CurrentTimeMs;
+ }
+ WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(WaitTimeHundredNanoseconds);
+ }
+ }
+ WdfTimerStart(pDevice->m_Timer, WaitTimeHundredNanoseconds);
+ }
+
+Exit:
+
+ SENSOR_FunctionExit(Status);
+}
+
+
+
+// Called by Sensor CLX to begin continuously sampling the sensor.
+NTSTATUS
+PedometerDevice::OnStart(
+ _In_ SENSOROBJECT SensorInstance // Sensor device object
+ )
+{
+ PHardwareSimulator pSimulator = nullptr;
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ // Get the simulator context
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Start the simulator
+ pSimulator->Start();
+
+ pDevice->m_FirstSample = TRUE;
+
+ // Start polling
+
+ pDevice->m_Started = TRUE;
+
+ InitPropVariantFromUInt32(SensorState_Active,
+ &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ // Start the sample polling timer.
+ //
+ // Note: The polling timer is configured to allow for the first sample to be reported immediately.
+ // Some hardware may want to delay the first sample report a little to account for hardware start time.
+ WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Pedometer_Default_MinDataInterval_Ms));
+ }
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to stop continuously sampling the sensor.
+NTSTATUS
+PedometerDevice::OnStop(
+ _In_ SENSOROBJECT SensorInstance // Sensor device object
+ )
+{
+ PHardwareSimulator pSimulator = nullptr;
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ // Stop polling
+ pDevice->m_Started = FALSE;
+
+ // Waiting for the callback to complete, then stopping the timer
+ WdfTimerStop(pDevice->m_Timer, TRUE);
+
+ InitPropVariantFromUInt32(SensorState_Idle,
+ &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ // Stop the simulator
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator->Stop();
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+// Called by Sensor CLX to begin keeping history
+NTSTATUS
+PedometerDevice::OnStartHistory(
+ _In_ SENSOROBJECT SensorInstance // Sensor device object
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHardwareSimulator pSimulator = nullptr;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_HistorySupported)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! History is not supported by the HW");
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_PoweredOn)
+ {
+ Status = STATUS_DEVICE_NOT_READY;
+ TraceError("PED %!FUNC! Sensor is not powered on! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Start the pedometer history
+ Status = pSimulator->StartHistory();
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! Start History failed %!STATUS!", Status);
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to stop keeping history.
+NTSTATUS
+PedometerDevice::OnStopHistory(
+ _In_ SENSOROBJECT SensorInstance // Sensor device object
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHardwareSimulator pSimulator = nullptr;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_HistorySupported)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! History is not supported by the HW");
+ goto Exit;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Stop the pedometer history
+ Status = pSimulator->StopHistory();
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! Stop History failed %!STATUS!", Status);
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+// Resets the pedometer to its initial values.
+VOID
+PedometerDevice::ResetPedometer()
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ }
+ else
+ {
+ // Reset the pedometer
+ pSimulator->Reset();
+ }
+
+ SENSOR_FunctionExit(Status);
+}
+
+// Called by Sensor CLX to clear all history stored in the sensor.
+NTSTATUS
+PedometerDevice::OnClearHistory(
+ _In_ SENSOROBJECT SensorInstance // Sensor device object
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHardwareSimulator pSimulator;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_HistorySupported)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! History is not supported by the HW");
+ goto Exit;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Clear the pedometer history
+ Status = pSimulator->ClearHistory();
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! Clear History failed %!STATUS!", Status);
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to start retrieving history.
+//
+// Arguments:
+// SensorInstance: IN:
+//
+// Return Value:
+// NTSTATUS code
+//------------------------------------------------------------------------------
+NTSTATUS
+PedometerDevice::OnStartHistoryRetrieval(
+ _In_ SENSOROBJECT SensorInstance, // sensor device object
+ _Inout_updates_bytes_(HistorySizeInBytes) PSENSOR_COLLECTION_LIST pHistoryBuffer, // Pointer to a buffer containing the history elements
+ _In_ ULONG HistorySizeInBytes // Size of the pHistoryBuffer buffer in bytes
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN IsLocked = FALSE;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_HistorySupported)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! History is not supported by the HW");
+ goto Exit;
+ }
+
+ // Check if the previously created history retrieval thread finished.
+ // When StartHistoryRetrieval is called again before we signal to CLX that history retrieval is
+ // completed, fail the second call.
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ BOOLEAN IsStarted = pDevice->m_HistoryRetrievalStarted;
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ if (FALSE != IsStarted)
+ {
+ Status = STATUS_DEVICE_BUSY;
+ TraceError("PED %!FUNC! StartHistoryRetrieval called again before the previous call"
+ "finishes retrieving history %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // check that the buffer is not null
+ if (NULL == pHistoryBuffer)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! History buffer cannot be NULL. %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // check that the buffer can hold at least one record
+ if (HistorySizeInBytes < pDevice->m_HistoryMarshalledRecordSize)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ TraceError("PED %!FUNC! History buffer is too small to even fill one complete entry. %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Before creating a new thread, close handle to the previously created thread.
+ if (NULL != pDevice->m_hThread)
+ {
+ CloseHandle(pDevice->m_hThread);
+ pDevice->m_hThread = NULL;
+ }
+
+ pDevice->m_ClientHistoryBuffer = pHistoryBuffer;
+ pDevice->m_ClientHistoryBufferSize = HistorySizeInBytes;
+
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ IsLocked = TRUE;
+
+ // Create a new thread to retrieve data from the driver's history buffer
+ pDevice->m_hThread = CreateThread(NULL, // thread attributes
+ 0, // default stack size
+ HistoryRetrievalThread, //start address
+ reinterpret_cast<void*>(SensorInstance), // pointer to variable to be passed
+ 0, // run immediately
+ NULL); // Thread ID
+ if (NULL == pDevice->m_hThread)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ TraceError("PED %!FUNC! CreateThread Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice->m_HistoryRetrievalStarted = TRUE;
+ WdfWaitLockRelease(pDevice->m_Lock);
+ IsLocked = FALSE;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+
+ if (nullptr != pDevice)
+ {
+ if (FALSE != IsLocked)
+ {
+ WdfWaitLockRelease(pDevice->m_Lock);
+ }
+
+ if (!NT_SUCCESS(Status) && NULL != pDevice->m_hThread)
+ {
+ CloseHandle(pDevice->m_hThread);
+ pDevice->m_hThread = NULL;
+ }
+ }
+
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to cancel history retrieval.
+NTSTATUS
+PedometerDevice::OnCancelHistoryRetrieval(
+ _In_ SENSOROBJECT SensorInstance, // sensor device object
+ _Out_ PULONG pBytesWritten // Upon exit, contains the number of bytes written to the history buffer
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHardwareSimulator pSimulator = nullptr;
+
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pBytesWritten)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Invalid Parameters: Sensor(0x%p), pDevice (0x%p), pBytesWritten (0x%p). Failed %!STATUS!", SensorInstance, pDevice, pBytesWritten, Status);
+ goto Exit;
+ }
+
+ if (FALSE == pDevice->m_HistorySupported)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! History is not supported by the HW");
+ goto Exit;
+ }
+
+ *pBytesWritten = 0;
+
+ // Check if history retrieval operation is in progress
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ BOOLEAN IsStarted = pDevice->m_HistoryRetrievalStarted;
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ if (FALSE == IsStarted)
+ {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ TraceError("PED %!FUNC! History retrieval is not in progress %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Get the simulator context
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ }
+
+ Status = pSimulator->SignalReadCancellation();
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! Failed to cancel history retrieval from HW %!STATUS!", Status);
+ }
+
+ // Wait for the history retrieval thread to finish writing the entry since no partial entries are allowed.
+ DWORD result = WaitForSingleObjectEx(pDevice->m_hThread, Pedometer_TimeoutForHistoryThread_Ms, FALSE);
+ if (WAIT_OBJECT_0 != result)
+ {
+ TraceError("PED %!FUNC! WaitForSingleObjectEx failed with error %d", result);
+ Status = STATUS_DEVICE_BUSY;
+ goto Exit;
+ }
+
+ *pBytesWritten = CollectionsListGetMarshalledSizeWithoutSerialization(pDevice->m_ClientHistoryBuffer);
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Created on calling StartHistoryRetrieval function
+ULONG
+WINAPI
+PedometerDevice::HistoryRetrievalThread(
+ _In_ LPVOID lpParam // sensor device object
+ )
+{
+ WDF_OBJECT_ATTRIBUTES MemoryAttributes;
+ WDFMEMORY MemoryHandle = NULL;
+ PHardwareSimulator pSimulator = nullptr;
+ SENSOROBJECT SensorInstance = reinterpret_cast<SENSOROBJECT>(lpParam);
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ ULONG ReturnCode = ERROR_SUCCESS;
+ PPedometerSample HwHistoryBuffer = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG FillableCount = 0;
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. pDevice is null", SensorInstance);
+ goto Exit;
+ }
+
+ // Get the simulator context
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Get the number of elements that can actually fit into the provided client buffer.
+ FillableCount = (pDevice->m_ClientHistoryBufferSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) / (pDevice->m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE);
+
+ // Allocate enough memory to read the samples from HW
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_PEDOMETER,
+ FillableCount * sizeof(PedometerSample),
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&HwHistoryBuffer));
+ if (!NT_SUCCESS(Status) || nullptr == HwHistoryBuffer)
+ {
+ TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ Status = pSimulator->ReadHistory(&FillableCount, HwHistoryBuffer);
+ if (STATUS_BUFFER_OVERFLOW == Status)
+ {
+ // It is okay to return as much as that fits in the buffer.
+ TraceWarning("PED %!FUNC! Buffer Overflow. More entries available than requested %!STATUS!", Status);
+ }
+ else if (STATUS_CANCELLED == Status)
+ {
+ TraceWarning("PED %!FUNC! Retrieval canceled. Filling the buffer with retrieved entries %!STATUS!", Status);
+ }
+ else if (STATUS_NO_MORE_ENTRIES == Status)
+ {
+ TraceInformation("PED %!FUNC! No history entries available %!STATUS!", Status);
+ goto Exit;
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! Failed to read history from the HW %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // All entries into the client's buffer must be complete i.e. no partial entries are allowed.
+ for (ULONG index = 0; index < FillableCount; index++)
+ {
+ ULONG ElementIndex = 0;
+ PedometerSample Data = HwHistoryBuffer[index];
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_TIMESTAMP;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_Timestamp;
+ InitPropVariantFromFileTime(&(Data.Timestamp), &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_FIRST_AFTER_RESET;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerReset;
+ InitPropVariantFromBoolean(Data.IsFirstAfterReset, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_UNKNOWN_STEP_TYPE;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepType;
+ InitPropVariantFromUInt32(PedometerStepType_Unknown, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_UNKNOWN_STEP_COUNT;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepCount;
+ InitPropVariantFromUInt32(Data.UnknownStepCount, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_UNKNOWN_STEP_DURATION;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepDuration_Ms;
+ InitPropVariantFromInt64(Data.UnknownStepDurationMs, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_WALKING_STEP_TYPE;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepType;
+ InitPropVariantFromUInt32(PedometerStepType_Walking, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_WALKING_STEP_COUNT;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepCount;
+ InitPropVariantFromUInt32(Data.WalkingStepCount, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_WALKING_STEP_DURATION;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepDuration_Ms;
+ InitPropVariantFromInt64(Data.WalkingStepDurationMs, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_RUNNING_STEP_TYPE;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepType;
+ InitPropVariantFromUInt32(PedometerStepType_Running, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_RUNNING_STEP_COUNT;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepCount;
+ InitPropVariantFromUInt32(Data.RunningStepCount, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ ElementIndex = (index * PEDOMETER_DATA_COUNT) + PEDOMETER_DATA_RUNNING_STEP_DURATION;
+ pDevice->m_ClientHistoryBuffer->List[ElementIndex].Key = PKEY_SensorData_PedometerStepDuration_Ms;
+ InitPropVariantFromInt64(Data.RunningStepDurationMs, &(pDevice->m_ClientHistoryBuffer->List[ElementIndex].Value));
+
+ // Keep the count in the sensor collection list updated
+ // so that the count is valid even when exit is signaled.
+ pDevice->m_ClientHistoryBuffer->Count += PEDOMETER_DATA_COUNT;
+ }
+
+Exit:
+
+ if (NULL != MemoryHandle)
+ {
+ // delete the memory handle and associated memory
+ WdfObjectDelete(MemoryHandle);
+ }
+
+ // Update the state before we notify the Sensor CX as we are done with this request at this point
+ // It would also help should the CX invoke 'EvtSensorStartHistoryRetrieval' on the same thread
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ pDevice->m_HistoryRetrievalStarted = FALSE;
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ // call completed method only if retrieval was not canceled
+ if (STATUS_CANCELLED != Status)
+ {
+ SensorsCxSensorHistoryRetrievalCompleted(pDevice->m_SensorInstance, CollectionsListGetMarshalledSizeWithoutSerialization(pDevice->m_ClientHistoryBuffer), Status);
+ }
+
+ return ReturnCode;
+}
+
+
+
+// Called by Sensor CLX to get supported data fields. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS
+PedometerDevice::OnGetSupportedDataFields(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Inout_opt_ PSENSOR_PROPERTY_LIST pFields, // Pointer to a list of supported properties
+ _Out_ PULONG pSize // Number of bytes for the list of supported properties
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Invalid parameters! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pFields)
+ {
+ // Just return size
+ *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ else
+ {
+ if (pFields->AllocatedSizeInBytes < pDevice->m_pSupportedDataFields->AllocatedSizeInBytes)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out data
+ Status = PropertiesListCopy(pFields, pDevice->m_pSupportedDataFields);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! PropertiesListCopy failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to get sensor properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS
+PedometerDevice::OnGetProperties(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pProperties, // Pointer to a list of sensor properties
+ _Out_ PULONG pSize // Number of bytes for the list of sensor properties
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Invalid parameters! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pProperties))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pProperties, pDevice->m_pProperties);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+// Called by Sensor CLX to get data field properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS
+PedometerDevice::OnGetDataFieldProperties(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _In_ const PROPERTYKEY *DataField, // Pointer to the propertykey of requested property
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pProperties, // Pointer to a list of sensor properties
+ _Out_ PULONG pSize // Number of bytes for the list of sensor properties
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize || nullptr == DataField)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Invalid parameters! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if ((*DataField == PKEY_SensorData_PedometerStepCount))
+ {
+ if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall (pProperties, pDevice->m_pDataFieldProperties);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties);
+ }
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("PED %!FUNC! Ped does NOT have properties for this data field. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to get sampling rate of the sensor.
+NTSTATUS
+PedometerDevice::OnGetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Out_ PULONG DataRateMs // Sampling rate in ms
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (nullptr == DataRateMs)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! DataRateMs(0x%p) parameter is invalid. Failed %!STATUS!", DataRateMs, Status);
+ goto Exit;
+ }
+
+ *DataRateMs = pDevice->m_Interval;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to set sampling rate of the sensor.
+NTSTATUS
+PedometerDevice::OnSetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _In_ ULONG DataRateMs // Sampling rate in ms
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (Pedometer_Default_MinDataInterval_Ms > DataRateMs)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! DataRateMs(%d) parameter is smaller than the minimum data interval. Failed %!STATUS!", DataRateMs, Status);
+ goto Exit;
+ }
+
+ pDevice->m_Interval = DataRateMs;
+
+ // reschedule sample to return as soon as possible if it's started
+ if (FALSE != pDevice->m_Started)
+ {
+ pDevice->m_Started = FALSE;
+ WdfTimerStop(pDevice->m_Timer, TRUE);
+
+ pDevice->m_Started = TRUE;
+ pDevice->m_FirstSample = TRUE;
+ WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Pedometer_Default_MinDataInterval_Ms));
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to get data thresholds. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS
+PedometerDevice::OnGetDataThresholds(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pThresholds, // Pointer to a list of sensor thresholds
+ _Out_ PULONG pSize // Number of bytes for the list of sensor thresholds
+ )
+{
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Invalid parameters! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pThresholds)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pThresholds);
+ }
+ else
+ {
+ if (pThresholds->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pThresholds))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("PED %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pThresholds, pDevice->m_pThresholds);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pThresholds);
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+
+ SENSOR_FunctionExit(Status);
+
+ return Status;
+}
+
+
+
+// Called by Sensor CLX to set data thresholds.
+NTSTATUS
+PedometerDevice::OnSetDataThresholds(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _In_ PSENSOR_COLLECTION_LIST pThresholds // Pointer to a list of sensor thresholds
+ )
+{
+ ULONG Element;
+ BOOLEAN IsLocked = FALSE;
+ PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (pDevice == nullptr)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ IsLocked = TRUE;
+
+ for (Element = 0; Element < pThresholds->Count; Element++)
+ {
+ Status = PropKeyFindKeySetPropVariant(pDevice->m_pThresholds,
+ &(pThresholds->List[Element].Key),
+ TRUE,
+ &(pThresholds->List[Element].Value));
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("PED %!FUNC! Pedometer driver does NOT have threshold for this data field. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+ }
+
+ // Get data thresholds
+ Status = PropKeyFindKeyGetUlong(pDevice->m_pThresholds,
+ &PKEY_SensorData_PedometerStepCount,
+ &(pDevice->m_CachedThreshold));
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("PED %!FUNC! PropKeyFindKeyGetUlong for PedometerStepCount failed! %!STATUS!", Status);
+ goto Exit;
+ }
+
+Exit:
+ if (FALSE != IsLocked)
+ {
+ WdfWaitLockRelease(pDevice->m_Lock);
+ IsLocked = FALSE;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+// Called by Sensor CLX to handle IOCTLs that clx does not support
+NTSTATUS
+PedometerDevice::OnIoControl(
+ _In_ SENSOROBJECT /*SensorInstance*/, // WDF queue object
+ _In_ WDFREQUEST /*Request*/, // WDF request object
+ _In_ size_t /*OutputBufferLength*/, // number of bytes to retrieve from output buffer
+ _In_ size_t /*InputBufferLength*/, // number of bytes to retrieve from input buffer
+ _In_ ULONG /*IoControlCode*/ // IOCTL control code
+ )
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+ SENSOR_FunctionEnter();
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+} \ No newline at end of file