Exemple #1
0
NTSTATUS 
AssignS0IdleSettings(
    _In_ WDFDEVICE Device
    )
/*++
Routine Description:

    Helper function to assign S0 idle settings for the device

Arguments:

    Device - Handle to the framework device object

Return Value:

    An NTSTATUS value representing success or failure of the function.
    
--*/
{
    NTSTATUS status;
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS powerPolicy;

    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&powerPolicy, 
                                               IdleCannotWakeFromS0);
    powerPolicy.IdleTimeoutType = SystemManagedIdleTimeout;

    status = WdfDeviceAssignS0IdleSettings(Device, &powerPolicy);
    if (FALSE == NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
              "%!FUNC! - WdfDeviceAssignS0IdleSettings failed with %!status!.", 
              status);
    }
    return status;
}
Exemple #2
0
static NTSTATUS UsbChief_SetPowerPolicy(IN WDFDEVICE Device)
{
	WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
	WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
	NTSTATUS Status = STATUS_SUCCESS;

	PAGED_CODE();

	WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
	idleSettings.IdleTimeout = 10000; // 10-sec

	Status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(DEBUG_POWER, ("WdfDeviceSetPowerPolicyS0IdlePolicy failed  %!STATUS!\n", Status));
		return Status;
	}

	WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

	Status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(DEBUG_POWER, ("WdfDeviceAssignSxWakeSettings failed  %!STATUS!\n", Status));
		return Status;
	}

	return Status;
}
Exemple #3
0
NTSTATUS SetPowerPolicy(__in WDFDEVICE Device)
{
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();

    // Init the idle policy structure.
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IDLE_CAPS_TYPE);
    idleSettings.IdleTimeout = 10000; // 10-sec

    status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(3, ("WdfDeviceAssignS0IdleSettings failed! (Status = %x)\n", status));
        return status;
    }

    // Init wait-wake policy structure.
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

    status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(3, ("WdfDeviceAssignSxWakeSettings failed! (Status = %x)\n", status));
        return status;
    }

    return status;
}
Exemple #4
0
NTSTATUS
CySetPowerPolicy(
    __in WDFDEVICE Device
    )
{
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS PowerIdleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS PowerWakeSettings;
    NTSTATUS    NTStatus = STATUS_SUCCESS;

    PAGED_CODE();
    
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&PowerIdleSettings, IdleCanWakeFromS0/*IdleUsbSelectiveSuspend*/);
    PowerIdleSettings.IdleTimeout = 10000; // 10-sec

    NTStatus = WdfDeviceAssignS0IdleSettings(Device, &PowerIdleSettings);
    if ( !NT_SUCCESS(NTStatus))
	{
        CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", NTStatus);
        return NTStatus;
    }
    
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&PowerWakeSettings);

    NTStatus = WdfDeviceAssignSxWakeSettings(Device, &PowerWakeSettings);
    if (!NT_SUCCESS(NTStatus)) {
        CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceAssignSxWakeSettings failed %x\n", NTStatus);
        return NTStatus;
    }

    return NTStatus;
}
NTSTATUS
PLxSetIdleAndWakeSettings(
        IN PDEVICE_EXTENSION FdoData
    )
