diff options
Diffstat (limited to 'src/phFriNfc_LlcpUtils.c')
-rw-r--r-- | src/phFriNfc_LlcpUtils.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/src/phFriNfc_LlcpUtils.c b/src/phFriNfc_LlcpUtils.c new file mode 100644 index 0000000..3927552 --- /dev/null +++ b/src/phFriNfc_LlcpUtils.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file phFriNfc_Llcp.c + * \brief NFC LLCP core + * + * Project: NFC-FRI + * + */ + +/*include files*/ +#include <phNfcTypes.h> +#include <phNfcHalTypes.h> +#include <phLibNfcStatus.h> +#include <phFriNfc_LlcpUtils.h> +#include <phFriNfc_Llcp.h> + +NFCSTATUS phFriNfc_Llcp_DecodeTLV( phNfc_sData_t *psRawData, + uint32_t *pOffset, + uint8_t *pType, + phNfc_sData_t *psValueBuffer ) +{ + uint8_t type; + uint8_t length; + uint32_t offset = *pOffset; + + /* Check for NULL pointers */ + if ((psRawData == NULL) || (pOffset == NULL) || (pType == NULL) || (psValueBuffer == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check offset */ + if (offset > psRawData->length) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if enough room for Type and Length (with overflow check) */ + if ((offset+2 > psRawData->length) && (offset+2 > offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Get Type and Length from current TLV, and update offset */ + type = psRawData->buffer[offset]; + length = psRawData->buffer[offset+1]; + offset += 2; + + /* Check if enough room for Value with announced Length (with overflow check) */ + if ((offset+length > psRawData->length) && (offset+length > offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Save response, and update offset */ + *pType = type; + psValueBuffer->buffer = psRawData->buffer + offset; + psValueBuffer->length = length; + offset += length; + + /* Save updated offset */ + *pOffset = offset; + + return NFCSTATUS_SUCCESS; +} + +NFCSTATUS phFriNfc_Llcp_EncodeTLV( phNfc_sData_t *psValueBuffer, + uint32_t *pOffset, + uint8_t type, + uint8_t length, + uint8_t *pValue) +{ + uint32_t offset = *pOffset; + uint8_t i; + + /* Check for NULL pointers */ + if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check offset */ + if (offset > psValueBuffer->length) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if enough room for Type and Length (with overflow check) */ + if ((offset+2 > psValueBuffer->length) && (offset+2 > offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Set the TYPE */ + psValueBuffer->buffer[offset] = type; + offset += 1; + + /* Set the LENGTH */ + psValueBuffer->buffer[offset] = length; + offset += 1; + + /* Set the VALUE */ + for(i=0;i<length;i++,offset++) + { + psValueBuffer->buffer[offset] = pValue[i]; + } + + /* Save updated offset */ + *pOffset = offset; + + return NFCSTATUS_SUCCESS; +} + +/* TODO: comment function EncodeMIUX */ +void phFriNfc_Llcp_EncodeMIUX(uint16_t* pMiux, + uint16_t* pMiuxEncoded) +{ + uint16_t miux = *pMiux; + uint8_t encodeBuffer[2]; + + /* MASK */ + miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK; + + encodeBuffer[0] = miux >> 8; + encodeBuffer[1] = (uint8_t)miux; + + /* Set the new value of MIUX */ + *pMiuxEncoded =(encodeBuffer[0]) + (encodeBuffer[1] *16*16); +} + +/* TODO: comment function EncodeRW */ +void phFriNfc_Llcp_EncodeRW(uint8_t *pRw) +{ + /* MASK */ + *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK; +} + +/** + * Initializes a Fifo Cyclic Buffer to point to some allocated memory. + */ +void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER pUtilFifo, + const uint8_t *pBuffStart, + uint32_t buffLength) +{ + pUtilFifo->pBuffStart = (uint8_t *)pBuffStart; + pUtilFifo->pBuffEnd = (uint8_t *)pBuffStart + buffLength-1; + pUtilFifo->pIn = (uint8_t *)pBuffStart; + pUtilFifo->pOut = (uint8_t *)pBuffStart; + pUtilFifo->bFull = FALSE; +} + +/** + * Clears the Fifo Cyclic Buffer - loosing any data that was in it. + */ +void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + pUtilFifo->pIn = pUtilFifo->pBuffStart; + pUtilFifo->pOut = pUtilFifo->pBuffStart; + pUtilFifo->bFull = FALSE; +} + +/** + * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER pUtilFifo, + uint8_t *pData, + uint32_t dataLength) +{ + uint32_t dataLengthWritten = 0; + uint8_t * pNext; + + while(dataLengthWritten < dataLength) + { + pNext = (uint8_t*)pUtilFifo->pIn+1; + + if(pNext > pUtilFifo->pBuffEnd) + { + //Wrap around + pNext = pUtilFifo->pBuffStart; + } + + if(pUtilFifo->bFull) + { + //Full + break; + } + + if(pNext == pUtilFifo->pOut) + { + // Trigger Full flag + pUtilFifo->bFull = TRUE; + } + + dataLengthWritten++; + *pNext = *pData++; + pUtilFifo->pIn = pNext; + } + + return dataLengthWritten; +} + +/** + * Attempts to read dataLength bytes from the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER pUtilFifo, + uint8_t *pBuffer, + uint32_t dataLength) +{ + uint32_t dataLengthRead = 0; + uint8_t * pNext; + + while(dataLengthRead < dataLength) + { + if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE)) + { + //No more bytes in buffer + break; + } + else + { + dataLengthRead++; + + if(pUtilFifo->pOut == pUtilFifo->pBuffEnd) + { + /* Wrap around */ + pNext = pUtilFifo->pBuffStart; + } + else + { + pNext = (uint8_t*)pUtilFifo->pOut + 1; + } + + *pBuffer++ = *pNext; + + pUtilFifo->pOut = pNext; + + pUtilFifo->bFull = FALSE; + } + } + + return dataLengthRead; +} + +/** + * Returns the number of bytes currently stored in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + uint32_t dataLength; + uint8_t * pIn = (uint8_t *)pUtilFifo->pIn; + uint8_t * pOut = (uint8_t *)pUtilFifo->pOut; + + if (pUtilFifo->bFull) + { + dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1; + } + else + { + if(pIn >= pOut) + { + dataLength = pIn - pOut; + } + else + { + dataLength = pUtilFifo->pBuffEnd - pOut; + dataLength += (pIn+1) - pUtilFifo->pBuffStart; + } + } + + return dataLength; +} + + +/** + * Returns the available room for writing in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + uint32_t dataLength; + uint32_t size; + uint8_t * pIn = (uint8_t *)pUtilFifo->pIn; + uint8_t * pOut = (uint8_t *)pUtilFifo->pOut; + + if (pUtilFifo->bFull) + { + dataLength = 0; + } + else + { + if(pIn >= pOut) + { + size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1; + dataLength = size - (pIn - pOut); + } + else + { + dataLength = pOut - pIn; + } + } + + return dataLength; +} + + + +uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset ) +{ + uint32_t nOriginalOffset = nOffset; + pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2) | (psHeader->ptype >> 2)); + pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap); + return nOffset - nOriginalOffset; +} + +uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset ) +{ + uint32_t nOriginalOffset = nOffset; + pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr)); + return nOffset - nOriginalOffset; +} + +uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader ) +{ + psHeader->dsap = (pBuffer[nOffset] & 0xFC) >> 2; + psHeader->ptype = ((pBuffer[nOffset] & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6); + psHeader->ssap = pBuffer[nOffset+1] & 0x3F; + return PHFRINFC_LLCP_PACKET_HEADER_SIZE; +} + +uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence ) +{ + psSequence->ns = pBuffer[nOffset] >> 4; + psSequence->nr = pBuffer[nOffset] & 0x0F; + return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; +} + + |