Example #1
0
NTSTATUS
EvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
{
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    
    UNREFERENCED_PARAMETER(Driver);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfDeviceCreate failed 0x%x\n", status));
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device,
                                (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                NULL);// Reference String
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));
        return status;
    }

    return status;
}
Example #2
0
void CPreAllocatedDeviceInit::SetPowerCallbacks(PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT SelfManagedIoFunc)
{
    WDF_PNPPOWER_EVENT_CALLBACKS  Callbacks;
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
    Callbacks.EvtDeviceSelfManagedIoInit = SelfManagedIoFunc;
    WdfDeviceInitSetPnpPowerEventCallbacks(m_DeviceInit, &Callbacks);
}
Example #3
0
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver,
                             IN PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_FILEOBJECT_CONFIG fileConfig;
    WDF_OBJECT_ATTRIBUTES attributes;

    UNREFERENCED_PARAMETER(Driver);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %!FUNC!");

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware;
	pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry;
	pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

	WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate,
		WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK);

	WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig,
		WDF_NO_OBJECT_ATTRIBUTES);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceCreate failed: %!STATUS!", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!");

    return status;
}
_Use_decl_annotations_
NTSTATUS
SampleDrvEvtDeviceAdd (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
)

/*++

Routine Description:

    This routine is the AddDevice entry point for the sample device driver.
    It sets the ISR and DPC routine handlers for the interrupt and the passive
    level callback for the passive interrupt

    N.B. The sample device expects two interrupt resources in connecting its
    DIRQL ISR and PASSIVE_LEVEL callback.

Arguments:

    Driver - Supplies a handle to the driver object created in DriverEntry.

    DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT
        structure.

Return Value:

    NTSTATUS code.

--*/

{

    WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
    WDFDEVICE Device;
    WDF_OBJECT_ATTRIBUTES FdoAttributes;
    WDF_INTERRUPT_CONFIG InterruptConfiguration;
    NTSTATUS Status;
    WDFINTERRUPT WdfInterrupt;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    //
    // Set PnP callbacks for prepare/release hardware and D0 entry/exit. All
    // callbacks not overriden here will be handled by the framework in the
    // default manner.
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
    Callbacks.EvtDevicePrepareHardware = SampleDrvEvtDevicePrepareHardware;
    Callbacks.EvtDeviceD0Entry = SampleDrvEvtDeviceD0Entry;

    //
    // Register the PnP callbacks with the framework.
    //

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &Callbacks);

    //
    // Initialize FDO attributes with the sample device extension.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&FdoAttributes);
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&FdoAttributes, SAMPLE_DRV_DEVICE_EXTENSION);

    //
    // Call the framework to create the device and attach it to the lower stack.
    //

    Status = WdfDeviceCreate(&DeviceInit, &FdoAttributes, &Device);
    if (!NT_SUCCESS(Status)) {
        goto EvtDeviceAddEnd;
    }

    //
    // Create an interrupt object for the DIRQL ISR
    //

    WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
                              SampleDrvInterruptIsr,
                              SampleDrvInterruptDpc);

    Status = WdfInterruptCreate(Device,
                                &InterruptConfiguration,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &WdfInterrupt);

    if (!NT_SUCCESS(Status)) {

        goto EvtDeviceAddEnd;
    }

#if 0
    //
    // Create an interrupt object for the passive interrupt callback. Note that
    // the interrupt object is chained to the same interrupt line/IDT as the
    // DIRQL one.
    //

    WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
                              SampleDrvInterruptIsr,
                              NULL);

    //
    //  Set passive handling to true
    //

    InterruptConfiguration.PassiveHandling = TRUE;

    Status = WdfInterruptCreate(Device,
                                &InterruptConfiguration,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &WdfInterrupt);
#endif

EvtDeviceAddEnd:
    return Status;
}
Example #5
0
NTSTATUS
SingleCompEvtDeviceAdd(
    _In_    WDFDRIVER       Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by UMDF in response to AddDevice call from 
    the PnP manager. 

Arguments:

    Driver - Handle to the UMDF driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    An NTSTATUS value representing success or failure of the function.

--*/
{
    NTSTATUS status;
    WDFDEVICE device;
    WDFQUEUE queue;
    WDF_IO_QUEUE_CONFIG     queueConfig;
    FDO_DATA               *fdoContext = NULL;
    WDF_OBJECT_ATTRIBUTES   objectAttributes;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;

    UNREFERENCED_PARAMETER(Driver);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FDO_DATA);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
    pnpCallbacks.EvtDeviceD0Entry = SingleCompEvtDeviceD0Entry;
    pnpCallbacks.EvtDeviceD0Exit = SingleCompEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);
    
    status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
              "%!FUNC! - WdfDeviceCreate failed with %!status!.", 
              status);
        goto exit;
    }

    fdoContext = FdoGetContext(device);

    //
    // Our initial state is active
    //
    fdoContext->IsActive = TRUE;

    //
    // Create a power-managed queue for IOCTL requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, 
                                           WdfIoQueueDispatchParallel);
    queueConfig.EvtIoDeviceControl = SingleCompEvtIoDeviceControl;

    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests or 
    // forward them to other drivers. This driver completes the requests 
    // directly in the queue's handlers. If the EvtIoStop callback is not 
    // implemented, the framework waits for all driver-owned requests to be
    // done before moving in the Dx/sleep states or before removing the 
    // device, which is the correct behavior for this type of driver.
    // If the requests were taking an indeterminate amount of time to complete,
    // or if the driver forwarded the requests to a lower driver/another stack,
    // the queue should have an EvtIoStop/EvtIoResume.
    //
    __analysis_assume(queueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &queue);
    __analysis_assume(queueConfig.EvtIoStop == 0);

    if (FALSE == NT_SUCCESS (status)) {
        Trace(TRACE_LEVEL_ERROR,
              "%!FUNC! - WdfIoQueueCreate for IoDeviceControl failed with %!status!.", 
              status);
        goto exit;
    }

    status = WdfDeviceConfigureRequestDispatching(device,
                                                  queue,
                                                  WdfRequestTypeDeviceControl);
    if (FALSE == NT_SUCCESS (status)) {
        Trace(TRACE_LEVEL_ERROR,
              "%!FUNC! - WdfDeviceConfigureRequestDispatching for "
              "WdfRequestTypeDeviceControl failed with %!status!.", 
              status);
        goto exit;
    }

    status = AssignS0IdleSettings(device);
    if (!NT_SUCCESS(status)) {
        goto exit;
    }

    //
    // Create a device interface so that applications can open a handle to this
    // device.
    //
    status = WdfDeviceCreateDeviceInterface(device, 
                                            &GUID_DEVINTERFACE_POWERFX,
                                            NULL /* ReferenceString */);
    if (FALSE == NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.", 
              status);
        goto exit;
    }

    //
    // Initialize the hardware simulator
    //
    status = HwSimInitialize(device);
    if (FALSE == NT_SUCCESS(status)) {
        goto exit;
    }    
exit:
    return status;
}
Example #6
0
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;
    NTSTATUS status;
    
    UNREFERENCED_PARAMETER(FxDriver);

    //
    // 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);
    }

    //
    // Prepare for file object handling.
    //

    {
        WDF_FILEOBJECT_CONFIG fileObjectConfig;

        WDF_FILEOBJECT_CONFIG_INIT(
            &fileObjectConfig, 
            nullptr, 
            nullptr,
            OnFileCleanup);

        WDF_OBJECT_ATTRIBUTES fileObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);

        WdfDeviceInitSetFileObjectConfig(
            FxDeviceInit, 
            &fileObjectConfig,
            &fileObjectAttributes);
    }

    //
    // Set request attributes.
    //

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &attributes,
            REQUEST_CONTEXT);

        WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes);
    }

    //
    // Create the device.
    //

    {
        WDFDEVICE fxDevice;
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &FxDeviceInit, 
            &deviceAttributes,
            &fxDevice);

        if (!NT_SUCCESS(status))
        {
            Trace(
                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))
        {
            Trace(
                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.EvtIoRead = OnIoRead;
        queueConfig.EvtIoWrite = OnIoWrite;
        queueConfig.EvtIoDeviceControl = OnIoDeviceControl;
        queueConfig.PowerManaged = WdfFalse;

        status = WdfIoQueueCreate(
            pDevice->FxDevice,
            &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
            &pDevice->SpbQueue
            );

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating SPB IO queue - %!STATUS!", 
                status);

            goto exit;
        }
    }

    //
    // Create a symbolic link.
    //

    {
        DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128);

        status = RtlUnicodeStringPrintf(
            &symbolicLinkName, L"%ws",
            sensy_SYMBOLIC_NAME);

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating symbolic link string for device "
                "- %!STATUS!", 
                status);

            goto exit;
        }

        status = WdfDeviceCreateSymbolicLink(
            pDevice->FxDevice, 
            &symbolicLinkName);

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating symbolic link for device "
                "- %!STATUS!", 
                status);

            goto exit;
        }
    }

    //
    // Retrieve registry settings.
    //

    {
        WDFKEY key = NULL;
        WDFKEY subkey = NULL;
        ULONG connectInterrupt = 0;
        NTSTATUS settingStatus;
    
        DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings");
        DECLARE_CONST_UNICODE_STRING(connectInterruptName, L"ConnectInterrupt");

        settingStatus = WdfDeviceOpenRegistryKey(
            pDevice->FxDevice,
            PLUGPLAY_REGKEY_DEVICE,
            KEY_READ,
            WDF_NO_OBJECT_ATTRIBUTES,
            &key);

        if (!NT_SUCCESS(settingStatus))
        {
            Trace(
                TRACE_LEVEL_WARNING, 
                TRACE_FLAG_WDFLOADING,
                "Error opening device registry key - %!STATUS!",
                settingStatus);
        }

        if (NT_SUCCESS(settingStatus))
        {
            settingStatus = WdfRegistryOpenKey(
                key,
                &subkeyName,
                KEY_READ,
                WDF_NO_OBJECT_ATTRIBUTES,
                &subkey);

            if (!NT_SUCCESS(settingStatus))
            {
                Trace(
                    TRACE_LEVEL_WARNING, 
                    TRACE_FLAG_WDFLOADING,
                    "Error opening registry subkey for 'Settings' - %!STATUS!", 
                    settingStatus);
            }
        }

        if (NT_SUCCESS(settingStatus))
        {

            settingStatus = WdfRegistryQueryULong(
                subkey,
                &connectInterruptName,
                &connectInterrupt);

            if (!NT_SUCCESS(settingStatus))
            {
                Trace(
                    TRACE_LEVEL_WARNING, 
                    TRACE_FLAG_WDFLOADING,
                    "Error querying registry value for 'ConnectInterrupt' - %!STATUS!", 
                    settingStatus);
            }
        }

        if (key != NULL)
        {
            WdfRegistryClose(key);
        }

        if (subkey != NULL)
        {
            WdfRegistryClose(subkey);
        }

        pDevice->ConnectInterrupt = (connectInterrupt == 1);
    }

