Having problem with GPIO sample

I’m working from the simdevice GPIO sample and running into an issue where WdfIoTargetOpen on line 741 returns a status of 0xc000000d - An invalid parameter was passed to a service or function.

In this simple case, I have control over the BIOS and have created a new peripheral device (my version of simdevice) with 8 GPIO inputs. I save these 8 GPIO_IO ConnectionIds during PrepareHardware. Prior to calling WdfIoTargetOpen on line 741 I use WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME with a request string created using RESOURCE_HUB_CREATE_PATH_FROM_ID(); which returns STATUS_SUCCESS.

I could really use some help understanding why WdfIoTargetOpen would fail in this case.

Shane_Corbin wrote:

I’m working from the simdevice GPIO sample and running into an issue where WdfIoTargetOpen on line 741 returns a status of 0xc000000d - An invalid parameter was passed to a service or function.

In this simple case, I have control over the BIOS and have created a new peripheral device (my version of simdevice) with 8 GPIO inputs. I save these 8 GPIO_IO ConnectionIds during PrepareHardware. Prior to calling WdfIoTargetOpen on line 741 I use WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME with a request string created using RESOURCE_HUB_CREATE_PATH_FROM_ID(); which returns STATUS_SUCCESS.

I could really use some help understanding why WdfIoTargetOpen would fail in this case.

Are the resources being handed to you as CmResourceTypeConnection in
your PrepareHardware call?  If that much is working, that means your
DSDT is probably correct.  Did you happen to print out the request
string to see if it looked reasonable?  I’m not sure I could recognize
“reasonable” in this case, but I’d expect it to have your pin number
embedded somewhere.

@Tim_Roberts said:

Are the resources being handed to you as CmResourceTypeConnection in
your PrepareHardware call? If that much is working, that means your
DSDT is probably correct. Did you happen to print out the request
string to see if it looked reasonable? I’m not sure I could recognize
“reasonable” in this case, but I’d expect it to have your pin number
embedded somewhere.

Yes. The resources are being handed to me as CmResourceTypeConnection with a .class of CM_RESOURCE_CONNECTION_CLASS_GPIO and .type of CM_RESOURCE_CONNECTION_TYPE_GPIO_IO.

I’m in the same boat as far as not knowing what reasonable is. The Connection IDs I’m getting for the resources are just 1-8. There’s nothing about them that correlates to the actual pin number; which I thought was weird. The unicode RequestString returned by RESOURCE_HUB_CREATE_PATH_FROM_ID for the first ID is:
.length = 0x4a
.MaximumLength = 0x98
.Buffer = “\Device\RESOURCE_HUB\0000000000000001”

Shane_Corbin wrote:

Yes. The resources are being handed to me as CmResourceTypeConnection with a .class of CM_RESOURCE_CONNECTION_CLASS_GPIO and .type of CM_RESOURCE_CONNECTION_TYPE_GPIO_IO.

I’m in the same boat as far as not knowing what reasonable is. The Connection IDs I’m getting for the resources are just 1-8. There’s nothing about them that correlates to the actual pin number; which I thought was weird. The unicode RequestString returned by RESOURCE_HUB_CREATE_PATH_FROM_ID for the first ID is:

.length = 0x4a
.MaximumLength = 0xc8
.Buffer = “\Device\RESOURCE_HUB\0000000000000001”

Have you modified the sample at all?  WdfIoTargetOpen will immediately
return STATUS_INVALID_PARAMETER if any of the fields of the
UNICODE_STRING are 0.  Of course, it also ends up calling several other
functions, any of which could also be returning that status.  Does the
inflight recorder log tell you anything?

@Tim_Roberts said:
Have you modified the sample at all? WdfIoTargetOpen will immediately
return STATUS_INVALID_PARAMETER if any of the fields of the
UNICODE_STRING are 0. Of course, it also ends up calling several other
functions, any of which could also be returning that status. Does the
inflight recorder log tell you anything?

The only modifications to the sample I have made are:

  • I removed all interrupt handling routines. I’m only exposing GpioIo and not any GpioInt.
  • I put an assert in the CmResourceTypeInterrupt case during PrepareHardware.
  • I’ve tried declaring/initializing the UNICODE_STRING both as shown in the sample and as DECLARE_UNICODE_STRING_SIZE(resource_string, RESOURCE_HUB_PATH_SIZE);

If the inflight recorder is telling me anything useful, I’m too dense to understand. Here are the last few lines:
34: FxIoTargetRemote::OpenTargetHandle - ZwCreateFile for WDFIOTARGET 00006C7977BB3968 returned status 0xc000000d(STATUS_INVALID_PARAMETER), info 0x2

