summaryrefslogtreecommitdiff
path: root/sensors/Fusion/device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sensors/Fusion/device.cpp')
-rw-r--r--sensors/Fusion/device.cpp729
1 files changed, 729 insertions, 0 deletions
diff --git a/sensors/Fusion/device.cpp b/sensors/Fusion/device.cpp
new file mode 100644
index 00000000..0ac6e042
--- /dev/null
+++ b/sensors/Fusion/device.cpp
@@ -0,0 +1,729 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of WDF callback functions
+// for FusionSensor driver.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "HardwareSimulator.h"
+
+#include "Device.tmh"
+
+// FusionSensor Unique ID
+// {997335D7-A71C-4C89-9D95-58EAEF917C6A}
+//
+// TODO: The unique ID below must be set per sensor. A different GUID must be provided for each sensor. Please generate a new GUID.
+DEFINE_GUID(GUID_FusionSensorDevice_UniqueID,
+ 0x997335d7, 0xa71c, 0x4c89, 0x9d, 0x95, 0x58, 0xea, 0xef, 0x91, 0x7c, 0x6a);
+
+
+// This routine initializes the sensor to its default properties
+NTSTATUS
+FusionSensorDevice::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;
+ PHardwareSimulator pSimulator = nullptr;
+
+ SENSOR_FunctionEnter();
+
+ // Store device and instance
+ m_FxDevice = Device;
+ m_SensorInstance = SensorInstance;
+ m_Started = FALSE;
+
+ // TODO: Remove the HardwareSimulator code in your final driver. The HardwareSimulator is only used for the purpose of demonstrating how sensor driver samples work.
+ // Initialize the FusionSensor simulator
+ Status = HardwareSimulator::Initialize(Device, &m_SimulatorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("FUS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Create Lock
+ Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Create timer object for polling sensor samples
+ WDF_TIMER_CONFIG_INIT(&TimerConfig, FusionSensorDevice::OnTimerExpire);
+ WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
+ TimerAttributes.ParentObject = SensorInstance;
+ TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!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,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pEnumerationProperties);
+ if (!NT_SUCCESS(Status) || m_pEnumerationProperties == nullptr)
+ {
+ TraceError("FUS %!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_Orientation,
+ &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
+ InitPropVariantFromString(L"TODO-Set-Manufacturer",
+ &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value));
+
+ m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model;
+ InitPropVariantFromString(L"Sample fusion sensor",
+ &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));
+
+ m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
+ InitPropVariantFromCLSID(GUID_FusionSensorDevice_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));
+ }
+
+ //
+ // Supported Data-Fields
+ //
+ {
+ Size = SENSOR_PROPERTY_LIST_SIZE(FUSIONSENSOR_DATA_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pSupportedDataFields);
+ if (!NT_SUCCESS(Status) || m_pSupportedDataFields == nullptr)
+ {
+ TraceError("FUS %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size);
+ m_pSupportedDataFields->Count = FUSIONSENSOR_DATA_COUNT;
+
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_QUATERNION_W] = PKEY_SensorData_QuaternionW;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_QUATERNION_X] = PKEY_SensorData_QuaternionX;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_QUATERNION_Y] = PKEY_SensorData_QuaternionY;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_QUATERNION_Z] = PKEY_SensorData_QuaternionZ;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_ACCURACY] = PKEY_SensorData_MagnetometerAccuracy;
+ m_pSupportedDataFields->List[FUSIONSENSOR_DATA_DECLINATION_ANGLE] = PKEY_SensorData_DeclinationAngle_Degrees;
+ }
+
+ //
+ // Data
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(FUSIONSENSOR_DATA_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pData);
+ if (!NT_SUCCESS(Status) || m_pData == nullptr)
+ {
+ TraceError("FUS %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pData, Size);
+ m_pData->Count = FUSIONSENSOR_DATA_COUNT;
+
+ m_pData->List[FUSIONSENSOR_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
+ GetSystemTimePreciseAsFileTime(&Time);
+ InitPropVariantFromFileTime(&Time, &(m_pData->List[FUSIONSENSOR_DATA_TIMESTAMP].Value));
+
+ m_pData->List[FUSIONSENSOR_DATA_QUATERNION_W].Key = PKEY_SensorData_QuaternionW;
+ InitPropVariantFromFloat(0.0, &(m_pData->List[FUSIONSENSOR_DATA_QUATERNION_W].Value));
+
+ m_pData->List[FUSIONSENSOR_DATA_QUATERNION_X].Key = PKEY_SensorData_QuaternionX;
+ InitPropVariantFromFloat(0.0, &(m_pData->List[FUSIONSENSOR_DATA_QUATERNION_X].Value));
+
+ m_pData->List[FUSIONSENSOR_DATA_QUATERNION_Y].Key = PKEY_SensorData_QuaternionY;
+ InitPropVariantFromFloat(0.0, &(m_pData->List[FUSIONSENSOR_DATA_QUATERNION_Y].Value));
+
+ m_pData->List[FUSIONSENSOR_DATA_QUATERNION_Z].Key = PKEY_SensorData_QuaternionZ;
+ InitPropVariantFromFloat(0.0, &(m_pData->List[FUSIONSENSOR_DATA_QUATERNION_Z].Value));
+
+ m_pData->List[FUSIONSENSOR_DATA_ACCURACY].Key = PKEY_SensorData_MagnetometerAccuracy;
+ InitPropVariantFromUInt32(Unknown, &(m_pData->List[FUSIONSENSOR_DATA_ACCURACY].Value));
+
+ // Declination angle is optional, it will be computed by the system if not present.
+ m_pData->List[FUSIONSENSOR_DATA_DECLINATION_ANGLE].Key = PKEY_SensorData_DeclinationAngle_Degrees;
+ InitPropVariantFromFloat(0.0, &(m_pData->List[FUSIONSENSOR_DATA_DECLINATION_ANGLE].Value));
+ }
+
+ //
+ // Sensor Properties
+ //
+ {
+ m_Interval = FusionSensor_Default_DataInterval;
+
+ Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_PROPERTIES_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pProperties);
+ if (!NT_SUCCESS(Status) || m_pProperties == nullptr)
+ {
+ TraceError("FUS %!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(FusionSensor_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_pData),
+ &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_Orientation,
+ &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));
+
+ m_pProperties->List[SENSOR_PROPERTY_USE_GYRO].Key = PKEY_OrientationSensor_GyroscopeUsed;
+ InitPropVariantFromBoolean(FALSE, &(m_pProperties->List[SENSOR_PROPERTY_USE_GYRO].Value));
+ }
+
+ //
+ // Accelerometer related data field properties
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ACC_DATA_FIELD_PROPERTY_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pAccDataFieldProperties);
+ if (!NT_SUCCESS(Status) || m_pAccDataFieldProperties == nullptr)
+ {
+ TraceError("FUS %!FUNC! Fusion sensor WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pAccDataFieldProperties, Size);
+ m_pAccDataFieldProperties->Count = SENSOR_ACC_DATA_FIELD_PROPERTY_COUNT;
+
+ m_pAccDataFieldProperties->List[SENSOR_ACC_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
+ InitPropVariantFromFloat((float)AccFakeDevice_Axis_Resolution,
+ &(m_pAccDataFieldProperties->List[SENSOR_ACC_RESOLUTION].Value));
+
+ m_pAccDataFieldProperties->List[SENSOR_ACC_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
+ InitPropVariantFromFloat(AccFakeDevice_Axis_Minimum,
+ &(m_pAccDataFieldProperties->List[SENSOR_ACC_MIN_RANGE].Value));
+
+ m_pAccDataFieldProperties->List[SENSOR_ACC_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
+ InitPropVariantFromFloat(AccFakeDevice_Axis_Maximum,
+ &(m_pAccDataFieldProperties->List[SENSOR_ACC_MAX_RANGE].Value));
+
+ }
+
+ //
+ // Gyroscope related data field properties
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_GYR_DATA_FIELD_PROPERTY_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pGyrDataFieldProperties);
+ if (!NT_SUCCESS(Status) || m_pGyrDataFieldProperties == nullptr)
+ {
+ TraceError("FUS %!FUNC! Fusion sensor WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pGyrDataFieldProperties, Size);
+ m_pGyrDataFieldProperties->Count = SENSOR_GYR_DATA_FIELD_PROPERTY_COUNT;
+
+ m_pGyrDataFieldProperties->List[SENSOR_GYR_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
+ InitPropVariantFromFloat(GyrFakeDevice_Resolution_DegreesPerSecond,
+ &(m_pGyrDataFieldProperties->List[SENSOR_GYR_RESOLUTION].Value));
+
+ m_pGyrDataFieldProperties->List[SENSOR_GYR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
+ InitPropVariantFromFloat(GyrFakeDevice_Minimum_DegreesPerSecond,
+ &(m_pGyrDataFieldProperties->List[SENSOR_GYR_MIN_RANGE].Value));
+
+ m_pGyrDataFieldProperties->List[SENSOR_GYR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
+ InitPropVariantFromFloat(GyrFakeDevice_Maximum_DegreesPerSecond,
+ &(m_pGyrDataFieldProperties->List[SENSOR_GYR_MAX_RANGE].Value));
+ }
+
+ //
+ // Set default threshold
+ //
+ {
+ Size = SENSOR_COLLECTION_LIST_SIZE(FUSIONSENSOR_THRESHOLD_COUNT);
+
+ MemoryHandle = NULL;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+ Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSOR_POOL_TAG_FUSIONSENSOR,
+ Size,
+ &MemoryHandle,
+ (PVOID*)&m_pThresholds);
+ if (!NT_SUCCESS(Status) || m_pThresholds == nullptr)
+ {
+ TraceError("FUS %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size);
+ m_pThresholds->Count = FUSIONSENSOR_THRESHOLD_COUNT;
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_ANGLE].Key = PKEY_SensorData_RotationAngle_Degrees;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_ANGLE].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_X].Key = PKEY_SensorData_LinearAccelerationX_Gs;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_X].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_Y].Key = PKEY_SensorData_LinearAccelerationY_Gs;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_Y].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_Z].Key = PKEY_SensorData_LinearAccelerationZ_Gs;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_LINEAR_ACCELERATION_Z].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_X].Key = PKEY_SensorData_CorrectedAngularVelocityX_DegreesPerSecond;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_X].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_Y].Key = PKEY_SensorData_CorrectedAngularVelocityY_DegreesPerSecond;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_Y].Value));
+
+ m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_Z].Key = PKEY_SensorData_CorrectedAngularVelocityZ_DegreesPerSecond;
+ InitPropVariantFromFloat(0.0, &(m_pThresholds->List[FUSIONSENSOR_THRESHOLD_ROTATION_RATE_Z].Value));
+
+ ZeroMemory(&m_CachedThresholds, sizeof(m_CachedThresholds));
+ }
+
+ ZeroMemory(&m_LastSample, sizeof(m_LastSample));
+
+ // Set default threshold
+ m_FirstSample = TRUE;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+
+
+// This routine is the AddDevice entry point for the FusionSensor 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
+FusionSensorDevice::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("FUS %!FUNC! SensorsCxDeviceInitConfig failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Register the PnP callbacks with the framework.
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
+ Callbacks.EvtDevicePrepareHardware = FusionSensorDevice::OnPrepareHardware;
+ Callbacks.EvtDeviceReleaseHardware = FusionSensorDevice::OnReleaseHardware;
+ Callbacks.EvtDeviceD0Entry = FusionSensorDevice::OnD0Entry;
+ Callbacks.EvtDeviceD0Exit = FusionSensorDevice::OnD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &Callbacks);
+
+ // Call the framework to create the device
+ Status = WdfDeviceCreate(&pDeviceInit, &FdoAttributes, &Device);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!FUNC! WdfDeviceCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Register CLX callback function pointers
+ SENSOR_CONTROLLER_CONFIG_INIT(&SensorConfig);
+ SensorConfig.DriverIsPowerPolicyOwner = WdfUseDefault;
+
+ SensorConfig.EvtSensorStart = FusionSensorDevice::OnStart;
+ SensorConfig.EvtSensorStop = FusionSensorDevice::OnStop;
+ SensorConfig.EvtSensorGetSupportedDataFields = FusionSensorDevice::OnGetSupportedDataFields;
+ SensorConfig.EvtSensorGetDataInterval = FusionSensorDevice::OnGetDataInterval;
+ SensorConfig.EvtSensorSetDataInterval = FusionSensorDevice::OnSetDataInterval;
+ SensorConfig.EvtSensorGetDataFieldProperties = FusionSensorDevice::OnGetDataFieldProperties;
+ SensorConfig.EvtSensorGetDataThresholds = FusionSensorDevice::OnGetDataThresholds;
+ SensorConfig.EvtSensorSetDataThresholds = FusionSensorDevice::OnSetDataThresholds;
+ SensorConfig.EvtSensorGetProperties = FusionSensorDevice::OnGetProperties;
+ SensorConfig.EvtSensorDeviceIoControl = FusionSensorDevice::OnIoControl;
+
+ // Set up power capabilities and IO queues
+ Status = SensorsCxDeviceInitialize(Device, &SensorConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!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).
+NTSTATUS
+FusionSensorDevice::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.
+{
+ PFusionSensorDevice 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, FusionSensorDevice);
+
+ // Register sensor instance with clx
+
+ Status = SensorsCxSensorCreate(Device, &SensorAttr, &SensorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!FUNC! SensorsCxSensorCreate failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetFusionSensorContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("FUS %!FUNC! GetFusionSensorContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // Device initialization
+
+ Status = pDevice->Initialize(Device, SensorInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("FUS %!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("FUS %!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.
+//
+// Argument:
+// Device: IN: Supplies a handle to the framework device object
+// ResourcesTranslated: IN: 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.
+//
+// Return Value:
+// NTSTATUS code
+//------------------------------------------------------------------------------
+NTSTATUS
+FusionSensorDevice::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;
+ PFusionSensorDevice 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("FUS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetFusionSensorContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("FUS %!FUNC! GetFusionSensorContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ // TODO: Remove the HardwareSimulator code in your final driver. The HardwareSimulator is only used for the purpose of demonstrating how sensor driver samples work.
+ pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
+ if (nullptr == pSimulator)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("FUS %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+
+ // Delete lock
+ if (NULL != pDevice->m_Lock)
+ {
+ WdfObjectDelete(pDevice->m_Lock);
+ pDevice->m_Lock = NULL;
+ }
+
+ // Cleanup the FusionSensor simulator
+ 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.
+NTSTATUS
+FusionSensorDevice::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
+{
+ PFusionSensorDevice pDevice;
+ SENSOROBJECT SensorInstance = NULL;
+ 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("FUS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetFusionSensorContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("FUS %!FUNC! GetFusionSensorContextFromSensorInstance 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.
+NTSTATUS
+FusionSensorDevice::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
+{
+ PFusionSensorDevice pDevice;
+ SENSOROBJECT SensorInstance = NULL;
+ 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("FUS %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ pDevice = GetFusionSensorContextFromSensorInstance(SensorInstance);
+ if (nullptr == pDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("FUS %!FUNC! GetFusionSensorContextFromSensorInstance failed %!STATUS!", Status);
+ goto Exit;
+ }
+
+ //
+ // Power on sensor
+ //
+ pDevice->m_PoweredOn = FALSE;
+
+Exit:
+ SENSOR_FunctionExit(Status);
+ return Status;
+}