// 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; }
NTSTATUS EchoTimerCreate( IN WDFTIMER* Timer, IN WDFQUEUE Queue ) /*++ Routine Description: Subroutine to create timer. By associating the timerobject with the queue, we are basically telling the framework to serialize the queue callbacks with the timer callback. By doing so, we don't have to worry about protecting queue-context structure from multiple threads accessing it simultaneously. Arguments: Return Value: NTSTATUS --*/ { NTSTATUS Status; WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; // // Create a WDFTIMER object // WDF_TIMER_CONFIG_INIT(&timerConfig, EchoEvtTimerFunc); // // WDF_OBJECT_ATTRIBUTES_INIT sets AutomaticSerialization to TRUE by default // WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = Queue; // Synchronize with the I/O Queue timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; // // Create a non-periodic timer since WDF does not allow periodic timer // with autosynchronization at passive level // Status = WdfTimerCreate(&timerConfig, &timerAttributes, Timer // Output handle ); return Status; }
NTSTATUS EchoTimerCreate( IN WDFTIMER* Timer, IN ULONG Period, IN WDFQUEUE Queue ) /*++ Routine Description: Subroutine to create periodic timer. By associating the timerobject with the queue, we are basically telling the framework to serialize the queue callbacks with the dpc callback. By doing so, we don't have to worry about protecting queue-context structure from multiple threads accessing it simultaneously. Arguments: Return Value: NTSTATUS --*/ { NTSTATUS Status; WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; PAGED_CODE(); // // Create a WDFTIMER object // WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, EchoEvtTimerFunc, Period); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = Queue; // Synchronize with the I/O Queue Status = WdfTimerCreate(&timerConfig, &timerAttributes, Timer // Output handle ); return Status; }
NTSTATUS TpmEntropyInit(PTPM_CONTEXT TpmContext) { NTSTATUS status = STATUS_SUCCESS; #if _NT_TARGET_VERSION >= 0x601 // win7 WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; WDFTIMER timerHandle; PTPM_ENTROPY_TIMER_CONTEXT TimerContext; PAGED_CODE(); status = EntropyRegisterSource(&TpmContext->hEntropySource, ENTROPY_SOURCE_TYPE_TPM, CNG_ENTROPY_NAME); TpmContext->EntropyDensity = TpmGetEntropyDensity(); TpmContext->TimeOutSecond = 60000; timerConfig.TolerableDelay = 60000; TpmContext->bUseTimeOut = FALSE; TpmContext->PendingEntropy = FALSE; WDF_TIMER_CONFIG_INIT(&timerConfig, TpmEvtEntropyTimer); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes,TPM_ENTROPY_TIMER_CONTEXT); timerAttributes.ParentObject = TpmContext->Device; status = WdfTimerCreate( &timerConfig, &timerAttributes, &TpmContext->timerHandle ); if(NT_SUCCESS(status)) { TimerContext = GetTimerContext(TpmContext->timerHandle); TimerContext->TpmContext = TpmContext; } #endif return status; }
NTSTATUS BOOTTRACKPAD( _In_ PDEVICE_CONTEXT pDevice ) { NTSTATUS status = 0; static char bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static char bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; cyapa_boot_regs boot; FuncEntry(TRACE_FLAG_WDFLOADING); SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot)); if ((boot.stat & CYAPA_STAT_RUNNING) == 0) { if (boot.error & CYAPA_ERROR_BOOTLOADER) SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_deactivate, sizeof(bl_deactivate)); else SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_exit, sizeof(bl_exit)); } WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; WDF_OBJECT_ATTRIBUTES attributes; WDF_TIMER_CONFIG_INIT(&timerConfig, CyapaBootTimer); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = pDevice->FxDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(75)); FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS Ds4_AssignPdoContext(WDFDEVICE Device, PPDO_IDENTIFICATION_DESCRIPTION Description) { NTSTATUS status; PDS4_DEVICE_DATA ds4 = Ds4GetData(Device); KdPrint(("Initializing DS4 context...\n")); // I/O Queue for pending IRPs WDF_IO_QUEUE_CONFIG pendingUsbQueueConfig, notificationsQueueConfig; // Create and assign queue for incoming interrupt transfer WDF_IO_QUEUE_CONFIG_INIT(&pendingUsbQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(Device, &pendingUsbQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ds4->PendingUsbInRequests); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // Initialize periodic timer WDF_TIMER_CONFIG timerConfig; WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Ds4_PendingUsbRequestsTimerFunc, DS4_QUEUE_FLUSH_PERIOD); // Timer object attributes WDF_OBJECT_ATTRIBUTES timerAttribs; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); // PDO is parent timerAttribs.ParentObject = Device; // Create timer status = WdfTimerCreate(&timerConfig, &timerAttribs, &ds4->PendingUsbInRequestsTimer); if (!NT_SUCCESS(status)) { KdPrint(("WdfTimerCreate failed 0x%x\n", status)); return status; } // Create and assign queue for user-land notification requests WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ds4->PendingNotificationRequests); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // Load/generate MAC address // TODO: tidy up this region WDFKEY keyParams, keyTargets, keyDS, keySerial; UNICODE_STRING keyName, valueName; status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &keyParams); if (!NT_SUCCESS(status)) { KdPrint(("WdfDriverOpenParametersRegistryKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&keyName, L"Targets"); status = WdfRegistryCreateKey(keyParams, &keyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keyTargets); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&keyName, L"DualShock"); status = WdfRegistryCreateKey(keyTargets, &keyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keyDS); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } DECLARE_UNICODE_STRING_SIZE(serialPath, 4); RtlUnicodeStringPrintf(&serialPath, L"%04d", Description->SerialNo); status = WdfRegistryCreateKey(keyDS, &serialPath, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keySerial); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&valueName, L"TargetMacAddress"); status = WdfRegistryQueryValue(keySerial, &valueName, sizeof(MAC_ADDRESS), &ds4->TargetMacAddress, NULL, NULL); KdPrint(("MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n", ds4->TargetMacAddress.Vendor0, ds4->TargetMacAddress.Vendor1, ds4->TargetMacAddress.Vendor2, ds4->TargetMacAddress.Nic0, ds4->TargetMacAddress.Nic1, ds4->TargetMacAddress.Nic2)); if (status == STATUS_OBJECT_NAME_NOT_FOUND) { GenerateRandomMacAddress(&ds4->TargetMacAddress); status = WdfRegistryAssignValue(keySerial, &valueName, REG_BINARY, sizeof(MAC_ADDRESS), (PVOID)&ds4->TargetMacAddress); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryAssignValue failed 0x%x\n", status)); return status; } } else if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryQueryValue failed 0x%x\n", status)); return status; } WdfRegistryClose(keySerial); WdfRegistryClose(keyDS); WdfRegistryClose(keyTargets); WdfRegistryClose(keyParams); return STATUS_SUCCESS; }
//------------------------------------------------------------------------------ // 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; }
NTSTATUS OnDeviceAdd( _In_ WDFDRIVER FxDriver, _Inout_ PWDFDEVICE_INIT FxDeviceInit ) /*++ Routine Description: This routine creates the device object for an SPB controller and the device's child objects. Arguments: FxDriver - the WDF driver object handle FxDeviceInit - information about the PDO that we are loading on Return Value: Status --*/ { FuncEntry(TRACE_FLAG_WDFLOADING); PDEVICE_CONTEXT pDevice; WDFDEVICE fxDevice; WDF_INTERRUPT_CONFIG interruptConfig; NTSTATUS status; UNREFERENCED_PARAMETER(FxDriver); // // Tell framework this is a filter driver. Filter drivers by default are // not power policy owners. This works well for this driver because // HIDclass driver is the power policy owner for HID minidrivers. // WdfFdoInitSetFilter(FxDeviceInit); // // Setup PNP/Power callbacks. // { WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks); } // // Set request attributes. // { WDF_OBJECT_ATTRIBUTES attributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &attributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes); } // // Create the device. // { WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &FxDeviceInit, &deviceAttributes, &fxDevice); if (!NT_SUCCESS(status)) { CyapaPrint( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating WDFDEVICE - %!STATUS!", status); goto exit; } pDevice = GetDeviceContext(fxDevice); NT_ASSERT(pDevice != nullptr); pDevice->FxDevice = fxDevice; } // // Ensure device is disable-able // { WDF_DEVICE_STATE deviceState; WDF_DEVICE_STATE_INIT(&deviceState); deviceState.NotDisableable = WdfFalse; WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState); } // // Create queues to handle IO // { WDF_IO_QUEUE_CONFIG queueConfig; WDFQUEUE queue; // // Top-level queue // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDefault = OnTopLevelIoDefault; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS(status)) { CyapaPrint( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating top-level IO queue - %!STATUS!", status); goto exit; } // // Sequential SPB queue // WDF_IO_QUEUE_CONFIG_INIT( &queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoInternalDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( fxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->SpbQueue ); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto exit; } } WDF_IO_QUEUE_CONFIG queueConfig; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->ReportQueue ); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Queue 2!\n"); CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Create an interrupt object for hardware notifications // WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, OnInterruptIsr, NULL); interruptConfig.PassiveHandling = TRUE; status = WdfInterruptCreate( fxDevice, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->Interrupt); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Error creating WDF interrupt object - %!STATUS!", status); goto exit; } WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; WDF_OBJECT_ATTRIBUTES attributes; WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, CyapaTimerFunc, 10); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = fxDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); pDevice->Timer = hTimer; if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); return status; } CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Success! 0x%x\n", status); pDevice->DeviceMode = DEVICE_MODE_MOUSE; exit: FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS SerialCreateTimersAndDpcs( IN PSERIAL_DEVICE_EXTENSION pDevExt ) /*++ Routine Description: This function creates all the timers and DPC objects. All the objects are associated with the WDFDEVICE and the callbacks are serialized with the device callbacks. Also these objects will be deleted automatically when the device is deleted, so there is no need for the driver to explicitly delete the objects. Arguments: PDevExt - Pointer to the device extension for the device Return Value: return NTSTATUS --*/ { WDF_DPC_CONFIG dpcConfig; WDF_TIMER_CONFIG timerConfig; NTSTATUS status; WDF_OBJECT_ATTRIBUTES dpcAttributes; WDF_OBJECT_ATTRIBUTES timerAttributes; // // Initialize all the timers used to timeout operations. // // // This timer dpc is fired off if the timer for the total timeout // for the read expires. It will cause the current read to complete. // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialReadTimeout); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->ReadRequestTotalTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestTotalTimer) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if the timer for the interval timeout // expires. If no more characters have been read then the // dpc routine will cause the read to complete. However, if // more characters have been read then the dpc routine will // resubmit the timer. // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialIntervalReadTimeout); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->ReadRequestIntervalTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestIntervalTimer) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if the timer for the total timeout // for the write expires. It will queue a dpc routine that // will cause the current write to complete. // // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialWriteTimeout); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->WriteRequestTotalTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(WriteRequestTotalTimer) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if the transmit immediate char // character times out. The dpc routine will "grab" the // request from the isr and time it out. // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutImmediate); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->ImmediateTotalTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ImmediateTotalTimer) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if the timer used to "timeout" counting // the number of characters received after the Xoff ioctl is started // expired. // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutXoff); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->XoffCountTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(XoffCountTimer) failed [%#08lx]\n", status); return status; } // // This dpc is fired off when a timer expires (after one // character time), so that code can be invoked that will // check to see if we should lower the RTS line when // doing transmit toggling. // WDF_TIMER_CONFIG_INIT(&timerConfig, SerialInvokePerhapsLowerRTS); timerConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = pDevExt->WdfDevice; status = WdfTimerCreate(&timerConfig, &timerAttributes, &pDevExt->LowerRTSTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(LowerRTSTimer) failed [%#08lx]\n", status); return status; } // // Create a DPC to complete read requests. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWrite); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->CompleteWriteDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteWriteDpc) failed [%#08lx]\n", status); return status; } // // Create a DPC to complete read requests. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteRead); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->CompleteReadDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteReadDpc) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if a comm error occurs. It will // cancel all pending reads and writes. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCommError); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->CommErrorDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommErrorDpc) failed [%#08lx]\n", status); return status; } // // This dpc is fired off when the transmit immediate char // character is given to the hardware. It will simply complete // the request. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteImmediate); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->CompleteImmediateDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteImmediateDpc) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if an event occurs and there was // a request waiting on that event. A dpc routine will execute // that completes the request. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWait); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->CommWaitDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommWaitDpc) failed [%#08lx]\n", status); return status; } // // This dpc is fired off if the xoff counter actually runs down // to zero. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteXoff); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->XoffCountCompleteDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(XoffCountCompleteDpc) failed [%#08lx]\n", status); return status; } // // This dpc is fired off only from device level to start off // a timer that will queue a dpc to check if the RTS line // should be lowered when we are doing transmit toggling. // WDF_DPC_CONFIG_INIT(&dpcConfig, SerialStartTimerLowerRTS); dpcConfig.AutomaticSerialization = TRUE; WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); dpcAttributes.ParentObject = pDevExt->WdfDevice; status = WdfDpcCreate(&dpcConfig, &dpcAttributes, &pDevExt->StartTimerLowerRTSDpc); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(StartTimerLowerRTSDpc) failed [%#08lx]\n", status); return status; } return status; }
NTSTATUS HidFx2EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: HidFx2EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a WDF device object to represent a new instance of toaster device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE hDevice; PDEVICE_EXTENSION devContext = NULL; WDFQUEUE queue; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_TIMER_CONFIG timerConfig; WDFTIMER timerHandle; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "HidFx2EvtDeviceAdd called\n"); // // Tell framework this is a filter driver. Filter drivers by default are // not power policy owners. This works well for this driver because // HIDclass driver is the power policy owner for HID minidrivers. // WdfFdoInitSetFilter(DeviceInit); // // Initialize pnp-power callbacks, attributes and a context area for the device object. // // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // For usb devices, PrepareHardware callback is the to place select the // interface and configure the device. // pnpPowerCallbacks.EvtDevicePrepareHardware = HidFx2EvtDevicePrepareHardware; // // These two callbacks start and stop the wdfusb pipe continuous reader // as we go in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // // Create a framework device object.This call will in turn create // a WDM device object, attach to the lower stack, and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &attributes, &hDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed with status code 0x%x\n", status); return status; } devContext = GetDeviceContext(hDevice); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Register a manual I/O queue for handling Interrupt Message Read Requests. // This queue will be used for storing Requests that need to wait for an // interrupt to occur before they can be completed. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); // // This queue is used for requests that dont directly access the device. The // requests in this queue are serviced only when the device is in a fully // powered state and sends an interrupt. So we can use a non-power managed // queue to park the requests since we dont care whether the device is idle // or fully powered up. // queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->InterruptMsgQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Create a timer to handle debouncing of switchpack // WDF_TIMER_CONFIG_INIT( &timerConfig, HidFx2EvtTimerFunction ); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfTimerCreate( &timerConfig, &attributes, &timerHandle ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate failed status:0x%x\n", status); return status; } devContext->DebounceTimer = timerHandle; return status; }
//HidFx2EvtDeviceAdd is called by the framework in response to AddDevicecall from the PnP manager. //We create and initialize a WDF device object to represent a new instance of device. // NTSTATUS HidFx2EvtDeviceAdd(_In_ WDFDRIVER hDriver, _Inout_ PWDFDEVICE_INIT pDeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE hDevice; PDEVICE_EXTENSION pDevContext = NULL; WDFQUEUE hQueue; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; UNREFERENCED_PARAMETER(hDriver); PAGED_CODE(); TraceVerbose(DBG_PNP, "(%!FUNC!) Enter\n"); // Tell framework this is a filter driver. WdfFdoInitSetFilter(pDeviceInit); // Initialize pnp-power callbacks, attributes and a context area for the device object. WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // For usb devices, PrepareHardware callback is the to place select the interface and configure the device. pnpPowerCallbacks.EvtDevicePrepareHardware = HidFx2EvtDevicePrepareHardware; // These two callbacks start and stop the wdfusb pipe continuous reader as we go in and out of the D0-working state. pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // Create a framework device object.This call will in turn create a WDM device object, attach to the lower stack. status = WdfDeviceCreate(&pDeviceInit, &attributes, &hDevice); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfDeviceCreate failed with status code %!STATUS!\n", status); return status; } pDevContext = GetDeviceContext(hDevice); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue); if (!NT_SUCCESS (status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed 0x%x\n", status); return status; } // Register a manual I/O queue for handling Interrupt Message Read Requests. WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); // This queue is used for requests that dont directly access the device. // The requests in this queue are serviced only when the device is in a fully powered state and sends an interrupt. queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hInterruptMsgQueue); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed %!STATUS!\n", status); return status; } // Create a timer to handle debouncing of switchpack WDF_TIMER_CONFIG_INIT(&timerConfig, HidFx2EvtTimerFunction); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); return status; } pDevContext->hDebounceTimer = hTimer; TraceVerbose(DBG_PNP, "(%!FUNC!) Exit\n"); return status; }
// This routine initializes the sensor to its default properties NTSTATUS ActivityDevice::Initialize( _In_ WDFDEVICE device, // WDFDEVICE object _In_ SENSOROBJECT sensorInstance) // SENSOROBJECT for each sensor instance { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); // Initial configuration m_FxDevice = device; m_SensorInstance = sensorInstance; m_Interval = Act_Default_MinDataInterval_Ms; m_FirstSample = TRUE; m_Started = FALSE; m_HistorySizeInRecords = Act_Default_MaxHistoryEntries; m_HistoryPowerInuW = Act_Default_Power_uW; m_HistoryIntervalInMs = Act_Default_HistoryInterval_Ms; m_HistoryStarted = FALSE; m_HistoryRetrievalStarted = FALSE; m_History.FirstElemIndex = 0; m_History.LastElemIndex = 0; m_History.NumOfElems = 0; m_History.BufferLength = m_HistorySizeInRecords; m_hThread = NULL; // Initialize the activity simulator status = HardwareSimulator::Initialize(device, &m_SimulatorInstance); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", status); status = STATUS_SUCCESS; // Failed to set up simulator should not fail the driver } // Create Lock status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! WdfWaitLockCreate failed %!STATUS!", status); } // Create history lock if (NT_SUCCESS(status)) { status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_HistoryLock); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! WdfWaitLockCreate failed %!STATUS!", status); } } // Create timer object for polling sensor samples if (NT_SUCCESS(status)) { WDF_OBJECT_ATTRIBUTES timerAttributes = {}; WDF_TIMER_CONFIG timerConfig = {}; WDF_TIMER_CONFIG_INIT(&timerConfig, ActivityDevice::OnTimerExpire); WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = sensorInstance; timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_Timer); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! WdfTimerCreate failed %!STATUS!", status); } } // Create timer object for keeping history if (NT_SUCCESS(status)) { WDF_OBJECT_ATTRIBUTES timerAttributes = {}; WDF_TIMER_CONFIG timerConfig = {}; WDF_TIMER_CONFIG_INIT(&timerConfig, ActivityDevice::OnHistoryTimerExpire); WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = sensorInstance; timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_HistoryTimer); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! WdfTimerCreate for history failed %!STATUS!", status); } } // Last available data if (NT_SUCCESS(status)) { // Allocate a buffer for max state count. 7 States and 1 timestamp, each // state has activity and confidence. The actual size will be adjusted when // data is ready to be pushed to clx. const ULONG size = SENSOR_COLLECTION_LIST_SIZE(Act_Max_State_Count * 2 + 1); WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = sensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, size, &memoryHandle, reinterpret_cast<PVOID*>(&m_pLastSample)); if (!NT_SUCCESS(status) || nullptr == m_pLastSample) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } else { FILETIME time = {}; SENSOR_COLLECTION_LIST_INIT(m_pLastSample, size); m_pLastSample->Count = Act_Max_State_Count * 2 + 1; m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp; InitPropVariantFromFileTime(&time, &(m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Value)); for (ULONG Count = 1; Count < Act_Max_State_Count * 2 + 1; Count += 2) { m_pLastSample->List[Count].Key = PKEY_SensorData_CurrentActivityState; InitPropVariantFromUInt32(ActivityState_Stationary, &(m_pLastSample->List[Count].Value)); m_pLastSample->List[Count + 1].Key = PKEY_SensorData_CurrentActivityStateConfidence_Percentage; InitPropVariantFromUInt16(100, &(m_pLastSample->List[Count + 1].Value)); } } } // Filtered data if (NT_SUCCESS(status) && nullptr != m_pLastSample && 0 != m_pLastSample->AllocatedSizeInBytes) { WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = sensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, m_pLastSample->AllocatedSizeInBytes, &memoryHandle, reinterpret_cast<PVOID*>(&m_pFilteredSample)); if (!NT_SUCCESS(status) || nullptr == m_pFilteredSample) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } else { // It's safe to memcpy because there is no embedded pointer memcpy_s(m_pFilteredSample, m_pLastSample->AllocatedSizeInBytes, m_pLastSample, m_pLastSample->AllocatedSizeInBytes); } } // Get the Marshalled size for a single history record if (NT_SUCCESS(status)) { // Set the count to 3, as the History Record contains information about only // the most probable activity (unlike the Activity Data that can represent multiple activities) // { Timestamp, ActivityState, Confidence} m_pFilteredSample->Count = 3; // 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_pFilteredSample); } // Sensor Properties. This must be called after setting up m_pLastSample and m_HistoryMarshalledRecordSize if (NT_SUCCESS(status)) { status = InitializeSensorProperties(); } // Sensor Enumeration Properties. if (NT_SUCCESS(status)) { status = InitializeEnumerationProperties(); } // Supported Data-Fields if (NT_SUCCESS(status)) { status = InitializeSupportedDataFields(); } // Data field properties if (NT_SUCCESS(status)) { status = InitializeDataFieldProperties(); } // Set default threshold if (NT_SUCCESS(status)) { const ULONG size = SENSOR_COLLECTION_LIST_SIZE(ACTIVITY_THRESHOLD_COUNT); WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = sensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, size, &memoryHandle, reinterpret_cast<PVOID*>(&m_pThresholds)); if (!NT_SUCCESS(status) || nullptr == m_pThresholds) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } else { SENSOR_COLLECTION_LIST_INIT(m_pThresholds, size); m_pThresholds->Count = ACTIVITY_THRESHOLD_COUNT; m_pThresholds->List[ACTIVITY_THRESHOLD_SUBSCRIBED_STATES].Key = PKEY_SensorData_SubscribedActivityStates; InitPropVariantFromUInt32(Act_Default_SubscribedStates, &(m_pThresholds->List[ACTIVITY_THRESHOLD_SUBSCRIBED_STATES].Value)); m_pThresholds->List[ACTIVITY_THRESHOLD_STREAMING].Key = PKEY_SensorData_ActivityStream; InitPropVariantFromBoolean(Act_Default_Streaming, &(m_pThresholds->List[ACTIVITY_THRESHOLD_STREAMING].Value)); m_pThresholds->List[ACTIVITY_THRESHOLD_CONFIDENCE].Key = PKEY_SensorData_ConfidenceThreshold_Percentage; InitPropVariantFromUInt16(Act_Default_ConfidenceThreshold_Percentage, &(m_pThresholds->List[ACTIVITY_THRESHOLD_CONFIDENCE].Value)); } } // Initialize history buffer if (NT_SUCCESS(status)) { const ULONG size = sizeof(ActivitySample) * m_HistorySizeInRecords; WDF_OBJECT_ATTRIBUTES memoryAttributes = {}; WDFMEMORY memoryHandle = NULL; WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = sensorInstance; status = WdfMemoryCreate(&memoryAttributes, PagedPool, SENSOR_POOL_TAG_ACTIVITY, size, &memoryHandle, reinterpret_cast<PVOID*>(&(m_History.pData))); if (!NT_SUCCESS(status) || nullptr == m_History.pData) { TraceError("ACT %!FUNC! WdfMemoryCreate failed %!STATUS!", status); } } // Create event for signaling the history retrieval thread to exit if (NT_SUCCESS(status)) { m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (NULL == m_ExitEvent || INVALID_HANDLE_VALUE == m_ExitEvent) { status = STATUS_INSUFFICIENT_RESOURCES; TraceError("ACT %!FUNC! Failed to create an event %!STATUS!", status); } } SENSOR_FunctionExit(status); return status; }
/** * @brief Called by the framework when a new PDO has arrived that this driver manages. * The device in question is not operational at this point in time. * * @param[in] Driver handle to WDFDRIVER object created by DriverEntry() * @param[in,out] DeviceInit device init object provided by framework. * * @returns NTSTATUS value indicating success or failure. * */ NTSTATUS FdoEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) { UNREFERENCED_PARAMETER(Driver); WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, __FUNCTION__"\n"); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(DeviceInit, FALSE); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, USB_FDO_CONTEXT); attributes.EvtCleanupCallback = FdoEvtDeviceContextCleanup; // // Device state callbacks. // WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = FdoEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = FdoEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = FdoEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = FdoEvtDeviceD0EntryPostInterruptsEnabled; pnpPowerCallbacks.EvtDeviceD0Exit = FdoEvtDeviceD0Exit; pnpPowerCallbacks.EvtDeviceSurpriseRemoval = FdoEvtDeviceSurpriseRemoval; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // establish a request context // WDF_OBJECT_ATTRIBUTES requestAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttributes, FDO_REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes); // // static verifier seems to have a rule that the FDO must call // WdfFdoInitSetDefaultChildListConfig if any component in the driver has // dynamic child devices, and the roothub has one if it is not operating in // connect usb hub mode. // WDF_CHILD_LIST_CONFIG config; WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_INDENTIFICATION_DESCRIPTION), FdoEvtChildListCreateDevice); WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES); // // add a preprocess callback for QueryInterface to support multi-version USBDI intefaces // UCHAR MinorFunctionTable[1] = {IRP_MN_QUERY_INTERFACE}; status = WdfDeviceInitAssignWdmIrpPreprocessCallback( DeviceInit, FdoPreProcessQueryInterface, IRP_MJ_PNP, MinorFunctionTable, 1); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceInitAssignWdmIrpPreprocessCallback failed error %x\n", status); return status; } // // Add create/close handlers // WDF_OBJECT_ATTRIBUTES fileAttributes; WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes); fileAttributes.SynchronizationScope = WdfSynchronizationScopeNone; WDF_FILEOBJECT_CONFIG FileObjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &FileObjectConfig, FdoEvtDeviceFileCreate, FdoEvtFileClose, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig( DeviceInit, &FileObjectConfig, &fileAttributes); WDFDEVICE device; status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceCreate failed error %x\n", status); return status; } PUSB_FDO_CONTEXT fdoContext = DeviceGetFdoContext(device); RtlZeroMemory(fdoContext, sizeof(USB_FDO_CONTEXT)); fdoContext->WdfDevice = device; KeInitializeEvent(&fdoContext->resetCompleteEvent, SynchronizationEvent, FALSE); // // allocate the dpc request collection. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &fdoContext->RequestCollection); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionCreate failed\n"); return status; }; // // The FDO is the USB Controller, create a device interface for that. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceCreateDeviceInterface for device %p error %x\n", device, status); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfStringCreate(NULL, &attributes, &fdoContext->hcdsymlink); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfStringCreate for device %p error %x\n", device, status); return status; } status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, fdoContext->hcdsymlink); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfStringCreate for device %p error %x\n", device, status); return status; } // // Some of our resources are independent of the device state and // can be allocated/initialized here. // status = InitScratchpad(fdoContext); if (!NT_SUCCESS(status)) { return status; } // // Initialize the I/O Package and any Queues // status = FdoQueueInitialize(device); if (!NT_SUCCESS(status)) { return status; } // // --XT-- All of the WDF ISR and DPC setup code was removed // here. The DPC is now setup through the Xen interface in the // previous call. Note the event channel is setup but not active // until the backend is connected. // // // Allocate a watchdog timer for our Xen interface. // WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; WDF_TIMER_CONFIG_INIT( &timerConfig, FdoEvtTimerFunc); WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = device; timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfTimerCreate( &timerConfig, &timerAttributes, &fdoContext->WatchdogTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfTimerCreate error %x\n", status); return status; } // // Create a collection of work items. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &fdoContext->FreeWorkItems); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionCreate error %x\n", status); return status; } for (ULONG index = 0; index < INIT_WORK_ITEM_COUNT; index++) { WDFWORKITEM workitem = NewWorkItem(fdoContext, NULL, 0,0,0,0); if (workitem) { status = WdfCollectionAdd(fdoContext->FreeWorkItems, workitem); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionAdd for workitem index %d error %x\n", index, status); WdfObjectDelete(workitem); return status; } } } PNP_BUS_INFORMATION busInformation; busInformation.BusNumber = 0; busInformation.BusTypeGuid = GUID_BUS_TYPE_USB; busInformation.LegacyBusType = PNPBus; WdfDeviceSetBusInformationForChildren( device, &busInformation); if (NT_SUCCESS(status)) { status = LateSetup(device); } 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; }
// 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; }
NTSTATUS Toastmon_OpenDevice( WDFDEVICE Device, PUNICODE_STRING SymbolicLink, WDFIOTARGET *Target ) /*++ Routine Description: Open the I/O target and preallocate any resources required to communicate with the target device. Arguments: Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PTARGET_DEVICE_INFO targetDeviceInfo = NULL; WDF_IO_TARGET_OPEN_PARAMS openParams; WDFIOTARGET ioTarget; WDF_OBJECT_ATTRIBUTES attributes; PDEVICE_EXTENSION deviceExtension = GetDeviceExtension(Device); WDF_TIMER_CONFIG wdfTimerConfig; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TARGET_DEVICE_INFO); status = WdfIoTargetCreate(deviceExtension->WdfDevice, &attributes, &ioTarget); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoTargetCreate failed 0x%x\n", status)); return status; } targetDeviceInfo = GetTargetDeviceInfo(ioTarget); targetDeviceInfo->DeviceExtension = deviceExtension; // // Warning: It's not recommended to open the targetdevice // from a pnp notification callback routine, because if // the target device initiates any kind of PnP action as // a result of this open, the PnP manager could deadlock. // You should queue a workitem to do that. // For example, SWENUM devices in conjunction with KS // initiate an enumeration of a device when you do the // open on the device interface. // We can open the target device here because we know the // toaster function driver doesn't trigger any pnp action. // WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( &openParams, SymbolicLink, STANDARD_RIGHTS_ALL); openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; // // Framework provides default action for all of these if you don't register // these callbacks -it will close the handle to the target when the device is // being query-removed and reopen it if the query-remove fails. // In this sample, we use a periodic timers to post requests to the target. // So we need to register these callbacks so that we can start and stop // the timer when the state of the target device changes. Since we are // registering these callbacks, we are now responsbile for closing and // reopening the target. // openParams.EvtIoTargetQueryRemove = ToastMon_EvtIoTargetQueryRemove; openParams.EvtIoTargetRemoveCanceled = ToastMon_EvtIoTargetRemoveCanceled; openParams.EvtIoTargetRemoveComplete = ToastMon_EvtIoTargetRemoveComplete; status = WdfIoTargetOpen(ioTarget, &openParams); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoTargetOpen failed with status 0x%x\n", status)); WdfObjectDelete(ioTarget); return status; } KdPrint(("Target Device 0x%x, PDO 0x%x, Fileobject 0x%x, Filehandle 0x%x\n", WdfIoTargetWdmGetTargetDeviceObject(ioTarget), WdfIoTargetWdmGetTargetPhysicalDevice(ioTarget), WdfIoTargetWdmGetTargetFileObject(ioTarget), WdfIoTargetWdmGetTargetFileHandle(ioTarget))); // // Create two requests - one for read and one for write. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ioTarget; status = WdfRequestCreate(&attributes, ioTarget, &targetDeviceInfo->ReadRequest); if (!NT_SUCCESS(status)) { WdfObjectDelete(ioTarget); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ioTarget; status = WdfRequestCreate(&attributes, ioTarget, &targetDeviceInfo->WriteRequest); if (!NT_SUCCESS(status)) { WdfObjectDelete(ioTarget); return status; } // // Create a passive timer to post requests to the I/O target. // WDF_TIMER_CONFIG_INIT(&wdfTimerConfig, Toastmon_EvtTimerPostRequests); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TIMER_CONTEXT); // // Make IoTarget as parent of the timer to prevent the ioTarget // from deleted until the dpc has runto completion. // attributes.ParentObject = ioTarget; // // By specifying WdfExecutionLevelPassive the framework will invoke // the timer callback Toastmon_EvtTimerPostRequests at PASSIVE_LEVEL. // attributes.ExecutionLevel = WdfExecutionLevelPassive; // // Setting the AutomaticSerialization to FALSE prevents // WdfTimerCreate to fail if the parent device object's // execution level is set to WdfExecutionLevelPassive. // wdfTimerConfig.AutomaticSerialization = FALSE; status = WdfTimerCreate(&wdfTimerConfig, &attributes, &targetDeviceInfo->TimerForPostingRequests ); if(!NT_SUCCESS(status)) { KdPrint(("WdfTimerCreate failed 0x%x\n", status)); WdfObjectDelete(ioTarget); return status; } GetTimerContext(targetDeviceInfo->TimerForPostingRequests)->IoTarget = ioTarget; // // Start the passive timer. The first timer will be queued after 1ms interval and // after that it will be requeued in the timer callback function. // The value of 1 ms (lowest timer resoltion allowed on NT) is chosen here so // that timer would fire right away. // WdfTimerStart(targetDeviceInfo->TimerForPostingRequests, WDF_REL_TIMEOUT_IN_MS(1)); *Target = ioTarget; return status; }
VOID SimSensorAddReadRequest ( _In_ WDFDEVICE Device, _In_ WDFREQUEST ReadRequest ) /*++ Routine Description: Handles IOCTL_THERMAL_READ_TEMPERATURE. If the request can be satisfied, it is completed immediately. Else, adds request to pending request queue. Arguments: Device - Supplies a handle to the device that received the request. ReadRequest - Supplies a handle to the request. --*/ { ULONG BytesReturned; PREAD_REQUEST_CONTEXT Context; WDF_OBJECT_ATTRIBUTES ContextAttributes; PFDO_DATA DevExt; LARGE_INTEGER ExpirationTime; size_t Length; BOOLEAN LockHeld; PULONG RequestTemperature; NTSTATUS Status; ULONG Temperature; WDFTIMER Timer; WDF_OBJECT_ATTRIBUTES TimerAttributes; WDF_TIMER_CONFIG TimerConfig; PTHERMAL_WAIT_READ ThermalWaitRead; DebugEnter(); PAGED_CODE(); DevExt = GetDeviceExtension(Device); BytesReturned = 0; LockHeld = FALSE; Status = WdfRequestRetrieveInputBuffer(ReadRequest, sizeof(THERMAL_WAIT_READ), &ThermalWaitRead, &Length); if (!NT_SUCCESS(Status) || Length != sizeof(THERMAL_WAIT_READ)) { // // This request is malformed, bail. // WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } if (ThermalWaitRead->Timeout != -1 /* INFINITE */ ) { // // Estimate the system time this request will expire at. // KeQuerySystemTime(&ExpirationTime); ExpirationTime.QuadPart += ThermalWaitRead->Timeout * 10000; } else { // // Value which indicates the request never expires. // ExpirationTime.QuadPart = -1LL /* INFINITE */; } // // Handle the immediate timeout case in the fast path. // Temperature = SimSensorReadVirtualTemperature(Device); if (SimSensorAreConstraintsSatisfied(Temperature, ThermalWaitRead->LowTemperature, ThermalWaitRead->HighTemperature, ExpirationTime)) { Status = WdfRequestRetrieveOutputBuffer(ReadRequest, sizeof(ULONG), &RequestTemperature, &Length); if(NT_SUCCESS(Status) && Length == sizeof(ULONG)) { *RequestTemperature = Temperature; BytesReturned = sizeof(ULONG); } else { Status = STATUS_INVALID_PARAMETER; DebugPrint(SIMSENSOR_ERROR, "WdfRequestRetrieveOutputBuffer() Failed. 0x%x", Status); } WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); } else { WdfWaitLockAcquire(DevExt->QueueLock, NULL); LockHeld = TRUE; // // Create a context to store request-specific information. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, READ_REQUEST_CONTEXT); Status = WdfObjectAllocateContext(ReadRequest, &ContextAttributes, &Context); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfObjectAllocateContext() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } Context->ExpirationTime.QuadPart = ExpirationTime.QuadPart; Context->LowTemperature = ThermalWaitRead->LowTemperature; Context->HighTemperature = ThermalWaitRead->HighTemperature; if(Context->ExpirationTime.QuadPart != -1LL /* INFINITE */ ) { // // This request eventually expires, create a timer to complete it. // WDF_TIMER_CONFIG_INIT(&TimerConfig, SimSensorExpiredRequestTimer); WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; TimerAttributes.SynchronizationScope = WdfSynchronizationScopeNone; TimerAttributes.ParentObject = Device; Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &Timer); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfTimerCreate() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } WdfTimerStart(Timer, WDF_REL_TIMEOUT_IN_MS(ThermalWaitRead->Timeout)); } Status = WdfRequestForwardToIoQueue(ReadRequest, DevExt->PendingRequestQueue); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfRequestForwardToIoQueue() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } // // Force a rescan of the queue to update the interrupt thresholds. // SimSensorScanPendingQueue(Device); } AddReadRequestEnd: if(LockHeld == TRUE) { WdfWaitLockRelease(DevExt->QueueLock); } DebugExitStatus(Status); }