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 <phNfcLlcpTypes.h>
     27 #include <phOsalNfc_Timer.h>
     28 
     29 #include <phFriNfc_Llcp.h>
     30 #include <phFriNfc_LlcpUtils.h>
     31 
     32 /**
     33  * \internal
     34  * \name States of the LLC state machine.
     35  *
     36  */
     37 /*@{*/
     38 #define PHFRINFC_LLCP_STATE_RESET_INIT               0   /**< \internal Initial state.*/
     39 #define PHFRINFC_LLCP_STATE_CHECKED                  1   /**< \internal The tag has been checked for LLCP compliance.*/
     40 #define PHFRINFC_LLCP_STATE_ACTIVATION               2   /**< \internal The deactivation phase.*/
     41 #define PHFRINFC_LLCP_STATE_PAX                      3   /**< \internal Parameter exchange phase.*/
     42 #define PHFRINFC_LLCP_STATE_OPERATION_RECV           4   /**< \internal Normal operation phase (ready to receive).*/
     43 #define PHFRINFC_LLCP_STATE_OPERATION_SEND           5   /**< \internal Normal operation phase (ready to send).*/
     44 #define PHFRINFC_LLCP_STATE_DEACTIVATION             6   /**< \internal The deactivation phase.*/
     45 /*@}*/
     46 
     47 /**
     48  * \internal
     49  * \name Masks used for VERSION parsing.
     50  *
     51  */
     52 /*@{*/
     53 #define PHFRINFC_LLCP_VERSION_MAJOR_MASK            0xF0    /**< \internal Mask to apply to get major version number.*/
     54 #define PHFRINFC_LLCP_VERSION_MINOR_MASK            0x0F    /**< \internal Mask to apply to get major version number.*/
     55 /*@}*/
     56 
     57 /**
     58  * \internal
     59  * \name Invalid values for parameters.
     60  *
     61  */
     62 /*@{*/
     63 #define PHFRINFC_LLCP_INVALID_VERSION              0x00   /**< \internal Invalid VERSION value.*/
     64 /*@}*/
     65 
     66 /**
     67  * \internal
     68  * \name Internal constants.
     69  *
     70  */
     71 /*@{*/
     72 #define PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH \
     73    (( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_VERSION ) + \
     74     ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_MIUX ) + \
     75     ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_WKS ) + \
     76     ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_LTO ) + \
     77     ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_OPT ))   /**< \internal Maximum size of link params TLV.*/
     78 /*@}*/
     79 
     80 
     81 
     82 /* --------------------------- Internal functions ------------------------------ */
     83 
     84 static void phFriNfc_Llcp_Receive_CB( void               *pContext,
     85                                       NFCSTATUS          status,
     86                                       phNfc_sData_t      *psData);
     87 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t    *Llcp,
     88                                                      phNfc_sData_t      *psPacket );
     89 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp );
     90 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t                    *Llcp,
     91                                              phFriNfc_Llcp_sPacketHeader_t      *psHeader,
     92                                              phFriNfc_Llcp_sPacketSequence_t    *psSequence,
     93                                              phNfc_sData_t                      *psInfo );
     94 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp );
     95 
     96 static phNfc_sData_t * phFriNfc_Llcp_AllocateAndCopy(phNfc_sData_t * pOrig)
     97 {
     98    phNfc_sData_t * pDest = NULL;
     99 
    100    if (pOrig == NULL)
    101    {
    102        return NULL;
    103    }
    104 
    105    pDest = phOsalNfc_GetMemory(sizeof(phNfc_sData_t));
    106    if (pDest == NULL)
    107    {
    108       goto error;
    109    }
    110 
    111    pDest->buffer = phOsalNfc_GetMemory(pOrig->length);
    112    if (pDest->buffer == NULL)
    113    {
    114       goto error;
    115    }
    116 
    117    memcpy(pDest->buffer, pOrig->buffer, pOrig->length);
    118    pDest->length = pOrig->length;
    119 
    120    return pDest;
    121 
    122 error:
    123    if (pDest != NULL)
    124    {
    125       if (pDest->buffer != NULL)
    126       {
    127          phOsalNfc_FreeMemory(pDest->buffer);
    128       }
    129       phOsalNfc_FreeMemory(pDest);
    130    }
    131    return NULL;
    132 }
    133 
    134 static void phFriNfc_Llcp_Deallocate(phNfc_sData_t * pData)
    135 {
    136    if (pData != NULL)
    137    {
    138       if (pData->buffer != NULL)
    139       {
    140          phOsalNfc_FreeMemory(pData->buffer);
    141       }
    142       else
    143       {
    144          LLCP_PRINT("Warning, deallocating empty buffer");
    145       }
    146       phOsalNfc_FreeMemory(pData);
    147    }
    148 }
    149 
    150 static NFCSTATUS phFriNfc_Llcp_InternalDeactivate( phFriNfc_Llcp_t *Llcp )
    151 {
    152    phFriNfc_Llcp_Send_CB_t pfSendCB;
    153    void * pSendContext;
    154    if ((Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) ||
    155        (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) ||
    156        (Llcp->state == PHFRINFC_LLCP_STATE_PAX)            ||
    157        (Llcp->state == PHFRINFC_LLCP_STATE_ACTIVATION))
    158    {
    159       /* Update state */
    160       Llcp->state = PHFRINFC_LLCP_STATE_DEACTIVATION;
    161 
    162       /* Stop timer */
    163       phOsalNfc_Timer_Stop(Llcp->hSymmTimer);
    164 
    165       Llcp->psSendHeader = NULL;
    166       Llcp->psSendSequence = NULL;
    167       /* Return delayed send operation in error, in any */
    168       if (Llcp->psSendInfo != NULL)
    169       {
    170          phFriNfc_Llcp_Deallocate(Llcp->psSendInfo);
    171          Llcp->psSendInfo = NULL;
    172       }
    173       if (Llcp->pfSendCB != NULL)
    174       {
    175          /* Get Callback params */
    176          pfSendCB = Llcp->pfSendCB;
    177          pSendContext = Llcp->pSendContext;
    178          /* Reset callback params */
    179          Llcp->pfSendCB = NULL;
    180          Llcp->pSendContext = NULL;
    181          /* Call the callback */
    182          (pfSendCB)(pSendContext, NFCSTATUS_FAILED);
    183       }
    184 
    185       /* Notify service layer */
    186       Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated);
    187 
    188       /* Forward check request to MAC layer */
    189       return phFriNfc_LlcpMac_Deactivate(&Llcp->MAC);
    190    }
    191 
    192    return NFCSTATUS_SUCCESS;
    193 }
    194 
    195 
    196 static NFCSTATUS phFriNfc_Llcp_SendSymm( phFriNfc_Llcp_t *Llcp )
    197 {
    198    phFriNfc_Llcp_sPacketHeader_t sHeader;
    199 
    200    sHeader.dsap  = PHFRINFC_LLCP_SAP_LINK;
    201    sHeader.ssap  = PHFRINFC_LLCP_SAP_LINK;
    202    sHeader.ptype = PHFRINFC_LLCP_PTYPE_SYMM;
    203    return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL);
    204 }
    205 
    206 
    207 static NFCSTATUS phFriNfc_Llcp_SendPax( phFriNfc_Llcp_t *Llcp, phFriNfc_Llcp_sLinkParameters_t *psLinkParams)
    208 {
    209    uint8_t                       pTLVBuffer[PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH];
    210    phNfc_sData_t                 sParamsTLV;
    211    phFriNfc_Llcp_sPacketHeader_t sHeader;
    212    NFCSTATUS                     result;
    213 
    214    /* Prepare link parameters TLV */
    215    sParamsTLV.buffer = pTLVBuffer;
    216    sParamsTLV.length = PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH;
    217    result = phFriNfc_Llcp_EncodeLinkParams(&sParamsTLV, psLinkParams, PHFRINFC_LLCP_VERSION);
    218    if (result != NFCSTATUS_SUCCESS)
    219    {
    220       /* Error while encoding */
    221       return NFCSTATUS_FAILED;
    222    }
    223 
    224    /* Check if ready to send */
    225    if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND)
    226    {
    227       /* No send pending, send the PAX packet */
    228       sHeader.dsap  = PHFRINFC_LLCP_SAP_LINK;
    229       sHeader.ssap  = PHFRINFC_LLCP_SAP_LINK;
    230       sHeader.ptype = PHFRINFC_LLCP_PTYPE_PAX;
    231       return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, &sParamsTLV);
    232    }
    233    else
    234    {
    235       /* Error: A send is already pending, cannot send PAX */
    236       /* NOTE: this should not happen since PAX are sent before any other packet ! */
    237       return NFCSTATUS_FAILED;
    238    }
    239 }
    240 
    241 
    242 static NFCSTATUS phFriNfc_Llcp_SendDisconnect( phFriNfc_Llcp_t *Llcp )
    243 {
    244    phFriNfc_Llcp_sPacketHeader_t sHeader;
    245 
    246    /* Check if ready to send */
    247    if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND)
    248    {
    249       /* No send pending, send the DISC packet */
    250       sHeader.dsap  = PHFRINFC_LLCP_SAP_LINK;
    251       sHeader.ssap  = PHFRINFC_LLCP_SAP_LINK;
    252       sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC;
    253       return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL);
    254    }
    255    else
    256    {
    257       /* A send is already pending, raise a flag to send DISC as soon as possible */
    258       Llcp->bDiscPendingFlag = TRUE;
    259       return NFCSTATUS_PENDING;
    260    }
    261 }
    262 
    263 
    264 static void phFriNfc_Llcp_Timer_CB(uint32_t TimerId, void *pContext)
    265 {
    266    phFriNfc_Llcp_t               *Llcp = (phFriNfc_Llcp_t*)pContext;
    267 
    268    PHNFC_UNUSED_VARIABLE(TimerId);
    269 
    270    /* Check current state */
    271    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
    272    {
    273       /* No data is coming before LTO, disconnecting */
    274       phFriNfc_Llcp_InternalDeactivate(Llcp);
    275    }
    276    else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
    277    {
    278       /* Send SYMM */
    279       phFriNfc_Llcp_SendSymm(Llcp);
    280    }
    281    else
    282    {
    283       /* Nothing to do if not in Normal Operation state */
    284    }
    285 }
    286 
    287 
    288 static NFCSTATUS phFriNfc_Llcp_HandleAggregatedPacket( phFriNfc_Llcp_t *Llcp,
    289                                                        phNfc_sData_t *psRawPacket )
    290 {
    291    phNfc_sData_t  sInfo;
    292    phNfc_sData_t  sCurrentInfo;
    293    uint16_t       length;
    294    NFCSTATUS      status;
    295 
    296    /* Get info field */
    297    sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    298    sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    299 
    300    /* Check for empty info field */
    301    if (sInfo.length == 0)
    302    {
    303       return NFCSTATUS_FAILED;
    304    }
    305 
    306    /* Check consistency */
    307    while (sInfo.length != 0)
    308    {
    309       /* Check if enough room to read length */
    310       if (sInfo.length < sizeof(sInfo.length))
    311       {
    312          return NFCSTATUS_FAILED;
    313       }
    314       /* Read length */
    315       length = (sInfo.buffer[0] << 8) | sInfo.buffer[1];
    316       /* Update info buffer */
    317       sInfo.buffer += 2; /*Size of length field is 2*/
    318       sInfo.length -= 2; /*Size of length field is 2*/
    319       /* Check if declared length fits in remaining space */
    320       if (length > sInfo.length)
    321       {
    322          return NFCSTATUS_FAILED;
    323       }
    324       /* Update info buffer */
    325       sInfo.buffer += length;
    326       sInfo.length -= length;
    327    }
    328 
    329    /* Get info field */
    330    sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    331    sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    332 
    333    /* Handle aggregated packets */
    334    while (sInfo.length != 0)
    335    {
    336       /* Read length */
    337       length = (sInfo.buffer[0] << 8) | sInfo.buffer[1];
    338       /* Update info buffer */
    339       sInfo.buffer += 2;        /* Size of length field is 2 */
    340       sInfo.length -= 2;    /*Size of length field is 2*/
    341       /* Handle aggregated packet */
    342       sCurrentInfo.buffer=sInfo.buffer;
    343       sCurrentInfo.length=length;
    344       status = phFriNfc_Llcp_HandleIncomingPacket(Llcp, &sCurrentInfo);
    345       if ( (status != NFCSTATUS_SUCCESS) &&
    346            (status != NFCSTATUS_PENDING) )
    347       {
    348          /* TODO: Error: invalid frame */
    349       }
    350       /* Update info buffer */
    351       sInfo.buffer += length;
    352       sInfo.length -= length;
    353    }
    354    return NFCSTATUS_SUCCESS;
    355 }
    356 
    357 
    358 static NFCSTATUS phFriNfc_Llcp_ParseLinkParams( phNfc_sData_t                    *psParamsTLV,
    359                                                 phFriNfc_Llcp_sLinkParameters_t  *psParsedParams,
    360                                                 uint8_t                          *pnParsedVersion )
    361 {
    362    NFCSTATUS                        status;
    363    uint8_t                          type;
    364    phFriNfc_Llcp_sLinkParameters_t  sParams;
    365    phNfc_sData_t                    sValueBuffer;
    366    uint32_t                         offset = 0;
    367    uint8_t                          version = PHFRINFC_LLCP_INVALID_VERSION;
    368 
    369    /* Check for NULL pointers */
    370    if ((psParamsTLV == NULL) || (psParsedParams == NULL) || (pnParsedVersion == NULL))
    371    {
    372       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    373    }
    374 
    375    /* Prepare default param structure */
    376    sParams.miu    = PHFRINFC_LLCP_MIU_DEFAULT;
    377    sParams.wks    = PHFRINFC_LLCP_WKS_DEFAULT;
    378    sParams.lto    = PHFRINFC_LLCP_LTO_DEFAULT;
    379    sParams.option = PHFRINFC_LLCP_OPTION_DEFAULT;
    380 
    381    /* Decode TLV */
    382    while (offset < psParamsTLV->length)
    383    {
    384       status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type, &sValueBuffer);
    385       if (status != NFCSTATUS_SUCCESS)
    386       {
    387          /* Error: Ill-formed TLV */
    388          return status;
    389       }
    390       switch(type)
    391       {
    392          case PHFRINFC_LLCP_TLV_TYPE_VERSION:
    393          {
    394             /* Check length */
    395             if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_VERSION)
    396             {
    397                /* Error : Ill-formed VERSION parameter TLV */
    398                break;
    399             }
    400             /* Get VERSION */
    401             version = sValueBuffer.buffer[0];
    402             break;
    403          }
    404          case PHFRINFC_LLCP_TLV_TYPE_MIUX:
    405          {
    406             /* Check length */
    407             if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX)
    408             {
    409                /* Error : Ill-formed MIUX parameter TLV */
    410                break;
    411             }
    412             /* Get MIU */
    413             sParams.miu = (PHFRINFC_LLCP_MIU_DEFAULT + ((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1])) & PHFRINFC_LLCP_TLV_MIUX_MASK;
    414             break;
    415          }
    416          case PHFRINFC_LLCP_TLV_TYPE_WKS:
    417          {
    418             /* Check length */
    419             if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_WKS)
    420             {
    421                /* Error : Ill-formed MIUX parameter TLV */
    422                break;
    423             }
    424             /* Get WKS */
    425             sParams.wks = (sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1];
    426             /* Ignored bits must always be set */
    427             sParams.wks |= PHFRINFC_LLCP_TLV_WKS_MASK;
    428             break;
    429          }
    430          case PHFRINFC_LLCP_TLV_TYPE_LTO:
    431          {
    432             /* Check length */
    433             if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_LTO)
    434             {
    435                /* Error : Ill-formed LTO parameter TLV */
    436                break;
    437             }
    438             /* Get LTO */
    439             sParams.lto = sValueBuffer.buffer[0];
    440             break;
    441          }
    442          case PHFRINFC_LLCP_TLV_TYPE_OPT:
    443          {
    444             /* Check length */
    445             if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_OPT)
    446             {
    447                /* Error : Ill-formed OPT parameter TLV */
    448                break;;
    449             }
    450             /* Get OPT */
    451             sParams.option = sValueBuffer.buffer[0] & PHFRINFC_LLCP_TLV_OPT_MASK;
    452             break;
    453          }
    454          default:
    455          {
    456             /* Error : Unknown Type */
    457             break;
    458          }
    459       }
    460    }
    461 
    462    /* Check if a VERSION parameter has been provided */
    463    if (version == PHFRINFC_LLCP_INVALID_VERSION)
    464    {
    465       /* Error : Mandatory VERSION parameter not provided */
    466       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    467    }
    468 
    469    /* Save response */
    470    *pnParsedVersion = version;
    471    memcpy(psParsedParams, &sParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
    472 
    473    return NFCSTATUS_SUCCESS;
    474 }
    475 
    476 
    477 static NFCSTATUS phFriNfc_Llcp_VersionAgreement( uint8_t localVersion,
    478                                                  uint8_t remoteVersion,
    479                                                  uint8_t *pNegociatedVersion )
    480 {
    481    uint8_t     localMajor  = localVersion  & PHFRINFC_LLCP_VERSION_MAJOR_MASK;
    482    uint8_t     localMinor  = localVersion  & PHFRINFC_LLCP_VERSION_MINOR_MASK;
    483    uint8_t     remoteMajor = remoteVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK;
    484    uint8_t     remoteMinor = remoteVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK;
    485    uint8_t     negociatedVersion;
    486 
    487    /* Check for NULL pointers */
    488    if (pNegociatedVersion == NULL)
    489    {
    490       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
    491    }
    492 
    493    /* Compare Major numbers */
    494    if (localMajor == remoteMajor)
    495    {
    496       /* Version agreement succeed : use lowest version */
    497       negociatedVersion = localMajor | ((remoteMinor<localMinor)?remoteMinor:localMinor);
    498    }
    499    else if (localMajor > remoteMajor)
    500    {
    501       /* Decide if versions are compatible */
    502       /* Currently, there is no backward compatibility to handle */
    503       return NFCSTATUS_FAILED;
    504    }
    505    else /* if (localMajor < remoteMajor) */
    506    {
    507       /* It is up to the remote host to decide if versions are compatible */
    508       /* Set negociated version to our local version, the remote will
    509          deacivate the link if its own version agreement fails */
    510       negociatedVersion = localVersion;
    511    }
    512 
    513    /* Save response */
    514    *pNegociatedVersion = negociatedVersion;
    515 
    516    return NFCSTATUS_SUCCESS;
    517 }
    518 
    519 
    520 static NFCSTATUS phFriNfc_Llcp_InternalActivate( phFriNfc_Llcp_t *Llcp,
    521                                                  phNfc_sData_t   *psParamsTLV)
    522 {
    523    NFCSTATUS                        status;
    524    phFriNfc_Llcp_sLinkParameters_t  sRemoteParams;
    525    uint8_t                          remoteVersion;
    526    uint8_t                          negociatedVersion;
    527    const uint16_t nMaxHeaderSize =  PHFRINFC_LLCP_PACKET_HEADER_SIZE +
    528                                     PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
    529 
    530    /* Parse parameters  */
    531    status = phFriNfc_Llcp_ParseLinkParams(psParamsTLV, &sRemoteParams, &remoteVersion);
    532    if (status != NFCSTATUS_SUCCESS)
    533    {
    534       /* Error: invalid parameters TLV */
    535       status = NFCSTATUS_FAILED;
    536    }
    537    else
    538    {
    539       /* Version agreement procedure */
    540       status = phFriNfc_Llcp_VersionAgreement(PHFRINFC_LLCP_VERSION , remoteVersion, &negociatedVersion);
    541       if (status != NFCSTATUS_SUCCESS)
    542       {
    543          /* Error: version agreement failed */
    544          status = NFCSTATUS_FAILED;
    545       }
    546       else
    547       {
    548          /* Save parameters */
    549          Llcp->version = negociatedVersion;
    550          memcpy(&Llcp->sRemoteParams, &sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
    551 
    552          /* Update remote MIU to match local Tx buffer size */
    553          if (Llcp->nTxBufferLength < (Llcp->sRemoteParams.miu + nMaxHeaderSize))
    554          {
    555             Llcp->sRemoteParams.miu = Llcp->nTxBufferLength - nMaxHeaderSize;
    556          }
    557 
    558          /* Initiate Symmetry procedure by resetting LTO timer */
    559          /* NOTE: this also updates current state */
    560          phFriNfc_Llcp_ResetLTO(Llcp);
    561       }
    562    }
    563    /* Notify upper layer, if Activation failed CB called by Deactivate */
    564    if (status == NFCSTATUS_SUCCESS)
    565    {
    566       /* Link activated ! */
    567       Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated);
    568    }
    569 
    570    return status;
    571 }
    572 
    573 
    574 static NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t  *Llcp,
    575                                                        phNfc_sData_t    *psParamsTLV)
    576 {
    577    NFCSTATUS                     status = NFCSTATUS_SUCCESS;
    578 
    579    /* Create the timer */
    580    Llcp->hSymmTimer = phOsalNfc_Timer_Create();
    581    if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID)
    582    {
    583       /* Error: unable to create timer */
    584       return NFCSTATUS_INSUFFICIENT_RESOURCES;
    585    }
    586 
    587    /* Check if params received from MAC activation procedure */
    588    if (psParamsTLV == NULL)
    589    {
    590       /* No params with selected MAC mapping, enter PAX mode for parameter exchange */
    591       Llcp->state = PHFRINFC_LLCP_STATE_PAX;
    592       /* Set default MIU for PAX exchange */
    593       Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT;
    594       /* If the local device is the initiator, it must initiate PAX exchange */
    595       if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
    596       {
    597          /* Send PAX */
    598          status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
    599       }
    600    }
    601    else
    602    {
    603       /* Params exchanged during MAX activation, try LLC activation */
    604       status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV);
    605    }
    606 
    607    if (status == NFCSTATUS_SUCCESS)
    608    {
    609       /* Start listening for incoming packets */
    610       Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
    611       phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
    612    }
    613 
    614    return status;
    615 }
    616 
    617 
    618 static void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t  *Llcp )
    619 {
    620    uint8_t state = Llcp->state;
    621 
    622    /* Delete the timer */
    623    if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID)
    624    {
    625       phOsalNfc_Timer_Delete(Llcp->hSymmTimer);
    626    }
    627 
    628    /* Reset state */
    629    Llcp->state = PHFRINFC_LLCP_STATE_RESET_INIT;
    630 
    631    switch (state)
    632    {
    633       case PHFRINFC_LLCP_STATE_DEACTIVATION:
    634       {
    635          /* The service layer has already been notified, nothing more to do */
    636          break;
    637       }
    638       default:
    639       {
    640          /* Notify service layer of link failure */
    641          Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated);
    642          break;
    643       }
    644    }
    645 }
    646 
    647 
    648 static void phFriNfc_Llcp_ChkLlcp_CB( void       *pContext,
    649                                       NFCSTATUS  status )
    650 {
    651    /* Get monitor from context */
    652    phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
    653 
    654    /* Update state */
    655    Llcp->state = PHFRINFC_LLCP_STATE_CHECKED;
    656 
    657    /* Invoke callback */
    658    Llcp->pfChk_CB(Llcp->pChkContext, status);
    659 }
    660 
    661 static void phFriNfc_Llcp_LinkStatus_CB( void                              *pContext,
    662                                          phFriNfc_LlcpMac_eLinkStatus_t    eLinkStatus,
    663                                          phNfc_sData_t                     *psParamsTLV,
    664                                          phFriNfc_LlcpMac_ePeerType_t      PeerRemoteDevType)
    665 {
    666    NFCSTATUS status;
    667 
    668    /* Get monitor from context */
    669    phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
    670 
    671    /* Save the local peer role (initiator/target) */
    672    Llcp->eRole = PeerRemoteDevType;
    673 
    674    /* Check new link status */
    675    switch(eLinkStatus)
    676    {
    677       case phFriNfc_LlcpMac_eLinkActivated:
    678       {
    679          /* Handle MAC link activation */
    680          status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV);
    681          if (status != NFCSTATUS_SUCCESS)
    682          {
    683             /* Error: LLC link activation procedure failed, deactivate MAC link */
    684             status = phFriNfc_Llcp_InternalDeactivate(Llcp);
    685          }
    686          break;
    687       }
    688       case phFriNfc_LlcpMac_eLinkDeactivated:
    689       {
    690          /* Handle MAC link deactivation (cannot fail) */
    691          phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp);
    692          break;
    693       }
    694       default:
    695       {
    696          /* Warning: Unknown link status, should not happen */
    697       }
    698    }
    699 }
    700 
    701 
    702 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp )
    703 {
    704    uint32_t nDuration = 0;
    705    uint8_t bIsReset = 0;
    706 
    707    /* Stop timer */
    708    phOsalNfc_Timer_Stop(Llcp->hSymmTimer);
    709 
    710 
    711    /* Update state */
    712    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
    713    {
    714       Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND;
    715    }
    716    else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
    717    {
    718       Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV;
    719    }
    720    else if (Llcp->state != PHFRINFC_LLCP_STATE_DEACTIVATION &&
    721             Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT)
    722    {
    723       bIsReset = 1;
    724       /* Not yet in OPERATION state, perform first reset */
    725       if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
    726       {
    727          Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND;
    728       }
    729       else
    730       {
    731          Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV;
    732       }
    733    }
    734 
    735    /* Calculate timer duration */
    736    /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */
    737    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
    738    {
    739       /* Response must be received before LTO announced by remote peer */
    740       nDuration = Llcp->sRemoteParams.lto * 10;
    741    }
    742    else
    743    {
    744       if (bIsReset)
    745       {
    746           /* Immediately bounce SYMM back - it'll take
    747            * a while for the host to come up with something,
    748            * and maybe the remote is faster.
    749            */
    750           nDuration = 1;
    751       }
    752       else
    753       {
    754           /* Must answer before the local announced LTO */
    755           /* NOTE: to ensure the answer is completely sent before LTO, the
    756                   timer is triggered _before_ LTO expiration */
    757           /* TODO: make sure time scope is enough, and avoid use of magic number */
    758           nDuration = (Llcp->sLocalParams.lto * 10) / 2;
    759       }
    760    }
    761 
    762    LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration);
    763 
    764    /* Restart timer */
    765    phOsalNfc_Timer_Start(
    766       Llcp->hSymmTimer,
    767       nDuration,
    768       phFriNfc_Llcp_Timer_CB,
    769       Llcp);
    770 }
    771 
    772 
    773 static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t    *Llcp,
    774                                                  phNfc_sData_t      *psPacket )
    775 {
    776    NFCSTATUS                        result;
    777    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    778 
    779    /* Parse header */
    780    phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
    781 
    782    /* Check packet type */
    783    switch (sHeader.ptype)
    784    {
    785       case PHFRINFC_LLCP_PTYPE_SYMM:
    786       {
    787          /* Nothing to do, the LTO is handled upon all packet reception */
    788          result = NFCSTATUS_SUCCESS;
    789          break;
    790       }
    791 
    792       case PHFRINFC_LLCP_PTYPE_AGF:
    793       {
    794          /* Handle the aggregated packet */
    795          result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket);
    796          if (result != NFCSTATUS_SUCCESS)
    797          {
    798             /* Error: invalid info field, dropping frame */
    799          }
    800          break;
    801       }
    802 
    803       case PHFRINFC_LLCP_PTYPE_DISC:
    804       {
    805          /* Handle link disconnection request */
    806          result = phFriNfc_Llcp_InternalDeactivate(Llcp);
    807          break;
    808       }
    809 
    810 
    811       case PHFRINFC_LLCP_PTYPE_FRMR:
    812       {
    813          /* TODO: what to do upon reception of FRMR on Link SAP ? */
    814          result = NFCSTATUS_SUCCESS;
    815          break;
    816       }
    817 
    818       case PHFRINFC_LLCP_PTYPE_PAX:
    819       {
    820          /* Ignore PAX when in Normal Operation */
    821          result = NFCSTATUS_SUCCESS;
    822          break;
    823       }
    824 
    825       default:
    826       {
    827          /* Error: invalid ptype field, dropping packet */
    828          break;
    829       }
    830    }
    831 
    832    return result;
    833 }
    834 
    835 
    836 static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t    *Llcp,
    837                                                       phNfc_sData_t      *psPacket )
    838 {
    839    phFriNfc_Llcp_Recv_CB_t          pfRecvCB;
    840    void                             *pContext;
    841    NFCSTATUS                        result = NFCSTATUS_SUCCESS;
    842    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    843 
    844    /* Forward to upper layer */
    845    if (Llcp->pfRecvCB != NULL)
    846    {
    847       /* Get callback details */
    848       pfRecvCB = Llcp->pfRecvCB;
    849       pContext = Llcp->pRecvContext;
    850       /* Reset callback details */
    851       Llcp->pfRecvCB = NULL;
    852       Llcp->pRecvContext = NULL;
    853       /* Call the callback */
    854       (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS);
    855    }
    856 
    857    return result;
    858 }
    859 
    860 
    861 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp )
    862 {
    863    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    864    phNfc_sData_t                    sInfoBuffer;
    865    phFriNfc_Llcp_sPacketHeader_t    *psSendHeader = NULL;
    866    phFriNfc_Llcp_sPacketSequence_t  *psSendSequence = NULL;
    867    phNfc_sData_t                    *psSendInfo = NULL;
    868    NFCSTATUS                        result;
    869    uint8_t                          bDeallocate = FALSE;
    870    uint8_t                          return_value = FALSE;
    871    /* Handle pending disconnection request */
    872    if (Llcp->bDiscPendingFlag == TRUE)
    873    {
    874       /* Last send si acheived, send the pending DISC packet */
    875       sHeader.dsap  = PHFRINFC_LLCP_SAP_LINK;
    876       sHeader.ssap  = PHFRINFC_LLCP_SAP_LINK;
    877       sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC;
    878       /* Set send params */
    879       psSendHeader = &sHeader;
    880       /* Reset flag */
    881       Llcp->bDiscPendingFlag = FALSE;
    882    }
    883    /* Handle pending frame reject request */
    884    else if (Llcp->bFrmrPendingFlag == TRUE)
    885    {
    886       /* Last send si acheived, send the pending FRMR packet */
    887       sInfoBuffer.buffer = Llcp->pFrmrInfo;
    888       sInfoBuffer.length = sizeof(Llcp->pFrmrInfo);
    889       /* Set send params */
    890       psSendHeader = &Llcp->sFrmrHeader;
    891       psSendInfo   = &sInfoBuffer;
    892       /* Reset flag */
    893       Llcp->bFrmrPendingFlag = FALSE;
    894    }
    895    /* Handle pending service frame */
    896    else if (Llcp->pfSendCB != NULL)
    897    {
    898       /* Set send params */
    899       psSendHeader = Llcp->psSendHeader;
    900       psSendSequence = Llcp->psSendSequence;
    901       psSendInfo = Llcp->psSendInfo;
    902       /* Reset pending send infos */
    903       Llcp->psSendHeader = NULL;
    904       Llcp->psSendSequence = NULL;
    905       Llcp->psSendInfo = NULL;
    906       bDeallocate = TRUE;
    907    }
    908 
    909    /* Perform send, if needed */
    910    if (psSendHeader != NULL)
    911    {
    912       result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo);
    913       if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING))
    914       {
    915          /* Error: send failed, impossible to recover */
    916          phFriNfc_Llcp_InternalDeactivate(Llcp);
    917       }
    918       return_value = TRUE;
    919    } else if (Llcp->pfSendCB == NULL) {
    920       // Nothing to send, send SYMM instead to allow peer to send something
    921       // if it wants.
    922       phFriNfc_Llcp_SendSymm(Llcp);
    923       return_value = TRUE;
    924    }
    925 
    926 clean_and_return:
    927    if (bDeallocate)
    928    {
    929        phFriNfc_Llcp_Deallocate(psSendInfo);
    930    }
    931 
    932    return return_value;
    933 }
    934 
    935 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t    *Llcp,
    936                                                      phNfc_sData_t      *psPacket )
    937 {
    938    NFCSTATUS                        status = NFCSTATUS_SUCCESS;
    939    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    940 
    941    /* Parse header */
    942    phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
    943 
    944    /* Check destination */
    945    if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK)
    946    {
    947       /* Handle packet as destinated to the Link SAP */
    948       status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket);
    949    }
    950    else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER)
    951    {
    952      /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */
    953      status = NFCSTATUS_FAILED;
    954    }
    955    else
    956    {
    957       /* Handle packet as destinated to the SDP and transport SAPs */
    958       status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket);
    959    }
    960    return status;
    961 }
    962 
    963 
    964 static void phFriNfc_Llcp_Receive_CB( void               *pContext,
    965                                       NFCSTATUS          status,
    966                                       phNfc_sData_t      *psData)
    967 {
    968    /* Get monitor from context */
    969    phFriNfc_Llcp_t               *Llcp = (phFriNfc_Llcp_t*)pContext;
    970    NFCSTATUS                     result = NFCSTATUS_SUCCESS;
    971    phFriNfc_Llcp_sPacketHeader_t sPacketHeader;
    972 
    973    /* Check reception status and for pending disconnection */
    974    if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE))
    975    {
    976 	  LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status);
    977       /* Reset disconnection operation */
    978       Llcp->bDiscPendingFlag = FALSE;
    979       /* Deactivate the link */
    980       phFriNfc_Llcp_InternalDeactivate(Llcp);
    981       return;
    982    }
    983 
    984    /* Parse header */
    985    phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader);
    986 
    987    if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM)
    988    {
    989       LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length);
    990    }
    991    else
    992    {
    993       LLCP_PRINT("?");
    994    }
    995 
    996 
    997    /* Check new link status */
    998    switch(Llcp->state)
    999    {
   1000       /* Handle packets in PAX-waiting state */
   1001       case PHFRINFC_LLCP_STATE_PAX:
   1002       {
   1003          /* Check packet type */
   1004          if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX)
   1005          {
   1006             /* Params exchanged during MAC activation, try LLC activation */
   1007             result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE);
   1008             /* If the local LLC is the target, it must answer the PAX */
   1009             if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget)
   1010             {
   1011                /* Send PAX */
   1012                result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
   1013             }
   1014          }
   1015          else
   1016          {
   1017             /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */
   1018          }
   1019          break;
   1020       }
   1021 
   1022       /* Handle normal operation packets */
   1023       case PHFRINFC_LLCP_STATE_OPERATION_RECV:
   1024       case PHFRINFC_LLCP_STATE_OPERATION_SEND:
   1025       {
   1026          /* Handle Symmetry procedure by resetting LTO timer */
   1027          phFriNfc_Llcp_ResetLTO(Llcp);
   1028          /* Handle packet */
   1029          result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData);
   1030          if ( (result != NFCSTATUS_SUCCESS) &&
   1031               (result != NFCSTATUS_PENDING) )
   1032          {
   1033             /* TODO: Error: invalid frame */
   1034          }
   1035          /* Perform pending send request, if any */
   1036          phFriNfc_Llcp_HandlePendingSend(Llcp);
   1037          break;
   1038       }
   1039 
   1040       default:
   1041       {
   1042          /* Warning: Should not receive packets in other states, drop them */
   1043       }
   1044    }
   1045 
   1046    /* Restart reception */
   1047    Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
   1048    phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
   1049 }
   1050 
   1051 
   1052 static void phFriNfc_Llcp_Send_CB( void               *pContext,
   1053                                    NFCSTATUS          status )
   1054 {
   1055    /* Get monitor from context */
   1056    phFriNfc_Llcp_t                  *Llcp = (phFriNfc_Llcp_t*)pContext;
   1057    phFriNfc_Llcp_Send_CB_t          pfSendCB;
   1058    void                             *pSendContext;
   1059 
   1060    /* Call the upper layer callback if last packet sent was  */
   1061    /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */
   1062    if (Llcp->psSendHeader == NULL)
   1063    {
   1064       if (Llcp->pfSendCB != NULL)
   1065       {
   1066          /* Get Callback params */
   1067          pfSendCB = Llcp->pfSendCB;
   1068          pSendContext = Llcp->pSendContext;
   1069          /* Reset callback params */
   1070          Llcp->pfSendCB = NULL;
   1071          Llcp->pSendContext = NULL;
   1072          /* Call the callback */
   1073          (pfSendCB)(pSendContext, status);
   1074       }
   1075    }
   1076 
   1077    /* Check reception status */
   1078    if (status != NFCSTATUS_SUCCESS)
   1079    {
   1080        /* Error: Reception failed, link must be down */
   1081        phFriNfc_Llcp_InternalDeactivate(Llcp);
   1082    }
   1083 }
   1084 
   1085 
   1086 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t                    *Llcp,
   1087                                              phFriNfc_Llcp_sPacketHeader_t      *psHeader,
   1088                                              phFriNfc_Llcp_sPacketSequence_t    *psSequence,
   1089                                              phNfc_sData_t                      *psInfo )
   1090 {
   1091    NFCSTATUS status;
   1092    phNfc_sData_t  *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */
   1093 
   1094    /* Handle Symmetry procedure */
   1095    phFriNfc_Llcp_ResetLTO(Llcp);
   1096 
   1097    /* Generate raw packet to send (aggregate header + sequence + info fields) */
   1098    psRawPacket->length = 0;
   1099    psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length);
   1100    if (psSequence != NULL)
   1101    {
   1102       psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length);
   1103    }
   1104    if (psInfo != NULL)
   1105    {
   1106       memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length);
   1107       psRawPacket->length += psInfo->length;
   1108    }
   1109 
   1110    if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM)
   1111    {
   1112       LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length);
   1113    }
   1114    else
   1115    {
   1116       LLCP_PRINT("!");
   1117    }
   1118 
   1119    /* Send raw packet */
   1120    status = phFriNfc_LlcpMac_Send (
   1121                &Llcp->MAC,
   1122                psRawPacket,
   1123                phFriNfc_Llcp_Send_CB,
   1124                Llcp );
   1125 
   1126    return status;
   1127 }
   1128 
   1129 /* ---------------------------- Public functions ------------------------------- */
   1130 
   1131 NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t                   *psRawBuffer,
   1132                                           phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
   1133                                           uint8_t                         nVersion )
   1134 {
   1135    uint32_t    nOffset = 0;
   1136    uint16_t    miux;
   1137    uint16_t    wks;
   1138    uint8_t     pValue[2];
   1139    NFCSTATUS   result = NFCSTATUS_SUCCESS;
   1140 
   1141    /* Check parameters */
   1142    if ((psRawBuffer == NULL) || (psLinkParams == NULL))
   1143    {
   1144       return NFCSTATUS_INVALID_PARAMETER;
   1145    }
   1146 
   1147    /* Encode mandatory VERSION field */
   1148    if (result == NFCSTATUS_SUCCESS)
   1149    {
   1150       result = phFriNfc_Llcp_EncodeTLV(
   1151                   psRawBuffer,
   1152                   &nOffset,
   1153                   PHFRINFC_LLCP_TLV_TYPE_VERSION,
   1154                   PHFRINFC_LLCP_TLV_LENGTH_VERSION,
   1155                   &nVersion);
   1156    }
   1157 
   1158    /* Encode mandatory VERSION field */
   1159    if (result == NFCSTATUS_SUCCESS)
   1160    {
   1161       /* Encode MIUX field, if needed */
   1162       if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT)
   1163       {
   1164          miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK;
   1165          pValue[0] = (miux >> 8) & 0xFF;
   1166          pValue[1] =  miux       & 0xFF;
   1167          result = phFriNfc_Llcp_EncodeTLV(
   1168                      psRawBuffer,
   1169                      &nOffset,
   1170                      PHFRINFC_LLCP_TLV_TYPE_MIUX,
   1171                      PHFRINFC_LLCP_TLV_LENGTH_MIUX,
   1172                      pValue);
   1173       }
   1174    }
   1175 
   1176    /* Encode WKS field */
   1177    if (result == NFCSTATUS_SUCCESS)
   1178    {
   1179       wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK;
   1180       pValue[0] = (wks >> 8) & 0xFF;
   1181       pValue[1] =  wks       & 0xFF;
   1182       result = phFriNfc_Llcp_EncodeTLV(
   1183                   psRawBuffer,
   1184                   &nOffset,
   1185                   PHFRINFC_LLCP_TLV_TYPE_WKS,
   1186                   PHFRINFC_LLCP_TLV_LENGTH_WKS,
   1187                   pValue);
   1188    }
   1189 
   1190    /* Encode LTO field, if needed */
   1191    if (result == NFCSTATUS_SUCCESS)
   1192    {
   1193       if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT)
   1194       {
   1195          result = phFriNfc_Llcp_EncodeTLV(
   1196                      psRawBuffer,
   1197                      &nOffset,
   1198                      PHFRINFC_LLCP_TLV_TYPE_LTO,
   1199                      PHFRINFC_LLCP_TLV_LENGTH_LTO,
   1200                      &psLinkParams->lto);
   1201       }
   1202    }
   1203 
   1204    /* Encode OPT field, if needed */
   1205    if (result == NFCSTATUS_SUCCESS)
   1206    {
   1207       if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT)
   1208       {
   1209          result = phFriNfc_Llcp_EncodeTLV(
   1210                      psRawBuffer,
   1211                      &nOffset,
   1212                      PHFRINFC_LLCP_TLV_TYPE_OPT,
   1213                      PHFRINFC_LLCP_TLV_LENGTH_OPT,
   1214                      &psLinkParams->option);
   1215       }
   1216    }
   1217 
   1218    if (result != NFCSTATUS_SUCCESS)
   1219    {
   1220       /* Error: failed to encode TLV */
   1221       return NFCSTATUS_FAILED;
   1222    }
   1223 
   1224    /* Save new buffer size */
   1225    psRawBuffer->length = nOffset;
   1226 
   1227    return result;
   1228 }
   1229 
   1230 
   1231 NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t                 *Llcp,
   1232                                void                            *LowerDevice,
   1233                                phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
   1234                                void                            *pRxBuffer,
   1235                                uint16_t                        nRxBufferLength,
   1236                                void                            *pTxBuffer,
   1237                                uint16_t                        nTxBufferLength,
   1238                                phFriNfc_Llcp_LinkStatus_CB_t   pfLink_CB,
   1239                                void                            *pContext )
   1240 {
   1241    const uint16_t nMaxHeaderSize =  PHFRINFC_LLCP_PACKET_HEADER_SIZE +
   1242                                     PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
   1243    NFCSTATUS result;
   1244 
   1245    /* Check parameters presence */
   1246    if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) ||
   1247        (pRxBuffer == NULL) || (pTxBuffer == NULL) )
   1248    {
   1249       return NFCSTATUS_INVALID_PARAMETER;
   1250    }
   1251 
   1252    /* Check parameters value */
   1253    if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT)
   1254    {
   1255       return NFCSTATUS_INVALID_PARAMETER;
   1256    }
   1257 
   1258    /* Check if buffers are large enough to support minimal MIU */
   1259    if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ||
   1260        (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) )
   1261    {
   1262       return NFCSTATUS_BUFFER_TOO_SMALL;
   1263    }
   1264 
   1265    /* Check compatibility between reception buffer size and announced MIU */
   1266    if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu))
   1267    {
   1268       return NFCSTATUS_BUFFER_TOO_SMALL;
   1269    }
   1270 
   1271    /* Start with a zero-filled monitor */
   1272    memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t));
   1273 
   1274    /* Reset the MAC Mapping layer */
   1275    result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp);
   1276    if (result != NFCSTATUS_SUCCESS) {
   1277       return result;
   1278    }
   1279 
   1280    /* Save the working buffers */
   1281    Llcp->sRxBuffer.buffer = pRxBuffer;
   1282    Llcp->sRxBuffer.length = nRxBufferLength;
   1283    Llcp->nRxBufferLength = nRxBufferLength;
   1284    Llcp->sTxBuffer.buffer = pTxBuffer;
   1285    Llcp->sTxBuffer.length = nTxBufferLength;
   1286    Llcp->nTxBufferLength = nTxBufferLength;
   1287 
   1288    /* Save the link status callback references */
   1289    Llcp->pfLink_CB = pfLink_CB;
   1290    Llcp->pLinkContext = pContext;
   1291 
   1292    /* Save the local link parameters */
   1293    memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1294 
   1295    return NFCSTATUS_SUCCESS;
   1296 }
   1297 
   1298 
   1299 NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t               *Llcp,
   1300                                  phHal_sRemoteDevInformation_t *psRemoteDevInfo,
   1301                                  phFriNfc_Llcp_Check_CB_t      pfCheck_CB,
   1302                                  void                          *pContext )
   1303 {
   1304    /* Check parameters */
   1305    if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) )
   1306    {
   1307       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1308    }
   1309 
   1310    /* Check current state */
   1311    if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) {
   1312       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1313    }
   1314 
   1315    /* Save the compliance check callback */
   1316    Llcp->pfChk_CB = pfCheck_CB;
   1317    Llcp->pChkContext = pContext;
   1318 
   1319    /* Forward check request to MAC layer */
   1320    return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp);
   1321 }
   1322 
   1323 
   1324 NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp )
   1325 {
   1326    /* Check parameters */
   1327    if (Llcp == NULL)
   1328    {
   1329       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1330    }
   1331 
   1332    /* Check current state */
   1333    if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) {
   1334       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1335    }
   1336 
   1337    /* Update state */
   1338    Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION;
   1339 
   1340    /* Reset any headers to send */
   1341    Llcp->psSendHeader = NULL;
   1342    Llcp->psSendSequence = NULL;
   1343 
   1344    /* Forward check request to MAC layer */
   1345    return phFriNfc_LlcpMac_Activate(&Llcp->MAC);
   1346 }
   1347 
   1348 
   1349 NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp )
   1350 {
   1351    NFCSTATUS status;
   1352 
   1353    /* Check parameters */
   1354    if (Llcp == NULL)
   1355    {
   1356       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1357    }
   1358 
   1359    /* Check current state */
   1360    if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) &&
   1361        (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) {
   1362       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1363    }
   1364 
   1365    /* Send DISC packet */
   1366    status = phFriNfc_Llcp_SendDisconnect(Llcp);
   1367    if (status == NFCSTATUS_PENDING)
   1368    {
   1369       /* Wait for packet to be sent before deactivate link */
   1370       return status;
   1371    }
   1372 
   1373    /* Perform actual deactivation */
   1374    return phFriNfc_Llcp_InternalDeactivate(Llcp);
   1375 }
   1376 
   1377 
   1378 NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t                   *Llcp,
   1379                                       phFriNfc_Llcp_sLinkParameters_t   *pParams )
   1380 {
   1381    /* Check parameters */
   1382    if ((Llcp == NULL) || (pParams == NULL))
   1383    {
   1384       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1385    }
   1386 
   1387    /* Copy response */
   1388    memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1389 
   1390    return NFCSTATUS_SUCCESS;
   1391 }
   1392 
   1393 
   1394 NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t                  *Llcp,
   1395                                        phFriNfc_Llcp_sLinkParameters_t  *pParams )
   1396 {
   1397    /* Check parameters */
   1398    if ((Llcp == NULL) || (pParams == NULL))
   1399    {
   1400       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1401    }
   1402 
   1403    /* Copy response */
   1404    memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1405 
   1406    return NFCSTATUS_SUCCESS;
   1407 }
   1408 
   1409 
   1410 NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t                  *Llcp,
   1411                               phFriNfc_Llcp_sPacketHeader_t    *psHeader,
   1412                               phFriNfc_Llcp_sPacketSequence_t  *psSequence,
   1413                               phNfc_sData_t                    *psInfo,
   1414                               phFriNfc_Llcp_Send_CB_t          pfSend_CB,
   1415                               void                             *pContext )
   1416 {
   1417    NFCSTATUS result;
   1418    /* Check parameters */
   1419    if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL))
   1420    {
   1421       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1422    }
   1423 
   1424    /* Check if previous phFriNfc_Llcp_Send() has finished */
   1425    if (Llcp->pfSendCB != NULL)
   1426    {
   1427       /* Error: a send operation is already running */
   1428       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
   1429    }
   1430 
   1431    /* Save the callback parameters */
   1432    Llcp->pfSendCB = pfSend_CB;
   1433    Llcp->pSendContext = pContext;
   1434 
   1435    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
   1436    {
   1437       /* Ready to send */
   1438       result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo);
   1439    }
   1440    else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
   1441    {
   1442       /* Not ready to send, save send params for later use */
   1443       Llcp->psSendHeader = psHeader;
   1444       Llcp->psSendSequence = psSequence;
   1445       Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo);
   1446       result = NFCSTATUS_PENDING;
   1447    }
   1448    else
   1449    {
   1450       /* Incorrect state for sending ! */
   1451       result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);;
   1452    }
   1453 
   1454    if (result != NFCSTATUS_PENDING) {
   1455        Llcp->pfSendCB = NULL;
   1456    }
   1457    return result;
   1458 }
   1459 
   1460 
   1461 NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t            *Llcp,
   1462                               phFriNfc_Llcp_Recv_CB_t    pfRecv_CB,
   1463                               void                       *pContext )
   1464 {
   1465    NFCSTATUS result = NFCSTATUS_SUCCESS;
   1466 
   1467    /* Check parameters */
   1468    if ((Llcp == NULL) || (pfRecv_CB == NULL))
   1469    {
   1470       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1471    }
   1472 
   1473    /* Check if previous phFriNfc_Llcp_Recv() has finished */
   1474    if (Llcp->pfRecvCB != NULL)
   1475    {
   1476       /* Error: a send operation is already running */
   1477       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
   1478    }
   1479 
   1480    /* Save the callback parameters */
   1481    Llcp->pfRecvCB = pfRecv_CB;
   1482    Llcp->pRecvContext = pContext;
   1483 
   1484    /* NOTE: nothing more to do, the receive function is called in background */
   1485 
   1486    return result;
   1487 }
   1488