exit:

    //FuncExit(TRACE_FLAG_WDFLOADING);

    return status;
}
NTSTATUS
OsrFxEvtDeviceAdd(
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device. All the software resources
    should be allocated in this callback.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;
    GUID                                activity;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");

    //
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter 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 = OsrFxEvtDevicePrepareHardware;

    //
    // These two callbacks start and stop the wdfusb pipe continuous reader
    // as we go in and out of the D0-working state.
    //

    pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceSelfManagedIoFlush = OsrFxEvtDeviceSelfManagedIoFlush;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

    //
    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
        return status;
    }

    //
    // Setup the activity ID so that we can log events using it.
    //

    activity = DeviceToActivityId(device);

    //
    // Get the DeviceObject context by using accessor function specified in
    // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
    //
    pDevContext = GetDeviceContext(device);

    //
    // Get the device's friendly name and location so that we can use it in
    // error logging.  If this fails then it will setup dummy strings.
    //

    GetDeviceEventLoggingNames(device);

    //
    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermodewhen you surprise remove the device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    //
    // Create a parallel default queue and register an event callback to
    // receive ioctl requests. We will create separate queues for
    // handling read and write requests. All other requests will be
    // completed with error status automatically by the framework.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                             WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl    = OsrFxEvtIoDeviceControl;
    
    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests for 
    // long time or forward them to other drivers. 
    // If the EvtIoStop callback is not implemented, the framework waits for
    // all driver-owned requests to be done before moving in the Dx/sleep 
    // states or before removing the device, which is the correct behavior 
    // for this type of driver. If the requests were taking an indeterminate
    // amount of time to complete, or if the driver forwarded the requests
    // to a lower driver/another stack, the queue should have an 
    // EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(device,
                             &ioQueueConfig,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             &queue);// pointer to default queue
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                            "WdfIoQueueCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    //
    // We will create a separate sequential queue and configure it
    // to receive read requests.  We also need to register a EvtIoStop
    // handler so that we can acknowledge requests that are pending
    // at the target driver.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = OsrFxEvtIoRead;
    ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeRead);

    if(!NT_SUCCESS (status)){
        assert(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }


    //
    // We will create another sequential queue and configure it
    // to receive write requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite;
    ioQueueConfig.EvtIoStop  = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

     status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeWrite);

    if(!NT_SUCCESS (status)){
        assert(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }

    //
    // 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(&ioQueueConfig, 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.
    //
    ioQueueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &pDevContext->InterruptMsgQueue
                              );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    //
    // Register a device interface so that app can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                            (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                            NULL); // Reference String

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfDeviceCreateDeviceInterface failed  %!STATUS!\n", status);
        goto Error;
    }

    // 
    // Create the lock that we use to serialize calls to ResetDevice(). As an 
    // alternative to using a WDFWAITLOCK to serialize the calls, a sequential 
    // WDFQUEUE can be created and reset IOCTLs would be forwarded to it.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;

    status = WdfWaitLockCreate(&attributes, &pDevContext->ResetDeviceWaitLock);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfWaitLockCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n");

    return status;

