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