Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/**
 * @brief Called by the framework when a new PDO has arrived that this driver manages.
 * The device in question is not operational at this point in time.
 * 
 * @param[in] Driver handle to WDFDRIVER object created by DriverEntry()
 * @param[in,out] DeviceInit device init object provided by framework.
 * 
 * @returns NTSTATUS value indicating success or failure.
 * 
 */
NTSTATUS
FdoEvtDeviceAdd(
    _In_    WDFDRIVER       Driver,    
    _Inout_ PWDFDEVICE_INIT DeviceInit 
    )
{
    UNREFERENCED_PARAMETER(Driver);
    WDF_OBJECT_ATTRIBUTES   attributes;
    NTSTATUS status;

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE,
        __FUNCTION__"\n");
    
    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
    WdfDeviceInitSetExclusive(DeviceInit, FALSE);
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, USB_FDO_CONTEXT);
    attributes.EvtCleanupCallback = FdoEvtDeviceContextCleanup;
    
    //
    // Device state callbacks.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS    pnpPowerCallbacks;
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = FdoEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = FdoEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry = FdoEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = FdoEvtDeviceD0EntryPostInterruptsEnabled;
    pnpPowerCallbacks.EvtDeviceD0Exit  = FdoEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceSurpriseRemoval = FdoEvtDeviceSurpriseRemoval;
    
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
    //
    // establish a request context
    //
    WDF_OBJECT_ATTRIBUTES   requestAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttributes, FDO_REQUEST_CONTEXT);
    WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes);

    //
    // static verifier seems to have a rule that the FDO must call 
    // WdfFdoInitSetDefaultChildListConfig if any component in the driver has
    // dynamic child devices, and the roothub has one if it is not operating in 
    // connect usb hub mode.
    //
    WDF_CHILD_LIST_CONFIG  config;
    WDF_CHILD_LIST_CONFIG_INIT(&config,
        sizeof(PDO_INDENTIFICATION_DESCRIPTION),
        FdoEvtChildListCreateDevice);

    WdfFdoInitSetDefaultChildListConfig(DeviceInit,
        &config,
        WDF_NO_OBJECT_ATTRIBUTES);
    //
    // add a preprocess callback for QueryInterface to support multi-version USBDI intefaces
    //
    UCHAR MinorFunctionTable[1] = {IRP_MN_QUERY_INTERFACE};

    status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
        DeviceInit,
        FdoPreProcessQueryInterface,
        IRP_MJ_PNP,
        MinorFunctionTable,
        1);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
            __FUNCTION__": WdfDeviceInitAssignWdmIrpPreprocessCallback failed error %x\n",
            status);
        return status;
    }

    //
    // Add create/close handlers
    //
    WDF_OBJECT_ATTRIBUTES   fileAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes);
    fileAttributes.SynchronizationScope = WdfSynchronizationScopeNone;
    WDF_FILEOBJECT_CONFIG FileObjectConfig;
    WDF_FILEOBJECT_CONFIG_INIT(
        &FileObjectConfig,
        FdoEvtDeviceFileCreate,
        FdoEvtFileClose,
        WDF_NO_EVENT_CALLBACK);

    WdfDeviceInitSetFileObjectConfig(
        DeviceInit,
        &FileObjectConfig,
        &fileAttributes);
        
    WDFDEVICE device;
    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
            __FUNCTION__": WdfDeviceCreate failed error %x\n",
            status);
        return status;
    }

    PUSB_FDO_CONTEXT fdoContext = DeviceGetFdoContext(device);
    RtlZeroMemory(fdoContext, sizeof(USB_FDO_CONTEXT));
    fdoContext->WdfDevice = device;
    KeInitializeEvent(&fdoContext->resetCompleteEvent, SynchronizationEvent, FALSE);
    //
    // allocate the dpc request collection.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;
    status = WdfCollectionCreate(&attributes,
        &fdoContext->RequestCollection);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
        __FUNCTION__": WdfCollectionCreate failed\n");
        return status;
    };
    //
    // The FDO is the USB Controller, create a device interface for that.
    //
    status = WdfDeviceCreateDeviceInterface(
        device,
        &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
        NULL);

    if (!NT_SUCCESS(status)) 
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
            __FUNCTION__": WdfDeviceCreateDeviceInterface for device %p error %x\n",
            device,
            status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);    
    attributes.ParentObject = device;
    status = WdfStringCreate(NULL, &attributes, &fdoContext->hcdsymlink);
    if (!NT_SUCCESS(status)) 
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
            __FUNCTION__": WdfStringCreate for device %p error %x\n",
            device,
            status);
        return status;
    }

    status = WdfDeviceRetrieveDeviceInterfaceString(device,
        &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
        NULL,
        fdoContext->hcdsymlink);
    if (!NT_SUCCESS(status)) 
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
            __FUNCTION__": WdfStringCreate for device %p error %x\n",
            device,
            status);
        return status;
    }
    //
    // Some of our resources are independent of the device state and 
    // can be allocated/initialized here.
    //
    status = InitScratchpad(fdoContext);

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

    //
    // --XT-- All of the WDF ISR and DPC setup code was removed
    // here. The DPC is now setup through the Xen interface in the
    // previous call. Note the event channel is setup but not active
    // until the backend is connected.
    //

    //
    // Allocate a watchdog timer for our Xen interface.
    //
    WDF_TIMER_CONFIG  timerConfig;
    WDF_OBJECT_ATTRIBUTES  timerAttributes;

    WDF_TIMER_CONFIG_INIT(
        &timerConfig,
        FdoEvtTimerFunc); 

    WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);
    timerAttributes.ParentObject = device;
    timerAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    status = WdfTimerCreate(
        &timerConfig,
        &timerAttributes,
        &fdoContext->WatchdogTimer);

    if (!NT_SUCCESS(status)) 
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
        __FUNCTION__": WdfTimerCreate error %x\n",
        status);
        return status;
    }

    //
    // Create a collection of work items.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;
    status = WdfCollectionCreate(&attributes,
        &fdoContext->FreeWorkItems);
    if (!NT_SUCCESS(status)) 
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
        __FUNCTION__": WdfCollectionCreate error %x\n",
        status);
        return status;
    }

    for (ULONG index = 0; index < INIT_WORK_ITEM_COUNT; index++)
    {
        WDFWORKITEM workitem = NewWorkItem(fdoContext,
            NULL,
            0,0,0,0);
        if (workitem)
        {
            status = WdfCollectionAdd(fdoContext->FreeWorkItems, workitem);
            if (!NT_SUCCESS(status))
            {
                TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
                    __FUNCTION__": WdfCollectionAdd for workitem index %d error %x\n",
                    index,
                    status);
                
                WdfObjectDelete(workitem);
                return status;
            }
        }
    }

    PNP_BUS_INFORMATION  busInformation;
    busInformation.BusNumber = 0;
    busInformation.BusTypeGuid = GUID_BUS_TYPE_USB;
    busInformation.LegacyBusType = PNPBus;

    WdfDeviceSetBusInformationForChildren(
        device,
        &busInformation);

    if (NT_SUCCESS(status)) {
        status = LateSetup(device);
    }

    return status;
}
NTSTATUS AndroidUsbDeviceObject::CreateFDODevice(PWDFDEVICE_INIT device_init) {
  ASSERT_IRQL_PASSIVE();

  ASSERT(!IsTaretDeviceCreated());
  if (IsTaretDeviceCreated())
    return STATUS_INTERNAL_ERROR;

  // Initialize our object attributes first
  WDF_OBJECT_ATTRIBUTES device_attr;
  NTSTATUS status = InitObjectAttributes(&device_attr, NULL);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Initialize the pnp_power_callbacks structure.  Callback events for PnP
  // and Power are specified here. If we don't supply any callbacks, the
  // KMDF will take appropriate default actions for an FDO device object.
  // EvtDevicePrepareHardware and EvtDeviceReleaseHardware are major entry
  // points for initializing / cleaning up our device. Probably, we can leave
  // the rest to the framework.
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDevicePrepareHardware =
    EvtDevicePrepareHardwareEntry;
  pnp_power_callbacks.EvtDeviceReleaseHardware =
    EvtDeviceReleaseHardwareEntry;
  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  // Initialize the request attributes to specify the context size and type
  // for every request created by framework for this device.
  WDF_OBJECT_ATTRIBUTES request_attr;
  WDF_OBJECT_ATTRIBUTES_INIT(&request_attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&request_attr, AndroidUsbWdfRequestContext);
  WdfDeviceInitSetRequestAttributes(device_init, &request_attr);

  // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the KMDF that we are
  // interested in handling Create requests that get genereated when an
  // application or another kernel component opens a handle through the device.
  // We are not interested in receiving cleanup / close IRPs at this point.
  WDF_FILEOBJECT_CONFIG file_config;
  WDF_OBJECT_ATTRIBUTES file_attr;
  WDF_FILEOBJECT_CONFIG_INIT(&file_config,
                             EvtDeviceFileCreateEntry,
                             WDF_NO_EVENT_CALLBACK,
                             WDF_NO_EVENT_CALLBACK);
  WDF_OBJECT_ATTRIBUTES_INIT(&file_attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&file_attr,
                                         AndroidUsbWdfObjectContext);
  file_attr.EvtCleanupCallback = AndroidUsbWdfObject::EvtCleanupCallbackEntry;
  file_attr.EvtDestroyCallback = AndroidUsbWdfObject::EvtDestroyCallbackEntry;
  // We will provide our own synchronization for file access
  file_attr.SynchronizationScope = WdfSynchronizationScopeNone;
  WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attr);

  // I/O type is buffered by default. It could be very inefficient if we have
  // large reads / writes through our device.
  WdfDeviceInitSetIoType(device_init, WdfDeviceIoDirect);

  // DeviceInit is completely initialized. So call the framework
  // to create the device and attach it to the lower stack.
  WDFDEVICE wdf_dev = NULL;
  status = WdfDeviceCreate(&device_init, &device_attr, &wdf_dev);
  ASSERT(NT_SUCCESS(status) && (NULL != wdf_dev));
  if (!NT_SUCCESS(status))
    return status;

  // Save handle to the created device
  set_wdf_object(wdf_dev);

  // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
  // that we don't get the popup in usermode (on Win2K) when we surprise
  // remove the device.
  WDF_DEVICE_PNP_CAPABILITIES pnp_caps;
  WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnp_caps);
  pnp_caps.SurpriseRemovalOK = WdfTrue;
  WdfDeviceSetPnpCapabilities(wdf_device(), &pnp_caps);

  // Create our default queue object for this device to start receiving I/O
  status = CreateDefaultQueue();
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Register a device interface so that app can find our device and talk to it.
  status = WdfDeviceCreateDeviceInterface(wdf_device(), &android_guid, NULL);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Initialize our extension to that device. We will do this at the very end
  // so we know that we successfully passed entire device create chain when
  // we are called with other callbacks to that device.
  status = InitializeContext();
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  return STATUS_SUCCESS;
}
Esempio n. 7
0
static NTSTATUS UsbChief_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_OBJECT_ATTRIBUTES fileObjectAttributes, requestAttributes, fdoAttributes;
	WDF_FILEOBJECT_CONFIG fileConfig;
	NTSTATUS Status;
	WDFDEVICE device;
	WDF_IO_QUEUE_CONFIG ioQueueConfig;
	WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
	WDFQUEUE queue;
	UNICODE_STRING linkname;

	UNREFERENCED_PARAMETER(Driver);
	PAGED_CODE();

	UsbChief_DbgPrint(DEBUG_CONFIG, ("ExtDeviceAdd\n"));

	/* Init PnP */
	WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
	pnpPowerCallbacks.EvtDevicePrepareHardware = UsbChief_EvtDevicePrepareHardware;
	WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	/* Request Attributes */
	WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT);
	WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes);

	/* Fileobject init */

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

	WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT);
	WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes);

	WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT);

	Status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreate: %08x\n", Status));
		return Status;
	}

	RtlInitUnicodeString(&linkname, L"\\DosDevices\\ChiefUSB");
	Status = WdfDeviceCreateSymbolicLink(device, &linkname);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreateSymbolicLink: %08x\n", Status));
		goto out;
	}

	WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
	pnpCaps.SurpriseRemovalOK = WdfTrue;
	WdfDeviceSetPnpCapabilities(device, &pnpCaps);

	/* Register I/O callbacks */
	WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);
	ioQueueConfig.EvtIoRead = UsbChief_EvtIoRead;
	ioQueueConfig.EvtIoWrite = UsbChief_EvtIoWrite;
	ioQueueConfig.EvtIoDeviceControl = UsbChief_EvtIoDeviceControl;
	ioQueueConfig.EvtIoStop = UsbChief_EvtIoStop;
	ioQueueConfig.EvtIoResume = UsbChief_EvtIoResume;

	Status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);

	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfIoQueueCreate: %08x\n", Status));
		goto out;
	}

	Status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_USBCHIEF_USB, NULL);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreateDeviceInterface: %08x\n", Status));
		goto out;
	}
	UsbChief_DbgPrint(3, ("EvtDriverDeviceAdd successful\n"));
	return STATUS_SUCCESS;
out:
	return Status;
}