Files
NxpNfcRdLib/.svn/pristine/14/146a4d1b235471003405192bbda6ddf670a9a83b.svn-base
2024-07-08 21:03:06 +08:00

745 lines
21 KiB
Plaintext

/*----------------------------------------------------------------------------*/
/* Copyright 2009,2020,2022 NXP */
/* */
/* NXP Confidential. This software is owned or controlled by NXP and may only */
/* be used strictly in accordance with the applicable license terms. */
/* By expressly accepting such terms or by downloading, installing, */
/* activating and/or otherwise using the software, you are agreeing that you */
/* have read, and that you agree to comply with and are bound by, such */
/* license terms. If you do not agree to be bound by the applicable license */
/* terms, then you may not retain, install, activate or otherwise use the */
/* software. */
/*----------------------------------------------------------------------------*/
/** \file
* Generic Tools Component of Reader Library Framework.
* $Author$
* $Revision$ (v07.10.00)
* $Date$
*
* History:
* CHu: Generated 19. May 2009
*
*/
#include <phTools.h>
#include <ph_RefDefs.h>
#include <NxpNfcRdLib_Ver.h>
#ifdef _WIN32
#pragma warning(push) /* PRQA S 3116 */
#pragma warning(disable:4001) /* PRQA S 3116 */
#include <stdlib.h>
#include <string.h> /* memcpy */
#pragma warning(pop) /* PRQA S 3116 */
#else
#include <string.h> /* memcpy */
#endif
static uint8_t phTools_CalcParity(uint8_t bDataByte, uint8_t bOption);
phStatus_t phTools_EncodeParity(
uint8_t bOption,
uint8_t * pInBuffer,
uint16_t wInBufferLength,
uint8_t bInBufferBits,
uint16_t wOutBufferSize,
uint8_t * pOutBuffer,
uint16_t * pOutBufferLength,
uint8_t * pOutBufferBits
)
{
uint16_t PH_MEMLOC_REM wByteIndexIn;
uint16_t PH_MEMLOC_REM wByteIndexOut;
uint8_t PH_MEMLOC_REM bBitPosition;
uint16_t PH_MEMLOC_REM wInByteCount;
/* Parameter check */
if (((bOption != PH_TOOLS_PARITY_OPTION_EVEN) && (bOption != PH_TOOLS_PARITY_OPTION_ODD)) || (bInBufferBits > 7U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
/* Retrieve full input byte count */
if (bInBufferBits == 0U)
{
wInByteCount = wInBufferLength;
}
else
{
wInByteCount = wInBufferLength - 1u;
}
/* Retrieve number of (additional) full bytes */
(*pOutBufferLength) = (uint16_t)((uint16_t)(wInByteCount + bInBufferBits) >> 3U);
/* Retrieve output bits */
*pOutBufferBits = (uint8_t)((uint16_t)(wInByteCount + bInBufferBits) % 8U);
/* Increment output length in case of incomplete byte */
if (*pOutBufferBits > 0U)
{
++(*pOutBufferLength);
}
/* Overflow check */
if ((*pOutBufferLength) > (0xFFFFU - wInByteCount))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
/* Calculate number of output bytes */
(*pOutBufferLength) = wInByteCount + (*pOutBufferLength);
/* Buffer overflow check*/
if (wOutBufferSize < (*pOutBufferLength))
{
(*pOutBufferLength) = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_TOOLS);
}
/* Prepare output buffer */
pOutBuffer[0] = 0x00;
/* Prepare loop vars */
wByteIndexIn = 0;
wByteIndexOut = 0;
bBitPosition = 7;
/* Do for each byte */
for (; wByteIndexIn < wInBufferLength; ++wByteIndexIn )
{
/* Append source bits to output */
pOutBuffer[wByteIndexOut] |= (uint8_t)(pInBuffer[wByteIndexIn] << (7U - bBitPosition));
/* If there is more data bits in the sourcebyte append it to next data byte */
if ((wByteIndexOut + 1U) < (*pOutBufferLength))
{
if(bBitPosition == 7U)
{
pOutBuffer[wByteIndexOut + 1U] = 0;
}
else
{
pOutBuffer[wByteIndexOut + 1U] = (uint8_t)(pInBuffer[wByteIndexIn] >> (1u + bBitPosition));
}
/* Perform parity appending if this isn't an incomplete byte */
if ((bInBufferBits == 0U) || ((wByteIndexIn + 1U) < wInBufferLength))
{
pOutBuffer[wByteIndexOut + 1U] |= (uint8_t)(phTools_CalcParity(pInBuffer[wByteIndexIn], bOption) << (7U - bBitPosition));
}
}
/* We have reached the 8th parity bit, the output buffer index is now one ahead */
if (bBitPosition == 0U)
{
if ((wByteIndexOut + 2U) < (*pOutBufferLength))
{
bBitPosition = 8;
pOutBuffer[++wByteIndexOut + 1U] = 0x00;
}
}
++wByteIndexOut;
--bBitPosition;
}
/* Mask out invalid bits of last byte */
if (*pOutBufferBits > 0U)
{
pOutBuffer[(*pOutBufferLength) - 1U] &= (uint8_t)(0xFFU >> (8U - *pOutBufferBits));
}
return PH_ERR_SUCCESS;
}
phStatus_t phTools_DecodeParity(
uint8_t bOption,
uint8_t * pInBuffer,
uint16_t wInBufferLength,
uint8_t bInBufferBits,
uint16_t wOutBufferSize,
uint8_t * pOutBuffer,
uint16_t * pOutBufferLength,
uint8_t * pOutBufferBits
)
{
uint16_t PH_MEMLOC_REM wByteIndexIn;
uint16_t PH_MEMLOC_REM wByteIndexOut;
uint8_t PH_MEMLOC_REM bBitPosition;
uint16_t PH_MEMLOC_REM wDiv;
uint8_t PH_MEMLOC_REM bMod;
uint8_t PH_MEMLOC_REM bParity;
/* Parameter check */
if (((bOption != PH_TOOLS_PARITY_OPTION_EVEN) && (bOption != PH_TOOLS_PARITY_OPTION_ODD)) || (bInBufferBits > 7U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
/* Parameter check */
if (wInBufferLength == 0U)
{
/* Zero input length is simply passed through */
if (bInBufferBits == 0U)
{
(*pOutBufferLength) = 0;
*pOutBufferBits = 0;
return PH_ERR_SUCCESS;
}
/* Invalid parameter */
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
}
/* Retrieve DIV and MOD */
if (bInBufferBits == 0U)
{
wDiv = (uint16_t)(wInBufferLength / 9U);
bMod = (uint8_t)(wInBufferLength % 9U);
}
else
{
wDiv = (uint16_t)((wInBufferLength - 1U) / 9U);
bMod = (uint8_t)((wInBufferLength - 1U) % 9U);
}
/* Calculate number of output bytes */
(*pOutBufferLength) = (uint16_t)((wDiv << 3U) + bMod);
if (bMod > bInBufferBits)
{
--(*pOutBufferLength);
}
/* Calculate number of rest-bits of output */
*pOutBufferBits = (uint8_t)((8U - (((8U + ((*pOutBufferLength) % 8U)) - bInBufferBits) % 8U)) % 8U);
/* Increment output length in case of incomplete byte */
if (*pOutBufferBits > 0U)
{
++(*pOutBufferLength);
}
/* Buffer overflow check*/
if (wOutBufferSize < (*pOutBufferLength))
{
(*pOutBufferLength) = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_TOOLS);
}
/* Prepare loop vars */
wByteIndexIn = 0U;
wByteIndexOut = 0U;
bBitPosition = 7U;
/* Do for each byte */
for (; wByteIndexOut < (*pOutBufferLength); ++wByteIndexOut, ++wByteIndexIn, --bBitPosition)
{
/* Append source bits to output */
pOutBuffer[wByteIndexOut] = (uint8_t)(pInBuffer[wByteIndexIn] >> (7U - bBitPosition));
/* If there is more data bits in the sourcebyte append it to next data byte */
if ((wByteIndexIn + /* */ 1U) < wInBufferLength)
{
/* Append remaining bits to output */
pOutBuffer[wByteIndexOut] |= (uint8_t)(pInBuffer[wByteIndexIn + 1U] << (1U + bBitPosition));
/* Perform parity checking if this isn't an incomplete byte */
if ((*pOutBufferBits == 0U)
|| ((wByteIndexOut + /* */ 1U) < (*pOutBufferLength)))
{
bParity = phTools_CalcParity(pOutBuffer[wByteIndexOut], bOption);
if ((pInBuffer[wByteIndexIn + 1U] & (uint8_t)(1U << (7U - bBitPosition))) != (bParity << (7U - bBitPosition)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTEGRITY_ERROR, PH_COMP_TOOLS);
}
}
}
/* We have reached the 8th parity bit, the input buffer index is now one ahead */
if (bBitPosition == 0U)
{
bBitPosition = 8;
++wByteIndexIn;
}
}
/* Mask out invalid bits of last byte */
if (*pOutBufferBits > 0U)
{
pOutBuffer[(*pOutBufferLength) - 1U] &= (uint8_t)(0xFFU >> (8U - *pOutBufferBits));
}
return PH_ERR_SUCCESS;
}
phStatus_t phTools_CalculateCrc5(
uint8_t bOption,
uint8_t bPreset,
uint8_t bPolynom,
uint8_t * pData,
uint16_t wDataLength,
uint8_t * pCrc
)
{
uint16_t PH_MEMLOC_REM wDataIndex = 0;
uint8_t PH_MEMLOC_REM bBitIndex;
uint8_t PH_MEMLOC_REM bBitMax;
if (0u != (bOption & (uint8_t)~(uint8_t)PH_TOOLS_CRC_OPTION_MASK))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
*pCrc = bPreset;
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
/* Shift 5bit preset to 8bit (data) alignment */
*pCrc <<= 3U;
/* Shift 5bit polinom to 8bit (data) alignment */
bPolynom <<= 3U;
}
/* Loop through all data bytes */
while (0U != wDataLength)
{
/* XOR input data */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_BITWISE))
{
if (wDataLength < 8U)
{
bBitMax = (uint8_t)wDataLength;
wDataLength = 0;
}
else
{
bBitMax = 8;
wDataLength -= 8u;
}
}
else
{
bBitMax = 8;
/* Decrement DataLen */
--wDataLength;
}
/* CRC polynom (MSB first) */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
*pCrc ^= pData[wDataIndex++] & (0xFFU << (8U - bBitMax));
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x80U))
{
*pCrc = (uint8_t)(((*pCrc) << 1U) ^ bPolynom);
}
else
{
*pCrc = (*pCrc) << 1U;
}
}
}
/* CRC polynom (LSB first) */
else
{
*pCrc ^= pData[wDataIndex++] & (0xFFU >> (8U - bBitMax));
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x01U))
{
*pCrc = (uint8_t)(((*pCrc) >> 1U) ^ bPolynom);
}
else
{
*pCrc = ((*pCrc) >> 1U);
}
}
}
}
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
/* Shift back for 5bit alignment */
*pCrc >>= 3U;
}
/* Invert CRC if requested */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_OUPUT_INVERTED))
{
*pCrc ^= 0x1FU;
}
return PH_ERR_SUCCESS;
}
phStatus_t phTools_CalculateCrc8(
uint8_t bOption,
uint8_t bPreset,
uint8_t bPolynom,
uint8_t * pData,
uint16_t wDataLength,
uint8_t * pCrc
)
{
uint16_t PH_MEMLOC_REM wDataIndex = 0;
uint8_t PH_MEMLOC_REM bBitIndex;
uint8_t PH_MEMLOC_REM bBitMax;
if (0u != (bOption & (uint8_t)~(uint8_t)PH_TOOLS_CRC_OPTION_MASK))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
*pCrc = bPreset;
/* Loop through all data bytes */
while (0U != wDataLength)
{
/* XOR input data */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_BITWISE))
{
if (wDataLength < 8U)
{
bBitMax = (uint8_t)wDataLength;
wDataLength = 0;
}
else
{
bBitMax = 8;
wDataLength -= 8u;
}
}
else
{
bBitMax = 8;
/* Decrement DataLen */
--wDataLength;
}
/* CRC polynom (MSB first) */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
*pCrc ^= pData[wDataIndex++] & (0xFFU << (8U - bBitMax));
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0U != ((*pCrc) & 0x80U))
{
*pCrc = (uint8_t)(((*pCrc) << 1U) ^ bPolynom);
}
else
{
*pCrc = ((*pCrc) << 1U);
}
}
}
/* CRC polynom (LSB first) */
else
{
*pCrc ^= pData[wDataIndex++] & (0xFFU >> (8U - bBitMax));
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x01U))
{
*pCrc = (uint8_t)(((*pCrc) >> 1U) ^ bPolynom);
}
else
{
*pCrc = ((*pCrc) >> 1U);
}
}
}
}
/* Invert CRC if requested */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_OUPUT_INVERTED))
{
*pCrc ^= 0xFFU;
}
return PH_ERR_SUCCESS;
}
phStatus_t phTools_CalculateCrc16(
uint8_t bOption,
uint16_t wPreset,
uint16_t wPolynom,
uint8_t * pData,
uint16_t wDataLength,
uint16_t * pCrc
)
{
uint16_t PH_MEMLOC_REM wDataIndex = 0;
uint8_t PH_MEMLOC_REM bBitIndex;
uint8_t PH_MEMLOC_REM bBitMax;
if (0u != (bOption & (uint8_t)~(uint8_t)PH_TOOLS_CRC_OPTION_MASK))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
*pCrc = wPreset;
/* Loop through all data bytes */
while (0U != wDataLength)
{
/* XOR input data */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_BITWISE))
{
if (wDataLength < 8U)
{
bBitMax = (uint8_t)wDataLength;
wDataLength = 0;
}
else
{
bBitMax = 8;
wDataLength -= 8u;
}
}
else
{
bBitMax = 8;
/* Decrement DataLen */
--wDataLength;
}
/* CRC polynom (MSB first) */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
*pCrc ^= (uint16_t)pData[wDataIndex++] << 8U;
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x8000U))
{
*pCrc = (uint16_t)(((*pCrc) << 1U) ^ wPolynom);
}
else
{
*pCrc = ((*pCrc) << 1U);
}
}
}
/* CRC polynom (LSB first) */
else
{
*pCrc ^= pData[wDataIndex++];
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0U != ((*pCrc) & 0x0001U))
{
*pCrc = (uint16_t)(((*pCrc) >> 1U) ^ wPolynom);
}
else
{
*pCrc = ((*pCrc) >> 1U);
}
}
}
}
/* Invert CRC if requested */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_OUPUT_INVERTED))
{
*pCrc ^= 0xFFFFU;
}
return PH_ERR_SUCCESS;
}
phStatus_t phTools_CalculateCrc32(
uint8_t bOption,
uint32_t dwPreset,
uint32_t dwPolynom,
uint8_t * pData,
uint32_t dwDataLength,
uint32_t * pCrc
)
{
uint32_t PH_MEMLOC_REM dwDataIndex = 0;
uint8_t PH_MEMLOC_REM bBitIndex;
uint8_t PH_MEMLOC_REM bBitMax;
if (0u != (bOption & (uint8_t)~(uint8_t)PH_TOOLS_CRC_OPTION_MASK))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_TOOLS);
}
*pCrc = dwPreset;
/* Loop through all data bytes */
while (0U != dwDataLength)
{
/* XOR input data */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_BITWISE))
{
if (dwDataLength < 8U)
{
bBitMax = (uint8_t)dwDataLength;
dwDataLength = 0;
}
else
{
bBitMax = 8;
dwDataLength -= 8u;
}
}
else
{
bBitMax = 8;
/* Decrement DataLen */
--dwDataLength;
}
/* CRC polynom (MSB first) */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_MSB_FIRST))
{
*pCrc ^= (uint32_t)pData[dwDataIndex++] << 24U;
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x80000000U))
{
*pCrc = (uint32_t)(((*pCrc) << 1U) ^ dwPolynom);
}
else
{
*pCrc = ((*pCrc) << 1U);
}
}
}
/* CRC polynom (LSB first) */
else
{
*pCrc ^= pData[dwDataIndex++];
for (bBitIndex = 0; bBitIndex < bBitMax; ++bBitIndex)
{
if (0u != ((*pCrc) & 0x00000001U))
{
*pCrc = (uint32_t)(((*pCrc) >> 1U) ^ dwPolynom);
}
else
{
*pCrc = ((*pCrc) >> 1U);
}
}
}
}
/* Invert CRC if requested */
if (0U != (bOption & PH_TOOLS_CRC_OPTION_OUPUT_INVERTED))
{
*pCrc ^= 0xFFFFFFFFU;
}
return PH_ERR_SUCCESS;
}
static uint8_t phTools_CalcParity(
uint8_t bDataByte,
uint8_t bOption
)
{
uint8_t PH_MEMLOC_REM bBit;
uint8_t PH_MEMLOC_REM bParity;
if (bOption == PH_TOOLS_PARITY_OPTION_EVEN)
{
bParity = 0x00;
}
else
{
bParity = 0x01;
}
for (bBit = 0; bBit < 8U; ++bBit)
{
if (0U != (bDataByte & (uint8_t)(1U << bBit)))
{
++bParity;
}
}
return bParity & 0x01U;
}
static void phTools_UpdateCrc_B(uint8_t bCh, uint16_t *pLpwCrc)
{
bCh = (bCh^(uint8_t)((*pLpwCrc)&0x00FFU));
bCh = (bCh ^ (bCh<<4U));
*pLpwCrc = (*pLpwCrc >> 8U) ^ ((uint16_t)bCh << 8U) ^ ((uint16_t)bCh << 3U) ^ ((uint16_t)bCh>>4U);
}
phStatus_t phTools_ComputeCrc_B(
uint8_t *pData,
uint32_t dwLength,
uint8_t *pCrc)
{
uint8_t PH_MEMLOC_REM bChBlock = 0;
uint16_t PH_MEMLOC_REM wCrc = 0xFFFF;
do
{
bChBlock = *pData++;
phTools_UpdateCrc_B(bChBlock, &wCrc);
} while (0u != (--dwLength));
wCrc = ~wCrc;
pCrc[0] = (uint8_t) (wCrc & 0xFFU);
pCrc[1] = (uint8_t) ( (wCrc>>8U) & 0xFFU);
return PH_ERR_SUCCESS;
}
#ifndef __min
# define __min(X,Y) (((X) < (Y)) ? (X) : (Y))
#endif
phStatus_t phTools_GetVersion(
uint8_t * pProductVer,
uint16_t * pMajor,
uint8_t * pMinor,
uint16_t * pPatch_Dev,
uint8_t * pVersionString,
uint16_t * pVersionStringLen)
{
uint16_t PH_MEMLOC_REM wCopyLen = 0;
const char szNxpNfcRdLib_VER_FILEDESCRIPTION[] = NxpNfcRdLib_VER_FILEDESCRIPTION;
PH_UNUSED_VARIABLE(pProductVer);
/* *pProductVer = ; ankur update it when there ir product version */
*pMajor = NxpNfcRdLib_VER_MAJOR;
*pMinor = NxpNfcRdLib_VER_MINOR;
*pPatch_Dev = NxpNfcRdLib_VER_DEV;
wCopyLen = (uint16_t)(sizeof(szNxpNfcRdLib_VER_FILEDESCRIPTION)/sizeof(szNxpNfcRdLib_VER_FILEDESCRIPTION[0]));
if(*pVersionStringLen < (wCopyLen - 1u))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_LENGTH_ERROR, PH_COMP_TOOLS);
}
else
{
wCopyLen = __min(wCopyLen,(*pVersionStringLen));
(void)memcpy(pVersionString, szNxpNfcRdLib_VER_FILEDESCRIPTION, wCopyLen);
*pVersionStringLen = wCopyLen - 1u;
}
return PH_ERR_SUCCESS;
}