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       /* Return delayed send operation in error, in any */
    166       if (Llcp->psSendInfo != NULL)
    167       {
    168          phFriNfc_Llcp_Deallocate(Llcp->psSendInfo);
    169          Llcp->psSendInfo = NULL;
    170          Llcp->psSendHeader = NULL;
    171          Llcp->psSendSequence = 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 
    564    /* Notify upper layer, if Activation failed CB called by Deactivate */
    565    if (status == NFCSTATUS_SUCCESS)
    566    {
    567       /* Link activated ! */
    568       Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated);
    569    }
    570 
    571    return status;
    572 }
    573 
    574 
    575 static NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t  *Llcp,
    576                                                        phNfc_sData_t    *psParamsTLV)
    577 {
    578    NFCSTATUS                     status = NFCSTATUS_SUCCESS;
    579 
    580    /* Create the timer */
    581    Llcp->hSymmTimer = phOsalNfc_Timer_Create();
    582    if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID)
    583    {
    584       /* Error: unable to create timer */
    585       return NFCSTATUS_INSUFFICIENT_RESOURCES;
    586    }
    587 
    588    /* Check if params received from MAC activation procedure */
    589    if (psParamsTLV == NULL)
    590    {
    591       /* No params with selected MAC mapping, enter PAX mode for parameter exchange */
    592       Llcp->state = PHFRINFC_LLCP_STATE_PAX;
    593       /* Set default MIU for PAX exchange */
    594       Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT;
    595       /* If the local device is the initiator, it must initiate PAX exchange */
    596       if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
    597       {
    598          /* Send PAX */
    599          status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
    600       }
    601    }
    602    else
    603    {
    604       /* Params exchanged during MAX activation, try LLC activation */
    605       status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV);
    606    }
    607 
    608    if (status == NFCSTATUS_SUCCESS)
    609    {
    610       /* Start listening for incoming packets */
    611       Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
    612       phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
    613    }
    614 
    615    return status;
    616 }
    617 
    618 
    619 static void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t  *Llcp )
    620 {
    621    uint8_t state = Llcp->state;
    622 
    623    /* Delete the timer */
    624    if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID)
    625    {
    626       phOsalNfc_Timer_Delete(Llcp->hSymmTimer);
    627    }
    628 
    629    /* Reset state */
    630    Llcp->state = PHFRINFC_LLCP_STATE_RESET_INIT;
    631 
    632    switch (state)
    633    {
    634       case PHFRINFC_LLCP_STATE_DEACTIVATION:
    635       {
    636          /* The service layer has already been notified, nothing more to do */
    637          break;
    638       }
    639       default:
    640       {
    641          /* Notify service layer of link failure */
    642          Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated);
    643          break;
    644       }
    645    }
    646 }
    647 
    648 
    649 static void phFriNfc_Llcp_ChkLlcp_CB( void       *pContext,
    650                                       NFCSTATUS  status )
    651 {
    652    /* Get monitor from context */
    653    phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
    654 
    655    /* Update state */
    656    Llcp->state = PHFRINFC_LLCP_STATE_CHECKED;
    657 
    658    /* Invoke callback */
    659    Llcp->pfChk_CB(Llcp->pChkContext, status);
    660 }
    661 
    662 static void phFriNfc_Llcp_LinkStatus_CB( void                              *pContext,
    663                                          phFriNfc_LlcpMac_eLinkStatus_t    eLinkStatus,
    664                                          phNfc_sData_t                     *psParamsTLV,
    665                                          phFriNfc_LlcpMac_ePeerType_t      PeerRemoteDevType)
    666 {
    667    NFCSTATUS status;
    668 
    669    /* Get monitor from context */
    670    phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
    671 
    672    /* Save the local peer role (initiator/target) */
    673    Llcp->eRole = PeerRemoteDevType;
    674 
    675    /* Check new link status */
    676    switch(eLinkStatus)
    677    {
    678       case phFriNfc_LlcpMac_eLinkActivated:
    679       {
    680          /* Handle MAC link activation */
    681          status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV);
    682          if (status != NFCSTATUS_SUCCESS)
    683          {
    684             /* Error: LLC link activation procedure failed, deactivate MAC link */
    685             status = phFriNfc_Llcp_InternalDeactivate(Llcp);
    686          }
    687          break;
    688       }
    689       case phFriNfc_LlcpMac_eLinkDeactivated:
    690       {
    691          /* Handle MAC link deactivation (cannot fail) */
    692          phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp);
    693          break;
    694       }
    695       default:
    696       {
    697          /* Warning: Unknown link status, should not happen */
    698       }
    699    }
    700 }
    701 
    702 
    703 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp )
    704 {
    705    uint32_t nDuration;
    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       /* Not yet in OPERATION state, perform first reset */
    724       if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
    725       {
    726          Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND;
    727       }
    728       else
    729       {
    730          Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV;
    731       }
    732    }
    733 
    734    /* Calculate timer duration */
    735    /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */
    736    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
    737    {
    738       /* Response must be received before LTO announced by remote peer */
    739       nDuration = Llcp->sRemoteParams.lto * 10;
    740    }
    741    else
    742    {
    743       /* Must answer before the local announced LTO */
    744       /* NOTE: to ensure the answer is completely sent before LTO, the
    745                timer is triggered _before_ LTO expiration */
    746       /* TODO: make sure time scope is enough, and avoid use of magic number */
    747       nDuration = (Llcp->sLocalParams.lto * 10) / 2;
    748    }
    749 
    750    LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration);
    751 
    752    /* Restart timer */
    753    phOsalNfc_Timer_Start(
    754       Llcp->hSymmTimer,
    755       nDuration,
    756       phFriNfc_Llcp_Timer_CB,
    757       Llcp);
    758 }
    759 
    760 
    761 static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t    *Llcp,
    762                                                  phNfc_sData_t      *psPacket )
    763 {
    764    NFCSTATUS                        result;
    765    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    766 
    767    /* Parse header */
    768    phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
    769 
    770    /* Check packet type */
    771    switch (sHeader.ptype)
    772    {
    773       case PHFRINFC_LLCP_PTYPE_SYMM:
    774       {
    775          /* Nothing to do, the LTO is handled upon all packet reception */
    776          result = NFCSTATUS_SUCCESS;
    777          break;
    778       }
    779 
    780       case PHFRINFC_LLCP_PTYPE_AGF:
    781       {
    782          /* Handle the aggregated packet */
    783          result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket);
    784          if (result != NFCSTATUS_SUCCESS)
    785          {
    786             /* Error: invalid info field, dropping frame */
    787          }
    788          break;
    789       }
    790 
    791       case PHFRINFC_LLCP_PTYPE_DISC:
    792       {
    793          /* Handle link disconnection request */
    794          result = phFriNfc_Llcp_InternalDeactivate(Llcp);
    795          break;
    796       }
    797 
    798 
    799       case PHFRINFC_LLCP_PTYPE_FRMR:
    800       {
    801          /* TODO: what to do upon reception of FRMR on Link SAP ? */
    802          result = NFCSTATUS_SUCCESS;
    803          break;
    804       }
    805 
    806       case PHFRINFC_LLCP_PTYPE_PAX:
    807       {
    808          /* Ignore PAX when in Normal Operation */
    809          result = NFCSTATUS_SUCCESS;
    810          break;
    811       }
    812 
    813       default:
    814       {
    815          /* Error: invalid ptype field, dropping packet */
    816          break;
    817       }
    818    }
    819 
    820    return result;
    821 }
    822 
    823 
    824 static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t    *Llcp,
    825                                                       phNfc_sData_t      *psPacket )
    826 {
    827    phFriNfc_Llcp_Recv_CB_t          pfRecvCB;
    828    void                             *pContext;
    829    NFCSTATUS                        result = NFCSTATUS_SUCCESS;
    830    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    831 
    832    /* Forward to upper layer */
    833    if (Llcp->pfRecvCB != NULL)
    834    {
    835       /* Get callback details */
    836       pfRecvCB = Llcp->pfRecvCB;
    837       pContext = Llcp->pRecvContext;
    838       /* Reset callback details */
    839       Llcp->pfRecvCB = NULL;
    840       Llcp->pRecvContext = NULL;
    841       /* Call the callback */
    842       (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS);
    843    }
    844 
    845    return result;
    846 }
    847 
    848 
    849 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp )
    850 {
    851    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    852    phNfc_sData_t                    sInfoBuffer;
    853    phFriNfc_Llcp_sPacketHeader_t    *psSendHeader = NULL;
    854    phFriNfc_Llcp_sPacketSequence_t  *psSendSequence = NULL;
    855    phNfc_sData_t                    *psSendInfo = NULL;
    856    NFCSTATUS                        result;
    857    uint8_t                          bDeallocate = FALSE;
    858    uint8_t                          return_value = FALSE;
    859 
    860    /* Handle pending disconnection request */
    861    if (Llcp->bDiscPendingFlag == TRUE)
    862    {
    863       /* Last send si acheived, send the pending DISC packet */
    864       sHeader.dsap  = PHFRINFC_LLCP_SAP_LINK;
    865       sHeader.ssap  = PHFRINFC_LLCP_SAP_LINK;
    866       sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC;
    867       /* Set send params */
    868       psSendHeader = &sHeader;
    869       /* Reset flag */
    870       Llcp->bDiscPendingFlag = FALSE;
    871    }
    872    /* Handle pending frame reject request */
    873    else if (Llcp->bFrmrPendingFlag == TRUE)
    874    {
    875       /* Last send si acheived, send the pending FRMR packet */
    876       sInfoBuffer.buffer = Llcp->pFrmrInfo;
    877       sInfoBuffer.length = sizeof(Llcp->pFrmrInfo);
    878       /* Set send params */
    879       psSendHeader = &Llcp->sFrmrHeader;
    880       psSendInfo   = &sInfoBuffer;
    881       /* Reset flag */
    882       Llcp->bFrmrPendingFlag = FALSE;
    883    }
    884    /* Handle pending service frame */
    885    else if (Llcp->pfSendCB != NULL)
    886    {
    887       /* Set send params */
    888       psSendHeader = Llcp->psSendHeader;
    889       psSendSequence = Llcp->psSendSequence;
    890       psSendInfo = Llcp->psSendInfo;
    891       /* Reset pending send infos */
    892       Llcp->psSendHeader = NULL;
    893       Llcp->psSendSequence = NULL;
    894       Llcp->psSendInfo = NULL;
    895       bDeallocate = TRUE;
    896    }
    897 
    898    /* Perform send, if needed */
    899    if (psSendHeader != NULL)
    900    {
    901       result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo);
    902       if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING))
    903       {
    904          /* Error: send failed, impossible to recover */
    905          phFriNfc_Llcp_InternalDeactivate(Llcp);
    906       }
    907       return_value = TRUE;
    908    } else if (Llcp->pfSendCB == NULL) {
    909       // Nothing to send, send SYMM instead to allow peer to send something
    910       // if it wants.
    911       phFriNfc_Llcp_SendSymm(Llcp);
    912       return_value = TRUE;
    913    }
    914 
    915 clean_and_return:
    916    if (bDeallocate)
    917    {
    918        phFriNfc_Llcp_Deallocate(psSendInfo);
    919    }
    920 
    921    return return_value;
    922 }
    923 
    924 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t    *Llcp,
    925                                                      phNfc_sData_t      *psPacket )
    926 {
    927    NFCSTATUS                        status = NFCSTATUS_SUCCESS;
    928    phFriNfc_Llcp_sPacketHeader_t    sHeader;
    929 
    930    /* Parse header */
    931    phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
    932 
    933    /* Check destination */
    934    if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK)
    935    {
    936       /* Handle packet as destinated to the Link SAP */
    937       status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket);
    938    }
    939    else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER)
    940    {
    941      /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */
    942      status = NFCSTATUS_FAILED;
    943    }
    944    else
    945    {
    946       /* Handle packet as destinated to the SDP and transport SAPs */
    947       status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket);
    948    }
    949    return status;
    950 }
    951 
    952 
    953 static void phFriNfc_Llcp_Receive_CB( void               *pContext,
    954                                       NFCSTATUS          status,
    955                                       phNfc_sData_t      *psData)
    956 {
    957    /* Get monitor from context */
    958    phFriNfc_Llcp_t               *Llcp = (phFriNfc_Llcp_t*)pContext;
    959    NFCSTATUS                     result = NFCSTATUS_SUCCESS;
    960    phFriNfc_Llcp_sPacketHeader_t sPacketHeader;
    961 
    962    /* Check reception status and for pending disconnection */
    963    if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE))
    964    {
    965 	  LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status);
    966       /* Reset disconnection operation */
    967       Llcp->bDiscPendingFlag = FALSE;
    968       /* Deactivate the link */
    969       phFriNfc_Llcp_InternalDeactivate(Llcp);
    970       return;
    971    }
    972 
    973    /* Parse header */
    974    phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader);
    975 
    976    if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM)
    977    {
    978       LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length);
    979    }
    980    else
    981    {
    982       LLCP_PRINT("?");
    983    }
    984 
    985 
    986    /* Check new link status */
    987    switch(Llcp->state)
    988    {
    989       /* Handle packets in PAX-waiting state */
    990       case PHFRINFC_LLCP_STATE_PAX:
    991       {
    992          /* Check packet type */
    993          if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX)
    994          {
    995             /* Params exchanged during MAC activation, try LLC activation */
    996             result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE);
    997             /* If the local LLC is the target, it must answer the PAX */
    998             if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget)
    999             {
   1000                /* Send PAX */
   1001                result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
   1002             }
   1003          }
   1004          else
   1005          {
   1006             /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */
   1007          }
   1008          break;
   1009       }
   1010 
   1011       /* Handle normal operation packets */
   1012       case PHFRINFC_LLCP_STATE_OPERATION_RECV:
   1013       case PHFRINFC_LLCP_STATE_OPERATION_SEND:
   1014       {
   1015          /* Handle Symmetry procedure by resetting LTO timer */
   1016          phFriNfc_Llcp_ResetLTO(Llcp);
   1017          /* Handle packet */
   1018          result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData);
   1019          if ( (result != NFCSTATUS_SUCCESS) &&
   1020               (result != NFCSTATUS_PENDING) )
   1021          {
   1022             /* TODO: Error: invalid frame */
   1023          }
   1024          /* Perform pending send request, if any */
   1025          phFriNfc_Llcp_HandlePendingSend(Llcp);
   1026          break;
   1027       }
   1028 
   1029       default:
   1030       {
   1031          /* Warning: Should not receive packets in other states, drop them */
   1032       }
   1033    }
   1034 
   1035    /* Restart reception */
   1036    Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
   1037    phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
   1038 }
   1039 
   1040 
   1041 static void phFriNfc_Llcp_Send_CB( void               *pContext,
   1042                                    NFCSTATUS          status )
   1043 {
   1044    /* Get monitor from context */
   1045    phFriNfc_Llcp_t                  *Llcp = (phFriNfc_Llcp_t*)pContext;
   1046    phFriNfc_Llcp_Send_CB_t          pfSendCB;
   1047    void                             *pSendContext;
   1048 
   1049    /* Call the upper layer callback if last packet sent was  */
   1050    /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */
   1051    if (Llcp->psSendHeader == NULL)
   1052    {
   1053       if (Llcp->pfSendCB != NULL)
   1054       {
   1055          /* Get Callback params */
   1056          pfSendCB = Llcp->pfSendCB;
   1057          pSendContext = Llcp->pSendContext;
   1058          /* Reset callback params */
   1059          Llcp->pfSendCB = NULL;
   1060          Llcp->pSendContext = NULL;
   1061          /* Call the callback */
   1062          (pfSendCB)(pSendContext, status);
   1063       }
   1064    }
   1065 
   1066    /* Check reception status */
   1067    if (status != NFCSTATUS_SUCCESS)
   1068    {
   1069        /* Error: Reception failed, link must be down */
   1070        phFriNfc_Llcp_InternalDeactivate(Llcp);
   1071    }
   1072 }
   1073 
   1074 
   1075 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t                    *Llcp,
   1076                                              phFriNfc_Llcp_sPacketHeader_t      *psHeader,
   1077                                              phFriNfc_Llcp_sPacketSequence_t    *psSequence,
   1078                                              phNfc_sData_t                      *psInfo )
   1079 {
   1080    NFCSTATUS status;
   1081    phNfc_sData_t  *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */
   1082 
   1083    /* Handle Symmetry procedure */
   1084    phFriNfc_Llcp_ResetLTO(Llcp);
   1085 
   1086    /* Generate raw packet to send (aggregate header + sequence + info fields) */
   1087    psRawPacket->length = 0;
   1088    psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length);
   1089    if (psSequence != NULL)
   1090    {
   1091       psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length);
   1092    }
   1093    if (psInfo != NULL)
   1094    {
   1095       memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length);
   1096       psRawPacket->length += psInfo->length;
   1097    }
   1098 
   1099    if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM)
   1100    {
   1101       LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length);
   1102    }
   1103    else
   1104    {
   1105       LLCP_PRINT("!");
   1106    }
   1107 
   1108    /* Send raw packet */
   1109    status = phFriNfc_LlcpMac_Send (
   1110                &Llcp->MAC,
   1111                psRawPacket,
   1112                phFriNfc_Llcp_Send_CB,
   1113                Llcp );
   1114 
   1115    return status;
   1116 }
   1117 
   1118 /* ---------------------------- Public functions ------------------------------- */
   1119 
   1120 NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t                   *psRawBuffer,
   1121                                           phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
   1122                                           uint8_t                         nVersion )
   1123 {
   1124    uint32_t    nOffset = 0;
   1125    uint16_t    miux;
   1126    uint16_t    wks;
   1127    uint8_t     pValue[2];
   1128    NFCSTATUS   result = NFCSTATUS_SUCCESS;
   1129 
   1130    /* Check parameters */
   1131    if ((psRawBuffer == NULL) || (psLinkParams == NULL))
   1132    {
   1133       return NFCSTATUS_INVALID_PARAMETER;
   1134    }
   1135 
   1136    /* Encode mandatory VERSION field */
   1137    if (result == NFCSTATUS_SUCCESS)
   1138    {
   1139       result = phFriNfc_Llcp_EncodeTLV(
   1140                   psRawBuffer,
   1141                   &nOffset,
   1142                   PHFRINFC_LLCP_TLV_TYPE_VERSION,
   1143                   PHFRINFC_LLCP_TLV_LENGTH_VERSION,
   1144                   &nVersion);
   1145    }
   1146 
   1147    /* Encode mandatory VERSION field */
   1148    if (result == NFCSTATUS_SUCCESS)
   1149    {
   1150       /* Encode MIUX field, if needed */
   1151       if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT)
   1152       {
   1153          miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK;
   1154          pValue[0] = (miux >> 8) & 0xFF;
   1155          pValue[1] =  miux       & 0xFF;
   1156          result = phFriNfc_Llcp_EncodeTLV(
   1157                      psRawBuffer,
   1158                      &nOffset,
   1159                      PHFRINFC_LLCP_TLV_TYPE_MIUX,
   1160                      PHFRINFC_LLCP_TLV_LENGTH_MIUX,
   1161                      pValue);
   1162       }
   1163    }
   1164 
   1165    /* Encode WKS field */
   1166    if (result == NFCSTATUS_SUCCESS)
   1167    {
   1168       wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK;
   1169       pValue[0] = (wks >> 8) & 0xFF;
   1170       pValue[1] =  wks       & 0xFF;
   1171       result = phFriNfc_Llcp_EncodeTLV(
   1172                   psRawBuffer,
   1173                   &nOffset,
   1174                   PHFRINFC_LLCP_TLV_TYPE_WKS,
   1175                   PHFRINFC_LLCP_TLV_LENGTH_WKS,
   1176                   pValue);
   1177    }
   1178 
   1179    /* Encode LTO field, if needed */
   1180    if (result == NFCSTATUS_SUCCESS)
   1181    {
   1182       if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT)
   1183       {
   1184          result = phFriNfc_Llcp_EncodeTLV(
   1185                      psRawBuffer,
   1186                      &nOffset,
   1187                      PHFRINFC_LLCP_TLV_TYPE_LTO,
   1188                      PHFRINFC_LLCP_TLV_LENGTH_LTO,
   1189                      &psLinkParams->lto);
   1190       }
   1191    }
   1192 
   1193    /* Encode OPT field, if needed */
   1194    if (result == NFCSTATUS_SUCCESS)
   1195    {
   1196       if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT)
   1197       {
   1198          result = phFriNfc_Llcp_EncodeTLV(
   1199                      psRawBuffer,
   1200                      &nOffset,
   1201                      PHFRINFC_LLCP_TLV_TYPE_OPT,
   1202                      PHFRINFC_LLCP_TLV_LENGTH_OPT,
   1203                      &psLinkParams->option);
   1204       }
   1205    }
   1206 
   1207    if (result != NFCSTATUS_SUCCESS)
   1208    {
   1209       /* Error: failed to encode TLV */
   1210       return NFCSTATUS_FAILED;
   1211    }
   1212 
   1213    /* Save new buffer size */
   1214    psRawBuffer->length = nOffset;
   1215 
   1216    return result;
   1217 }
   1218 
   1219 
   1220 NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t                 *Llcp,
   1221                                void                            *LowerDevice,
   1222                                phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
   1223                                void                            *pRxBuffer,
   1224                                uint16_t                        nRxBufferLength,
   1225                                void                            *pTxBuffer,
   1226                                uint16_t                        nTxBufferLength,
   1227                                phFriNfc_Llcp_LinkStatus_CB_t   pfLink_CB,
   1228                                void                            *pContext )
   1229 {
   1230    const uint16_t nMaxHeaderSize =  PHFRINFC_LLCP_PACKET_HEADER_SIZE +
   1231                                     PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
   1232    NFCSTATUS result;
   1233 
   1234    /* Check parameters presence */
   1235    if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) ||
   1236        (pRxBuffer == NULL) || (pTxBuffer == NULL) )
   1237    {
   1238       return NFCSTATUS_INVALID_PARAMETER;
   1239    }
   1240 
   1241    /* Check parameters value */
   1242    if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT)
   1243    {
   1244       return NFCSTATUS_INVALID_PARAMETER;
   1245    }
   1246 
   1247    /* Check if buffers are large enough to support minimal MIU */
   1248    if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ||
   1249        (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) )
   1250    {
   1251       return NFCSTATUS_BUFFER_TOO_SMALL;
   1252    }
   1253 
   1254    /* Check compatibility between reception buffer size and announced MIU */
   1255    if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu))
   1256    {
   1257       return NFCSTATUS_BUFFER_TOO_SMALL;
   1258    }
   1259 
   1260    /* Start with a zero-filled monitor */
   1261    memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t));
   1262 
   1263    /* Reset the MAC Mapping layer */
   1264    result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp);
   1265    if (result != NFCSTATUS_SUCCESS) {
   1266       return result;
   1267    }
   1268 
   1269    /* Save the working buffers */
   1270    Llcp->sRxBuffer.buffer = pRxBuffer;
   1271    Llcp->sRxBuffer.length = nRxBufferLength;
   1272    Llcp->nRxBufferLength = nRxBufferLength;
   1273    Llcp->sTxBuffer.buffer = pTxBuffer;
   1274    Llcp->sTxBuffer.length = nTxBufferLength;
   1275    Llcp->nTxBufferLength = nTxBufferLength;
   1276 
   1277    /* Save the link status callback references */
   1278    Llcp->pfLink_CB = pfLink_CB;
   1279    Llcp->pLinkContext = pContext;
   1280 
   1281    /* Save the local link parameters */
   1282    memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1283 
   1284    return NFCSTATUS_SUCCESS;
   1285 }
   1286 
   1287 
   1288 NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t               *Llcp,
   1289                                  phHal_sRemoteDevInformation_t *psRemoteDevInfo,
   1290                                  phFriNfc_Llcp_Check_CB_t      pfCheck_CB,
   1291                                  void                          *pContext )
   1292 {
   1293    /* Check parameters */
   1294    if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) )
   1295    {
   1296       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1297    }
   1298 
   1299    /* Check current state */
   1300    if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) {
   1301       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1302    }
   1303 
   1304    /* Save the compliance check callback */
   1305    Llcp->pfChk_CB = pfCheck_CB;
   1306    Llcp->pChkContext = pContext;
   1307 
   1308    /* Forward check request to MAC layer */
   1309    return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp);
   1310 }
   1311 
   1312 
   1313 NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp )
   1314 {
   1315    /* Check parameters */
   1316    if (Llcp == NULL)
   1317    {
   1318       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1319    }
   1320 
   1321    /* Check current state */
   1322    if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) {
   1323       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1324    }
   1325 
   1326    /* Update state */
   1327    Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION;
   1328 
   1329    /* Forward check request to MAC layer */
   1330    return phFriNfc_LlcpMac_Activate(&Llcp->MAC);
   1331 }
   1332 
   1333 
   1334 NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp )
   1335 {
   1336    NFCSTATUS status;
   1337 
   1338    /* Check parameters */
   1339    if (Llcp == NULL)
   1340    {
   1341       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1342    }
   1343 
   1344    /* Check current state */
   1345    if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) &&
   1346        (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) {
   1347       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
   1348    }
   1349 
   1350    /* Send DISC packet */
   1351    status = phFriNfc_Llcp_SendDisconnect(Llcp);
   1352    if (status == NFCSTATUS_PENDING)
   1353    {
   1354       /* Wait for packet to be sent before deactivate link */
   1355       return status;
   1356    }
   1357 
   1358    /* Perform actual deactivation */
   1359    return phFriNfc_Llcp_InternalDeactivate(Llcp);
   1360 }
   1361 
   1362 
   1363 NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t                   *Llcp,
   1364                                       phFriNfc_Llcp_sLinkParameters_t   *pParams )
   1365 {
   1366    /* Check parameters */
   1367    if ((Llcp == NULL) || (pParams == NULL))
   1368    {
   1369       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1370    }
   1371 
   1372    /* Copy response */
   1373    memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1374 
   1375    return NFCSTATUS_SUCCESS;
   1376 }
   1377 
   1378 
   1379 NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t                  *Llcp,
   1380                                        phFriNfc_Llcp_sLinkParameters_t  *pParams )
   1381 {
   1382    /* Check parameters */
   1383    if ((Llcp == NULL) || (pParams == NULL))
   1384    {
   1385       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1386    }
   1387 
   1388    /* Copy response */
   1389    memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
   1390 
   1391    return NFCSTATUS_SUCCESS;
   1392 }
   1393 
   1394 
   1395 NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t                  *Llcp,
   1396                               phFriNfc_Llcp_sPacketHeader_t    *psHeader,
   1397                               phFriNfc_Llcp_sPacketSequence_t  *psSequence,
   1398                               phNfc_sData_t                    *psInfo,
   1399                               phFriNfc_Llcp_Send_CB_t          pfSend_CB,
   1400                               void                             *pContext )
   1401 {
   1402    NFCSTATUS result;
   1403 
   1404    /* Check parameters */
   1405    if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL))
   1406    {
   1407       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1408    }
   1409 
   1410    /* Check if previous phFriNfc_Llcp_Send() has finished */
   1411    if (Llcp->pfSendCB != NULL)
   1412    {
   1413       /* Error: a send operation is already running */
   1414       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
   1415    }
   1416 
   1417    /* Save the callback parameters */
   1418    Llcp->pfSendCB = pfSend_CB;
   1419    Llcp->pSendContext = pContext;
   1420 
   1421    if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
   1422    {
   1423       /* Ready to send */
   1424       result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo);
   1425    }
   1426    else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
   1427    {
   1428       /* Not ready to send, save send params for later use */
   1429       Llcp->psSendHeader = psHeader;
   1430       Llcp->psSendSequence = psSequence;
   1431       Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo);
   1432       result = NFCSTATUS_PENDING;
   1433    }
   1434    else
   1435    {
   1436       /* Incorrect state for sending ! */
   1437       result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);;
   1438    }
   1439 
   1440    if (result != NFCSTATUS_PENDING) {
   1441        Llcp->pfSendCB = NULL;
   1442    }
   1443    return result;
   1444 }
   1445 
   1446 
   1447 NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t            *Llcp,
   1448                               phFriNfc_Llcp_Recv_CB_t    pfRecv_CB,
   1449                               void                       *pContext )
   1450 {
   1451    NFCSTATUS result = NFCSTATUS_SUCCESS;
   1452 
   1453    /* Check parameters */
   1454    if ((Llcp == NULL) || (pfRecv_CB == NULL))
   1455    {
   1456       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
   1457    }
   1458 
   1459    /* Check if previous phFriNfc_Llcp_Recv() has finished */
   1460    if (Llcp->pfRecvCB != NULL)
   1461    {
   1462       /* Error: a send operation is already running */
   1463       return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
   1464    }
   1465 
   1466    /* Save the callback parameters */
   1467    Llcp->pfRecvCB = pfRecv_CB;
   1468    Llcp->pRecvContext = pContext;
   1469 
   1470    /* NOTE: nothing more to do, the receive function is called in background */
   1471 
   1472    return result;
   1473 }
   1474