summaryrefslogtreecommitdiff
path: root/Sensors/Activity
diff options
context:
space:
mode:
authorWei Mao <[email protected]>2017-03-17 19:47:04 -0700
committerWei Mao <[email protected]>2017-03-17 19:47:04 -0700
commit1a3e0d580380e58bf336a242d2affc8a1e2d1ddf (patch)
treebf5d9c5b0b4cba1b81726b9f78c4d5ff5c636fea /Sensors/Activity
parentda21c8784c83c5fd614f3030323e229d6a5fb10e (diff)
Fix cases
Diffstat (limited to 'Sensors/Activity')
-rw-r--r--Sensors/Activity/Activity.def6
-rw-r--r--Sensors/Activity/Activity.inxbin0 -> 5180 bytes
-rw-r--r--Sensors/Activity/Activity.sln28
-rw-r--r--Sensors/Activity/Activity.vcxproj204
-rw-r--r--Sensors/Activity/Activity.vcxproj.Filters43
-rw-r--r--Sensors/Activity/Device.h200
-rw-r--r--Sensors/Activity/Driver.h16
-rw-r--r--Sensors/Activity/HardwareSimulator.h49
-rw-r--r--Sensors/Activity/SensorsTrace.h102
-rw-r--r--Sensors/Activity/client.cpp1021
-rw-r--r--Sensors/Activity/device.cpp835
-rw-r--r--Sensors/Activity/driver.cpp55
-rw-r--r--Sensors/Activity/hardwaresimulator.cpp276
13 files changed, 2835 insertions, 0 deletions
diff --git a/Sensors/Activity/Activity.def b/Sensors/Activity/Activity.def
new file mode 100644
index 00000000..1fe10e90
--- /dev/null
+++ b/Sensors/Activity/Activity.def
@@ -0,0 +1,6 @@
+; Activity.def : Declares the module parameters.
+
+LIBRARY Activity
+
+EXPORTS
+
diff --git a/Sensors/Activity/Activity.inx b/Sensors/Activity/Activity.inx
new file mode 100644
index 00000000..7f2558c1
--- /dev/null
+++ b/Sensors/Activity/Activity.inx
Binary files differ
diff --git a/Sensors/Activity/Activity.sln b/Sensors/Activity/Activity.sln
new file mode 100644
index 00000000..918419d9
--- /dev/null
+++ b/Sensors/Activity/Activity.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Activity", "Activity.vcxproj", "{9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Debug|Win32.Build.0 = Debug|Win32
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Release|Win32.ActiveCfg = Release|Win32
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Release|Win32.Build.0 = Release|Win32
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Debug|x64.ActiveCfg = Debug|x64
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Debug|x64.Build.0 = Debug|x64
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Release|x64.ActiveCfg = Release|x64
+ {9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Sensors/Activity/Activity.vcxproj b/Sensors/Activity/Activity.vcxproj
new file mode 100644
index 00000000..724803cd
--- /dev/null
+++ b/Sensors/Activity/Activity.vcxproj
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9C41A0A9-BEE7-4410-A604-2B97BDDE6A87}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{C9C93A11-59AB-4977-BE1F-E0AB103302E2}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="client.cpp; device.cpp; driver.cpp; hardwaresimulator.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppModuleName>Activity</WppModuleName>
+ <WppScanConfigurationData>sensorstrace.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include="Activity.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\Activity.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Activity</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Activity</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Activity</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Activity</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE;WPP_MACRO_USE_KM_VERSION_FOR_UM</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\sensors\1.1;$(SDK_INC_PATH)\sensors\1.1</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/Sensors/Activity/Activity.vcxproj.Filters b/Sensors/Activity/Activity.vcxproj.Filters
new file mode 100644
index 00000000..f32344d8
--- /dev/null
+++ b/Sensors/Activity/Activity.vcxproj.Filters
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{E51044F1-2844-4B85-9CB3-50C5574B73E6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{18DACA49-0487-4FC6-94D7-DE977A2AD8D5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{60868430-E51C-40B0-86F8-D5C119418603}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{B845F613-F2F8-4EDB-8CAE-574E38ABD746}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="client.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="hardwaresimulator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="Activity.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="Activity.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Sensors/Activity/Device.h b/Sensors/Activity/Device.h
new file mode 100644
index 00000000..64b2a5e4
--- /dev/null
+++ b/Sensors/Activity/Device.h
@@ -0,0 +1,200 @@
+// 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)
+
+#pragma once
+
+#include <windows.h>
+#include <wdf.h>
+#include <math.h>
+
+#include <SensorsTrace.h>
+#include <SensorsCx.h>
+#include <SensorsUtils.h>
+
+#define SENSOR_POOL_TAG_ACTIVITY 'itcA'
+static const ULONG Act_Max_State_Count = 7; // Currently there are 7 states
+static const ULONG Act_Default_MinDataInterval_Ms = 3000; // 3 seconds in milli seconds.
+static const ULONG Act_Default_SubscribedStates = ActivityState_Max - 1; // all activities
+static const BOOLEAN Act_Default_Streaming = FALSE; // no streaming
+static const USHORT Act_Default_ConfidenceThreshold_Percentage = 50; // 50% default confidence threshold
+static const ULONG Act_Default_HistoryInterval_Ms = 60000; // 1 minute in milli seconds
+static const ULONG Act_Default_MaxHistoryEntries = 60; // max of 60 history entries
+static const ULONG Act_Default_Power_uW = 2000; // micro watts
+static const ULONG Act_TimeoutForHistoryThread_Ms = 1000; // milli seconds
+static const USHORT Act_ConfidenceForHistoryEntries_Percentage = 70; // percentage
+static const ULONG Act_First_Most_Probable_State = 0;
+
+// Sensor Common Properties
+typedef enum
+{
+ SENSOR_PROPERTY_STATE = 0,
+ SENSOR_PROPERTY_MIN_INTERVAL,
+ SENSOR_PROPERTY_MAX_DATAFIELDSIZE,
+ SENSOR_PROPERTY_SENSOR_TYPE,
+ SENSOR_PROPERTY_SENSOR_POWER,
+ SENSOR_PROPERTY_SUPPORTEDACTIVITIES,
+ SENSOR_PROPERTY_MAX_HISTORYSIZE,
+ SENSOR_PROPERTY_HISTORY_INTERVAL,
+ SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE,
+ SENSOR_COMMON_PROPERTIES_COUNT
+} SENSOR_COMMON_PROPERTIES_INDEX;
+
+// Sensor Enumeration Properties
+typedef enum
+{
+ SENSOR_TYPE_GUID = 0,
+ SENSOR_MANUFACTURER,
+ SENSOR_MODEL,
+ SENSOR_PERSISTENT_UNIQUEID,
+ SENSOR_CATEGORY,
+ SENSOR_ISPRIMARY,
+
+ // These enumeration properties overlap with a subset of the common properties,
+ // and facilitate discovery without opening a sensor
+ SENSOR_MIN_INTERVAL,
+ SENSOR_POWER,
+ SENSOR_SUPPORTEDACTIVITIES,
+ SENSOR_MAX_HISTORYSIZE,
+ SENSOR_ENUMERATION_PROPERTIES_COUNT
+} SENSOR_ENUMERATION_PROPERTIES_INDEX;
+
+// Data-field Properties
+typedef enum
+{
+ SENSOR_RESOLUTION = 0,
+ SENSOR_MIN_RANGE,
+ SENSOR_MAX_RANGE,
+ SENSOR_DATA_FIELD_PROPERTY_COUNT
+} SENSOR_DATA_FIELD_PROPERTY_INDEX;
+
+// Supported Data Fields
+typedef enum
+{
+ ACTIVITY_DATA_TIMESTAMP = 0,
+ ACTIVITY_DATA_CURRENT_STATE,
+ ACTIVITY_DATA_CURRENT_CONFIDENCE,
+ ACTIVITY_DATA_COUNT
+} ACTIVITY_DATA_INDEX;
+
+// Data Thresholds
+typedef enum
+{
+ ACTIVITY_THRESHOLD_SUBSCRIBED_STATES = 0,
+ ACTIVITY_THRESHOLD_STREAMING,
+ ACTIVITY_THRESHOLD_CONFIDENCE,
+ ACTIVITY_THRESHOLD_COUNT
+} ACTIVITY_THRESHOLD_INDEX;
+
+typedef struct _ActivitySample
+{
+ FILETIME Timestamp;
+ ULONG Activity;
+ UINT16 Confidence;
+} ActivitySample, *PActivitySample;
+
+// History buffer
+typedef struct _HistoryCircularBuffer
+{
+ PActivitySample pData;
+ ULONG FirstElemIndex; // index of the oldest entry
+ ULONG LastElemIndex; // index of the latest entry
+ ULONG NumOfElems; // number of entries
+ ULONG BufferLength; // length of the buffer
+} HistoryCircularBuffer, *PHistoryCircularBuffer;
+
+typedef class _ActivityDevice
+{
+private:
+ // Simulator
+ WDFOBJECT m_SimulatorInstance;
+
+ // WDF
+ WDFDEVICE m_FxDevice;
+ SENSOROBJECT m_SensorInstance;
+ WDFWAITLOCK m_Lock;
+ WDFTIMER m_Timer;
+ WDFWAITLOCK m_HistoryLock;
+ WDFTIMER m_HistoryTimer;
+
+ // Sensor operation
+ BOOLEAN m_PoweredOn;
+ BOOLEAN m_Started;
+ ULONG m_Interval;
+ BOOLEAN m_FirstSample;
+
+ // History operation
+ HistoryCircularBuffer m_History;
+ BOOLEAN m_HistoryStarted;
+ ULONG m_HistoryIntervalInMs;
+ ULONG m_HistorySizeInRecords;
+ ULONG m_HistoryMarshalledRecordSize;
+ ULONG m_HistoryPowerInuW;
+ HANDLE m_hThread;
+ HANDLE m_ExitEvent;
+ BOOLEAN m_HistoryRetrievalStarted;
+ PSENSOR_COLLECTION_LIST m_ClientHistoryBuffer;
+ ULONG m_ClientHistoryBufferSize;
+
+ // Sensor Specific Properties
+ PSENSOR_COLLECTION_LIST m_pEnumerationProperties;
+ PSENSOR_COLLECTION_LIST m_pProperties;
+ PSENSOR_PROPERTY_LIST m_pSupportedDataFields;
+ PSENSOR_COLLECTION_LIST m_pDataFieldProperties;
+ PSENSOR_COLLECTION_LIST m_pThresholds;
+ PSENSOR_COLLECTION_LIST m_pLastSample;
+ PSENSOR_COLLECTION_LIST m_pFilteredSample;
+
+public:
+ // WDF callbacks
+ static EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
+ static EVT_WDF_DEVICE_PREPARE_HARDWARE OnPrepareHardware;
+ static EVT_WDF_DEVICE_RELEASE_HARDWARE OnReleaseHardware;
+ static EVT_WDF_DEVICE_D0_ENTRY OnD0Entry;
+ static EVT_WDF_DEVICE_D0_EXIT OnD0Exit;
+ static EVT_WDF_TIMER OnTimerExpire;
+ static EVT_WDF_TIMER OnHistoryTimerExpire;
+
+ // CLX callbacks
+ static EVT_SENSOR_DRIVER_START_SENSOR OnStart;
+ static EVT_SENSOR_DRIVER_STOP_SENSOR OnStop;
+ static EVT_SENSOR_DRIVER_GET_SUPPORTED_DATA_FIELDS OnGetSupportedDataFields;
+ static EVT_SENSOR_DRIVER_GET_PROPERTIES OnGetProperties;
+ static EVT_SENSOR_DRIVER_GET_DATA_FIELD_PROPERTIES OnGetDataFieldProperties;
+ static EVT_SENSOR_DRIVER_GET_DATA_INTERVAL OnGetDataInterval;
+ static EVT_SENSOR_DRIVER_SET_DATA_INTERVAL OnSetDataInterval;
+ static EVT_SENSOR_DRIVER_GET_DATA_THRESHOLDS OnGetDataThresholds;
+ static EVT_SENSOR_DRIVER_SET_DATA_THRESHOLDS OnSetDataThresholds;
+ static EVT_SENSOR_DRIVER_DEVICE_IO_CONTROL OnIoControl;
+ static EVT_SENSOR_DRIVER_START_SENSOR_HISTORY OnStartHistory;
+ static EVT_SENSOR_DRIVER_STOP_SENSOR_HISTORY OnStopHistory;
+ static EVT_SENSOR_DRIVER_CLEAR_SENSOR_HISTORY OnClearHistory;
+ static EVT_SENSOR_DRIVER_START_HISTORY_RETRIEVAL OnStartHistoryRetrieval;
+ static EVT_SENSOR_DRIVER_CANCEL_HISTORY_RETRIEVAL OnCancelHistoryRetrieval;
+
+ // History retrieval
+ static ULONG WINAPI HistoryRetrievalThread(_In_ LPVOID lpParam);
+
+private:
+ NTSTATUS Initialize(_In_ WDFDEVICE Device, _In_ SENSOROBJECT SensorObj);
+ NTSTATUS InitializeSupportedDataFields();
+ NTSTATUS InitializeSensorProperties();
+ NTSTATUS InitializeEnumerationProperties();
+ NTSTATUS InitializeDataFieldProperties();
+ NTSTATUS GetData();
+ _Requires_lock_held_(m_HistoryLock)
+ NTSTATUS AddDataElementToHistoryBuffer(_In_ PActivitySample pData);
+ _Requires_lock_held_(m_HistoryLock)
+ NTSTATUS RemoveDataElementFromHistoryBuffer(_Out_ PActivitySample pData);
+ _Requires_lock_held_(m_HistoryLock)
+ NTSTATUS ClearHistoryBuffer();
+} ActivityDevice, *PActivityDevice;
+
+//
+// Set up accessor function to retrieve device context
+//
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ActivityDevice, GetActivityContextFromSensorInstance); \ No newline at end of file
diff --git a/Sensors/Activity/Driver.h b/Sensors/Activity/Driver.h
new file mode 100644
index 00000000..6c1611c5
--- /dev/null
+++ b/Sensors/Activity/Driver.h
@@ -0,0 +1,16 @@
+// Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+// Abstract:
+// This module contains the implementation of entry and exit point of activity sample driver.
+//
+// Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#pragma once
+
+WDF_EXTERN_C_START
+
+DRIVER_INITIALIZE DriverEntry;
+EVT_WDF_DRIVER_UNLOAD OnDriverUnload;
+
+WDF_EXTERN_C_END \ No newline at end of file
diff --git a/Sensors/Activity/HardwareSimulator.h b/Sensors/Activity/HardwareSimulator.h
new file mode 100644
index 00000000..c61325f1
--- /dev/null
+++ b/Sensors/Activity/HardwareSimulator.h
@@ -0,0 +1,49 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved
+//
+//Abstract:
+// This module contains the type definitions for the activity sample driver hardware simulator.
+//
+//Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#pragma once
+
+#include "Device.h"
+
+typedef enum SIMULATOR_STATE
+{
+ SimulatorState_NotInitialized = 0,
+ SimulatorState_Initialized,
+ SimulatorState_Started
+} SIMULATOR_STATE;
+
+typedef class HardwareSimulator
+{
+private:
+ WDFTIMER m_Timer;
+ ULONG m_Index;
+ WDFWAITLOCK m_Lock;
+ SIMULATOR_STATE m_State;
+
+public:
+ HardwareSimulator();
+ ~HardwareSimulator();
+
+ // WDF callbacks
+ static EVT_WDF_TIMER OnTimerExpire;
+
+ static NTSTATUS Initialize(_In_ WDFDEVICE device, _Out_ WDFOBJECT *pSimulatorInstance);
+ VOID Deinitialize();
+ VOID Start();
+ VOID Stop();
+ NTSTATUS GetSample(_Inout_ PSENSOR_COLLECTION_LIST pSample);
+ NTSTATUS GetSample(_Out_ PActivitySample pSample);
+
+private:
+ NTSTATUS InitializeInternal(_In_ WDFOBJECT simulatorInstance);
+
+} HardwareSimulator, *PHardwareSimulator;
+
+
+// Set up accessor function to retrieve device context
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HardwareSimulator, GetHardwareSimulatorContextFromInstance);
diff --git a/Sensors/Activity/SensorsTrace.h b/Sensors/Activity/SensorsTrace.h
new file mode 100644
index 00000000..f6239fd7
--- /dev/null
+++ b/Sensors/Activity/SensorsTrace.h
@@ -0,0 +1,102 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved
+//
+//Abstract:
+//
+// Header file for the debug tracing related function defintions and macros.
+//
+//Environment:
+//
+// User mode
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Define the tracing flags.
+//
+// Tracing GUID - B6E7F50C-8F25-445E-8B39-D05802A53EB9
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ ActivityTraceGuid, (B6E7F50C,8F25,445E,8B39,D05802A53EB9), \
+ WPP_DEFINE_BIT(EntryExit) \
+ WPP_DEFINE_BIT(DataFlow) \
+ WPP_DEFINE_BIT(Verbose) \
+ WPP_DEFINE_BIT(Information) \
+ WPP_DEFINE_BIT(Warning) \
+ WPP_DEFINE_BIT(Error) \
+ WPP_DEFINE_BIT(Fatal) \
+ WPP_DEFINE_BIT(DriverStatus) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) (WPP_LEVEL_ENABLED(flag) && WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+#define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(level, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level)
+
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+//
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+//
+// FUNC TraceFatal{LEVEL=TRACE_LEVEL_FATAL,FLAGS=Fatal}(MSG,...);
+// FUNC TraceError{LEVEL=TRACE_LEVEL_ERROR,FLAGS=Error}(MSG,...);
+// FUNC TraceWarning{LEVEL=TRACE_LEVEL_WARNING,FLAGS=Warning}(MSG,...);
+// FUNC TraceInformation{LEVEL=TRACE_LEVEL_INFORMATION,FLAGS=Information}(MSG,...);
+// FUNC TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=Verbose}(MSG,...);
+// FUNC TracePerformance{PERF=DUMMY,LEVEL=TRACE_LEVEL_PERF}(FLAGS,MSG,...);
+//
+// FUNC TraceData{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=DataFlow}(MSG,...);
+//
+// FUNC TraceDriverStatus{LEVEL=TRACE_LEVEL_INFORMATION,FLAGS=DriverStatus}(MSG,...);
+//
+// end_wpp
+
+
+
+// SENSOR ------------------------------------------------------------------------------------------------
+
+// MACRO: SENSOR_FunctionEnter
+//
+// begin_wpp config
+// USEPREFIX (SENSOR_FunctionEnter, "%!STDPREFIX! SENSOR %!FUNC! FunctionEnter");
+// FUNC SENSOR_FunctionEnter{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=EntryExit}(...);
+// end_wpp
+
+
+// MACRO: SENSOR_FunctionExit
+//
+// begin_wpp config
+// USEPREFIX (SENSOR_FunctionExit, "%!STDPREFIX! SENSOR %!FUNC! FunctionExit: %!STATUS!", __status);
+// FUNC SENSOR_FunctionExit{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=EntryExit}(SENSOREXIT);
+// end_wpp
+#define WPP_LEVEL_FLAGS_SENSOREXIT_ENABLED(LEVEL, FLAGS, status) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS)
+#define WPP_LEVEL_FLAGS_SENSOREXIT_LOGGER(LEVEL, FLAGS, status) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS)
+
+#define WPP_LEVEL_FLAGS_SENSOREXIT_PRE(LEVEL, FLAGS, status) { \
+ NTSTATUS __status = status;
+#define WPP_LEVEL_FLAGS_SENSOREXIT_POST(LEVEL, FLAGS, status) /*TraceMessage()*/; \
+ }
+
+
+
+// WPP Recorder -------------------------------------------------------------------------------------------
+//
+// The following two macros are required to enable WPP Recorder functionality for clients of the Sensor Class Extension
+//
+#define WPP_RECORDER_LEVEL_FLAGS_SENSOREXIT_FILTER(LEVEL, FLAGS, status) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)
+#define WPP_RECORDER_LEVEL_FLAGS_SENSOREXIT_ARGS(LEVEL, FLAGS, status) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/Sensors/Activity/client.cpp b/Sensors/Activity/client.cpp
new file mode 100644
index 00000000..ca4c5bc2
--- /dev/null
+++ b/Sensors/Activity/client.cpp
@@ -0,0 +1,1021 @@
+// Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+// Abstract:
+// This module contains the implementation of driver callback function from clx to activity detection driver.
+//
+// Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "HardwareSimulator.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 ActivityDevice::GetData()
+{
+ BOOLEAN dataReady = FALSE;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (NULL != m_SimulatorInstance)
+ {
+ // Use simulator to get m_pFiltered Sample
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
+ if (nullptr != pSimulator)
+ {
+ status = pSimulator->GetSample(m_pFilteredSample);
+ }
+ else
+ {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ if (NT_SUCCESS(status))
+ {
+ status = CollectionsListSortSubscribedActivitiesByConfidence(m_pThresholds, m_pFilteredSample);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! CollectionsListSortSubscribedActivitiesByConfidence failed! %!STATUS!", status);
+ }
+ else
+ {
+ // new sample?
+ if (FALSE != m_FirstSample)
+ {
+ dataReady = TRUE;
+ }
+ else
+ {
+ dataReady = EvaluateActivityThresholds(m_pFilteredSample, m_pLastSample, m_pThresholds);
+ }
+ }
+ }
+
+ if (FALSE != dataReady)
+ {
+ // update last sample
+ FILETIME TimeStamp = {};
+ memcpy_s(m_pLastSample, m_pFilteredSample->AllocatedSizeInBytes, m_pFilteredSample, m_pFilteredSample->AllocatedSizeInBytes);
+ GetSystemTimePreciseAsFileTime(&TimeStamp);
+ InitPropVariantFromFileTime(&TimeStamp, &(m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Value));
+
+ // push to clx
+ SensorsCxSensorDataReady(m_SensorInstance, m_pLastSample);
+ m_FirstSample = FALSE;
+ }
+ else
+ {
+ status = STATUS_DATA_NOT_ACCEPTED;
+ TraceInformation("ACT %!FUNC! Data did NOT meet the threshold");
+ }
+
+ SENSOR_FunctionExit(status);
+ 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 ActivityDevice::OnTimerExpire(_In_ WDFTIMER timer)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(timer));
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Get data and push to clx
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ status = pDevice->GetData();
+ if (!NT_SUCCESS(status) && STATUS_DATA_NOT_ACCEPTED != status)
+ {
+ TraceError("ACT %!FUNC! GetAccData Failed %!STATUS!", status);
+ }
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ // Schedule next wake up time
+ if (Act_Default_MinDataInterval_Ms <= pDevice->m_Interval &&
+ FALSE != pDevice->m_PoweredOn &&
+ FALSE != pDevice->m_Started)
+ {
+ WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval));
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+}
+
+// Called by Sensor CLX to begin continously sampling the sensor.
+NTSTATUS ActivityDevice::OnStart(_In_ SENSOROBJECT sensorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ if (FALSE == pDevice->m_PoweredOn)
+ {
+ status = STATUS_DEVICE_NOT_READY;
+ TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status);
+ }
+ else
+ {
+ // Start simulation
+ if (NULL != pDevice->m_SimulatorInstance)
+ {
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr != pSimulator)
+ {
+ pSimulator->Start();
+ }
+ }
+
+ // Start sensing
+ pDevice->m_FirstSample = TRUE;
+ pDevice->m_Started = TRUE;
+ InitPropVariantFromUInt32(SensorState_Active, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+ WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Act_Default_MinDataInterval_Ms));
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to stop continously sampling the sensor.
+NTSTATUS ActivityDevice::OnStop(_In_ SENSOROBJECT sensorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Stop sensing
+ pDevice->m_Started = FALSE;
+ WdfTimerStop(pDevice->m_Timer, TRUE);
+ InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ // Stop simulation
+ if (NULL != pDevice->m_SimulatorInstance)
+ {
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr != pSimulator)
+ {
+ pSimulator->Stop();
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is called by history retrieval thread to remove an entry from the history buffer.
+// Note this function must be called under lock
+_Requires_lock_held_(m_HistoryLock)
+NTSTATUS ActivityDevice::RemoveDataElementFromHistoryBuffer(_Out_ PActivitySample pData)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (nullptr == pData)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! NULL ptr passed in %!STATUS!", status);
+ }
+ else
+ {
+ if (0 == m_History.NumOfElems)
+ {
+ // buffer empty
+ status = STATUS_NO_MORE_ENTRIES;
+ }
+ else
+ {
+ // Remove the oldest element from the circular buffer
+ *pData = m_History.pData[m_History.FirstElemIndex];
+ m_History.FirstElemIndex++;
+ m_History.FirstElemIndex %= m_History.BufferLength;
+ m_History.NumOfElems--;
+ if (0 == m_History.NumOfElems)
+ {
+ // Buffer Empty. 'LastElemIndex' should be same as 'FirstElemIndex'
+ m_History.LastElemIndex = m_History.FirstElemIndex;
+ }
+ }
+ }
+
+ return status;
+}
+
+// This routine is called by worker thread to add an entry to the history buffer.
+// Note this function must be called under lock
+_Requires_lock_held_(m_HistoryLock)
+NTSTATUS ActivityDevice::AddDataElementToHistoryBuffer(_In_ PActivitySample pData)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (nullptr == pData)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ if (0 == m_History.NumOfElems)
+ {
+ // buffer empty
+ m_History.NumOfElems++;
+ }
+ else if (m_History.BufferLength > m_History.NumOfElems)
+ {
+ // buffer not full yet. Increment the index of the last element
+ m_History.LastElemIndex++;
+ m_History.LastElemIndex %= m_History.BufferLength;
+ m_History.NumOfElems++;
+ }
+ else if (m_History.BufferLength == m_History.NumOfElems)
+ {
+ // buffer full. Over-write the oldest element
+ m_History.FirstElemIndex++;
+ m_History.FirstElemIndex %= m_History.BufferLength;
+ m_History.LastElemIndex++;
+ m_History.LastElemIndex %= m_History.BufferLength;
+ }
+ memcpy_s(&(m_History.pData[m_History.LastElemIndex]),
+ sizeof(m_History.pData[m_History.LastElemIndex]),
+ pData,
+ sizeof(*pData));
+ }
+
+ return status;
+}
+
+// This routine is for clearing the history buffer. Note this function must be called under lock.
+_Requires_lock_held_(m_HistoryLock)
+NTSTATUS ActivityDevice::ClearHistoryBuffer()
+{
+ m_History.FirstElemIndex = 0;
+ m_History.LastElemIndex = 0;
+ m_History.NumOfElems = 0;
+ RtlZeroMemory(m_History.pData, (m_History.BufferLength*sizeof(ActivitySample)));
+ return STATUS_SUCCESS;
+}
+
+// This callback is called when interval wait time has expired and driver is ready
+// to collect new sample. The callback stores activity data in history buffer,
+// and schedules next wake up time.
+VOID ActivityDevice::OnHistoryTimerExpire(_In_ WDFTIMER historyTimer)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(historyTimer));
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ ActivitySample data = {};
+ if (NULL != pDevice->m_SimulatorInstance)
+ {
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr != pSimulator)
+ {
+ status = pSimulator->GetSample(&data);
+ }
+ else
+ {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ GetSystemTimePreciseAsFileTime(&(data.Timestamp));
+
+ if (NT_SUCCESS(status))
+ {
+ // Add data to the buffer
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ status = pDevice->AddDataElementToHistoryBuffer(&data);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! AddDataElementToHistoryBuffer Failed %!STATUS!", status);
+ }
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ }
+
+ // Schedule next wake up time
+ if (FALSE != pDevice->m_HistoryStarted)
+ {
+ WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs));
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+}
+
+// Called by Sensor CLX to begin keeping history
+NTSTATUS ActivityDevice::OnStartHistory(_In_ SENSOROBJECT sensorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else if (0 == pDevice->m_HistorySizeInRecords)
+ {
+ status = STATUS_NOT_SUPPORTED;
+ TraceError("ACT %!FUNC! Sensor does not support History");
+ }
+ else if (FALSE == pDevice->m_PoweredOn)
+ {
+ status = STATUS_DEVICE_NOT_READY;
+ TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status);
+ }
+ else
+ {
+ // Start keeping history
+ pDevice->m_HistoryStarted = TRUE;
+ WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs));
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to stop keeping history.
+NTSTATUS ActivityDevice::OnStopHistory(_In_ SENSOROBJECT sensorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Stop keeping history
+ pDevice->m_HistoryStarted = FALSE;
+ WdfTimerStop(pDevice->m_HistoryTimer, TRUE);
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to clear all history stored in the sensor.
+NTSTATUS ActivityDevice::OnClearHistory(_In_ SENSOROBJECT sensorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ status = pDevice->ClearHistoryBuffer();
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! ClearHistoryBuffer Failed %!STATUS!", status);
+ }
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to start retrieving history.
+NTSTATUS ActivityDevice::OnStartHistoryRetrieval(
+ _In_ SENSOROBJECT sensorInstance,
+ _Inout_updates_bytes_(historySizeInBytes) PSENSOR_COLLECTION_LIST pHistoryBuffer,
+ _In_ ULONG historySizeInBytes
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // 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_HistoryLock, NULL);
+ BOOLEAN IsStarted = pDevice->m_HistoryRetrievalStarted;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+
+ if (FALSE != IsStarted)
+ {
+ status = STATUS_DEVICE_BUSY;
+ TraceError("ACT %!FUNC! StartHistoryRetrieval called again before the previous call"
+ "finishes retrieving history %!STATUS!", status);
+ }
+ else
+ {
+ // 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;
+ }
+
+ // check that the buffer is not null
+ if (NULL == pHistoryBuffer)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! History buffer cannot be NULL. %!STATUS!", status);
+ }
+ else
+ {
+ // check that the buffer can hold at least one entry
+ if (historySizeInBytes < pDevice->m_HistoryMarshalledRecordSize)
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ TraceError("ACT %!FUNC! History buffer is too small to even fill one complete entry. %!STATUS!", status);
+ }
+ else
+ {
+ pDevice->m_ClientHistoryBuffer = pHistoryBuffer;
+ pDevice->m_ClientHistoryBufferSize = historySizeInBytes;
+
+ // Reset exit event
+ ResetEvent(pDevice->m_ExitEvent);
+
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+
+ // 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<PVOID>(sensorInstance), // pointer to variable to be passed
+ 0, // run immediately
+ NULL); // Thread ID
+ if (NULL == pDevice->m_hThread)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceError("ACT %!FUNC! CreateThread Failed %!STATUS!", status);
+ }
+ else
+ {
+ pDevice->m_HistoryRetrievalStarted = TRUE;
+ }
+
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+
+ if (nullptr != pDevice && !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 ActivityDevice::OnCancelHistoryRetrieval(_In_ SENSOROBJECT sensorInstance, _Out_ PULONG pBytesWritten)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ *pBytesWritten = 0;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Check if history retrieval operation is in progress
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ BOOLEAN IsStarted = pDevice->m_HistoryRetrievalStarted;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+
+ if (FALSE == IsStarted)
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ TraceError("ACT %!FUNC! History retrieval is not in progress %!STATUS!", status);
+ }
+ else
+ {
+ // Signal the history retrieval thread to exit
+ SetEvent(pDevice->m_ExitEvent);
+
+ // Wait for the history retrieval thread to finish writing the entry since no partial entries are allowed.
+ DWORD result = WaitForSingleObjectEx(pDevice->m_hThread, Act_TimeoutForHistoryThread_Ms, FALSE);
+ if (WAIT_OBJECT_0 != result)
+ {
+ // continue to mark history retrieval stop
+ status = NTSTATUS_FROM_WIN32(result);
+ TraceError("ACT %!FUNC! WaitForSingleObjectEx failed! %!STATUS!", status);
+ }
+
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ *pBytesWritten = CollectionsListGetMarshalledSizeWithoutSerialization(pDevice->m_ClientHistoryBuffer);
+ pDevice->m_HistoryRetrievalStarted = FALSE;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Created on calling StartHistoryRetrieval function.
+ULONG WINAPI ActivityDevice::HistoryRetrievalThread(_In_ LPVOID lpParam)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOLEAN exitSignal = FALSE;
+ UINT existingCount = 0;
+ UINT fillableCount = 0;
+
+ SENSOROBJECT sensorInstance = reinterpret_cast<SENSOROBJECT>(lpParam);
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice ||
+ NULL == pDevice->m_ClientHistoryBuffer ||
+ pDevice->m_HistoryMarshalledRecordSize > pDevice->m_ClientHistoryBufferSize)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Capture the number of entries in the driver's history buffer at this moment
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ existingCount = pDevice->m_History.NumOfElems;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+
+ // How many entries can the client supplied buffer hold
+ fillableCount = (pDevice->m_ClientHistoryBufferSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) / (pDevice->m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE);
+
+ // Find the minimum of the number of entries in the driver's history buffer and
+ // the number of entries that can be held by the client supplied buffer
+ UINT count = min(existingCount, fillableCount);
+
+ // All entries into the client's buffer must be complete i.e. no partial entries are allowed.
+ // Check whether the exit event is signaled before looping through each time to retrieve an entry from the driver's history buffer.
+ // Each history record will only contain first entry of the most probable state.
+ for (UINT index = 0; index < count; index++)
+ {
+ ActivitySample data = {};
+ UINT elementIndex = ACTIVITY_DATA_COUNT * index;
+ if (WAIT_OBJECT_0 == WaitForSingleObject(pDevice->m_ExitEvent, 0))
+ {
+ exitSignal = TRUE;
+ break;
+ }
+
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ if (!NT_SUCCESS(pDevice->RemoveDataElementFromHistoryBuffer(&data)))
+ {
+ // Only return error if there is no more entry which is not an error. Therefore no need to set status.
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ break;
+ }
+
+ elementIndex = (index * ACTIVITY_DATA_COUNT) + ACTIVITY_DATA_TIMESTAMP;
+ pDevice->m_ClientHistoryBuffer->List[elementIndex].Key = PKEY_SensorData_Timestamp;
+ InitPropVariantFromFileTime(&(data.Timestamp), &(pDevice->m_ClientHistoryBuffer->List[elementIndex].Value));
+
+ elementIndex = (index * ACTIVITY_DATA_COUNT) + ACTIVITY_DATA_CURRENT_STATE;
+ pDevice->m_ClientHistoryBuffer->List[elementIndex].Key = PKEY_SensorData_CurrentActivityState;
+ InitPropVariantFromUInt32(data.Activity, &(pDevice->m_ClientHistoryBuffer->List[elementIndex].Value));
+
+ elementIndex = (index * ACTIVITY_DATA_COUNT) + ACTIVITY_DATA_CURRENT_CONFIDENCE;
+ pDevice->m_ClientHistoryBuffer->List[elementIndex].Key = PKEY_SensorData_CurrentActivityStateConfidence_Percentage;
+ InitPropVariantFromUInt16(data.Confidence, &(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 = (index + 1) * ACTIVITY_DATA_COUNT;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+ }
+ }
+
+ if (FALSE == exitSignal)
+ {
+ if (fillableCount < existingCount)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (0 == existingCount)
+ {
+ status = STATUS_NO_MORE_ENTRIES;
+ }
+ // call completed callback only if retrieval was not canceled
+ SensorsCxSensorHistoryRetrievalCompleted(pDevice->m_SensorInstance, CollectionsListGetMarshalledSizeWithoutSerialization(pDevice->m_ClientHistoryBuffer), status);
+ }
+
+ WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
+ pDevice->m_HistoryRetrievalStarted = FALSE;
+ WdfWaitLockRelease(pDevice->m_HistoryLock);
+
+ return ERROR_SUCCESS;
+}
+
+// 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 ActivityDevice::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
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Invalid parameters! %!STATUS!", status);
+ }
+ else
+ {
+ if (nullptr == pFields)
+ {
+ // Just return size
+ *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ else
+ {
+ if (pFields->AllocatedSizeInBytes < pDevice->m_pSupportedDataFields->AllocatedSizeInBytes)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! Buffer is too small. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Fill out data
+ status = PropertiesListCopy(pFields, pDevice->m_pSupportedDataFields);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! PropertiesListCopy failed %!STATUS!", status);
+ }
+ else
+ {
+ *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ }
+ }
+ }
+
+ 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 ActivityDevice::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
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Invalid parameters! %!STATUS!", status);
+ }
+ else
+ {
+ if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pProperties))
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! Buffer is too small. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Fill out all data
+ status = CollectionsListCopyAndMarshall(pProperties, pDevice->m_pProperties);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+ }
+ }
+ }
+
+ 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 ActivityDevice::OnGetDataFieldProperties(
+ _In_ SENSOROBJECT sensorInstance, // sensor device object
+ _In_ const PROPERTYKEY *pDataField, // 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
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || nullptr == pSize || nullptr == pDataField)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Invalid parameters! %!STATUS!", status);
+ }
+ else
+ {
+ if (*pDataField == PKEY_SensorData_CurrentActivityStateConfidence_Percentage)
+ {
+ if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties))
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! Buffer is too small. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Fill out all data
+ status = CollectionsListCopyAndMarshall(pProperties, pDevice->m_pDataFieldProperties);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pDataFieldProperties);
+ }
+ }
+ }
+ }
+ else
+ {
+ status = STATUS_NOT_SUPPORTED;
+ TraceError("ACT %!FUNC! AccFake does NOT have properties for this data field. Failed %!STATUS!", status);
+ }
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ *pSize = 0;
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to get sampling rate of the sensor.
+NTSTATUS ActivityDevice::OnGetDataInterval(_In_ SENSOROBJECT sensorInstance, _Out_ PULONG pDataRateMs)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ *pDataRateMs = 0;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || nullptr == pDataRateMs)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
+ }
+ else
+ {
+ *pDataRateMs = pDevice->m_Interval;
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to set sampling rate of the sensor.
+NTSTATUS ActivityDevice::OnSetDataInterval(_In_ SENSOROBJECT sensorInstance, _In_ ULONG dataRateMs)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || Act_Default_MinDataInterval_Ms > dataRateMs)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Invalid parameters! %!STATUS!", status);
+ }
+ else
+ {
+ 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(Act_Default_MinDataInterval_Ms));
+ }
+ }
+
+ 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 ActivityDevice::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
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Invalid parameters! %!STATUS!", status);
+ }
+ else
+ {
+ if (nullptr == pThresholds)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pThresholds);
+ }
+ else
+ {
+ if (pThresholds->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pDevice->m_pThresholds))
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! Buffer is too small. Failed %!STATUS!", status);
+ }
+ else
+ {
+ // Fill out all data
+ status = CollectionsListCopyAndMarshall(pThresholds, pDevice->m_pThresholds);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pThresholds);
+ }
+ }
+ }
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ *pSize = 0;
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to set data thresholds.
+NTSTATUS ActivityDevice::OnSetDataThresholds(
+ _In_ SENSOROBJECT sensorInstance, // sensor device object
+ _In_ PSENSOR_COLLECTION_LIST pThresholds) // pointer to a list of sensor thresholds
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
+ if (nullptr == pDevice)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", sensorInstance, status);
+ }
+ else
+ {
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+
+ for (ULONG 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("ACT %!FUNC! ActivityFake does NOT have threshold for this data field. Failed %!STATUS!", status);
+ break;
+ }
+ }
+
+ WdfWaitLockRelease(pDevice->m_Lock);
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// Called by Sensor CLX to handle IOCTLs that clx does not support.
+NTSTATUS ActivityDevice::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
+{
+ SENSOR_FunctionEnter();
+
+ WdfRequestComplete(request, STATUS_NOT_SUPPORTED);
+
+ SENSOR_FunctionExit(STATUS_NOT_SUPPORTED);
+ return STATUS_NOT_SUPPORTED;
+}
diff --git a/Sensors/Activity/device.cpp b/Sensors/Activity/device.cpp
new file mode 100644
index 00000000..1b0339db
--- /dev/null
+++ b/Sensors/Activity/device.cpp
@@ -0,0 +1,835 @@
+// 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_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary;
+ InitPropVariantFromBoolean(FALSE,
+ &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].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
diff --git a/Sensors/Activity/driver.cpp b/Sensors/Activity/driver.cpp
new file mode 100644
index 00000000..b501f30a
--- /dev/null
+++ b/Sensors/Activity/driver.cpp
@@ -0,0 +1,55 @@
+// Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+// Abstract:
+// This module contains the implementation of entry and exit point of activity sample driver.
+//
+// Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "Driver.h"
+#include "Driver.tmh"
+
+NTSTATUS DriverEntry(
+ _In_ PDRIVER_OBJECT driverObject, // Pointer to the driver object created by the I/O manager
+ _In_ PUNICODE_STRING registryPath) // Pointer to the driver specific registry key
+{
+ WDF_DRIVER_CONFIG driverConfig;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // Initialize WPP Tracing
+ WPP_INIT_TRACING(driverObject, NULL);
+
+ SENSOR_FunctionEnter();
+
+ driverConfig.DriverPoolTag = SENSOR_POOL_TAG_ACTIVITY;
+
+ // Initialize the driver configuration structure.
+ WDF_DRIVER_CONFIG_INIT(&driverConfig, ActivityDevice::OnDeviceAdd);
+ driverConfig.EvtDriverUnload = OnDriverUnload;
+
+ // Create a framework driver object to represent our driver.
+ status = WdfDriverCreate(driverObject, registryPath, WDF_NO_OBJECT_ATTRIBUTES, &driverConfig, WDF_NO_HANDLE);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfDriverCreate failed: %!STATUS!", status);
+ }
+
+ SENSOR_FunctionExit(status);
+ return status;
+}
+
+// This routine is called when the driver unloads.
+VOID OnDriverUnload(_In_ WDFDRIVER driver)
+{
+ SENSOR_FunctionEnter();
+
+ SENSOR_FunctionExit(STATUS_SUCCESS);
+
+ // WPP_CLEANUP doesn't actually use the Driver parameter
+ // So we need to set it as unreferenced.
+ UNREFERENCED_PARAMETER(driver);
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject(driver));
+
+ return;
+} \ No newline at end of file
diff --git a/Sensors/Activity/hardwaresimulator.cpp b/Sensors/Activity/hardwaresimulator.cpp
new file mode 100644
index 00000000..29d9203b
--- /dev/null
+++ b/Sensors/Activity/hardwaresimulator.cpp
@@ -0,0 +1,276 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+// This module contains the implementation of the activity sample driver hardware simulator.
+//
+//Environment:
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "HardwareSimulator.h"
+#include "HardwareSimulator.tmh"
+
+static const ULONG SIMULATOR_HARDWARE_INTERVAL_SEC = 10;
+static const ULONG MAX_ACTIVITY_STATE_PER_SAMPLE = 4;
+
+// Simulated activity data
+const ActivitySample c_SimulatorData[][MAX_ACTIVITY_STATE_PER_SAMPLE] = {
+ // This is a 2D array. Each row is one activity sample. One activity sample consist one or more
+ // state and confidence pair.
+ { { {}, ActivityState_InVehicle, 40 }, { {}, ActivityState_Biking, 30 }, { {}, ActivityState_Walking, 20 }, { } }, // InVehicle 40%, Biking 30%, Walking 20%
+ { { {}, ActivityState_Biking, 45 }, { {}, ActivityState_InVehicle, 40 }, { {}, ActivityState_Fidgeting, 30 }, { {}, ActivityState_Walking, 20 } }, // Biking 45%, InVehicle 40% Fidgeting 30%, Walking 20%
+ { { {}, ActivityState_Idle, 80 }, { {}, ActivityState_InVehicle, 60 }, { {}, ActivityState_Biking, 35 }, { {}, ActivityState_Walking, 20 } }, // Idle 80%, InVehicle 60%, Biking 35%, Walking 20%
+ { { {}, ActivityState_InVehicle, 75 }, { {}, ActivityState_Idle, 55 }, { {}, ActivityState_Walking, 18 }, { } }, // InVehicle 75%, Idle 55%, Walking 18%
+ { { {}, ActivityState_Biking, 90 }, { }, { }, { } }, // Biking 90%
+};
+
+HardwareSimulator::HardwareSimulator() :
+ m_Index(0),
+ m_Lock(NULL),
+ m_State(SimulatorState_NotInitialized),
+ m_Timer(NULL)
+{
+}
+
+HardwareSimulator::~HardwareSimulator()
+{
+}
+
+// This static routine performs simulator initialization. The routine creates a
+// timer object that periodically updates the m_Index location
+NTSTATUS HardwareSimulator::Initialize(
+ _In_ WDFDEVICE device, // WDF device representing the sensor
+ _Out_ WDFOBJECT *pSimulatorInstance) // Instance of the WDF object for the simulator
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ *pSimulatorInstance = NULL;
+
+ // Create WDFOBJECT for the hardware simulator
+ WDF_OBJECT_ATTRIBUTES hardwareSimulatorAttributes = {};
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&hardwareSimulatorAttributes, HardwareSimulator);
+ hardwareSimulatorAttributes.ParentObject = device;
+
+ status = WdfObjectCreate(&hardwareSimulatorAttributes, pSimulatorInstance);
+ if (!NT_SUCCESS(status))
+ {
+ TraceError("ACT %!FUNC! WdfObjectCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(*pSimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ status = pSimulator->InitializeInternal(*pSimulatorInstance);
+ }
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+}
+
+
+// Internal routine to perform simulator initialization
+NTSTATUS HardwareSimulator::InitializeInternal(_In_ WDFOBJECT SimulatorInstance)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Only initialize the simulator if it is in the "not initialized" state
+ if (SimulatorState_NotInitialized == m_State)
+ {
+ // Create sample Lock
+ status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
+ if (!NT_SUCCESS(status))
+ {
+ m_Lock = NULL;
+ TraceError("ACT %!FUNC! WdfWaitLockCreate for m_Lock failed %!STATUS!", status);
+ }
+ else
+ {
+ WDF_OBJECT_ATTRIBUTES timerAttributes = {};
+ WDF_TIMER_CONFIG timerConfig = {};
+
+ // Create a timer object for simulation updates
+ WDF_TIMER_CONFIG_INIT(&timerConfig, HardwareSimulator::OnTimerExpire);
+ WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);
+ timerAttributes.ParentObject = SimulatorInstance;
+ timerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_Timer);
+ if (!NT_SUCCESS(status))
+ {
+ m_Timer = NULL;
+ TraceError("ACT %!FUNC! WdfTimerCreate failed %!STATUS!", status);
+ }
+ else
+ {
+ // Set the simulator state to "initialized"
+ m_State = SimulatorState_Initialized;
+ }
+ }
+ }
+
+ if (!NT_SUCCESS(status) && NULL != m_Lock)
+ {
+ WdfObjectDelete(m_Lock);
+ m_Lock = NULL;
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+}
+
+
+// This routine perform a simulator cleanup
+VOID HardwareSimulator::Deinitialize()
+{
+ if (SimulatorState_Started == m_State)
+ {
+ Stop();
+ }
+
+ // Delete lock. m_Timer will be deleted when the wdfobject is deleted
+ if (NULL != m_Lock)
+ {
+ WdfObjectDelete(m_Lock);
+ m_Lock = NULL;
+ }
+
+ // Set the simulator state to "not initialized"
+ m_State = SimulatorState_NotInitialized;
+}
+
+
+// This routine starts the simulator
+VOID HardwareSimulator::Start()
+{
+ SENSOR_FunctionEnter();
+
+ if (SimulatorState_Initialized == m_State)
+ {
+ WdfTimerStart(m_Timer, WDF_REL_TIMEOUT_IN_SEC(SIMULATOR_HARDWARE_INTERVAL_SEC));
+ m_State = SimulatorState_Started;
+ }
+
+ SENSOR_FunctionExit(STATUS_SUCCESS);
+}
+
+
+// This routine stops the simulator
+VOID HardwareSimulator::Stop()
+{
+ SENSOR_FunctionEnter();
+
+ if (SimulatorState_Started == m_State)
+ {
+ WdfTimerStop(m_Timer, TRUE);
+ m_State = SimulatorState_Initialized;
+ }
+
+ SENSOR_FunctionExit(STATUS_SUCCESS);
+}
+
+
+// This callback is called when the simulator wait time has expired and the simulator
+// is ready to switch to the next sample. The callback updates the sample index and
+// schedules the next wake up time.
+VOID HardwareSimulator::OnTimerExpire(_In_ WDFTIMER timer)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(WdfTimerGetParentObject(timer));
+ if (nullptr == pSimulator)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACT %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", status);
+ }
+ else
+ {
+ // Increment the sample index, roll over if the index reach the end of the array
+ WdfWaitLockAcquire(pSimulator->m_Lock, NULL);
+ pSimulator->m_Index++;
+ pSimulator->m_Index = pSimulator->m_Index % ARRAYSIZE(c_SimulatorData);
+ WdfWaitLockRelease(pSimulator->m_Lock);
+ WdfTimerStart(pSimulator->m_Timer, WDF_REL_TIMEOUT_IN_SEC(SIMULATOR_HARDWARE_INTERVAL_SEC));
+ }
+
+ SENSOR_FunctionExit(status);
+}
+
+
+// This routine returns the current sample collection from the driver at the current m_Index location
+NTSTATUS HardwareSimulator::GetSample(_Inout_ PSENSOR_COLLECTION_LIST pSample)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSample ||
+ SENSOR_COLLECTION_LIST_SIZE(MAX_ACTIVITY_STATE_PER_SAMPLE * 2 + 1) > pSample->AllocatedSizeInBytes)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sample parameter is null");
+ }
+ else
+ {
+ pSample->Count = 1;
+
+ WdfWaitLockAcquire(m_Lock, NULL);
+ if (ARRAYSIZE(c_SimulatorData) > m_Index)
+ {
+ for (ULONG count = 0, index = 1;
+ count < MAX_ACTIVITY_STATE_PER_SAMPLE && NULL != c_SimulatorData[m_Index][count].Activity;
+ count++, index += 2)
+ {
+ pSample->List[index].Key = PKEY_SensorData_CurrentActivityState;
+ InitPropVariantFromUInt32(c_SimulatorData[m_Index][count].Activity, &(pSample->List[index].Value));
+
+ pSample->List[index + 1].Key = PKEY_SensorData_CurrentActivityStateConfidence_Percentage;
+ InitPropVariantFromUInt16(c_SimulatorData[m_Index][count].Confidence, &(pSample->List[index + 1].Value));
+
+ pSample->Count += 2;
+ }
+ }
+ WdfWaitLockRelease(m_Lock);
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+}
+
+// This routine returns the current most probable sample from the driver at the current m_Index location
+NTSTATUS HardwareSimulator::GetSample(_Out_ PActivitySample pSample)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSample)
+ {
+ status = STATUS_INVALID_PARAMETER;
+ TraceError("ACT %!FUNC! Sample parameter is null");
+ }
+ else
+ {
+ WdfWaitLockAcquire(m_Lock, NULL);
+ *pSample = c_SimulatorData[m_Index][0];
+ WdfWaitLockRelease(m_Lock);
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+} \ No newline at end of file