none
Handling IRP_MN_QUERY_INTERFACE in KMDF bus driver RRS feed

  • Question

  • I have a number of questions on handling IRP_MN_QUERY_INTERFACE in KMDF

    1. Does a child PDO thats attached to a device necessarily send this IRP to a bus driver?

    2. Should KMDF bus drivers necessarily implement an interface for this?


    I am aware that in order to handle this IRP a bus driver can precprocess this IRP EvtDeviceWdmIrpPreprocess(). I tried to preproces this IRP in tosater kmdf(static bus ) sample. But this routine is not getting called. I tried as below:

    In Bus_CreatePdo() before calling WdfDeviceCreate() to create child PDO

    status = WdfDeviceInitAssignWdmIrpPreprocessCallback(pDeviceInit, EvtDeviceWdmIrpPreprocess, IRP_MN_QUERY_INTERFACE, NULL, 0);
    	if (!NT_SUCCESS(status))
    	{
    		KdPrint(("WdfDeviceInitAssignWdmIrpPreprocessCallback failed with status 0x%x\n", status));
    		return status;
    	}

    Then in BusEnum.c

    NTSTATUS IoCompletion(
    	_In_      PDEVICE_OBJECT DeviceObject,
    	_In_      PIRP Irp,
    	_In_opt_  PVOID Context
    	)
    {
    	UNREFERENCED_PARAMETER(DeviceObject);
    	UNREFERENCED_PARAMETER(Irp);
    	UNREFERENCED_PARAMETER(Context);
    
    	Irp->IoStatus.Status = STATUS_SUCCESS;
    	Irp->IoStatus.Information = 0;
    	IoCompleteRequest(Irp, IO_NO_INCREMENT);
    	return STATUS_SUCCESS;
    }
    
    NTSTATUS EvtDeviceWdmIrpPreprocess(
    									_In_     WDFDEVICE Device,
    									_Inout_  PIRP Irp
    									)
    {
    
    	NTSTATUS status;
    	UNREFERENCED_PARAMETER(Device);
    	UNREFERENCED_PARAMETER(Irp);
    
    
    	Irp->IoStatus.Status = STATUS_SUCCESS;
    	IoSetCompletionRoutine(Irp, &IoCompletion, NULL, TRUE, TRUE, TRUE);
    	status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
    	return status;
    }

    I did the above based on the discussion at http://www.osronline.com/showthread.cfm?link=167995

    But on child PDO enumeration, the EvtDeviceWdmIrpPreprocess() is not called. I also tried using EvtDeviceProcessQueryInterfaceRequest() method as below:

    In Bus_CreatePDO() before calling WdfAddStaticChild() and after WdfDeviceCreate()

    	
        WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
                                        (PINTERFACE) &ToasterInterface,
                                        &GUID_TOASTER_INTERFACE_STANDARD,
    									EvtDeviceProcessQueryInterfaceRequest);
    	qiConfig.Size = sizeof(qiConfig);
    	qiConfig.ImportInterface = TRUE;
    	qiConfig.Interface = NULL;// (PINTERFACE) &ToasterInterface;
    	qiConfig.InterfaceType = &GUID_TOASTER_INTERFACE_STANDARD;
    	qiConfig.SendQueryToParentStack = TRUE;
    
        //
        // If you have multiple interfaces, you can call WdfDeviceAddQueryInterface
        // multiple times to add additional interfaces.
        //
        status = WdfDeviceAddQueryInterface(hChild, &qiConfig);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
    
        }

    But the EvtDeviceProcessQueryInterfaceRequest() routine is not getting called. I am aware that when the child PDO is enumerated, the FDO of the child device should request the interface information from the bus driver.




    Tuesday, June 3, 2014 6:05 PM

Answers

  • Why would you want to preprocess this request?  Setting up an EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST should be all that you need.  In the child device driver are you calling WdfFdoQueryForInterface in your EVT_WDF_DEVICE_PREPARE_HARDWARE callback?


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Tuesday, June 3, 2014 6:18 PM

