summaryrefslogtreecommitdiff
path: root/sensors/Activity/device.cpp
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /sensors/Activity/device.cpp
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'sensors/Activity/device.cpp')
-rw-r--r--sensors/Activity/device.cpp831
1 files changed, 831 insertions, 0 deletions
diff --git a/sensors/Activity/device.cpp b/sensors/Activity/device.cpp
new file mode 100644
index 00000000..1414b67b
--- /dev/null
+++ b/sensors/Activity/device.cpp
@@ -0,0 +1,831 @@
+// Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+// Abstract:
+// This module contains the type definitions for the client driver's device callback class.
+//
+// Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "HardwareSimulator.h"
+#include "Device.tmh"
+
+// Activity Unique ID {8b3dd227-cc0e-465f-a36e-811c94a1b240}
+DEFINE_GUID(GUID_ActivityDevice_UniqueID, 0x8b3dd227, 0xcc0e, 0x465f, 0xa3, 0x6e, 0x81, 0x1c, 0x94, 0xa1, 0xb2, 0x40);
+
+static const float ActivityFakeDevice_Confidence_Resolution = 1.0f;
+static const float ActivityFakeDevice_Confidence_Minimum = 0.0f;
+static const float ActivityFakeDevice_Confidence_Maximum = 100.0f;
+
+// This routine initializes the sensor's enumeration properties
+NTSTATUS ActivityDevice::InitializeEnumerationProperties()
+{
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+ const ULONG size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ENUMERATION_PROPERTIES_COUNT);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = m_SensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pEnumerationProperties));
+ if (!NT_SUCCESS(status) || nullptr == m_pEnumerationProperties)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, size);
+ m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT;
+
+ m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_ActivityDetection,
+ &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
+ InitPropVariantFromString(L"Microsoft",
+ &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model;
+ InitPropVariantFromString(L"Fake ACTIVITY V2",
+ &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));
+
+ m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
+ InitPropVariantFromCLSID(GUID_ActivityDevice_UniqueID,
+ &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value));
+
+ m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category;
+ InitPropVariantFromCLSID(GUID_SensorCategory_Motion,
+ &(m_pEnumerationProperties->List[SENSOR_CATEGORY].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
+ InitPropVariantFromUInt32(Act_Default_MinDataInterval_Ms,
+ &(m_pEnumerationProperties->List[SENSOR_MIN_INTERVAL].Value));
+
+ m_pEnumerationProperties->List[SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
+ InitPropVariantFromFloat((m_HistoryPowerInuW / 1000.0f),
+ &(m_pEnumerationProperties->List[SENSOR_POWER].Value));
+
+ m_pEnumerationProperties->List[SENSOR_SUPPORTEDACTIVITIES].Key = PKEY_SensorData_SupportedActivityStates;
+ InitPropVariantFromUInt32(Act_Default_SubscribedStates,
+ &(m_pEnumerationProperties->List[SENSOR_SUPPORTEDACTIVITIES].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
+ InitPropVariantFromUInt32(SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * m_HistorySizeInRecords),
+ &(m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Value)); // History only logs one most probable state
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine initializes the sensor's properties
+NTSTATUS ActivityDevice::InitializeSensorProperties()
+{
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+ const ULONG size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = m_SensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pProperties));
+ if (!NT_SUCCESS(status) || nullptr == m_pProperties)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_COLLECTION_LIST_INIT(m_pProperties, size);
+ m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT;
+
+ m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State;
+ InitPropVariantFromUInt32(SensorState_Initializing,
+ &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
+ InitPropVariantFromUInt32(Act_Default_MinDataInterval_Ms,
+ &(m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
+ InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pLastSample),
+ &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_ActivityDetection,
+ &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
+ InitPropVariantFromFloat((m_HistoryPowerInuW / 1000.0f),
+ &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_SUPPORTEDACTIVITIES].Key = PKEY_SensorData_SupportedActivityStates;
+ InitPropVariantFromUInt32(Act_Default_SubscribedStates,
+ &(m_pProperties->List[SENSOR_PROPERTY_SUPPORTEDACTIVITIES].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
+ InitPropVariantFromUInt32(SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * m_HistorySizeInRecords),
+ &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Value)); // History only logs one most probable state
+
+ m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Key = PKEY_SensorHistory_Interval_Ms;
+ InitPropVariantFromUInt32(m_HistoryIntervalInMs,
+ &(m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Key = PKEY_SensorHistory_MaximumRecordSize_Bytes;
+ InitPropVariantFromUInt32(m_HistoryMarshalledRecordSize,
+ &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Value));
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine initializes the data field properties
+NTSTATUS ActivityDevice::InitializeDataFieldProperties()
+{
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+ const ULONG size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = m_SensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pDataFieldProperties));
+ if (!NT_SUCCESS(status) || nullptr == m_pDataFieldProperties)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_COLLECTION_LIST_INIT(m_pDataFieldProperties, size);
+ m_pDataFieldProperties->Count = SENSOR_DATA_FIELD_PROPERTY_COUNT;
+
+ m_pDataFieldProperties->List[SENSOR_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
+ InitPropVariantFromFloat(ActivityFakeDevice_Confidence_Resolution,
+ &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value));
+
+ m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
+ InitPropVariantFromFloat(ActivityFakeDevice_Confidence_Minimum,
+ &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value));
+
+ m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
+ InitPropVariantFromFloat(ActivityFakeDevice_Confidence_Maximum,
+ &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value));
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine initializes the supported data fields
+NTSTATUS ActivityDevice::InitializeSupportedDataFields()
+{
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+ const ULONG size = SENSOR_PROPERTY_LIST_SIZE(ACTIVITY_DATA_COUNT);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = m_SensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pSupportedDataFields));
+ if (!NT_SUCCESS(status) || nullptr == m_pSupportedDataFields)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, size);
+ m_pSupportedDataFields->Count = ACTIVITY_DATA_COUNT;
+
+ m_pSupportedDataFields->List[ACTIVITY_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp;
+ m_pSupportedDataFields->List[ACTIVITY_DATA_CURRENT_STATE] = PKEY_SensorData_CurrentActivityState;
+ m_pSupportedDataFields->List[ACTIVITY_DATA_CURRENT_CONFIDENCE] = PKEY_SensorData_CurrentActivityStateConfidence_Percentage;
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine initializes the sensor to its default properties
+NTSTATUS ActivityDevice::Initialize(
+ _In_ WDFDEVICE device, // WDFDEVICE object
+ _In_ SENSOROBJECT sensorInstance) // SENSOROBJECT for each sensor instance
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Initial configuration
+ m_FxDevice = device;
+ m_SensorInstance = sensorInstance;
+ m_Interval = Act_Default_MinDataInterval_Ms;
+ m_FirstSample = TRUE;
+ m_Started = FALSE;
+ m_HistorySizeInRecords = Act_Default_MaxHistoryEntries;
+ m_HistoryPowerInuW = Act_Default_Power_uW;
+ m_HistoryIntervalInMs = Act_Default_HistoryInterval_Ms;
+ m_HistoryStarted = FALSE;
+ m_HistoryRetrievalStarted = FALSE;
+ m_History.FirstElemIndex = 0;
+ m_History.LastElemIndex = 0;
+ m_History.NumOfElems = 0;
+ m_History.BufferLength = m_HistorySizeInRecords;
+ m_hThread = NULL;
+
+ // Initialize the activity simulator
+ status = HardwareSimulator::Initialize(device, &m_SimulatorInstance);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", status);
+ status = STATUS_SUCCESS; // Failed to set up simulator should not fail the driver
+ }
+
+ // Create Lock
+ status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfWaitLockCreate failed %!STATUS!", status);
+ }
+
+ // Create history lock
+ if (NT_SUCCESS(status))
+ {
+ status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_HistoryLock);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfWaitLockCreate failed %!STATUS!", status);
+ }
+ }
+
+ // Create timer object for polling sensor samples
+ if (NT_SUCCESS(status))
+ {
+ WDF_OBJECT_ATTRIBUTES timerAttributes = {};
+ WDF_TIMER_CONFIG timerConfig = {};
+
+ WDF_TIMER_CONFIG_INIT(&timerConfig, ActivityDevice::OnTimerExpire);
+ WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);
+ timerAttributes.ParentObject = sensorInstance;
+ timerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_Timer);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfTimerCreate failed %!STATUS!", status);
+ }
+ }
+
+ // Create timer object for keeping history
+ if (NT_SUCCESS(status))
+ {
+ WDF_OBJECT_ATTRIBUTES timerAttributes = {};
+ WDF_TIMER_CONFIG timerConfig = {};
+
+ WDF_TIMER_CONFIG_INIT(&timerConfig, ActivityDevice::OnHistoryTimerExpire);
+ WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);
+ timerAttributes.ParentObject = sensorInstance;
+ timerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_HistoryTimer);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfTimerCreate for history failed %!STATUS!", status);
+ }
+ }
+
+ // Last available data
+ if (NT_SUCCESS(status))
+ {
+ // Allocate a buffer for max state count. 7 States and 1 timestamp, each
+ // state has activity and confidence. The actual size will be adjusted when
+ // data is ready to be pushed to clx.
+ const ULONG size = SENSOR_COLLECTION_LIST_SIZE(Act_Max_State_Count * 2 + 1);
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = sensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pLastSample));
+ if (!NT_SUCCESS(status) || nullptr == m_pLastSample)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ FILETIME time = {};
+ SENSOR_COLLECTION_LIST_INIT(m_pLastSample, size);
+ m_pLastSample->Count = Act_Max_State_Count * 2 + 1;
+ m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
+ InitPropVariantFromFileTime(&time, &(m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Value));
+ for (ULONG Count = 1; Count < Act_Max_State_Count * 2 + 1; Count += 2)
+ {
+ m_pLastSample->List[Count].Key = PKEY_SensorData_CurrentActivityState;
+ InitPropVariantFromUInt32(ActivityState_Stationary, &(m_pLastSample->List[Count].Value));
+ m_pLastSample->List[Count + 1].Key = PKEY_SensorData_CurrentActivityStateConfidence_Percentage;
+ InitPropVariantFromUInt16(100, &(m_pLastSample->List[Count + 1].Value));
+ }
+ }
+ }
+
+ // Filtered data
+ if (NT_SUCCESS(status) && nullptr != m_pLastSample && 0 != m_pLastSample->AllocatedSizeInBytes)
+ {
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = sensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ m_pLastSample->AllocatedSizeInBytes,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pFilteredSample));
+ if (!NT_SUCCESS(status) || nullptr == m_pFilteredSample)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ // It's safe to memcpy because there is no embedded pointer
+ memcpy_s(m_pFilteredSample, m_pLastSample->AllocatedSizeInBytes, m_pLastSample, m_pLastSample->AllocatedSizeInBytes);
+ }
+ }
+
+ // Get the Marshalled size for a single history record
+ if (NT_SUCCESS(status))
+ {
+ // Set the count to 3, as the History Record contains information about only
+ // the most probable activity (unlike the Activity Data that can represent multiple activities)
+ // { Timestamp, ActivityState, Confidence}
+ m_pFilteredSample->Count = 3;
+ // History Retrieval is not WOW64 compatible and hence will not involve
+ // serializing the collections list. Should Use
+ // CollectionsListGetMarshalledSizeWithoutSerialization instead of
+ // CollectionsListGetMarshalledSize when dealing with History Collection list.
+ m_HistoryMarshalledRecordSize = CollectionsListGetMarshalledSizeWithoutSerialization(m_pFilteredSample);
+ }
+
+ // Sensor Properties. This must be called after setting up m_pLastSample and m_HistoryMarshalledRecordSize
+ if (NT_SUCCESS(status))
+ {
+ status = InitializeSensorProperties();
+ }
+
+ // Sensor Enumeration Properties.
+ if (NT_SUCCESS(status))
+ {
+ status = InitializeEnumerationProperties();
+ }
+
+ // Supported Data-Fields
+ if (NT_SUCCESS(status))
+ {
+ status = InitializeSupportedDataFields();
+ }
+
+ // Data field properties
+ if (NT_SUCCESS(status))
+ {
+ status = InitializeDataFieldProperties();
+ }
+
+ // Set default threshold
+ if (NT_SUCCESS(status))
+ {
+ const ULONG size = SENSOR_COLLECTION_LIST_SIZE(ACTIVITY_THRESHOLD_COUNT);
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = sensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&m_pThresholds));
+ if (!NT_SUCCESS(status) || nullptr == m_pThresholds)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_COLLECTION_LIST_INIT(m_pThresholds, size);
+ m_pThresholds->Count = ACTIVITY_THRESHOLD_COUNT;
+
+ m_pThresholds->List[ACTIVITY_THRESHOLD_SUBSCRIBED_STATES].Key = PKEY_SensorData_SubscribedActivityStates;
+ InitPropVariantFromUInt32(Act_Default_SubscribedStates,
+ &(m_pThresholds->List[ACTIVITY_THRESHOLD_SUBSCRIBED_STATES].Value));
+
+ m_pThresholds->List[ACTIVITY_THRESHOLD_STREAMING].Key = PKEY_SensorData_ActivityStream;
+ InitPropVariantFromBoolean(Act_Default_Streaming,
+ &(m_pThresholds->List[ACTIVITY_THRESHOLD_STREAMING].Value));
+
+ m_pThresholds->List[ACTIVITY_THRESHOLD_CONFIDENCE].Key = PKEY_SensorData_ConfidenceThreshold_Percentage;
+ InitPropVariantFromUInt16(Act_Default_ConfidenceThreshold_Percentage,
+ &(m_pThresholds->List[ACTIVITY_THRESHOLD_CONFIDENCE].Value));
+ }
+ }
+
+ // Initialize history buffer
+ if (NT_SUCCESS(status))
+ {
+ const ULONG size = sizeof(ActivitySample) * m_HistorySizeInRecords;
+ WDF_OBJECT_ATTRIBUTES memoryAttributes = {};
+ WDFMEMORY memoryHandle = NULL;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = sensorInstance;
+ status = WdfMemoryCreate(&memoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_ACTIVITY,
+ size,
+ &memoryHandle,
+ reinterpret_cast<PVOID*>(&(m_History.pData)));
+ if (!NT_SUCCESS(status) || nullptr == m_History.pData)
+ {
+ TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status);
+ }
+ }
+
+ // Create event for signaling the history retrieval thread to exit
+ if (NT_SUCCESS(status))
+ {
+ m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (NULL == m_ExitEvent || INVALID_HANDLE_VALUE == m_ExitEvent)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! Failed to create an event %!STATUS!", status);
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is the AddDevice entry point for the fake activity client
+// driver. This routine is called by the framework in response to AddDevice
+// call from the PnP manager. It will create and initialize the device object
+// to represent a new instance of the sensor client.
+NTSTATUS ActivityDevice::OnDeviceAdd(
+ _In_ WDFDRIVER /*driver*/, // Supplies a handle to the driver object created in DriverEntry
+ _Inout_ PWDFDEVICE_INIT pDeviceInit) // Supplies a pointer to a framework-allocated WDFDEVICE_INIT structure
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Initialize FDO attributes and set up file object with sensor extension
+ WDF_OBJECT_ATTRIBUTES fdoAttributes = {};
+ ULONG flag = 0;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
+ status = SensorsCxDeviceInitConfig(pDeviceInit, &fdoAttributes, flag);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! SensorsCxDeviceInitConfig failed %!STATUS!", status);
+ }
+ else
+ {
+ WDF_PNPPOWER_EVENT_CALLBACKS callbacks = {};
+ WDFDEVICE device = NULL;
+
+ // Register the PnP callbacks with the framework.
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&callbacks);
+ callbacks.EvtDevicePrepareHardware = ActivityDevice::OnPrepareHardware;
+ callbacks.EvtDeviceReleaseHardware = ActivityDevice::OnReleaseHardware;
+ callbacks.EvtDeviceD0Entry = ActivityDevice::OnD0Entry;
+ callbacks.EvtDeviceD0Exit = ActivityDevice::OnD0Exit;
+ WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &callbacks);
+
+ // Call the framework to create the device
+ status = WdfDeviceCreate(&pDeviceInit, &fdoAttributes, &device);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfDeviceCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_CONTROLLER_CONFIG sensorConfig = {};
+
+ // Register CLX callback function pointers
+ SENSOR_CONTROLLER_CONFIG_INIT(&sensorConfig);
+ sensorConfig.DriverIsPowerPolicyOwner = WdfUseDefault;
+
+ sensorConfig.EvtSensorStart = ActivityDevice::OnStart;
+ sensorConfig.EvtSensorStop = ActivityDevice::OnStop;
+ sensorConfig.EvtSensorGetSupportedDataFields = ActivityDevice::OnGetSupportedDataFields;
+ sensorConfig.EvtSensorGetDataInterval = ActivityDevice::OnGetDataInterval;
+ sensorConfig.EvtSensorSetDataInterval = ActivityDevice::OnSetDataInterval;
+ sensorConfig.EvtSensorGetDataFieldProperties = ActivityDevice::OnGetDataFieldProperties;
+ sensorConfig.EvtSensorGetDataThresholds = ActivityDevice::OnGetDataThresholds;
+ sensorConfig.EvtSensorSetDataThresholds = ActivityDevice::OnSetDataThresholds;
+ sensorConfig.EvtSensorGetProperties = ActivityDevice::OnGetProperties;
+ sensorConfig.EvtSensorDeviceIoControl = ActivityDevice::OnIoControl;
+ sensorConfig.EvtSensorStartHistory = ActivityDevice::OnStartHistory;
+ sensorConfig.EvtSensorStopHistory = ActivityDevice::OnStopHistory;
+ sensorConfig.EvtSensorClearHistory = ActivityDevice::OnClearHistory;
+ sensorConfig.EvtSensorStartHistoryRetrieval = ActivityDevice::OnStartHistoryRetrieval;
+ sensorConfig.EvtSensorCancelHistoryRetrieval = ActivityDevice::OnCancelHistoryRetrieval;
+
+ // Set up power capabilities and IO queues
+ status = SensorsCxDeviceInitialize(device, &sensorConfig);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! SensorsCxDeviceInitialize failed %!STATUS!", status);
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is called by the framework when the PnP manager sends an
+// IRP_MN_START_DEVICE request to the driver stack. This routine is
+// responsible for performing operations that are necessary to make the
+// driver's device operational (for e.g. mapping the hardware resources
+// into memory).
+NTSTATUS ActivityDevice::OnPrepareHardware(
+ _In_ WDFDEVICE device, // Supplies a handle to the framework device object
+ _In_ WDFCMRESLIST /*ResourcesRaw*/, // Supplies a handle to a collection of framework resource
+ // objects. This collection identifies the raw (bus-relative) hardware
+ // resources that have been assigned to the device.
+ _In_ WDFCMRESLIST /*ResourcesTranslated*/) // Supplies a handle to a collection of framework
+ // resource objects. This collection identifies the translated
+ // (system-physical) hardware resources that have been assigned to the
+ // device. The resources appear from the CPU's point of view.
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Create WDFOBJECT for the sensor
+ WDF_OBJECT_ATTRIBUTES sensorAttributes = {};
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&sensorAttributes, ActivityDevice);
+
+ // Register sensor instance with clx
+ SENSOROBJECT sensorInstance = NULL;
+ status = SensorsCxSensorCreate(device, &sensorAttributes, &sensorInstance);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! SensorsCxSensorCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Fill out properties
+ status = pDevice->Initialize(device, sensorInstance);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! Initialize device object failed %!STATUS!", status);
+ }
+ else
+ {
+ SENSOR_CONFIG sensorConfig = {};
+ SENSOR_CONFIG_INIT(&sensorConfig);
+ sensorConfig.pEnumerationList = pDevice->m_pEnumerationProperties;
+ status = SensorsCxSensorInitialize(sensorInstance, &sensorConfig);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! SensorsCxSensorInitialize failed %!STATUS!", status);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is called by the framework when the PnP manager is revoking
+// ownership of our resources. This may be in response to either
+// IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. This routine is responsible for
+// performing cleanup of resources allocated in PrepareHardware callback.
+// This callback is invoked before passing the request down to the lower driver.
+// This routine will also be invoked by the framework if the prepare hardware
+// callback returns a failure.
+NTSTATUS ActivityDevice::OnReleaseHardware(
+ _In_ WDFDEVICE device, // Supplies a handle to the framework device object
+ _In_ WDFCMRESLIST /*ResourcesTranslated*/) // Supplies a handle to a collection of framework
+ // resource objects. This collection identifies the translated
+ // (system-physical) hardware resources that have been assigned to the
+ // device. The resources appear from the CPU's point of view.
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ SENSOROBJECT sensorInstance = NULL;
+ ULONG sensorInstanceCount = 1; // only expect 1 sensor instance
+
+ status = SensorsCxDeviceGetSensorList(device, &sensorInstance, &sensorInstanceCount);
+ if (!NT_SUCCESS(status) || sensorInstanceCount == 0 || sensorInstance == NULL)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", status);
+ }
+ else
+ {
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Cleanup activity simulator
+ if (NULL != pDevice->m_SimulatorInstance)
+ {
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr != pSimulator)
+ {
+ pSimulator->Deinitialize();
+ }
+ // Continue tearing down
+ WdfObjectDelete(pDevice->m_SimulatorInstance);
+ pDevice->m_SimulatorInstance = NULL;
+ }
+
+ // Close handle to history retrieval thread
+ if (NULL != pDevice->m_hThread)
+ {
+ SetEvent(pDevice->m_ExitEvent);
+
+ DWORD result = WaitForSingleObjectEx(pDevice->m_hThread, Act_TimeoutForHistoryThread_Ms, FALSE);
+ if (WAIT_OBJECT_0 != result)
+ {
+ // continue tearing down
+ status = NTSTATUS_FROM_WIN32(result);
+ TraceError("ACT %!FUNC! WaitForSingleObjectEx failed %!STATUS!", status);
+ }
+
+ CloseHandle(pDevice->m_hThread);
+ pDevice->m_hThread = NULL;
+ }
+
+ // Close handle to exit event
+ if (NULL != pDevice->m_ExitEvent)
+ {
+ CloseHandle(pDevice->m_ExitEvent);
+ pDevice->m_ExitEvent = NULL;
+ }
+
+ // Delete history lock
+ if (NULL != pDevice->m_HistoryLock)
+ {
+ WdfObjectDelete(pDevice->m_HistoryLock);
+ pDevice->m_HistoryLock = NULL;
+ }
+
+ // Delete lock
+ if (NULL != pDevice->m_Lock)
+ {
+ WdfObjectDelete(pDevice->m_Lock);
+ pDevice->m_Lock = NULL;
+ }
+
+ // Delete sensor instance.
+ if (NULL != pDevice->m_SensorInstance)
+ {
+ // Memory created by WdfMemoryCreate with m_SensorInstance as parent object will be
+ // destroyed automatically when m_SensorInstance is deleted. pDevice will be no longer
+ // accessible at beyond this point.
+ WdfObjectDelete(pDevice->m_SensorInstance);
+ pDevice = nullptr;
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is invoked by the framework to program the device to goto
+// D0, which is the working state. The framework invokes callback every
+// time the hardware needs to be (re-)initialized. This includes after
+// IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
+// and IRP_MN_SET_POWER-D0.
+NTSTATUS ActivityDevice::OnD0Entry(
+ _In_ WDFDEVICE device, // Supplies a handle to the framework device object
+ _In_ WDF_POWER_DEVICE_STATE /*PreviousState*/) // WDF_POWER_DEVICE_STATE-typed enumerator that identifies the device
+ // power state that the device was in before this transition to D0.
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ SENSOROBJECT sensorInstance = NULL;
+ ULONG sensorInstanceCount = 1;
+
+ status = SensorsCxDeviceGetSensorList(device, &sensorInstance, &sensorInstanceCount);
+ if (!NT_SUCCESS(status) || sensorInstanceCount == 0 || sensorInstance == NULL)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", status);
+ }
+ else
+ {
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Power on sensor
+ pDevice->m_PoweredOn = TRUE;
+ InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is invoked by the framework to program the device to go into
+// a certain Dx state. The framework invokes callback every the the device is
+// leaving the D0 state, which happens when the device is stopped, when it is
+// removed, and when it is powered off.
+NTSTATUS ActivityDevice::OnD0Exit(
+ _In_ WDFDEVICE device, // Supplies a handle to the framework device object.
+ _In_ WDF_POWER_DEVICE_STATE /*TargetState*/) // Supplies the device power state which the device
+ // will be put in once the callback is complete.
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ SENSOROBJECT sensorInstance = NULL;
+ ULONG sensorInstanceCount = 1;
+ status = SensorsCxDeviceGetSensorList(device, &sensorInstance, &sensorInstanceCount);
+ if (!NT_SUCCESS(status) || sensorInstanceCount == 0 || sensorInstance == NULL)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", status);
+ }
+ else
+ {
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Power off sensor
+ pDevice->m_PoweredOn = FALSE;
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+} \ No newline at end of file