Error:

    //
    // Log fail to add device to the event log
    //
    EventWriteFailAddDevice(pDevContext->DeviceName,
                            pDevContext->Location,
                            status);

    return status;
}
Example #8
0
NTSTATUS
PLxEvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
/*++

Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. Here the driver should register all the
    PNP, power and Io callbacks, register interfaces and allocate other
    software resources required by the device. The driver can query
    any interfaces or get the config space information from the bus driver
    but cannot access hardware registers or initialize the device.

Arguments:

Return Value:

--*/
{
	KdPrint(("Entry PLxEvtDeviceAdd Routine"));
    NTSTATUS                   status = STATUS_SUCCESS;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES       attributes;
    WDFDEVICE                   device;
    PDEVICE_EXTENSION           devExt = NULL;

    UNREFERENCED_PARAMETER( Driver );

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

    PAGED_CODE();

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = PLxEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = PLxEvtDeviceReleaseHardware;

    //
    // These two callbacks set up and tear down hardware state that must be
    // done every time the device moves in and out of the D0-working state.
    //
    pnpPowerCallbacks.EvtDeviceD0Entry         = PLxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit          = PLxEvtDeviceD0Exit;

    //
    // Register the PnP Callbacks..
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    //
    // Initialize Fdo Attributes.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION);
    //
    // By opting for SynchronizationScopeDevice, we tell the framework to
    // synchronize callbacks events of all the objects directly associated
    // with the device. In this driver, we will associate queues and
    // and DpcForIsr. By doing that we don't have to worrry about synchronizing
    // access to device-context by Io Events and DpcForIsr because they would
    // not concurrently ever. Framework will serialize them by using an
    // internal device-lock.
    //
    attributes.SynchronizationScope = WdfSynchronizationScopeDevice;

    //
    // Create the device
    //
    status = WdfDeviceCreate( &DeviceInit, &attributes, &device );

    if (!NT_SUCCESS(status)) {
        //
        // Device Initialization failed.
        //
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceCreate failed %!STATUS!", status);
        return status;
    }

    //
    // Get the DeviceExtension and initialize it. PLxGetDeviceContext is an inline function
    // defined by WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in the
    // private header file. This function will do the type checking and return
    // the device context. If you pass a wrong object a wrong object handle
    // it will return NULL and assert if run under framework verifier mode.
    //
    devExt = PLxGetDeviceContext(device);

    devExt->Device = device;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                "     AddDevice PDO (0x%p) FDO (0x%p), DevExt (0x%p)",
                WdfDeviceWdmGetPhysicalDevice(device),
                WdfDeviceWdmGetDeviceObject(device), devExt);

    //
    // Tell the Framework that this device will need an interface
    //
    // NOTE: See the note in Public.h concerning this GUID value.
    //
    status = WdfDeviceCreateDeviceInterface( device,
                                             (LPGUID) &GUID_PLX_INTERFACE,
                                             NULL );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "<-- DeviceCreateDeviceInterface "
                    "failed %!STATUS!", status);
        return status;
    }

    //
    // Set the idle and wait-wake policy for this device.
    //
    status = PLxSetIdleAndWakeSettings(devExt);

    if (!NT_SUCCESS (status)) {
        //
        // NOTE: The attempt to set the Idle and Wake options
        //       is a best-effort try. Failure is probably due to
        //       the non-driver environmentals, such as the system,
        //       bus or OS indicating that Wake is not supported for
        //       this case.
        //       All that being said, it probably not desirable to
        //       return the failure code as it would cause the
        //       AddDevice to fail and Idle and Wake are probably not
        //       "must-have" options.
        //
        //       You must decide for your case whether Idle/Wake are
        //       "must-have" options...but my guess is probably not.
        //
#if 1
        status = STATUS_SUCCESS;
#else
        return status;
#endif
    }

    //
    // Initalize the Device Extension.
    //
    status = PLxInitializeDeviceExtension(devExt);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                "<-- PLxEvtDeviceAdd %!STATUS!", status);

	KdPrint(("Leave PLxEvtDeviceAdd Routine"));
    return status;
}
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver,
                             IN PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_FILEOBJECT_CONFIG fileConfig;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_IO_QUEUE_CONFIG queueConfig;
    PDEVICE_CONTEXT context;
    DECLARE_CONST_UNICODE_STRING(dosDeviceName, PVPANIC_DOS_DEVICE_NAME);

    UNREFERENCED_PARAMETER(Driver);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %!FUNC!");

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware;
	pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry;
	pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

	WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate,
		WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK);

	WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig,
		WDF_NO_OBJECT_ATTRIBUTES);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceCreate failed: %!STATUS!", status);
        return status;
    }

    status = WdfDeviceCreateSymbolicLink(device, &dosDeviceName);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceCreateSymbolicLink failed: %!STATUS!", status);
        return status;
    }

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
    queueConfig.EvtIoDeviceControl = PVPanicEvtQueueDeviceControl;

    context = GetDeviceContext(device);
    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &context->IoctlQueue);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfIoQueueCreate failed: %!STATUS!", status);
        return status;
    }

    status = WdfDeviceConfigureRequestDispatching(device,
                                                  context->IoctlQueue,
                                                  WdfRequestTypeDeviceControl);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceConfigureRequestDispatching failed: %!STATUS!", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!");

    return status;
}
// Sets up a new device.
NTSTATUS
DeviceContext::DeviceAdd(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    NFC_CX_CLIENT_CONFIG nfcCxConfig;
    NFC_CX_CLIENT_CONFIG_INIT(&nfcCxConfig, NFC_CX_TRANSPORT_CUSTOM);
    nfcCxConfig.EvtNfcCxWriteNciPacket = WriteNciPacketCallback;
    nfcCxConfig.EvtNfcCxDeviceIoControl = DeviceIoCallback;
    nfcCxConfig.DriverFlags = NFC_CX_DRIVER_ENABLE_EEPROM_WRITE_PROTECTION |
        NFC_CX_DRIVER_POWER_AND_LINK_CONTROL_SUPPORTED;

    status = NfcCxDeviceInitConfig(DeviceInit, &nfcCxConfig);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitConfig failed. %!STATUS!", status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES deviceObjectAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceObjectAttributes, DeviceContext);
    deviceObjectAttributes.EvtCleanupCallback = ShutdownCallback;
    deviceObjectAttributes.EvtDestroyCallback = DestroyCallback;

    WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
    pnpCallbacks.EvtDeviceD0Entry = D0EntryCallback;
    pnpCallbacks.EvtDeviceD0Exit = D0ExitCallback;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);

    FileObjectContext::DeviceInit(DeviceInit);

    WDFDEVICE device;
    status = WdfDeviceCreate(&DeviceInit, &deviceObjectAttributes, &device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreate failed. %!STATUS!", status);
        return status;
    }

    // Initialize device context.
    DeviceContext* deviceContext = DeviceGetContext(device);
    new (deviceContext) DeviceContext();
    deviceContext->_Device = device;

    status = NfcCxDeviceInitialize(device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitialize failed. %!STATUS!", status);
        return status;
    }

    // Create lock for clients (and sequence handling).
    WDF_OBJECT_ATTRIBUTES lockAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;

    status = WdfWaitLockCreate(&lockAttributes, &deviceContext->_ClientLock);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfWaitLockCreate failed. %!STATUS!", status);
        return status;
    }

    // Initialize RF discovery config (enable everything).
    NFC_CX_RF_DISCOVERY_CONFIG discoveryConfig;
    NFC_CX_RF_DISCOVERY_CONFIG_INIT(&discoveryConfig);
    discoveryConfig.PollConfig = NFC_CX_POLL_NFC_A | NFC_CX_POLL_NFC_B | NFC_CX_POLL_NFC_F_212 | NFC_CX_POLL_NFC_F_424 | NFC_CX_POLL_NFC_15693 | NFC_CX_POLL_NFC_ACTIVE | NFC_CX_POLL_NFC_A_KOVIO;
    discoveryConfig.NfcIPMode = NFC_CX_NFCIP_NFC_A | NFC_CX_NFCIP_NFC_F_212 | NFC_CX_NFCIP_NFC_F_424 | NFC_CX_NFCIP_NFC_ACTIVE | NFC_CX_NFCIP_NFC_ACTIVE_A | NFC_CX_NFCIP_NFC_ACTIVE_F_212 | NFC_CX_NFCIP_NFC_ACTIVE_F_424;
    discoveryConfig.NfcIPTgtMode = NFC_CX_NFCIP_TGT_NFC_A | NFC_CX_NFCIP_TGT_NFC_F | NFC_CX_NFCIP_TGT_NFC_ACTIVE_A | NFC_CX_NFCIP_TGT_NFC_ACTIVE_F;
    discoveryConfig.NfcCEMode = NFC_CX_CE_NFC_A | NFC_CX_CE_NFC_B | NFC_CX_CE_NFC_F;

    status = NfcCxSetRfDiscoveryConfig(device, &discoveryConfig);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxSetRfDiscoveryConfig failed. %!STATUS!", status);
        return status;
    }

    // Set the sequence handlers.
    for (int sequenceType = 0; sequenceType != SequenceMaximum; ++sequenceType)
    {
        status = NfcCxRegisterSequenceHandler(device, NFC_CX_SEQUENCE(sequenceType), SequenceHandlerCallback);
        if (!NT_SUCCESS(status))
        {
            TRACE_LINE(LEVEL_ERROR, "NfcCxRegisterSequenceHandler failed. %!STATUS!", status);
            return status;
        }
    }

    // Initialize callbacks manager.
    status = deviceContext->_ApiCallbacksManager.Initialize(device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "CallbacksManager::Initialize failed. %!STATUS!", status);
        return status;
    }

    // Create device interface for NciSim
    DECLARE_CONST_UNICODE_STRING(interfaceName, FILE_NAMESPACE_NCI_SIMULATOR);
    status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_NCI_SIMULATOR, &interfaceName);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreateDeviceInterface failed. %!STATUS!", status);
        return status;
    }

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
    return STATUS_SUCCESS;
}
Example #11
0
NTSTATUS
EvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
{
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;

    UNREFERENCED_PARAMETER(Driver);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfDeviceCreate failed %!STATUS!\n", status));
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device,
                                (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                NULL);// Reference String
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfDeviceCreateDeviceInterface failed %!STATUS!\n", status));
        return status;
    }

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;
    ioQueueConfig.EvtIoRead = EvtIoRead;
    ioQueueConfig.EvtIoWrite = EvtIoWrite;

    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. 
    // Please see 'final' step for implementation of EvtIoStop.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(device,
                         &ioQueueConfig,
                         WDF_NO_OBJECT_ATTRIBUTES,
                         WDF_NO_HANDLE);
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoQueueCreate failed  %!STATUS!\n", status));
        return status;
    }

    return status;
}
NTSTATUS
XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
{
  NTSTATUS status;
  WDF_CHILD_LIST_CONFIG child_list_config;
  WDFDEVICE device;
  PXENUSB_DEVICE_DATA xudd;
  //UNICODE_STRING reference;
  WDF_OBJECT_ATTRIBUTES device_attributes;
  PNP_BUS_INFORMATION pbi;
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
  WDF_IO_QUEUE_CONFIG queue_config;
  UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
  DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
  WDFSTRING symbolicname_value_wdfstring;
  WDFKEY device_key;
  UNICODE_STRING symbolicname_value;

  UNREFERENCED_PARAMETER(driver);

  FUNCTION_ENTER();

  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
  pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;

  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
    IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
  WdfDeviceInitSetExclusive(device_init, FALSE);

  WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
  child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
  WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);

  WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);

  WdfDeviceInitSetPowerNotPageable(device_init);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
  status = WdfDeviceCreate(&device_init, &device_attributes, &device);
  if (!NT_SUCCESS(status))
  {
    FUNCTION_MSG("Error creating device %08x\n", status);
    return status;
  }

  xudd = GetXudd(device);
  xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device);
  xudd->child_list = WdfFdoGetDefaultChildList(device);
  KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE);
  InitializeListHead(&xudd->partial_pvurb_queue);
  InitializeListHead(&xudd->partial_pvurb_ring);
  KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd);

  KeInitializeSpinLock(&xudd->urb_ring_lock);
  
  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
  queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
      return status;
  }

  WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
  //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
      return status;
  }

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
  power_capabilities.DeviceD1 = WdfTrue;
  power_capabilities.WakeFromD1 = WdfTrue;
  power_capabilities.DeviceWake = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(device, &power_capabilities);  

  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
  
  pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
  pbi.LegacyBusType = PNPBus;
  pbi.BusNumber = 0;
  WdfDeviceSetBusInformationForChildren(device, &pbi);

  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
    return status;
  }

  /* USB likes to have a registry key with the symbolic link name in it */
  status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfStringCreate returned %08x\n");
    return status;
  }
  status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
    return status;
  }
  WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
  status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
    return status;
  }
  WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);

  FUNCTION_EXIT();
  return status;
}
Example #13
0
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
BalloonDeviceAdd(
    IN WDFDRIVER  Driver,
    IN PWDFDEVICE_INIT  DeviceInit)
{
    NTSTATUS                     status = STATUS_SUCCESS;
    WDFDEVICE                    device;
    PDEVICE_CONTEXT              devCtx = NULL;
    WDF_INTERRUPT_CONFIG         interruptConfig;
    WDF_FILEOBJECT_CONFIG        fileConfig;
    WDF_OBJECT_ATTRIBUTES        attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;

    UNREFERENCED_PARAMETER(Driver);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware      = BalloonEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware      = BalloonEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry              = BalloonEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit               = BalloonEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = BalloonEvtDeviceD0ExitPreInterruptsDisabled;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_FILEOBJECT_CONFIG_INIT(
                            &fileConfig,
                            WDF_NO_EVENT_CALLBACK,
                            BalloonEvtFileClose,
                            WDF_NO_EVENT_CALLBACK
                            );

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                            &fileConfig,
                            WDF_NO_OBJECT_ATTRIBUTES);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    attributes.EvtCleanupCallback = BalloonEvtDeviceContextCleanup;
    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreate failed with status 0x%08x\n", status);
        return status;
    }

    devCtx = GetDeviceContext(device);

    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                            BalloonInterruptIsr,
                            BalloonInterruptDpc);

    interruptConfig.EvtInterruptEnable  = BalloonInterruptEnable;
    interruptConfig.EvtInterruptDisable = BalloonInterruptDisable;

    status = WdfInterruptCreate(device,
                            &interruptConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &devCtx->WdfInterrupt);
    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfInterruptCreate failed: 0x%08x\n", status);
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BALLOON, NULL);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status);
        return status;
    }
    devCtx->bShutDown = FALSE;
    devCtx->num_pages = 0;
    devCtx->PageListHead.Next = NULL;
    ExInitializeNPagedLookasideList(
                      &devCtx->LookAsideList,
                      NULL,
                      NULL,
                      0,
                      sizeof(PAGE_LIST_ENTRY),
                      BALLOON_MGMT_POOL_TAG,
                      0
                      );
    devCtx->bListInitialized = TRUE;
    devCtx->pfns_table = (PPFN_NUMBER)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      PAGE_SIZE,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->pfns_table == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    devCtx->MemStats = (PBALLOON_STAT)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->MemStats == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    RtlFillMemory (devCtx->MemStats, sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR, -1);

    KeInitializeEvent(&devCtx->HostAckEvent,
                      SynchronizationEvent,
                      FALSE
                      );

    status = BalloonQueueInitialize(device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "BalloonQueueInitialize failed with status 0x%08x\n", status);
        return status;
    }

    KeInitializeEvent(&devCtx->WakeUpThread,
                      SynchronizationEvent,
                      FALSE
                      );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
    return status;
}
//
// 作用相当于WDM中的AddDevice函数。
// 他是PNP过程中首当其冲被调用的回调函数。主要任务是创建设备对象。
// 设备对象在系统中以软件形式,代表外部的某个物理硬件设备。
//NTSTATUS PnpAdd(IN WDFDRIVER  Driver, IN PWDFDEVICE_INIT  DeviceInit)
NTSTATUS DrvClass::PnpAdd(IN PWDFDEVICE_INIT DeviceInit)
{
	NTSTATUS status;
	WDFDEVICE device;
	int nInstance = 0;
	PDEVICE_CONTEXT pContext = NULL;
	UNICODE_STRING DeviceName;
	UNICODE_STRING DosDeviceName;
	UNICODE_STRING RefString;
	WDFSTRING	   SymbolName;
	WDF_OBJECT_ATTRIBUTES attributes;
	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;

	WCHAR wcsDeviceName[] = L"\\Device\\CY001-0";		// 设备名
	WCHAR wcsDosDeviceName[] = L"\\DosDevices\\CY001-0";// 符号链接名
	WCHAR wcsRefString[] = L"CY001-0";					// 符号链接名
	int	  nLen = wcslen(wcsDeviceName);

	KDBG(DPFLTR_INFO_LEVEL, "[PnpAdd]");

	RtlInitUnicodeString(&DeviceName, wcsDeviceName) ;
	RtlInitUnicodeString(&DosDeviceName, wcsDosDeviceName);
	RtlInitUnicodeString(&RefString, wcsRefString);

	WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
	InitPnpPwrEvents(&pnpPowerCallbacks);
	WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	// 读、写请求的缓冲方式
	// 默认为Buffered方式,另外两种方式是Direct和Neither。
	WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

	// 设定设备环境块长度
	// 宏内部会调用sizeof(DEVICE_CONTEXT)求结构体长度
	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

	// 驱动支持最多8个实例,即当多个开发板连到PC上时,驱动对它们给予并行支持。
	// 不同的设备对象,各以其名称的尾数(0-7)相别,并将此尾数称作设备ID。
	// 下面的代码逻辑为当前设备对象寻找一个可用ID。
	for(nInstance = 0; nInstance < MAX_INSTANCE_NUMBER; nInstance++)
	{
		// 修改设备ID
		wcsDeviceName[nLen-1] += nInstance;

		// 尝试命名;命名可能失败,失败的原因包括:名称无效、名称已存在等
		WdfDeviceInitAssignName(DeviceInit, &DeviceName);

		// 创建WDF设备
		// 如能成功,则命名亦成功。
		status = WdfDeviceCreate(&DeviceInit, &attributes, &device);  
		if(!NT_SUCCESS(status))
		{
			if(status == STATUS_OBJECT_NAME_COLLISION)// 名字冲突
			{
				KDBG(DPFLTR_ERROR_LEVEL, "Already exist: %wZ", &DeviceName);
			}
			else
			{
				KDBG(DPFLTR_ERROR_LEVEL, "WdfDeviceCreate failed with status 0x%08x!!!", status);
				return status;
			}
		}else
		{
			KdPrint(("Device name: %wZ", &DeviceName));
			break;
		}
	}

	// 如失败,可能是连接的开发板数量太多;
	// 建议使用WinOBJ查看系统中的设备名称。
	if (!NT_SUCCESS(status)) 
		return status;

	m_hDevice = device;// 保存设备对象句柄

	// 创建符号链接,应用程序根据符号链接查看并使用内核设备。
	// 除了创建符号链接外,现在更好的方法是使用WdfDeviceCreateDeviceInterface创建设备接口。
	// 设备接口能保证名字不会冲突,但不具有可读性,所以我们仍采用符号链接形式。
	nLen = wcslen(wcsDosDeviceName);
	wcsDosDeviceName[nLen-1] += nInstance;

	status = WdfDeviceCreateSymbolicLink(device, &DosDeviceName);
	if(!NT_SUCCESS(status))
	{
		KDBG(DPFLTR_INFO_LEVEL, "Failed to create symbol link: 0x%08X", status);
		return status;
	}

	// 初始化环境块
	// GetDeviceContext是一个函数指针,由宏WDF_DECLARE_CONTEXT_TYPE_WITH_NAME定义。
	// 参看pulibc.h中的说明。
	pContext = GetDeviceContext(device);
	RtlZeroMemory(pContext, sizeof(DEVICE_CONTEXT));
	pContext->par1 = this; // 通过this指针可以得到一切

	// PNP属性。允许设备异常拔除,系统不会弹出错误框。
	WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
	InitPnpCap(&pnpCapabilities);
	WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);

	status = CreateWDFQueues();
	if(!NT_SUCCESS(status))
		return status;

	return status;
}
Example #16
0
NTSTATUS
RoboDeviceCreateDevice(
    _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

--*/
{
    DEVICE_CONTEXT* pCtx;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    scope
    {
        // pnpPowerCallbacks structure
        WDF_PNPPOWER_EVENT_CALLBACKS pnpPwrCallbacks;
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT( &pnpPwrCallbacks );
        pnpPwrCallbacks.EvtDevicePrepareHardware = RoboDeviceEvtDevicePrepareHardware;
        pnpPwrCallbacks.EvtDeviceReleaseHardware = RoboDeviceEvtDeviceReleaseHardware;
        pnpPwrCallbacks.EvtDeviceD0Entry = RoboDeviceEvtDeviceD0Entry;
        pnpPwrCallbacks.EvtDeviceD0Exit = RoboDeviceEvtDeviceD0Exit;
        WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPwrCallbacks);
    }


    {
        // power policy callback used to arm/disarm hardware to handle wait-wake
        WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;
        WDF_POWER_POLICY_EVENT_CALLBACKS_INIT( &powerPolicyCallbacks );
        powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = RoboDeviceEvtDeviceArmWakeFromS0;
        powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = RoboDeviceEvtDeviceDisarmWakeFromS0;
        powerPolicyCallbacks.EvtDeviceWakeFromS0Triggered = RoboDeviceEvtDeviceWakeFromS0Triggered;
        powerPolicyCallbacks.EvtDeviceArmWakeFromSx = RoboDeviceEvtDeviceArmWakeFromSx;
        powerPolicyCallbacks.EvtDeviceDisarmWakeFromSx = RoboDeviceEvtDeviceDisarmWakeFromSx;
        powerPolicyCallbacks.EvtDeviceWakeFromSxTriggered = RoboDeviceEvtDeviceWakeFromSxTriggered;
        WdfDeviceInitSetPowerPolicyEventCallbacks( DeviceInit, &powerPolicyCallbacks );
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &attributes, DEVICE_CONTEXT );
    attributes.EvtCleanupCallback = RoboDeviceEvtDeviceContextCleanup;

    status = WdfDeviceCreate( &DeviceInit, &attributes, &device );
    if( !NT_SUCCESS(status) ) {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WdfDeviceCreate failed: 0x%x", status );
        return status;
    }

    // Initialize the context
    pCtx = DeviceGetContext( device );
    pCtx->PrivateDeviceData = 0;

    status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_RoboDevice, NULL );
    if( !NT_SUCCESS(status) ) {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Error Create device interface: 0x%x", status );
        return status;
    }

    status = RoboDeviceQueueInitialize( device );
	
	/*

    scope {
        WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
        WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT( &idleSettings, IdleCannotWakeFromS0 );
        idleSettings.IdleTimeout = 60000;
        status = WdfDeviceAssignS0IdleSettings( device, &idleSettings );
    }

    scope {
        WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
        WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT( &wakeSettings );
        WdfDeviceAssignSxWakeSettings( device, &wakeSettings );
    }


	*/

    return status;
}
Example #17
0
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;
}
// This routine is the AddDevice entry point for the fake activity client
// driver. This routine is called by the framework in response to AddDevice
// call from the PnP manager. It will create and initialize the device object
// to represent a new instance of the sensor client.
NTSTATUS ActivityDevice::OnDeviceAdd(
    _In_ WDFDRIVER /*driver*/,              // Supplies a handle to the driver object created in DriverEntry
    _Inout_ PWDFDEVICE_INIT pDeviceInit)    // Supplies a pointer to a framework-allocated WDFDEVICE_INIT structure
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    // Initialize FDO attributes and set up file object with sensor extension
    WDF_OBJECT_ATTRIBUTES fdoAttributes = {};
    ULONG flag = 0;

    WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
    status = SensorsCxDeviceInitConfig(pDeviceInit, &fdoAttributes, flag);
    if (!NT_SUCCESS(status))
    {
        TraceError("ACT %!FUNC! SensorsCxDeviceInitConfig failed %!STATUS!", status);
    }
    else
    {
        WDF_PNPPOWER_EVENT_CALLBACKS callbacks = {};
        WDFDEVICE device = NULL;

        // Register the PnP callbacks with the framework.
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&callbacks);
        callbacks.EvtDevicePrepareHardware = ActivityDevice::OnPrepareHardware;
        callbacks.EvtDeviceReleaseHardware = ActivityDevice::OnReleaseHardware;
        callbacks.EvtDeviceD0Entry = ActivityDevice::OnD0Entry;
        callbacks.EvtDeviceD0Exit = ActivityDevice::OnD0Exit;
        WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &callbacks);

        // Call the framework to create the device
        status = WdfDeviceCreate(&pDeviceInit, &fdoAttributes, &device);
        if (!NT_SUCCESS(status))
        {
            TraceError("ACT %!FUNC! WdfDeviceCreate failed %!STATUS!", status);
        }
        else
        {
            SENSOR_CONTROLLER_CONFIG sensorConfig = {};

            // Register CLX callback function pointers
            SENSOR_CONTROLLER_CONFIG_INIT(&sensorConfig);
            sensorConfig.DriverIsPowerPolicyOwner = WdfUseDefault;

            sensorConfig.EvtSensorStart = ActivityDevice::OnStart;
            sensorConfig.EvtSensorStop = ActivityDevice::OnStop;
            sensorConfig.EvtSensorGetSupportedDataFields = ActivityDevice::OnGetSupportedDataFields;
            sensorConfig.EvtSensorGetDataInterval = ActivityDevice::OnGetDataInterval;
            sensorConfig.EvtSensorSetDataInterval = ActivityDevice::OnSetDataInterval;
            sensorConfig.EvtSensorGetDataFieldProperties = ActivityDevice::OnGetDataFieldProperties;
            sensorConfig.EvtSensorGetDataThresholds = ActivityDevice::OnGetDataThresholds;
            sensorConfig.EvtSensorSetDataThresholds = ActivityDevice::OnSetDataThresholds;
            sensorConfig.EvtSensorGetProperties = ActivityDevice::OnGetProperties;
            sensorConfig.EvtSensorDeviceIoControl = ActivityDevice::OnIoControl;
            sensorConfig.EvtSensorStartHistory = ActivityDevice::OnStartHistory;
            sensorConfig.EvtSensorStopHistory = ActivityDevice::OnStopHistory;
            sensorConfig.EvtSensorClearHistory = ActivityDevice::OnClearHistory;
            sensorConfig.EvtSensorStartHistoryRetrieval = ActivityDevice::OnStartHistoryRetrieval;
            sensorConfig.EvtSensorCancelHistoryRetrieval = ActivityDevice::OnCancelHistoryRetrieval;

            // Set up power capabilities and IO queues
            status = SensorsCxDeviceInitialize(device, &sensorConfig);
            if (!NT_SUCCESS(status))
            {
                TraceError("ACT %!FUNC! SensorsCxDeviceInitialize failed %!STATUS!", status);
            }
        }
    }

    SENSOR_FunctionExit(status);
    return status;
}
Example #19
0
NTSTATUS
AmccPciAddDevice(
    _In_    WDFDRIVER        Driver,
    _Inout_ PWDFDEVICE_INIT  DeviceInit
    )
