NFC CX Quick Start Guide - Windows drivers (2024)

Edit

Share via

  • Article

This guide demonstrates how to write an NFC functional driver using the NFC Class Extension (NFC CX) driver.

Note

A driver that uses a class extension driver in its implementation is known as a 'client driver'. That is to say, a client of the class extension driver.

Prerequisites

  • Your NFC Controller's firmware must implement the NFC Forum's NFC Controller Interface (NCI) protocol.
  • Visual Studio 2017 (or later).
  • The Windows SDK.
  • The Windows Driver Kit (WDK).

Client driver responsibilities

The NFC CX driver is responsible for handling I/O requests sent to the driver and creating the relevant NCI command packets. The client driver is responsible for sending those NCI packets to the NFC Controller and sending back the NCI response packets to the NFC CX driver.

It's up to the client driver to determine how to send the NCI packets to the NFC Controller. This process varies depending on what type of hardware bus is used. Common buses used by NFC Controllers include I2C, SPI and USB.

Complete project code

A complete version of this sample code is available on GitHub: NFC CX client driver sample.

Project setup

  1. In Visual Studio, create a new "User Mode Driver, Empty (UMDF V2)" project.

    On the File menu, point to New, and then select Project. In the Visual C++ node, under Windows Drivers, select WDF, and then select User Mode Driver, Empty (UMDF V2)

    NFC CX Quick Start Guide - Windows drivers (1)

  2. Open the INF file.

    In Solution Explorer, under the <project-name> node, in the Driver Files folder, double-click <project-name>.inf.

  3. In the INF file, remove the custom device class, by using the following steps:

    1. Remove the following two sections:

      [ClassInstall32]AddReg=SampleClass_RegistryAdd[SampleClass_RegistryAdd]HKR,,,,%ClassName%HKR,,Icon,,"-10"
    2. Under the [Strings] section, remove the following line.

      ClassName="Samples" ; TODO: edit ClassName
  4. In the INF file, set driver's device class to Proximity:

    1. Change the value of Class to Proximity
    2. Change the value of ClassGuid to {5630831C-06C9-4856-B327-F5D32586E060}
      • This is the GUID of the Proximity device class.
    [Version]...Class=ProximityClassGuid={5630831C-06C9-4856-B327-F5D32586E060} ; Proximity class GUID...
  5. In the INF file, add a reference to the NFC Class Extension. Doing this ensures that Windows Driver Framework (WDF) loads the NFC CX driver when the client driver loads.

    1. Find the <project-name>_Install section.
    2. Add UmdfExtensions=NfcCx0102.
    [<project-name>_Install]...UmdfExtensions=NfcCx0102
  6. In the driver build settings, link to the NFC Class Extension. Doing this ensures that the NFC CX API is available during code compilation.

    1. In Solution Explorer, right-click the project, and select Properties. In Configuration Properties, under Driver Settings, select NFC.
    2. Ensure that Configuration is set to All Configurations.
    3. Ensure that Platform is to set to All Platforms.
    4. Set Link to NFC Class Extension to Yes.

    NFC CX Quick Start Guide - Windows drivers (2)

  7. Add file named Driver.cpp to the project.

  8. Create a DriverEntry routine in Driver.cpp. This is the entry point for the driver. Its primary purpose is to initialize WDF and to register the EvtDriverDeviceAdd callback function.

    #include <windows.h>#include <wdf.h>#include "Device.h" // created in Step 9// The entry point for the driver.extern "C" NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ){ NTSTATUS status = STATUS_SUCCESS; // Specify `DeviceContext::AddDevice` as the // `EvtDriverDeviceAdd` 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;}
  9. Add two files named Device.cpp and Device.h to the project.

  10. In Device.h, define the DeviceContext class.

    #pragma once#include <windows.h>#include <wdf.h>#include <NfcCx.h>// The class that will store the driver's custom state for// a device instance.class DeviceContext{public: // Implementation of `EvtDriverDeviceAdd`. static NTSTATUS AddDevice( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit);private: // 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 `EvtNfcCxWriteNciPacket`. static void WriteNciPacket( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request);};// Define the `DeviceGetContext` function.WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DeviceContext, DeviceGetContext);
  11. In Device.cpp, begin the DeviceContext::AddDevice function's definition.

    #include "Device.h"NTSTATUS DeviceContext::AddDevice( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit){ NTSTATUS status;
  12. Set the NFC CX device configuration. The device configuration includes providing the EvtNfcCxWriteNciPacket callback function. This callback receives the NCI packets from the NFC CX driver that the client driver should forward to the NFC Controller.

     // Create the NfcCx config. NFC_CX_CLIENT_CONFIG nfcCxConfig; NFC_CX_CLIENT_CONFIG_INIT(&nfcCxConfig, NFC_CX_TRANSPORT_CUSTOM); nfcCxConfig.EvtNfcCxWriteNciPacket = WriteNciPacket; nfcCxConfig.DriverFlags = NFC_CX_DRIVER_ENABLE_EEPROM_WRITE_PROTECTION; // Set the NfcCx config. status = NfcCxDeviceInitConfig(DeviceInit, &nfcCxConfig); if (!NT_SUCCESS(status)) { return status; }
  13. Register the PnP power callbacks required by your client driver.

    A typical client driver will likely require the EvtDevicePrepareHardware, the EvtDeviceReleaseHardware, the EvtDeviceD0Entry and the EvtDeviceD0Exit functions. Requirements can vary depending on how your client driver handles power management.

     // 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);
  14. Call the WdfDeviceCreate function to create the WDFDEVICE object.

     // Create WDF object attributes for the WDFDEVICE object. WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DeviceContext); // Create the device. WDFDEVICE device; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; }
  15. Call the NfcCxDeviceInitialize function.

    This function should be called after the WDFDEVICE object has been created to allow the NFC CX driver to complete its initialization of the device instance.

     // Let NFC CX finish initializing the device instance. status = NfcCxDeviceInitialize(device); if (!NT_SUCCESS(status)) { return status; }
  16. Call NfcCxSetRfDiscoveryConfig to specify the NFC technologies and protocols supported by the NFC Controller.

     // 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; }
  17. End the DeviceContext::AddDevice function.

     return STATUS_SUCCESS;}
  18. Implement the PrepareHardware and ReleaseHardware callback functions.

    These two functions are used to initialize and uninitialize the hardware resources assigned to the NFC Controller's device instance. Their implementation depends on what type of bus the device is connected to (for example, I2C, SPI and USB).

    NTSTATUS DeviceContext::PrepareHardware( _In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesRaw, _In_ WDFCMRESLIST ResourcesTranslated){ // FIX ME: Initialize hardware resources. return STATUS_SUCCESS;}NTSTATUS DeviceContext::ReleaseHardware( _In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesTranslated){ // FIX ME: Uninitialize hardware resources. return STATUS_SUCCESS;}
  19. Call the NfcCxHardwareEvent function with HostActionStart and HostActionStop to start and stop the NCI state machine at the appropriate times.

    Some drivers do this during the D0Entry and D0Exit PnP power callbacks. This can vary depending on how your client driver handles power management, though.

    // Device exiting low power state (or is booting up).NTSTATUS DeviceContext::D0Entry( _In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE PreviousState){ (void)PreviousState; NTSTATUS status; // Invoke the HostActionStart event, so that the NFC CX initializes // the NFC Controller. NFC_CX_HARDWARE_EVENT eventArgs = {}; eventArgs.HostAction = HostActionStart; status = NfcCxHardwareEvent(Device, &eventArgs); if (!NT_SUCCESS(status)) { return status; } return STATUS_SUCCESS;}// Device entering low power state.NTSTATUS DeviceContext::D0Exit( _In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE TargetState){ (void)TargetState; NTSTATUS status; // Trigger the HostActionStop event, so that the NFC CX // uninitializes the NFC Controller. NFC_CX_HARDWARE_EVENT eventArgs = {}; eventArgs.HostAction = HostActionStop; status = NfcCxHardwareEvent(Device, &eventArgs); if (!NT_SUCCESS(status)) { return status; } return STATUS_SUCCESS;}
  20. Implement the WriteNciPacket function.

    This callback is called by the NFC CX when there's an NCI packet to send to the NFC Controller.

    void DeviceContext::WriteNciPacket( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request){ NTSTATUS status; // Get the NCI packet as a raw byte buffer. void* nciPacket; size_t nciPacketLength; status = WdfRequestRetrieveInputBuffer(Request, 0, &nciPacket, &nciPacketLength); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } // FIX ME: Use the NCI packet in some way. // FIX ME: Call `WdfRequestComplete` on `Request` with failure // or success `NTSTATUS` code.};
  21. Call the NfcCxNciReadNotification function when the NFC Controller has an NCI packet that should be sent to the NFC CX. This is typically done in a hardware event callback.

    For example:

    • A GPIO interrupt event callback. (I2C and SPI)
    • A USB continuous reader callback.

Logging

Consider adding logging to the client driver to make it easier to debug. Both ETW tracing and WPP tracing are good options.

Feedback

Was this page helpful?

Provide product feedback|

NFC CX Quick Start Guide - Windows drivers (2024)

References

Top Articles
Endwell Family Patient Portal
Is File2Share Safe? | Batten Safe
Navicent Human Resources Phone Number
Whas Golf Card
Aberration Surface Entrances
The Ivy Los Angeles Dress Code
How to Type German letters ä, ö, ü and the ß on your Keyboard
Palace Pizza Joplin
Jasmine
Rls Elizabeth Nj
FIX: Spacebar, Enter, or Backspace Not Working
The Weather Channel Facebook
Regal Stone Pokemon Gaia
Gas Station Drive Thru Car Wash Near Me
Miss America Voy Forum
Luna Lola: The Moon Wolf book by Park Kara
Ts Lillydoll
Magic Mike's Last Dance Showtimes Near Marcus Cedar Creek Cinema
Operation Cleanup Schedule Fresno Ca
Jinx Chapter 24: Release Date, Spoilers & Where To Read - OtakuKart
Www Craigslist Milwaukee Wi
Jalapeno Grill Ponca City Menu
Candy Land Santa Ana
Lehmann's Power Equipment
Wausau Marketplace
Delaware Skip The Games
Outlet For The Thames Crossword
Att.com/Myatt.
Busted Mcpherson Newspaper
Www.paystubportal.com/7-11 Login
Watch Your Lie in April English Sub/Dub online Free on HiAnime.to
Play Tetris Mind Bender
The 15 Best Sites to Watch Movies for Free (Legally!)
Divina Rapsing
Ullu Coupon Code
Evil Dead Rise Showtimes Near Regal Sawgrass & Imax
Missing 2023 Showtimes Near Mjr Southgate
Urban Blight Crossword Clue
First Light Tomorrow Morning
Yoshidakins
Facebook Marketplace Marrero La
The 50 Best Albums of 2023
Husker Football
Live Delta Flight Status - FlightAware
התחבר/י או הירשם/הירשמי כדי לראות.
Exploring the Digital Marketplace: A Guide to Craigslist Miami
Swsnj Warehousing Inc
Bf273-11K-Cl
Verizon Forum Gac Family
Congressional hopeful Aisha Mills sees district as an economical model
Tamilyogi Cc
Latest Posts
Article information

Author: Kareem Mueller DO

Last Updated:

Views: 5342

Rating: 4.6 / 5 (66 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Kareem Mueller DO

Birthday: 1997-01-04

Address: Apt. 156 12935 Runolfsdottir Mission, Greenfort, MN 74384-6749

Phone: +16704982844747

Job: Corporate Administration Planner

Hobby: Mountain biking, Jewelry making, Stone skipping, Lacemaking, Knife making, Scrapbooking, Letterboxing

Introduction: My name is Kareem Mueller DO, I am a vivacious, super, thoughtful, excited, handsome, beautiful, combative person who loves writing and wants to share my knowledge and understanding with you.