Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Deze handleiding laat zien hoe u een NFC-functioneel stuurprogramma schrijft met behulp van het NFC Class Extension (NFC CX)-stuurprogramma.
Note
Een stuurprogramma dat gebruikmaakt van een stuurprogramma voor de klasse-extensie in de implementatie, wordt een 'clientstuurprogramma' genoemd. Dat wil zeggen, een client van het klasse-extensiestuurprogramma.
Prerequisites
- De firmware van de NFC-controller moet het protocol van het NFC-forum voor de NFC-controllerinterface (NCI) implementeren.
- Visual Studio 2017 (of hoger).
- De Windows SDK.
- De Windows Driver Kit (WDK).
Verantwoordelijkheden van het clientstuurprogramma
Het NFC CX-stuurprogramma is verantwoordelijk voor het verwerken van I/O-aanvragen die naar het stuurprogramma worden verzonden en het maken van de relevante NCI-opdrachtpakketten. Het clientstuurprogramma is verantwoordelijk voor het verzenden van die NCI-pakketten naar de NFC-controller en het terugsturen van de NCI-antwoordpakketten naar het NFC CX-stuurprogramma.
Het is aan het clientstuurprogramma om te bepalen hoe de NCI-pakketten naar de NFC-controller moeten worden verzonden. Dit proces varieert afhankelijk van het type hardwarebus dat wordt gebruikt. Veelgebruikte bussen die worden gebruikt door NFC Controllers zijn I2C, SPI en USB.
Volledige projectcode
Een volledige versie van deze voorbeeldcode is beschikbaar op GitHub: Voorbeeld van het NFC CX-clientstuurprogramma.
Projectopstelling
Maak in Visual Studio een nieuw project 'User Mode Driver, Empty (UMDF V2)'.
Wijs in het menu Bestand de optie Nieuw aan en selecteer Project. Selecteer in het knooppunt Visual C++, onder Windows Stuurprogramma's, WDF en selecteer vervolgens Stuurprogramma voor gebruikersmodus, Leeg (UMDF V2)
Open het INF-bestand.
Dubbelklik op <project-name>.inf in Solution Explorer, onder het knooppunt <project-name>, in de map Stuurprogrammabestanden.
Verwijder in het INF-bestand de aangepaste apparaatklasse met behulp van de volgende stappen:
Verwijder de volgende twee secties:
[ClassInstall32] AddReg=SampleClass_RegistryAdd [SampleClass_RegistryAdd] HKR,,,,%ClassName% HKR,,Icon,,"-10"Verwijder onder de
[Strings]sectie de volgende regel.ClassName="Samples" ; TODO: edit ClassName
Stel in het INF-bestand de apparaatklasse van het stuurprogramma in op Proximity:
- Wijzig de waarde van
ClassinProximity - Wijzig de waarde van
ClassGuidin{5630831C-06C9-4856-B327-F5D32586E060}- Dit is de GUID van de proximity-apparaatklasse.
[Version] ... Class=Proximity ClassGuid={5630831C-06C9-4856-B327-F5D32586E060} ; Proximity class GUID ...- Wijzig de waarde van
Voeg in het INF-bestand een verwijzing toe naar de NFC-klasseextensie. Dit zorgt ervoor dat Windows Driver Framework (WDF) het NFC CX-stuurprogramma laadt wanneer het clientstuurprogramma wordt geladen.
- Zoek de
<project-name>_Installsectie. - Voeg
UmdfExtensions=NfcCx0102toe.
[<project-name>_Install] ... UmdfExtensions=NfcCx0102- Zoek de
Maak in de build-instellingen van het stuurprogramma een koppeling naar de NFC-klasse-extensie. Dit zorgt ervoor dat de NFC CX-API beschikbaar is tijdens het compileren van code.
- Klik in Solution Explorer met de rechtermuisknop op het project en selecteer Eigenschappen. Selecteer in Configuratie-eigenschappen onder Stuurprogramma-instellingenNFC.
- Zorg ervoor dat de configuratie is ingesteld op
All Configurations. - Zorg ervoor dat Platform moet worden ingesteld op
All Platforms. - Stel koppeling naar NFC-klasse-extensie in op
Yes.
Voeg het bestand met de naam
Driver.cpptoe aan het project.Maak een
DriverEntryroutine inDriver.cpp. Dit is het toegangspunt voor de bestuurder. Het primaire doel is om WDF te initialiseren en deEvtDriverDeviceAddcallback-functie te registreren.#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; }Voeg twee bestanden met de naam
Device.cppenDevice.haan het project toe.Definieer in
Device.hde klasseDeviceContext.#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);Begin
Device.cppin de definitie van deDeviceContext::AddDevicefunctie.#include "Device.h" NTSTATUS DeviceContext::AddDevice( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) { NTSTATUS status;Stel de configuratie van het NFC CX-apparaat in. De configuratie van het apparaat omvat het leveren van de
EvtNfcCxWriteNciPacketcallback-functie. Deze callback ontvangt de NCI-pakketten van het NFC CX-stuurprogramma die het clientstuurprogramma moet doorsturen naar de 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; }Registreer de PnP-power callbacks die zijn vereist voor het clientstuurprogramma.
Een typisch clientstuurprogramma vereist waarschijnlijk de
EvtDevicePrepareHardware, deEvtDeviceReleaseHardware, deEvtDeviceD0Entryen deEvtDeviceD0Exitfuncties. De vereisten kunnen variëren, afhankelijk van hoe uw clientstuurprogramma energiebeheer afhandelt.// 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);Roep de
WdfDeviceCreatefunctie aan om hetWDFDEVICEobject te maken.// 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; }Roep de functie
NfcCxDeviceInitializeaan.Deze functie moet worden aangeroepen nadat het
WDFDEVICEobject is gemaakt, zodat het NFC CX-stuurprogramma de initialisatie van het apparaatexemplaar kan voltooien.// Let NFC CX finish initializing the device instance. status = NfcCxDeviceInitialize(device); if (!NT_SUCCESS(status)) { return status; }Roep
NfcCxSetRfDiscoveryConfigaan om de NFC-technologieën en -protocollen op te geven die worden ondersteund door de 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; }Beëindig de
DeviceContext::AddDevicefunctie.return STATUS_SUCCESS; }Implementeer de callbackfuncties
PrepareHardwareenReleaseHardware.Deze twee functies worden gebruikt om de hardwarebronnen die zijn toegewezen aan de apparaatinstantie van de NFC-controller te initialiseren en te de-initialiseren. De implementatie is afhankelijk van het type bus waarmee het apparaat is verbonden (bijvoorbeeld I2C, SPI en 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; }Roep de
NfcCxHardwareEventfunctie aan metHostActionStartenHostActionStopom de NCI-statusmachine op de juiste tijdstippen te starten en te stoppen.Sommige stuurprogramma's doen dit tijdens de
D0EntryenD0ExitPnP-energiecallbacks. Dit kan echter variëren, afhankelijk van hoe uw clientstuurprogramma energiebeheer afhandelt.// 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; }Implementeer de
WriteNciPacketfunctie.Deze callback wordt aangeroepen door de NFC CX wanneer er een NCI-pakket is dat naar de NFC-controller moet worden verzonden.
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. };Roep de
NfcCxNciReadNotificationfunctie aan wanneer de NFC-controller een NCI-pakket heeft dat naar de NFC CX moet worden verzonden. Doe dit meestal in een callback van hardware-gebeurtenissen.Voorbeeld:
- Een GPIO-interrupt-gebeurteniscallback. (I2C en SPI)
- Een USB continuous reader callback.
Logging
Overweeg logboekregistratie toe te voegen aan het clientstuurprogramma, zodat u eenvoudiger fouten kunt opsporen. Zowel ETW-tracering als WPP-tracering zijn goede opties.