/*++

Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager.  It is responsible for initializing and
    creating a WDFDEVICE object.

    Any work that should be done after the object is created should be
    deferred until EvtDeviceSoftwareInit, as that callback will be made
    with the device lock held (if there is one.)

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_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES       fdoAttributes;
    WDF_INTERRUPT_CONFIG        interruptConfig;
    WDF_OBJECT_ATTRIBUTES       interruptAttributes;
    WDF_IO_QUEUE_CONFIG         ioQueueConfig;
    PAMCC_DEVICE_EXTENSION           devExt;
    WDFQUEUE                    hQueue;
    WDFDEVICE                   device;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_INIT,
                        "AmccPciAddDevice: 0x%p", Driver);

    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = AmccPciEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = AmccPciEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry         = AmccPciEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit          = AmccPciEvtDeviceD0Exit;

    //
    // Register the PnP Callbacks..
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    //
    // Set various attributes for this device
    //
    WdfDeviceInitSetIoType( DeviceInit, WdfDeviceIoDirect );

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, AMCC_DEVICE_EXTENSION);
    fdoAttributes.EvtCleanupCallback = AmccPciContextCleanup;
    //
    // We want all the queue callbacks, cancel routine, and DpcForIsr to be serialized
    // at the device level, so we don't have worry about any synchronization issues.
    //
    fdoAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;

    status = WdfDeviceCreate( &DeviceInit, &fdoAttributes, &device );

    if ( !NT_SUCCESS(status) ) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                                "WdfDeviceInitialize failed 0x%X", status);
        return status;
    }

    //
    // Device Initialization is complete.
    // Get the Device Extension and initialize it.
    //
    devExt = AmccPciGetDevExt(device);

    devExt->Device = device;

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_INIT,
                        "PDO 0x%p, FDO 0x%p, DevExt 0x%p",
                        WdfDeviceWdmGetPhysicalDevice(device),
                        WdfDeviceWdmGetDeviceObject( device ), devExt);

    //
    // This device generates an interrupt.  So create an interrupt object which
    // will later be associated with the devices resources and connected
    // by the Framework.
    //

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&interruptAttributes, INTERRUPT_DATA);

    //
    // Configure the Interrupt object
    //
    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                              AmccPciEvtInterruptIsr,
                              AmccPciEvtInterruptDpc);

    status = WdfInterruptCreate(device,
                                &interruptConfig,
                                &interruptAttributes,
                                &devExt->WdfInterrupt);
    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                    "WdfInterruptCreate failed: %!STATUS!\n", status);
        return status;
    }

    //
    // The S5933 requires DMA buffers be aligned on a 32-bit boundary
    //
    // NOTE: Read the existing alignment value. If it is greater than
    //       or equal then keep it.  If it is less then update the
    //       alignment requirement field with this device's required
    //       value.
    //
    // NOTE: See the MSDN section titled "Initializing a Device Object"
    //       for details on how to specify this alignment value.
    //
    // NOTE: AMCC5933_ALIGNMENT__32BITS is equated to (4-1) for 32-bit
    //       alignment.
    //
    {
        ULONG alignReq;

        alignReq = WdfDeviceGetAlignmentRequirement( device );

        if (alignReq < AMCC5933_ALIGNMENT__32BITS) {

            //
            // Set the S5933 alignment requirement as new value.
            //
            WdfDeviceSetAlignmentRequirement( device,
                                              AMCC5933_ALIGNMENT__32BITS);
        }
    }

    //
    // Register I/O callbacks.
    //
    // Create a sequential IO Queue for serial operation. That means all the requests (Read/Write
    // & IOCTL) are serialized to the device. Until the driver completes the request presented to it,
    // the framework will not schedule another one. The requests held in the framework will be
    // cancelled automatically if the source of request (application) terminate or cancels it.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &ioQueueConfig,
                              WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDefault = AmccPciEvtIoDefault;
    
    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests for 
    // long time or forward them to other drivers. 
    // If the EvtIoStop callback is not implemented, the framework waits for
    // all driver-owned requests to be done before moving in the Dx/sleep 
    // states or before removing the device, which is the correct behavior 
    // for this type of driver. If the requests were taking an indeterminate
    // amount of time to complete, or if the driver forwarded the requests
    // to a lower driver/another stack, the queue should have an 
    // EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate( device,
                               &ioQueueConfig,
                               WDF_NO_OBJECT_ATTRIBUTES,
                               &hQueue );
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS (status)) {
        //
        // We don't have worry about deleting the device here because framework will automatically
        // cleanup that when the driver unloads.
        //
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                                "WdfIoQueueCreate failed %!STATUS!", status);
        return status;
    }

    //
    // Register an interface so that application can find and talk to us.
    // NOTE: See the note in Public.h concerning this GUID value.
    //
    status = WdfDeviceCreateDeviceInterface( device,
                                             (LPGUID) &GUID_DEVINTERFACE_AMCC_PCI,
                                             NULL );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                "<-- AMCCAddDevice: WdfDeviceCreateDeviceInterface failed %!STATUS!", status);
        return status;
    }

    devExt->MaximumTransferLength = MAXIMUM_REQUEST_CONTEXT_LENGTH;

    //
    // Set the maximum physical pages for now, but this value may change if
    // there aren't enough map registers
    //
    devExt->MaximumPhysicalPages = MAXIMUM_PHYSICAL_PAGES;

    return status;
}
Example #20
0
NTSTATUS
OsrFxEvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device. All the software resources
    should be allocated in this callback.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");

    //
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter 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 = OsrFxEvtDevicePrepareHardware;

    //
    // These two callbacks start and stop the WDFUSBPIPE continuous reader
    // as we go in and out of the D0-working state.
    //

    pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    OsrFxInitChildList(DeviceInit);

    //
    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "OsrFxEvtDeviceAdd  - ends\n");

    return status;
}
Example #21
0
File: device.c Project: MHesham/bsp
VCHIQ_PAGED_SEGMENT_BEGIN

/*++

Routine Description:

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

Arguments:

     DeviceInitPtr - 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

--*/
_Use_decl_annotations_
NTSTATUS VchiqCreateDevice (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInitPtr
    )
{
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    DEVICE_CONTEXT* deviceContextPtr;
    WDFDEVICE device;
    NTSTATUS status;
    WDF_IO_TYPE_CONFIG ioConfig;
    DECLARE_CONST_UNICODE_STRING(vchiqSymbolicLink, VCHIQ_SYMBOLIC_NAME);

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    {
        WDF_FILEOBJECT_CONFIG fileobjectConfig;
        WDF_FILEOBJECT_CONFIG_INIT(
            &fileobjectConfig,
            WDF_NO_EVENT_CALLBACK,
            VchiqFileClose,
            WDF_NO_EVENT_CALLBACK);

        fileobjectConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext;

        WdfDeviceInitSetFileObjectConfig(
            DeviceInitPtr,
            &fileobjectConfig,
            WDF_NO_OBJECT_ATTRIBUTES);
    }

    WDF_IO_TYPE_CONFIG_INIT(&ioConfig);
    ioConfig.ReadWriteIoType = WdfDeviceIoDirect;
    ioConfig.DeviceControlIoType = WdfDeviceIoDirect;
    ioConfig.DirectTransferThreshold = 0;

    WdfDeviceInitSetIoTypeEx(DeviceInitPtr, &ioConfig);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = 
        VchiqPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware =
        VchiqReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = 
        VchiqInitOperation;
    WdfDeviceInitSetPnpPowerEventCallbacks(
        DeviceInitPtr, 
        &pnpPowerCallbacks);

    WdfDeviceInitSetIoInCallerContextCallback(
        DeviceInitPtr,
        VchiqInCallerContext);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
        &deviceAttributes, 
        DEVICE_CONTEXT);

    status = WdfDeviceCreate(
        &DeviceInitPtr,
        &deviceAttributes,
        &device);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "WdfDeviceCreate fail %!STATUS!", status);
        goto End;
    }

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_IO_QUEUE_CONFIG queueConfig;
        WDFQUEUE queue;

        deviceContextPtr = VchiqGetDeviceContext(device);
        deviceContextPtr->Device = device;
        deviceContextPtr->VersionMajor = VCHIQ_VERSION_MAJOR;
        deviceContextPtr->VersionMinor = VCHIQ_VERSION_MINOR;

        deviceContextPtr->PhyDeviceObjectPtr =
            WdfDeviceWdmGetPhysicalDevice(device);

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
            &queueConfig,
            WdfIoQueueDispatchParallel);
        queueConfig.EvtIoDeviceControl = VchiqIoDeviceControl;
        queueConfig.EvtIoStop = VchiqIoStop;

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfIoQueueCreate(
            device,
            &queueConfig,
            &attributes,
            &queue);
        if (!NT_SUCCESS(status)) {
            VCHIQ_LOG_ERROR(
                "WdfIoQueueCreate fail %!STATUS!", status);
            goto End;
        }
    }

    // Create symbolic and device interface
    status = WdfDeviceCreateSymbolicLink(
        device,
        &vchiqSymbolicLink);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "Fail to register symbolic link %!STATUS!",
            status);
        goto End;
    }

