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