summaryrefslogtreecommitdiffstats
path: root/src/phFriNfc_LlcpUtils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/phFriNfc_LlcpUtils.c')
-rw-r--r--src/phFriNfc_LlcpUtils.c351
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;
+}
+
+