コード例 #1
0
// 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;
}
コード例 #2
0
ファイル: queue.c プロジェクト: 340211173/Driver
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;
}
コード例 #3
0
ファイル: queue.c プロジェクト: 0xhack/Windows-driver-samples
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;
}
コード例 #4
0
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;
}
コード例 #5
0
ファイル: device.cpp プロジェクト: coolstar/crostrackpad3
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;
}
コード例 #6
0
ファイル: ds4hid.c プロジェクト: InputMapper/ViGEm
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(&notificationsQueueConfig, WdfIoQueueDispatchManual);

    status = WdfIoQueueCreate(Device, &notificationsQueueConfig, 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;
}
コード例 #7
0
//------------------------------------------------------------------------------
// 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;
}
コード例 #8
0
ファイル: driver.cpp プロジェクト: sunsuri/crostrackpad2
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;
}
コード例 #9
0
ファイル: utils.c プロジェクト: MHesham/bsp
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;
}
コード例 #10
0
ファイル: driver.c プロジェクト: 340211173/Driver
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;
}
コード例 #11
0
//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;
}
コード例 #12
0
// 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;
}
コード例 #13
0
ファイル: Device.cpp プロジェクト: OpenXT/xc-vusb
/**
 * @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;
}
コード例 #14
0
// 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;
}
コード例 #15
0
// 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;
}
コード例 #16
0
ファイル: toastmon.c プロジェクト: kcrazy/winekit
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;

}
コード例 #17
0
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);
}