Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2010 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * \file  phFriNfc_Llcp.c
     19  * \brief NFC LLCP core
     20  *
     21  * Project: NFC-FRI
     22  *
     23  */
     24 
     25 /*include files*/
     26 #include <phNfcTypes.h>
     27 #include <phNfcHalTypes.h>
     28 #include <phLibNfcStatus.h>
     29 #include <phFriNfc_LlcpUtils.h>
     30 #include <phFriNfc_Llcp.h>
     31 
     32 NFCSTATUS phFriNfc_Llcp_DecodeTLV( phNfc_sData_t  *psRawData,
     33                                    uint32_t       *pOffset,
     34                                    uint8_t        *pType,
     35                                    phNfc_sData_t  *psValueBuffer )
     36 {
     37    uint8_t type;
     38    uint8_t length;
     39    uint32_t offset = *pOffset;
     40 
     41    /* Check for NULL pointers */
     42    if ((psRawData == NULL) || (pOffset == NULL) || (pType == NULL) || (psValueBuffer == NULL))
     43    {
     44       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     45    }
     46 
     47    /* Check offset */
     48    if (offset > psRawData->length)
     49    {
     50       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     51    }
     52 
     53    /* Check if enough room for Type and Length (with overflow check) */
     54    if ((offset+2 > psRawData->length) && (offset+2 > offset))
     55    {
     56       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     57    }
     58 
     59    /* Get Type and Length from current TLV, and update offset */
     60    type = psRawData->buffer[offset];
     61    length = psRawData->buffer[offset+1];
     62    offset += 2;
     63 
     64    /* Check if enough room for Value with announced Length (with overflow check) */
     65    if ((offset+length > psRawData->length) && (offset+length > offset))
     66    {
     67       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     68    }
     69 
     70    /* Save response, and update offset */
     71    *pType = type;
     72    psValueBuffer->buffer = psRawData->buffer + offset;
     73    psValueBuffer->length = length;
     74    offset += length;
     75 
     76    /* Save updated offset */
     77    *pOffset = offset;
     78 
     79    return NFCSTATUS_SUCCESS;
     80 }
     81 
     82 NFCSTATUS phFriNfc_Llcp_EncodeTLV( phNfc_sData_t  *psValueBuffer,
     83                                    uint32_t       *pOffset,
     84                                    uint8_t        type,
     85                                    uint8_t        length,
     86                                    uint8_t        *pValue)
     87 {
     88    uint32_t offset = *pOffset;
     89    uint32_t finalOffset = offset + 2 + length; /* 2 stands for Type and Length fields size */
     90    uint8_t i;
     91 
     92    /* Check for NULL pointers */
     93    if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL))
     94    {
     95       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     96    }
     97 
     98    /* Check offset */
     99    if (offset > psValueBuffer->length)
    100    {
    101       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    102    }
    103 
    104    /* Check if enough room for Type, Length and Value (with overflow check) */
    105    if ((finalOffset > psValueBuffer->length) || (finalOffset < offset))
    106    {
    107       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    108    }
    109 
    110    /* Set the TYPE */
    111    psValueBuffer->buffer[offset] = type;
    112    offset += 1;
    113 
    114    /* Set the LENGTH */
    115    psValueBuffer->buffer[offset] = length;
    116    offset += 1;
    117 
    118    /* Set the VALUE */
    119    for(i=0;i<length;i++,offset++)
    120    {
    121       psValueBuffer->buffer[offset]  = pValue[i];
    122    }
    123 
    124    /* Save updated offset */
    125    *pOffset = offset;
    126 
    127    return NFCSTATUS_SUCCESS;
    128 }
    129 
    130 NFCSTATUS phFriNfc_Llcp_AppendTLV( phNfc_sData_t  *psValueBuffer,
    131                                    uint32_t       nTlvOffset,
    132                                    uint32_t       *pCurrentOffset,
    133                                    uint8_t        length,
    134                                    uint8_t        *pValue)
    135 {
    136    uint32_t offset = *pCurrentOffset;
    137    uint32_t finalOffset = offset + length;
    138 
    139    /* Check for NULL pointers */
    140    if ((psValueBuffer == NULL) || (pCurrentOffset == NULL) || (pValue == NULL))
    141    {
    142       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    143    }
    144 
    145    /* Check offset */
    146    if (offset > psValueBuffer->length)
    147    {
    148       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    149    }
    150 
    151    /* Check if enough room for Type and Length (with overflow check) */
    152    if ((finalOffset > psValueBuffer->length) || (finalOffset < offset))
    153    {
    154       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    155    }
    156 
    157    /* Update the LENGTH */
    158    psValueBuffer->buffer[nTlvOffset+1] += length;
    159 
    160    /* Set the VALUE */
    161    memcpy(psValueBuffer->buffer + offset, pValue, length);
    162    offset += length;
    163 
    164    /* Save updated offset */
    165    *pCurrentOffset = offset;
    166 
    167    return NFCSTATUS_SUCCESS;
    168 }
    169 
    170 
    171 /* TODO: comment function EncodeMIUX */
    172 void phFriNfc_Llcp_EncodeMIUX(uint16_t miux,
    173                               uint8_t* pMiuxEncoded)
    174 {
    175    /* MASK */
    176    miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK;
    177 
    178    pMiuxEncoded[0] = miux >> 8;
    179    pMiuxEncoded[1] = miux & 0xff;
    180 }
    181 
    182 /* TODO: comment function EncodeRW */
    183 void phFriNfc_Llcp_EncodeRW(uint8_t *pRw)
    184 {
    185    /* MASK */
    186    *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK;
    187 }
    188 
    189 /**
    190  * Initializes a Fifo Cyclic Buffer to point to some allocated memory.
    191  */
    192 void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER   pUtilFifo,
    193                                   const uint8_t        *pBuffStart,
    194                                   uint32_t             buffLength)
    195 {
    196    pUtilFifo->pBuffStart = (uint8_t *)pBuffStart;
    197    pUtilFifo->pBuffEnd   = (uint8_t *)pBuffStart + buffLength-1;
    198    pUtilFifo->pIn        = (uint8_t *)pBuffStart;
    199    pUtilFifo->pOut       = (uint8_t *)pBuffStart;
    200    pUtilFifo->bFull      = FALSE;
    201 }
    202 
    203 /**
    204  * Clears the Fifo Cyclic Buffer - loosing any data that was in it.
    205  */
    206 void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo)
    207 {
    208    pUtilFifo->pIn = pUtilFifo->pBuffStart;
    209    pUtilFifo->pOut = pUtilFifo->pBuffStart;
    210    pUtilFifo->bFull      = FALSE;
    211 }
    212 
    213 /**
    214  * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer.
    215  */
    216 uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER   pUtilFifo,
    217                                        uint8_t              *pData,
    218                                        uint32_t             dataLength)
    219 {
    220    uint32_t dataLengthWritten = 0;
    221    uint8_t * pNext;
    222 
    223    while(dataLengthWritten < dataLength)
    224    {
    225       pNext = (uint8_t*)pUtilFifo->pIn+1;
    226 
    227       if(pNext > pUtilFifo->pBuffEnd)
    228       {
    229          //Wrap around
    230          pNext = pUtilFifo->pBuffStart;
    231       }
    232 
    233       if(pUtilFifo->bFull)
    234       {
    235          //Full
    236          break;
    237       }
    238 
    239       if(pNext == pUtilFifo->pOut)
    240       {
    241          // Trigger Full flag
    242          pUtilFifo->bFull = TRUE;
    243       }
    244 
    245       dataLengthWritten++;
    246       *pNext = *pData++;
    247       pUtilFifo->pIn = pNext;
    248    }
    249 
    250    return dataLengthWritten;
    251 }
    252 
    253 /**
    254  * Attempts to read dataLength bytes from the specified  Fifo Cyclic Buffer.
    255  */
    256 uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER   pUtilFifo,
    257                                           uint8_t              *pBuffer,
    258                                           uint32_t             dataLength)
    259 {
    260    uint32_t  dataLengthRead = 0;
    261    uint8_t * pNext;
    262 
    263    while(dataLengthRead < dataLength)
    264    {
    265       if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE))
    266       {
    267          //No more bytes in buffer
    268          break;
    269       }
    270       else
    271       {
    272          dataLengthRead++;
    273 
    274          if(pUtilFifo->pOut == pUtilFifo->pBuffEnd)
    275          {
    276             /* Wrap around */
    277             pNext = pUtilFifo->pBuffStart;
    278          }
    279          else
    280          {
    281             pNext = (uint8_t*)pUtilFifo->pOut + 1;
    282          }
    283 
    284          *pBuffer++ = *pNext;
    285 
    286          pUtilFifo->pOut = pNext;
    287 
    288          pUtilFifo->bFull = FALSE;
    289       }
    290    }
    291 
    292    return dataLengthRead;
    293 }
    294 
    295 /**
    296  * Returns the number of bytes currently stored in Fifo Cyclic Buffer.
    297  */
    298 uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo)
    299 {
    300    uint32_t dataLength;
    301    uint8_t * pIn        = (uint8_t *)pUtilFifo->pIn;
    302    uint8_t * pOut       = (uint8_t *)pUtilFifo->pOut;
    303 
    304    if (pUtilFifo->bFull)
    305    {
    306       dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
    307    }
    308    else
    309    {
    310       if(pIn >= pOut)
    311       {
    312          dataLength = pIn - pOut;
    313       }
    314       else
    315       {
    316          dataLength = pUtilFifo->pBuffEnd - pOut;
    317          dataLength += (pIn+1) - pUtilFifo->pBuffStart;
    318       }
    319    }
    320 
    321    return dataLength;
    322 }
    323 
    324 
    325 /**
    326  * Returns the available room for writing in Fifo Cyclic Buffer.
    327  */
    328 uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo)
    329 {
    330    uint32_t dataLength;
    331    uint32_t  size;
    332    uint8_t * pIn         = (uint8_t *)pUtilFifo->pIn;
    333    uint8_t * pOut        = (uint8_t *)pUtilFifo->pOut;
    334 
    335    if (pUtilFifo->bFull)
    336    {
    337       dataLength = 0;
    338    }
    339    else
    340    {
    341       if(pIn >= pOut)
    342       {
    343          size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
    344          dataLength = size - (pIn - pOut);
    345       }
    346       else
    347       {
    348          dataLength = pOut - pIn;
    349       }
    350    }
    351 
    352    return dataLength;
    353 }
    354 
    355 
    356 
    357 uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset )
    358 {
    359    uint32_t nOriginalOffset = nOffset;
    360    pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2)  | (psHeader->ptype >> 2));
    361    pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap);
    362    return nOffset - nOriginalOffset;
    363 }
    364 
    365 uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset )
    366 {
    367    uint32_t nOriginalOffset = nOffset;
    368    pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr));
    369    return nOffset - nOriginalOffset;
    370 }
    371 
    372 uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader )
    373 {
    374    psHeader->dsap  = (pBuffer[nOffset] & 0xFC) >> 2;
    375    psHeader->ptype = ((pBuffer[nOffset]  & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6);
    376    psHeader->ssap  = pBuffer[nOffset+1] & 0x3F;
    377    return PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    378 }
    379 
    380 uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence )
    381 {
    382    psSequence->ns = pBuffer[nOffset] >> 4;
    383    psSequence->nr = pBuffer[nOffset] & 0x0F;
    384    return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
    385 }
    386 
    387 
    388