35: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C1D1D60 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000

36: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C1D1F10 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000

37: FxIoTargetRemote::OpenTargetHandle - ZwCreateFile for WDFIOTARGET 00006C7977BB3968 returned status 0xc000000d(STATUS_INVALID_PARAMETER), info 0x2

38: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C2EFD60 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000

@Tim_Roberts said:
Have you modified the sample at all? WdfIoTargetOpen will immediately
return STATUS_INVALID_PARAMETER if any of the fields of the
UNICODE_STRING are 0. Of course, it also ends up calling several other
functions, any of which could also be returning that status. Does the
inflight recorder log tell you anything?

I modified it only as follows:

  • Updated the inf to match my HardwareID
  • Removed any interrupt handling routines since I’m only exposing GpioIo
  • Threw an assert in the case where a GpioInt was found

If the inflight recorder has anything useful, I’m too dense to interpret it correctly. Here are the last few lines:

34: FxIoTargetRemote::OpenTargetHandle - ZwCreateFile for WDFIOTARGET 00006C7977BB3968 returned status 0xc000000d(STATUS_INVALID_PARAMETER), info 0x2    
35: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C1D1D60 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000    
36: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C1D1F10 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000    
37: FxIoTargetRemote::OpenTargetHandle - ZwCreateFile for WDFIOTARGET 00006C7977BB3968 returned status 0xc000000d(STATUS_INVALID_PARAMETER), info 0x2    
38: FxIoTargetRemote::ClearTargetPointers - WDFIOTARGET 00006C7977BB3968 cleared pointers FFFFFB819C2EFD60 state WdfIoTargetClosed, open state 1, pdo 0000000000000000, fileobj 0000000000000000, handle 0000000000000000

Shane_Corbin wrote:

If the inflight recorder is telling me anything useful, I’m too dense to understand. Here are the last few lines:

`34: FxIoTargetRemote::OpenTargetHandle - ZwCreateFile for WDFIOTARGET 00006C7977BB3968 returned status 0xc000000d(STATUS_INVALID_PARAMETER), info 0x2

Well, this is actually important, although not quite helpful. This tells
is the error actually came from ZwCreateFile itself, and not from the
framework’s pre- or post-processing.

I don’t know where to go next.  We’ll have to hope someone who knows the
SPB stack gets involved here.

Note: The email was trying to reply to an invalid Comment (291666).

Thanks for the feedback Tim.

I’ve been doing some follow-up testing to make sure I’ve addressed the issue. It looks like the way I was requesting the ResourceString using the RESOURCE_HUB_CREATE_PATH_FROM_ID was incorrect. It expects me to provide a UNICODE_STRING for the framework to populate. I was doing this improperly. I found 2 WDK samples that illustrate how to do this.

  1. This i2c example that shows how to get the ResourceString from the resource hub.

It does it like so:

    // Create the device path using the connection ID.  
    DECLARE_UNICODE_STRING_SIZE(ResourceString, RESOURCE_HUB_PATH_SIZE);  
    RESOURCE_HUB_CREATE_PATH_FROM_ID(  
        &ResourceString,  
        DeviceContext->I2CConnectionId.LowPart,  
        DeviceContext->I2CConnectionId.HighPart);  
  1. This GPIO example that shows how to get the ResourceString from the resource hub.

    UNICODE_STRING ResourceString;
    WCHAR ResourceStringBuffer[100];

    RtlInitEmptyUnicodeString(
    &ResourceString,
    ResourceStringBuffer,
    sizeof(ResourceStringBuffer));

    RESOURCE_HUB_CREATE_PATH_FROM_ID(
    &ResourceString,
    SampleDrvExtension->ConnectionIds[0].LowPart,
    SampleDrvExtension->ConnectionIds[0].HighPart);

I initially started with method 2. That wasn’t working so I switched to method 1; because it seems more intuitive. It turns out I had an issue with my connectionID index first so it didn’t matter which method I used. Once I corrected that, method 1 wasn’t working. Once I reverted to method 2 I was able to get past this issue.

On Nov 30, 2018, at 4:04 PM, Shane_Corbin wrote:
>
> I initially started with method 2. That wasn’t working so I switched to method 1; because it seems more intuitive. It turns out I had an issue with my connectionID index first so it didn’t matter which method I used. Once I corrected that, method 1 wasn’t working. Once I reverted to method 2 I was able to get past this issue.

You get extra credit points for letting us know what the problem actually was. That will help future developers with this kind of problem.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.