End:
    VCHIQ_LOG_INFORMATION("Exit Status %!STATUS!", status);

    return status;
}
NTSTATUS
VIOSerialDeviceListCreatePdo(
    IN WDFCHILDLIST DeviceList,
    IN PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
    IN PWDFDEVICE_INIT ChildInit
    )
{
    PVIOSERIAL_PORT                 pport = NULL;
    NTSTATUS                        status = STATUS_SUCCESS;

    WDFDEVICE                       hChild = NULL;

    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS    PnpPowerCallbacks;
    WDF_DEVICE_PNP_CAPABILITIES     pnpCaps;
    WDF_DEVICE_STATE                deviceState;
    WDF_IO_QUEUE_CONFIG             queueConfig;
    PRAWPDO_VIOSERIAL_PORT          rawPdo = NULL;
    WDF_FILEOBJECT_CONFIG           fileConfig;

    DECLARE_CONST_UNICODE_STRING(deviceId, PORT_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"RedHat VIOSerial Port" );

    DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);

    UNREFERENCED_PARAMETER(DeviceList);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    pport = CONTAINING_RECORD(IdentificationDescription,
                                 VIOSERIAL_PORT,
                                 Header
                                 );

    WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_SERIAL_PORT);
    WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);

    do
    {
        WdfDeviceInitSetExclusive(ChildInit, TRUE);
        status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_PORT_DEVICE);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignRawDevice failed - 0x%x\n", status);
           break;
        }

        status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceInitAssignSDDLString failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignDeviceID failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddHardwareID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddHardwareID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"%02u",
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignInstanceID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"vport%up%u",
                                 pport->DeviceId,
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "RtlUnicodeStringPrintf failed 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddDeviceText(
                                 ChildInit,
                                 &buffer,
                                 &deviceLocation,
                                 0x409
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfPdoInitAddDeviceText failed 0x%x\n", status);
           break;
        }

        WdfPdoInitSetDefaultLocale(ChildInit, 0x409);

        WDF_FILEOBJECT_CONFIG_INIT(
                                 &fileConfig,
                                 VIOSerialPortCreate,
                                 VIOSerialPortClose,
                                 WDF_NO_EVENT_CALLBACK
                                 );

        WdfDeviceInitSetFileObjectConfig(
                                 ChildInit,
                                 &fileConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES
                                 );

        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
        PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry;
        PnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = VIOSerialPortEvtDeviceD0ExitPreInterruptsDisabled;
        PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit;
        WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks);

        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
        attributes.SynchronizationScope = WdfSynchronizationScopeDevice;
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfDeviceCreate(
                                 &ChildInit,
                                 &attributes,
                                 &hChild
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreate failed 0x%x\n", status);
           break;
        }

        rawPdo = RawPdoSerialPortGetData(hChild);
        rawPdo->port = pport;
        pport->Device = hChild;

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential
                                 );

        queueConfig.EvtIoDeviceControl = VIOSerialPortDeviceControl;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->IoctlQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->IoctlQueue,
                                 WdfRequestTypeDeviceControl
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential);

        queueConfig.EvtIoRead   =  VIOSerialPortRead;
        queueConfig.EvtIoStop   =  VIOSerialPortIoStop;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->ReadQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate (Read Queue) failed 0x%x\n", status);
           break;
        }

        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->ReadQueue,
                                 WdfRequestTypeRead
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Read Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
        queueConfig.AllowZeroLengthRequests = WdfFalse;
        queueConfig.EvtIoWrite = VIOSerialPortWrite;

        status = WdfIoQueueCreate(hChild, &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES, &pport->WriteQueue);

        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (Write Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->WriteQueue,
                                 WdfRequestTypeWrite
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Write Queue): 0x%x\n", status);
           break;
        }

        WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

        pnpCaps.NoDisplayInUI    =  WdfTrue;
        pnpCaps.Removable        =  WdfTrue;
        pnpCaps.EjectSupported   =  WdfTrue;
        pnpCaps.SurpriseRemovalOK=  WdfTrue;
        pnpCaps.Address          =  pport->DeviceId;
        pnpCaps.UINumber         =  pport->PortId;

        WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.DontDisplayInUI = WdfTrue;
        WdfDeviceSetDeviceState(hChild, &deviceState);

        status = WdfDeviceCreateDeviceInterface(
                                 hChild,
                                 &GUID_VIOSERIAL_PORT,
                                 NULL
                                 );

        if (!NT_SUCCESS (status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreateDeviceInterface failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->InBufLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->OutVqLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

    } while (0);

    if (!NT_SUCCESS(status))
    {
        // We can send this before PDO is PRESENT since the device won't send any response.
        VIOSerialSendCtrlMsg(pport->BusDevice, pport->PortId, VIRTIO_CONSOLE_PORT_READY, 0);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s status 0x%x\n", __FUNCTION__, status);
    return status;
}
Example #23
0
NTSTATUS
EchoDeviceCreate(
    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 attributes;
    PDEVICE_CONTEXT deviceContext;
    WDF_PNPPOWER_EVENT_CALLBACKS    pnpPowerCallbacks;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Register pnp/power callbacks so that we can start and stop the timer as the device
    // gets started and stopped.
    //
    pnpPowerCallbacks.EvtDeviceSelfManagedIoInit    = EchoEvtDeviceSelfManagedIoStart;
    pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = EchoEvtDeviceSelfManagedIoSuspend;

    //
    // Function used for both Init and Restart Callbacks
    //
    #pragma warning(suppress: 28024)
    pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = EchoEvtDeviceSelfManagedIoStart;

    //
    // Register the PnP and power callbacks. Power policy related callbacks will be registered
    // later in SotwareInit.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
    WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);

    if (NT_SUCCESS(status)) {
        //
        // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT 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 = WdfObjectGet_DEVICE_CONTEXT(device);
        deviceContext->PrivateDeviceData = 0;

        //
        // Create a device interface so that application can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(
            device,
            &GUID_DEVINTERFACE_ECHO,
            NULL // ReferenceString
            );

        if (NT_SUCCESS(status)) {
            //
            // Initialize the I/O Package and any Queues
            //
            status = EchoQueueInitialize(device);
        }
    }

    return status;
}
Example #24
0
///////////////////////////////////////////////////////////////////////////////
//
//  BasicUsbEvtDeviceAdd
//
//    This routine is called by the framework when a device of
//    the type we support is found in the system.
//
//  INPUTS:
//
//      DriverObject - Our WDFDRIVER object
//
//      DeviceInit   - The device iniitalization structure we'll
//                     be using to create our WDFDEVICE
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS, otherwise an error indicating why the driver could not
//                      load.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL.
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
BasicUsbEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES objAttributes;
    WDFDEVICE device;
    WDF_IO_QUEUE_CONFIG queueConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    PBASICUSB_DEVICE_CONTEXT  devContext;   
    

