Rewrite NfcCxRF sequence handling.

1. Remove the concept of sequence process functions. These functions
were originally intended to be used to process the results of
asynchronous operations. However the result processing logic instead
exists in the operations' callback handlers. So the sequence process
functions are always set to NULL and are therefore pointless.

2. Store the value of the sequence complete function (the function
called when the sequence has finished) separately, instead of having it
be part of the the list of sequence handlers. This was done because
there is a number of sequences that only differ by their complete
function. So it makes the code cleaner to support this directly.

3. Ensure that all sequence lists are specified in immutable global
memory, instead of mutable global memory. (#2 made doing this a lot
easier.)

4. Store the state of a running sequence in heap allocated memory. This
memory is used:
    1. To uniquely identify a running sequence, so that sequence
    conflicts can be detected.
    2. As the context value for (LibNfc) asynchronous operations. This
    replaces the mutable global variables that were previously used for
    this purpose. (e.g. NFCCX_RF_LIBNFC_REQUEST_CONTEXT.)

5. Make the sequence complete functions return `void` instead of
`NTSTATUS`. This error code was never used for anything. So its
existence only causes confusion.

6. Remove the `Status` parameter from the sequence handler functions.
This value was alaways `STATUS_SUCCESS` and was never used for anything.
So its existence only causes confusion.

7. If the initial sequence handler completes synchronously (either
success or failure), then call complete function in a new message to the
LibNfc thread. This ensures that the state handler function is not
called recursively.
This commit is contained in:
Chris Gunn 2018-10-25 14:56:12 -07:00
Родитель d438ba038f
Коммит 5e57eea88a
8 изменённых файлов: 772 добавлений и 1003 удалений

Просмотреть файл

