summaryrefslogtreecommitdiff
path: root/Sensors/SimpleDeviceOrientationSensor
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/SimpleDeviceOrientationSensor
parentda21c8784c83c5fd614f3030323e229d6a5fb10e (diff)
Fix cases
Diffstat (limited to 'Sensors/SimpleDeviceOrientationSensor')
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/Device.h137
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/Driver.h19
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/HardwareSimulator.h58
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SensorsTrace.h100
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.def6
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.inxbin0 -> 6446 bytes
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.sln28
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj204
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj.Filters43
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/client.cpp595
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/device.cpp572
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/driver.cpp75
-rw-r--r--Sensors/SimpleDeviceOrientationSensor/hardwaresimulator.cpp248
13 files changed, 2085 insertions, 0 deletions
diff --git a/Sensors/SimpleDeviceOrientationSensor/Device.h b/Sensors/SimpleDeviceOrientationSensor/Device.h
new file mode 100644
index 00000000..b75b5ceb
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/Device.h
@@ -0,0 +1,137 @@
+//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>
+
+#include "HardwareSimulator.h"
+
+#include <windows.devices.sensors.h>
+
+#define SENSORV2_POOL_TAG_SDO 'sodS'
+
+#define Sdo_Mininum_DataInterval (20) // 50Hz
+#define Sdo_Default_DataInterval (200) // 5Hz
+
+//
+// Sensor Common Properties
+//
+typedef enum
+{
+ SENSOR_PROPERTY_STATE = 0,
+ SENSOR_PROPERTY_MIN_INTERVAL,
+ SENSOR_PROPERTY_MAX_DATAFIELDSIZE,
+ SENSOR_PROPERTY_SENSOR_TYPE,
+ SENSOR_PROPERTIES_COUNT
+} SENSOR_COMMON_PROPERTIES_INDEX;
+
+//
+// Sensor Enumeration Properties
+//
+typedef enum
+{
+ SENSOR_TYPE_GUID = 0,
+ SENSOR_MANUFACTURER,
+ SENSOR_MODEL,
+ SENSOR_PERSISTENT_UNIQUEID,
+ SENSOR_ISPRIMARY,
+ SENSOR_ENUMERATION_PROPERTIES_COUNT
+} SENSOR_ENUMERATION_PROPERTIES_INDEX;
+
+//
+// Supported Data Fields
+//
+typedef enum
+{
+ SDO_DATA_TIMESTAMP = 0,
+ SDO_DATA_SIMPLEDEVICEORIENTATION,
+ SDO_DATA_COUNT
+} SDO_DATA_INDEX;
+
+
+//
+// Simple Device Orientation Driver Class
+//
+
+typedef class _SdoDevice
+{
+private:
+ // Simulator
+ WDFOBJECT m_SimulatorInstance;
+
+ // WDF
+ WDFDEVICE m_FxDevice;
+ SENSOROBJECT m_SensorInstance;
+ WDFWAITLOCK m_Lock;
+ WDFTIMER m_Timer;
+
+ // Sensor operation
+ BOOLEAN m_PoweredOn;
+ BOOLEAN m_Started;
+
+ // Sensor Specific Properties
+ PSENSOR_PROPERTY_LIST m_pSupportedDataFields;
+ PSENSOR_COLLECTION_LIST m_pEnumerationProperties;
+ PSENSOR_COLLECTION_LIST m_pProperties;
+ PSENSOR_COLLECTION_LIST m_pEmptyThreshold;
+
+ //
+ // SDO Operation ----------------------------------------------------
+ //
+
+ ULONG m_Interval;
+ BOOLEAN m_FirstSample;
+ ULONG m_StartTime;
+ ULONGLONG m_SampleCount;
+
+ PSENSOR_COLLECTION_LIST m_pData; // Sdo data that is going to push to clx
+ ABI::Windows::Devices::Sensors::SimpleOrientation m_LastSample;
+
+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;
+
+
+ // 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;
+
+private:
+
+ NTSTATUS Initialize(_In_ WDFDEVICE Device, _In_ SENSOROBJECT SensorObj);
+ NTSTATUS GetData();
+
+} SdoDevice, *PSdoDevice;
+
+//
+// Set up accessor function to retrieve device context
+//
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SdoDevice, GetSdoContextFromSensorInstance);
diff --git a/Sensors/SimpleDeviceOrientationSensor/Driver.h b/Sensors/SimpleDeviceOrientationSensor/Driver.h
new file mode 100644
index 00000000..9718080c
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/Driver.h
@@ -0,0 +1,19 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved
+//
+//Abstract:
+//
+// This module contains the type definitions for the simple device orientation sensor
+// driver callback class.
+//
+//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/SimpleDeviceOrientationSensor/HardwareSimulator.h b/Sensors/SimpleDeviceOrientationSensor/HardwareSimulator.h
new file mode 100644
index 00000000..8f96b902
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/HardwareSimulator.h
@@ -0,0 +1,58 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved
+//
+//Abstract:
+//
+// This module contains the type definitions for the simple device orientation sensor sample
+// hardware simulator.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#pragma once
+
+#include <windows.h>
+#include <wdf.h>
+
+#include <SensorsTrace.h>
+#include <SensorsCx.h>
+#include <windows.devices.sensors.h>
+
+#define HardwareSimulator_HardwareInterval (1000)
+
+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;
+ WDFOBJECT m_SimulatorInstance;
+
+public:
+ _HardwareSimulator();
+ ~_HardwareSimulator();
+
+ // WDF callbacks
+ static EVT_WDF_TIMER OnTimerExpire;
+
+ static NTSTATUS Initialize(_In_ WDFDEVICE Device, _Out_ WDFOBJECT *SimulatorInstance);
+ NTSTATUS Cleanup();
+ NTSTATUS Start();
+ NTSTATUS Stop();
+ ABI::Windows::Devices::Sensors::SimpleOrientation GetOrientation();
+
+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/SimpleDeviceOrientationSensor/SensorsTrace.h b/Sensors/SimpleDeviceOrientationSensor/SensorsTrace.h
new file mode 100644
index 00000000..6098864d
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SensorsTrace.h
@@ -0,0 +1,100 @@
+//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 - 3C773167-F26D-4F72-A1DE-95F1FD795840
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ SimpleDeviceOrientationSensorTraceGuid, (3C773167,F26D,4F72,A1DE,95F1FD795840), \
+ 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/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.def b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.def
new file mode 100644
index 00000000..aa44c9aa
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.def
@@ -0,0 +1,6 @@
+; SimpleDeviceOrientationSensor.def : Declares the module parameters.
+
+LIBRARY SimpleDeviceOrientationSensor
+
+EXPORTS
+
diff --git a/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.inx b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.inx
new file mode 100644
index 00000000..7de2e6f0
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.inx
Binary files differ
diff --git a/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.sln b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.sln
new file mode 100644
index 00000000..3dc42976
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.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}") = "SimpleDeviceOrientationSensor", "SimpleDeviceOrientationSensor.vcxproj", "{EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}"
+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
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Debug|Win32.Build.0 = Debug|Win32
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Release|Win32.ActiveCfg = Release|Win32
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Release|Win32.Build.0 = Release|Win32
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Debug|x64.ActiveCfg = Debug|x64
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Debug|x64.Build.0 = Debug|x64
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Release|x64.ActiveCfg = Release|x64
+ {EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj
new file mode 100644
index 00000000..ee3d87a3
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.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>{EEA3DEEA-AF9A-45E3-B6AE-070677AC1032}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{1854CF02-14B5-40BD-A09F-4C744EFB31A8}</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>SimpleDeviceOrientationSensor</WppModuleName>
+ <WppScanConfigurationData>sensorstrace.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include="SimpleDeviceOrientationSensor.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\SimpleDeviceOrientationSensor.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>SimpleDeviceOrientationSensor</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>SimpleDeviceOrientationSensor</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>SimpleDeviceOrientationSensor</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>SimpleDeviceOrientationSensor</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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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>SimpleDeviceOrientationSensor.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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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>SimpleDeviceOrientationSensor.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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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>SimpleDeviceOrientationSensor.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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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);$(SDK_INC_PATH)\ABI;$(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>SimpleDeviceOrientationSensor.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/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj.Filters b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj.Filters
new file mode 100644
index 00000000..45db253b
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.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>{00557774-6CAE-4A42-9465-A85A4F048686}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{68764800-116B-4343-8B60-49693688236E}</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>{25662F7E-DB14-43DD-84A3-E8B7327B6ECE}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{372D6D06-B60D-4D04-901A-FC8530D3AC42}</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="SimpleDeviceOrientationSensor.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="SimpleDeviceOrientationSensor.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Sensors/SimpleDeviceOrientationSensor/client.cpp b/Sensors/SimpleDeviceOrientationSensor/client.cpp
new file mode 100644
index 00000000..c167b6c2
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/client.cpp
@@ -0,0 +1,595 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of driver callback function
+// from clx to simple device orientation sensor.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include <timeapi.h>
+
+#include "Client.tmh"
+
+// This routine is called by worker thread to read a single sample, compare threshold
+// and push it back to CLX.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::GetData()
+{
+ PHardwareSimulator pSimulator = nullptr;
+ FILETIME TimeStamp = {};
+ NTSTATUS Status = STATUS_SUCCESS;
+ ABI::Windows::Devices::Sensors::SimpleOrientation Sample;
+
+ SENSOR_FunctionEnter();
+
+ if (FALSE != m_FirstSample)
+ {
+ Status = GetPerformanceTime(&m_StartTime);
+ if (!NT_SUCCESS(Status))
+ {
+ m_StartTime = 0;
+ TraceError("SDOS %!FUNC! GetPerformanceTime %!STATUS!", Status);
+ }
+
+ m_SampleCount = 0;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ Sample = pSimulator->GetOrientation();
+
+ if (FALSE != m_FirstSample || m_LastSample != Sample)
+ {
+ m_LastSample = Sample;
+
+ // push to clx
+ InitPropVariantFromUInt32(m_LastSample, &(m_pData->List[SDO_DATA_SIMPLEDEVICEORIENTATION].Value));
+
+ GetSystemTimePreciseAsFileTime(&TimeStamp);
+ InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[SDO_DATA_TIMESTAMP].Value));
+
+ SensorsCxSensorDataReady(m_SensorInstance, m_pData);
+
+ m_FirstSample = FALSE;
+ }
+ else
+ {
+ Status = STATUS_DATA_NOT_ACCEPTED;
+ TraceInformation("SDOS %!FUNC! SDO Data did NOT meet the threshold");
+ }
+
+Exit:
+ 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 SdoDevice::OnTimerExpire(
+ _In_ WDFTIMER Timer // WDF timer object
+ )
+{
+ PSdoDevice pDevice = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ pDevice = GetSdoContextFromSensorInstance(WdfTimerGetParentObject(Timer));
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetSdoContextFromSensorInstance failed %!STATUS!", Status);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Get data and push to clx
+ WdfWaitLockAcquire(pDevice->m_Lock, NULL);
+ Status = pDevice->GetData();
+ if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
+ {
+ TraceError("SDOS %!FUNC! GetData Failed %!STATUS!", Status);
+ }
+ WdfWaitLockRelease(pDevice->m_Lock);
+
+ // Schedule next wake up time
+ if (Sdo_Mininum_DataInterval <= pDevice->m_Interval &&
+ FALSE != pDevice->m_PoweredOn &&
+ FALSE != pDevice->m_Started)
+ {
+ LONGLONG WaitTime = 0; // in unit of 100ns
+
+ if (0 == pDevice->m_StartTime)
+ {
+ // in case we fail to get sensor start time, use static wait time
+ WaitTime = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
+ }
+ else
+ {
+ ULONG CurrentTimeMs = 0;
+
+ // dynamically calculate wait time to avoid jitter
+ Status = GetPerformanceTime(&CurrentTimeMs);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! GetPerformanceTime %!STATUS!", Status);
+ WaitTime = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
+ }
+ else
+ {
+ pDevice->m_SampleCount++;
+ if (CurrentTimeMs > (pDevice->m_StartTime + (pDevice->m_Interval * (pDevice->m_SampleCount + 1))))
+ {
+ // If we skipped two or more beats, reschedule the timer with a zero due time to catch up on missing samples
+ WaitTime = 0;
+ }
+ else
+ {
+ WaitTime = (pDevice->m_StartTime +
+ (pDevice->m_Interval * (pDevice->m_SampleCount + 1))) - CurrentTimeMs;
+ }
+ WaitTime = WDF_REL_TIMEOUT_IN_MS(WaitTime);
+ }
+ }
+ WdfTimerStart(pDevice->m_Timer, WaitTime);
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+}
+
+// Called by Sensor CLX to begin continously sampling the sensor.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnStart(
+ _In_ SENSOROBJECT SensorInstance // sensor device object
+ )
+{
+ PHardwareSimulator pSimulator = nullptr;
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ }
+ else if (0 == pDevice->m_Interval)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Interval parameter is invalid (equal to 0). Failed %!STATUS!", Status);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Get the simulator context
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Start the simulator
+ pSimulator->Start();
+
+ pDevice->m_FirstSample = TRUE;
+
+ // Start polling
+ pDevice->m_Started = TRUE;
+
+ InitPropVariantFromUInt32(SensorState_Active,
+ &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+
+ // Start the sample polling timer.
+ // Note: The polling timer is configured to allow for the first sample to be reported immediately.
+ // Some hardware may want to delay the first sample report a little to account for hardware start time.
+ WdfTimerStart(pDevice->m_Timer, 0);
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to stop continously sampling the sensor.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnStop(
+ _In_ SENSOROBJECT SensorInstance // sensor device object
+ )
+{
+ PHardwareSimulator pSimulator = nullptr;
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Stop polling
+
+ pDevice->m_Started = FALSE;
+
+ // Waiting for the callback to complete, then stopping the timer
+ WdfTimerStop(pDevice->m_Timer, TRUE);
+
+ InitPropVariantFromUInt32(SensorState_Idle,
+ &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ // Stop the simulator
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator->Stop();
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+
+ return Status;
+}
+
+// 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.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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
+ )
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG size = 0;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = 0;
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! pDevice: Invalid parameter! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pFields)
+ {
+ // Just return size
+ size = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ else
+ {
+ if (pFields->AllocatedSizeInBytes < pDevice->m_pSupportedDataFields->AllocatedSizeInBytes)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out data
+ Status = PropertiesListCopy(pFields, pDevice->m_pSupportedDataFields);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! PropertiesListCopy failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ size = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+
+ *pSize = size;
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get sensor properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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
+ )
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG size = 0;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = 0;
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! pDevice: Invalid parameter! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pProperties)
+ {
+ // Just return size
+ size = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pProperties))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pProperties, pDevice->m_pProperties);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ size = CollectionsListGetMarshalledSize(pDevice->m_pProperties);
+ }
+
+ *pSize = size;
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get data field properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnGetDataFieldProperties(
+ _In_ SENSOROBJECT SensorInstance, // sensor device object
+ _In_ const PROPERTYKEY *DataField, // pointer to the propertykey of requested property
+ _Inout_opt_ PSENSOR_COLLECTION_LIST /*pProperties*/, // pointer to a list of sensor properties
+ _Out_ PULONG pSize // number of bytes for the list of sensor properties
+)
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize || nullptr == DataField)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+
+ *pSize = 0;
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get sampling rate of the sensor.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnGetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // sensor device object
+ _Out_ PULONG DataRateMs // sampling rate in milliseconds
+ )
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (nullptr == DataRateMs)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! DataRateMs(0x%p) parameter is invalid. Failed %!STATUS!", DataRateMs, Status);
+ goto Exit;
+ }
+
+ *DataRateMs = pDevice->m_Interval;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to set sampling rate of the sensor.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnSetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // sensor device object
+ _In_ ULONG DataRateMs // sampling rate in milliseconds
+ )
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
+ goto Exit;
+ }
+
+ if (Sdo_Mininum_DataInterval > DataRateMs)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! DataRateMs(%d) parameter is smaller than the minimum data interval. Failed %!STATUS!", DataRateMs, Status);
+ goto Exit;
+ }
+
+ pDevice->m_Interval = DataRateMs;
+
+ // Restart the timer at minimum report interval to return a sample as soon as possible.
+ 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(Sdo_Mininum_DataInterval));
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get data thresholds. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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
+ )
+{
+ PSdoDevice pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pDevice || nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! Invalid parameters! %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (nullptr == pThresholds)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pEmptyThreshold);
+ }
+ else
+ {
+ if (pThresholds->AllocatedSizeInBytes <
+ CollectionsListGetMarshalledSize(pDevice->m_pEmptyThreshold))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pThresholds, pDevice->m_pEmptyThreshold);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ *pSize = CollectionsListGetMarshalledSize(pDevice->m_pEmptyThreshold);
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status))
+ {
+ *pSize = 0;
+ }
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to set data thresholds.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnSetDataThresholds(
+ _In_ SENSOROBJECT /*SensorInstance*/, // sensor device object
+ _In_ PSENSOR_COLLECTION_LIST /*pThresholds*/ // pointer to a list of sensor thresholds
+ )
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+ SENSOR_FunctionEnter();
+
+ // Unsupported at this point in time.
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to handle IOCTLs that clx does not support
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::OnIoControl(
+ _In_ SENSOROBJECT /*SensorInstance*/, // Sensor object
+ _In_ WDFREQUEST /*Request*/, // WDF request object
+ _In_ size_t /*OutputBufferLength*/, // number of bytes to retrieve from output buffer
+ _In_ size_t /*InputBufferLength*/, // number of bytes to retrieve from input buffer
+ _In_ ULONG /*IoControlCode*/ // IOCTL control code
+ )
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+ SENSOR_FunctionEnter();
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
diff --git a/Sensors/SimpleDeviceOrientationSensor/device.cpp b/Sensors/SimpleDeviceOrientationSensor/device.cpp
new file mode 100644
index 00000000..e9624301
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/device.cpp
@@ -0,0 +1,572 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of WDF callback functions
+// for sample simple device orientation sensor driver.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+
+#include "Device.tmh"
+
+// Simple Device Orientation Sample Sensors Unique ID
+// DO NOT REUSE THIS GUID, CREATE A NEW GUID
+// {57AB5189-3D73-4E4D-AFEB-019A5CFB8F05}
+DEFINE_GUID(GUID_SdoDevice_UniqueID,
+ 0x57ab5189, 0x3d73, 0x4e4d, 0xaf, 0xeb, 0x1, 0x9a, 0x5c, 0xfb, 0x8f, 0x5);
+
+// This routine initializes the sensor to its default properties
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::Initialize(
+ _In_ WDFDEVICE Device, // WDFDEVICE object
+ _In_ SENSOROBJECT SensorInstance // SENSOROBJECT for each sensor instance
+ )
+{
+ ULONG Size = 0;
+ WDF_OBJECT_ATTRIBUTES MemoryAttributes;
+ WDFMEMORY MemoryHandle = NULL;
+ FILETIME Time = {};
+ WDF_OBJECT_ATTRIBUTES TimerAttributes;
+ WDF_TIMER_CONFIG TimerConfig;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Store device and instance
+ m_FxDevice = Device;
+ m_SensorInstance = SensorInstance;
+ m_Started = FALSE;
+
+ m_PoweredOn = FALSE;
+ m_FirstSample = TRUE;
+
+ // Initialize the simple device orientation simulator
+ HardwareSimulator::Initialize(Device, &m_SimulatorInstance);
+
+ //
+ // Create Locks
+ //
+ {
+ Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDO %!FUNC! WdfWaitLockCreate m_Lock failed %!STATUS!", Status);
+ goto Exit;
+ }
+ }
+
+ //
+ // Create timer object for polling sensor samples
+ //
+ {
+ WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
+ TimerAttributes.ParentObject = SensorInstance;
+ TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ WDF_TIMER_CONFIG_INIT(&TimerConfig, OnTimerExpire);
+ Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDO %!FUNC! WdfTimerCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+ }
+
+ //
+ // Sensor Enumeration Properties
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ENUMERATION_PROPERTIES_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_SDO,
+ Size,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&m_pEnumerationProperties));
+ if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties)
+ {
+ TraceError("SDO %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ 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_SimpleDeviceOrientation,
+ &(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"Simple Device Orientation",
+ &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));
+
+ m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
+ InitPropVariantFromCLSID(GUID_SdoDevice_UniqueID,
+ &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value));
+
+ m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary;
+ InitPropVariantFromBoolean(FALSE,
+ &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); // This value should be set to TRUE if multiple simple device orientation sensors
+ // exist on the system and this sensor is the primary sensor
+ }
+
+ //
+ // Supported Data-Fields
+ //
+ {
+ Size = SENSOR_PROPERTY_LIST_SIZE(SDO_DATA_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_SDO,
+ Size,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&m_pSupportedDataFields));
+ if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields)
+ {
+ TraceError("SDO %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size);
+ m_pSupportedDataFields->Count = SDO_DATA_COUNT;
+
+ m_pSupportedDataFields->List[SDO_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp;
+ m_pSupportedDataFields->List[SDO_DATA_SIMPLEDEVICEORIENTATION] = PKEY_SensorData_SimpleDeviceOrientation;
+ }
+
+ //
+ // Data
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(SDO_DATA_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_SDO,
+ Size,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&m_pData));
+ if (!NT_SUCCESS(Status) || nullptr == m_pData)
+ {
+ TraceError("SDO %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pData, Size);
+ m_pData->Count = SDO_DATA_COUNT;
+
+ m_pData->List[SDO_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
+ GetSystemTimePreciseAsFileTime(&Time);
+ InitPropVariantFromFileTime(&Time, &(m_pData->List[SDO_DATA_TIMESTAMP].Value));
+
+ m_pData->List[SDO_DATA_SIMPLEDEVICEORIENTATION].Key = PKEY_SensorData_SimpleDeviceOrientation;
+ InitPropVariantFromUInt32(ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup, &(m_pData->List[SDO_DATA_SIMPLEDEVICEORIENTATION].Value));
+ }
+
+ //
+ // Sensor Properties
+ //
+ {
+ m_Interval = Sdo_Default_DataInterval;
+
+ Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_PROPERTIES_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_SDO,
+ Size,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&m_pProperties));
+ if (!NT_SUCCESS(Status) || nullptr == m_pProperties)
+ {
+ TraceError("SDO %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size);
+ m_pProperties->Count = SENSOR_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(Sdo_Mininum_DataInterval,
+ &(m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
+ InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pData),
+ &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_SimpleDeviceOrientation,
+ &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));
+ }
+
+ //
+ // Empty Threshold List
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(0);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_SDO,
+ Size,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(&m_pEmptyThreshold));
+ if (!NT_SUCCESS(Status) || nullptr == m_pEmptyThreshold)
+ {
+ TraceError("SDO %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pEmptyThreshold, Size);
+ m_pEmptyThreshold->Count = 0;
+ }
+
+ // Reset the FirstSample flag
+ m_FirstSample = TRUE;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// This routine is the AddDevice entry point for the SDO 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.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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
+ )
+{
+ WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
+ WDFDEVICE Device = nullptr;
+ WDF_OBJECT_ATTRIBUTES FdoAttributes;
+ ULONG Flag = 0;
+ SENSOR_CONTROLLER_CONFIG SensorConfig;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&FdoAttributes);
+
+ // Initialize FDO attributes and set up file object with sensor extension
+ Status = SensorsCxDeviceInitConfig(pDeviceInit, &FdoAttributes, Flag);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! SensorsCxDeviceInitConfig failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Register the PnP callbacks with the framework.
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
+ Callbacks.EvtDevicePrepareHardware = SdoDevice::OnPrepareHardware;
+ Callbacks.EvtDeviceReleaseHardware = SdoDevice::OnReleaseHardware;
+ Callbacks.EvtDeviceD0Entry = SdoDevice::OnD0Entry;
+ Callbacks.EvtDeviceD0Exit = SdoDevice::OnD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &Callbacks);
+
+ // Call the framework to create the device
+ Status = WdfDeviceCreate(&pDeviceInit, &FdoAttributes, &Device);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! WdfDeviceCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Register CLX callback function pointers
+ SENSOR_CONTROLLER_CONFIG_INIT(&SensorConfig);
+ SensorConfig.DriverIsPowerPolicyOwner = WdfUseDefault;
+
+ SensorConfig.EvtSensorStart = SdoDevice::OnStart;
+ SensorConfig.EvtSensorStop = SdoDevice::OnStop;
+ SensorConfig.EvtSensorGetSupportedDataFields = SdoDevice::OnGetSupportedDataFields;
+ SensorConfig.EvtSensorGetDataInterval = SdoDevice::OnGetDataInterval;
+ SensorConfig.EvtSensorSetDataInterval = SdoDevice::OnSetDataInterval;
+ SensorConfig.EvtSensorGetDataFieldProperties = SdoDevice::OnGetDataFieldProperties;
+ SensorConfig.EvtSensorGetDataThresholds = SdoDevice::OnGetDataThresholds;
+ SensorConfig.EvtSensorSetDataThresholds = SdoDevice::OnSetDataThresholds;
+ SensorConfig.EvtSensorGetProperties = SdoDevice::OnGetProperties;
+ SensorConfig.EvtSensorDeviceIoControl = SdoDevice::OnIoControl;
+
+ // Set up power capabilities and IO queues
+ Status = SensorsCxDeviceInitialize(Device, &SensorConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! SensorsCxDeviceInitialize failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+Exit:
+ 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).
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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.
+
+{
+ PSdoDevice pDevice = nullptr;
+ WDF_OBJECT_ATTRIBUTES SensorAttr = {};
+ SENSOR_CONFIG SensorConfig = {};
+ SENSOROBJECT SensorInstance = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Construct sensor instance
+
+ // Create WDFOBJECT for the sensor
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&SensorAttr, SdoDevice);
+
+ // Register sensor instance with clx
+ Status = SensorsCxSensorCreate(Device, &SensorAttr, &SensorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! SensorsCxSensorCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetSdoContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ Status = pDevice->Initialize(Device, SensorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! Initialize device object failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_CONFIG_INIT(&SensorConfig);
+ SensorConfig.pEnumerationList = pDevice->m_pEnumerationProperties;
+ Status = SensorsCxSensorInitialize(SensorInstance, &SensorConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! SensorsCxSensorInitialize failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+
+Exit:
+ 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.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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.
+{
+ PHardwareSimulator pSimulator = nullptr;
+ PSdoDevice pDevice = nullptr;
+ SENSOROBJECT SensorInstance = nullptr;
+ ULONG SensorInstanceCount = 1; // only expect 1 sensor instance
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount);
+ if (!NT_SUCCESS(Status) ||
+ 0 == SensorInstanceCount ||
+ NULL == SensorInstance)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! GetSdoContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Delete lock
+ if (pDevice->m_Lock)
+ {
+ WdfObjectDelete(pDevice->m_Lock);
+ pDevice->m_Lock = NULL;
+ }
+
+ // Cleanup the simple device orientation simulator
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator->Cleanup();
+
+ // Delete hardware simulator instance
+ if (NULL != pDevice->m_SimulatorInstance)
+ {
+ WdfObjectDelete(pDevice->m_SimulatorInstance);
+ pDevice->m_SimulatorInstance = NULL;
+ }
+
+ // Delete sensor instance
+ if (NULL != pDevice->m_SensorInstance)
+ {
+ WdfObjectDelete(pDevice->m_SensorInstance);
+ }
+
+Exit:
+ 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.
+// Returns an NTSTATUS code
+NTSTATUS SdoDevice::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
+{
+ PSdoDevice pDevice;
+ SENSOROBJECT SensorInstance = nullptr;
+ ULONG SensorInstanceCount = 1;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount);
+ if (!NT_SUCCESS(Status) ||
+ 0 == SensorInstanceCount ||
+ NULL == SensorInstance)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! GetSdoContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Power on sensor
+ pDevice->m_PoweredOn = TRUE;
+ InitPropVariantFromUInt32(SensorState_Idle,
+ &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+Exit:
+ 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.
+// Returns an NTSTATUS code
+NTSTATUS
+SdoDevice::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
+{
+ PSdoDevice pDevice;
+ SENSOROBJECT SensorInstance = nullptr;
+ ULONG SensorInstanceCount = 1;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get sensor instance
+ Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount);
+ if (!NT_SUCCESS(Status) ||
+ 0 == SensorInstanceCount ||
+ NULL == SensorInstance)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetSdoContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("SDOS %!FUNC! GetSdoContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Power off sensor
+ pDevice->m_PoweredOn = FALSE;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
diff --git a/Sensors/SimpleDeviceOrientationSensor/driver.cpp b/Sensors/SimpleDeviceOrientationSensor/driver.cpp
new file mode 100644
index 00000000..f3ed0045
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/driver.cpp
@@ -0,0 +1,75 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of entry and exit point of sample simple device orientation sensor driver.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "Driver.h"
+
+#include "Driver.tmh"
+
+// This routine is the driver initialization entry point.
+// Returns an NTSTATUS code
+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 = SENSORV2_POOL_TAG_SDO;
+
+ //
+ // Initialize the driver configuration structure.
+ //
+ WDF_DRIVER_CONFIG_INIT(&DriverConfig, SdoDevice::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("SDOS %!FUNC! WdfDriverCreate failed: %!STATUS!", Status);
+ goto Exit;
+ }
+
+Exit:
+ SENSOR_FunctionExit(Status);
+
+ return Status;
+}
+
+// This routine is called when the driver unloads.
+VOID OnDriverUnload(
+ _In_ WDFDRIVER Driver) // driver object
+{
+ 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(Driver);
+
+ return;
+} \ No newline at end of file
diff --git a/Sensors/SimpleDeviceOrientationSensor/hardwaresimulator.cpp b/Sensors/SimpleDeviceOrientationSensor/hardwaresimulator.cpp
new file mode 100644
index 00000000..759338cd
--- /dev/null
+++ b/Sensors/SimpleDeviceOrientationSensor/hardwaresimulator.cpp
@@ -0,0 +1,248 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of the simple device orientation sensor sample
+// hardware simulator.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "HardwareSimulator.h"
+
+#include "HardwareSimulator.tmh"
+
+// Simulated device orientations
+const ABI::Windows::Devices::Sensors::SimpleOrientation OrientationData[] = {
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Facedown,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_NotRotated,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Rotated90DegreesCounterclockwise,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Facedown,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Rotated180DegreesCounterclockwise,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup,
+ ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Rotated270DegreesCounterclockwise
+};
+
+HardwareSimulator::_HardwareSimulator() :
+ m_Index(0),
+ m_Lock(NULL),
+ m_State(SimulatorState_NotInitialized),
+ m_SimulatorInstance(NULL),
+ m_Timer(NULL)
+{
+}
+
+HardwareSimulator::~_HardwareSimulator()
+{
+}
+
+// This static routine performs simulator initialization. The routine creates a
+// timer object that periodically updates the m_Index location
+// Returns an NTSTATUS code
+NTSTATUS HardwareSimulator::Initialize(
+ _In_ WDFDEVICE Device, // WDF device representing the sensor
+ _Out_ WDFOBJECT *SimulatorInstance) // Instance of the WDF object for the simulator
+{
+ PHardwareSimulator pSimulator = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_OBJECT_ATTRIBUTES HardwareSimulatorAttributes = {};
+
+ SENSOR_FunctionEnter();
+
+ // Create WDFOBJECT for the hardware simulator
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&HardwareSimulatorAttributes, HardwareSimulator);
+ HardwareSimulatorAttributes.ParentObject = Device;
+
+ Status = WdfObjectCreate(&HardwareSimulatorAttributes, SimulatorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("SDOS %!FUNC! WdfObjectCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(*SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator->InitializeInternal(*SimulatorInstance);
+
+Exit:
+
+ SENSOR_FunctionExit(Status);
+
+ return Status;
+}
+
+// Internal routine to perform simulator initialization
+// Returns an NTSTATUS code
+NTSTATUS HardwareSimulator::InitializeInternal(
+ _In_ WDFOBJECT SimulatorInstance) // Instance of the WDF object for the simulator
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_OBJECT_ATTRIBUTES TimerAttributes = {};
+ WDF_TIMER_CONFIG TimerConfig = {};
+
+ SENSOR_FunctionEnter();
+
+ // Only initialize the simulator if it is in the "not initialized" state
+ if (SimulatorState_NotInitialized == m_State)
+ {
+ // Create Lock
+ Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
+ if (!NT_SUCCESS(Status))
+ {
+ m_Lock = NULL;
+
+ TraceError("SDOS %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // 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("SDOS %!FUNC! WdfTimerCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Set the simulator state to "initialized"
+ m_State = SimulatorState_Initialized;
+ m_SimulatorInstance = SimulatorInstance;
+ }
+
+Exit:
+ if (!NT_SUCCESS(Status) && NULL != m_Lock)
+ {
+ WdfObjectDelete(m_Lock);
+ m_Lock = NULL;
+ }
+
+ SENSOR_FunctionExit(Status);
+
+ return Status;
+}
+
+// This routine perform a simulator cleanup
+// Returns an NTSTATUS code
+NTSTATUS HardwareSimulator::Cleanup()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (SimulatorState_Started == m_State)
+ {
+ Stop();
+ }
+
+ // Delete lock
+ if (NULL != m_Lock)
+ {
+ WdfObjectDelete(m_Lock);
+ m_Lock = NULL;
+ }
+
+ // Set the simulator state to "not initialized"
+ m_State = SimulatorState_NotInitialized;
+
+ return status;
+}
+
+// This routine starts the simulator
+// Returns an NTSTATUS code
+NTSTATUS HardwareSimulator::Start()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (SimulatorState_Initialized == m_State)
+ {
+ WdfTimerStart(m_Timer, WDF_REL_TIMEOUT_IN_MS(HardwareSimulator_HardwareInterval));
+ m_State = SimulatorState_Started;
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+}
+
+// This routine stops the simulator
+// Returns an NTSTATUS code
+NTSTATUS HardwareSimulator::Stop()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (SimulatorState_Started == m_State)
+ {
+ WdfTimerStop(m_Timer, TRUE);
+ m_State = SimulatorState_Initialized;
+ }
+
+ SENSOR_FunctionExit(status);
+
+ return status;
+}
+
+// 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) // WDF timer object
+{
+ HardwareSimulator *pSimulator = nullptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(WdfTimerGetParentObject(Timer));
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("SDOS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // 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 %= ARRAYSIZE(OrientationData);
+ WdfWaitLockRelease(pSimulator->m_Lock);
+
+ WdfTimerStart(pSimulator->m_Timer, WDF_REL_TIMEOUT_IN_MS(HardwareSimulator_HardwareInterval));
+ }
+
+ SENSOR_FunctionExit(Status);
+}
+
+// This routine returns the current sample from the driver at the current m_Index location.
+// Returns one of the ABI::Windows::Devices::Sensors::SimpleOrientation enum values.
+ABI::Windows::Devices::Sensors::SimpleOrientation HardwareSimulator::GetOrientation()
+{
+ ABI::Windows::Devices::Sensors::SimpleOrientation Sample = ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ WdfWaitLockAcquire(m_Lock, NULL);
+ Sample = OrientationData[m_Index];
+ WdfWaitLockRelease(m_Lock);
+
+ SENSOR_FunctionExit(Status);
+
+ return Sample;
+} \ No newline at end of file