summaryrefslogtreecommitdiff
path: root/sensors/ADXL345Acc/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sensors/ADXL345Acc/client.cpp')
-rw-r--r--sensors/ADXL345Acc/client.cpp1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/sensors/ADXL345Acc/client.cpp b/sensors/ADXL345Acc/client.cpp
new file mode 100644
index 00000000..937949b7
--- /dev/null
+++ b/sensors/ADXL345Acc/client.cpp
@@ -0,0 +1,1036 @@
+//Copyright (C) Microsoft Corporation, All Rights Reserved.
+//
+//Abstract:
+//
+// This module contains the implementation of driver callback functions
+// from clx to ADXL345 accelerometer.
+//
+//Environment:
+//
+// Windows User-Mode Driver Framework (UMDF)
+
+#include "Device.h"
+#include "Adxl345.h"
+
+#include <timeapi.h>
+
+#include "Client.tmh"
+
+
+// Analog Adxl345 Unique ID
+// {EF2C014C-DEBA-43F4-890D-978095684DD6}
+DEFINE_GUID(GUID_Adxl345Device_UniqueID,
+ 0xef2c014c, 0xdeba, 0x43f4, 0x89, 0xd, 0x97, 0x80, 0x95, 0x68, 0x4d, 0xd6);
+
+
+// Helper function for initializing ADXL345AccDevice. Returns status.
+inline NTSTATUS InitSensorCollection(
+ _In_ ULONG CollectionListCount,
+ _Outptr_ PSENSOR_COLLECTION_LIST *CollectionList,
+ _In_ SENSOROBJECT SensorInstance) // SENSOROBJECT for sensor instance
+{
+ WDF_OBJECT_ATTRIBUTES MemoryAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+
+ WDFMEMORY MemoryHandle = NULL;
+ ULONG MemorySize = SENSOR_COLLECTION_LIST_SIZE(CollectionListCount);
+ NTSTATUS Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_ACCELEROMETER,
+ MemorySize,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(CollectionList));
+ if (!NT_SUCCESS(Status) || nullptr == *CollectionList)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ TraceError("ACC %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ return Status;
+ }
+
+ SENSOR_COLLECTION_LIST_INIT(*CollectionList, MemorySize);
+ (*CollectionList)->Count = CollectionListCount;
+ return Status;
+}
+
+// Helper function for initializing ADXL345AccDevice. Returns status.
+inline NTSTATUS InitSensorProperty(
+ _In_ ULONG PropertyListCount,
+ _Outptr_ PSENSOR_PROPERTY_LIST *PropertyList,
+ _In_ SENSOROBJECT SensorInstance) // SENSOROBJECT for sensor instance
+{
+ WDF_OBJECT_ATTRIBUTES MemoryAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
+ MemoryAttributes.ParentObject = SensorInstance;
+
+ WDFMEMORY MemoryHandle = NULL;
+ ULONG MemorySize = SENSOR_PROPERTY_LIST_SIZE(PropertyListCount);
+ NTSTATUS Status = WdfMemoryCreate(&MemoryAttributes,
+ PagedPool,
+ SENSORV2_POOL_TAG_ACCELEROMETER,
+ MemorySize,
+ &MemoryHandle,
+ reinterpret_cast<PVOID*>(PropertyList));
+ if (!NT_SUCCESS(Status) || nullptr == *PropertyList)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ TraceError("ACC %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
+ return Status;
+ }
+
+ SENSOR_PROPERTY_LIST_INIT(*PropertyList, MemorySize);
+ (*PropertyList)->Count = PropertyListCount;
+ return Status;
+}
+
+// This routine initializes the sensor to its default properties
+NTSTATUS ADXL345AccDevice::Initialize(
+ _In_ WDFDEVICE Device, // WDFDEVICE object
+ _In_ SENSOROBJECT SensorInstance) // SENSOROBJECT for each sensor instance
+{
+ SENSOR_FunctionEnter();
+
+ // Store device and instance
+ m_Device = Device;
+ m_SensorInstance = SensorInstance;
+ m_Started = false;
+
+ // Create Lock
+ NTSTATUS Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &(m_I2CWaitLock));
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
+ }
+
+ // Sensor Enumeration Properties
+ if (NT_SUCCESS(Status))
+ {
+ Status = InitSensorCollection(SENSOR_ENUMERATION_PROPERTIES_COUNT, &m_pEnumerationProperties, SensorInstance);
+ if (NT_SUCCESS(Status))
+ {
+ m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_TYPE].Key = DEVPKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_Accelerometer3D,
+ &(m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_TYPE].Value));
+
+ m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
+ InitPropVariantFromString(SENSOR_ACCELEROMETER_MANUFACTURER,
+ &(m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_MANUFACTURER].Value));
+
+ m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_MODEL].Key = DEVPKEY_Sensor_Model;
+ InitPropVariantFromString(SENSOR_ACCELEROMETER_MODEL,
+ &(m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_MODEL].Value));
+
+ m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_PERSISTENT_UNIQUE_ID].Key = DEVPKEY_Sensor_PersistentUniqueId;
+ InitPropVariantFromCLSID(GUID_Adxl345Device_UniqueID,
+ &(m_pEnumerationProperties->List[SENSOR_ENUMERATION_PROPERTY_PERSISTENT_UNIQUE_ID].Value));
+ }
+ }
+
+ // Supported Data-Fields
+ if (NT_SUCCESS(Status))
+ {
+ Status = InitSensorProperty(SENSOR_DATA_COUNT, &m_pSupportedDataFields, SensorInstance);
+ if (NT_SUCCESS(Status))
+ {
+ m_pSupportedDataFields->List[SENSOR_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp;
+ m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_X_G] = PKEY_SensorData_AccelerationX_Gs;
+ m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_Y_G] = PKEY_SensorData_AccelerationY_Gs;
+ m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_Z_G] = PKEY_SensorData_AccelerationZ_Gs;
+ }
+ }
+
+ // Sensor Data
+ if (NT_SUCCESS(Status))
+ {
+ Status = InitSensorCollection(SENSOR_DATA_COUNT, &m_pSensorData, SensorInstance);
+ if (NT_SUCCESS(Status))
+ {
+ FILETIME time;
+ m_pSensorData->List[SENSOR_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
+ GetSystemTimeAsFileTime(&time);
+ InitPropVariantFromFileTime(&time, &(m_pSensorData->List[SENSOR_DATA_TIMESTAMP].Value));
+
+ m_pSensorData->List[SENSOR_DATA_ACCELERATION_X_G].Key = PKEY_SensorData_AccelerationX_Gs;
+ InitPropVariantFromFloat(0.0f, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_X_G].Value));
+
+ m_pSensorData->List[SENSOR_DATA_ACCELERATION_Y_G].Key = PKEY_SensorData_AccelerationY_Gs;
+ InitPropVariantFromFloat(0.0f, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_Y_G].Value));
+
+ m_pSensorData->List[SENSOR_DATA_ACCELERATION_Z_G].Key = PKEY_SensorData_AccelerationZ_Gs;
+ InitPropVariantFromFloat(0.0f, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_Z_G].Value));
+ }
+ }
+
+ // Sensor Properties
+ if (NT_SUCCESS(Status))
+ {
+ Status = InitSensorCollection(SENSOR_PROPERTIES_COUNT, &m_pSensorProperties, SensorInstance);
+ if (NT_SUCCESS(Status))
+ {
+ m_Interval = DEFAULT_ACCELEROMETER_REPORT_INTERVAL;
+
+ m_pSensorProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State;
+ InitPropVariantFromUInt32(SensorState_Initializing, &(m_pSensorProperties->List[SENSOR_PROPERTY_STATE].Value));
+
+ m_pSensorProperties->List[SENSOR_PROPERTY_MIN_DATA_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
+ InitPropVariantFromUInt32(ACCELEROMETER_MIN_REPORT_INTERVAL, &(m_pSensorProperties->List[SENSOR_PROPERTY_MIN_DATA_INTERVAL].Value));
+
+ m_pSensorProperties->List[SENSOR_PROPERTY_MAX_DATA_FIELD_SIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
+ InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pSensorData), &(m_pSensorProperties->List[SENSOR_PROPERTY_MAX_DATA_FIELD_SIZE].Value));
+
+ m_pSensorProperties->List[SENSOR_PROPERTY_TYPE].Key = PKEY_Sensor_Type;
+ InitPropVariantFromCLSID(GUID_SensorType_Accelerometer3D, &(m_pSensorProperties->List[SENSOR_PROPERTY_TYPE].Value));
+ }
+ }
+
+ // Data field properties
+ if (NT_SUCCESS(Status))
+ {
+ Status = InitSensorCollection(SENSOR_DATA_FIELD_PROPERTIES_COUNT, &m_pDataFieldProperties, SensorInstance);
+ if (NT_SUCCESS(Status))
+ {
+ m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_CHANGE_SENSITIVITY_RESOLUTION), &(m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RESOLUTION].Value));
+
+ m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RANGE_MIN].Key = PKEY_SensorDataField_RangeMinimum;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_MIN_CHANGE_SENSITIVITY), &(m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RANGE_MIN].Value));
+
+ m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RANGE_MAX].Key = PKEY_SensorDataField_RangeMaximum;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_MAX_CHANGE_SENSITIVITY), &(m_pDataFieldProperties->List[SENSOR_DATA_FIELD_PROPERTY_RANGE_MAX].Value));
+ }
+ }
+
+ // Set default threshold
+ if (NT_SUCCESS(Status))
+ {
+ // note: COUNT-1 as timestamp does not have thresholds
+ Status = InitSensorCollection(SENSOR_DATA_COUNT-1, &m_pThresholds, SensorInstance);
+ if NT_SUCCESS(Status)
+ {
+ m_CachedThresholds.X = static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD);
+ m_CachedThresholds.Y = static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD);
+ m_CachedThresholds.Z = static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD);
+
+ m_pThresholds->List[SENSOR_DATA_ACCELERATION_X_G].Key = PKEY_SensorData_AccelerationX_Gs;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD), &(m_pThresholds->List[SENSOR_DATA_ACCELERATION_X_G].Value));
+
+ m_pThresholds->List[SENSOR_DATA_ACCELERATION_Y_G].Key = PKEY_SensorData_AccelerationY_Gs;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD), &(m_pThresholds->List[SENSOR_DATA_ACCELERATION_Y_G].Value));
+
+ m_pThresholds->List[SENSOR_DATA_ACCELERATION_Z_G].Key = PKEY_SensorData_AccelerationZ_Gs;
+ InitPropVariantFromFloat(static_cast<float>(ACCELEROMETER_DEFAULT_AXIS_THRESHOLD), &(m_pThresholds->List[SENSOR_DATA_ACCELERATION_Z_G].Value));
+ }
+ }
+
+ // Reset the FirstSample flag
+ if (NT_SUCCESS(Status))
+ {
+ m_FirstSample = true;
+ }
+ // Trace to this function in case of failure
+ else
+ {
+ TraceError("ACC %!FUNC! failed %!STATUS!", Status);
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+VOID ADXL345AccDevice::DeInit()
+{
+ // Delete lock
+ if (NULL != m_I2CWaitLock)
+ {
+ WdfObjectDelete(m_I2CWaitLock);
+ m_I2CWaitLock = NULL;
+ }
+
+ // Delete sensor instance
+ if (NULL != m_SensorInstance)
+ {
+ WdfObjectDelete(m_SensorInstance);
+ }
+}
+
+// This routine reads a single sample, compares threshold and pushes sample
+// to sensor class extension. This routine is protected by the caller.
+NTSTATUS ADXL345AccDevice::GetData()
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Read the device data
+ BYTE DataBuffer[ADXL345_DATA_REPORT_SIZE_BYTES];
+ WdfWaitLockAcquire(m_I2CWaitLock, NULL);
+ Status = I2CSensorReadRegister(m_I2CIoTarget, ADXL345_DATA_X0, &DataBuffer[0], sizeof(DataBuffer));
+ WdfWaitLockRelease(m_I2CWaitLock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorReadRegister from 0x%02x failed! %!STATUS!", ADXL345_DATA_X0, Status);
+ }
+ else
+ {
+ bool DataReady = false;
+
+ // Perform data conversion
+ SHORT xRaw = static_cast<SHORT>((DataBuffer[1] << 8) | DataBuffer[0]);
+ SHORT yRaw = static_cast<SHORT>((DataBuffer[3] << 8) | DataBuffer[2]);
+ SHORT zRaw = static_cast<SHORT>((DataBuffer[5] << 8) | DataBuffer[4]);
+
+ const float ScaleFactor = 1 / 256.0F;
+ VEC3D Sample = {};
+ Sample.X = static_cast<float>(xRaw * ScaleFactor);
+ Sample.Y = static_cast<float>(yRaw * ScaleFactor);
+ Sample.Z = static_cast<float>(zRaw * ScaleFactor);
+
+ // Set data ready if this is the first sample or we have exceeded the thresholds
+ if (m_FirstSample)
+ {
+ m_FirstSample = false;
+ DataReady = true;
+ }
+ else if ((fabsf(Sample.X - m_LastSample.X) >= m_CachedThresholds.X) ||
+ (fabsf(Sample.Y - m_LastSample.Y) >= m_CachedThresholds.Y) ||
+ (fabsf(Sample.Z - m_LastSample.Z) >= m_CachedThresholds.Z))
+ {
+ DataReady = true;
+ }
+
+ if (DataReady)
+ {
+ // Update values for SW thresholding and send data to class extension
+ m_LastSample.X = Sample.X;
+ m_LastSample.Y = Sample.Y;
+ m_LastSample.Z = Sample.Z;
+
+ // Save the data in the context
+ InitPropVariantFromFloat(Sample.X, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_X_G].Value));
+ InitPropVariantFromFloat(Sample.Y, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_Y_G].Value));
+ InitPropVariantFromFloat(Sample.Z, &(m_pSensorData->List[SENSOR_DATA_ACCELERATION_Z_G].Value));
+
+ FILETIME Timestamp = {};
+ GetSystemTimeAsFileTime(&Timestamp);
+ InitPropVariantFromFileTime(&Timestamp, &(m_pSensorData->List[SENSOR_DATA_TIMESTAMP].Value));
+
+ SensorsCxSensorDataReady(m_SensorInstance, m_pSensorData);
+ }
+ else
+ {
+ TraceInformation("ACC %!FUNC! Data did NOT meet the threshold");
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Services a hardware interrupt.
+BOOLEAN ADXL345AccDevice::OnInterruptIsr(
+ _In_ WDFINTERRUPT Interrupt, // Handle to a framework interrupt object
+ _In_ ULONG /*MessageID*/) // If the device is using message-signaled interrupts (MSIs),
+ // this parameter is the message number that identifies the
+ // device's hardware interrupt message. Otherwise, this value is 0.
+{
+ BOOLEAN InterruptRecognized = FALSE;
+ PADXL345AccDevice pAccDevice = nullptr;
+
+ SENSOR_FunctionEnter();
+
+ // Get the sensor instance
+ ULONG SensorInstanceCount = 1;
+ SENSOROBJECT SensorInstance = NULL;
+ NTSTATUS Status = SensorsCxDeviceGetSensorList(WdfInterruptGetDevice(Interrupt), &SensorInstance, &SensorInstanceCount);
+ if (!NT_SUCCESS(Status) || 0 == SensorInstanceCount || NULL == SensorInstance)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ }
+
+ // Get the device context
+ else // if (NT_SUCCESS(Status))
+ {
+ pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! GetADXL345AccContextFromSensorInstance failed %!STATUS!", Status);
+ }
+ }
+
+ // Read the interrupt source
+ if (NT_SUCCESS(Status))
+ {
+ BYTE IntSrcBuffer = 0;
+ WdfWaitLockAcquire(pAccDevice->m_I2CWaitLock, NULL);
+ Status = I2CSensorReadRegister(pAccDevice->m_I2CIoTarget, ADXL345_INT_SOURCE, &IntSrcBuffer, sizeof(IntSrcBuffer));
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorReadRegister from 0x%02x failed! %!STATUS!", ADXL345_INT_SOURCE, Status);
+ }
+ else if ((IntSrcBuffer & ADXL345_INT_ACTIVITY) == 0)
+ {
+ TraceError("%!FUNC! Interrupt source not recognized");
+ }
+ else
+ {
+ InterruptRecognized = TRUE;
+ BOOLEAN WorkItemQueued = WdfInterruptQueueWorkItemForIsr(Interrupt);
+ TraceVerbose("%!FUNC! Work item %s queued for interrupt", WorkItemQueued ? "" : " already");
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return InterruptRecognized;
+}
+
+// Processes interrupt information that the driver's EvtInterruptIsr callback function has stored.
+VOID ADXL345AccDevice::OnInterruptWorkItem(
+ _In_ WDFINTERRUPT Interrupt, // Handle to a framework object
+ _In_ WDFOBJECT /*AssociatedObject*/) // A handle to the framework device object that
+ // the driver passed to WdfInterruptCreate.
+{
+ PADXL345AccDevice pAccDevice = nullptr;
+
+ SENSOR_FunctionEnter();
+
+ // Get the sensor instance
+ ULONG SensorInstanceCount = 1;
+ SENSOROBJECT SensorInstance = NULL;
+ NTSTATUS Status = SensorsCxDeviceGetSensorList(WdfInterruptGetDevice(Interrupt), &SensorInstance, &SensorInstanceCount);
+ if (!NT_SUCCESS(Status) || 0 == SensorInstanceCount || NULL == SensorInstance)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
+ }
+
+ // Get the device context
+ else //if (NT_SUCCESS(Status))
+ {
+ pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! GetADXL345AccContextFromSensorInstance failed %!STATUS!", Status);
+ }
+ }
+
+ // Read the device data
+ if (NT_SUCCESS(Status))
+ {
+ WdfInterruptAcquireLock(Interrupt);
+ Status = pAccDevice->GetData();
+ WdfInterruptReleaseLock(Interrupt);
+ if (!NT_SUCCESS(Status) && STATUS_DATA_NOT_ACCEPTED != Status)
+ {
+ TraceError("ACC %!FUNC! GetData failed %!STATUS!", Status);
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+}
+
+// Called by Sensor CLX to begin continously sampling the sensor.
+NTSTATUS ADXL345AccDevice::OnStart(
+ _In_ SENSOROBJECT SensorInstance) // Sensor device object
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Sensor(%08X) parameter is invalid %!STATUS!", (INT) SensorInstance, Status);
+ }
+ else if (!pAccDevice->m_PoweredOn)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Sensor is not powered on! %!STATUS!", Status);
+ }
+ else
+ {
+ WdfWaitLockAcquire(pAccDevice->m_I2CWaitLock, NULL);
+
+ // Set accelerometer to measurement mode
+ REGISTER_SETTING RegisterSetting = { ADXL345_POWER_CTL, ADXL345_POWER_CTL_MEASURE };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+
+ // Enable interrupts
+ else // if (NT_SUCCESS(Status))
+ {
+ RegisterSetting = { ADXL345_INT_ENABLE, ADXL345_INT_ACTIVITY };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ pAccDevice->m_FirstSample = true;
+ pAccDevice->m_Started = true;
+
+ InitPropVariantFromUInt32(SensorState_Active, &(pAccDevice->m_pSensorProperties->List[SENSOR_PROPERTY_STATE].Value));
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to stop continously sampling the sensor.
+NTSTATUS ADXL345AccDevice::OnStop(
+ _In_ SENSOROBJECT SensorInstance) // Sensor device object
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Sensor(%08X) parameter is invalid %!STATUS!", (INT)SensorInstance, Status);
+ }
+ else
+ {
+ pAccDevice->m_Started = false;
+
+ // Disable interrupts
+ REGISTER_SETTING RegisterSetting = { ADXL345_INT_ENABLE, 0 };
+ WdfWaitLockAcquire(pAccDevice->m_I2CWaitLock, NULL);
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ // Clear any stale interrupts
+ else
+ {
+ RegisterSetting = { ADXL345_INT_SOURCE, 0 };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorReadRegister from 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ }
+
+ // Set accelerometer to standby
+ RegisterSetting = { ADXL345_POWER_CTL, ADXL345_POWER_CTL_STANDBY };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ else
+ {
+ InitPropVariantFromUInt32(SensorState_Idle, &(pAccDevice->m_pSensorProperties->List[SENSOR_PROPERTY_STATE].Value));
+ }
+ }
+
+ 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.
+NTSTATUS ADXL345AccDevice::OnGetSupportedDataFields(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Inout_opt_ PSENSOR_PROPERTY_LIST pFields, // Pointer to a list of supported properties
+ _Out_ PULONG pSize) // Number of bytes for the list of supported properties
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = 0;
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else if (nullptr == pFields)
+ {
+ // Just return size
+ *pSize = pAccDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ else
+ {
+ if (pFields->AllocatedSizeInBytes < pAccDevice->m_pSupportedDataFields->AllocatedSizeInBytes)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACC %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ }
+ else
+ {
+ // Fill out data
+ Status = PropertiesListCopy(pFields, pAccDevice->m_pSupportedDataFields);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! PropertiesListCopy failed %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = pAccDevice->m_pSupportedDataFields->AllocatedSizeInBytes;
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get sensor properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS ADXL345AccDevice::OnGetProperties(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pProperties, // Pointer to a list of sensor properties
+ _Out_ PULONG pSize) // Number of bytes for the list of sensor properties
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = 0;
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pSensorProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pAccDevice->m_pSensorProperties))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACC %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ }
+ else
+ {
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pProperties, pAccDevice->m_pSensorProperties);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pSensorProperties);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get data field properties. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS ADXL345AccDevice::OnGetDataFieldProperties(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _In_ const PROPERTYKEY *pDataField, // Pointer to the propertykey of requested property
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pProperties, // Pointer to a list of sensor properties
+ _Out_ PULONG pSize) // Number of bytes for the list of sensor properties
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = 0;
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice || nullptr == pDataField)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else if (!IsEqualPropertyKey(*pDataField, pAccDevice->m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_X_G]) &&
+ !IsEqualPropertyKey(*pDataField, pAccDevice->m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_Y_G]) &&
+ !IsEqualPropertyKey(*pDataField, pAccDevice->m_pSupportedDataFields->List[SENSOR_DATA_ACCELERATION_Z_G]))
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ TraceError("ACC %!FUNC! ADXL345 does NOT have properties for this data field. Failed %!STATUS!", Status);
+ }
+ else if (nullptr == pProperties)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pDataFieldProperties);
+ }
+ else
+ {
+ if (pProperties->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pAccDevice->m_pDataFieldProperties))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACC %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ }
+ else
+ {
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pProperties, pAccDevice->m_pDataFieldProperties);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pDataFieldProperties);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get sampling rate of the sensor.
+NTSTATUS ADXL345AccDevice::OnGetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _Out_ PULONG pDataRateMs) // Sampling rate in milliseconds
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else if (nullptr == pDataRateMs)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else
+ {
+ *pDataRateMs = pAccDevice->m_Interval;
+ TraceInformation("%!FUNC! giving data rate %lu", *pDataRateMs);
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Return the rate that is just less than the desired report interval
+inline DATA_RATE _GetDataRateFromReportInterval(_In_ ULONG ReportInterval)
+{
+ DATA_RATE dataRate = ACCELEROMETER_SUPPORTED_DATA_RATES[0];
+
+ for (ULONG i = 0; i < ACCELEROMETER_SUPPORTED_DATA_RATES_COUNT; i++)
+ {
+ dataRate = ACCELEROMETER_SUPPORTED_DATA_RATES[i];
+ if (dataRate.DataRateInterval <= ReportInterval)
+ {
+ break;
+ }
+ }
+
+ return dataRate;
+}
+
+// Called by Sensor CLX to set sampling rate of the sensor.
+NTSTATUS ADXL345AccDevice::OnSetDataInterval(
+ _In_ SENSOROBJECT SensorInstance, // Sensor device object
+ _In_ ULONG DataRateMs) // Sampling rate in milliseconds
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ // Get the device context
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice || DataRateMs < ACCELEROMETER_MIN_REPORT_INTERVAL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else
+ {
+ pAccDevice->m_Interval = DataRateMs;
+ if (pAccDevice->m_Started)
+ {
+ pAccDevice->m_Started = false;
+
+ WdfWaitLockAcquire(pAccDevice->m_I2CWaitLock, NULL);
+
+ // Disable Interrupts
+ REGISTER_SETTING RegisterSetting = { ADXL345_INT_ENABLE, 0 };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ TraceError("ACC %!FUNC! Failed to disable interrupts. %!STATUS!", Status);
+ }
+
+ // Update data rate in HW
+ else // (if NT_SUCCESS(Status))
+ {
+ RegisterSetting = { ADXL345_BW_RATE, _GetDataRateFromReportInterval(DataRateMs).RateCode };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ }
+
+ // Re-enable Interrupts
+ if (NT_SUCCESS(Status))
+ {
+ pAccDevice->m_Started = true;
+ pAccDevice->m_FirstSample = true;
+
+ RegisterSetting = { ADXL345_INT_ENABLE, ADXL345_INT_ACTIVITY };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! Failed to re-enable interrupts. %!STATUS!", Status);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to get data thresholds. The typical usage is to call
+// this function once with buffer pointer as NULL to acquire the required size
+// for the buffer, allocate buffer, then call the function again to retrieve
+// sensor information.
+NTSTATUS ADXL345AccDevice::OnGetDataThresholds(
+ _In_ SENSOROBJECT SensorInstance, // Sensor Device Object
+ _Inout_opt_ PSENSOR_COLLECTION_LIST pThresholds, // Pointer to a list of sensor thresholds
+ _Out_ PULONG pSize) // Number of bytes for the list of sensor thresholds
+{
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ if (nullptr == pSize)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! pSize: Invalid parameter! %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = 0;
+
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Invalid parameters! %!STATUS!", Status);
+ }
+ else if (nullptr == pThresholds)
+ {
+ // Just return size
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pThresholds);
+ }
+ else
+ {
+ if (pThresholds->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pAccDevice->m_pThresholds))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ TraceError("ACC %!FUNC! Buffer is too small. Failed %!STATUS!", Status);
+ }
+ else
+ {
+ // Fill out all data
+ Status = CollectionsListCopyAndMarshall(pThresholds, pAccDevice->m_pThresholds);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status);
+ }
+ else
+ {
+ *pSize = CollectionsListGetMarshalledSize(pAccDevice->m_pThresholds);
+ }
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to set data thresholds.
+NTSTATUS ADXL345AccDevice::OnSetDataThresholds(
+ _In_ SENSOROBJECT SensorInstance, // Sensor Device Object
+ _In_ PSENSOR_COLLECTION_LIST pThresholds) // Pointer to a list of sensor thresholds
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ SENSOR_FunctionEnter();
+
+ PADXL345AccDevice pAccDevice = GetADXL345AccContextFromSensorInstance(SensorInstance);
+ if (nullptr == pAccDevice)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Sensor(%08X) parameter is invalid %!STATUS!", (INT) SensorInstance, Status);
+ }
+
+ else // if (NT_SUCCESS(Status))
+ {
+ for (ULONG i = 0; i < pThresholds->Count; i++)
+ {
+ Status = PropKeyFindKeySetPropVariant(pAccDevice->m_pThresholds, &(pThresholds->List[i].Key), true, &(pThresholds->List[i].Value));
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! Adxl345 does NOT have threshold for this data field. Failed %!STATUS!", Status);
+ break;
+ }
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = PropKeyFindKeyGetFloat(pAccDevice->m_pThresholds, &PKEY_SensorData_AccelerationX_Gs, &(pAccDevice->m_CachedThresholds.X));
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! PropKeyFindKeyGetFloat for X failed! %!STATUS!", Status);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = PropKeyFindKeyGetFloat(pAccDevice->m_pThresholds, &PKEY_SensorData_AccelerationY_Gs, &(pAccDevice->m_CachedThresholds.Y));
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! PropKeyFindKeyGetFloat for Y failed! %!STATUS!", Status);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = PropKeyFindKeyGetFloat(pAccDevice->m_pThresholds, &PKEY_SensorData_AccelerationZ_Gs, &(pAccDevice->m_CachedThresholds.Z));
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ TraceError("ACC %!FUNC! PropKeyFindKeyGetFloat for Z failed! %!STATUS!", Status);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // The accelerometer only supports a single value, so pick the smallest, i.e. most sensitive.
+ FLOAT MinThreshold = min(pAccDevice->m_CachedThresholds.X, min(pAccDevice->m_CachedThresholds.Y, pAccDevice->m_CachedThresholds.Z));
+ MinThreshold = max(MinThreshold, static_cast<FLOAT>(ACCELEROMETER_MIN_CHANGE_SENSITIVITY));
+
+ // Disable Interrupts
+ REGISTER_SETTING RegisterSetting = { ADXL345_INT_ENABLE, 0 };
+ WdfWaitLockAcquire(pAccDevice->m_I2CWaitLock, NULL);
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ TraceError("ACC %!FUNC! Failed to disable interrupts. %!STATUS!", Status);
+ }
+
+ // The threshold can only be set in increments, so round down to a more sensitive setting for hardware
+ else //if (NT_SUCCESS(Status))
+ {
+ BYTE NewThreshold = static_cast<BYTE>(MinThreshold / ACCELEROMETER_CHANGE_SENSITIVITY_RESOLUTION);
+ RegisterSetting = { ADXL345_THRESH_ACT, NewThreshold };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ if (!NT_SUCCESS(Status))
+ {
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ TraceError("ACC %!FUNC! I2CSensorWriteRegister to 0x%02x failed! %!STATUS!", RegisterSetting.Register, Status);
+ }
+ }
+
+ // Re-enable Interrupts
+ if (NT_SUCCESS(Status))
+ {
+ RegisterSetting = { ADXL345_INT_ENABLE, ADXL345_INT_ACTIVITY };
+ Status = I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, RegisterSetting.Register, &RegisterSetting.Value, sizeof(RegisterSetting.Value));
+ WdfWaitLockRelease(pAccDevice->m_I2CWaitLock);
+ if (!NT_SUCCESS(Status))
+ {
+ TraceError("ACC %!FUNC! Failed to re-enable interrupts. %!STATUS!", Status);
+ }
+ }
+ }
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+}
+
+// Called by Sensor CLX to handle IOCTLs that clx does not support
+NTSTATUS ADXL345AccDevice::OnIoControl(
+ _In_ SENSOROBJECT /*SensorInstance*/, // WDF queue object
+ _In_ WDFREQUEST /*Request*/, // WDF request object
+ _In_ size_t /*OutputBufferLength*/, // number of bytes to retrieve from output buffer
+ _In_ size_t /*InputBufferLength*/, // number of bytes to retrieve from input buffer
+ _In_ ULONG /*IoControlCode*/) // IOCTL control code
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+ SENSOR_FunctionEnter();
+
+ SENSOR_FunctionExit(Status);
+ return Status;
+} \ No newline at end of file