diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /gpio/samples/simdevice | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'gpio/samples/simdevice')
| -rw-r--r-- | gpio/samples/simdevice/GpioSample.asl | 124 | ||||
| -rw-r--r-- | gpio/samples/simdevice/common.h | 84 | ||||
| -rw-r--r-- | gpio/samples/simdevice/simdevice.c | 819 | ||||
| -rw-r--r-- | gpio/samples/simdevice/simdevice.inx | 76 | ||||
| -rw-r--r-- | gpio/samples/simdevice/simdevice.rc | 12 | ||||
| -rw-r--r-- | gpio/samples/simdevice/simdevice.vcxproj | 189 | ||||
| -rw-r--r-- | gpio/samples/simdevice/simdevice.vcxproj.Filters | 39 |
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 |