/*++
Routine Description:

    Called by EvtDeviceAdd to set the idle and wait-wake policy. Registering this policy
    causes Power Management Tab to show up in the device manager. By default these
    options are enabled and the user is provided control to change the settings.

Return Value:

    NTSTATUS - Failure status is returned if the device is not capable of suspending
    or wait-waking the machine by an external event. Framework checks the
    capability information reported by the bus driver to decide whether the device is
    capable of waking the machine.

--*/
{
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
    NTSTATUS    status = STATUS_SUCCESS;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxSetIdleAndWakeSettings");

    PAGED_CODE();

    //
    // Init the idle policy structure.
    //
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0);
    idleSettings.IdleTimeout = 10000; // 10-sec

    status = WdfDeviceAssignS0IdleSettings(FdoData->Device, &idleSettings);
    if ( !NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceSetPowerPolicyS0IdlePolicy failed %!STATUS!", status);
        return status;
    }

    //
    // Init wait-wake policy structure.
    //
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

    status = WdfDeviceAssignSxWakeSettings(FdoData->Device, &wakeSettings);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceAssignSxWakeSettings failed %!STATUS!", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxSetIdleAndWakeSettings");

    return status;
}
// 配置设备驱动的电源管理功能
NTSTATUS DrvClass::InitPowerManagement()
{
	NTSTATUS status = STATUS_SUCCESS;
	WDF_USB_DEVICE_INFORMATION usbInfo;

	KDBG(DPFLTR_INFO_LEVEL, "[InitPowerManagement]");

	// 获取设备信息
	WDF_USB_DEVICE_INFORMATION_INIT(&usbInfo);
	WdfUsbTargetDeviceRetrieveInformation(m_hUsbDevice, &usbInfo);

	// USB设备信息以掩码形式被保存在Traits中。
	KDBG( DPFLTR_INFO_LEVEL, "Device self powered: %s", 
		usbInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED ? "TRUE" : "FALSE");
	KDBG( DPFLTR_INFO_LEVEL, "Device remote wake capable: %s",
		usbInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE ? "TRUE" : "FALSE");
	KDBG( DPFLTR_INFO_LEVEL, "Device high speed: %s",
		usbInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED ? "TRUE" : "FALSE");

	m_bIsDeviceHighSpeed = usbInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED;

	// 设置设备的休眠和远程唤醒功能
	if(usbInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE)
	{
		WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
		WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;

		// 设置设备为闲时休眠。闲时超过10S,自动进入休眠状态。
		WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
		idleSettings.IdleTimeout = 10000;
		status = WdfDeviceAssignS0IdleSettings(m_hDevice, &idleSettings);
		if(!NT_SUCCESS(status))
		{
			KDBG( DPFLTR_ERROR_LEVEL, "WdfDeviceAssignS0IdleSettings failed with status 0x%0.8x!!!", status);
			return status;
		}

		// 设置为可远程唤醒。包含设备自身醒来,已经当PC系统进入休眠后,设备可以将系统唤醒,两个方面。
		WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
		status = WdfDeviceAssignSxWakeSettings(m_hDevice, &wakeSettings);
		if(!NT_SUCCESS(status))
		{
			KDBG( DPFLTR_ERROR_LEVEL, "WdfDeviceAssignSxWakeSettings failed with status 0x%0.8x!!!", status);
			return status;
		}
	}

	return status;
}
NTSTATUS
OsrFxSetPowerPolicy(
    _In_ WDFDEVICE Device
    )
{
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
    NTSTATUS    status = STATUS_SUCCESS;

    PAGED_CODE();

    //
    // Init the idle policy structure.
    //
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
    idleSettings.IdleTimeout = 10000; // 10-sec

    status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
    if ( !NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
        return status;
    }

    //
    // Init wait-wake policy structure.
    //
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

    status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceAssignSxWakeSettings failed %x\n", status);
        return status;
    }

    return status;
}
Exemple #8
0
NTSTATUS
InitPowerManagement(
    IN WDFDEVICE  Device,
    IN PDEVICE_CONTEXT Context)
{
  NTSTATUS status = STATUS_SUCCESS;
  WDF_USB_DEVICE_INFORMATION usbInfo;

  KdPrint((__DRIVER_NAME "Device init power management\n"));

  // Lay thong tin cua thiet bi USB
  WDF_USB_DEVICE_INFORMATION_INIT(&usbInfo);	// init object
  status = WdfUsbTargetDeviceRetrieveInformation(
                                Context->UsbDevice,
                                &usbInfo);
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfUsbTargetDeviceRetrieveInformation failed with status 0x%08x\n",
      status));
    return status;
  }
  
  // Xem cac thong tin debug, thiet bi co ho tro self powered, wakeup hay high speed khong?
  KdPrint((__DRIVER_NAME  "Device self powered: %d\n",
    usbInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED ? 1 : 0));
  KdPrint((__DRIVER_NAME  "Device remote wake capable: %d\n",
    usbInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE ? 1 : 0));
  KdPrint((__DRIVER_NAME  "Device high speed: %d\n",
    usbInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED ? 1 : 0));

  if(usbInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE)
  {
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;

    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings,
                                               IdleUsbSelectiveSuspend);
    idleSettings.IdleTimeout = 10000;
    status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
    if(!NT_SUCCESS(status))
    {
      KdPrint((__DRIVER_NAME
        "WdfDeviceAssignS0IdleSettings failed with status 0x%08x\n",
        status));
      return status;
    }
    
    WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
    wakeSettings.DxState = PowerDeviceD2;
    status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
    if(!NT_SUCCESS(status))
    {
      KdPrint((__DRIVER_NAME
        "WdfDeviceAssignSxWakeSettings failed with status 0x%08x\n",
        status));
      return status;
    }
  }

  return status;
}
NTSTATUS
UfxClientDeviceCreate(
    _In_ WDFDRIVER Driver,
    _In_ PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    Driver - WDF driver object

    DeviceInit - Pointer to an opaque init structure. Memory for this
                 structure will be freed by the framework when the WdfDeviceCreate
                 succeeds. So don't access the structure after that point.

Return Value:

    Appropriate NTSTATUS value

--*/
{
    WDF_OBJECT_ATTRIBUTES DeviceAttributes;
    WDFDEVICE WdfDevice;
    NTSTATUS Status;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpCallbacks;
    WDF_DMA_ENABLER_CONFIG DmaConfig;
    PCONTROLLER_CONTEXT ControllerContext;

    PAGED_CODE();

    TraceEntry();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DeviceAttributes, CONTROLLER_CONTEXT);

    //
    // Do UFX-specific initialization
    //
    Status = UfxFdoInit(Driver, DeviceInit, &DeviceAttributes);
    CHK_NT_MSG(Status, "Failed UFX initialization");

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpCallbacks);
    PnpCallbacks.EvtDevicePrepareHardware = OnEvtDevicePrepareHardware;
    PnpCallbacks.EvtDeviceReleaseHardware = OnEvtDeviceReleaseHardware;
    PnpCallbacks.EvtDeviceD0Entry = OnEvtDeviceD0Entry;
    PnpCallbacks.EvtDeviceD0Exit = OnEvtDeviceD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpCallbacks);

    Status = WdfDeviceCreate(&DeviceInit, &DeviceAttributes, &WdfDevice);
    CHK_NT_MSG(Status, "Failed to create wdf device");

    ControllerContext = DeviceGetControllerContext(WdfDevice);

    KeInitializeEvent(&ControllerContext->DetachEvent,
                      NotificationEvent,
                      FALSE);

    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&ControllerContext->IdleSettings, IdleCanWakeFromS0);
    ControllerContext->IdleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint;
    ControllerContext->IdleSettings.IdleTimeout = IDLE_TIMEOUT;
    ControllerContext->IdleSettings.DxState = PowerDeviceD3;

    Status = WdfDeviceAssignS0IdleSettings(WdfDevice, &ControllerContext->IdleSettings);
    LOG_NT_MSG(Status, "Failed to set S0 Idle Settings");

    //
    // Create and initialize device's default queue
    //
    Status = DefaultQueueCreate(WdfDevice);
    CHK_NT_MSG(Status, "Failed to intialize default queue");

    //
    // Set alignment required by controller
    //
    WdfDeviceSetAlignmentRequirement(WdfDevice, UFX_CLIENT_ALIGNMENT);

    //
    // Create and Initialize DMA Enabler object for the device.
    //
    WDF_DMA_ENABLER_CONFIG_INIT(
                        &DmaConfig,
                        WdfDmaProfileScatterGatherDuplex,
                        MAX_DMA_LENGTH);
    //
    // Version 3 is required to perform multiple
    // simultaneous transfers.
    //
    DmaConfig.WdmDmaVersionOverride = 3;

    Status = WdfDmaEnablerCreate(
                            WdfDevice,
                            &DmaConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &ControllerContext->DmaEnabler);
    CHK_NT_MSG(Status, "Failed to create DMA enabler object");

    //
    // Create UFXDEVICE object
    //
    Status = UfxDevice_DeviceCreate(WdfDevice);
    CHK_NT_MSG(Status, "Failed to create UFX Device object");

    //
    // Create DPC Lock
    //
    Status = WdfSpinLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &ControllerContext->DpcLock);
    CHK_NT_MSG(Status, "Failed to create DPC lock");

    Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &ControllerContext->InitializeDefaultEndpointLock);
    CHK_NT_MSG(Status, "Failed to create Ep0 init lock");

