diff options
Diffstat (limited to 'sensors/SensorsComboDriver/AlsClient.cpp')
| -rw-r--r-- | sensors/SensorsComboDriver/AlsClient.cpp | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/sensors/SensorsComboDriver/AlsClient.cpp b/sensors/SensorsComboDriver/AlsClient.cpp new file mode 100644 index 00000000..eb7080a2 --- /dev/null +++ b/sensors/SensorsComboDriver/AlsClient.cpp @@ -0,0 +1,639 @@ +// Copyright (C) Microsoft Corporation, All Rights Reserved. +// +// Abstract: +// +// This module contains the implementation of sensor specific functions. +// +// Environment: +// +// Windows User-Mode Driver Framework (WUDF) + +#include "Clients.h" + +#include "AlsClient.tmh" + +#define SENSORV2_POOL_TAG_AMBIENT_LIGHT '2LmA' + +#define Als_Initial_MinDataInterval_Ms (10) // 100Hz +#define Als_Initial_Lux_Threshold_Pct (1.0f) // Percent threshold: 100% +#define Als_Initial_Lux_Threshold_Abs (0.0f) // Absolute threshold: 0 lux +#define Als_Initial_Kelvin_Threshold_Abs (100.0f) // Absolute threshold: 100 Kelvins +#define Als_Initial_Chromaticity_X_Threshold_Abs (0.01f) // Absolute threshold: 0.01 of a CIE 1931 chromaticity x coordinate +#define Als_Initial_Chromaticity_Y_Threshold_Abs (0.01f) // Absolute threshold: 0.01 of a CIE 1931 chromaticity y coordinate + +#define AlsDevice_Minimum_Lux (-4.0f) +#define AlsDevice_Maximum_Lux (4.0f) +#define AlsDevice_Precision (65536.0f) // 65536 = 2^16, 16 bit data +#define AlsDevice_Range_Lux (AlsDevice_Maximum_Lux - AlsDevice_Minimum_Lux) +#define AlsDevice_Resolution_Lux (AlsDevice_Range_Lux / AlsDevice_Precision) + +// Ambient Light Sensor Unique ID +// {2D2A4524-51E3-4E68-9B0F-5CAEDFB12C02} +DEFINE_GUID(GUID_AlsDevice_UniqueID, + 0x2d2a4524, 0x51e3, 0x4e68, 0x9b, 0xf, 0x5c, 0xae, 0xdf, 0xb1, 0x2c, 0x2); + +// Sensor data +typedef enum +{ + ALS_DATA_TIMESTAMP = 0, + ALS_DATA_LUX, + ALS_DATA_KELVINS, + ALS_DATA_CHROMATICITY_X, + ALS_DATA_CHROMATICITY_Y, + ALS_DATA_ISVALID, + ALS_DATA_COUNT +} ALS_DATA_INDEX; + +// Sensor thresholds +typedef enum +{ + ALS_THRESHOLD_LUX_PCT = 0, + ALS_THRESHOLD_LUX_ABS, + ALS_THRESHOLD_KELVINS_ABS, + ALS_THRESHOLD_CHROMATICITY_X_ABS, + ALS_THRESHOLD_CHROMATICITY_Y_ABS, + ALS_THRESHOLD_COUNT +} ALS_THRESHOLD_INDEX; + +// +// Sensor Enumeration Properties +// + +typedef enum +{ + SENSOR_ALS_AUTOBRIGHTNESS_PREFERRED = SENSOR_ENUMERATION_PROPERTIES_COUNT, // SENSOR_ALS_ENUMERATION_PROPERTIES_INDEX is adding properties to the base SENSOR_ENUMERATION_PROPERTIES_COUNT enum. + SENSOR_ALS_COLOR_CAPABLE, // In order to keep the SENSOR_ALS_ENUMERATION_PROPERTIES_INDEX enum indexing coherent with the SENSOR_ENUMERATION_PROPERTIES_INDEX enum, + // set SENSOR_ALS_AUTOBRIGHTNESS_PREFERRED to the index of the last value in the SENSOR_ENUMERATION_PROPERTIES_INDEX enum + SENSOR_ALS_ENUMERATION_PROPERTIES_COUNT +} SENSOR_ALS_ENUMERATION_PROPERTIES_INDEX; + +typedef enum +{ + SENSOR_PROPERTY_ALS_RESPONSE_CURVE = SENSOR_COMMON_PROPERTY_COUNT, // SENSOR_ALS_PROPERTIES_INDEX is adding SENSOR_PROPERTY_ALS_RESPONSE_CURVE to the base SENSOR_COMMON_PROPERTIES_INDEX enum. + // In order to keep the SENSOR_ALS_PROPERTIES_INDEX enum indexing coherent with the SENSOR_COMMON_PROPERTIES_INDEX enum, + // set SENSOR_PROPERTY_ALS_RESPONSE_CURVE to the index of the last value in the SENSOR_COMMON_PROPERTIES_INDEX enum + SENSOR_ALS_PROPERTY_COUNT +} SENSOR_ALS_PROPERTIES_INDEX; + +//------------------------------------------------------------------------------ +// Function: Initialize +// +// This routine initializes the sensor to its default properties +// +// Arguments: +// Device: IN: WDFDEVICE object +// SensorInstance: IN: SENSOROBJECT for each sensor instance +// +// Return Value: +// NTSTATUS code +//------------------------------------------------------------------------------ +NTSTATUS +AlsDevice::Initialize( + _In_ WDFDEVICE Device, + _In_ SENSOROBJECT SensorInstance + ) +{ + NTSTATUS Status = STATUS_SUCCESS; + + SENSOR_FunctionEnter(); + + // + // Store device and instance + // + m_Device = Device; + m_SensorInstance = SensorInstance; + m_Started = FALSE; + + // + // Create Lock + // + Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! ALS WdfWaitLockCreate failed %!STATUS!", Status); + goto Exit; + } + + // + // Create timer object for polling sensor samples + // + { + WDF_OBJECT_ATTRIBUTES TimerAttributes; + WDF_TIMER_CONFIG TimerConfig; + + WDF_TIMER_CONFIG_INIT(&TimerConfig, OnTimerExpire); + WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); + TimerAttributes.ParentObject = SensorInstance; + TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; + + Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! ALS WdfTimerCreate failed %!STATUS!", Status); + goto Exit; + } + } + + // + // Sensor Enumeration Properties + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ALS_ENUMERATION_PROPERTIES_COUNT); + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pEnumerationProperties); + if (!NT_SUCCESS(Status) || m_pEnumerationProperties == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size); + m_pEnumerationProperties->Count = SENSOR_ALS_ENUMERATION_PROPERTIES_COUNT; + + m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type; + InitPropVariantFromCLSID(GUID_SensorType_AmbientLight, + &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value)); + + m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer; + InitPropVariantFromString(L"Manufacturer name", + &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value)); + + m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model; + InitPropVariantFromString(L"ALS", + &(m_pEnumerationProperties->List[SENSOR_MODEL].Value)); + + m_pEnumerationProperties->List[SENSOR_CONNECTION_TYPE].Key = DEVPKEY_Sensor_ConnectionType; + // The DEVPKEY_Sensor_ConnectionType values match the SensorConnectionType enumeration + InitPropVariantFromUInt32(static_cast<ULONG>(SensorConnectionType::Integrated), + &(m_pEnumerationProperties->List[SENSOR_CONNECTION_TYPE].Value)); + + m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId; + InitPropVariantFromCLSID(GUID_AlsDevice_UniqueID, + &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value)); + + m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary; + InitPropVariantFromBoolean(TRUE, + &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); + + m_pEnumerationProperties->List[SENSOR_ALS_AUTOBRIGHTNESS_PREFERRED].Key = DEVPKEY_LightSensor_AutoBrightnessPreferred; + InitPropVariantFromBoolean(TRUE, + &(m_pEnumerationProperties->List[SENSOR_ALS_AUTOBRIGHTNESS_PREFERRED].Value)); + + m_pEnumerationProperties->List[SENSOR_ALS_COLOR_CAPABLE].Key = DEVPKEY_LightSensor_ColorCapable; + InitPropVariantFromBoolean(TRUE, + &(m_pEnumerationProperties->List[SENSOR_ALS_COLOR_CAPABLE].Value)); + } + + // + // Supported Data-Fields + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_PROPERTY_LIST_SIZE(ALS_DATA_COUNT); + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pSupportedDataFields); + if (!NT_SUCCESS(Status) || m_pSupportedDataFields == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size); + m_pSupportedDataFields->Count = ALS_DATA_COUNT; + + m_pSupportedDataFields->List[ALS_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp; + m_pSupportedDataFields->List[ALS_DATA_LUX] = PKEY_SensorData_LightLevel_Lux; + m_pSupportedDataFields->List[ALS_DATA_KELVINS] = PKEY_SensorData_LightTemperature_Kelvins; + m_pSupportedDataFields->List[ALS_DATA_CHROMATICITY_X] = PKEY_SensorData_LightChromaticityX; + m_pSupportedDataFields->List[ALS_DATA_CHROMATICITY_Y] = PKEY_SensorData_LightChromaticityY; + m_pSupportedDataFields->List[ALS_DATA_ISVALID] = PKEY_SensorData_IsValid; + } + + // + // Data + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_COLLECTION_LIST_SIZE(ALS_DATA_COUNT); + FILETIME Time = {0}; + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pData); + if (!NT_SUCCESS(Status) || m_pData == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_COLLECTION_LIST_INIT(m_pData, Size); + m_pData->Count = ALS_DATA_COUNT; + + m_pData->List[ALS_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp; + GetSystemTimePreciseAsFileTime(&Time); + InitPropVariantFromFileTime(&Time, &(m_pData->List[ALS_DATA_TIMESTAMP].Value)); + + m_pData->List[ALS_DATA_LUX].Key = PKEY_SensorData_LightLevel_Lux; + InitPropVariantFromFloat(0.0f, &(m_pData->List[ALS_DATA_LUX].Value)); + + m_pData->List[ALS_DATA_KELVINS].Key = PKEY_SensorData_LightTemperature_Kelvins; + InitPropVariantFromFloat(0.0f, &(m_pData->List[ALS_DATA_KELVINS].Value)); + + m_pData->List[ALS_DATA_CHROMATICITY_X].Key = PKEY_SensorData_LightChromaticityX; + InitPropVariantFromFloat(0.0f, &(m_pData->List[ALS_DATA_CHROMATICITY_X].Value)); + + m_pData->List[ALS_DATA_CHROMATICITY_Y].Key = PKEY_SensorData_LightChromaticityY; + InitPropVariantFromFloat(0.0f, &(m_pData->List[ALS_DATA_CHROMATICITY_Y].Value)); + + m_pData->List[ALS_DATA_ISVALID].Key = PKEY_SensorData_IsValid; + InitPropVariantFromBoolean(TRUE, &(m_pData->List[ALS_DATA_ISVALID].Value)); + + m_CachedData = { + 1.0f, // Lux + 1.0f, // Kelvins + 0.5f, // Chromaticity X + 0.5f, // Chromaticity Y + TRUE // IsValid + }; + + m_LastSample = { + 0.0f, // Lux + 0.0f, // Kelvins + 0.0f, // Chromaticity X + 0.0f, // Chromaticity Y + TRUE // IsValid + }; + } + + // + // Sensor Properties + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ALS_PROPERTY_COUNT); + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pProperties); + if (!NT_SUCCESS(Status) || m_pProperties == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size); + m_pProperties->Count = SENSOR_ALS_PROPERTY_COUNT; + + m_pProperties->List[SENSOR_COMMON_PROPERTY_STATE].Key = PKEY_Sensor_State; + InitPropVariantFromUInt32(SensorState_Initializing, + &(m_pProperties->List[SENSOR_COMMON_PROPERTY_STATE].Value)); + + m_pProperties->List[SENSOR_COMMON_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms; + InitPropVariantFromUInt32(Als_Initial_MinDataInterval_Ms, + &(m_pProperties->List[SENSOR_COMMON_PROPERTY_MIN_INTERVAL].Value)); + m_IntervalMs = Als_Initial_MinDataInterval_Ms; + m_MinimumIntervalMs = Als_Initial_MinDataInterval_Ms; + + m_pProperties->List[SENSOR_COMMON_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes; + InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pData), + &(m_pProperties->List[SENSOR_COMMON_PROPERTY_MAX_DATAFIELDSIZE].Value)); + + m_pProperties->List[SENSOR_COMMON_PROPERTY_TYPE].Key = PKEY_Sensor_Type; + InitPropVariantFromCLSID(GUID_SensorType_AmbientLight, + &(m_pProperties->List[SENSOR_COMMON_PROPERTY_TYPE].Value)); + + ULONG responseCurve[10] = {}; // Array to contain the response curve data. + + // **************************************************************************************** + // The response curve consists of an array of byte pairs. + // The first byte contains the percentage brightness offset to be applied to the display. + // The second byte contains the corresponding ambient light value (in LUX). + // **************************************************************************************** + // (0, 10) + responseCurve[0] = 0; responseCurve[1] = 10; + // (10, 40) + responseCurve[2] = 10; responseCurve[3] = 40; + // (40, 100) + responseCurve[4] = 40; responseCurve[5] = 100; + // (68, 400) + responseCurve[6] = 68; responseCurve[7] = 400; + // (90, 1000) + responseCurve[8] = 90; responseCurve[9] = 1000; + + m_pProperties->List[SENSOR_PROPERTY_ALS_RESPONSE_CURVE].Key = PKEY_LightSensor_ResponseCurve; + InitPropVariantFromUInt32Vector(responseCurve, + 10, + &(m_pProperties->List[SENSOR_PROPERTY_ALS_RESPONSE_CURVE].Value)); + } + + // + // Data filed properties + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT); + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pDataFieldProperties); + if (!NT_SUCCESS(Status) || m_pDataFieldProperties == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_COLLECTION_LIST_INIT(m_pDataFieldProperties, Size); + m_pDataFieldProperties->Count = SENSOR_DATA_FIELD_PROPERTY_COUNT; + + m_pDataFieldProperties->List[SENSOR_RESOLUTION].Key = PKEY_SensorDataField_Resolution; + InitPropVariantFromFloat(AlsDevice_Resolution_Lux, + &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value)); + + m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum; + InitPropVariantFromFloat(AlsDevice_Minimum_Lux, + &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value)); + + m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum; + InitPropVariantFromFloat(AlsDevice_Maximum_Lux, + &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value)); + } + + // + // Set default threshold + // + { + WDF_OBJECT_ATTRIBUTES MemoryAttributes; + WDFMEMORY MemoryHandle = NULL; + ULONG Size = SENSOR_COLLECTION_LIST_SIZE(ALS_THRESHOLD_COUNT); + + MemoryHandle = NULL; + WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); + MemoryAttributes.ParentObject = SensorInstance; + Status = WdfMemoryCreate(&MemoryAttributes, + PagedPool, + SENSORV2_POOL_TAG_AMBIENT_LIGHT, + Size, + &MemoryHandle, + (PVOID*)&m_pThresholds); + if (!NT_SUCCESS(Status) || m_pThresholds == nullptr) + { + TraceError("COMBO %!FUNC! ALS WdfMemoryCreate failed %!STATUS!", Status); + goto Exit; + } + + SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size); + m_pThresholds->Count = ALS_THRESHOLD_COUNT; + + // Set lux threshold + m_pThresholds->List[ALS_THRESHOLD_LUX_PCT].Key = PKEY_SensorData_LightLevel_Lux; + InitPropVariantFromFloat(Als_Initial_Lux_Threshold_Pct, + &(m_pThresholds->List[ALS_THRESHOLD_LUX_PCT].Value)); + m_CachedThresholds.LuxPct = Als_Initial_Lux_Threshold_Pct; + + m_pThresholds->List[ALS_THRESHOLD_LUX_ABS].Key = PKEY_SensorData_LightLevel_Lux_Threshold_AbsoluteDifference; + InitPropVariantFromFloat(Als_Initial_Lux_Threshold_Abs, + &(m_pThresholds->List[ALS_THRESHOLD_LUX_ABS].Value)); + m_CachedThresholds.LuxAbs = Als_Initial_Lux_Threshold_Abs; + + // Set kelvins threshold + m_pThresholds->List[ALS_THRESHOLD_KELVINS_ABS].Key = PKEY_SensorData_LightTemperature_Kelvins; + InitPropVariantFromFloat(Als_Initial_Kelvin_Threshold_Abs, + &(m_pThresholds->List[ALS_THRESHOLD_KELVINS_ABS].Value)); + m_CachedThresholds.KelvinsAbs = Als_Initial_Kelvin_Threshold_Abs; + + // Set chromaticity x threshold + m_pThresholds->List[ALS_THRESHOLD_CHROMATICITY_X_ABS].Key = PKEY_SensorData_LightChromaticityX; + InitPropVariantFromFloat(Als_Initial_Chromaticity_X_Threshold_Abs, + &(m_pThresholds->List[ALS_THRESHOLD_CHROMATICITY_X_ABS].Value)); + m_CachedThresholds.ChromaticityXAbs = Als_Initial_Chromaticity_X_Threshold_Abs; + + // Set chromaticity y threshold + m_pThresholds->List[ALS_THRESHOLD_CHROMATICITY_Y_ABS].Key = PKEY_SensorData_LightChromaticityY; + InitPropVariantFromFloat(Als_Initial_Chromaticity_Y_Threshold_Abs, + &(m_pThresholds->List[ALS_THRESHOLD_CHROMATICITY_Y_ABS].Value)); + m_CachedThresholds.ChromaticityYAbs = Als_Initial_Chromaticity_Y_Threshold_Abs; + + m_FirstSample = TRUE; + } + +Exit: + SENSOR_FunctionExit(Status); + return Status; +} + + + +//------------------------------------------------------------------------------ +// Function: GetData +// +// This routine is called by worker thread to read a single sample, compare threshold +// and push it back to CLX. It simulates hardware thresholding by only generating data +// when the change of data is greater than threshold. +// +// Arguments: +// None +// +// Return Value: +// NTSTATUS code +//------------------------------------------------------------------------------ +NTSTATUS +AlsDevice::GetData( + ) +{ + BOOLEAN DataReady = FALSE; + FILETIME TimeStamp = {0}; + NTSTATUS Status = STATUS_SUCCESS; + + SENSOR_FunctionEnter(); + + // new sample? + if (m_FirstSample != FALSE) + { + Status = GetPerformanceTime(&m_StartTime); + if (!NT_SUCCESS(Status)) + { + m_StartTime = 0; + TraceError("COMBO %!FUNC! ALS GetPerformanceTime %!STATUS!", Status); + } + + m_SampleCount = 0; + + DataReady = TRUE; + } + else + { + // Compare the change of data to threshold, and only push the data back to + // clx if the change exceeds threshold. This is usually done in HW. + if ( + ( + // Lux thresholds needs to exceed absolute and percentage + ((abs(m_CachedData.Lux - m_LastSample.Lux) >= (m_LastSample.Lux * m_CachedThresholds.LuxPct)) && + (abs(m_CachedData.Lux - m_LastSample.Lux) >= m_CachedThresholds.LuxAbs)) || + // If IsValid has changed, the sample is valid + (m_CachedData.IsValid != m_LastSample.IsValid) || + // Kelvin temperature and Chromaticity thresholds + (abs(m_CachedData.Kelvins - m_LastSample.Kelvins) >= m_CachedThresholds.KelvinsAbs) || + (abs(m_CachedData.ChromaticityX - m_LastSample.ChromaticityX) >= m_CachedThresholds.ChromaticityXAbs) || + (abs(m_CachedData.ChromaticityY - m_LastSample.ChromaticityY) >= m_CachedThresholds.ChromaticityYAbs) + ) + && + ( + // In thresholded mode, don't send sample if the last sample sent was not IsValid and current sample is also not IsValid + !((m_CachedThresholds.LuxAbs != 0.0f) && (m_CachedThresholds.LuxPct != 0.0f) && + (m_CachedThresholds.KelvinsAbs != 0.0f) && (m_CachedThresholds.ChromaticityXAbs != 0.0f) && + (m_CachedThresholds.ChromaticityYAbs != 0.0f) && !m_CachedData.IsValid && !m_LastSample.IsValid) + ) + ) + { + DataReady = TRUE; + } + } + + if (DataReady != FALSE) + { + // update last sample + m_LastSample = m_CachedData; + + // push to clx + InitPropVariantFromFloat(m_LastSample.Lux, &(m_pData->List[ALS_DATA_LUX].Value)); + + InitPropVariantFromFloat(m_LastSample.Kelvins, &(m_pData->List[ALS_DATA_KELVINS].Value)); + + InitPropVariantFromFloat(m_LastSample.ChromaticityX, &(m_pData->List[ALS_DATA_CHROMATICITY_X].Value)); + + InitPropVariantFromFloat(m_LastSample.ChromaticityY, &(m_pData->List[ALS_DATA_CHROMATICITY_Y].Value)); + + InitPropVariantFromBoolean(m_LastSample.IsValid, &(m_pData->List[ALS_DATA_ISVALID].Value)); + + GetSystemTimePreciseAsFileTime(&TimeStamp); + InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[ALS_DATA_TIMESTAMP].Value)); + + SensorsCxSensorDataReady(m_SensorInstance, m_pData); + m_FirstSample = FALSE; + } + else + { + Status = STATUS_DATA_NOT_ACCEPTED; + TraceInformation("COMBO %!FUNC! ALS Data did NOT meet the threshold"); + } + + SENSOR_FunctionExit(Status); + return Status; +} + + + +//------------------------------------------------------------------------------ +// Function: UpdateCachedThreshold +// +// This routine updates the cached threshold +// +// Arguments: +// None +// +// Return Value: +// NTSTATUS code +//------------------------------------------------------------------------------ +NTSTATUS +AlsDevice::UpdateCachedThreshold( + ) +{ + NTSTATUS Status = STATUS_SUCCESS; + + SENSOR_FunctionEnter(); + + Status = PropKeyFindKeyGetFloat(m_pThresholds, + &PKEY_SensorData_LightLevel_Lux, + &m_CachedThresholds.LuxPct); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! Failed to get lux pct data from cached threshold %!STATUS!", Status); + } + + if (NT_SUCCESS(Status)) + { + Status = PropKeyFindKeyGetFloat(m_pThresholds, + &PKEY_SensorData_LightLevel_Lux_Threshold_AbsoluteDifference, + &m_CachedThresholds.LuxAbs); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! Failed to get lux abs data from cached threshold %!STATUS!", Status); + } + } + + if (NT_SUCCESS(Status)) + { + Status = PropKeyFindKeyGetFloat(m_pThresholds, + &PKEY_SensorData_LightTemperature_Kelvins, + &m_CachedThresholds.KelvinsAbs); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! Failed to get kelvin data from cached threshold %!STATUS!", Status); + } + } + + if (NT_SUCCESS(Status)) + { + Status = PropKeyFindKeyGetFloat(m_pThresholds, + &PKEY_SensorData_LightChromaticityX, + &m_CachedThresholds.ChromaticityXAbs); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! Failed to get chromaticity x data from cached threshold %!STATUS!", Status); + } + } + + if (NT_SUCCESS(Status)) + { + Status = PropKeyFindKeyGetFloat(m_pThresholds, + &PKEY_SensorData_LightChromaticityY, + &m_CachedThresholds.ChromaticityYAbs); + if (!NT_SUCCESS(Status)) + { + TraceError("COMBO %!FUNC! Failed to get chromaticity y data from cached threshold %!STATUS!", Status); + } + } + + SENSOR_FunctionExit(Status); + return Status; +}
\ No newline at end of file |
