OnPrepareHardware: WdfUsbTargetDeviceCreate failed with "STATUS_INVALID_DEVICE_OBJECT"

Hi,
I’m trying to write a KMDF driver for I2C using SPBCx framework, the I2C command should be sent over the USB Stack to the Controller connected to USB Port 8. The API call

status = WdfUsbTargetDeviceCreate(
FxDevice,
WDF_NO_OBJECT_ATTRIBUTES,
&pDevice->UsbDevice

fails with the status code 0xc0000010 (STATUS_INVALID_DEVICE_OBJECT) all ways.
also the “WdfCmResourceListGetCount” return 0.

I’m using the ACPI to define the resource and Device Id.

2 question

Why Resource count is 0
Can I communicate to USB Stack from the SPBCx KMDF driver?

Thanks,
Prasad

(Moved from the A&A forum to NTDEV, where this post belongs)

Hmmmm… OK, so let’s be clear about what you’re trying to accomplish, so I can be sure I’m answering your actual question:

You have an I2C Controller device that attaches to the system (dynamically) via USB. You want to write a I2C Controller Driver for this device using the standard Windows SPBCx… because that would enable “standard” Windows I2C client (that is, peripheral) device drivers (that also use SPBCx) to “just work” with your USB-connected I2C Controller.

Is that correct?

If so… This will be extremely tricky to accomplish, and perhaps impossible to do in any useful way.

Remember that the Controller and the Client (peripheral) devices both must be fully specified to ACPI via the SSDT. So, there’s really no useful way to specify a dynamically attached USB-based I2C controller that, in turn, has one or more devices (potentially dynamically) attached to it.

The Client driver is going to get a Connection ID and use the Resource Hub to resolve that into a Remote I/O Target to the (appropriate, specific) I2C Controller device and driver. This is all happens through the magic of SPBCx and ACPIEX.

So, at a minimum, you’ll need to specify a “dummy” static I2c Controller in the SSDT and load a (rather unconventional) driver over that client. When your USB-based I2C controller is dynamically enumerated, you’re going to load your rather conventional USB driver on that device (to talk to the real I2C Controller). Your “dummy” static I2C Controller driver will need to service requests from SPBCx by sending them to your USB-based driver.

You’ll also need to specify a static I2c Client device. If you know in advance the type of device, then at least THAT could (potentially) be rather conventional. It will connect to the “dummy” static I2C controller via the Resource Hub.

If you need to support the attachment of dynamic I2c CLIENT devices to your USB I2C controller, your job is even more complex. You need to ALSO create a “dummy” I2C Client device in your SSDT and load a dummy driver for that device. Your USB-based I2C controller driver will need to be a bus driver… and you’ll need to play some considerable games inject Connection ID resources for your enumerated Client devices. Of course, you’ll need to use the Connection ID from your dummy client device (because the Resource Hub needs to understand it). Ugh… it all gets very messy.

I hope that helps, and perhaps dissuades you from doing what you’ve described.

Peter

Thanks Peter for your inputs.

Yes your understanding is correct.

I have defined a Virtual I2C device in the ACPI Table and updated the Table. I’m able see the new unknown device. As it is virtual I have not defined any resource for this.

In my situation the I2C client device are not dynamically attached, they are actually real peripheral devices like camera sensor, which communicates with the sensor driver, and the camera sensor is connected to the USB I2C controller. The I2C request from the Sensor driver is sent down through the dummy static I2C Controller driver(Virtual I2C driver), request should be translated to USB packet and sent to the windows USB Stack.

I’m Using the WDF calls “WdfUsbTargetDeviceCreate” and “WdfUsbTargetDeviceSendControlTransferSynchronously” to do the USB transfer.
In my Dummy Static SPBCx I2c driver event callback function “OnPrepareHardware” I’m trying to call the function to get establish the interface with the USB.

//Setup the connection to the Win USB Stack
{
WDF_USB_DEVICE_CREATE_CONFIG Config;

        // If object handle is not NULL, OnPrepareHardware
        // was called previously and the handle is still valid.
        if (pDevice->UsbDevice != NULL) {
            return STATUS_SUCCESS;
        }

        WDF_USB_DEVICE_CREATE_CONFIG_INIT(
            &Config,
            USBD_CLIENT_CONTRACT_VERSION_602
        );

        status = WdfUsbTargetDeviceCreate(
            FxDevice,
            WDF_NO_OBJECT_ATTRIBUTES,
            &pDevice->UsbDevice
        );
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER,
                "%!FUNC! WdfUsbTargetDeviceCreate failed"
                "- %!STATUS!",
                status);
            return status;
        }

Thanks,
Prasad

Well… your driver has to be a USB client driver, that loads as a result of the VID/PID being enumerated, right? You can’t combine the “dummy” I2C controller driver instance and the USB client driver instance (the one that really sends requests to the USB-connected I2C controller). You need two separate drivers that talk to each other.

Is there already a driver talking to your USB device? So the VID and PID matched a known driver, and you see it in Device Manager?

Tim,

Thanks for the reply,

There is a Intel USB Bridge Driver that is talking to the USB Device. The Virtual I2C driver sits under the scope of the USB Bridge Driver.
The Bridge driver is from Intel not from us. The ACPI entry for the virtual device is under the scope “_SB.PC00.XHCI.RHUB.HS08.VIC0” where VIC0 is the virtual I2C device defined by us.

The USB Bridge Driver Device IDs are

USB\VID_8086&PID_0B63&REV_1002
USB\VID_8086&PID_0B63

Thanks Peter,
Currently we don’t the USB client driver, can the Static I2C driver communicate with the Intel USB Bridge Driver or WinUSb?

Thanks,
Prasad

I’m now lost. Sorry. I need a diagram, I guess. And this is very rapidly becoming far too complex to handle in a forum post.

You can’t call WdfUsbTargetDeviceCreate if your driver hasn’t been instantiated by the USB stack. That’s probably the only advice I can safely give at this point.

Peter

So, what services does the Intel driver provide? Given your scenario, I would expect IT would be the driver that exposes the I2C device.

Hi Peter,

Yes this is lot of information to discuss.

I can attach a diagram but I don’t see the option to attach.

“You can’t call WdfUsbTargetDeviceCreate if your driver hasn’t been instantiated by the USB stack.”
This could be the reason for failure.

Yes the Static/Virtual I2C driver is system device, enumerated by ACPI not USB.

VirtualI2C Driver(USBI2C)
|
USB Bridge Driver
|
USB Root HUB Driver
|
XHCI Controller Driver
|
I2C Peripheral

Hi Tim,

The Intel driver provides the exposure to the I2C devices connected to the USB port.

Thanks all, in advance for all the replies.

The Intel driver provides the exposure to the I2C devices connected to the USB port.

And why isn’t that enough? If your driver is already being loaded by the bridge driver, then why do you need a DSDT trigger?

Hi Tim,

Some of the I2C Interface Stubs from Intel Bridge Driver are not exposed to other OEM driver in the USB Stack, it is only exposed to Intel specific SPBCx drivers., This makes us to develop our own USB bridge driver.

Thanks,
Prasad

“Not exposed?” How do you mean? It’s ALWAYS easier to add a simple filter to an existing driver than it is to replace a driver where you may not have complete specs.