summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Gunn <[email protected]>2018-12-11 17:47:03 -0800
committerChris Gunn <[email protected]>2019-01-08 16:37:40 -0800
commitc400fd8f0b50f3b5b2c51ba2b16eb8e90e7f0700 (patch)
tree56f1f744f5c59ca7153484aedf1d776f50a562be
parent693d7cc6da06e374a0931123f0b5d8c29c945b97 (diff)
Add NFC CX sample driver.
-rw-r--r--nfc/NfcCxSample/README.md49
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc.sln51
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/Device.cpp343
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/Device.h74
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/Driver.cpp41
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.infbin0 -> 3832 bytes
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj95
-rw-r--r--nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj.filters13
8 files changed, 666 insertions, 0 deletions
diff --git a/nfc/NfcCxSample/README.md b/nfc/NfcCxSample/README.md
new file mode 100644
index 00000000..fe2abbc8
--- /dev/null
+++ b/nfc/NfcCxSample/README.md
@@ -0,0 +1,49 @@
+---
+topic: sample
+name: NFC CX client driver sample
+description: Sample code for creating a NFC driver using the NFC Class Extension.
+generateZip: true
+author: windows-driver-content
+languages:
+- cpp
+products:
+- windows
+technologies:
+- WDF
+- UMDF2
+---
+
+# NFC CX client driver sample
+
+A template for creating an NFC functional driver using the NFC Class Extension (CX) driver.
+
+This is a complete version of the code created in the [NFC CX quick start guide](https://docs.microsoft.com/windows-hardware/drivers/nfc/nfc-class-extension-quickstart).
+
+## Prerequisites
+
+To use the NFC CX, your NFC Controller must implement NFC Forum's [NFC Controller Interface (NCI)](https://nfc-forum.org/our-work/specifications-and-application-documents/specifications/nfc-controller-interface-nci-specification/) protocol.
+
+In addition, the NFC CX requires the driver to use the [UMDF 2](https://docs.microsoft.com/windows-hardware/drivers/wdf/overview-of-the-umdf) framework.
+
+## Universal windows driver compliant
+
+This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
+
+## File manifest
+
+### WDK
+
+- [NfcCx.h](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/) - The NFC CX's client driver API. (This file is included in the WDK.)
+
+### Project
+
+- [Driver.cpp](windows-drivertemplate-nfc/Driver.cpp)
+ - `DriverEntry` - Driver initialization.
+
+- [Device.cpp](windows-drivertemplate-nfc/Device.cpp)
+ - `DeviceContext::AddDevice` - Device initialization, including initializing the NFC CX driver.
+ - `DeviceContext::WriteNciPacket` - The implementation of the [`EvtNfcCxWriteNciPacket`](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/nc-nfccx-evt_nfc_cx_write_nci_packet) callback function.
+ - `DeviceContext::ReadNciPacket` - Demonstrates calling [`NfcCxNciReadNotification`](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/nf-nfccx-nfccxncireadnotification).
+
+- [Device.h](windows-drivertemplate-nfc/Device.h)
+ - `DeviceContext` - The class that stores the device instance's state.
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc.sln b/nfc/NfcCxSample/windows-drivertemplate-nfc.sln
new file mode 100644
index 00000000..c2a7a8bf
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28010.2048
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows-drivertemplate-nfc", "windows-drivertemplate-nfc\windows-drivertemplate-nfc.vcxproj", "{E84EF126-888E-4B14-93A3-3B7776036D01}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM.ActiveCfg = Debug|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM.Build.0 = Debug|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM.Deploy.0 = Debug|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM64.Build.0 = Debug|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x64.ActiveCfg = Debug|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x64.Build.0 = Debug|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x64.Deploy.0 = Debug|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x86.ActiveCfg = Debug|Win32
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x86.Build.0 = Debug|Win32
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Debug|x86.Deploy.0 = Debug|Win32
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM.ActiveCfg = Release|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM.Build.0 = Release|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM.Deploy.0 = Release|ARM
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM64.ActiveCfg = Release|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM64.Build.0 = Release|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|ARM64.Deploy.0 = Release|ARM64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x64.ActiveCfg = Release|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x64.Build.0 = Release|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x64.Deploy.0 = Release|x64
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x86.ActiveCfg = Release|Win32
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x86.Build.0 = Release|Win32
+ {E84EF126-888E-4B14-93A3-3B7776036D01}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E67B0F62-B28A-4B28-845C-B31B2614CF22}
+ EndGlobalSection
+EndGlobal
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.cpp b/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.cpp
new file mode 100644
index 00000000..5429d2a8
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.cpp
@@ -0,0 +1,343 @@
+#include <new>
+
+#include "Device.h"
+
+// [Required]
+// Called when the device is provisioned during system boot or when a new device is plugged-in while the
+// system is running.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdriver/nc-wdfdriver-evt_wdf_driver_device_add
+NTSTATUS DeviceContext::AddDevice(
+ _In_ WDFDRIVER Driver,
+ _Inout_ PWDFDEVICE_INIT DeviceInit)
+{
+ (void)Driver;
+
+ NTSTATUS status;
+
+ // Configure the NFC Class Extension.
+ // Note: The NFC_CX_TRANSPORT_TYPE is only used for telemetry purposes. It does not affect the behavior of
+ // the driver.
+ NFC_CX_CLIENT_CONFIG nfcCxConfig;
+ NFC_CX_CLIENT_CONFIG_INIT(&nfcCxConfig, NFC_CX_TRANSPORT_CUSTOM);
+
+#ifdef ENABLE_IF_IMPLEMENTING_CUSTOM_IOCTLS
+ nfcCxConfig.EvtNfcCxDeviceIoControl = IoControl;
+#endif
+
+ // Provide the NCI Write callback, which is called by the NFC CX when it has an NCI packet that needs to
+ // be sent to the NFC Controller.
+ nfcCxConfig.EvtNfcCxWriteNciPacket = WriteNciPacket;
+
+ // Instruct the NFC CX to read the existing NCI configuration values and only update them if necessary.
+ nfcCxConfig.DriverFlags = NFC_CX_DRIVER_ENABLE_EEPROM_WRITE_PROTECTION;
+
+ status = NfcCxDeviceInitConfig(DeviceInit, &nfcCxConfig);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ // Create the PnP power callbacks configuration.
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
+ pnpCallbacks.EvtDevicePrepareHardware = PrepareHardware;
+ pnpCallbacks.EvtDeviceReleaseHardware = ReleaseHardware;
+ pnpCallbacks.EvtDeviceD0Entry = D0Entry;
+ pnpCallbacks.EvtDeviceD0Exit = D0Exit;
+
+ // Set the PnP power callbacks.
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);
+
+ // Create WDF object attributes for the device.
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DeviceContext);
+ deviceAttributes.EvtDestroyCallback = Destroy;
+
+ // Create the device.
+ WDFDEVICE device;
+ status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ // Get a pointer to the raw memory that WDF allocated for the Device class.
+ DeviceContext* context = DeviceGetContext(device);
+
+ // Initialize the raw memory using C++'s placement new operator.
+ // https://en.cppreference.com/w/cpp/language/new
+ new (context) DeviceContext(device);
+
+ // Let the NFC Class Extension initialize the device.
+ status = NfcCxDeviceInitialize(device);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ // Create the RF config. (Enable everything.)
+ NFC_CX_RF_DISCOVERY_CONFIG discoveryConfig;
+ NFC_CX_RF_DISCOVERY_CONFIG_INIT(&discoveryConfig);
+ discoveryConfig.PollConfig = NFC_CX_POLL_NFC_A | NFC_CX_POLL_NFC_B | NFC_CX_POLL_NFC_F_212 | NFC_CX_POLL_NFC_F_424 | NFC_CX_POLL_NFC_15693 | NFC_CX_POLL_NFC_ACTIVE | NFC_CX_POLL_NFC_A_KOVIO;
+ discoveryConfig.NfcIPMode = NFC_CX_NFCIP_NFC_A | NFC_CX_NFCIP_NFC_F_212 | NFC_CX_NFCIP_NFC_F_424 | NFC_CX_NFCIP_NFC_ACTIVE | NFC_CX_NFCIP_NFC_ACTIVE_A | NFC_CX_NFCIP_NFC_ACTIVE_F_212 | NFC_CX_NFCIP_NFC_ACTIVE_F_424;
+ discoveryConfig.NfcIPTgtMode = NFC_CX_NFCIP_TGT_NFC_A | NFC_CX_NFCIP_TGT_NFC_F | NFC_CX_NFCIP_TGT_NFC_ACTIVE_A | NFC_CX_NFCIP_TGT_NFC_ACTIVE_F;
+ discoveryConfig.NfcCEMode = NFC_CX_CE_NFC_A | NFC_CX_CE_NFC_B | NFC_CX_CE_NFC_F;
+
+ // Set the RF config.
+ status = NfcCxSetRfDiscoveryConfig(device, &discoveryConfig);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+#ifdef ENABLE_IF_USING_SEQUENCE_HANDLER_CALLBACKS
+ // Set the NFC Class Extension sequence handlers.
+ for (int sequenceType = 0; sequenceType != SequenceMaximum; ++sequenceType)
+ {
+ status = NfcCxRegisterSequenceHandler(device, NFC_CX_SEQUENCE(sequenceType), SequenceHandler);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+ }
+#endif
+
+ return STATUS_SUCCESS;
+}
+
+DeviceContext::DeviceContext(_In_ WDFDEVICE Device) :
+ _Device(Device)
+{
+}
+
+// [Required]
+// Called when the memory for the class is about to be freed by WDF.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfobject/nc-wdfobject-evt_wdf_object_context_destroy
+void DeviceContext::Destroy(
+ _In_ WDFOBJECT Object)
+{
+ // Manually call the destructor for the class.
+ // This mirrors the use of the placement new operator in `DeviceContext::AddDevice`.
+ DeviceContext* context = DeviceGetContext(Object);
+ context->~DeviceContext();
+}
+
+// [Likely required]
+// Called when the device's hardware resources are ready to be initialized.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nc-wdfdevice-evt_wdf_device_prepare_hardware
+NTSTATUS DeviceContext::PrepareHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourcesRaw,
+ _In_ WDFCMRESLIST ResourcesTranslated)
+{
+ (void)Device;
+ (void)ResourcesRaw;
+ (void)ResourcesTranslated;
+
+ // FIX ME:
+ // Initialize the hardware so that it is ready to accept NCI packets.
+
+ return STATUS_SUCCESS;
+}
+
+// [Likely required]
+// Called when the device's hardware resources are no longer accessible.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nc-wdfdevice-evt_wdf_device_release_hardware
+NTSTATUS DeviceContext::ReleaseHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourcesTranslated)
+{
+ (void)Device;
+ (void)ResourcesTranslated;
+
+ // FIX ME:
+ // If neccessary, free any resources created by PrepareHardware.
+
+ return STATUS_SUCCESS;
+}
+
+// [Likely required]
+// Called when the NFC Controller is entering the fully powered-on state.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nc-wdfdevice-evt_wdf_device_d0_entry
+NTSTATUS DeviceContext::D0Entry(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState)
+{
+ (void)PreviousState;
+
+ NTSTATUS status;
+
+ // Invoke the HostActionStart event, so that the NFC Class Extension initializes the NFC Controller (by
+ // sending the relevant NCI packets).
+ NFC_CX_HARDWARE_EVENT eventArgs = {};
+ eventArgs.HostAction = HostActionStart;
+
+ status = NfcCxHardwareEvent(Device, &eventArgs);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+// [Likely required]
+// Called when the NFC Controller is entering a low power state.
+//
+// By default, the NFC Class Extension will prevent this callback from being invoked if there is an client
+// process that may be using the NFC Controller. So it is okay for the NFC Controller to be fully
+// uninitialized here.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nc-wdfdevice-evt_wdf_device_d0_exit
+NTSTATUS DeviceContext::D0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE TargetState)
+{
+ (void)TargetState;
+
+ NTSTATUS status;
+
+ // Invoke the HostActionStop event, so that the NFC Class Extension uninitializes the NFC Controller (by sending
+ // the relevant NCI packets).
+ NFC_CX_HARDWARE_EVENT eventArgs = {};
+ eventArgs.HostAction = HostActionStop;
+
+ status = NfcCxHardwareEvent(Device, &eventArgs);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+// [Optional]
+// Called when certain state transitions occur within the NFC Class Extension state machine. This can be used to send
+// custom commands to the NFC Controller if neccessary.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/nfc/sequence-handling
+void DeviceContext::SequenceHandler(
+ _In_ WDFDEVICE Device,
+ _In_ NFC_CX_SEQUENCE Sequence,
+ _In_ PFN_NFC_CX_SEQUENCE_COMPLETION_ROUTINE CompletionRoutine,
+ _In_opt_ WDFCONTEXT CompletionContext)
+{
+ (void)Sequence;
+
+ // Nothing to do. So complete the sequence handler immediately.
+ // Note: CompletionRoutine may be called asynchronously.
+ CompletionRoutine(Device, STATUS_SUCCESS, 0, CompletionContext);
+}
+
+// [Optional]
+// Can be used to implement custom IOCTLs.
+//
+// The NFC Class Extension registers for the default I/O queue and so it gets the first crack at handling all I/O requests.
+// If this callback is enabled, any IOCTL the NFC Class Extension doesn't recognize will be forwarded here.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/nc-nfccx-evt_nfc_cx_device_io_control
+void DeviceContext::IoControl(
+ _In_ WDFDEVICE Device,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode)
+{
+ (void)Device;
+ (void)OutputBufferLength;
+ (void)InputBufferLength;
+ (void)IoControlCode;
+
+ // No custom IOCTLs are currently supported. So complete all I/O requests with a standard error.
+ WdfRequestComplete(Request, STATUS_INVALID_DEVICE_STATE);
+}
+
+// [Required]
+// Called by the NFC Class Extension when an NCI packet must be sent to the NFC Controller.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/nc-nfccx-evt_nfc_cx_write_nci_packet
+void DeviceContext::WriteNciPacket(
+ _In_ WDFDEVICE Device,
+ _In_ WDFREQUEST Request)
+{
+ (void)Device;
+
+ NTSTATUS status;
+
+ // Get the NCI packet.
+ void* nciPacket;
+ size_t nciPacketLength;
+ status = WdfRequestRetrieveInputBuffer(Request, 0, &nciPacket, &nciPacketLength);
+ if (!NT_SUCCESS(status))
+ {
+ WdfRequestComplete(Request, status);
+ return;
+ }
+
+ // FIX ME:
+ // Send NCI packet to NFC Controller hardware using the relevant bus API.
+ // For example,
+ // - I2C or SPI: https://docs.microsoft.com/windows-hardware/drivers/spb/spb-peripheral-device-drivers
+ // - USB: https://docs.microsoft.com/windows-hardware/drivers/usbcon/usb-driver-development-guide
+
+ // FIX ME:
+ // Complete I/O request with STATUS_SUCCESS if NCI packet is succesfully sent to the NFC Controller.
+ WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
+}
+
+// FIX ME:
+// Ensure NfcCxNciReadNotification is called when the NFC Controller needs to send an NCI packet to the driver.
+// This is usually done in response to a hardware notification. For example,
+// - GPIO interrupt (I2C or SPI): https://docs.microsoft.com/windows-hardware/drivers/gpio/gpio-interrupts
+// - USB continuous reader: https://docs.microsoft.com/windows-hardware/drivers/usbcon/how-to-use-the-continous-reader-for-getting-data-from-a-usb-endpoint--umdf-/
+//
+// https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/nf-nfccx-nfccxncireadnotification
+
+// A helper function that forwards NCI packets from the NFC Controller to the NFC Class Extension driver.
+//
+// NOTE: If the NCI packet is already packaged within an existing WDFMEMORY, then the NfcCxNciReadNotification
+// function can be called directly.
+NTSTATUS DeviceContext::ReadNciPacket(
+ _In_reads_bytes_(nciPacketLength) void* nciPacket,
+ _In_ size_t nciPacketLength)
+{
+ NTSTATUS status;
+
+ if (!_NciReadMemory)
+ {
+ // Create the WDFMEMORY object that will be used for all NCI reads.
+ WDF_OBJECT_ATTRIBUTES memoryAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
+ memoryAttributes.ParentObject = _Device;
+
+ status = WdfMemoryCreatePreallocated(&memoryAttributes, nciPacket, nciPacketLength, &_NciReadMemory);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+ }
+ else
+ {
+ // Re-assign the WDFMEMORY to point to the new NCI packet.
+ status = WdfMemoryAssignBuffer(_NciReadMemory, nciPacket, nciPacketLength);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+ }
+
+ // Note: NfcCxNciReadNotification does not store a reference to the WDFMEMORY object passed to it. So it
+ // is safe to free the NCI packet's memory after the call has completed.
+ status = NfcCxNciReadNotification(_Device, _NciReadMemory);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.h b/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.h
new file mode 100644
index 00000000..5d373d11
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/Device.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include <windows.h>
+#include <wdf.h>
+#include <NfcCx.h>
+
+class DeviceContext
+{
+public:
+ // Implementation of `EvtDriverDeviceAdd`.
+ static NTSTATUS AddDevice(
+ _In_ WDFDRIVER Driver,
+ _Inout_ PWDFDEVICE_INIT DeviceInit);
+
+private:
+ DeviceContext(_In_ WDFDEVICE Device);
+ ~DeviceContext() = default;
+
+ // Implementation of `EvtDestroyCallback`.
+ static void Destroy(
+ _In_ WDFOBJECT Object);
+
+ // Implementation of `EvtDevicePrepareHardware`.
+ static NTSTATUS PrepareHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourcesRaw,
+ _In_ WDFCMRESLIST ResourcesTranslated);
+
+ // Implementation of `EvtDeviceReleaseHardware`.
+ static NTSTATUS ReleaseHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourcesTranslated);
+
+ // Implementation of `EvtDeviceD0Entry`.
+ static NTSTATUS D0Entry(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState);
+
+ // Implementation of `EvtDeviceD0Exit`.
+ static NTSTATUS D0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE TargetState);
+
+ // Implementation of `EvtNfcCxSequenceHandler`.
+ static void SequenceHandler(
+ _In_ WDFDEVICE Device,
+ _In_ NFC_CX_SEQUENCE Sequence,
+ _In_ PFN_NFC_CX_SEQUENCE_COMPLETION_ROUTINE CompletionRoutine,
+ _In_opt_ WDFCONTEXT CompletionContext);
+
+ static void IoControl(
+ _In_ WDFDEVICE Device,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode);
+
+ // Implementation of `EvtNfcCxWriteNciPacket`.
+ static void WriteNciPacket(
+ _In_ WDFDEVICE Device,
+ _In_ WDFREQUEST Request);
+
+ NTSTATUS ReadNciPacket(
+ _In_reads_bytes_(nciPacketLength) void* nciPacket,
+ _In_ size_t nciPacketLength);
+
+ const WDFDEVICE _Device = nullptr;
+ WDFMEMORY _NciReadMemory = nullptr;
+};
+
+// Define the DeviceGetContext() function which can be used to get a pointer the DeviceContext from a WDFDEVICE object.
+// Equivalent to:
+// DeviceContext* DeviceGetContext(WDFOBJECT Handle) { ... }
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DeviceContext, DeviceGetContext);
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/Driver.cpp b/nfc/NfcCxSample/windows-drivertemplate-nfc/Driver.cpp
new file mode 100644
index 00000000..c07eabe8
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/Driver.cpp
@@ -0,0 +1,41 @@
+#include <windows.h>
+#include <wdf.h>
+
+#include "Device.h"
+
+extern "C" DRIVER_INITIALIZE DriverEntry;
+
+// [Required]
+// The entry point for the driver.
+//
+// In general, almost nothing should be done during driver initialization. Instead, almost all resources should
+// be associated with a specific device.
+//
+// https://docs.microsoft.com/windows-hardware/drivers/wdf/driverentry-for-kmdf-drivers
+extern "C" NTSTATUS DriverEntry(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+ )
+{
+ NTSTATUS status;
+
+ // Specify `DeviceContext::AddDevice` as the `EvtDriverDeviceAdd` callback function
+ // for the driver.
+ WDF_DRIVER_CONFIG driverConfig;
+ WDF_DRIVER_CONFIG_INIT(&driverConfig, DeviceContext::AddDevice);
+
+ // Initialize WDF.
+ status = WdfDriverCreate(
+ DriverObject,
+ RegistryPath,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &driverConfig,
+ WDF_NO_HANDLE
+ );
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.inf b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.inf
new file mode 100644
index 00000000..d6070a8c
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.inf
Binary files differ
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj
new file mode 100644
index 00000000..ce9fe362
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj
@@ -0,0 +1,95 @@
+<?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>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="windows-drivertemplate-nfc.inf" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E84EF126-888E-4B14-93A3-3B7776036D01}</ProjectGuid>
+ <TemplateGuid>{2177f19c-eb4c-4687-9e7f-f9eec1f12cf1}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <RootNamespace>windows_drivertemplate_nfc</RootNamespace>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <NfcDriver>true</NfcDriver>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <EnablePREfast>true</EnablePREfast>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Device.cpp" />
+ <ClCompile Include="Driver.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Device.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj.filters b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj.filters
new file mode 100644
index 00000000..c02665df
--- /dev/null
+++ b/nfc/NfcCxSample/windows-drivertemplate-nfc/windows-drivertemplate-nfc.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="Driver.cpp" />
+ <ClCompile Include="Device.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="windows-drivertemplate-nfc.inf" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Device.h" />
+ </ItemGroup>
+</Project> \ No newline at end of file