// Called by Sensor CLX to set sampling rate of the sensor. NTSTATUS CustomSensorDevice::OnSetDataInterval( _In_ SENSOROBJECT SensorInstance, // sensor device object _In_ ULONG DataRateMs // sampling rate in milliseconds ) { PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pDevice || Cstm_Default_MinDataInterval_Ms > DataRateMs) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT) SensorInstance, Status); goto Exit; } pDevice->m_Interval = DataRateMs; // reschedule sample to return as soon as possible if it's started if (FALSE != pDevice->m_Started) { pDevice->m_Started = FALSE; WdfTimerStop(pDevice->m_Timer, TRUE); pDevice->m_Started = TRUE; pDevice->m_FirstSample = TRUE; WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Cstm_Default_MinDataInterval_Ms)); } Exit: SENSOR_FunctionExit(Status); return Status; }
// Called by Sensor CLX to stop continously sampling the sensor. NTSTATUS ActivityDevice::OnStop(_In_ SENSOROBJECT sensorInstance) { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance); if (nullptr == pDevice) { status = STATUS_INVALID_PARAMETER; TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status); } else { // Stop sensing pDevice->m_Started = FALSE; WdfTimerStop(pDevice->m_Timer, TRUE); InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); // Stop simulation if (NULL != pDevice->m_SimulatorInstance) { PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr != pSimulator) { pSimulator->Stop(); } } } SENSOR_FunctionExit(status); return status; }
// Called by Sensor CLX to get sampling rate of the sensor. NTSTATUS CustomSensorDevice::OnGetDataInterval( _In_ SENSOROBJECT SensorInstance, // sensor device object _Out_ PULONG DataRateMs // sampling rate in milliseconds ) { PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT) SensorInstance, Status); goto Exit; } if (nullptr == DataRateMs) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! DataRateMs(%08X) parameter is invalid. Failed %!STATUS!", (INT)DataRateMs, Status); goto Exit; } *DataRateMs = pDevice->m_Interval; Exit: SENSOR_FunctionExit(Status); return Status; }
// This callback is called when the simulator wait time has expired and the simulator // is ready to switch to the next sample. The callback updates the sample index and // schedules the next wake up time. VOID HardwareSimulator::OnTimerExpire( _In_ WDFTIMER Timer) // WDF timer object { HardwareSimulator *pSimulator = nullptr; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); pSimulator = GetHardwareSimulatorContextFromInstance(WdfTimerGetParentObject(Timer)); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); } if (NT_SUCCESS(Status)) { // Increment the sample index, roll over if the index reach the end of the array WdfWaitLockAcquire(pSimulator->m_Lock, NULL); pSimulator->m_Index++; pSimulator->m_Index = pSimulator->m_Index % ARRAYSIZE(SimulatorData); WdfWaitLockRelease(pSimulator->m_Lock); WdfTimerStart(pSimulator->m_Timer, WDF_REL_TIMEOUT_IN_MS(SIMULATOR_HARDWARE_INTERVAL_MS)); } SENSOR_FunctionExit(Status); }
// Called by Sensor CLX to clear all history stored in the sensor. NTSTATUS ActivityDevice::OnClearHistory(_In_ SENSOROBJECT sensorInstance) { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance); if (nullptr == pDevice) { status = STATUS_INVALID_PARAMETER; TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status); } else { WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL); status = pDevice->ClearHistoryBuffer(); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! ClearHistoryBuffer Failed %!STATUS!", status); } WdfWaitLockRelease(pDevice->m_HistoryLock); } SENSOR_FunctionExit(status); return status; }
// This routine initializes the supported data fields NTSTATUS ActivityDevice::InitializeSupportedDataFields() { WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; const ULONG size = SENSOR_PROPERTY_LIST_SIZE(ACTIVITY_DATA_COUNT); NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = m_SensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, size, &memoryHandle, reinterpret_cast<PVOID*>(&m_pSupportedDataFields)); if (!NT_SUCCESS(status) || nullptr == m_pSupportedDataFields) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } else { SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, size); m_pSupportedDataFields->Count = ACTIVITY_DATA_COUNT; m_pSupportedDataFields->List[ACTIVITY_DATA_TIMESTAMP] = PKEY_SensorData_Timestamp; m_pSupportedDataFields->List[ACTIVITY_DATA_CURRENT_STATE] = PKEY_SensorData_CurrentActivityState; m_pSupportedDataFields->List[ACTIVITY_DATA_CURRENT_CONFIDENCE] = PKEY_SensorData_CurrentActivityStateConfidence_Percentage; } SENSOR_FunctionExit(status); return status; }
// Called by Sensor CLX to begin continously sampling the sensor. NTSTATUS CustomSensorDevice::OnStart( _In_ SENSOROBJECT SensorInstance // sensor device object ) { PHardwareSimulator pSimulator = nullptr; PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("PED %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT)SensorInstance, Status); } if (NT_SUCCESS(Status)) { // Get the simulator context pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); } } if (NT_SUCCESS(Status)) { // Start the simulator pSimulator->Start(); pDevice->m_FirstSample = TRUE; // Start polling pDevice->m_Started = TRUE; InitPropVariantFromUInt32(SensorState_Active, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); // Start the sample polling timer. // Note1: the WDF timer is only as precise as the system resolution allows it to be. // In the case of the CO2 sensor, the reporting interval is 200 milliseconds. The default // system resolution (15.6 milliseconds) is therefore fine enough to guarantee an accurate sample // reporting interval. Some sensors using a lower reporting interval may want to reduce the system // time resolution by calling into timeBeginPeriod() before starting the polling timer. // // Important consideration: calling into timeBeginPeriod() should be used with care as it has // an adverse on the system performance and power consumption. // // Note2: The polling timer is configured to allow for the first sample to be reported immediately. // Some hardware may want to delay the first sample report a little to account for hardware start time. WdfTimerStart(pDevice->m_Timer, 0); } SENSOR_FunctionExit(Status); return Status; }
// Called by Sensor CLX to begin keeping history NTSTATUS ActivityDevice::OnStartHistory(_In_ SENSOROBJECT sensorInstance) { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance); if (nullptr == pDevice) { status = STATUS_INVALID_PARAMETER; TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status); } else if (0 == pDevice->m_HistorySizeInRecords) { status = STATUS_NOT_SUPPORTED; TraceError("ACT %!FUNC! Sensor does not support History"); } else if (FALSE == pDevice->m_PoweredOn) { status = STATUS_DEVICE_NOT_READY; TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status); } else { // Start keeping history pDevice->m_HistoryStarted = TRUE; WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs)); } SENSOR_FunctionExit(status); return status; }
// This callback is called when interval wait time has expired and driver is ready // to collect new sample. The callback reads current value, compare value to threshold, // pushes it up to CLX framework, and schedule next wake up time. VOID ActivityDevice::OnTimerExpire(_In_ WDFTIMER timer) { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(timer)); if (nullptr == pDevice) { status = STATUS_INSUFFICIENT_RESOURCES; TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status); } else { // Get data and push to clx WdfWaitLockAcquire(pDevice->m_Lock, NULL); status = pDevice->GetData(); if (!NT_SUCCESS(status) && STATUS_DATA_NOT_ACCEPTED != status) { TraceError("ACT %!FUNC! GetAccData Failed %!STATUS!", status); } WdfWaitLockRelease(pDevice->m_Lock); // Schedule next wake up time if (Act_Default_MinDataInterval_Ms <= pDevice->m_Interval && FALSE != pDevice->m_PoweredOn && FALSE != pDevice->m_Started) { WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval)); } } SENSOR_FunctionExit(status); }
// UNSUPPORTED at this point of time NTSTATUS CustomSensorDevice::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_COLLECTION_LIST emptyList = {}; SENSOR_FunctionEnter(); if (nullptr == pSize) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! Invalid parameters! %!STATUS!", Status); goto Exit; } // Even though thresholds are not yet supported for custom sensors, // the minimum reported size must be that of an empty list for the // class extension to work properly emptyList.AllocatedSizeInBytes = sizeof(emptyList); *pSize = CollectionsListGetMarshalledSize(&emptyList); SENSOR_FunctionExit(Status); Exit: return Status; }
// This routine is called by the framework when the PnP manager sends an // IRP_MN_START_DEVICE request to the driver stack. This routine is // responsible for performing operations that are necessary to make the // driver's device operational (for e.g. mapping the hardware resources // into memory). NTSTATUS ActivityDevice::OnPrepareHardware( _In_ WDFDEVICE device, // Supplies a handle to the framework device object _In_ WDFCMRESLIST /*ResourcesRaw*/, // Supplies a handle to a collection of framework resource // objects. This collection identifies the raw (bus-relative) hardware // resources that have been assigned to the device. _In_ WDFCMRESLIST /*ResourcesTranslated*/) // Supplies a handle to a collection of framework // resource objects. This collection identifies the translated // (system-physical) hardware resources that have been assigned to the // device. The resources appear from the CPU's point of view. { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); // Create WDFOBJECT for the sensor WDF_OBJECT_ATTRIBUTES sensorAttributes = {}; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&sensorAttributes, ActivityDevice); // Register sensor instance with clx SENSOROBJECT sensorInstance = NULL; status = SensorsCxSensorCreate(device, &sensorAttributes, &sensorInstance); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! SensorsCxSensorCreate failed %!STATUS!", status); } else { PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance); if (nullptr == pDevice) { status = STATUS_INSUFFICIENT_RESOURCES; TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status); } else { // Fill out properties status = pDevice->Initialize(device, sensorInstance); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! Initialize device object failed %!STATUS!", status); } else { SENSOR_CONFIG sensorConfig = {}; SENSOR_CONFIG_INIT(&sensorConfig); sensorConfig.pEnumerationList = pDevice->m_pEnumerationProperties; status = SensorsCxSensorInitialize(sensorInstance, &sensorConfig); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! SensorsCxSensorInitialize failed %!STATUS!", status); } } } } 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 CustomSensorDevice::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 ) { PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pSize) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! pSize: Invalid parameter! %!STATUS!", Status); goto Exit; } *pSize = 0; if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! pDevice: Invalid parameter! %!STATUS!", Status); goto Exit; } if (nullptr == pProperties) { // Just return size *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties); } else { if (pProperties->AllocatedSizeInBytes < CollectionsListGetMarshalledSize(pDevice->m_pProperties)) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! Buffer is too small. Failed %!STATUS!", Status); goto Exit; } // Fill out all data Status = CollectionsListCopyAndMarshall(pProperties, pDevice->m_pProperties); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! CollectionsListCopyAndMarshall failed %!STATUS!", Status); goto Exit; } *pSize = CollectionsListGetMarshalledSize(pDevice->m_pProperties); } 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 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; }
// 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 CustomSensorDevice::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 ) { PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pSize) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! pSize: Invalid parameter! %!STATUS!", Status); goto Exit; } *pSize = 0; if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! pDevice: Invalid parameter! %!STATUS!", Status); goto Exit; } if (nullptr == pFields) { // Just return size *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes; } else { if (pFields->AllocatedSizeInBytes < pDevice->m_pSupportedDataFields->AllocatedSizeInBytes) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! Buffer is too small. Failed %!STATUS!", Status); goto Exit; } // Fill out data Status = PropertiesListCopy (pFields, pDevice->m_pSupportedDataFields); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! PropertiesListCopy failed %!STATUS!", Status); goto Exit; } *pSize = pDevice->m_pSupportedDataFields->AllocatedSizeInBytes; } Exit: SENSOR_FunctionExit(Status); return Status; }
// Internal routine to perform simulator initialization NTSTATUS HardwareSimulator::InitializeInternal( _In_ WDFOBJECT SimulatorInstance) // Instance of the WDF object for the simulator { NTSTATUS Status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES TimerAttributes = {}; WDF_TIMER_CONFIG TimerConfig = {}; SENSOR_FunctionEnter(); // Only initialize the simulator if it is in the "not initialized" state if (SimulatorState_NotInitialized == m_State) { // Create Lock Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock); if (!NT_SUCCESS(Status)) { m_Lock = NULL; TraceError("CSTM %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status); goto Exit; } // Create a timer object for simulation updates WDF_TIMER_CONFIG_INIT(&TimerConfig, HardwareSimulator::OnTimerExpire); WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); TimerAttributes.ParentObject = SimulatorInstance; TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer); if (!NT_SUCCESS(Status)) { m_Timer = NULL; TraceError("CSTM %!FUNC! WdfTimerCreate failed %!STATUS!", Status); goto Exit; } // Set the simulator state to "initialized" m_State = SimulatorState_Initialized; m_SimulatorInstance = SimulatorInstance; } Exit: if (!NT_SUCCESS(Status) && NULL != m_Lock) { WdfObjectDelete(m_Lock); m_Lock = NULL; } SENSOR_FunctionExit(Status); return Status; }
// Called by Sensor CLX to begin keeping history NTSTATUS PedometerDevice::OnStartHistory( _In_ SENSOROBJECT SensorInstance // Sensor device object ) { PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; PHardwareSimulator pSimulator = nullptr; SENSOR_FunctionEnter(); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status); goto Exit; } if (FALSE == pDevice->m_HistorySupported) { Status = STATUS_NOT_SUPPORTED; TraceError("PED %!FUNC! History is not supported by the HW"); goto Exit; } if (FALSE == pDevice->m_PoweredOn) { Status = STATUS_DEVICE_NOT_READY; TraceError("PED %!FUNC! Sensor is not powered on! %!STATUS!", Status); goto Exit; } pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } // Start the pedometer history Status = pSimulator->StartHistory(); if (!NT_SUCCESS(Status)) { TraceError("PED %!FUNC! Start History failed %!STATUS!", Status); } Exit: SENSOR_FunctionExit(Status); return Status; }
// Called by Sensor CLX to begin continuously sampling the sensor. NTSTATUS PedometerDevice::OnStart( _In_ SENSOROBJECT SensorInstance // Sensor device object ) { PHardwareSimulator pSimulator = nullptr; PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status); goto Exit; } // Get the simulator context pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); } if (NT_SUCCESS(Status)) { // Start the simulator pSimulator->Start(); pDevice->m_FirstSample = TRUE; // Start polling pDevice->m_Started = TRUE; InitPropVariantFromUInt32(SensorState_Active, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); // Start the sample polling timer. // // Note: The polling timer is configured to allow for the first sample to be reported immediately. // Some hardware may want to delay the first sample report a little to account for hardware start time. WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Pedometer_Default_MinDataInterval_Ms)); } Exit: SENSOR_FunctionExit(Status); return Status; }
// This callback is called when interval wait time has expired and driver is ready // to collect new sample. The callback 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); }
// This routine returns the current sample from the driver at the current m_Index location. // Returns one of the ABI::Windows::Devices::Sensors::SimpleOrientation enum values. ABI::Windows::Devices::Sensors::SimpleOrientation HardwareSimulator::GetOrientation() { ABI::Windows::Devices::Sensors::SimpleOrientation Sample = ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); WdfWaitLockAcquire(m_Lock, NULL); Sample = OrientationData[m_Index]; WdfWaitLockRelease(m_Lock); SENSOR_FunctionExit(Status); return Sample; }
// UNSUPPORTED at this point of time NTSTATUS CustomSensorDevice::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(); // Usupported at this point in time SENSOR_FunctionExit(Status); return Status; }
//------------------------------------------------------------------------------ // Function: OnDriverUnload // // This routine is called when the driver unloads. // // Arguments: // Driver: IN: driver object // // Return Value: // NTSTATUS code //------------------------------------------------------------------------------ VOID OnDriverUnload( _In_ WDFDRIVER Driver ) { SENSOR_FunctionEnter(); UNREFERENCED_PARAMETER(Driver); SENSOR_FunctionExit(STATUS_SUCCESS); WPP_CLEANUP(Driver); return; }
// This routine stops the simulator // Returns an NTSTATUS code NTSTATUS HardwareSimulator::Stop() { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (SimulatorState_Started == m_State) { WdfTimerStop(m_Timer, TRUE); m_State = SimulatorState_Initialized; } SENSOR_FunctionExit(status); return status; }
// This routine returns the current sample from the driver at the current m_Index // location FLOAT HardwareSimulator::GetSample() { FLOAT Sample = 0.0f; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); WdfWaitLockAcquire(m_Lock, NULL); Sample = SimulatorData[m_Index]; WdfWaitLockRelease(m_Lock); SENSOR_FunctionExit(Status); return Sample; }
// This routine starts the simulator // Returns an NTSTATUS code NTSTATUS HardwareSimulator::Start() { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (SimulatorState_Initialized == m_State) { WdfTimerStart(m_Timer, WDF_REL_TIMEOUT_IN_MS(HardwareSimulator_HardwareInterval)); m_State = SimulatorState_Started; } SENSOR_FunctionExit(status); return status; }
// Called by Sensor CLX to handle IOCTLs that clx does not support NTSTATUS CustomSensorDevice::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; }
// This routine is called when the driver unloads. VOID OnDriverUnload( _In_ WDFDRIVER Driver // Driver object ) { SENSOR_FunctionEnter(); SENSOR_FunctionExit(STATUS_SUCCESS); // WPP_CLEANUP doesn't actually use the Driver parameter // So we need to set it as unreferenced. UNREFERENCED_PARAMETER(Driver); WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); return; }
// Called by Sensor CLX to stop continously sampling the sensor. NTSTATUS CustomSensorDevice::OnStop( _In_ SENSOROBJECT SensorInstance // sensor device object ) { PHardwareSimulator pSimulator = nullptr; PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("CSTM %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT) SensorInstance, Status); } if (NT_SUCCESS(Status)) { // Stop polling pDevice->m_Started = FALSE; // Waiting for the callback to complete, then stopping the timer WdfTimerStop(pDevice->m_Timer, TRUE); InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); // Stop the simulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } pSimulator->Stop(); } Exit: SENSOR_FunctionExit(Status); return Status; }
//------------------------------------------------------------------------------ // Function: DriverEntry // // This routine is the driver initialization entry point. // // Arguments: // DriverObject: IN: Pointer to the driver object created by the I/O manager // RegistryPath: IN: Pointer to the driver specific registry key // // Return Value: // NTSTATUS code //------------------------------------------------------------------------------ NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { WDF_DRIVER_CONFIG DriverConfig; NTSTATUS Status = STATUS_SUCCESS; // // Initialize WPP Tracing // WPP_INIT_TRACING(DriverObject, NULL); SENSOR_FunctionEnter(); DriverConfig.DriverPoolTag = SENSORV2_POOL_TAG_COMBO; // // Initialize the driver configuration structure. // WDF_DRIVER_CONFIG_INIT(&DriverConfig, OnDeviceAdd); DriverConfig.EvtDriverUnload = OnDriverUnload; // // Create a framework driver object to represent our driver. // Status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &DriverConfig, WDF_NO_HANDLE); if (!NT_SUCCESS(Status)) { TraceError("COMBO %!FUNC! WdfDriverCreate failed: %!STATUS!", Status); goto Exit; } Exit: SENSOR_FunctionExit(Status); return Status; }
// This routine is invoked by the framework to program the device to goto // D0, which is the working state. The framework invokes callback every // time the hardware needs to be (re-)initialized. This includes after // IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE, // and IRP_MN_SET_POWER-D0. NTSTATUS PedometerDevice::OnD0Entry( _In_ WDFDEVICE Device, // Supplies a handle to the framework device object _In_ WDF_POWER_DEVICE_STATE /*PreviousState*/) // WDF_POWER_DEVICE_STATE-typed enumerator that identifies // the device power state that the device was in before this transition to D0 { PPedometerDevice pDevice; SENSOROBJECT SensorInstance = NULL; ULONG SensorInstanceCount = 1; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); // Get sensor instance Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount); if (!NT_SUCCESS(Status) || 0 == SensorInstanceCount || NULL == SensorInstance) { Status = STATUS_INVALID_PARAMETER; TraceError("PED %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status); goto Exit; } pDevice = GetPedometerContextFromSensorInstance(SensorInstance); if (nullptr == pDevice) { Status = STATUS_INVALID_PARAMETER; TraceError("PED %!FUNC! GetPedometerContextFromSensorInstance failed %!STATUS!", Status); goto Exit; } // // Power on sensor // pDevice->m_PoweredOn = TRUE; InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value)); Exit: SENSOR_FunctionExit(Status); return Status; }
// This routine initializes the data field properties NTSTATUS ActivityDevice::InitializeDataFieldProperties() { WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; const ULONG size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT); NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = m_SensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, size, &memoryHandle, reinterpret_cast<PVOID*>(&m_pDataFieldProperties)); if (!NT_SUCCESS(status) || nullptr == m_pDataFieldProperties) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } else { 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(ActivityFakeDevice_Confidence_Resolution, &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value)); m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum; InitPropVariantFromFloat(ActivityFakeDevice_Confidence_Minimum, &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value)); m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum; InitPropVariantFromFloat(ActivityFakeDevice_Confidence_Maximum, &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value)); } SENSOR_FunctionExit(status); return status; }