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