Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa guida illustra come scrivere un driver funzionale NFC usando il driver NFC Class Extension (NFC CX).
Nota
Un driver che usa un driver di estensione di classe nell'implementazione è noto come "driver client". Cioè, un client del driver di estensione della classe.
Prerequisiti
- Il firmware del controller NFC deve implementare il protocollo NFC Controller Interface (NCI) del forum NFC.
- Visual Studio 2017 (o versione successiva).
- Windows SDK.
- Windows Driver Kit (WDK).
Responsabilità del driver del cliente
Il driver CX NFC è responsabile della gestione delle richieste di I/O inviate al driver e della creazione dei pacchetti di comandi NCI pertinenti. Il driver client è responsabile dell'invio di tali pacchetti NCI al controller NFC e dell'invio dei pacchetti di risposta NCI al driver CX NFC.
Spetta al driver client determinare come inviare i pacchetti NCI al controller NFC. Questo processo varia a seconda del tipo di bus hardware usato. I bus comuni usati dai controller NFC includono I2C, SPI e USB.
Codice del progetto completo
Una versione completa di questo codice di esempio è disponibile in GitHub: esempio di driver client CX NFC.
Configurazione del progetto
In Visual Studio creare un nuovo progetto "Driver in modalità utente, Vuoto (UMDF V2)".
Scegliere Nuovo dal menu Filee quindi selezionare Progetto. Nel nodo Visual C++, in Driver di Windows, seleziona WDF, e quindi seleziona Driver in modalità utente, Vuoto (UMDF V2)
Aprire il file INF.
In Esplora soluzioni, nel nodo <project-name>, nella cartella File driver fare doppio clic su <project-name.inf>.
Nel file INF rimuovere la classe di dispositivo personalizzata seguendo questa procedura:
Rimuovere le due sezioni seguenti:
[ClassInstall32] AddReg=SampleClass_RegistryAdd [SampleClass_RegistryAdd] HKR,,,,%ClassName% HKR,,Icon,,"-10"[Strings]Nella sezione rimuovere la riga seguente.ClassName="Samples" ; TODO: edit ClassName
Nel file INF impostare la classe di dispositivo del driver su Prossimità:
- Modificare il valore di
ClassinProximity - Modificare il valore di
ClassGuidin{5630831C-06C9-4856-B327-F5D32586E060}- Questo è il GUID della classe del dispositivo di prossimità.
[Version] ... Class=Proximity ClassGuid={5630831C-06C9-4856-B327-F5D32586E060} ; Proximity class GUID ...- Modificare il valore di
Nel file INF aggiungere un riferimento all'estensione di classe NFC. In questo modo si garantisce che Windows Driver Framework (WDF) carichi il driver CX NFC quando viene caricato il driver client.
- Trova la sezione
<project-name>_Install. - Aggiungere
UmdfExtensions=NfcCx0102.
[<project-name>_Install] ... UmdfExtensions=NfcCx0102- Trova la sezione
Nelle impostazioni di compilazione del driver collegarsi all'estensione della classe NFC. In questo modo si garantisce che l'API CX NFC sia disponibile durante la compilazione del codice.
- In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Proprietà. In Proprietà di configurazione, in Impostazioni driver selezionare NFC.
- Assicurarsi che Configuration sia impostato su
All Configurations. - Assicurarsi che Platform sia impostato su
All Platforms. - Configura Collegamento all'estensione della classe NFC su
Yes.
Aggiungere un file denominato
Driver.cppal progetto.Crea una
DriverEntryroutine inDriver.cpp. Questo è il punto di ingresso per il driver. Lo scopo principale è inizializzare WDF e registrare laEvtDriverDeviceAddfunzione di callback.#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; }Aggiungere due file denominati
Device.cppeDevice.hal progetto.In
Device.hdefinire la classeDeviceContext.#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);Nella
Device.cpp, iniziare la definizione della funzioneDeviceContext::AddDevice.#include "Device.h" NTSTATUS DeviceContext::AddDevice( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) { NTSTATUS status;Impostare la configurazione del dispositivo CX NFC. La configurazione del dispositivo include la
EvtNfcCxWriteNciPacketfunzione di callback. Questo callback riceve i pacchetti NCI dal driver CX NFC che il driver client deve inoltrare al controller NFC.// 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; }Registrare i callback di alimentazione PnP richiesti dal driver client.
È probabile che un driver client tipico richieda le funzioni
EvtDevicePrepareHardware,EvtDeviceReleaseHardware,EvtDeviceD0EntryeEvtDeviceD0Exit. I requisiti possono variare a seconda del modo in cui il driver client gestisce la gestione dell'alimentazione.// 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);Chiamare la
WdfDeviceCreatefunzione per creare l'oggettoWDFDEVICE.// 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; }Chiamare la funzione
NfcCxDeviceInitialize.Questa funzione deve essere chiamata dopo la creazione dell'oggetto
WDFDEVICEper consentire al driver CX NFC di completare l'inizializzazione dell'istanza del dispositivo.// Let NFC CX finish initializing the device instance. status = NfcCxDeviceInitialize(device); if (!NT_SUCCESS(status)) { return status; }Chiamare
NfcCxSetRfDiscoveryConfigper specificare le tecnologie NFC e i protocolli supportati dal controller NFC.// 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; }Termina la funzione
DeviceContext::AddDevice.return STATUS_SUCCESS; }Implementare le funzioni di callback
PrepareHardwareeReleaseHardware.Queste due funzioni vengono usate per inizializzare e deinizializzare le risorse hardware assegnate all'istanza del dispositivo del controller NFC. La loro implementazione dipende dal tipo di bus a cui il dispositivo è connesso (ad esempio, I2C, SPI e 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; }Chiamare la funzione
NfcCxHardwareEventconHostActionStarteHostActionStopper avviare e arrestare la macchina a stati NCI nei momenti appropriati.Alcuni driver eseguono questa operazione durante i callback di alimentazione PnP di
D0EntryeD0Exit. Tuttavia, questo può variare a seconda del modo in cui il driver client gestisce il risparmio energetico.// 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; }Implementare la
WriteNciPacketfunzione .Questo callback viene chiamato da NFC CX quando è presente un pacchetto NCI da inviare al controller NFC.
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. };Chiamare la
NfcCxNciReadNotificationfunzione quando il controller NFC ha un pacchetto NCI che deve essere inviato a NFC CX. In genere, eseguire questa operazione in un callback di eventi hardware.Per esempio:
- Callback dell'evento di interrupt GPIO . (I2C e SPI)
- Callback del lettore USB continuo.
Registrazione
Prendere in considerazione l'aggiunta della registrazione al driver client per semplificare il debug. Sia la traccia ETW che la traccia WPP sono opzioni valide.