#if DBG
    DbgPrint("BasicUsbEvtDeviceAdd\n");
#endif
   
    
    //
    // Our "internal" (native) and user-accessible device names
    //
    DECLARE_CONST_UNICODE_STRING(nativeDeviceName, L"\\Device\\BasicUsb");
    DECLARE_CONST_UNICODE_STRING(userDeviceName, L"\\Global??\\BasicUsb");
    
    UNREFERENCED_PARAMETER(Driver);

    //
    // Life is a bit more complicated in this driver...
    //
    // We need an EvtPrepareHardware to configure our device. In addition, we
    // must handle EvtD0Entry and EvtD0Exit in order to manage our continuous
    // reader.
    //
    
    //
    // Prepare for WDFDEVICE creation
    //
    // Initialize standard WDF Object Attributes structure
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes);

    //
    // Specify our device context
    //
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes,
                                        BASICUSB_DEVICE_CONTEXT);

    //
    // We want our device object NAMED, thank you very much
    //
    status = WdfDeviceInitAssignName(DeviceInit, &nativeDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceInitAssignName failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Set our I/O type to DIRECT, meaning that we want to receive
    // MDLs for both read and write requests.
    //
    // While we are not obligated to choose direct, USB drivers
    // typically do so because the USB bus driver needs MDLs to
    // actually perform the transfer. If we select DIRECT I/O, the
    // bus driver can just use the MDL that we're given as opposed
    // to creating his own.
    //
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
    
    //
    // In this driver we need to be notified of some Pnp/Power
    // events, so initialize a pnp power callbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // USB drivers configure their device within prepare hardware,
    // so register an EvtDevicePrepareHardware callback.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware 
                                     = BasicUsbEvtDevicePrepareHardware;

    //
    // Our driver uses a continuous reader on the interrupt pipe to
    // be notified asynchronously of changes to the OSRFX2's
    // switchpack. We need to start the reader in D0Entry and stop
    // it in D0Exit, so register for EvtDeviceD0Entry and
    // EvtDeviceD0Exit callbacks
    //
    pnpPowerCallbacks.EvtDeviceD0Entry = BasicUsbEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = BasicUsbEvtDeviceD0Exit;  

    //
    // Update the DeviceInit structure to contain the new callbacks.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, 
                                           &pnpPowerCallbacks);

    //
    // We want to send control transfers synchronously from within
    // EvtIoDeviceControl, so we'll apply a PASSIVE_LEVEL constraint
    // to our device
    //
    objAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // Now let's create our device object
    //
    status = WdfDeviceCreate(&DeviceInit,
                            &objAttributes, 
                            &device);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreate failed 0x%0x\n", status);
