mirror of
https://gitlab.com/fabinfra/fabhardware/FabReader2.git
synced 2025-03-13 07:01:53 +01:00
589 lines
17 KiB
C
589 lines
17 KiB
C
/******************************************************************************
|
|
* \attention
|
|
*
|
|
* <h2><center>© COPYRIGHT 2019 STMicroelectronics</center></h2>
|
|
*
|
|
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
|
|
* You may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* www.st.com/myliberty
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
|
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* PROJECT: NDEF firmware
|
|
* Revision:
|
|
* LANGUAGE: ISO C99
|
|
*/
|
|
|
|
/*! \file
|
|
*
|
|
* \author
|
|
*
|
|
* \brief Provides NDEF methods and definitions to access NFC Forum Tags
|
|
*
|
|
* This module provides an interface to handle NDEF message
|
|
*
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* INCLUDES
|
|
******************************************************************************
|
|
*/
|
|
#include "ndef_poller.h"
|
|
#include "ndef_t2t.h"
|
|
#include "ndef_t3t.h"
|
|
#include "ndef_t4t.h"
|
|
#include "ndef_t5t.h"
|
|
#include "utils.h"
|
|
|
|
/*
|
|
******************************************************************************
|
|
* ENABLE SWITCH
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL DEFINES
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL TYPES
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL MACROS
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* LOCAL VARIABLES
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
******************************************************************************
|
|
*/
|
|
|
|
static ndefDeviceType ndefPollerGetDeviceType(const rfalNfcDevice *dev);
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL VARIABLE DEFINITIONS
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerContextInitialization(ndefContext *ctx, const rfalNfcDevice *dev)
|
|
{
|
|
#if RFAL_FEATURE_T1T
|
|
static const ndefPollerWrapper ndefT1TWrapper =
|
|
{
|
|
NULL, /* ndefT1TPollerContextInitialization, */
|
|
NULL, /* ndefT1TPollerNdefDetect, */
|
|
NULL, /* ndefT1TPollerReadBytes, */
|
|
NULL, /* ndefT1TPollerReadRawMessage, */
|
|
#if NDEF_FEATURE_ALL
|
|
NULL, /* ndefT1TPollerWriteBytes, */
|
|
NULL, /* ndefT1TPollerWriteRawMessage, */
|
|
NULL, /* ndefT1TPollerTagFormat, */
|
|
NULL, /* ndefT1TPollerWriteRawMessageLen */
|
|
NULL, /* ndefT1TPollerCheckPresence */
|
|
NULL, /* ndefT1TPollerCheckAvailableSpace */
|
|
NULL, /* ndefT1TPollerBeginWriteMessage */
|
|
NULL /* ndefT1TPollerEndWriteMessage */
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
};
|
|
#endif /* RFAL_FEATURE_T1T */
|
|
|
|
#if RFAL_FEATURE_T2T
|
|
static const ndefPollerWrapper ndefT2TWrapper =
|
|
{
|
|
ndefT2TPollerContextInitialization,
|
|
ndefT2TPollerNdefDetect,
|
|
ndefT2TPollerReadBytes,
|
|
ndefT2TPollerReadRawMessage,
|
|
#if NDEF_FEATURE_ALL
|
|
ndefT2TPollerWriteBytes,
|
|
ndefT2TPollerWriteRawMessage,
|
|
ndefT2TPollerTagFormat,
|
|
ndefT2TPollerWriteRawMessageLen,
|
|
ndefT2TPollerCheckPresence,
|
|
ndefT2TPollerCheckAvailableSpace,
|
|
ndefT2TPollerBeginWriteMessage,
|
|
ndefT2TPollerEndWriteMessage
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
};
|
|
#endif /* RFAL_FEATURE_T2T */
|
|
|
|
#if RFAL_FEATURE_NFCF
|
|
static const ndefPollerWrapper ndefT3TWrapper =
|
|
{
|
|
ndefT3TPollerContextInitialization,
|
|
ndefT3TPollerNdefDetect,
|
|
ndefT3TPollerReadBytes,
|
|
ndefT3TPollerReadRawMessage,
|
|
#if NDEF_FEATURE_ALL
|
|
ndefT3TPollerWriteBytes,
|
|
ndefT3TPollerWriteRawMessage,
|
|
ndefT3TPollerTagFormat,
|
|
ndefT3TPollerWriteRawMessageLen,
|
|
ndefT3TPollerCheckPresence,
|
|
ndefT3TPollerCheckAvailableSpace,
|
|
ndefT3TPollerBeginWriteMessage,
|
|
ndefT3TPollerEndWriteMessage
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
};
|
|
#endif /* RFAL_FEATURE_NFCF */
|
|
|
|
#if RFAL_FEATURE_T4T
|
|
static const ndefPollerWrapper ndefT4TWrapper =
|
|
{
|
|
ndefT4TPollerContextInitialization,
|
|
ndefT4TPollerNdefDetect,
|
|
ndefT4TPollerReadBytes,
|
|
ndefT4TPollerReadRawMessage,
|
|
#if NDEF_FEATURE_ALL
|
|
ndefT4TPollerWriteBytes,
|
|
ndefT4TPollerWriteRawMessage,
|
|
ndefT4TPollerTagFormat,
|
|
ndefT4TPollerWriteRawMessageLen,
|
|
ndefT4TPollerCheckPresence,
|
|
ndefT4TPollerCheckAvailableSpace,
|
|
ndefT4TPollerBeginWriteMessage,
|
|
ndefT4TPollerEndWriteMessage
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
};
|
|
#endif /* RFAL_FEATURE_T4T */
|
|
|
|
#if RFAL_FEATURE_NFCV
|
|
static const ndefPollerWrapper ndefT5TWrapper =
|
|
{
|
|
ndefT5TPollerContextInitialization,
|
|
ndefT5TPollerNdefDetect,
|
|
ndefT5TPollerReadBytes,
|
|
ndefT5TPollerReadRawMessage,
|
|
#if NDEF_FEATURE_ALL
|
|
ndefT5TPollerWriteBytes,
|
|
ndefT5TPollerWriteRawMessage,
|
|
ndefT5TPollerTagFormat,
|
|
ndefT5TPollerWriteRawMessageLen,
|
|
ndefT5TPollerCheckPresence,
|
|
ndefT5TPollerCheckAvailableSpace,
|
|
ndefT5TPollerBeginWriteMessage,
|
|
ndefT5TPollerEndWriteMessage
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
};
|
|
#endif /* RFAL_FEATURE_NFCV */
|
|
|
|
static const ndefPollerWrapper *ndefPollerWrappers[] =
|
|
{
|
|
NULL,
|
|
#if RFAL_FEATURE_T1T
|
|
&ndefT1TWrapper,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if RFAL_FEATURE_T2T
|
|
&ndefT2TWrapper,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if RFAL_FEATURE_NFCF
|
|
&ndefT3TWrapper,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if RFAL_FEATURE_T4T
|
|
&ndefT4TWrapper,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if RFAL_FEATURE_NFCV
|
|
&ndefT5TWrapper,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
};
|
|
|
|
if( (ctx == NULL) || (dev == NULL) )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
ctx->ndefPollWrapper = ndefPollerWrappers[ndefPollerGetDeviceType(dev)];
|
|
|
|
/* ndefPollWrapper is NULL when support of a given tag type is not enabled */
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_NOTSUPP;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerContextInitialization)(ctx, dev);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerNdefDetect(ndefContext *ctx, ndefInfo *info)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerNdefDetect)(ctx, info);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerReadRawMessage(ndefContext *ctx, uint8_t *buf, uint32_t bufLen, uint32_t *rcvdLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerReadRawMessage)(ctx, buf, bufLen, rcvdLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerReadBytes(ndefContext *ctx, uint32_t offset, uint32_t len, uint8_t *buf, uint32_t *rcvdLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerReadBytes)(ctx, offset, len, buf, rcvdLen);
|
|
}
|
|
|
|
#if NDEF_FEATURE_ALL
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerWriteRawMessage(ndefContext *ctx, const uint8_t *buf, uint32_t bufLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerWriteRawMessage)(ctx, buf, bufLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerTagFormat(ndefContext *ctx, const ndefCapabilityContainer *cc, uint32_t options)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerTagFormat)(ctx, cc, options);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerWriteRawMessageLen(ndefContext *ctx, uint32_t rawMessageLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerWriteRawMessageLen)(ctx, rawMessageLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerWriteBytes(ndefContext *ctx, uint32_t offset, const uint8_t *buf, uint32_t len)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerWriteBytes)(ctx, offset, buf, len);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerCheckPresence(ndefContext *ctx)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerCheckPresence)(ctx);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerCheckAvailableSpace(const ndefContext *ctx, uint32_t messageLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerCheckAvailableSpace)(ctx, messageLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerBeginWriteMessage(ndefContext *ctx, uint32_t messageLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerBeginWriteMessage)(ctx, messageLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerEndWriteMessage(ndefContext *ctx, uint32_t messageLen)
|
|
{
|
|
if( ctx == NULL )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if( ctx->ndefPollWrapper == NULL )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
return (ctx->ndefPollWrapper->pollerEndWriteMessage)(ctx, messageLen);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode ndefPollerWriteMessage(ndefContext *ctx, const ndefMessage* message)
|
|
{
|
|
ReturnCode err;
|
|
ndefMessageInfo info;
|
|
ndefRecord* record;
|
|
uint8_t recordHeaderBuf[NDEF_RECORD_HEADER_LEN];
|
|
ndefBuffer bufHeader;
|
|
ndefConstBuffer bufPayloadItem;
|
|
uint32_t offset;
|
|
bool firstPayloadItem;
|
|
|
|
if ( (ctx == NULL) || (message == NULL) )
|
|
{
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
if ( (ctx->state != NDEF_STATE_INITIALIZED) && (ctx->state != NDEF_STATE_READWRITE) )
|
|
{
|
|
return ERR_WRONG_STATE;
|
|
}
|
|
|
|
(void)ndefMessageGetInfo(message, &info);
|
|
|
|
/* Verify length of the NDEF message */
|
|
err = ndefPollerCheckAvailableSpace(ctx, info.length);
|
|
if (err != ERR_NONE)
|
|
{
|
|
/* Conclude procedure */
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
/* Reset L-Field/NLEN field */
|
|
err = ndefPollerBeginWriteMessage(ctx, info.length);
|
|
if (err != ERR_NONE)
|
|
{
|
|
ctx->state = NDEF_STATE_INVALID;
|
|
/* Conclude procedure */
|
|
return err;
|
|
}
|
|
|
|
if (info.length != 0U)
|
|
{
|
|
offset = ctx->messageOffset;
|
|
record = ndefMessageGetFirstRecord(message);
|
|
|
|
while (record != NULL)
|
|
{
|
|
bufHeader.buffer = recordHeaderBuf;
|
|
bufHeader.length = sizeof(recordHeaderBuf);
|
|
(void)ndefRecordEncodeHeader(record, &bufHeader);
|
|
err = ndefPollerWriteBytes(ctx, offset, bufHeader.buffer, bufHeader.length);
|
|
if (err != ERR_NONE)
|
|
{
|
|
return err;
|
|
}
|
|
offset += bufHeader.length;
|
|
// TODO Use API to access record internal
|
|
if (record->typeLength != 0U)
|
|
{
|
|
err = ndefPollerWriteBytes(ctx, offset, record->type, record->typeLength);
|
|
if (err != ERR_NONE)
|
|
{
|
|
/* Conclude procedure */
|
|
ctx->state = NDEF_STATE_INVALID;
|
|
return err;
|
|
}
|
|
offset += record->typeLength;
|
|
}
|
|
if (record->idLength != 0U)
|
|
{
|
|
err = ndefPollerWriteBytes(ctx, offset, record->id, record->idLength);
|
|
if (err != ERR_NONE)
|
|
{
|
|
/* Conclude procedure */
|
|
ctx->state = NDEF_STATE_INVALID;
|
|
return err;
|
|
}
|
|
offset += record->idLength;
|
|
}
|
|
if (ndefRecordGetPayloadLength(record) != 0U)
|
|
{
|
|
firstPayloadItem = true;
|
|
while (ndefRecordGetPayloadItem(record, &bufPayloadItem, firstPayloadItem) != NULL)
|
|
{
|
|
firstPayloadItem = false;
|
|
err = ndefPollerWriteBytes(ctx, offset, bufPayloadItem.buffer, bufPayloadItem.length);
|
|
if (err != ERR_NONE)
|
|
{
|
|
/* Conclude procedure */
|
|
ctx->state = NDEF_STATE_INVALID;
|
|
return err;
|
|
}
|
|
offset += bufPayloadItem.length;
|
|
}
|
|
}
|
|
record = ndefMessageGetNextRecord(record);
|
|
}
|
|
|
|
err = ndefPollerEndWriteMessage(ctx, info.length);
|
|
if (err != ERR_NONE)
|
|
{
|
|
/* Conclude procedure */
|
|
ctx->state = NDEF_STATE_INVALID;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
#endif /* NDEF_FEATURE_ALL */
|
|
|
|
/*******************************************************************************/
|
|
static ndefDeviceType ndefPollerGetDeviceType(const rfalNfcDevice *dev)
|
|
{
|
|
ndefDeviceType type;
|
|
|
|
if( dev == NULL )
|
|
{
|
|
type = NDEF_DEV_NONE;
|
|
}
|
|
else
|
|
{
|
|
switch( dev->type )
|
|
{
|
|
case RFAL_NFC_LISTEN_TYPE_NFCA:
|
|
switch( dev->dev.nfca.type )
|
|
{
|
|
case RFAL_NFCA_T1T:
|
|
type = NDEF_DEV_T1T;
|
|
break;
|
|
case RFAL_NFCA_T2T:
|
|
type = NDEF_DEV_T2T;
|
|
break;
|
|
case RFAL_NFCA_T4T:
|
|
type = NDEF_DEV_T4T;
|
|
break;
|
|
default:
|
|
type = NDEF_DEV_NONE;
|
|
break;
|
|
}
|
|
break;
|
|
case RFAL_NFC_LISTEN_TYPE_NFCB:
|
|
type = NDEF_DEV_T4T;
|
|
break;
|
|
case RFAL_NFC_LISTEN_TYPE_NFCF:
|
|
type = NDEF_DEV_T3T;
|
|
break;
|
|
case RFAL_NFC_LISTEN_TYPE_NFCV:
|
|
type = NDEF_DEV_T5T;
|
|
break;
|
|
default:
|
|
type = NDEF_DEV_NONE;
|
|
break;
|
|
}
|
|
}
|
|
return type;
|
|
}
|
|
|
|
|