static int l_gettime(lua_State *L) { #if 0 union { FILETIME ft; ULONGLONG ull; } u = {0}; const double scale = 1.0e9; GetSystemTimePreciseAsFileTime(&u.ft); #elif 0 union { LARGE_INTEGER li; ULONGLONG ull; } u = {0}; const double scale = 1.0e7; NtQuerySystemTime(&u.li); #else union { FILETIME ft; ULONGLONG ull; } u = {0}; const double scale = 1.0e7; SYSTEMTIME st = {0}; GetSystemTime(&st); SystemTimeToFileTime(&st, &u.ft); #endif const double win32Epoch = ((double)u.ull)/scale; const double unixEpoch = win32Epoch - SEC_TO_UNIX_EPOCH; lua_pushnumber(L, (lua_Number)(unixEpoch)); return 1; }
// GetSystemTimeAsFileTime // Retrieves the current system date and time. The information is in Coordinated Universal Time (UTC) format. void getTimeAccuracy_GetSystemTimePreciseAsFileTime() { // FILETIME structure // Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). FILETIME start, finish; GetSystemTimePreciseAsFileTime(&start); do { GetSystemTimePreciseAsFileTime(&finish); } while (start.dwLowDateTime == finish.dwLowDateTime); unsigned _int64 startTime = (((unsigned _int64)start.dwHighDateTime) << 32) | (start.dwLowDateTime); unsigned _int64 finishTime = (((unsigned _int64)finish.dwHighDateTime) << 32) | (finish.dwLowDateTime); unsigned _int64 accuracy = finishTime - startTime; printf("TimeAccuracy_GetSystemTimePreciseAsFileTime: %I64d", accuracy); }
double getWallTime(void) { #if defined(_WIN32) FILETIME tm; ULARGE_INTEGER t; /* * Time is given in 100-nanosecond intervals. Crazy! * * See: * * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724397%28v=vs.85%29.aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/hh706895%28v=vs.85%29.aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx */ #if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8 GetSystemTimePreciseAsFileTime(&tm); #else GetSystemTimeAsFileTime(&tm); #endif t.LowPart = tm.dwLowDateTime; t.HighPart = tm.dwHighDateTime; return ((double) t.QuadPart) / 1e7; #else /* !defined(_WIN32) */ struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) return -1; return ((double) ts.tv_sec) + ((double) ts.tv_nsec) / 1e9; #endif }
//------------------------------------------------------------------------------ // 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 PrxDevice::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! PRX GetPerformanceTime %!STATUS!", Status); } m_SampleCount = 0; DataReady = TRUE; } else { // Compare the change of detection state, and only push the data back to // clx. This is usually done in HW. if (m_CachedData.Detected != m_LastSample.Detected) { DataReady = TRUE; } } if (DataReady != FALSE) { // update last sample m_LastSample = m_CachedData; // push to clx InitPropVariantFromBoolean(m_LastSample.Detected, &(m_pData->List[PRX_DATA_DETECT].Value)); InitPropVariantFromUInt32(m_LastSample.DistanceMillimeters, &(m_pData->List[PRX_DATA_DISTANCE].Value)); GetSystemTimePreciseAsFileTime(&TimeStamp); InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[PRX_DATA_TIMESTAMP].Value)); SensorsCxSensorDataReady(m_SensorInstance, m_pData); m_FirstSample = FALSE; } else { Status = STATUS_DATA_NOT_ACCEPTED; TraceInformation("COMBO %!FUNC! PRX Data did NOT meet the threshold"); } SENSOR_FunctionExit(Status); return Status; }
time_t getMicroseconds(){ FILETIME time; // TODO: See about replacing this with less precise version GetSystemTimePreciseAsFileTime(&time); ULARGE_INTEGER lTime; lTime.LowPart = time.dwLowDateTime; lTime.HighPart = time.dwHighDateTime; return (lTime.QuadPart / 10); }
// This callback is called when interval wait time has expired and driver is ready // to collect new sample. The callback stores activity data in history buffer, // and schedules next wake up time. VOID ActivityDevice::OnHistoryTimerExpire(_In_ WDFTIMER historyTimer) { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(historyTimer)); if (nullptr == pDevice) { status = STATUS_INSUFFICIENT_RESOURCES; TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status); } else { ActivitySample data = {}; if (NULL != pDevice->m_SimulatorInstance) { PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr != pSimulator) { status = pSimulator->GetSample(&data); } else { status = STATUS_INVALID_PARAMETER; } } GetSystemTimePreciseAsFileTime(&(data.Timestamp)); if (NT_SUCCESS(status)) { // Add data to the buffer WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL); status = pDevice->AddDataElementToHistoryBuffer(&data); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! AddDataElementToHistoryBuffer Failed %!STATUS!", status); } WdfWaitLockRelease(pDevice->m_HistoryLock); } // Schedule next wake up time if (FALSE != pDevice->m_HistoryStarted) { WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs)); } } SENSOR_FunctionExit(status); }
static mtime_t mdate_wall (void) { FILETIME ts; ULARGE_INTEGER s; #if (_WIN32_WINNT >= 0x0602) && !VLC_WINSTORE_APP GetSystemTimePreciseAsFileTime (&ts); #else GetSystemTimeAsFileTime (&ts); #endif s.LowPart = ts.dwLowDateTime; s.HighPart = ts.dwHighDateTime; /* hundreds of nanoseconds */ static_assert ((10000000 % CLOCK_FREQ) == 0, "Broken frequencies ratio"); return s.QuadPart / (10000000 / CLOCK_FREQ); }
// This routine is called by worker thread to read a single sample and push it back // to CLX. NTSTATUS CustomSensorDevice::GetData() { PHardwareSimulator pSimulator = nullptr; FILETIME TimeStamp = {}; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (FALSE != m_FirstSample) { Status = GetPerformanceTime(&m_StartTime); if (!NT_SUCCESS(Status)) { m_StartTime = 0; TraceError("CSTM %!FUNC! GetPerformanceTime %!STATUS!", Status); } } pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } // push to clx InitPropVariantFromFloat(pSimulator->GetSample(), &(m_pData->List[CSTM_DATA_CO2_LEVEL_PERCENT].Value)); GetSystemTimePreciseAsFileTime(&TimeStamp); InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[CSTM_DATA_TIMESTAMP].Value)); SensorsCxSensorDataReady(m_SensorInstance, m_pData); m_FirstSample = FALSE; Exit: SENSOR_FunctionExit(Status); return Status; }
// This routine initializes the sensor to its default properties NTSTATUS CustomSensorDevice::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; // Initialize the CO2 simulator HardwareSimulator::Initialize(Device, &m_SimulatorInstance); // Create Lock Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status); goto Exit; } // Create timer object for polling sensor samples WDF_TIMER_CONFIG_INIT(&TimerConfig, CustomSensorDevice::OnTimerExpire); WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); TimerAttributes.ParentObject = SensorInstance; TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!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_CUSTOM_SENSOR, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pEnumerationProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties) { TraceError("CSTM %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size); m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT; // The sensor type must be GUID_SensorType_Custom, the driver must also define and "vendor defined subtype" m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type; InitPropVariantFromCLSID(GUID_SensorType_Custom, &(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"CO2 based sample Custom sensor V2", &(m_pEnumerationProperties->List[SENSOR_MODEL].Value)); m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId; InitPropVariantFromCLSID(GUID_CustomSensorDevice_UniqueID, &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value)); m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category; InitPropVariantFromCLSID(GUID_SensorCategory_Other, &(m_pEnumerationProperties->List[SENSOR_CATEGORY].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 custom sensors // with the same vendor defined type exist on the system and // this sensor is the primary sensor m_pEnumerationProperties->List[SENSOR_VENDOR_DEFINED_TYPE].Key = DEVPKEY_Sensor_VendorDefinedSubType; InitPropVariantFromCLSID(GUID_CustomSensorDevice_VendorDefinedSubTypeID, &(m_pEnumerationProperties->List[SENSOR_VENDOR_DEFINED_TYPE].Value)); // Supported Data-Fields Size = SENSOR_PROPERTY_LIST_SIZE(CSTM_DATA_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_CUSTOM_SENSOR, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pSupportedDataFields)); if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields) { TraceError("CSTM %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size); m_pSupportedDataFields->Count = CSTM_DATA_COUNT; m_pSupportedDataFields->List[CSTM_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp; m_pSupportedDataFields->List[CSTM_DATA_CO2_LEVEL_PERCENT] = PKEY_CustomSensorSampleData_CO2Level; // Data Size = SENSOR_COLLECTION_LIST_SIZE(CSTM_DATA_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_CUSTOM_SENSOR, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pData)); if (!NT_SUCCESS(Status) || nullptr == m_pData) { TraceError("CSTM %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pData, Size); m_pData->Count = CSTM_DATA_COUNT; m_pData->List[CSTM_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp; GetSystemTimePreciseAsFileTime(&Time); InitPropVariantFromFileTime(&Time, &(m_pData->List[CSTM_DATA_TIMESTAMP].Value)); // Initialize the sample, at this point of time the sensor is not started yet, // So, initialize the sample to a default value m_pData->List[CSTM_DATA_CO2_LEVEL_PERCENT].Key = PKEY_CustomSensorSampleData_CO2Level; InitPropVariantFromFloat(CustomSensorDevice_Minimum_CO2Level, &(m_pData->List[CSTM_DATA_CO2_LEVEL_PERCENT].Value)); // Sensor Properties m_Interval = Cstm_Default_MinDataInterval_Ms; Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_CUSTOM_SENSOR, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pProperties) { TraceError("CSTM %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size); m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT; m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State; InitPropVariantFromUInt32(SensorState_Initializing, &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms; InitPropVariantFromUInt32(Cstm_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_Custom, &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value)); // Data filed properties 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_CUSTOM_SENSOR, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pDataFieldProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties) { TraceError("CSTM %!FUNC! 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((float)CustomSensorDevice_Resolution, &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value)); m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum; InitPropVariantFromFloat(CustomSensorDevice_Minimum_CO2Level, &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value)); m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum; InitPropVariantFromFloat(CustomSensorDevice_Maximum_CO2Level, &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value)); // Reset the FirstSample flag m_FirstSample = TRUE; Exit: SENSOR_FunctionExit(Status); return Status; }
//------------------------------------------------------------------------------ // 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 PrxDevice::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! PRX 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! PRX WdfTimerCreate failed %!STATUS!", Status); goto Exit; } } // // Sensor Enumeration Properties // { WDF_OBJECT_ATTRIBUTES MemoryAttributes; WDFMEMORY MemoryHandle = NULL; ULONG Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_PRX_ENUMERATION_PROPERTY_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_PROXIMITY, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pEnumerationProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties) { TraceError("COMBO %!FUNC! PRX WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size); m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT; m_pEnumerationProperties->Count = SENSOR_PRX_ENUMERATION_PROPERTY_COUNT; m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type; InitPropVariantFromCLSID(GUID_SensorType_Proximity, &(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"PRX", &(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_PrxDevice_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)); m_pEnumerationProperties->List[SENSOR_PROPERTY_PRX_TYPE].Key = DEVPKEY_Sensor_ProximityType; InitPropVariantFromUInt32(PROXIMITY_TYPE::ProximityType_HumanProximity, &(m_pEnumerationProperties->List[SENSOR_PROPERTY_PRX_TYPE].Value)); m_pEnumerationProperties->List[SENSOR_ISWAKECAPABLE].Key = PKEY_Sensor_WakeCapable; InitPropVariantFromBoolean(FALSE, &(m_pEnumerationProperties->List[SENSOR_ISWAKECAPABLE].Value)); } // // Supported Data-Fields // { WDF_OBJECT_ATTRIBUTES MemoryAttributes; WDFMEMORY MemoryHandle = NULL; ULONG Size = SENSOR_PROPERTY_LIST_SIZE(PRX_DATA_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_PROXIMITY, Size, &MemoryHandle, (PVOID*)&m_pSupportedDataFields); if (!NT_SUCCESS(Status) || m_pSupportedDataFields == nullptr) { TraceError("COMBO %!FUNC! PRX WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size); m_pSupportedDataFields->Count = PRX_DATA_COUNT; m_pSupportedDataFields->List[PRX_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp; m_pSupportedDataFields->List[PRX_DATA_DETECT] = PKEY_SensorData_ProximityDetection; m_pSupportedDataFields->List[PRX_DATA_DISTANCE] = PKEY_SensorData_ProximityDistanceMillimeters; } // // Data // { WDF_OBJECT_ATTRIBUTES MemoryAttributes; WDFMEMORY MemoryHandle = NULL; ULONG Size = SENSOR_COLLECTION_LIST_SIZE(PRX_DATA_COUNT); FILETIME Time = {}; MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_PROXIMITY, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pData)); if (!NT_SUCCESS(Status) || nullptr == m_pData) { TraceError("COMBO %!FUNC! PRX WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pData, Size); m_pData->Count = PRX_DATA_COUNT; m_pData->List[PRX_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp; GetSystemTimePreciseAsFileTime(&Time); InitPropVariantFromFileTime(&Time, &(m_pData->List[PRX_DATA_TIMESTAMP].Value)); m_pData->List[PRX_DATA_DETECT].Key = PKEY_SensorData_ProximityDetection; InitPropVariantFromBoolean(FALSE, &(m_pData->List[PRX_DATA_DETECT].Value)); m_pData->List[PRX_DATA_DISTANCE].Key = PKEY_SensorData_ProximityDistanceMillimeters; InitPropVariantFromUInt32(FALSE, &(m_pData->List[PRX_DATA_DISTANCE].Value)); m_CachedData.Detected = FALSE; m_CachedData.DistanceMillimeters = PrxDevice_Maximum_Millimeters; m_LastSample.Detected = FALSE; m_LastSample.DistanceMillimeters = PrxDevice_Maximum_Millimeters; } // // Sensor Properties // { WDF_OBJECT_ATTRIBUTES MemoryAttributes; WDFMEMORY MemoryHandle = NULL; ULONG Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTY_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_PROXIMITY, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pProperties) { TraceError("COMBO %!FUNC! PRX WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size); m_pProperties->Count = SENSOR_COMMON_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(Prx_MinDataInterval_Ms, &(m_pProperties->List[SENSOR_COMMON_PROPERTY_MIN_INTERVAL].Value)); m_IntervalMs = Prx_MinDataInterval_Ms; m_MinimumIntervalMs = Prx_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_Proximity, &(m_pProperties->List[SENSOR_COMMON_PROPERTY_TYPE].Value)); } // // Data field 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_PROXIMITY, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pDataFieldProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties) { TraceError("COMBO %!FUNC! PRX 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; InitPropVariantFromUInt32(PrxDevice_Resolution_Millimeters, &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value)); m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum; InitPropVariantFromUInt32(PrxDevice_Minimum_Millimeters, &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value)); m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum; InitPropVariantFromUInt32(PrxDevice_Maximum_Millimeters, &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value)); } // // Set default threshold // { WDF_OBJECT_ATTRIBUTES MemoryAttributes; WDFMEMORY MemoryHandle = NULL; ULONG Size = SENSOR_COLLECTION_LIST_SIZE(PRX_THRESHOLD_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSORV2_POOL_TAG_PROXIMITY, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pThresholds)); if (!NT_SUCCESS(Status) || nullptr == m_pThresholds) { TraceError("COMBO %!FUNC! PRX WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size); m_FirstSample = TRUE; } Exit: SENSOR_FunctionExit(Status); return Status; }
WORD TZF_Timestamp (wchar_t* const out) { SYSTEMTIME stLogTime; #if 0 // Check for Windows 8 / Server 2012 static bool __hasSystemTimePrecise = (LOBYTE (LOWORD (GetVersion ())) == 6 && HIBYTE (LOWORD (GetVersion ())) >= 2) || LOBYTE (LOWORD (GetVersion () > 6)); // More accurate timestamp is available on Windows 6.2+ if (__hasSystemTimePrecise) { FILETIME ftLogTime; GetSystemTimePreciseAsFileTime (&ftLogTime); FileTimeToSystemTime (&ftLogTime, &stLogTime); } else { #else GetLocalTime (&stLogTime); #endif //} wchar_t date [64] = { L'\0' }; wchar_t time [64] = { L'\0' }; GetDateFormat (LOCALE_INVARIANT,DATE_SHORTDATE, &stLogTime,NULL,date,64); GetTimeFormat (LOCALE_INVARIANT,TIME_NOTIMEMARKER,&stLogTime,NULL,time,64); out [0] = L'\0'; lstrcatW (out, date); lstrcatW (out, L" "); lstrcatW (out, time); lstrcatW (out, L"."); return stLogTime.wMilliseconds; } tzf_logger_t dll_log; void tzf_logger_t::close (void) { if (fLog != NULL) { fflush (fLog); fclose (fLog); } initialized = false; silent = true; DeleteCriticalSection (&log_mutex); } bool tzf_logger_t::init (const char* const szFileName, const char* const szMode) { if (initialized) return true; // // Split the path, so we can create the log directory if necessary // if (strstr (szFileName, "\\")) { char* szSplitPath = strdup (szFileName); // Replace all instances of '/' with '\' size_t len = strlen (szSplitPath); for (size_t i = 0; i < len; i++) { if (szSplitPath [i] == '/') szSplitPath [i] = '\\'; } char* szSplitter = strrchr (szSplitPath, '\\'); *szSplitter = '\0'; char path [MAX_PATH] = { '\0' }; char* subpath = strtok (szSplitPath, "\\"); // For each subdirectory, create it... while (subpath != nullptr) { strcat (path, subpath); CreateDirectoryA (path, NULL); strcat (path, "\\"); subpath = strtok (NULL, "\\"); } free (szSplitPath); } fLog = fopen (szFileName, szMode); BOOL bRet = InitializeCriticalSectionAndSpinCount (&log_mutex, 2500); if ((! bRet) || (fLog == NULL)) { silent = true; return false; } initialized = true; return initialized; } void tzf_logger_t::LogEx (bool _Timestamp, _In_z_ _Printf_format_string_ wchar_t const* const _Format, ...) { va_list _ArgList; if (! initialized) return; EnterCriticalSection (&log_mutex); if ((! fLog) || silent) { LeaveCriticalSection (&log_mutex); return; } if (_Timestamp) { wchar_t wszLogTime [128]; WORD ms = TZF_Timestamp (wszLogTime); fwprintf (fLog, L"%s%03u: ", wszLogTime, ms); } va_start (_ArgList, _Format); { vfwprintf (fLog, _Format, _ArgList); } va_end (_ArgList); fflush (fLog); LeaveCriticalSection (&log_mutex); }
/** * Returns the real time, in seconds, or -1.0 if an error occurred. * * Time is measured since an arbitrary and OS-dependent start time. * The returned real time is only useful for computing an elapsed time * between two calls to this function. */ double getRealTime( ) { #if defined(_WIN32) FILETIME tm; ULONGLONG t; #if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8 /* Windows 8, Windows Server 2012 and later. ---------------- */ GetSystemTimePreciseAsFileTime( &tm ); #else /* Windows 2000 and later. ---------------------------------- */ GetSystemTimeAsFileTime( &tm ); #endif t = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; return (double)t / 10000000.0; #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) /* HP-UX, Solaris. ------------------------------------------ */ return (double)gethrtime( ) / 1000000000.0; #elif defined(__MACH__) && defined(__APPLE__) /* OSX. ----------------------------------------------------- */ static double timeConvert = 0.0; if ( timeConvert == 0.0 ) { mach_timebase_info_data_t timeBase; (void)mach_timebase_info( &timeBase ); timeConvert = (double)timeBase.numer / (double)timeBase.denom / 1000000000.0; } return (double)mach_absolute_time( ) * timeConvert; #elif defined(_POSIX_VERSION) /* POSIX. --------------------------------------------------- */ #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) { struct timespec ts; #if defined(CLOCK_MONOTONIC_PRECISE) /* BSD. --------------------------------------------- */ const clockid_t id = CLOCK_MONOTONIC_PRECISE; #elif defined(CLOCK_MONOTONIC_RAW) /* Linux. ------------------------------------------- */ const clockid_t id = CLOCK_MONOTONIC_RAW; #elif defined(CLOCK_HIGHRES) /* Solaris. ----------------------------------------- */ const clockid_t id = CLOCK_HIGHRES; #elif defined(CLOCK_MONOTONIC) /* AIX, BSD, Linux, POSIX, Solaris. ----------------- */ const clockid_t id = CLOCK_MONOTONIC; #elif defined(CLOCK_REALTIME) /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ const clockid_t id = CLOCK_REALTIME; #else const clockid_t id = (clockid_t)-1;/* Unknown. */ #endif /* CLOCK_* */ if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; /* Fall thru. */ } #endif /* _POSIX_TIMERS */ /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ struct timeval tm; gettimeofday( &tm, NULL ); return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0; #else return -1.0;/* Failed. */ #endif }
// This routine is called by worker thread to read a single sample, compare threshold // and push it back to CLX. It simulates hardware thresholding by only generating data // when the change of data is greater than threshold. NTSTATUS ActivityDevice::GetData() { BOOLEAN dataReady = FALSE; NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (NULL != m_SimulatorInstance) { // Use simulator to get m_pFiltered Sample PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance); if (nullptr != pSimulator) { status = pSimulator->GetSample(m_pFilteredSample); } else { status = STATUS_INVALID_PARAMETER; } } if (NT_SUCCESS(status)) { status = CollectionsListSortSubscribedActivitiesByConfidence(m_pThresholds, m_pFilteredSample); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! CollectionsListSortSubscribedActivitiesByConfidence failed! %!STATUS!", status); } else { // new sample? if (FALSE != m_FirstSample) { dataReady = TRUE; } else { dataReady = EvaluateActivityThresholds(m_pFilteredSample, m_pLastSample, m_pThresholds); } } } if (FALSE != dataReady) { // update last sample FILETIME TimeStamp = {}; memcpy_s(m_pLastSample, m_pFilteredSample->AllocatedSizeInBytes, m_pFilteredSample, m_pFilteredSample->AllocatedSizeInBytes); GetSystemTimePreciseAsFileTime(&TimeStamp); InitPropVariantFromFileTime(&TimeStamp, &(m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Value)); // push to clx SensorsCxSensorDataReady(m_SensorInstance, m_pLastSample); m_FirstSample = FALSE; } else { status = STATUS_DATA_NOT_ACCEPTED; TraceInformation("ACT %!FUNC! Data did NOT meet the threshold"); } SENSOR_FunctionExit(status); return status; }
// This routine initializes the sensor to its default properties NTSTATUS PedometerDevice::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; ULONG HistorySizeInRecords = 0; SENSOR_FunctionEnter(); // Store device and instance m_FxDevice = Device; m_SensorInstance = SensorInstance; m_Started = FALSE; m_HistoryRetrievalStarted = FALSE; // Initialize the pedometer simulator Status = HardwareSimulator::Initialize(Device, &m_SimulatorInstance); if (!NT_SUCCESS(Status)) { TraceError("PED %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", Status); goto Exit; } pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } // Create Lock Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock); if (!NT_SUCCESS(Status)) { TraceError("PED %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status); goto Exit; } // Create timer object for polling sensor samples WDF_TIMER_CONFIG_INIT(&TimerConfig, PedometerDevice::OnTimerExpire); WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); TimerAttributes.ParentObject = SensorInstance; TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer); if (!NT_SUCCESS(Status)) { TraceError("PED %!FUNC! WdfTimerCreate failed %!STATUS!", Status); goto Exit; } // Supported Data-Fields Size = SENSOR_PROPERTY_LIST_SIZE(PEDOMETER_DATAFIELD_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSOR_POOL_TAG_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pSupportedDataFields)); if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields) { TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size); m_pSupportedDataFields->Count = PEDOMETER_DATAFIELD_COUNT; m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_TIMESTAMP] = PKEY_SensorData_Timestamp; m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_FIRST_AFTER_RESET] = PKEY_SensorData_PedometerReset; m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_TYPE] = PKEY_SensorData_PedometerStepType; m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_COUNT] = PKEY_SensorData_PedometerStepCount; m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_DURATION] = PKEY_SensorData_PedometerStepDuration_Ms; // Data Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_DATA_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSOR_POOL_TAG_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pData)); if (!NT_SUCCESS(Status) || nullptr == m_pData) { TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pData, Size); m_pData->Count = PEDOMETER_DATA_COUNT; m_pData->List[PEDOMETER_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp; GetSystemTimePreciseAsFileTime(&Time); InitPropVariantFromFileTime(&Time, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value)); m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Key = PKEY_SensorData_PedometerReset; InitPropVariantFromBoolean(FALSE, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value)); m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType; InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Unknown), &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value)); m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount; InitPropVariantFromUInt32(600, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value)); m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms; InitPropVariantFromInt64(123, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value)); m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType; InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Walking), &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value)); m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount; InitPropVariantFromUInt32(700, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value)); m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms; InitPropVariantFromInt64(456, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value)); m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType; InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Running), &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value)); m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount; InitPropVariantFromUInt32(800, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value)); m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms; InitPropVariantFromInt64(789, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value)); m_LastSample.Timestamp = Time; m_LastSample.UnknownStepCount = 0; m_LastSample.UnknownStepDurationMs = 0; m_LastSample.WalkingStepCount = 0; m_LastSample.WalkingStepDurationMs = 0; m_LastSample.RunningStepCount = 0; m_LastSample.RunningStepDurationMs = 0; m_LastSample.IsFirstAfterReset = FALSE; // Get the History Size to populate 'PKEY_SensorHistory_MaxSize_Bytes' // Typically the size needed to store a history record on the hardware is // smaller than the size needed to represent a history record as a // SENSOR_COLLECTION_LIST (collection of SENSOR_VALUE_PAIRs) // To be able to accurately represent the size of the history on the // hardware (simulator in this case), get the number of records that the HW // can store and multiply it with the marshalled size of // SENSOR_COLLECTION_LIST needed to represent a single record. HistorySizeInRecords = pSimulator->GetHistorySizeInRecords(); m_HistorySupported = (HistorySizeInRecords > 0) ? TRUE : FALSE; // Pedometer History format is exactly same as it's data sample. // so, we can simply reuse the 'm_pData' to compute the marshalled size // History Retrieval is not WOW64 compatible and hence will not involve // serializing the collections list. Should Use // CollectionsListGetMarshalledSizeWithoutSerialization instead of // CollectionsListGetMarshalledSize when dealing with History Collection list. m_HistoryMarshalledRecordSize = CollectionsListGetMarshalledSizeWithoutSerialization(m_pData); // 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_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pEnumerationProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties) { TraceError("PED %!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_Pedometer, &(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"PEDOMETER", &(m_pEnumerationProperties->List[SENSOR_MODEL].Value)); m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId; InitPropVariantFromCLSID(GUID_PedometerDevice_UniqueID, &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value)); m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category; InitPropVariantFromCLSID(GUID_SensorCategory_Motion, &(m_pEnumerationProperties->List[SENSOR_CATEGORY].Value)); m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary; InitPropVariantFromBoolean(FALSE, &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); // This value should be set to TRUE if multiple pedometers // exist on the system and this sensor is the primary sensor m_pEnumerationProperties->List[SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts; InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts, &(m_pEnumerationProperties->List[SENSOR_POWER].Value)); m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes; InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ? (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) : 0), &(m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Value)); m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes; InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running, &(m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Value)); // Sensor Properties m_Interval = Pedometer_Default_MinDataInterval_Ms; Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSOR_POOL_TAG_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pProperties) { TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size); m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT; m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State; InitPropVariantFromUInt32(SensorState_Initializing, &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms; InitPropVariantFromUInt32(Pedometer_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_Pedometer, &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value)); m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts; InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts, &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Value)); m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes; InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ? (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) : 0), &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Value)); m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Key = PKEY_SensorHistory_Interval_Ms; InitPropVariantFromUInt32(pSimulator->GetHistoryIntervalInMs(), &(m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Value)); m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Key = PKEY_SensorHistory_MaximumRecordSize_Bytes; InitPropVariantFromUInt32(m_HistoryMarshalledRecordSize, &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Value)); m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes; InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running, &(m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Value)); // Data field properties Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSOR_POOL_TAG_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pDataFieldProperties)); if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties) { TraceError("PED %!FUNC! 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; InitPropVariantFromInt64(PedometerDevice_StepCount_Resolution, &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value)); m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum; InitPropVariantFromUInt32(PedometerDevice_StepCount_Minimum, &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value)); m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum; InitPropVariantFromUInt32(PedometerDevice_StepCount_Maximum, &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value)); // Set default threshold m_FirstSample = TRUE; Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_THRESHOLD_COUNT); MemoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes); MemoryAttributes.ParentObject = SensorInstance; Status = WdfMemoryCreate(&MemoryAttributes, PagedPool, SENSOR_POOL_TAG_PEDOMETER, Size, &MemoryHandle, reinterpret_cast<PVOID*>(&m_pThresholds)); if (!NT_SUCCESS(Status) || nullptr == m_pThresholds) { TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status); goto Exit; } SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size); m_pThresholds->Count = PEDOMETER_THRESHOLD_COUNT; m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount; InitPropVariantFromUInt32(Pedometer_Default_Threshold_StepCount, &(m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Value)); m_CachedThreshold = Pedometer_Default_Threshold_StepCount; Exit: SENSOR_FunctionExit(Status); return Status; }