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    uint8_t i;
     90 
     91    /* Check for NULL pointers */
     92    if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL))
     93    {
     94       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
     95    }
     96 
     97    /* Check offset */
     98    if (offset > psValueBuffer->length)
     99    {
    100       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    101    }
    102 
    103    /* Check if enough room for Type and Length (with overflow check) */
    104    if ((offset+2 > psValueBuffer->length) && (offset+2 > offset))
    105    {
    106       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    107    }
    108 
    109    /* Set the TYPE */
    110    psValueBuffer->buffer[offset] = type;
    111    offset += 1;
    112 
    113    /* Set the LENGTH */
    114    psValueBuffer->buffer[offset] = length;
    115    offset += 1;
    116 
    117    /* Set the VALUE */
    118    for(i=0;i<length;i++,offset++)
    119    {
    120       psValueBuffer->buffer[offset]  = pValue[i];
    121    }
    122 
    123    /* Save updated offset */
    124    *pOffset = offset;
    125 
    126    return NFCSTATUS_SUCCESS;
    127 }
    128 
    129 /* TODO: comment function EncodeMIUX */
    130 void phFriNfc_Llcp_EncodeMIUX(uint16_t miux,
    131                               uint8_t* pMiuxEncoded)
    132 {
    133    /* MASK */
    134    miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK;
    135 
    136    pMiuxEncoded[0] = miux >> 8;
    137    pMiuxEncoded[1] = miux & 0xff;
    138 }
    139 
    140 /* TODO: comment function EncodeRW */
    141 void phFriNfc_Llcp_EncodeRW(uint8_t *pRw)
    142 {
    143    /* MASK */
    144    *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK;
    145 }
    146 
    147 /**
    148  * Initializes a Fifo Cyclic Buffer to point to some allocated memory.
    149  */
    150 void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER   pUtilFifo,
    151                                   const uint8_t        *pBuffStart,
    152                                   uint32_t             buffLength)
    153 {
    154    pUtilFifo->pBuffStart = (uint8_t *)pBuffStart;
    155    pUtilFifo->pBuffEnd   = (uint8_t *)pBuffStart + buffLength-1;
    156    pUtilFifo->pIn        = (uint8_t *)pBuffStart;
    157    pUtilFifo->pOut       = (uint8_t *)pBuffStart;
    158    pUtilFifo->bFull      = FALSE;
    159 }
    160 
    161 /**
    162  * Clears the Fifo Cyclic Buffer - loosing any data that was in it.
    163  */
    164 void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo)
    165 {
    166    pUtilFifo->pIn = pUtilFifo->pBuffStart;
    167    pUtilFifo->pOut = pUtilFifo->pBuffStart;
    168    pUtilFifo->bFull      = FALSE;
    169 }
    170 
    171 /**
    172  * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer.
    173  */
    174 uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER   pUtilFifo,
    175                                        uint8_t              *pData,
    176                                        uint32_t             dataLength)
    177 {
    178    uint32_t dataLengthWritten = 0;
    179    uint8_t * pNext;
    180 
    181    while(dataLengthWritten < dataLength)
    182    {
    183       pNext = (uint8_t*)pUtilFifo->pIn+1;
    184 
    185       if(pNext > pUtilFifo->pBuffEnd)
    186       {
    187          //Wrap around
    188          pNext = pUtilFifo->pBuffStart;
    189       }
    190 
    191       if(pUtilFifo->bFull)
    192       {
    193          //Full
    194          break;
    195       }
    196 
    197       if(pNext == pUtilFifo->pOut)
    198       {
    199          // Trigger Full flag
    200          pUtilFifo->bFull = TRUE;
    201       }
    202 
    203       dataLengthWritten++;
    204       *pNext = *pData++;
    205       pUtilFifo->pIn = pNext;
    206    }
    207 
    208    return dataLengthWritten;
    209 }
    210 
    211 /**
    212  * Attempts to read dataLength bytes from the specified  Fifo Cyclic Buffer.
    213  */
    214 uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER   pUtilFifo,
    215                                           uint8_t              *pBuffer,
    216                                           uint32_t             dataLength)
    217 {
    218    uint32_t  dataLengthRead = 0;
    219    uint8_t * pNext;
    220 
    221    while(dataLengthRead < dataLength)
    222    {
    223       if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE))
    224       {
    225          //No more bytes in buffer
    226          break;
    227       }
    228       else
    229       {
    230          dataLengthRead++;
    231 
    232          if(pUtilFifo->pOut == pUtilFifo->pBuffEnd)
    233          {
    234             /* Wrap around */
    235             pNext = pUtilFifo->pBuffStart;
    236          }
    237          else
    238          {
    239             pNext = (uint8_t*)pUtilFifo->pOut + 1;
    240          }
    241 
    242          *pBuffer++ = *pNext;
    243 
    244          pUtilFifo->pOut = pNext;
    245 
    246          pUtilFifo->bFull = FALSE;
    247       }
    248    }
    249 
    250    return dataLengthRead;
    251 }
    252 
    253 /**
    254  * Returns the number of bytes currently stored in Fifo Cyclic Buffer.
    255  */
    256 uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo)
    257 {
    258    uint32_t dataLength;
    259    uint8_t * pIn        = (uint8_t *)pUtilFifo->pIn;
    260    uint8_t * pOut       = (uint8_t *)pUtilFifo->pOut;
    261 
    262    if (pUtilFifo->bFull)
    263    {
    264       dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
    265    }
    266    else
    267    {
    268       if(pIn >= pOut)
    269       {
    270          dataLength = pIn - pOut;
    271       }
    272       else
    273       {
    274          dataLength = pUtilFifo->pBuffEnd - pOut;
    275          dataLength += (pIn+1) - pUtilFifo->pBuffStart;
    276       }
    277    }
    278 
    279    return dataLength;
    280 }
    281 
    282 
    283 /**
    284  * Returns the available room for writing in Fifo Cyclic Buffer.
    285  */
    286 uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo)
    287 {
    288    uint32_t dataLength;
    289    uint32_t  size;
    290    uint8_t * pIn         = (uint8_t *)pUtilFifo->pIn;
    291    uint8_t * pOut        = (uint8_t *)pUtilFifo->pOut;
    292 
    293    if (pUtilFifo->bFull)
    294    {
    295       dataLength = 0;
    296    }
    297    else
    298    {
    299       if(pIn >= pOut)
    300       {
    301          size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
    302          dataLength = size - (pIn - pOut);
    303       }
    304       else
    305       {
    306          dataLength = pOut - pIn;
    307       }
    308    }
    309 
    310    return dataLength;
    311 }
    312 
    313 
    314 
    315 uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset )
    316 {
    317    uint32_t nOriginalOffset = nOffset;
    318    pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2)  | (psHeader->ptype >> 2));
    319    pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap);
    320    return nOffset - nOriginalOffset;
    321 }
    322 
    323 uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset )
    324 {
    325    uint32_t nOriginalOffset = nOffset;
    326    pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr));
    327    return nOffset - nOriginalOffset;
    328 }
    329 
    330 uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader )
    331 {
    332    psHeader->dsap  = (pBuffer[nOffset] & 0xFC) >> 2;
    333    psHeader->ptype = ((pBuffer[nOffset]  & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6);
    334    psHeader->ssap  = pBuffer[nOffset+1] & 0x3F;
    335    return PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    336 }
    337 
    338 uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence )
    339 {
    340    psSequence->ns = pBuffer[nOffset] >> 4;
    341    psSequence->nr = pBuffer[nOffset] & 0x0F;
    342    return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
    343 }
    344 
    345 
    346