@ -89,7 +89,7 @@ NfcCxLLCPInterfaceCheckCB(
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
LLCPInterface->eRequestState = NFCCX_LLCP_REQUEST_COMPLETE;
NfcCxInternalSequence(NfcCxLLCPInterfaceGetRFInterface(LLCPInterface), NfcCxLLCPInterfaceGetRFInterface(LLCPInterface)->pSeqHandler, status, NULL, NULL);
NfcCxSequenceDispatchResume(NfcCxLLCPInterfaceGetRFInterface(LLCPInterface), NfcCxLLCPInterfaceGetRFInterface(LLCPInterface)->CurrentSequence, status, NULL, NULL);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
}
@ -126,7 +126,7 @@ NfcCxLLCPInterfaceLinkStatusCB(
if (LLCPInterface->IsDeactivatePending)
{
LLCPInterface->IsDeactivatePending = false;
NfcCxInternalSequence(RFInterface, RFInterface->pSeqHandler, STATUS_SUCCESS, NULL, NULL);
NfcCxSequenceDispatchResume(RFInterface, RFInterface->CurrentSequence, STATUS_SUCCESS, NULL, NULL);
}
else
{
@ -142,32 +142,31 @@ NfcCxLLCPInterfaceLinkStatusCB(
NTSTATUS
NfcCxLLCPInterfaceCheck(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
{
NFCSTATUS nfcStatus = NFCSTATUS_SUCCESS;
PNFCCX_LLCP_INTERFACE LLCPInterface = NfcCxRFInterfaceGetLLCPInterface(RFInterface);
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
LLCPInterface->eRequestState = NFCCX_LLCP_REQUEST_PENDING;
nfcStatus = phLibNfc_Llcp_CheckLlcp(RFInterface->pLibNfcContext->pRemDevList[0].hTargetDev,
NFCSTATUS nfcStatus = phLibNfc_Llcp_CheckLlcp(RFInterface->pLibNfcContext->pRemDevList[0].hTargetDev,
NfcCxLLCPInterfaceCheckCB,
NfcCxLLCPInterfaceLinkStatusCB,
(VOID *)LLCPInterface);
NTSTATUS status;
if (LLCPInterface->eRequestState == NFCCX_LLCP_REQUEST_COMPLETE) {
Status = STATUS_PENDING;
status = STATUS_PENDING;
}
else {
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
status = NfcCxNtStatusFromNfcStatus(nfcStatus);
}
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
static VOID
@ -177,11 +176,11 @@ NfcCxLLCPInterfaceConfigureCB(
)
{
NTSTATUS status = NfcCxNtStatusFromNfcStatus(NfcStatus);
PNFCCX_LLCP_INTERFACE LLCPInterface = ((PNFCCX_LLCP_LIBNFC_REQUEST_CONTEXT)pContext)->LLCPInterface;
auto sequence = reinterpret_cast<NFCCX_CX_SEQUENCE*>(pContext);
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
NfcCxInternalSequence(NfcCxLLCPInterfaceGetRFInterface(LLCPInterface), NfcCxLLCPInterfaceGetRFInterface(LLCPInterface)->pSeqHandler, status, NULL, NULL);
NfcCxSequenceDispatchResume(sequence->RFInterface, sequence, status, NULL, NULL);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
}
@ -189,7 +188,6 @@ NfcCxLLCPInterfaceConfigureCB(
NTSTATUS
NfcCxLLCPInterfaceConfigure(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
@ -197,7 +195,6 @@ NfcCxLLCPInterfaceConfigure(
NFCSTATUS nfcStatus = NFCSTATUS_SUCCESS;
PNFCCX_LLCP_INTERFACE LLCPInterface = NfcCxRFInterfaceGetLLCPInterface(RFInterface);
uint8_t ServiceName[] = "NFC Application";
static NFCCX_LLCP_LIBNFC_REQUEST_CONTEXT LibNfcContext;
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
@ -209,23 +206,19 @@ NfcCxLLCPInterfaceConfigure(
LLCPInterface->sLocalLinkInfo.wks = PHFRINFC_LLCP_WKS_DEFAULT;
LLCPInterface->sLocalLinkInfo.option = PHFRINFC_LLCP_OPTION_DEFAULT;
LibNfcContext.LLCPInterface = LLCPInterface;
LibNfcContext.Sequence = RFInterface->pSeqHandler;
nfcStatus = phLibNfc_Mgt_SetLlcp_ConfigParams(&LLCPInterface->sLocalLinkInfo,
NfcCxLLCPInterfaceConfigureCB,
&LibNfcContext);
RFInterface->CurrentSequence);
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
NTSTATUS status = NfcCxNtStatusFromNfcStatus(nfcStatus);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
NTSTATUS
NfcCxLLCPInterfaceActivate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
@ -235,16 +228,15 @@ NfcCxLLCPInterfaceActivate(
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
nfcStatus = phLibNfc_Llcp_Activate(RFInterface->pLibNfcContext->pRemDevList[0].hTargetDev);
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
NTSTATUS status = NfcCxNtStatusFromNfcStatus(nfcStatus);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
NTSTATUS
NfcCxLLCPInterfaceDeactivate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
@ -262,8 +254,8 @@ NfcCxLLCPInterfaceDeactivate(
}
}
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
NTSTATUS status = NfcCxNtStatusFromNfcStatus(nfcStatus);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}

Просмотреть файл

@ -46,11 +46,6 @@ typedef struct _NFCCX_LLCP_INTERFACE {
bool IsDeactivatePending;
} NFCCX_LLCP_INTERFACE, *PNFCCX_LLCP_INTERFACE;
typedef struct _NFCCX_LLCP_LIBNFC_REQUEST_CONTEXT {
PNFCCX_LLCP_INTERFACE LLCPInterface;
PNFCCX_CX_SEQUENCE Sequence;
} NFCCX_LLCP_LIBNFC_REQUEST_CONTEXT, *PNFCCX_LLCP_LIBNFC_REQUEST_CONTEXT;
NTSTATUS
NfcCxLLCPInterfaceCreate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
@ -65,18 +60,16 @@ NfcCxLLCPInterfaceDestroy(
NTSTATUS
NfcCxLLCPInterfaceConfigure(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);
#define LLCP_INTERFACE_CONFIG_SEQUENCE \
{ NfcCxLLCPInterfaceConfigure, NULL },
NFCCX_CX_SEQUENCE_ENTRY(NfcCxLLCPInterfaceConfigure)
NTSTATUS
NfcCxLLCPInterfaceCheck(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);
@ -87,7 +80,6 @@ NfcCxLLCPInterfaceCheck(
NTSTATUS
NfcCxLLCPInterfaceActivate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);
@ -98,7 +90,6 @@ NfcCxLLCPInterfaceActivate(
NTSTATUS
NfcCxLLCPInterfaceDeactivate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -35,7 +35,7 @@ enum NFCCX_LIBNFC_MESSAGE : UINT32
{
LIBNFC_STATE_PROCESS_NEXT_QUEUED_EVENT,
LIBNFC_STATE_CHAIN_EVENT,
LIBNFC_SEQUENCE_HANDLER,
LIBNFC_SEQUENCE_RESUME,
LIBNFC_MESSAGE_MAX,
};
@ -109,12 +109,13 @@ typedef struct _NFCCX_RF_INTERFACE {
WDFWAITLOCK DeviceLock;
//
// Sequence related
// Sequence handler
//
NFCCX_CX_SEQUENCE* CurrentSequence;
//
// Client driver sequence handlers
//
PNFCCX_CX_SEQUENCE pSeqHandler;
BOOLEAN bSeqHandler;
UCHAR SeqNext;
UCHAR SeqMax;
_Guarded_by_(SequenceLock)
PFN_NFC_CX_SEQUENCE_HANDLER SeqHandlers[SequenceMaximum];
WDFWAITLOCK SequenceLock;
@ -194,11 +195,6 @@ typedef struct _NFCCX_RF_INTERFACE {
} NFCCX_RF_INTERFACE, *PNFCCX_RF_INTERFACE;
typedef struct _NFCCX_RF_LIBNFC_REQUEST_CONTEXT {
PNFCCX_RF_INTERFACE RFInterface;
PNFCCX_CX_SEQUENCE Sequence;
} NFCCX_RF_LIBNFC_REQUEST_CONTEXT, *PNFCCX_RF_LIBNFC_REQUEST_CONTEXT;
//
// Helpers
//
@ -543,31 +539,40 @@ FN_NFCCX_CX_SEQUENCE_ENTRY NfcCxRFInterfaceESEResetSeq;
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRfDiscoveryStop) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePostRfDiscoveryStop)
#define RF_INTERFACE_REMOTEDEV_NTF_REGISTER_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevNtfRegister)
#define RF_INTERFACE_REMOTEDEV_CONNECT_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevConnect)
#define RF_INTERFACE_REMOTEDEV_NTF_REGISTER_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevNtfRegister)
#define RF_INTERFACE_REMOTEDEV_CONNECT_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevConnect)
#define RF_INTERFACE_REMOTEDEV_DISCONNECT_STOP_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePreRfDiscoveryStop) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevDisconnect) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePostRfDiscoveryStop)
#define RF_INTERFACE_REMOTEDEV_DISCONNECT_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevDisconnect)
#define RF_INTERFACE_REMOTEDEV_DISCONNECT_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceRemoteDevDisconnect)
#define RF_INTERFACE_TAG_READ_NDEF_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagCheckNdef) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagReadNdef)
#define RF_INTERFACE_TAG_READ_BARCODE_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagReadBarcode)
#define RF_INTERFACE_TAG_READ_BARCODE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagReadBarcode)
#define RF_INTERFACE_TAG_WRITE_NDEF_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagFormatNdef) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagCheckNdef) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagWriteNdef)
#define RF_INTERFACE_TAG_CONVERT_READONLY_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagConvertReadOnly)
#define RF_INTERFACE_TAG_CONVERT_READONLY_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTagConvertReadOnly)
#define RF_INTERFACE_TARGET_TRANSCEIVE_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTargetTransceive)
#define RF_INTERFACE_TARGET_PRESENCE_CHECK_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTargetPresenceCheck)
#define RF_INTERFACE_TARGET_TRANSCEIVE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTargetTransceive)
#define RF_INTERFACE_TARGET_PRESENCE_CHECK_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceTargetPresenceCheck)
#define RF_INTERFACE_EMBEDDEDSE_TRANSCEIVE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceESETransceiveSeq)
@ -575,7 +580,8 @@ FN_NFCCX_CX_SEQUENCE_ENTRY NfcCxRFInterfaceESEResetSeq;
#define RF_INTERFACE_EMBEDDEDSE_RESET_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceESEResetSeq)
#define RF_INTERFACE_SE_NTF_REGISTER_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceSENtfRegister)
#define RF_INTERFACE_SE_NTF_REGISTER_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceSENtfRegister)
#define RF_INTERFACE_SE_ENUMERATE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePreSEEnumerate) \
@ -583,13 +589,18 @@ FN_NFCCX_CX_SEQUENCE_ENTRY NfcCxRFInterfaceESEResetSeq;
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePostSEEnumerate) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceSetDefaultRoutingTable)
#define RF_INTERFACE_SE_DISABLE_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceDisableSecureElements)
#define RF_INTERFACE_SE_DISABLE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceDisableSecureElements)
#define RF_INTERFACE_SE_SET_MODE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceSESetPowerAndLinkControl) \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceSESetModeConfig) \
#define RF_INTERFACE_SE_SET_ROUTING_MODE_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceConfigureRoutingTable)
#define RF_INTERFACE_SE_SET_ROUTING_MODE_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfaceConfigureRoutingTable)
#define RF_INTERFACE_PRE_RECOVERY_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePreRecovery)
#define RF_INTERFACE_POST_RECOVERY_SEQUENCE NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePostRecovery)
#define RF_INTERFACE_PRE_RECOVERY_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePreRecovery)
#define RF_INTERFACE_POST_RECOVERY_SEQUENCE \
NFCCX_CX_SEQUENCE_ENTRY(NfcCxRFInterfacePostRecovery)

Просмотреть файл

@ -8,7 +8,7 @@ Module Name:
Abstract:
SNEP Interface implementation
SNEP interface implementation
Environment:
@ -237,7 +237,8 @@ NfcCxSNEPInterfaceClientConnCB(
)
{
NTSTATUS status = STATUS_SUCCESS;
PNFCCX_SNEP_INTERFACE snepInterface = ((PNFCCX_SNEP_LIBNFC_REQUEST_CONTEXT)pContext)->SNEPInterface;
auto sequence = reinterpret_cast<NFCCX_CX_SEQUENCE*>(pContext);
PNFCCX_SNEP_INTERFACE snepInterface = NfcCxRFInterfaceGetSNEPInterface(sequence->RFInterface);
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
@ -252,7 +253,7 @@ NfcCxSNEPInterfaceClientConnCB(
status = STATUS_UNSUCCESSFUL;
}
NfcCxInternalSequence(NfcCxSNEPInterfaceGetRFInterface(snepInterface), ((PNFCCX_SNEP_LIBNFC_REQUEST_CONTEXT)pContext)->Sequence, status, NULL, NULL);
NfcCxSequenceDispatchResume(sequence->RFInterface, sequence, status, NULL, NULL);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
}
@ -260,29 +261,23 @@ NfcCxSNEPInterfaceClientConnCB(
NTSTATUS
NfcCxSNEPInterfaceClientConnect(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
{
NFCSTATUS nfcStatus = NFCSTATUS_SUCCESS;
PNFCCX_SNEP_INTERFACE snepInterface = NfcCxRFInterfaceGetSNEPInterface(RFInterface);
static NFCCX_SNEP_LIBNFC_REQUEST_CONTEXT LibNfcContext;
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
LibNfcContext.SNEPInterface = snepInterface;
LibNfcContext.Sequence = RFInterface->pSeqHandler;
nfcStatus = phLibNfc_SnepClient_Init(&snepInterface->sConfigInfo,
NFCSTATUS nfcStatus = phLibNfc_SnepClient_Init(&snepInterface->sConfigInfo,
RFInterface->pLibNfcContext->pRemDevList[0].hTargetDev,
NfcCxSNEPInterfaceClientConnCB,
&LibNfcContext);
RFInterface->CurrentSequence);
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
NTSTATUS status = NfcCxNtStatusFromNfcStatus(nfcStatus);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
static VOID
@ -294,7 +289,7 @@ NfcCxSNEPInterfaceClientPutReqCB(
)
{
NTSTATUS status = STATUS_SUCCESS;
PNFCCX_SNEP_INTERFACE snepInterface = ((PNFCCX_SNEP_LIBNFC_REQUEST_CONTEXT)pContext)->SNEPInterface;
auto sequence = reinterpret_cast<NFCCX_CX_SEQUENCE*>(pContext);
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
@ -302,7 +297,7 @@ NfcCxSNEPInterfaceClientPutReqCB(
UNREFERENCED_PARAMETER(ConnHandle);
status = NfcCxNtStatusFromNfcStatus(NfcStatus);
NfcCxInternalSequence(NfcCxSNEPInterfaceGetRFInterface(snepInterface), ((PNFCCX_SNEP_LIBNFC_REQUEST_CONTEXT)pContext)->Sequence, status, NULL, NULL);
NfcCxSequenceDispatchResume(sequence->RFInterface, sequence, status, NULL, NULL);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
}
@ -310,27 +305,21 @@ NfcCxSNEPInterfaceClientPutReqCB(
NTSTATUS
NfcCxSNEPInterfaceClientPut(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* /*Param1*/,
_In_opt_ VOID* /*Param2*/
)
{
NFCSTATUS nfcStatus = NFCSTATUS_SUCCESS;
PNFCCX_SNEP_INTERFACE snepInterface = NfcCxRFInterfaceGetSNEPInterface(RFInterface);
static NFCCX_SNEP_LIBNFC_REQUEST_CONTEXT LibNfcContext;
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
LibNfcContext.SNEPInterface = snepInterface;
LibNfcContext.Sequence = RFInterface->pSeqHandler;
nfcStatus = phLibNfc_SnepProtocolCliReqPut(snepInterface->pClientHandleDef,
NFCSTATUS nfcStatus = phLibNfc_SnepProtocolCliReqPut(snepInterface->pClientHandleDef,
&snepInterface->sSendDataBuff,
NfcCxSNEPInterfaceClientPutReqCB,
&LibNfcContext);
RFInterface->CurrentSequence);
Status = NfcCxNtStatusFromNfcStatus(nfcStatus);
NTSTATUS status = NfcCxNtStatusFromNfcStatus(nfcStatus);
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status);
return Status;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}

Просмотреть файл

@ -8,8 +8,11 @@ Module Name:
Abstract:
SNEP Interface declarations
SNEP interface declarations
SNEP (Simple NDEF Exchange Protocol) implements NDEF publications and subscriptions over
NFC peer-to-peer (P2P) connections.
Environment:
User-mode Driver Framework
@ -28,11 +31,6 @@ typedef struct _NFCCX_SNEP_INTERFACE {
phLibNfc_Data_t sSendDataBuff;
} NFCCX_SNEP_INTERFACE, *PNFCCX_SNEP_INTERFACE;
typedef struct _NFCCX_SNEP_LIBNFC_REQUEST_CONTEXT {
PNFCCX_SNEP_INTERFACE SNEPInterface;
PNFCCX_CX_SEQUENCE Sequence;
} NFCCX_SNEP_LIBNFC_REQUEST_CONTEXT, *PNFCCX_SNEP_LIBNFC_REQUEST_CONTEXT;
NTSTATUS
NfcCxSNEPInterfaceCreate(
_In_ PNFCCX_RF_INTERFACE RFInterface,
@ -57,7 +55,6 @@ NfcCxSNEPInterfaceDeinit(
NTSTATUS
NfcCxSNEPInterfaceClientConnect(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);
@ -68,7 +65,6 @@ NfcCxSNEPInterfaceClientConnect(
NTSTATUS
NfcCxSNEPInterfaceClientPut(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
);

Просмотреть файл

@ -16,25 +16,35 @@ Abstract:
#include "NFcCxSequence.tmh"
NTSTATUS
NfcCxSequenceHandler(
static NTSTATUS
NfcCxSequenceRun(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
NTSTATUS
NfcCxSequenceStart(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_reads_(SequenceStepsSize) const PFN_NFCCX_CX_SEQUENCE_ENTRY* SequenceSteps,
_In_ UCHAR SequenceStepsSize,
_In_ PFN_NFCCX_CX_SEQUENCE_EXIT SequenceCompleteStep,
_In_opt_ void* Param1,
_In_opt_ void* Param2
)
/*++
Routine Description:
This routine for initiating and processing sequences
This routine for initiating sequences.
Arguments:
RFInterface - A pointer to the RF interface
Sequence - A pointer to sequence
Status - The status of the sequence
SequenceSteps - A pointer to a sequence handler list
SequenceStepsSize - The size of the sequence handler list
SequenceCompleteStep - The handler called when the sequence has completed
Param - The parameters for the sequence
Return Value:
@ -45,91 +55,209 @@ Return Value:
{
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
if (RFInterface->pSeqHandler != Sequence) {
TRACE_LINE(LEVEL_WARNING, "Sequence mismatch");
Status = STATUS_INVALID_PARAMETER;
}
else if (!RFInterface->bSeqHandler) {
NT_ASSERT(RFInterface->SeqMax > 0);
RFInterface->bSeqHandler = TRUE;
NTSTATUS status = STATUS_SUCCESS;
if ((STATUS_SUCCESS == Status) && (NULL != RFInterface->pSeqHandler)) {
if (RFInterface->SeqNext <= RFInterface->SeqMax) {
if (0 == RFInterface->SeqNext) {
if (NULL != RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate) {
Status = RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate(RFInterface, Status, Param1, Param2);
}
while ((STATUS_SUCCESS == Status) && (RFInterface->SeqMax > RFInterface->SeqNext)) {
RFInterface->SeqNext++;
if (NULL != RFInterface->pSeqHandler[RFInterface->SeqNext-1].SequenceProcess) {
Status = RFInterface->pSeqHandler[RFInterface->SeqNext-1].SequenceProcess(RFInterface, Status, Param1, Param2);
}
if ((STATUS_SUCCESS == Status) && (NULL != RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate)) {
Status = RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate(RFInterface, Status, Param1, Param2);
}
}
}
else {
while ((STATUS_SUCCESS == Status) && (RFInterface->SeqMax > RFInterface->SeqNext)) {
if (NULL != RFInterface->pSeqHandler[RFInterface->SeqNext-1].SequenceProcess) {
Status = RFInterface->pSeqHandler[RFInterface->SeqNext-1].SequenceProcess(RFInterface, Status, Param1, Param2);
}
if ((STATUS_SUCCESS == Status) && (NULL != RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate)) {
Status = RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceInitiate(RFInterface, Status, Param1, Param2);
}
RFInterface->SeqNext = (STATUS_SUCCESS == Status) ? RFInterface->SeqNext+1 : RFInterface->SeqNext;
}
}
}
}
else {
RFInterface->SeqNext = RFInterface->SeqMax;
// Check if there is an existing sequence.
if (RFInterface->CurrentSequence)
{
// Check if the sequence handling is being called recursively.
if (RFInterface->CurrentSequence->IsSequenceRunning)
{
status = STATUS_INVALID_DEVICE_STATE;
TRACE_LINE(LEVEL_ERROR, "Failed to start a new sequence. An existing sequence is currently executing. %!STATUS!", status);
goto Done;
}
if ((STATUS_SUCCESS != Status) && (STATUS_PENDING != Status)) {
RFInterface->SeqNext = RFInterface->SeqMax;
}
TRACE_LINE(LEVEL_WARNING, "WARNING: Overriding existing sequence.");
if (RFInterface->SeqNext == RFInterface->SeqMax) {
if (NULL != RFInterface->pSeqHandler &&
NULL != RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceProcess) {
RFInterface->pSeqHandler[RFInterface->SeqNext].SequenceProcess(RFInterface, Status, Param1, Param2);
}
}
else {
RFInterface->SeqNext++;
}
RFInterface->bSeqHandler = FALSE;
}
else {
TRACE_LINE(LEVEL_INFO, "Sequence handling in progress");
NfcCxPostLibNfcThreadMessage(RFInterface, LIBNFC_SEQUENCE_HANDLER, (UINT_PTR)Sequence, (UINT_PTR)Status, (UINT_PTR)Param1, (UINT_PTR)Param2);
Status = STATUS_PENDING;
// Cleanup existing sequence.
NFCCX_CX_SEQUENCE* existingSequence = RFInterface->CurrentSequence;
RFInterface->CurrentSequence = nullptr;
delete existingSequence;
}
TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);
return Status;
// Allocate the data context for the sequence.
auto sequence = new NFCCX_CX_SEQUENCE{ RFInterface, SequenceSteps, 0, SequenceStepsSize, SequenceCompleteStep, false };
if (!sequence)
{
status = STATUS_INSUFFICIENT_RESOURCES;
TRACE_LINE(LEVEL_ERROR, "Failed to allocate NFCCX_CX_SEQUENCE. %!STATUS!", status);
goto Done;
}
// Set the sequence.
RFInterface->CurrentSequence = sequence;
// Run the first handler within the sequence.
NTSTATUS sequenceStatus = NfcCxSequenceRun(RFInterface, sequence, Param1, Param2);
if (sequenceStatus != STATUS_PENDING)
{
// The sequence handler completed synchronously (success or failure).
TRACE_LINE(LEVEL_INFO, "Sequence handler completed synchronously. Deferring complete function. %!STATUS!", sequenceStatus);
// Ensure that the complete function is called when the sequence is next resumed.
sequence->SequenceStepsNext = sequence->SequenceStepsSize;
// Queue the sequence handler.
NfcCxSequenceDispatchResume(RFInterface, sequence, sequenceStatus, Param1, Param2);
goto Done;
}
// Sequence will complete asynchronously.
status = STATUS_PENDING;
Done:
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
VOID
NfcCxInternalSequence(
void
NfcCxSequenceResume(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ NTSTATUS SequenceStatus,
_In_opt_ void* Param1,
_In_opt_ void* Param2
)
/*++
Routine Description:
This routine is invoked by completing the sequence
Resumes a sequence that was suspended. This is usually called when an asynchronous operation has completed.
Arguments:
RFInterface - A pointer to the RF interface
Sequence - A pointer to sequence
SequenceStatus - The status of the sequence
Param - The parameters for the sequence
Return Value:
void
--*/
{
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
if (RFInterface->CurrentSequence != Sequence)
{
TRACE_LINE(LEVEL_WARNING, "Sequence mismatch.");
goto Done;
}
if (!Sequence)
{
TRACE_LINE(LEVEL_WARNING, "Empty sequence.");
goto Done;
}
// Check if the sequence handling is being called recursively.
if (Sequence->IsSequenceRunning)
{
TRACE_LINE(LEVEL_INFO, "Sequence handling already in progress. Deferring.");
NfcCxSequenceDispatchResume(RFInterface, Sequence, SequenceStatus, Param1, Param2);
goto Done;
}
if (SequenceStatus == STATUS_PENDING)
{
SequenceStatus = STATUS_CANCELLED;
TRACE_LINE(LEVEL_WARNING, "Sequence result has an unexpected value of STATUS_PENDING. Converting to STATUS_CANCELLED.");
}
if (SequenceStatus == STATUS_SUCCESS)
{
// Call the next sequence handler.
SequenceStatus = NfcCxSequenceRun(RFInterface, Sequence, Param1, Param2);
}
if (SequenceStatus != STATUS_PENDING)
{
// The sequence has completed (success or failure).
// Allow another sequence to start during the complete handler.
RFInterface->CurrentSequence = nullptr;
// Call the complete handler.
Sequence->SequenceCompleteStep(RFInterface, SequenceStatus, Param1, Param2);
// Cleanup sequence's memory.
delete Sequence;
}
Done:
TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);
}
static NTSTATUS
NfcCxSequenceRun(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_opt_ void* Param1,
_In_opt_ void* Param2
)
/*++
Routine Description:
Processes the next handler in the sequence
Arguments:
RFInterface - A pointer to the RF interface
Sequence - A pointer to sequence
SequenceStatus - The status of the sequence
Param - The parameters for the sequence
Return Value:
NTSTATUS
--*/
{
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
NTSTATUS status = STATUS_SUCCESS;
Sequence->IsSequenceRunning = true;
while (Sequence->SequenceStepsNext < Sequence->SequenceStepsSize)
{
// Invoke the next sequence handler.
PFN_NFCCX_CX_SEQUENCE_ENTRY handler = Sequence->SequenceSteps[Sequence->SequenceStepsNext];
Sequence->SequenceStepsNext++;
status = handler(RFInterface, Param1, Param2);
if (status == STATUS_SUCCESS)
{
// The sequence handler completed its work synchronously. Continue on to the next handler.
continue;
}
// Either an error occured or an asynchronous operation is pending.
break;
}
Sequence->IsSequenceRunning = false;
TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
return status;
}
void
NfcCxSequenceDispatchResume(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ NTSTATUS Status,
_In_opt_ void* Param1,
_In_opt_ void* Param2
)
/*++
Routine Description:
Queues a message on the LibNfc thread that will call NfcCxSequenceResume. This helps prevent reentrancy issues.
Arguments:
@ -144,48 +272,13 @@ Return Value:
--*/
{
NfcCxPostLibNfcThreadMessage(RFInterface, LIBNFC_SEQUENCE_HANDLER, (UINT_PTR)Sequence, (UINT_PTR)Status, (UINT_PTR)Param1, (UINT_PTR)Param2);
}
UCHAR
NfcCxGetSequenceLength(
PCNFCCX_CX_SEQUENCE Sequence
)
/*++
Routine Description:
This routine is used to calculate the length of the sequence
Arguments:
Sequence - A pointer to sequence
Return Value:
The length of the sequence
--*/
{
UCHAR length = 0;
if (Sequence == NULL) {
goto Done;
}
while (NULL != Sequence->SequenceInitiate) {
length++;
Sequence++;
}
Done:
return length;
NfcCxPostLibNfcThreadMessage(RFInterface, LIBNFC_SEQUENCE_RESUME, (UINT_PTR)Sequence, (UINT_PTR)Status, (UINT_PTR)Param1, (UINT_PTR)Param2);
}
NTSTATUS
NfcCxSkipSequence(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ UCHAR Value
)
/*++
@ -206,31 +299,25 @@ Return Value:
--*/
{
NTSTATUS status = STATUS_SUCCESS;
NT_ASSERT(RFInterface);
NT_ASSERT(Sequence);
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
if (0 == Value) {
NTSTATUS status = STATUS_SUCCESS;
if (RFInterface->CurrentSequence != Sequence)
{
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Sequence mismatch. %!STATUS!", status);
goto Done;
}
if (Sequence != RFInterface->pSeqHandler) {
if (Sequence->SequenceStepsNext + Value > Sequence->SequenceStepsSize)
{
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Sequence mismatch, can not decrement the current sequence");
TRACE_LINE(LEVEL_ERROR, "Value to increment is invalid. %!STATUS!", status);
goto Done;
}
if ((RFInterface->SeqNext + Value) > RFInterface->SeqMax) {
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Value to increment is invalid");
goto Done;
}
RFInterface->SeqNext += Value;
Sequence->SequenceStepsNext += Value;
Done:
TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);
@ -240,7 +327,7 @@ Done:
NTSTATUS
NfcCxRepeatSequence(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ UCHAR Value
)
/*++
@ -261,31 +348,25 @@ Return Value:
--*/
{
NTSTATUS status = STATUS_SUCCESS;
TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
NT_ASSERT(RFInterface);
NT_ASSERT(Sequence);
NTSTATUS status = STATUS_SUCCESS;
if (0 == Value) {
if (RFInterface->CurrentSequence != Sequence)
{
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Sequence mismatch. %!STATUS!", status);
goto Done;
}
if (Sequence != RFInterface->pSeqHandler) {
if (Sequence->SequenceStepsNext < Value)
{
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Sequence mismatch, can not decrement the current sequence");
TRACE_LINE(LEVEL_ERROR, "Value to decrement is invalid. %!STATUS!", status);
goto Done;
}
if (RFInterface->SeqNext < Value) {
status = STATUS_INVALID_PARAMETER;
TRACE_LINE(LEVEL_ERROR, "Value to decrement is invalid");
goto Done;
}
RFInterface->SeqNext -= Value;
Sequence->SequenceStepsNext -= Value;
Done:
TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);

Просмотреть файл

@ -18,79 +18,87 @@ typedef
NTSTATUS
(FN_NFCCX_CX_SEQUENCE_ENTRY)(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
typedef
NTSTATUS
void
(FN_NFCCX_CX_SEQUENCE_EXIT)(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
typedef FN_NFCCX_CX_SEQUENCE_ENTRY *PFN_NFCCX_CX_SEQUENCE_ENTRY;
typedef FN_NFCCX_CX_SEQUENCE_EXIT *PFN_NFCCX_CX_SEQUENCE_EXIT;
typedef FN_NFCCX_CX_SEQUENCE_ENTRY* PFN_NFCCX_CX_SEQUENCE_ENTRY;
typedef FN_NFCCX_CX_SEQUENCE_EXIT* PFN_NFCCX_CX_SEQUENCE_EXIT;
typedef struct _NFCCX_CX_SEQUENCE {
PFN_NFCCX_CX_SEQUENCE_ENTRY SequenceInitiate;
PFN_NFCCX_CX_SEQUENCE_EXIT SequenceProcess;
} NFCCX_CX_SEQUENCE, *PNFCCX_CX_SEQUENCE;
#define NFCCX_CX_BEGIN_SEQUENCE_MAP(Sequence) static constexpr PFN_NFCCX_CX_SEQUENCE_ENTRY Sequence[] = {
#define NFCCX_CX_SEQUENCE_ENTRY(SequenceInitiate) SequenceInitiate,
#define NFCCX_CX_END_SEQUENCE_MAP() };
typedef const NFCCX_CX_SEQUENCE* PCNFCCX_CX_SEQUENCE;
#define NFCCX_CX_BEGIN_SEQUENCE_MAP(Sequence) static NFCCX_CX_SEQUENCE Sequence[] = {
#define NFCCX_CX_SEQUENCE_ENTRY(SequenceInitiate) { SequenceInitiate, NULL },
#define NFCCX_CX_END_SEQUENCE_MAP() { NULL, NULL } };
typedef struct _NFCCX_CX_SEQUENCE_REQUEST {
PNFCCX_RF_INTERFACE RFInterface;
NTSTATUS Status;
VOID* Param1;
VOID* Param2;
} NFCCX_CX_SEQUENCE_REQUEST, *PNFCCX_CX_SEQUENCE_REQUEST;
struct NFCCX_CX_SEQUENCE
{
PNFCCX_RF_INTERFACE RFInterface;
const PFN_NFCCX_CX_SEQUENCE_ENTRY* SequenceSteps;
UCHAR SequenceStepsNext;
UCHAR SequenceStepsSize;
PFN_NFCCX_CX_SEQUENCE_EXIT SequenceCompleteStep;
bool IsSequenceRunning;
};
NTSTATUS
NfcCxSequenceHandler(
NfcCxSequenceStart(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_reads_(SequenceStepsSize) const PFN_NFCCX_CX_SEQUENCE_ENTRY* SequenceSteps,
_In_ UCHAR SequenceStepsSize,
_In_ PFN_NFCCX_CX_SEQUENCE_EXIT SequenceCompleteStep,
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
VOID
NfcCxInternalSequence(
template <UCHAR SequenceStepsSize>
NTSTATUS
NfcCxSequenceStart(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NTSTATUS Status,
_In_opt_ VOID* Param1,
_In_opt_ VOID* Param2
_In_ const PFN_NFCCX_CX_SEQUENCE_ENTRY (&SequenceSteps)[SequenceStepsSize],
_In_ PFN_NFCCX_CX_SEQUENCE_EXIT SeqComplete,
_In_opt_ void* Param1,
_In_opt_ void* Param2
)
{
return NfcCxSequenceStart(RFInterface, SequenceSteps, SequenceStepsSize, SeqComplete, Param1, Param2);
}
void
NfcCxSequenceResume(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ NTSTATUS SequenceStatus,
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
UCHAR
NfcCxGetSequenceLength(
PCNFCCX_CX_SEQUENCE Sequence
void
NfcCxSequenceDispatchResume(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ NTSTATUS Status,
_In_opt_ void* Param1,
_In_opt_ void* Param2
);
NTSTATUS
NfcCxSkipSequence(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ UCHAR Value
);
NTSTATUS
NfcCxRepeatSequence(
_In_ PNFCCX_RF_INTERFACE RFInterface,
_In_ PNFCCX_CX_SEQUENCE Sequence,
_In_ NFCCX_CX_SEQUENCE* Sequence,
_In_ UCHAR Value
);
#define NFCCX_INIT_SEQUENCE(RFInterface, Sequence) \
(RFInterface)->pSeqHandler = (Sequence); \
(RFInterface)->SeqNext = 0; \
(RFInterface)->SeqMax = NfcCxGetSequenceLength((Sequence))