End:
    TraceExit();
    return Status;
}
NTSTATUS
NfcCxEvtDeviceInitialize(
    _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals,
    _In_ WDFDEVICE Device
    )
/*++

Routine Description:

    This routine is called by the CX client to indicate
    that a device initialization is required.

Arguments:

    NfcCxGlobal - CX global pointer
    Device - WDF device to initialize

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                              status = STATUS_SUCCESS;
    WDF_OBJECT_ATTRIBUTES                 fdoAttributes;
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    WDF_IO_QUEUE_CONFIG                   queueConfig;
    PNFCCX_FDO_CONTEXT                    fdoContext;
    WDFQUEUE                              queue;
    PNFCCX_CLIENT_GLOBALS                 nfcCxClientGlobal;
    WDF_OBJECT_ATTRIBUTES                 objectAttrib;

    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    if (!VerifyPrivateGlobals(NfcCxGlobals)) {
        TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer");
        status = STATUS_INVALID_PARAMETER;
        goto Done;
    }

    nfcCxClientGlobal = GetPrivateGlobals(NfcCxGlobals);

    //
    // Create class extension device context
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, NFCCX_FDO_CONTEXT);
    fdoAttributes.EvtCleanupCallback = NfcCxFdoContextCleanup;
    
    status = WdfObjectAllocateContext(Device, &fdoAttributes, (PVOID*)&fdoContext);
    if (!NT_SUCCESS(status)) {
        TRACE_LINE(LEVEL_ERROR, "Failed to allocate the client context");
        goto Done;
    }
    fdoContext->Device = Device;
    fdoContext->NfpRadioInterfaceCreated = FALSE;
    fdoContext->NfpPowerOffSystemOverride = FALSE;
    fdoContext->NfpPowerOffPolicyOverride = FALSE;
    fdoContext->NfpPowerPolicyReferences = 0;
    fdoContext->SERadioInterfaceCreated = FALSE;
    fdoContext->SEPowerOffSystemOverride = FALSE;
    fdoContext->SEPowerOffPolicyOverride = FALSE;
    fdoContext->SEPowerPolicyReferences = 0;
    fdoContext->NfcCxClientGlobal = nfcCxClientGlobal;

    status = NfcCxFdoReadCxDriverRegistrySettings(&fdoContext->LogNciDataMessages);
    if (!NT_SUCCESS(status)) {
        TRACE_LINE(LEVEL_ERROR, "NfcCxFdoReadCxDriverRegistrySettings failed, %!STATUS!", status);
        goto Done;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib);
    objectAttrib.ParentObject = Device;
    
    status = WdfWaitLockCreate(&objectAttrib,
                                &fdoContext->PowerPolicyWaitLock);
    if (!NT_SUCCESS(status)) {
        TRACE_LINE(LEVEL_ERROR, "Failed to create the PowerPolicy WaitLock, %!STATUS!", status);
        goto Done;
    }
    
    //
    // Register I/O callbacks to tell the framework that you are interested
    // in handling IRP_MJ_DEVICE_CONTROL requests.
    //
    // In case a specific handler is not specified for one of these,
    // the request will be dispatched to the EvtIoDefault handler, if any.
    // If there is no EvtIoDefault handler, the request will be failed with
    // STATUS_INVALID_DEVICE_REQUEST.
    //
    // WdfIoQueueDispatchParallel means that we are capable of handling
    // all the I/O request simultaneously and we are responsible for protecting
    // data that could be accessed by these callbacks simultaneously.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
                             WdfIoQueueDispatchParallel);

    //
    // Our default queue is non power managed. Based on the request and the Radio on/off
    // state, we forward the request to the power managed queue to wake the system as
    // appropriate
    //
    queueConfig.PowerManaged = WdfFalse;
    queueConfig.EvtIoDeviceControl = NfcCxEvtDefaultIoControl;

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib);
    objectAttrib.ParentObject = Device;

    status = WdfIoQueueCreate(Device,
                                &queueConfig,
                                &objectAttrib,
                                &queue
                                );
    if (!NT_SUCCESS (status)) {
        TRACE_LINE(LEVEL_ERROR, "WdfIoQueueCreate failed %!STATUS!", status);
        goto Done;
    }
    fdoContext->DefaultQueue = queue;

    //
    // Our internal queue is non power managed because we need to send IO during.
    // D0Entry/D0Exit routines. It is the default queue for SelfIoTarget requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                             WdfIoQueueDispatchParallel);

    queueConfig.PowerManaged = WdfFalse;
    queueConfig.EvtIoDeviceControl = NfcCxEvtSelfIoControl;

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib);
    objectAttrib.ParentObject = Device;

    status = WdfIoQueueCreate(Device,
                                &queueConfig,
                                &objectAttrib,
                                &queue
                                );
    if (!NT_SUCCESS (status)) {
        TRACE_LINE(LEVEL_ERROR, "WdfIoQueueCreate failed %!STATUS!", status);
        goto Done;
    }
    fdoContext->SelfQueue = queue;

    //
    // Assign our internal queue as the default queue for the SelfIoTarget. Any IO
    // sent to the SelfIoTarget would be dispatched from this queue.
    //
    status = WdfIoTargetSelfAssignDefaultIoQueue(WdfDeviceGetSelfIoTarget(Device),
                                                 fdoContext->SelfQueue);
    if (!NT_SUCCESS (status)) {
        TRACE_LINE(LEVEL_ERROR, "WdfIoTargetSelfAssignDefaultIoQueue failed %!STATUS!", status);
        goto Done;
    }

    status = NfcCxFdoCreate(fdoContext);
    if (!NT_SUCCESS(status)) {
        TRACE_LINE(LEVEL_ERROR, "Failed to create the Fdo context failed %!STATUS!", status);
        goto Done;
    }

    if (NFC_CX_DEVICE_MODE_NCI == fdoContext->NfcCxClientGlobal->Config.DeviceMode) {
        //
        // Read the FDO's persisted settings from the registry
        //
        status = NfcCxFdoReadPersistedDeviceRegistrySettings(fdoContext);
        if (!NT_SUCCESS(status)) {
            TRACE_LINE(LEVEL_ERROR, "NfcCxFdoReadPersistedDeviceRegistrySettings, %!STATUS!", status);
            goto Done;
        }

        //
        // Log all settings that could have been overridden from the registry.
        //
        EventWriteDevicePersistedRegistrySettings(fdoContext->NfpPowerOffPolicyOverride,
                                                  fdoContext->NfpPowerOffSystemOverride,
                                                  fdoContext->SEPowerOffPolicyOverride,
                                                  fdoContext->SEPowerOffSystemOverride);

        //
        // Check the currently required power state
        //
        fdoContext->NfpRadioState = (!fdoContext->NfpPowerOffPolicyOverride && !fdoContext->NfpPowerOffSystemOverride);
        fdoContext->SERadioState = (!fdoContext->SEPowerOffPolicyOverride && !fdoContext->SEPowerOffSystemOverride);
    }

    //
    // The class extension is the default power policy owner. This option allows the client
    // to now be the power policy owner
    //
    if (fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner == WdfUseDefault) {
        fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner = WdfFalse;
    }

    if (fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner == WdfFalse) {
        //
        // Set the idle power policy to put the device to Dx if the device is not used
        // for the specified IdleTimeout time. Since this is a non wakeable device we
        // tell the framework that we cannot wake ourself if we sleep in S0. Only
        // way the device can be brought to D0 is if the device recieves an I/O from
        // the system.
        //
        WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0);
        idleSettings.IdleTimeoutType = fdoContext->NfcCxClientGlobal->Config.PowerIdleType;
        idleSettings.IdleTimeout = fdoContext->NfcCxClientGlobal->Config.PowerIdleTimeout;

        status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
        if (!NT_SUCCESS(status)) {
            TRACE_LINE(LEVEL_ERROR, "WdfDeviceAssignS0IdleSettings failed %!STATUS!", status);
            goto Done;
        }
    }

Done:

    TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
    TRACE_LOG_NTSTATUS_ON_FAILURE(status);
    
    return status;
}
NTSTATUS
OsrEvtDeviceListCreatePdo(
    WDFCHILDLIST DeviceList,
    PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
    PWDFDEVICE_INIT ChildInit
    )
/*++

Routine Description:

    Called by the framework in response to Query-Device relation when
    a new PDO for a child device needs to be created.

Arguments:

    DeviceList - Handle to the default WDFCHILDLIST created by the
                        framework as part of FDO.

    IdentificationDescription - Decription of the new child device.

    ChildInit - It's a opaque structure used in collecting device settings
                    and passed in as a parameter to CreateDevice.

Return Value:

    NT Status code.

--*/
{
    NTSTATUS                        status;
    WDFDEVICE                       hChild = NULL;
    PPDO_IDENTIFICATION_DESCRIPTION pDesc;
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    DECLARE_CONST_UNICODE_STRING(deviceId, OSRUSBFX2_SWITCH_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(hardwareId, OSRUSBFX2_SWITCH_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"OSR USB-FX2 Learning Kit" );
    DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);

    UNREFERENCED_PARAMETER(DeviceList);

    pDesc = CONTAINING_RECORD(IdentificationDescription,
                              PDO_IDENTIFICATION_DESCRIPTION,
                              Header);

    //
    // Mark the device RAW so that the child device can be started
    // and accessed without requiring a function driver. Since we are
    // creating a RAW PDO, we must provide a class guid.
    //
    status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_OSRUSBFX2);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since our devices for switches can trigger nuclear explosion,
    // we must protect them from random users sending I/Os.
    //
    status = WdfDeviceInitAssignSDDLString(ChildInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // On XP and later, there is no need to provide following IDs for raw pdos.
    // BusQueryHardwareIDs but on On Win2K, we must provide a HWID and a NULL
    // section in the INF to get the device installed without any problem.
    //
    status = WdfPdoInitAddHardwareID(ChildInit, &hardwareId);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since we are enumerating more than one children, we must
    // provide a BusQueryInstanceID. If we don't, system will throw
    // CA bugcheck.
    //
    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", pDesc->SwitchNumber);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. In the case of USB device, this text comes from the string
    // descriptor. This text is displayed momentarily by the PnP manager while
    // it's looking for a matching INF. If it finds one, it uses the Device
    // Description from the INF file to display in the device manager.
    // Since our device is raw device and we don't provide any hardware ID
    // to match with an INF, this text will be displayed in the device manager.
    //
    status = RtlUnicodeStringPrintf(&buffer,
                                    L"OsrUsbFX2 RawPdo For Switch %02d",
                                    pDesc->SwitchNumber);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // You can call WdfPdoInitAddDeviceText multiple times, adding device
    // text for multiple locales. When the system displays the text, it
    // chooses the text that matches the current locale, if available.
    // Otherwise it will use the string for the default locale.
    // The driver can specify the driver's default locale by calling
    // WdfPdoInitSetDefaultLocale.
    //
    status = WdfPdoInitAddDeviceText(ChildInit,
                                        &buffer,
                                        &deviceLocation,
                                        0x409);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    WdfPdoInitSetDefaultLocale(ChildInit, 0x409);

    status = WdfDeviceCreate(&ChildInit, WDF_NO_OBJECT_ATTRIBUTES, &hChild);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;

    }

    //
    // Set idle-time out on the child device. This is required to allow
    // the parent device to idle-out when there are no active I/O.
    //
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0);
    idleSettings.IdleTimeout = 1000; // 1-sec

    status = WdfDeviceAssignS0IdleSettings(hChild, &idleSettings);
    if ( !NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
        return status;
    }

    return status;

