Embedded Intel Atom® Processors
Technological Conversations about Intel Atom® Hardware, Software, Firmware, Graphics
1152 Discussions

Trouble using Apollo Lake GPIO in Windows

SCorb
Beginner
2,405 Views

I've been following the https://docs.microsoft.com/en-us/windows-hardware/drivers/gpio/ Windows GPIO Driver Design Guide and have the Intel Controller Driver installed; which I downloaded from https://www.intel.com/content/dam/www/public/us/en/zip/atom-e3900-board-support-package-iot-platforms.zip here.

I then followed the https://github.com/Microsoft/Windows-driver-samples/tree/master/gpio/samples/simdevice WDK GPIO simdevice sample making only changes to the inf to load for the new ACPI device I defined in a new BIOS build. My new ACPI device shows up in the Windows device manager, my simdevice peripheral driver loads for it and PrepareHardware hands me the 8 GpioIo I defined in ASL. When calling WdfCmResourceListGetDescriptor(ResourcesTranslated, index); for each resource their descriptor types are CmResourceTypeConnection; as expected. Their connection class is CM_RESOURCE_CONNECTION_CLASS_GPIO and their connection type is CM_RESOURCE_CONNECTION_TYPE_GPIO_IO. It seems like that part is working properly.

In order to send the IOCTL_GPIO_READ_PINS to the controller driver the sample indicates I need to:

  1. Create an IoTarget with the ParentObject set to the WDFDEVICE that my peripheral driver created. Shown https://github.com/Microsoft/Windows-driver-samples/blob/master/gpio/samples/simdevice/simdevice.c# L704 here.
  2. Open the IoTarget specifying a RequestString and the desired access levels
    1. The RequestString is created by using the RESOURCE_HUB_CREATE_PATH_FROM_ID macro. I provide the ConnectionId of the GPIO I want to target. The ConnectionId was provided to my driver during PrepareHardware.
  3. Create a WdfRequest and WdfMemory object with the data to pass to the IOCTL.
  4. Format the request for the IOCTL
  5. Send the IOCTL

However, step 2 above is failing with a STATUS_INVALID_PARAMETER. This step is done at https://github.com/Microsoft/Windows-driver-samples/blob/master/gpio/samples/simdevice/simdevice.c# L741 line 741 of the sample.

Any help in making the IOCTL_GPIO_READ_PINS and IOCTL_GPIO_WRITE_PINS calls to the controller driver would be greatly appreciated.

0 Kudos
3 Replies
Adolfo_S_Intel
Moderator
1,289 Views

Hello, scorbin,

Thanks for contacting us, we are investigating your case, and we will provide more information as soon as possible.

Best Regards,

Adolfo Sanchez.

0 Kudos
SCorb
Beginner
1,289 Views

AdolfoS,

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.

 

https://github.com/Microsoft/Windows-driver-samples/blob/master/usb/UcmTcpciCxClientSample/I2C.cpp# L192 Windows-driver-samples/I2C.cpp at master · Microsoft/Windows-driver-samples · GitHub

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

2) This https://github.com/Microsoft/Windows-driver-samples/blob/master/gpio/samples/simdevice/simdevice.c# L741 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 logical. 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.

Adolfo_S_Intel
Moderator
1,289 Views

Hello, scorbin

Thanks for sharing your solution with the rest of the community, your contribution is greatly appreciated.

Best Regards,

Adolfo Sanchez

0 Kudos
Reply