#endif
        return status;
    }

    //
    // Create a symbolic link for the control object so that usermode can open
    // the device by name.
    //
    status = WdfDeviceCreateSymbolicLink(device, &userDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // ALSO create a device interface for the device
    // This allows usage of the lovely SetupApiXxxx functions to locate
    // the device
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                    &GUID_DEVINTERFACE_BASICUSB,
                                    NULL);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateDeviceInterface failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Configure our queue of incoming requests
    //
    // We only use the default queue, and we set it for parallel processing.
    // We chose this because we may have, say, a bulk read hanging on the bus
    // driver that won't get completed until we send down a bulk write.
    //
    // If we chose a sequential queue we wouldn't be presented the write from
    // the user until the read completed, but the read wouldn't complete
    // until we were presented the write from the user - resulting in an "I/O
    // deadlock".
    //
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
                                           WdfIoQueueDispatchParallel);

    //
    // Declare our I/O Event Processing callbacks
    //
    // We handle, read, write, and device control requests.
    //
    // WDF will automagically handle Create and Close requests for us and will
    // will complete any OTHER request types with STATUS_INVALID_DEVICE_REQUEST.    
    //
    queueConfig.EvtIoRead = BasicUsbEvtRead;
    queueConfig.EvtIoWrite = BasicUsbEvtWrite;
    queueConfig.EvtIoDeviceControl = BasicUsbEvtDeviceControl;

    //
    // Because this is a queue for a real hardware
    // device, indicate that the queue needs to be
    // power managed
    //
    queueConfig.PowerManaged = WdfTrue;

    status = WdfIoQueueCreate(device,
                            &queueConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            NULL); // optional pointer to receive queue handle

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for default queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    devContext = BasicUsbGetContextFromDevice(device);

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                             WdfIoQueueDispatchManual);

    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &devContext->SwitchPackStateChangeQueue);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for manual queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    return(STATUS_SUCCESS);
}
Example #25
0
_Use_decl_annotations_
NTSTATUS OnDeviceAdd (WDFDRIVER /*WdfDriver*/, WDFDEVICE_INIT* DeviceInitPtr)
{
    PAGED_CODE();
    BCM_I2C_ASSERT_MAX_IRQL(PASSIVE_LEVEL);

    NTSTATUS status;

    //
    // Configure DeviceInit structure
    //
    status = SpbDeviceInitConfig(DeviceInitPtr);
    if (!NT_SUCCESS(status)) {
        BSC_LOG_ERROR(
            "SpbDeviceInitConfig() failed. (DeviceInitPtr = %p, status = %!STATUS!)",
            DeviceInitPtr,
            status);
        return status;
    }

    //
    // 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(DeviceInitPtr, &pnpCallbacks);
    }

    //
    // Create the device.
    //
    WDFDEVICE wdfDevice;
    BCM_I2C_DEVICE_CONTEXT* devicePtr;
    {
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &deviceAttributes,
            BCM_I2C_DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &DeviceInitPtr,
            &deviceAttributes,
            &wdfDevice);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create WDFDEVICE. (DeviceInitPtr = %p, status = %!STATUS!)",
                DeviceInitPtr,
                status);
            return status;
        }

        devicePtr = GetDeviceContext(wdfDevice);
        NT_ASSERT(devicePtr);
        devicePtr->WdfDevice = wdfDevice;
    }

    //
    // Query registry for ClockStretchTimeout
    //
    {
        WDFKEY wdfKey;
        status = WdfDeviceOpenRegistryKey(
                wdfDevice,
                PLUGPLAY_REGKEY_DEVICE,
                KEY_QUERY_VALUE,
                WDF_NO_OBJECT_ATTRIBUTES,
                &wdfKey);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to open device parameters registry key. (status=%!STATUS!)",
                status);
            return status;
        }
        auto closeRegKey = Finally([&] {
            PAGED_CODE();
            WdfRegistryClose(wdfKey);
        });

        DECLARE_CONST_UNICODE_STRING(
            regValString,
            REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);

        ULONG clockStretchTimeout;
        status = WdfRegistryQueryULong(
                wdfKey,
                &regValString,
                &clockStretchTimeout);
        if (NT_SUCCESS(status)) {
            if ((clockStretchTimeout & BCM_I2C_REG_CLKT_TOUT_MASK) !=
                 clockStretchTimeout) {

                BSC_LOG_ERROR(
                    "Clock stretch timeout value from registry is out of range. (clockStretchTimeout=0x%x, BCM_I2C_REG_CLKT_TOUT_MASK=0x%x)",
                    clockStretchTimeout,
                    BCM_I2C_REG_CLKT_TOUT_MASK);
                return STATUS_INVALID_PARAMETER;
            }

            BSC_LOG_INFORMATION(
                "Using ClockStretchTimeout value from registry. (clockStretchTimeout=0x%x)",
                clockStretchTimeout);

        } else {
            switch (status) {
            case STATUS_OBJECT_NAME_NOT_FOUND:
                clockStretchTimeout = BCM_I2C_REG_CLKT_TOUT_DEFAULT;
                status = STATUS_SUCCESS;
                break;
            default:
                BSC_LOG_ERROR(
                    "Failed to query clock stretch timeout from registry. (status=%!STATUS!, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT=%S)",
                    status,
                    REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);
                return status;
            }
        }

        devicePtr->ClockStretchTimeout = clockStretchTimeout;
    }

    //
    // Ensure device is disable-able
    //
    {
        WDF_DEVICE_STATE deviceState;
        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.NotDisableable = WdfFalse;
        WdfDeviceSetDeviceState(wdfDevice, &deviceState);
    }

    //
    // Bind a SPB controller object to the device.
    //
    {
        SPB_CONTROLLER_CONFIG spbConfig;
        SPB_CONTROLLER_CONFIG_INIT(&spbConfig);

        //
        // Register for target connect callback.  The driver
        // does not need to respond to target disconnect.
        //

        spbConfig.EvtSpbTargetConnect = OnTargetConnect;

        //
        // Register for IO callbacks.
        //

        spbConfig.ControllerDispatchType = WdfIoQueueDispatchSequential;
        spbConfig.EvtSpbIoRead = OnRead;
        spbConfig.EvtSpbIoWrite = OnWrite;
        spbConfig.EvtSpbIoSequence = OnSequence;

        status = SpbDeviceInitialize(wdfDevice, &spbConfig);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "SpbDeviceInitialize failed. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }
    }

    //
    // Set target object attributes.
    //
    {
        WDF_OBJECT_ATTRIBUTES targetAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &targetAttributes,
            BCM_I2C_TARGET_CONTEXT);

        SpbControllerSetTargetAttributes(wdfDevice, &targetAttributes);
    }

    //
    // Create an interrupt object
    //
    BCM_I2C_INTERRUPT_CONTEXT* interruptContextPtr;
    {
        WDF_OBJECT_ATTRIBUTES interruptObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &interruptObjectAttributes,
            BCM_I2C_INTERRUPT_CONTEXT);

        WDF_INTERRUPT_CONFIG interruptConfig;
        WDF_INTERRUPT_CONFIG_INIT(
            &interruptConfig,
            OnInterruptIsr,
            OnInterruptDpc);

        status = WdfInterruptCreate(
            wdfDevice,
            &interruptConfig,
            &interruptObjectAttributes,
            &devicePtr->WdfInterrupt);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create interrupt object. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }

        interruptContextPtr = GetInterruptContext(devicePtr->WdfInterrupt);
        interruptContextPtr->WdfInterrupt = devicePtr->WdfInterrupt;
    }
    devicePtr->InterruptContextPtr = interruptContextPtr;

    NT_ASSERT(NT_SUCCESS(status));
    return STATUS_SUCCESS;
}
Example #26
0
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;
}
// This routine is the AddDevice entry point for the custom sensor client
// driver. This routine is called by the framework in response to AddDevice
// call from the PnP manager. It will create and initialize the device object
// to represent a new instance of the sensor client.
NTSTATUS CustomSensorDevice::OnDeviceAdd(
    _In_ WDFDRIVER /*Driver*/,            // Supplies a handle to the driver object created in DriverEntry
    _Inout_ PWDFDEVICE_INIT pDeviceInit   // Supplies a pointer to a framework-allocated WDFDEVICE_INIT structure
)
{
    WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
    WDFDEVICE Device = nullptr;
    WDF_OBJECT_ATTRIBUTES FdoAttributes;
    ULONG Flag = 0;
    SENSOR_CONTROLLER_CONFIG SensorConfig;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    WDF_OBJECT_ATTRIBUTES_INIT(&FdoAttributes);

    // Initialize FDO attributes and set up file object with sensor extension
    Status = SensorsCxDeviceInitConfig(pDeviceInit, &FdoAttributes, Flag);
    if (!NT_SUCCESS(Status))
    {
        TraceError("CSTM %!FUNC! SensorsCxDeviceInitConfig failed %!STATUS!", Status);
        goto Exit;
    }

    // Register the PnP callbacks with the framework.
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
    Callbacks.EvtDevicePrepareHardware = CustomSensorDevice::OnPrepareHardware;
    Callbacks.EvtDeviceReleaseHardware = CustomSensorDevice::OnReleaseHardware;
    Callbacks.EvtDeviceD0Entry = CustomSensorDevice::OnD0Entry;
    Callbacks.EvtDeviceD0Exit = CustomSensorDevice::OnD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &Callbacks);

    // Call the framework to create the device
    Status = WdfDeviceCreate(&pDeviceInit, &FdoAttributes, &Device);
    if (!NT_SUCCESS(Status))
    {
        TraceError("CSTM %!FUNC! WdfDeviceCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Register CLX callback function pointers
    SENSOR_CONTROLLER_CONFIG_INIT(&SensorConfig);
    SensorConfig.DriverIsPowerPolicyOwner = WdfUseDefault;

    SensorConfig.EvtSensorStart                     = CustomSensorDevice::OnStart;
    SensorConfig.EvtSensorStop                      = CustomSensorDevice::OnStop;
    SensorConfig.EvtSensorGetSupportedDataFields    = CustomSensorDevice::OnGetSupportedDataFields;
    SensorConfig.EvtSensorGetDataInterval           = CustomSensorDevice::OnGetDataInterval;
    SensorConfig.EvtSensorSetDataInterval           = CustomSensorDevice::OnSetDataInterval;
    SensorConfig.EvtSensorGetDataFieldProperties    = CustomSensorDevice::OnGetDataFieldProperties;
    SensorConfig.EvtSensorGetDataThresholds         = CustomSensorDevice::OnGetDataThresholds;
    SensorConfig.EvtSensorSetDataThresholds         = CustomSensorDevice::OnSetDataThresholds;
    SensorConfig.EvtSensorGetProperties             = CustomSensorDevice::OnGetProperties;
    SensorConfig.EvtSensorDeviceIoControl           = CustomSensorDevice::OnIoControl;

    // Set up power capabilities and IO queues
    Status = SensorsCxDeviceInitialize(Device, &SensorConfig);
    if (!NT_SUCCESS(Status))
    {
        TraceError("CSTM %!FUNC! SensorsCxDeviceInitialize failed %!STATUS!", Status);
        goto Exit;
    }

Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Example #28
0
NTSTATUS
PortIODeviceCreate(
    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    pnpPowerCallbacks;
    WDFDEVICE                       device;
    NTSTATUS                        status;
    UNICODE_STRING                  ntDeviceName;
    UNICODE_STRING                  win32DeviceName;
    WDF_FILEOBJECT_CONFIG           fileConfig;
    
    PAGED_CODE();
    
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Register pnp/power callbacks so that we can start and stop the timer as 
    // the device gets started and stopped.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = PortIOEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = PortIOEvtDeviceReleaseHardware;
    
    //
    // Register the PnP and power callbacks. Power policy related callbacks will 
    // be registered later in SotwareInit.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);    

    WDF_FILEOBJECT_CONFIG_INIT(
                    &fileConfig,
                    WDF_NO_EVENT_CALLBACK, 
                    WDF_NO_EVENT_CALLBACK, 
                    WDF_NO_EVENT_CALLBACK // not interested in Cleanup
                    );
    
    // Let the framework complete create and close
    fileConfig.AutoForwardCleanupClose = WdfFalse;
    
    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                                     &fileConfig,
                                     WDF_NO_OBJECT_ATTRIBUTES);
    //
    // Create a named deviceobject so that legacy applications can talk to us.
    // Since we are naming the object, we wouldn't able to install multiple
    // instance of this driver. Please note that as per PNP guidelines, we
    // should not name the FDO or create symbolic links. We are doing it because
    // we have a legacy APP that doesn't know how to open an interface.
    //
    RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);
    
    status = WdfDeviceInitAssignName(DeviceInit,&ntDeviceName);
    if (!NT_SUCCESS(status)) {
        return status;
    }
    
    WdfDeviceInitSetDeviceType(DeviceInit, GPD_TYPE);

    //
    // Call this if the device is not holding a pagefile
    // crashdump file or hibernate file.
    //
    WdfDeviceInitSetPowerPageable(DeviceInit);

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT 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 = PortIOGetDeviceContext(device);

    //
    // This values is based on the hardware design.
    // I'm assuming the address is in I/O space for our hardware.
    // Refer http://support.microsoft.com/default.aspx?scid=kb;en-us;Q323595
    // for more info.
    //        
    deviceContext-> PortMemoryType = 1; 

    //
    // Create a device interface so that application can find and talk
    // to us.
    //
    RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
    
    status = WdfDeviceCreateSymbolicLink(
                device,
                &win32DeviceName);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Initialize the I/O Package and any Queues
    //
    status = PortIOQueueInitialize(device);

    return status;
}
Example #29
0
NTSTATUS
FilterEvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. Here you can query the device properties
    using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based
    on that, decide to create a filter device object and attach to the
    function stack. If you are not interested in filtering this particular
    instance of the device, you can just return STATUS_SUCCESS without creating
    a framework device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    PFILTER_EXTENSION       filterExt;
    NTSTATUS                status;
    WDFDEVICE               device;    
    WDF_IO_QUEUE_CONFIG     ioQueueConfig;
    WDFQUEUE                hQueue;
    
    PAGED_CODE ();

    UNREFERENCED_PARAMETER(Driver);

    KdPrint(("--> FilterEvtDeviceAdd\n"));

    //
    // Tell the framework that you are filter driver. Framework
    // takes care of inherting all the device flags & characterstics
    // from the lower device you are attaching to.
    //
    WdfFdoInitSetFilter(DeviceInit);

	//
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter 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 = FilterEvtDevicePrepareHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
	
    //
    // Specify the size of device extension where we track per device
    // context.
    //

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, FILTER_EXTENSION);
    
    //
    // Create a framework device object.This call will inturn create
    // a WDM deviceobject, attach to the lower stack and set the
    // appropriate flags and attributes.
    //
    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (!NT_SUCCESS(status)) {
        KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status));
        return status;
    }

    filterExt = FilterGetData(device);

    //
    // Configure the default queue to be Parallel. 
    // to handle IOCTLs that will be forwarded to us from
    // the rawPDO. 
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                             WdfIoQueueDispatchParallel);

    //
    // Framework by default creates non-power managed queues for
    // filter drivers.
    //
    ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControlFromRawPdo;

    status = WdfIoQueueCreate(device,
                            &ioQueueConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &hQueue // pointer to default queue
                            );
    if (!NT_SUCCESS(status)) {
        KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status));
        return status;
    }   

	filterExt->rawPdoQueue = hQueue;

    //
    // Create a RAW pdo so we can provide a sideband communication with
    // the application. Please note that not filter drivers desire to
    // produce such a communication and not all of them are contrained
    // by other filter above which prevent communication thru the device
    // interface exposed by the main stack. So use this only if absolutely
    // needed. Also look at the toaster filter driver sample for an alternate
    // approach to providing sideband communication.
    //
    status = FiltrCreateRawPdo(device, ++InstanceNo);

    KdPrint(("<-- FilterEvtDeviceAdd\n"));
	
    return status;
}
Example #30
0
/*++
Routine Description:

EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent a new instance of the device. All the software resources
should be allocated in this callback.

Arguments:

Driver - Handle to a framework driver object created in DriverEntry

DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

NTSTATUS
--*/
NTSTATUS PSDrv_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
    WDF_FILEOBJECT_CONFIG				fileConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               fdoAttributes;
    WDF_OBJECT_ATTRIBUTES               fileObjectAttributes;
    WDF_OBJECT_ATTRIBUTES               requestAttributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;
    ULONG                               maximumTransferSize;

    UNREFERENCED_PARAMETER(Driver);

    PSDrv_DbgPrint (3, ("PSDrv_EvtDeviceAdd - begins\n"));

    PAGED_CODE();

    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter device
    // object.
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = PSDrv_EvtDevicePrepareHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    // Initialize the request attributes to specify the context size and type
    // for every request created by framework for this device.
    WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT);

    WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes);

    // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
    // framework whether you are interested in handle Create, Close and
    // Cleanup requests that gets generate when an application or another
    // kernel component opens an handle to the device. If you don't register
    // the framework default behaviour would be complete these requests
    // with STATUS_SUCCESS. A driver might be interested in registering these
    // events if it wants to do security validation and also wants to maintain
    // per handle (fileobject) context.
    WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PSDrv_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK);

    // Specify a context for FileObject. If you register FILE_EVENT callbacks,
    // the framework by default creates a framework FILEOBJECT corresponding
    // to the WDM fileobject. If you want to track any per handle context,
    // use the context for FileObject. Driver that typically use FsContext
    // field should instead use Framework FileObject context.
    WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT);

    WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes);

    // We can do iso transfer only if the io type is directio.
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfDeviceCreate failed! (Status = %x)\n", status));
        return status;
    }

    // Get the DeviceObject context by using accessory function specified in
    // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
    pDevContext = GetDeviceContext(device);

    //Get MaximumTransferSize from registry
    maximumTransferSize=0;

    status = ReadFdoRegistryKeyValue(Driver, L"MaximumTransferSize", &maximumTransferSize);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("ReadFdoRegistryKeyValue failed with Status code %!STATUS!\n", status));
        return status;
    }

    if (maximumTransferSize)
	{
        pDevContext->MaximumTransferSize = maximumTransferSize;
    }
    else
	{
        pDevContext->MaximumTransferSize = DEFAULT_REGISTRY_TRANSFER_SIZE;
    }

    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermode (on Win2K) when you surprise
    // remove the device.
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

	// Do not show the little green remove icon
    pnpCaps.SurpriseRemovalOK = WdfTrue;