Cleanup:

    TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"CreatePdo failed %x\n", status);

    //
    // On error, framework will cleanup all the resources when it deletes
    // the device. So there is nothing to do.
    //

    return status;
}
Exemple #12
0
NTSTATUS
SmplDeviceCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    DeviceInit - Pointer to an opaque init structure. Memory for this
                    structure will be freed by the framework when the WdfDeviceCreate
                    succeeds. So don't access the structure after that point.

Return Value:

    NTSTATUS

--*/
{
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
    deviceAttributes.SynchronizationScope = WdfSynchronizationScopeQueue;

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks);
    PnpPowerEventCallbacks.EvtDevicePrepareHardware = SmplDeviceEvtPrepareHardware;
    PnpPowerEventCallbacks.EvtDeviceReleaseHardware = SmplDeviceEvtReleaseHardware;
    PnpPowerEventCallbacks.EvtDeviceD0Entry = SmplDeviceEvtD0Entry;
    PnpPowerEventCallbacks.EvtDeviceD0Exit = SmplDeviceEvtD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &PnpPowerEventCallbacks);

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (NT_SUCCESS(status)) 
    {   //
        // Get the device context and initialize it. DeviceGetContext is an
        // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the
        // device.h header file. This function will do the type checking and return
        // the device context. If you pass a wrong object  handle
        // it will return NULL and assert if run under framework verifier mode.
        //
        deviceContext = DeviceGetContext(device);

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(device,
                                                &GUID_DEVINTERFACE_SMPLDEVICE,
                                                NULL);
        if (NT_SUCCESS(status)) 
        {   //
            // Initialize the I/O Package and any Queues
            //
            status = SmplDeviceQueueInitialize(device);
        }

        if (NT_SUCCESS(status)) {
            WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS PowerPolicyIdleSettings;
            WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&PowerPolicyIdleSettings, IdleCannotWakeFromS0);
            PowerPolicyIdleSettings.IdleTimeoutType = SystemManagedIdleTimeout;

            status = WdfDeviceAssignS0IdleSettings(device, &PowerPolicyIdleSettings);
            if (!NT_SUCCESS(status)) 
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfDeviceAssignS0IdleSettings failed! 0x%x\n", status);
            }
        }

        if (NT_SUCCESS(status)) {
            SmplPoFxSingleComponentInitialize(device);
        }

        if (NT_SUCCESS(status)) 
        {
            WDFINTERRUPT Interrupt;
            WDF_INTERRUPT_CONFIG Configuration;
            WDF_INTERRUPT_CONFIG_INIT(&Configuration, SmplInterruptEvtIsr, SmplInterruptEvtDpc);
            Configuration.EvtInterruptEnable = SmplInterruptEvtEnable;
            Configuration.EvtInterruptDisable = SmplInterruptEvtDisable;
            status = WdfInterruptCreate(device,
                                        &Configuration,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &Interrupt);
            if (!NT_SUCCESS(status)) 
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "WdfInterruptCreate failed! 0x%x\n", status);
            }
        }

    }

    return status;
}