summaryrefslogtreecommitdiff
path: root/gpio/samples/simdevice
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /gpio/samples/simdevice
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'gpio/samples/simdevice')
-rw-r--r--gpio/samples/simdevice/GpioSample.asl124
-rw-r--r--gpio/samples/simdevice/common.h84
-rw-r--r--gpio/samples/simdevice/simdevice.c819
-rw-r--r--gpio/samples/simdevice/simdevice.inx76
-rw-r--r--gpio/samples/simdevice/simdevice.rc12
-rw-r--r--gpio/samples/simdevice/simdevice.vcxproj189
-rw-r--r--gpio/samples/simdevice/simdevice.vcxproj.Filters39
7 files changed, 1343 insertions, 0 deletions
diff --git a/gpio/samples/simdevice/GpioSample.asl b/gpio/samples/simdevice/GpioSample.asl
new file mode 100644
index 00000000..c393d9da
--- /dev/null
+++ b/gpio/samples/simdevice/GpioSample.asl
@@ -0,0 +1,124 @@
+
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ GpioSample.asl
+
+Abstract:
+
+ This sample ASL file describes a sample GPIO device and a sample peripheral
+ device which consumes IO and interrupt resources from the GPIO device. Please
+ note that:
+
+ 1. The memory and IO descriptor under the GPIO device are simply examples of
+ what can be described. They are commented out to illustrate this point. Actual
+ values will vary according to the platform specifications (e.g. GIC and memory)
+
+ 2. The sample ASL DSDT definition block defines only the components relevant
+ to demonstrate GPIO IO and interrupt resource usage. Rest of the DSDT will vary
+ according to platform specifications.
+
+ 3. The PNP IDs for the GPIO and peripheral device are for demonstration purposes
+ only. Actual values need to reflect those chosen for the actual GPIO or
+ peripheral device.
+
+--*/
+
+
+DefinitionBlock ("DSDT.AML", "DSDT", 0x02, "MSFT", "SAMPLE", 0x1) {
+
+ //
+ // System Bus
+ //
+
+ Scope (\_SB) {
+
+ //
+ // Sample GPIO device
+ //
+
+ Device(GPIO) {
+ Name (_ADR, 0)
+ Name (_HID, "TEST0001")
+ Name (_CID, "TEST0001")
+ Name(_UID, 4)
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+
+ //
+ // Interrupt resource. In this example, banks 0 & 1 share the same
+ // interrupt to the parent controller and similarly banks 2 & 3.
+ //
+ // N.B. The definition below is chosen for an arbitrary
+ // test platform. It needs to be changed to reflect the hardware
+ // configuration of the actual platform.
+ //
+
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, , , ) {50}
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, , , ) {50}
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, , , ) {51}
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, , , ) {51}
+
+ //
+ // Memory resource. The definition below is chosen for an arbitrary
+ // test platform. It needs to be changed to reflect the hardware
+ // configuration of the actual platform.
+ //
+
+ Memory32Fixed(ReadWrite, 0x00100000, 0x18)
+ })
+
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized) {
+ Return(0xf)
+ }
+
+ //
+ // Sample peripheral device
+ //
+
+ Device (TDEV) {
+ Name (_ADR, 0)
+ Name (_HID, "TEST0003")
+ Name (_CID, "TEST0003")
+ Name (_UID, 1)
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+
+ //
+ // GPIO Interrupt Resources
+ //
+
+ GpioInt(Edge, ActiveHigh, Shared, PullUp, 0, "\\_SB.GPIO", 0, ResourceConsumer,, RawDataBuffer() {1}) {1}
+ // GpioInt(Edge, ActiveHigh, Shared, PullUp, 0, "\\_SB.GPIO", 0, ResourceConsumer,, RawDataBuffer() {1}) {2}
+
+ //
+ // GPIO IO Resources
+ //
+
+ GpioIo(Exclusive, PullUp, 0, 0,, "\\_SB.GPIO",0, ResourceConsumer, , RawDataBuffer() {1}) {10}
+ GpioIo(Exclusive, PullUp, 0, 0,, "\\_SB.GPIO",0, ResourceConsumer, , RawDataBuffer() {1}) {11}
+ })
+
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized) {
+ Return(0xf)
+ }
+ }
+ }
+ }
+ }
diff --git a/gpio/samples/simdevice/common.h b/gpio/samples/simdevice/common.h
new file mode 100644
index 00000000..315044c8
--- /dev/null
+++ b/gpio/samples/simdevice/common.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ common.h
+
+Abstract:
+
+ Header file that provide some utility functionalities to the sample device driver
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#pragma once
+
+#include <ntddk.h>
+#pragma warning(disable:4201) // disable nameless struct/union warnings
+#include <wdf.h>
+#pragma warning(default:4201)
+
+#define NTSTRSAFE_LIB
+#include <ntstrsafe.h>
+
+#ifndef MAX_USHORT
+#define MAX_USHORT ((USHORT)-1)
+#endif
+
+#ifndef MAX_ULONG
+#define MAX_ULONG ((ULONG)-1)
+#endif
+
+#ifndef MAX_ULONG64
+#define MAX_ULONG64 ((ULONG64)-1)
+#endif
+
+//
+// Useful macros for setting and checking flags.
+//
+
+#define SET_FLAGS(_x, _f) ((_x) |= (_f))
+#define CLEAR_FLAGS(_x, _f) ((_x) &= ~(_f))
+#define CLEAR_OTHER_FLAGS(_x, _f) ((_x) &= (_f))
+#define CHECK_FLAG(_x, _f) ((_x) & (_f))
+
+//
+// Macros for rounding up or down.
+//
+
+#define ROUND_DOWN(_x, _alignment) \
+ ((_alignment == 1) ? (_x) : (((_x) / (_alignment)) * (_alignment)))
+
+#define ROUND_UP(_x, _alignment) \
+ ROUND_DOWN((_x) + (_alignment) - 1, (_alignment))
+
+//
+// Macros for find minimum and maximum of two integers.
+//
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) < (b)) ? (b) : (a))
+
+//
+// Define macros to allow easy pointer arithmetic.
+//
+
+#define Add2Ptr(_Ptr, _Value) ((PVOID)((PUCHAR)(_Ptr) + (_Value)))
+#define PtrOffset(_Base, _Ptr) ((ULONG_PTR)(_Ptr) - (ULONG_PTR)(_Base))
+
+// 4127 -- Conditional Expression is Constant warning
+#define WHILE(constant) \
+__pragma(warning(disable: 4127)) while(constant) __pragma(warning(default: 4127))
+
+#define FIELD_OFFSET_AND_SIZE(t, f) \
+ (FIELD_OFFSET(t, f) + FIELD_SIZE(t, f)) \ No newline at end of file
diff --git a/gpio/samples/simdevice/simdevice.c b/gpio/samples/simdevice/simdevice.c
new file mode 100644
index 00000000..f54f1a84
--- /dev/null
+++ b/gpio/samples/simdevice/simdevice.c
@@ -0,0 +1,819 @@
+/*++
+
+Copyright (c) 1990-2010 Microsoft Corporation
+
+Module Name:
+
+ SimpleDevice.c
+
+Abstract:
+
+ This is a simple device driver that consumes GPIO pins for I/O and interrupt.
+
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+//
+// ------------------------------------------------------------------- Includes
+//
+
+#include "common.h"
+#include <gpio.h>
+#define RESHUB_USE_HELPER_ROUTINES
+#include <reshub.h>
+
+//
+// -------------------------------------------------------------------- Defines
+//
+
+#define MAX_NUMBER_IO_RESOURCES 2
+
+//
+// -------------------------------------------------------------------- Types
+//
+
+typedef struct _SAMPLE_DRV_DEVICE_EXTENSION {
+ ULONG IoResourceCount;
+ ULONG InterruptCount;
+ LARGE_INTEGER ConnectionIds[MAX_NUMBER_IO_RESOURCES];
+} SAMPLE_DRV_DEVICE_EXTENSION, *PSAMPLE_DRV_DEVICE_EXTENSION;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SAMPLE_DRV_DEVICE_EXTENSION, SampleDrvGetDeviceExtension)
+
+//
+// ----------------------------------------------------------------- Prototypes
+//
+
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD SampleDrvEvtDeviceAdd;
+EVT_WDF_DEVICE_D0_ENTRY SampleDrvEvtDeviceD0Entry;
+EVT_WDF_DEVICE_PREPARE_HARDWARE SampleDrvEvtDevicePrepareHardware;
+EVT_WDF_INTERRUPT_DPC SampleDrvInterruptDpc;
+EVT_WDF_INTERRUPT_ISR SampleDrvInterruptIsr;
+EVT_WDF_INTERRUPT_ISR SampleDrvInterruptPassiveCallback;
+
+NTSTATUS
+TestReadWrite (
+ _In_ WDFDEVICE Device,
+ _In_ PCUNICODE_STRING RequestString,
+ _In_ BOOLEAN ReadOperation,
+ _Inout_ PUCHAR Data,
+ _In_ _In_range_(>, 0) ULONG Size,
+ _Out_ WDFIOTARGET *IoTargetOut
+ );
+
+//
+// -------------------------------------------------------------------- Pragmas
+//
+
+#pragma alloc_text(PAGE, SampleDrvEvtDeviceAdd)
+#pragma alloc_text(PAGE, SampleDrvEvtDevicePrepareHardware)
+
+//
+// ------------------------------------------------------------------ Functions
+//
+
+NTSTATUS
+DriverEntry (
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the driver initialization entry point.
+
+Arguments:
+
+ DriverObject - Pointer to the driver object created by the I/O manager.
+
+ RegistryPath - Pointer to the driver specific registry key.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+
+ WDFDRIVER Driver;
+ WDF_DRIVER_CONFIG DriverConfig;
+ NTSTATUS Status;
+
+ //
+ // Initialize the driver configuration structure.
+ //
+
+ WDF_DRIVER_CONFIG_INIT(&DriverConfig, SampleDrvEvtDeviceAdd);
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+
+ Status = WdfDriverCreate(DriverObject,
+ RegistryPath,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DriverConfig,
+ &Driver);
+
+ if (!NT_SUCCESS(Status)) {
+ goto DriverEntryEnd;
+ }
+
+DriverEntryEnd:
+ return Status;
+}
+
+BOOLEAN
+SampleDrvInterruptIsr (
+ _In_ WDFINTERRUPT Interrupt,
+ _In_ ULONG MessageID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the interrupt service routine for the sample device
+
+ N.B. This driver assumes that the interrupt line is not shared with any
+ other device. Hence it always claims the interrupt.
+
+Arguments:
+
+ Interupt - Supplies a handle to interrupt object (WDFINTERRUPT) for this
+ device.
+
+ MessageID - Supplies the MSI message ID for MSI-based interrupts.
+
+Return Value:
+
+ Always TRUE.
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER(Interrupt);
+ UNREFERENCED_PARAMETER(MessageID);
+
+ //
+ // The sample driver always returns TRUE (e.g. claiming the interrupt)
+ // from its ISR. In reality, the driver needs to do whatever necessary to
+ // quiesce the interrupt before claiming the interrupt. In case of spurious
+ // interrupts, the ISR returns FALSE. If additional work needs to be done
+ // at a lower IRQL, schedule a DPC.
+ //
+
+ return TRUE;
+}
+
+#if 0
+BOOLEAN
+SampleDrvInterruptPassiveCallback (
+ _In_ WDFINTERRUPT Interrupt,
+ _In_ ULONG MessageID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the passive interrupt callback routine for the sample device.
+ As its name suggests, this routine is always invoked at PASSIVE_LEVEL.
+ This is useful in scenarios where the device is located behind a slow serial
+ peripheral bus(SPB) and requires communication (possible only at PASSIVE_LEVEL)
+ over the bus in quiescing the interrupt source.
+
+ N.B. It is possible for passive interrupt callback and DIRQL ISRs to
+ coexist for the same device and/or IDT entry. Interrupt objects chained to a
+ given IDT entry are always ordered (at interrupt connect time) by the OS such
+ that the DIRQL ISR interrupt objects are located before the passive callback
+ ones. Consequently, during interrupt dispatching, the OS would walk the list
+ in that order until the first ISR/passive callback returns TRUE to claim the
+ interrupt.
+
+Arguments:
+
+ Interupt - Supplies a handle to interrupt object (WDFINTERRUPT) for this
+ device.
+
+ MessageID - Supplies the MSI message ID for MSI-based interrupts.
+
+Return Value:
+
+ Always TRUE.
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER(Interrupt);
+ UNREFERENCED_PARAMETER(MessageID);
+
+ //
+ // The sample driver always returns TRUE (e.g. claiming the interrupt)
+ // from its passive callback. In reality, the driver needs to do whatever necessary to
+ // quiesce the interrupt before claiming the interrupt.
+ //
+
+ return TRUE;
+}
+#endif
+
+VOID
+SampleDrvInterruptDpc (
+ _In_ WDFINTERRUPT WdfInterrupt,
+ _In_ WDFOBJECT WdfDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the DPC callback for the ISR. This routine is unused.
+
+Arguments:
+
+ Interupt - Supplies a handle to interrupt object (WDFINTERRUPT) for this
+ device.
+
+ Device - Supplies a handle to the framework device object.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(WdfInterrupt);
+ UNREFERENCED_PARAMETER(WdfDevice);
+ return;
+}
+
+_Use_decl_annotations_
+NTSTATUS
+SampleDrvEvtDeviceAdd (
+ WDFDRIVER Driver,
+ PWDFDEVICE_INIT DeviceInit
+)
+
+/*++
+
+Routine Description:
+
+ This routine is the AddDevice entry point for the sample device driver.
+ It sets the ISR and DPC routine handlers for the interrupt and the passive
+ level callback for the passive interrupt
+
+ N.B. The sample device expects two interrupt resources in connecting its
+ DIRQL ISR and PASSIVE_LEVEL callback.
+
+Arguments:
+
+ Driver - Supplies a handle to the driver object created in DriverEntry.
+
+ DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT
+ structure.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+
+ WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
+ WDFDEVICE Device;
+ WDF_OBJECT_ATTRIBUTES FdoAttributes;
+ WDF_INTERRUPT_CONFIG InterruptConfiguration;
+ NTSTATUS Status;
+ WDFINTERRUPT WdfInterrupt;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ PAGED_CODE();
+
+ //
+ // Set PnP callbacks for prepare/release hardware and D0 entry/exit. All
+ // callbacks not overriden here will be handled by the framework in the
+ // default manner.
+ //
+
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
+ Callbacks.EvtDevicePrepareHardware = SampleDrvEvtDevicePrepareHardware;
+ Callbacks.EvtDeviceD0Entry = SampleDrvEvtDeviceD0Entry;
+
+ //
+ // Register the PnP callbacks with the framework.
+ //
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &Callbacks);
+
+ //
+ // Initialize FDO attributes with the sample device extension.
+ //
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&FdoAttributes);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&FdoAttributes, SAMPLE_DRV_DEVICE_EXTENSION);
+
+ //
+ // Call the framework to create the device and attach it to the lower stack.
+ //
+
+ Status = WdfDeviceCreate(&DeviceInit, &FdoAttributes, &Device);
+ if (!NT_SUCCESS(Status)) {
+ goto EvtDeviceAddEnd;
+ }
+
+ //
+ // Create an interrupt object for the DIRQL ISR
+ //
+
+ WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
+ SampleDrvInterruptIsr,
+ SampleDrvInterruptDpc);
+
+ Status = WdfInterruptCreate(Device,
+ &InterruptConfiguration,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &WdfInterrupt);
+
+ if (!NT_SUCCESS(Status)) {
+
+ goto EvtDeviceAddEnd;
+ }
+
+#if 0
+ //
+ // Create an interrupt object for the passive interrupt callback. Note that
+ // the interrupt object is chained to the same interrupt line/IDT as the
+ // DIRQL one.
+ //
+
+ WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
+ SampleDrvInterruptIsr,
+ NULL);
+
+ //
+ // Set passive handling to true
+ //
+
+ InterruptConfiguration.PassiveHandling = TRUE;
+
+ Status = WdfInterruptCreate(Device,
+ &InterruptConfiguration,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &WdfInterrupt);
+#endif
+
+EvtDeviceAddEnd:
+ return Status;
+}
+
+NTSTATUS
+SampleDrvEvtDevicePrepareHardware (
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourcesRaw,
+ _In_ WDFCMRESLIST ResourcesTranslated
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by the framework when the PnP manager sends an
+ IRP_MN_START_DEVICE request to the driver stack.
+
+Arguments:
+
+ Device - Supplies a handle to a framework device object.
+
+ ResourcesRaw - Supplies a handle to a collection of framework resource
+ objects. This collection identifies the raw (bus-relative) hardware
+ resources that have been assigned to the device.
+
+ ResourcesTranslated - Supplies a handle to a collection of framework
+ resource objects. This collection identifies the translated
+ (system-physical) hardware resources that have been assigned to the
+ device. The resources appear from the CPU's point of view.
+
+Return Value:
+
+ NT status code.
+
+--*/
+
+{
+
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PSAMPLE_DRV_DEVICE_EXTENSION SampleDrvExtension;
+ ULONG Index;
+ ULONG ResourceCount;
+ NTSTATUS Status;
+ ULONG IoResourceIndex;
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(ResourcesRaw);
+
+ PAGED_CODE();
+
+ SampleDrvExtension = SampleDrvGetDeviceExtension(Device);
+ Status = STATUS_SUCCESS;
+ IoResourceIndex = 0;
+
+ SampleDrvExtension->InterruptCount = 0;
+
+ //
+ // Walk through the resource list and map all the resources. Only one
+ // memory resource and one interrupt is expected.
+ //
+
+ ResourceCount = WdfCmResourceListGetCount(ResourcesTranslated);
+ for (Index = 0; Index < ResourceCount; Index += 1) {
+ Descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, Index);
+ switch(Descriptor->Type) {
+
+ //
+ // This memory resource supplies the base of the device registers.
+ //
+
+ case CmResourceTypeConnection:
+
+ //
+ // Check against expected connection type
+ //
+
+ if ((Descriptor->u.Connection.Class ==
+ CM_RESOURCE_CONNECTION_CLASS_GPIO) &&
+ (Descriptor->u.Connection.Type ==
+ CM_RESOURCE_CONNECTION_TYPE_GPIO_IO)) {
+
+ SampleDrvExtension->ConnectionIds[IoResourceIndex].LowPart =
+ Descriptor->u.Connection.IdLowPart;
+ SampleDrvExtension->ConnectionIds[IoResourceIndex].HighPart =
+ Descriptor->u.Connection.IdHighPart;
+ IoResourceIndex++;
+ } else {
+
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ break;
+
+ //
+ // Interrupt resource
+ //
+
+ case CmResourceTypeInterrupt:
+ SampleDrvExtension->InterruptCount++;
+
+ default:
+ break;
+ }
+
+ if (!NT_SUCCESS(Status)) {
+ goto DevicePrepareHardwareEnd;
+ }
+ }
+
+ //
+ // Ensure that at least two interrupt resources are defined. One for DIRQL
+ // and another for the passive level ISR
+ //
+
+ NT_ASSERT(SampleDrvExtension->InterruptCount > 0);
+
+ if (SampleDrvExtension->InterruptCount < 1) {
+ Status = STATUS_UNSUCCESSFUL;
+ goto DevicePrepareHardwareEnd;
+ }
+
+ //
+ // Store the number of GPIO IO connection strings
+ //
+
+ SampleDrvExtension->IoResourceCount = IoResourceIndex;
+
+DevicePrepareHardwareEnd:
+ return Status;
+}
+
+NTSTATUS
+SampleDrvEvtDeviceD0Entry (
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE PreviousPowerState
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked by the framework to program the device to goto
+ D0, which is the working state. The framework invokes callback every
+ time the hardware needs to be (re-)initialized. This includes after
+ IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
+ and IRP_MN_SET_POWER-D0.
+
+ N.B. This function is not marked pageable because this function is in
+ the device power up path. When a function is marked pagable and the
+ code section is paged out, it will generate a page fault which could
+ impact the fast resume behavior because the client driver will have
+ to wait until the system drivers can service this page fault.
+
+Arguments:
+
+ Device - Supplies a handle to the framework device object.
+
+ PreviousPowerState - WDF_POWER_DEVICE_STATE-typed enumerator that identifies
+ the device power state that the device was in before this transition
+ to D0.
+
+Return Value:
+
+ NTSTATUS code. A failure here will indicate a fatal error and cause the
+ framework to tear down the stack.
+
+--*/
+
+{
+
+ BYTE Data;
+ NTSTATUS Status;
+ WDFIOTARGET ReadTarget;
+ WDFIOTARGET WriteTarget;
+ PSAMPLE_DRV_DEVICE_EXTENSION SampleDrvExtension;
+ UNICODE_STRING ReadString;
+ WCHAR ReadStringBuffer[100];
+ UNICODE_STRING WriteString;
+ WCHAR WriteStringBuffer[100];
+
+ UNREFERENCED_PARAMETER(PreviousPowerState);
+
+ ReadTarget = NULL;
+ WriteTarget = NULL;
+
+ SampleDrvExtension = SampleDrvGetDeviceExtension(Device);
+
+ //
+ // For demonstration purporses, the sample device consumes two IO resources,
+ // the first of which will be used for input, and the second for output.
+ //
+
+ RtlInitEmptyUnicodeString(&ReadString,
+ ReadStringBuffer,
+ sizeof(ReadStringBuffer));
+
+ RtlInitEmptyUnicodeString(&WriteString,
+ WriteStringBuffer,
+ sizeof(WriteStringBuffer));
+
+
+ //
+ // Construct full-path string for GPIO read operation
+ //
+
+ Status = RESOURCE_HUB_CREATE_PATH_FROM_ID(&ReadString,
+ SampleDrvExtension->ConnectionIds[0].LowPart,
+ SampleDrvExtension->ConnectionIds[0].HighPart);
+
+ if (!NT_SUCCESS(Status)) {
+ goto Cleanup;
+ }
+
+ //
+ // Construct full-path string for GPIO write operation
+ //
+
+ Status = RESOURCE_HUB_CREATE_PATH_FROM_ID(&WriteString,
+ SampleDrvExtension->ConnectionIds[1].LowPart,
+ SampleDrvExtension->ConnectionIds[1].HighPart);
+
+ if (!NT_SUCCESS(Status)) {
+ goto Cleanup;
+ }
+
+ //
+ // Perform the read operation
+ //
+
+ Data = 0x0;
+ Status = TestReadWrite(Device, &ReadString, TRUE, &Data, sizeof(Data), &ReadTarget);
+ if (!NT_SUCCESS(Status)) {
+ goto Cleanup;
+ }
+
+ //
+ // Perform the write operation
+ //
+
+ Status = TestReadWrite(Device, &WriteString, FALSE, &Data, sizeof(Data), &WriteTarget);
+ if (!NT_SUCCESS(Status)) {
+ goto Cleanup;
+ }
+
+Cleanup:
+
+ if (ReadTarget != NULL) {
+ WdfIoTargetClose(ReadTarget);
+ WdfObjectDelete(ReadTarget);
+ }
+
+ if (WriteTarget != NULL) {
+ WdfIoTargetClose(WriteTarget);
+ WdfObjectDelete(WriteTarget);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+TestReadWrite (
+ _In_ WDFDEVICE Device,
+ _In_ PCUNICODE_STRING RequestString,
+ _In_ BOOLEAN ReadOperation,
+ _Inout_ PUCHAR Data,
+ _In_ _In_range_(>, 0) ULONG Size,
+ _Out_ WDFIOTARGET *IoTargetOut
+ )
+
+/*++
+
+Routine Description:
+
+ This is a utility routine to test read or write on a set of GPIO pins.
+
+Arguments:
+
+ Device - Supplies a handle to the framework device object.
+
+ RequestString - Supplies a pointer to the unicode string to be opened.
+
+ ReadOperation - Supplies a boolean that identifies whether read (TRUE) or
+ write (FALSE) should be performed.
+
+ Data - Supplies a pointer containing the buffer that should be read from
+ or written to.
+
+ Size - Supplies the size of the data buffer in bytes.
+
+ IoTargetOut - Supplies a pointer that receives the IOTARGET created by
+ WDF.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ WDF_OBJECT_ATTRIBUTES Attributes;
+ WDFREQUEST IoctlRequest;
+ WDFIOTARGET IoTarget;
+ ULONG DesiredAccess;
+ WDFMEMORY WdfMemory;
+ WDF_OBJECT_ATTRIBUTES RequestAttributes;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ NTSTATUS Status;
+ WDF_OBJECT_ATTRIBUTES ObjectAttributes;
+ WDF_IO_TARGET_OPEN_PARAMS OpenParams;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&ObjectAttributes);
+ ObjectAttributes.ParentObject = Device;
+
+ IoctlRequest = NULL;
+ IoTarget = NULL;
+
+ if ((Data == NULL) || (Size == 0)) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto TestReadWriteEnd;
+ }
+
+ Status = WdfIoTargetCreate(Device,
+ &ObjectAttributes,
+ &IoTarget);
+
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ //
+ // Specify desired file access
+ //
+
+ if (ReadOperation != FALSE) {
+ DesiredAccess = FILE_GENERIC_READ;
+
+ } else {
+ DesiredAccess = FILE_GENERIC_WRITE;
+ }
+
+ WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&OpenParams,
+ RequestString,
+ DesiredAccess);
+
+ //
+ // Open the IoTarget for I/O operation
+ //
+
+ Status = WdfIoTargetOpen(IoTarget, &OpenParams);
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&RequestAttributes);
+ Status = WdfRequestCreate(&RequestAttributes, IoTarget, &IoctlRequest);
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ //
+ // Set up a WDF memory object for the IOCTL request
+ //
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
+ Attributes.ParentObject = IoctlRequest;
+ Status = WdfMemoryCreatePreallocated(&Attributes, Data, Size, &WdfMemory);
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ //
+ // Format the request as read or write operation
+ //
+
+ if (ReadOperation != FALSE) {
+ Status = WdfIoTargetFormatRequestForIoctl(IoTarget,
+ IoctlRequest,
+ IOCTL_GPIO_READ_PINS,
+ NULL,
+ 0,
+ WdfMemory,
+ 0);
+
+ } else {
+ Status = WdfIoTargetFormatRequestForIoctl(IoTarget,
+ IoctlRequest,
+ IOCTL_GPIO_WRITE_PINS,
+ WdfMemory,
+ 0,
+ WdfMemory,
+ 0);
+ }
+
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ //
+ // Send the request synchronously with an arbitrary timeout of 60 seconds
+ //
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions,
+ WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions,
+ WDF_REL_TIMEOUT_IN_SEC(60));
+
+ Status = WdfRequestAllocateTimer(IoctlRequest);
+ if (!NT_SUCCESS(Status)) {
+ goto TestReadWriteEnd;
+ }
+
+ if (!WdfRequestSend(IoctlRequest, IoTarget, &SendOptions)) {
+ Status = WdfRequestGetStatus(IoctlRequest);
+ }
+
+ if (NT_SUCCESS(Status)) {
+ *IoTargetOut = IoTarget;
+ }
+
+TestReadWriteEnd:
+ if (IoctlRequest != NULL) {
+ WdfObjectDelete(IoctlRequest);
+ }
+
+ if (!NT_SUCCESS(Status) && (IoTarget != NULL)) {
+ WdfIoTargetClose(IoTarget);
+ WdfObjectDelete(IoTarget);
+ }
+
+ return Status;
+}
+
+
+
diff --git a/gpio/samples/simdevice/simdevice.inx b/gpio/samples/simdevice/simdevice.inx
new file mode 100644
index 00000000..34e65a68
--- /dev/null
+++ b/gpio/samples/simdevice/simdevice.inx
@@ -0,0 +1,76 @@
+;/*++
+;
+;Copyright (c) Microsoft Corporation. All rights reserved.
+;
+;Module Name:
+;
+; SIMGPIO.INF
+;
+;Abstract:
+; INF file for installing Simulated Peripheral Device Driver.
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=System
+ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
+Provider=%MSFT%
+DriverVer=05/07/2010
+CatalogFile=gpiosamples.cat
+
+[SourceDisksNames]
+3426=windows cd
+
+[SourceDisksFiles]
+Simdevice.sys = 3426
+
+;12 == Windows\System32\Drivers
+[DestinationDirs]
+DefaultDestDir = 12
+
+[ControlFlags]
+ExcludeFromSelect=*
+
+;*****************************************
+; SimDevice Install Section
+;*****************************************
+
+[Manufacturer]
+%MSFT%=Microsoft,NT$ARCH$
+
+[Microsoft.NT$ARCH$]
+%DeviceDesc%=DriverInstall,ACPI\TEST0003
+
+[DriverInstall.NT]
+CopyFiles=DriverInstall_Copy
+
+[DriverInstall.NT.Services]
+AddService = simdevice,2,DriverInstall_Service
+
+[DriverInstall_Copy]
+simdevice.sys,,,0x100
+
+[DriverInstall_Service]
+DisplayName = %SvcDesc%
+ServiceType = %SERVICE_KERNEL_DRIVER%
+StartType = %SERVICE_DEMAND_START%
+ErrorControl = %SERVICE_ERROR_NORMAL%
+ServiceBinary = %12%\Simdevice.sys
+
+[Strings]
+;Localizable Strings
+MSFT = "Microsoft"
+Std = "(Standard system devices) Test device"
+SvcDesc = "Test device service"
+DeviceDesc = "Test device description"
+
+;Non-Localizable Strings
+SERVICE_KERNEL_DRIVER = 1
+SERVICE_DEMAND_START = 3
+SERVICE_ERROR_NORMAL = 1
+
+
+
+
+
diff --git a/gpio/samples/simdevice/simdevice.rc b/gpio/samples/simdevice/simdevice.rc
new file mode 100644
index 00000000..3171260d
--- /dev/null
+++ b/gpio/samples/simdevice/simdevice.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Sample device driver"
+#define VER_INTERNALNAME_STR "simdevice.sys"
+#define VER_ORIGINALFILENAME_STR "simdevice.sys"
+
+#include "common.ver"
+
diff --git a/gpio/samples/simdevice/simdevice.vcxproj b/gpio/samples/simdevice/simdevice.vcxproj
new file mode 100644
index 00000000..6d685fcf
--- /dev/null
+++ b/gpio/samples/simdevice/simdevice.vcxproj
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{57BFED37-06F0-435D-A4CA-610B56B8987F}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{7E5C1E9A-1990-437C-B2AB-608C84382F8B}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <Inf Include=".\simdevice.inx">
+ <DateStamp>*</DateStamp>
+ <SpecifyDriverVerDirectiveDate>true</SpecifyDriverVerDirectiveDate>
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\simdevice.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>simdevice</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>simdevice</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>simdevice</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>simdevice</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="simdevice.c" />
+ <ResourceCompile Include="simdevice.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/gpio/samples/simdevice/simdevice.vcxproj.Filters b/gpio/samples/simdevice/simdevice.vcxproj.Filters
new file mode 100644
index 00000000..2cc912e8
--- /dev/null
+++ b/gpio/samples/simdevice/simdevice.vcxproj.Filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{C0D3EEB7-2138-4947-92CF-E7B13BB61AA2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{70E36F5B-DD23-4371-98D3-59AB4042B0F1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{DCCD5E1C-EB33-41FC-81B3-52934D7E2A5A}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{6B2886D3-87CA-46FD-B2A0-C624C0F69F92}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\simdevice.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\simdevice.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="simdevice.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="simdevice.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file