/*
	// Show the little green remove icon...
	pnpCaps.SurpriseRemovalOK = WdfFalse;
	pnpCaps.Removable = WdfTrue;
*/

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    // Register I/O callbacks to tell the framework that you are interested
    // in handling WdfRequestTypeRead, WdfRequestTypeWrite, and IRP_MJ_DEVICE_CONTROL requests.
    // 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.
    // This queue will be,  by default,  auto managed by the framework with
    // respect to PNP and Power events. That is, framework will take care
    // of queuing, failing, dispatching incoming requests based on the current
    // pnp/power state of the device.
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoRead = PSDrv_EvtIoRead;
    ioQueueConfig.EvtIoWrite = PSDrv_EvtIoWrite;
    ioQueueConfig.EvtIoDeviceControl = PSDrv_EvtIoDeviceControl;
    ioQueueConfig.EvtIoStop = PSDrvEvtIoStop;
    ioQueueConfig.EvtIoResume = PSDrvEvtIoResume;

    status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfIoQueueCreate failed! (Status = %x)\n", status));
        return status;
    }

    // Register a device interface so that app can find our device and talk to it.
    status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_PSDRV_USB, NULL);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfDeviceCreateDeviceInterface failed! (Status = %x)\n", status));
        return status;
    }

    PSDrv_DbgPrint(3, ("PSDrv_EvtDeviceAdd - ends\n"));

    return status;
}