All replies

  • Why would you want to preprocess this request?  Setting up an EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST should be all that you need.  In the child device driver are you calling WdfFdoQueryForInterface in your EVT_WDF_DEVICE_PREPARE_HARDWARE callback?


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Tuesday, June 3, 2014 6:18 PM
  • Thanks Don. It is seen that the IRP_MN_QUERY_INTERFACE IRP is sent during enumeration.

    Do you mean to say that handling EvtDeviceProcessQueryInterfaceRequest() the way it has been done above is sufficient?

    If the child device driver is not calling WdfFdoQueryForInterface () but sends IRP_MN_QUERY_INTERFACE IRP( wdm),  then shouln't we preprocess the IRP_MN_QUERY_INTERFACE as is done in the first case?

    Is it OK to set up EvtDeviceProcessQueryInterfaceRequest() during PDO creation?


    Tuesday, June 3, 2014 6:31 PM
  • If the FDO for the child stack is KMDF, just use WdfFdoqueryForInterface.

    The PDO should call WdfDeviceAddQueryInterface to handle processing of the QI request. It doesn't matter how the attached FDO sends the QI (using KMDF or WDM APIs), WdfDeviceAddQueryInterface is the API you call to set up handling of the request. Calling WdfDeviceAddQueryInterface  after you have created the PDO (and if static, before adding it) is the right sequence.

     If the registered callback is not being called, the most likely cause is a malformed QI request sent by the FDO.   !wdfkd.wdflogdump <PDO driver name> should tell you why the QI was rejected and the callback not called.


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, June 3, 2014 7:47 PM
  • Thanks Doron. I got the log dump. But in the log dump, I was not able to find anything related to the QI request. I shall look into this in detail. But I would like to know some more related points:

    1. In order for a child PDO to be correctly attached and enumerated by a bus driver, should the bus driver handle/connect/share the interrupts on behalf of the child PDO? Is this part of loading the driver of the PDO? It  found a similar discussion at https://www.osronline.com/ShowThread.cfm?link=154211.

    2. Is the QI reuest/processing also part of enumeration? ie. in order for a PDO to be correctly enumerated by a bus driver, should the bus driver necessarily expose this interface? Or is it optional?



    • Edited by its_me_here Wednesday, June 4, 2014 4:33 PM
    Wednesday, June 4, 2014 4:31 PM
  • In your case the bus driver will have the ownership of the interrupt.  What the QI request will provide is a way for the child device to hand an interrupt routine and context to the bus driver to be called as part of the bus drivers interrupt handler, and for the bus driver to return to the child device a routine(s) that can be used to synchronize with the interrupt routine.

    QI processing is optional and has nothing to do with enumerating the PDO's.  It is the logical way to share data from the bus to the child devices.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Wednesday, June 4, 2014 4:53 PM
  • On sharing data between bus and bus-driver and child  child devices, I came across different methods all centered around the bus interface.

    The toaster sample has its own implementation of bus interface as below:

    typedef struct _TOASTER_INTERFACE_STANDARD {
        INTERFACE                        InterfaceHeader;
        PTOASTER_GET_CRISPINESS_LEVEL    GetCrispinessLevel;
        PTOASTER_SET_CRISPINESS_LEVEL    SetCrispinessLevel;
        PTOASTER_IS_CHILD_PROTECTED      IsSafetyLockEnabled; //):
    } TOASTER_INTERFACE_STANDARD, *PTOASTER_INTERFACE_STANDARD;

    Then there is the BUS_INTERFACE_STANDARD structure as such( at http://msdn.microsoft.com/en-us/library/windows/hardware/ff540707%28v=vs.85%29.aspx) which has routines for reading/writing device config data.

    The NT Inside article at http://insider.osr.com/2014/ntinsider_2014_02.pdf describes the bus interface structure as one with a routine for write operation(eg:PNV2BUDDY_WRITE). I have some questions in this regards:

    1. If I need to open a link between the bus and child PDO, which one is the best option?

    2. Is BUS_INTERFACE_STANDARD, a standard implementation that every child device driver( irrespective of wdf or wdm ) can understand and make calls to the bus and access data? In my case, I would be enumerating a child device on my kmdf bus and the child device driver can be either wdm or wdf. So in that case, if I use the BUS_INTERFACE_STANDARD structure, is the child device driver sure to make call to the bus?

    3. If I use the BUS_INTERFACE_STANDARD for driver-to-driver communication, can I use the read/write routines in it for connecting interrupts etc?

    3. MSDN docs say that bus drivers normally call WdfDeviceAddQueryInterface() in EvtDeviceAdd()/EvtPrepareHardware(). So is to OK to call this routine during PDO creation as in toaster sample?


    Thursday, June 5, 2014 6:13 PM
  • As to the questions:

    1.  Basically use a custom interface (be sure it starts with the INTERFACE structure), that descibes the data you want.  In you case that should be the raw and traslated base address and length of the registers for the PDO, plus callback data for interrupts and pointers to interrupt synchronization routines.

    2.  Use the same interface structure for each PDO, with differing values for the register address.  Unless your device has more than one sort of interface.

    3.  The bus driver does not need to call WdfDeviceAddQueryInterface() , the child driver does this to call the bus driver.  The child driver should pass in an interrupt callback and interrupt context, and upon return from the WdfDeviceAddQueryInterface() call save the register data and the interrupt synchronization routine pointers.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Thursday, June 5, 2014 6:42 PM